summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Evans <grknight@gentoo.org>2018-11-20 10:00:11 -0500
committerBrian Evans <grknight@gentoo.org>2018-11-20 10:00:11 -0500
commit1e53d7bc24cf9c600a1cc5b2b4fa62eeb5a509e0 (patch)
treeb0bf686bd2683356fab3fb018a934e3dba58463a
parentUpdate Thanks to REL1_30 (diff)
downloadextensions-1e53d7bc24cf9c600a1cc5b2b4fa62eeb5a509e0.tar.gz
extensions-1e53d7bc24cf9c600a1cc5b2b4fa62eeb5a509e0.tar.bz2
extensions-1e53d7bc24cf9c600a1cc5b2b4fa62eeb5a509e0.zip
Update Flow to REL1_30
Signed-off-by: Brian Evans <grknight@gentoo.org>
-rw-r--r--Flow/.eslintrc.json22
-rw-r--r--Flow/.gitignore5
-rw-r--r--Flow/.gitreview2
-rw-r--r--Flow/.stylelintrc.json8
-rw-r--r--Flow/CODE_OF_CONDUCT.md1
-rw-r--r--Flow/CONTRIBUTING.md30
-rw-r--r--Flow/Flow.alias.php133
-rw-r--r--Flow/Flow.namespaces.php247
-rw-r--r--Flow/Flow.php387
-rw-r--r--Flow/FlowActions.php786
-rw-r--r--Flow/Gemfile10
-rw-r--r--Flow/Gemfile.lock96
-rw-r--r--Flow/Gruntfile.js54
-rw-r--r--Flow/Hooks.php916
-rw-r--r--Flow/Makefile47
-rw-r--r--Flow/Rakefile3
-rw-r--r--Flow/build/typos.json3
-rw-r--r--Flow/composer.json16
-rw-r--r--Flow/composer.lock459
-rw-r--r--Flow/container.php941
-rw-r--r--Flow/db_patches/patch-add-wiki.sql9
-rw-r--r--Flow/db_patches/patch-addindex_flow_ext_ref_idx_v3.sql2
-rw-r--r--Flow/db_patches/patch-drop-flow_subscription.sql1
-rw-r--r--Flow/db_patches/patch-dropindex-flow_ext_ref_idx_v2.sql1
-rw-r--r--Flow/db_patches/patch-increase_width_wiki_fields.sql2
-rw-r--r--Flow/db_patches/patch-primary-keys.sql5
-rw-r--r--Flow/db_patches/patch-ref_id-phase1.sql2
-rw-r--r--Flow/db_patches/patch-ref_id-phase2.sql5
-rw-r--r--Flow/db_patches/patch-ref_id-phase2.sqlite.sql73
-rw-r--r--Flow/db_patches/patch-ref_target_not_null.sql1
-rw-r--r--Flow/db_patches/patch-reference_wiki-phase3.sql16
-rw-r--r--Flow/db_patches/patch-reference_wiki.sql8
-rw-r--r--Flow/db_patches/patch-remove_unique_ref_indices.sql2
-rw-r--r--Flow/defines.php5
-rw-r--r--Flow/extension.json1371
-rw-r--r--Flow/flow.sql40
-rw-r--r--Flow/gitinfo.json1
-rw-r--r--Flow/handlebars/compiled/flow_block_board-history.handlebars.php63
-rw-r--r--Flow/handlebars/compiled/flow_block_header.handlebars.php42
-rw-r--r--Flow/handlebars/compiled/flow_block_header_edit.handlebars.php7
-rw-r--r--Flow/handlebars/compiled/flow_block_header_single_view.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_block_header_undo_edit.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_block_topic.handlebars.php144
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_diff_view.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_edit_title.handlebars.php14
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_history.handlebars.php63
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_lock.handlebars.php43
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php150
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php150
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_single_view.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_block_topic_undo_edit.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_block_topiclist.handlebars.php160
-rw-r--r--Flow/handlebars/compiled/flow_block_topiclist_newtopic.handlebars.php10
-rw-r--r--Flow/handlebars/compiled/flow_block_topicsummary_edit.handlebars.php4
-rw-r--r--Flow/handlebars/compiled/flow_block_topicsummary_single_view.handlebars.php15
-rw-r--r--Flow/handlebars/compiled/flow_block_topicsummary_undo_edit.handlebars.php2
-rw-r--r--Flow/handlebars/compiled/flow_post.handlebars.php161
-rw-r--r--Flow/handlebars/compiled/flow_revision_diff_header.handlebars.php2
-rw-r--r--Flow/handlebars/flow_block_header.handlebars8
-rw-r--r--Flow/handlebars/flow_block_header_edit.handlebars6
-rw-r--r--Flow/handlebars/flow_block_header_undo_edit.handlebars2
-rw-r--r--Flow/handlebars/flow_block_topic_diff_view.handlebars2
-rw-r--r--Flow/handlebars/flow_block_topic_moderate_post.handlebars10
-rw-r--r--Flow/handlebars/flow_block_topic_moderate_topic.handlebars2
-rw-r--r--Flow/handlebars/flow_block_topic_undo_edit.handlebars2
-rw-r--r--Flow/handlebars/flow_block_topicsummary_edit.handlebars4
-rw-r--r--Flow/handlebars/flow_block_topicsummary_single_view.handlebars2
-rw-r--r--Flow/handlebars/flow_block_topicsummary_undo_edit.handlebars2
-rw-r--r--Flow/handlebars/flow_board_navigation.partial.handlebars3
-rw-r--r--Flow/handlebars/flow_edit_post.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_edit_topic_title.partial.handlebars12
-rw-r--r--Flow/handlebars/flow_header_categories.partial.handlebars12
-rw-r--r--Flow/handlebars/flow_header_detail.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_header_edit_restrictions.partial.handlebars11
-rw-r--r--Flow/handlebars/flow_load_more.partial.handlebars1
-rw-r--r--Flow/handlebars/flow_moderate_post.partial.handlebars15
-rw-r--r--Flow/handlebars/flow_moderate_topic.partial.handlebars15
-rw-r--r--Flow/handlebars/flow_moderation_actions_list.partial.handlebars76
-rw-r--r--Flow/handlebars/flow_newtopic_form.partial.handlebars16
-rw-r--r--Flow/handlebars/flow_patrol_action.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_patrol_diff.partial.handlebars2
-rw-r--r--[l---------]Flow/handlebars/flow_post.handlebars4
-rw-r--r--Flow/handlebars/flow_post_author.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_post_inner.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_post_meta_actions.partial.handlebars6
-rw-r--r--Flow/handlebars/flow_post_partial.partial.handlebars31
-rw-r--r--Flow/handlebars/flow_reply_form.partial.handlebars109
-rw-r--r--Flow/handlebars/flow_subscribed.partial.handlebars8
-rw-r--r--Flow/handlebars/flow_topic.partial.handlebars11
-rw-r--r--Flow/handlebars/flow_topic_moderation_flag.partial.handlebars2
-rw-r--r--Flow/handlebars/flow_topic_titlebar_content.partial.handlebars4
-rw-r--r--Flow/handlebars/flow_topic_titlebar_lock.partial.handlebars77
-rw-r--r--Flow/handlebars/flow_topic_titlebar_summary.partial.handlebars5
-rw-r--r--Flow/handlebars/flow_topic_titlebar_watch.partial.handlebars8
-rw-r--r--Flow/i18n/ady-cyrl.json5
-rw-r--r--Flow/i18n/aeb-arab.json8
-rw-r--r--Flow/i18n/ais.json165
-rw-r--r--Flow/i18n/api/ar.json12
-rw-r--r--Flow/i18n/api/ast.json139
-rw-r--r--Flow/i18n/api/bn.json9
-rw-r--r--Flow/i18n/api/bs.json109
-rw-r--r--Flow/i18n/api/de.json117
-rw-r--r--Flow/i18n/api/diq.json11
-rw-r--r--Flow/i18n/api/en.json145
-rw-r--r--Flow/i18n/api/es.json117
-rw-r--r--Flow/i18n/api/eu.json12
-rw-r--r--Flow/i18n/api/fa.json47
-rw-r--r--Flow/i18n/api/fi.json32
-rw-r--r--Flow/i18n/api/fr.json150
-rw-r--r--Flow/i18n/api/gl.json140
-rw-r--r--Flow/i18n/api/gom-latn.json30
-rw-r--r--Flow/i18n/api/he.json124
-rw-r--r--Flow/i18n/api/it.json136
-rw-r--r--Flow/i18n/api/ja.json79
-rw-r--r--Flow/i18n/api/ka.json28
-rw-r--r--Flow/i18n/api/kk-cyrl.json109
-rw-r--r--Flow/i18n/api/ko.json46
-rw-r--r--Flow/i18n/api/ksh.json40
-rw-r--r--Flow/i18n/api/lb.json19
-rw-r--r--Flow/i18n/api/mk.json139
-rw-r--r--Flow/i18n/api/nb.json118
-rw-r--r--Flow/i18n/api/oc.json11
-rw-r--r--Flow/i18n/api/pl.json119
-rw-r--r--Flow/i18n/api/pt-br.json141
-rw-r--r--Flow/i18n/api/pt.json144
-rw-r--r--Flow/i18n/api/qqq.json147
-rw-r--r--Flow/i18n/api/ru.json119
-rw-r--r--Flow/i18n/api/sv.json142
-rw-r--r--Flow/i18n/api/uk.json142
-rw-r--r--Flow/i18n/api/vi.json109
-rw-r--r--Flow/i18n/api/zh-hans.json143
-rw-r--r--Flow/i18n/api/zh-hant.json50
-rw-r--r--Flow/i18n/ar.json462
-rw-r--r--Flow/i18n/ast.json369
-rw-r--r--Flow/i18n/atj.json31
-rw-r--r--Flow/i18n/az.json4
-rw-r--r--Flow/i18n/azb.json14
-rw-r--r--Flow/i18n/ba.json22
-rw-r--r--Flow/i18n/bcl.json1
-rw-r--r--Flow/i18n/be-tarask.json14
-rw-r--r--Flow/i18n/be.json4
-rw-r--r--Flow/i18n/bg.json34
-rw-r--r--Flow/i18n/bgn.json9
-rw-r--r--Flow/i18n/bho.json12
-rw-r--r--Flow/i18n/bn.json100
-rw-r--r--Flow/i18n/br.json29
-rw-r--r--Flow/i18n/bs.json306
-rw-r--r--Flow/i18n/bxr.json22
-rw-r--r--Flow/i18n/ca.json247
-rw-r--r--Flow/i18n/cdo.json8
-rw-r--r--Flow/i18n/ce.json134
-rw-r--r--Flow/i18n/ckb.json11
-rw-r--r--Flow/i18n/cs.json213
-rw-r--r--Flow/i18n/cu.json8
-rw-r--r--Flow/i18n/da.json13
-rw-r--r--Flow/i18n/de.json328
-rw-r--r--Flow/i18n/diq.json64
-rw-r--r--Flow/i18n/dty.json7
-rw-r--r--Flow/i18n/ee.json2
-rw-r--r--Flow/i18n/el.json270
-rw-r--r--Flow/i18n/en-gb.json8
-rw-r--r--Flow/i18n/en.json367
-rw-r--r--Flow/i18n/eo.json58
-rw-r--r--Flow/i18n/es.json264
-rw-r--r--Flow/i18n/et.json37
-rw-r--r--Flow/i18n/eu.json46
-rw-r--r--Flow/i18n/fa.json620
-rw-r--r--Flow/i18n/fi.json316
-rw-r--r--Flow/i18n/fr.json652
-rw-r--r--Flow/i18n/gl.json375
-rw-r--r--Flow/i18n/gom-deva.json132
-rw-r--r--Flow/i18n/gom-latn.json307
-rw-r--r--Flow/i18n/gsw.json5
-rw-r--r--Flow/i18n/gu.json20
-rw-r--r--Flow/i18n/hak.json8
-rw-r--r--Flow/i18n/he.json297
-rw-r--r--Flow/i18n/hi.json275
-rw-r--r--Flow/i18n/hr.json25
-rw-r--r--Flow/i18n/hu.json372
-rw-r--r--Flow/i18n/hy.json71
-rw-r--r--Flow/i18n/ia.json173
-rw-r--r--Flow/i18n/id.json474
-rw-r--r--Flow/i18n/inh.json8
-rw-r--r--Flow/i18n/it.json308
-rw-r--r--Flow/i18n/ja.json231
-rw-r--r--Flow/i18n/jbo.json24
-rw-r--r--Flow/i18n/jv.json8
-rw-r--r--Flow/i18n/ka.json47
-rw-r--r--Flow/i18n/kab.json46
-rw-r--r--Flow/i18n/kk-cyrl.json424
-rw-r--r--Flow/i18n/ko.json322
-rw-r--r--Flow/i18n/krl.json8
-rw-r--r--Flow/i18n/ksh.json212
-rw-r--r--Flow/i18n/ku-latn.json58
-rw-r--r--Flow/i18n/lag.json13
-rw-r--r--Flow/i18n/lb.json85
-rw-r--r--Flow/i18n/lij.json8
-rw-r--r--Flow/i18n/lki.json21
-rw-r--r--Flow/i18n/lt.json277
-rw-r--r--Flow/i18n/lv.json65
-rw-r--r--Flow/i18n/mai.json7
-rw-r--r--Flow/i18n/mg.json3
-rw-r--r--Flow/i18n/mk.json357
-rw-r--r--Flow/i18n/ml.json23
-rw-r--r--Flow/i18n/mn.json3
-rw-r--r--Flow/i18n/mr.json370
-rw-r--r--Flow/i18n/ms.json3
-rw-r--r--Flow/i18n/mwl.json17
-rw-r--r--Flow/i18n/my.json7
-rw-r--r--Flow/i18n/nan.json8
-rw-r--r--Flow/i18n/nap.json242
-rw-r--r--Flow/i18n/nb.json434
-rw-r--r--Flow/i18n/nds.json10
-rw-r--r--Flow/i18n/ne.json13
-rw-r--r--Flow/i18n/nl.json191
-rw-r--r--Flow/i18n/nn.json50
-rw-r--r--Flow/i18n/oc.json82
-rw-r--r--Flow/i18n/om.json1
-rw-r--r--Flow/i18n/or.json25
-rw-r--r--Flow/i18n/pa.json22
-rw-r--r--Flow/i18n/pl.json216
-rw-r--r--Flow/i18n/ps.json8
-rw-r--r--Flow/i18n/pt-br.json531
-rw-r--r--Flow/i18n/pt.json463
-rw-r--r--Flow/i18n/qqq.json393
-rw-r--r--Flow/i18n/ro.json15
-rw-r--r--Flow/i18n/roa-tara.json12
-rw-r--r--Flow/i18n/ru.json408
-rw-r--r--Flow/i18n/sa.json2
-rw-r--r--Flow/i18n/sc.json4
-rw-r--r--Flow/i18n/scn.json3
-rw-r--r--Flow/i18n/sd.json13
-rw-r--r--Flow/i18n/sh.json9
-rw-r--r--Flow/i18n/si.json8
-rw-r--r--Flow/i18n/sk.json9
-rw-r--r--Flow/i18n/skr-arab.json155
-rw-r--r--Flow/i18n/sl.json28
-rw-r--r--Flow/i18n/so.json8
-rw-r--r--Flow/i18n/sq.json2
-rw-r--r--Flow/i18n/sr-ec.json63
-rw-r--r--Flow/i18n/sr-el.json54
-rw-r--r--Flow/i18n/su.json10
-rw-r--r--Flow/i18n/sv.json345
-rw-r--r--Flow/i18n/ta.json11
-rw-r--r--Flow/i18n/tay.json66
-rw-r--r--Flow/i18n/te.json10
-rw-r--r--Flow/i18n/tg-cyrl.json12
-rw-r--r--Flow/i18n/tl.json6
-rw-r--r--Flow/i18n/tr.json44
-rw-r--r--Flow/i18n/tt-cyrl.json11
-rw-r--r--Flow/i18n/udm.json8
-rw-r--r--Flow/i18n/uk.json392
-rw-r--r--Flow/i18n/ur.json365
-rw-r--r--Flow/i18n/vi.json341
-rw-r--r--Flow/i18n/wuu.json8
-rw-r--r--Flow/i18n/xmf.json1
-rw-r--r--Flow/i18n/yi.json13
-rw-r--r--Flow/i18n/zh-hans.json446
-rw-r--r--Flow/i18n/zh-hant.json185
-rw-r--r--Flow/images/betafeature-flow-ltr.svg39
-rw-r--r--Flow/images/betafeature-flow-rtl.svg39
-rw-r--r--Flow/includes/Actions/Action.php28
-rw-r--r--Flow/includes/Actions/EditAction.php3
-rw-r--r--Flow/includes/Actions/PurgeAction.php56
-rw-r--r--Flow/includes/Actions/ViewAction.php13
-rw-r--r--Flow/includes/Api/ApiFlow.php160
-rw-r--r--Flow/includes/Api/ApiFlowBase.php67
-rw-r--r--Flow/includes/Api/ApiFlowBaseGet.php28
-rw-r--r--Flow/includes/Api/ApiFlowBasePost.php25
-rw-r--r--Flow/includes/Api/ApiFlowEditHeader.php51
-rw-r--r--Flow/includes/Api/ApiFlowEditPost.php56
-rw-r--r--Flow/includes/Api/ApiFlowEditTitle.php44
-rw-r--r--Flow/includes/Api/ApiFlowEditTopicSummary.php51
-rw-r--r--Flow/includes/Api/ApiFlowLockTopic.php50
-rw-r--r--Flow/includes/Api/ApiFlowModeratePost.php49
-rw-r--r--Flow/includes/Api/ApiFlowModerateTopic.php44
-rw-r--r--Flow/includes/Api/ApiFlowNewTopic.php51
-rw-r--r--Flow/includes/Api/ApiFlowReply.php51
-rw-r--r--Flow/includes/Api/ApiFlowSearch.php67
-rw-r--r--Flow/includes/Api/ApiFlowUndoEditHeader.php18
-rw-r--r--Flow/includes/Api/ApiFlowUndoEditPost.php18
-rw-r--r--Flow/includes/Api/ApiFlowUndoEditTopicSummary.php22
-rw-r--r--Flow/includes/Api/ApiFlowViewHeader.php42
-rw-r--r--Flow/includes/Api/ApiFlowViewPost.php46
-rw-r--r--Flow/includes/Api/ApiFlowViewPostHistory.php20
-rw-r--r--Flow/includes/Api/ApiFlowViewTopic.php32
-rw-r--r--Flow/includes/Api/ApiFlowViewTopicHistory.php16
-rw-r--r--Flow/includes/Api/ApiFlowViewTopicList.php84
-rw-r--r--Flow/includes/Api/ApiFlowViewTopicSummary.php42
-rw-r--r--Flow/includes/Api/ApiParsoidUtilsFlow.php69
-rw-r--r--Flow/includes/Api/ApiQueryPropFlowInfo.php23
-rw-r--r--Flow/includes/Block/Block.php45
-rw-r--r--Flow/includes/Block/BoardHistory.php52
-rw-r--r--Flow/includes/Block/Header.php105
-rw-r--r--Flow/includes/Block/Topic.php222
-rw-r--r--Flow/includes/Block/TopicList.php90
-rw-r--r--Flow/includes/Block/TopicSummary.php84
-rw-r--r--Flow/includes/BlockFactory.php31
-rw-r--r--Flow/includes/BoardMover.php86
-rw-r--r--Flow/includes/Collection/AbstractCollection.php47
-rw-r--r--Flow/includes/Collection/HeaderCollection.php2
-rw-r--r--Flow/includes/Collection/LocalCacheAbstractCollection.php17
-rw-r--r--Flow/includes/Collection/PostCollection.php8
-rw-r--r--Flow/includes/Collection/PostSummaryCollection.php2
-rw-r--r--Flow/includes/Content/BoardContent.php10
-rw-r--r--Flow/includes/Content/BoardContentHandler.php23
-rw-r--r--Flow/includes/Conversion/Utils.php474
-rw-r--r--Flow/includes/Data/Compactor/FeatureCompactor.php8
-rw-r--r--Flow/includes/Data/Compactor/ShallowCompactor.php5
-rw-r--r--Flow/includes/Data/FlowObjectCache.php67
-rw-r--r--Flow/includes/Data/Index.php25
-rw-r--r--Flow/includes/Data/Index/BoardHistoryIndex.php55
-rw-r--r--Flow/includes/Data/Index/FeatureIndex.php259
-rw-r--r--Flow/includes/Data/Index/PostRevisionBoardHistoryIndex.php11
-rw-r--r--Flow/includes/Data/Index/PostRevisionTopicHistoryIndex.php94
-rw-r--r--Flow/includes/Data/Index/PostSummaryRevisionBoardHistoryIndex.php11
-rw-r--r--Flow/includes/Data/Index/TopKIndex.php240
-rw-r--r--Flow/includes/Data/Index/UniqueFeatureIndex.php12
-rw-r--r--Flow/includes/Data/Listener/AbstractListener.php8
-rw-r--r--Flow/includes/Data/Listener/DeferredInsertLifecycleHandler.php2
-rw-r--r--Flow/includes/Data/Listener/EditCountListener.php2
-rw-r--r--Flow/includes/Data/Listener/ModerationLoggingListener.php23
-rw-r--r--Flow/includes/Data/Listener/NotificationListener.php62
-rw-r--r--Flow/includes/Data/Listener/RecentChangesListener.php26
-rw-r--r--Flow/includes/Data/Listener/ReferenceRecorder.php104
-rw-r--r--Flow/includes/Data/Listener/TopicPageCreationListener.php12
-rw-r--r--Flow/includes/Data/Listener/UserNameListener.php4
-rw-r--r--Flow/includes/Data/Listener/WatchTopicListener.php13
-rw-r--r--Flow/includes/Data/Listener/WorkflowTopicListListener.php16
-rw-r--r--Flow/includes/Data/ManagerGroup.php16
-rw-r--r--Flow/includes/Data/Mapper/BasicObjectMapper.php4
-rw-r--r--Flow/includes/Data/Mapper/CachingObjectMapper.php6
-rw-r--r--Flow/includes/Data/ObjectLocator.php104
-rw-r--r--Flow/includes/Data/ObjectManager.php74
-rw-r--r--Flow/includes/Data/ObjectStorage.php8
-rw-r--r--Flow/includes/Data/Pager/HistoryPager.php34
-rw-r--r--Flow/includes/Data/Pager/Pager.php53
-rw-r--r--Flow/includes/Data/Storage/BasicDbStorage.php76
-rw-r--r--Flow/includes/Data/Storage/BoardHistoryStorage.php119
-rw-r--r--Flow/includes/Data/Storage/DbStorage.php38
-rw-r--r--Flow/includes/Data/Storage/PostRevisionBoardHistoryStorage.php44
-rw-r--r--Flow/includes/Data/Storage/PostRevisionStorage.php21
-rw-r--r--Flow/includes/Data/Storage/PostRevisionTopicHistoryStorage.php107
-rw-r--r--Flow/includes/Data/Storage/PostSummaryRevisionBoardHistoryStorage.php43
-rw-r--r--Flow/includes/Data/Storage/RevisionStorage.php153
-rw-r--r--Flow/includes/Data/Storage/TopicListStorage.php13
-rw-r--r--Flow/includes/Data/Utils/Merger.php8
-rw-r--r--Flow/includes/Data/Utils/MultiDimArray.php22
-rw-r--r--Flow/includes/Data/Utils/RecentChangeFactory.php2
-rw-r--r--Flow/includes/Data/Utils/ResultDuplicator.php15
-rw-r--r--Flow/includes/Data/Utils/SortArrayByKeys.php2
-rw-r--r--Flow/includes/Data/Utils/SortRevisionsByRevisionId.php55
-rw-r--r--Flow/includes/Data/Utils/UserMerger.php54
-rw-r--r--Flow/includes/DbFactory.php54
-rw-r--r--Flow/includes/Dump/Exporter.php439
-rw-r--r--Flow/includes/Dump/Importer.php400
-rw-r--r--Flow/includes/Dump/flow-1.0.xsd128
-rw-r--r--Flow/includes/Exception/ExceptionHandling.php98
-rw-r--r--Flow/includes/FlowActions.php2
-rw-r--r--Flow/includes/Formatter/AbstractFormatter.php27
-rw-r--r--Flow/includes/Formatter/AbstractQuery.php89
-rw-r--r--Flow/includes/Formatter/BaseTopicListFormatter.php17
-rw-r--r--Flow/includes/Formatter/BoardHistoryQuery.php75
-rw-r--r--Flow/includes/Formatter/CategoryViewerFormatter.php5
-rw-r--r--Flow/includes/Formatter/CategoryViewerQuery.php12
-rw-r--r--Flow/includes/Formatter/ChangesListFormatter.php26
-rw-r--r--Flow/includes/Formatter/ChangesListQuery.php24
-rw-r--r--Flow/includes/Formatter/CheckUserFormatter.php12
-rw-r--r--Flow/includes/Formatter/CheckUserQuery.php8
-rw-r--r--Flow/includes/Formatter/ContributionsFormatter.php19
-rw-r--r--Flow/includes/Formatter/ContributionsQuery.php149
-rw-r--r--Flow/includes/Formatter/FeedItemFormatter.php6
-rw-r--r--Flow/includes/Formatter/HistoryQuery.php127
-rw-r--r--Flow/includes/Formatter/IRCLineUrlFormatter.php10
-rw-r--r--Flow/includes/Formatter/PostHistoryQuery.php23
-rw-r--r--Flow/includes/Formatter/PostSummaryQuery.php4
-rw-r--r--Flow/includes/Formatter/RevisionDiffViewFormatter.php12
-rw-r--r--Flow/includes/Formatter/RevisionFormatter.php336
-rw-r--r--Flow/includes/Formatter/RevisionUndoViewFormatter.php20
-rw-r--r--Flow/includes/Formatter/RevisionViewFormatter.php17
-rw-r--r--Flow/includes/Formatter/RevisionViewQuery.php17
-rw-r--r--Flow/includes/Formatter/SinglePostQuery.php8
-rw-r--r--Flow/includes/Formatter/TocTopicListFormatter.php21
-rw-r--r--Flow/includes/Formatter/TopicFormatter.php40
-rw-r--r--Flow/includes/Formatter/TopicHistoryQuery.php62
-rw-r--r--Flow/includes/Formatter/TopicListFormatter.php60
-rw-r--r--Flow/includes/Formatter/TopicListQuery.php49
-rw-r--r--Flow/includes/Import/ArchiveNameHelper.php9
-rw-r--r--Flow/includes/Import/Converter.php22
-rw-r--r--Flow/includes/Import/Exception.php9
-rw-r--r--Flow/includes/Import/IConversionStrategy.php4
-rw-r--r--Flow/includes/Import/ImportSource.php1
-rw-r--r--Flow/includes/Import/Importer.php195
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/CachedData.php28
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/ConversionStrategy.php65
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/Exception.php1
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/Iterators.php18
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/Objects.php55
-rw-r--r--Flow/includes/Import/LiquidThreadsApi/Source.php80
-rw-r--r--Flow/includes/Import/OptInController.php248
-rw-r--r--Flow/includes/Import/OptInUpdate.php1
-rw-r--r--Flow/includes/Import/Postprocessor/LqtNotifications.php58
-rw-r--r--Flow/includes/Import/Postprocessor/LqtRedirector.php28
-rw-r--r--Flow/includes/Import/Postprocessor/Postprocessor.php8
-rw-r--r--Flow/includes/Import/Postprocessor/ProcessorGroup.php12
-rw-r--r--Flow/includes/Import/Postprocessor/SpecialLogTopic.php8
-rw-r--r--Flow/includes/Import/SourceStore/Exception.php12
-rw-r--r--Flow/includes/Import/SourceStore/FileImportSourceStore.php48
-rw-r--r--Flow/includes/Import/SourceStore/FlowRevisionsDb.php164
-rw-r--r--Flow/includes/Import/SourceStore/NullImportSourceStore.php22
-rw-r--r--Flow/includes/Import/SourceStore/SourceStoreInterface.php33
-rw-r--r--Flow/includes/Import/TemplateHelper.php29
-rw-r--r--Flow/includes/Import/Wikitext/ConversionStrategy.php37
-rw-r--r--Flow/includes/Import/Wikitext/ImportSource.php49
-rw-r--r--Flow/includes/LinksTableUpdater.php41
-rw-r--r--Flow/includes/Log/ActionFormatter.php97
-rw-r--r--Flow/includes/Log/LqtImportFormatter.php10
-rw-r--r--Flow/includes/Log/ModerationLogger.php10
-rw-r--r--Flow/includes/Log/Query.php8
-rw-r--r--Flow/includes/Model/AbstractRevision.php282
-rw-r--r--Flow/includes/Model/AbstractSummary.php2
-rw-r--r--Flow/includes/Model/Anchor.php16
-rw-r--r--Flow/includes/Model/Header.php4
-rw-r--r--Flow/includes/Model/HtmlRenderingInformation.php102
-rw-r--r--Flow/includes/Model/PostRevision.php93
-rw-r--r--Flow/includes/Model/PostSummary.php2
-rw-r--r--Flow/includes/Model/Reference.php45
-rw-r--r--Flow/includes/Model/TopicListEntry.php11
-rw-r--r--Flow/includes/Model/URLReference.php34
-rw-r--r--Flow/includes/Model/UUID.php67
-rw-r--r--Flow/includes/Model/UserTuple.php16
-rw-r--r--Flow/includes/Model/WikiReference.php40
-rw-r--r--Flow/includes/Model/Workflow.php134
-rw-r--r--Flow/includes/Notifications/Controller.php880
-rw-r--r--Flow/includes/Notifications/FlowEnabledOnTalkpagePresentationModel.php40
-rw-r--r--Flow/includes/Notifications/FlowPresentationModel.php221
-rw-r--r--Flow/includes/Notifications/HeaderEditedPresentationModel.php77
-rw-r--r--Flow/includes/Notifications/MentionPresentationModel.php65
-rw-r--r--Flow/includes/Notifications/MentionStatusPresentationModel.php31
-rw-r--r--Flow/includes/Notifications/NewTopicPresentationModel.php89
-rw-r--r--Flow/includes/Notifications/Notifications.php364
-rw-r--r--Flow/includes/Notifications/PostEditedPresentationModel.php100
-rw-r--r--Flow/includes/Notifications/PostReplyPresentationModel.php104
-rw-r--r--Flow/includes/Notifications/SummaryEditedPresentationModel.php90
-rw-r--r--Flow/includes/Notifications/TopicRenamedPresentationModel.php74
-rw-r--r--Flow/includes/Notifications/TopicResolvedPresentationModel.php50
-rw-r--r--Flow/includes/Notifications/UserLocator.php73
-rw-r--r--Flow/includes/OOUI/BoardDescriptionWidget.php24
-rw-r--r--Flow/includes/Parsoid/ContentFixer.php8
-rw-r--r--Flow/includes/Parsoid/Extractor/CategoryExtractor.php1
-rw-r--r--Flow/includes/Parsoid/Extractor/ExtLinkExtractor.php1
-rw-r--r--Flow/includes/Parsoid/Extractor/TransclusionExtractor.php4
-rw-r--r--Flow/includes/Parsoid/Fixer.php1
-rw-r--r--Flow/includes/Parsoid/Fixer/BadImageRemover.php5
-rw-r--r--Flow/includes/Parsoid/Fixer/BaseHrefFixer.php2
-rw-r--r--Flow/includes/Parsoid/Fixer/WikiLinkFixer.php6
-rw-r--r--Flow/includes/Parsoid/ReferenceExtractor.php9
-rw-r--r--Flow/includes/Parsoid/ReferenceFactory.php3
-rw-r--r--Flow/includes/ReferenceClarifier.php41
-rw-r--r--Flow/includes/Repository/MultiGetList.php42
-rw-r--r--Flow/includes/Repository/RootPostLoader.php46
-rw-r--r--Flow/includes/Repository/TreeCacheKey.php23
-rw-r--r--Flow/includes/Repository/TreeRepository.php187
-rw-r--r--Flow/includes/Repository/UserName/OneStepUserNameQuery.php20
-rw-r--r--Flow/includes/Repository/UserName/TwoStepUserNameQuery.php12
-rw-r--r--Flow/includes/Repository/UserName/UserNameQuery.php2
-rw-r--r--Flow/includes/Repository/UserNameBatch.php38
-rw-r--r--Flow/includes/RevisionActionPermissions.php56
-rw-r--r--Flow/includes/Search/Connection.php35
-rw-r--r--Flow/includes/Search/Iterators/AbstractIterator.php189
-rw-r--r--Flow/includes/Search/Iterators/HeaderIterator.php28
-rw-r--r--Flow/includes/Search/Iterators/TopicIterator.php117
-rw-r--r--Flow/includes/Search/SearchEngine.php38
-rw-r--r--Flow/includes/Search/Searcher.php62
-rw-r--r--Flow/includes/Search/Updaters/AbstractUpdater.php116
-rw-r--r--Flow/includes/Search/Updaters/HeaderUpdater.php61
-rw-r--r--Flow/includes/Search/Updaters/TopicUpdater.php126
-rw-r--r--Flow/includes/Search/maintenance/MappingConfigBuilder.php38
-rw-r--r--Flow/includes/SpamFilter/AbuseFilter.php58
-rw-r--r--Flow/includes/SpamFilter/ConfirmEdit.php36
-rw-r--r--Flow/includes/SpamFilter/ContentLengthFilter.php5
-rw-r--r--Flow/includes/SpamFilter/Controller.php16
-rw-r--r--Flow/includes/SpamFilter/RateLimits.php35
-rw-r--r--Flow/includes/SpamFilter/SpamBlacklist.php9
-rw-r--r--Flow/includes/SpamFilter/SpamFilter.php3
-rw-r--r--Flow/includes/SpamFilter/SpamRegex.php18
-rw-r--r--Flow/includes/Specials/SpecialEnableStructuredDiscussions.php175
-rw-r--r--Flow/includes/Specials/SpecialStructuredDiscussions.php200
-rw-r--r--Flow/includes/SubmissionHandler.php101
-rw-r--r--Flow/includes/TalkpageManager.php157
-rw-r--r--Flow/includes/TemplateHelper.php182
-rw-r--r--Flow/includes/Templating.php47
-rw-r--r--Flow/includes/UrlGenerator.php158
-rw-r--r--Flow/includes/Utils/NamespaceIterator.php14
-rw-r--r--Flow/includes/Utils/PagesWithPropertyIterator.php20
-rw-r--r--Flow/includes/View.php123
-rw-r--r--Flow/includes/WatchedTopicItems.php14
-rw-r--r--Flow/includes/WorkflowLoaderFactory.php36
-rw-r--r--Flow/jsduck.external.js30
-rw-r--r--Flow/jsduck.json2
-rw-r--r--Flow/jsduck_custom_tags.rb17
-rw-r--r--Flow/maintenance/FlowAddMissingModerationLogs.php39
-rw-r--r--Flow/maintenance/FlowCreateTemplates.php28
-rw-r--r--Flow/maintenance/FlowExternalStoreMoveCluster.php288
-rw-r--r--Flow/maintenance/FlowFixEditCount.php22
-rw-r--r--Flow/maintenance/FlowFixInconsistentBoards.php184
-rw-r--r--Flow/maintenance/FlowFixLinks.php58
-rw-r--r--Flow/maintenance/FlowFixLog.php49
-rw-r--r--Flow/maintenance/FlowFixUserIp.php57
-rw-r--r--Flow/maintenance/FlowFixWorkflowLastUpdateTimestamp.php43
-rw-r--r--Flow/maintenance/FlowForceSearchIndex.php108
-rw-r--r--Flow/maintenance/FlowPopulateLinksTables.php37
-rw-r--r--Flow/maintenance/FlowPopulateRefId.php73
-rw-r--r--Flow/maintenance/FlowRemoveOldTopics.php391
-rw-r--r--Flow/maintenance/FlowRestoreLQT.php302
-rw-r--r--Flow/maintenance/FlowSearchConfig.php49
-rw-r--r--Flow/maintenance/FlowSetUserIp.php60
-rw-r--r--Flow/maintenance/FlowUpdateBetaFeaturePreference.php28
-rw-r--r--Flow/maintenance/FlowUpdateRecentChanges.php28
-rw-r--r--Flow/maintenance/FlowUpdateResolvedNotifTitles.php97
-rw-r--r--Flow/maintenance/FlowUpdateRevContentModelFromOccupyPages.php20
-rw-r--r--Flow/maintenance/FlowUpdateRevisionContentLength.php27
-rw-r--r--Flow/maintenance/FlowUpdateRevisionTypeId.php25
-rw-r--r--Flow/maintenance/FlowUpdateUserWiki.php55
-rw-r--r--Flow/maintenance/FlowUpdateWorkflowPageId.php101
-rw-r--r--Flow/maintenance/MaintenanceDebugLogger.php7
-rw-r--r--Flow/maintenance/benchUuidTimestampConversion.php100
-rw-r--r--Flow/maintenance/compileLightncandy.php12
-rw-r--r--Flow/maintenance/convertAllLqtPages.php29
-rw-r--r--Flow/maintenance/convertLqtPageFromRemoteApiForTesting.php16
-rw-r--r--Flow/maintenance/convertLqtPageOnLocalWiki.php20
-rw-r--r--Flow/maintenance/convertNamespaceFromWikitext.php27
-rw-r--r--Flow/maintenance/convertToText.php304
-rw-r--r--Flow/maintenance/dumpBackup.php130
-rw-r--r--Flow/maintenance/repair_missing_from_csv.php17
-rw-r--r--Flow/maintenance/repair_missing_revision_content.php81
-rw-r--r--Flow/maintenance/repair_missing_revision_content_from_parent.php52
-rw-r--r--Flow/modules/contributions/base.js6
-rw-r--r--Flow/modules/editor/editors/ext.flow.editors.none.js7
-rw-r--r--Flow/modules/editor/editors/visualeditor/ext.flow.editors.visualeditor.js44
-rw-r--r--Flow/modules/editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js2
-rw-r--r--Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.js72
-rw-r--r--Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.less22
-rw-r--r--Flow/modules/editor/editors/visualeditor/mw.flow.ve.UserCache.js7
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js112
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js2
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/images/icons/flow-mention.svg83
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js14
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less2
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js3
-rw-r--r--Flow/modules/editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js14
-rw-r--r--Flow/modules/editor/ext.flow.editor.js35
-rw-r--r--Flow/modules/engine/components/board/base/flow-board-api-events.js416
-rw-r--r--Flow/modules/engine/components/board/base/flow-board-interactive-events.js156
-rw-r--r--Flow/modules/engine/components/board/base/flow-board-load-events.js2
-rw-r--r--Flow/modules/engine/components/board/base/flow-boardandhistory-base.js39
-rw-r--r--Flow/modules/engine/components/board/features/flow-board-loadmore.js65
-rw-r--r--Flow/modules/engine/components/board/features/flow-board-navigation.js2
-rw-r--r--Flow/modules/engine/components/board/features/flow-board-side-rail.js6
-rw-r--r--Flow/modules/engine/components/board/features/flow-board-switcheditor.js2
-rw-r--r--Flow/modules/engine/components/board/features/flow-board-visualeditor.js6
-rw-r--r--Flow/modules/engine/components/board/flow-board.js31
-rw-r--r--Flow/modules/engine/components/board/flow-boardhistory.js14
-rw-r--r--Flow/modules/engine/components/common/flow-component-engines.js18
-rw-r--r--Flow/modules/engine/components/common/flow-component-events.js54
-rw-r--r--Flow/modules/engine/components/common/flow-component-menus.js1
-rw-r--r--Flow/modules/engine/components/flow-component.js27
-rw-r--r--Flow/modules/engine/components/flow-registry.js4
-rw-r--r--Flow/modules/engine/components/flow-undo-page.js6
-rw-r--r--Flow/modules/engine/misc/flow-api.js24
-rw-r--r--Flow/modules/engine/misc/flow-eventlog.js29
-rw-r--r--Flow/modules/engine/misc/flow-handlebars.js54
-rw-r--r--Flow/modules/engine/misc/jquery.conditionalScroll.js1
-rw-r--r--Flow/modules/engine/misc/mw-ui.enhance.js63
-rw-r--r--Flow/modules/engine/misc/mw-ui.modal.js20
-rw-r--r--Flow/modules/flow-initialize.js385
-rw-r--r--Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js193
-rw-r--r--Flow/modules/flow/dm/mixins/mw.flow.dm.List.js10
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Board.js94
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Captcha.js70
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Categories.js26
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.CategoryItem.js43
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Content.js81
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Post.js6
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.RevisionedContent.js122
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.System.js3
-rw-r--r--Flow/modules/flow/dm/mw.flow.dm.Topic.js6
-rw-r--r--Flow/modules/flow/ui/mw.flow.ui.CancelConfirmDialog.js4
-rw-r--r--Flow/modules/flow/ui/mw.flow.ui.js1
-rw-r--r--Flow/modules/flow/ui/tools/mw.flow.ui.MWEditModeTool.js69
-rw-r--r--Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js25
-rw-r--r--Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js94
-rw-r--r--Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js62
-rw-r--r--Flow/modules/flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js20
-rw-r--r--Flow/modules/flow/ui/widgets/editor/mw.flow.ui.CanNotEditWidget.js173
-rw-r--r--Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js5
-rw-r--r--Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js102
-rw-r--r--Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js122
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js159
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.CaptchaWidget.js85
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.CategoriesWidget.js114
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.CategoryItemWidget.js53
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.EditPostWidget.js96
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js176
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.NavigationWidget.js2
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js120
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js127
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js6
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.ToCWidget.js2
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js15
-rw-r--r--Flow/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js164
-rw-r--r--Flow/modules/messagePoster/ext.flow.messagePoster.js7
-rw-r--r--Flow/modules/mw.flow.Initializer.js991
-rw-r--r--Flow/modules/notification/icon/flow-new-topic.svg4
-rw-r--r--Flow/modules/notification/icon/flow-post-edited.svg4
-rw-r--r--Flow/modules/notification/icon/flow-topic-renamed.svg4
-rw-r--r--Flow/modules/notification/icon/flow-topic-reopened.svg4
-rw-r--r--Flow/modules/notification/icon/flow-topic-resolved.svg4
-rw-r--r--Flow/modules/notification/icon/flowusertalk-new-topic.svg4
-rw-r--r--Flow/modules/styles/board/editor-switcher.less29
-rw-r--r--Flow/modules/styles/board/form-actions.less12
-rw-r--r--Flow/modules/styles/board/header.less28
-rw-r--r--Flow/modules/styles/board/menu.less50
-rw-r--r--Flow/modules/styles/board/moderated.less17
-rw-r--r--Flow/modules/styles/board/navigation.less56
-rw-r--r--Flow/modules/styles/board/replycount.less15
-rw-r--r--Flow/modules/styles/board/terms-of-use.less9
-rw-r--r--Flow/modules/styles/board/timestamps.less8
-rw-r--r--Flow/modules/styles/board/topic/meta.less7
-rw-r--r--Flow/modules/styles/board/topic/post.less53
-rw-r--r--Flow/modules/styles/board/topic/summary.less16
-rw-r--r--Flow/modules/styles/board/topic/titlebar.less100
-rw-r--r--Flow/modules/styles/board/topic/watchlist.less22
-rw-r--r--Flow/modules/styles/common.less89
-rw-r--r--Flow/modules/styles/errors.less3
-rw-r--r--Flow/modules/styles/flow.colors.less4
-rw-r--r--Flow/modules/styles/flow.variables.less12
-rw-r--r--Flow/modules/styles/flow/images/anon-user.svg4
-rw-r--r--Flow/modules/styles/flow/images/lock-ltr.svg4
-rw-r--r--Flow/modules/styles/flow/images/lock-rtl.svg4
-rw-r--r--Flow/modules/styles/flow/images/newest-topics.svg4
-rw-r--r--Flow/modules/styles/flow/images/topic-collapse-ltr.svg16
-rw-r--r--Flow/modules/styles/flow/images/topic-collapse-rtl.svg16
-rw-r--r--Flow/modules/styles/flow/mw.flow.ui.Overlay.less1
-rw-r--r--Flow/modules/styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less33
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less25
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.CanNotEditWidget.less30
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less2
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less46
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-monobook.less82
-rw-r--r--Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-vector.less91
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.CategoriesWidget.less10
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less3
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.NavigationWidget.less9
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.NewTopicWidget.less57
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less24
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.ReplyWidget.less6
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less11
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less11
-rw-r--r--Flow/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less18
-rw-r--r--Flow/modules/styles/js.less134
-rw-r--r--Flow/modules/styles/mediawiki.ui/forms.less107
-rw-r--r--Flow/modules/styles/mediawiki.ui/modal.less37
-rw-r--r--Flow/modules/styles/mediawiki.ui/text.less3
-rw-r--r--Flow/modules/styles/mediawiki.ui/tooltips.less124
-rw-r--r--Flow/modules/styles/minerva/common.less2
-rw-r--r--Flow/modules/styles/nojs.less9
-rw-r--r--Flow/modules/tours/flow-icon.svg36
-rw-r--r--Flow/modules/tours/flowOptIn.js62
-rw-r--r--Flow/package.json19
-rw-r--r--Flow/phpcs.xml30
-rw-r--r--Flow/scripts/gen-autoload.php47
-rw-r--r--Flow/scripts/generatecss.php15
-rw-r--r--Flow/scripts/hooks-shared.sh10
-rw-r--r--Flow/scripts/one-class-per-file.php10
-rwxr-xr-xFlow/scripts/pre-commit4
-rw-r--r--Flow/tests/browser/ci.yml9
-rw-r--r--Flow/tests/browser/environments.yml8
-rw-r--r--Flow/tests/browser/features/action_menu_permalink.feature4
-rw-r--r--Flow/tests/browser/features/anon_interface.feature6
-rw-r--r--Flow/tests/browser/features/categories.feature22
-rw-r--r--Flow/tests/browser/features/description.feature4
-rw-r--r--Flow/tests/browser/features/edit_existing.feature4
-rw-r--r--Flow/tests/browser/features/flow_in_recent_changes.feature4
-rw-r--r--Flow/tests/browser/features/flow_logged_in.feature4
-rw-r--r--Flow/tests/browser/features/flow_no_javascript.feature5
-rw-r--r--Flow/tests/browser/features/moderation.feature4
-rw-r--r--Flow/tests/browser/features/new_topic.feature14
-rw-r--r--Flow/tests/browser/features/opt_in.feature10
-rw-r--r--Flow/tests/browser/features/post_links.feature6
-rw-r--r--Flow/tests/browser/features/preload.feature4
-rw-r--r--Flow/tests/browser/features/reopen_topic.feature7
-rw-r--r--Flow/tests/browser/features/reply.feature4
-rw-r--r--Flow/tests/browser/features/reply_moderation.feature4
-rw-r--r--Flow/tests/browser/features/resolve_topic.feature30
-rw-r--r--Flow/tests/browser/features/sorting_topics.feature4
-rw-r--r--Flow/tests/browser/features/special_enableflow.feature6
-rw-r--r--Flow/tests/browser/features/step_definitions/categories_steps.rb47
-rw-r--r--Flow/tests/browser/features/step_definitions/edit_existing_steps.rb4
-rw-r--r--Flow/tests/browser/features/step_definitions/flow_in_recent_changes_steps.rb8
-rw-r--r--Flow/tests/browser/features/step_definitions/flow_no_javascript_steps.rb7
-rw-r--r--Flow/tests/browser/features/step_definitions/flow_steps.rb8
-rw-r--r--Flow/tests/browser/features/step_definitions/new_topic_steps.rb20
-rw-r--r--Flow/tests/browser/features/step_definitions/opt_in_steps.rb49
-rw-r--r--Flow/tests/browser/features/step_definitions/resolve_reopen_steps.rb14
-rw-r--r--Flow/tests/browser/features/step_definitions/special_enable_flow_steps.rb17
-rw-r--r--Flow/tests/browser/features/step_definitions/undo_actions.rb79
-rw-r--r--Flow/tests/browser/features/summarize.feature13
-rw-r--r--Flow/tests/browser/features/support/components/board_description.rb7
-rw-r--r--Flow/tests/browser/features/support/env.rb5
-rw-r--r--Flow/tests/browser/features/support/extensions.rb48
-rw-r--r--Flow/tests/browser/features/support/pages/abstract_flow_page.rb44
-rw-r--r--Flow/tests/browser/features/support/pages/board_history_page.rb8
-rw-r--r--Flow/tests/browser/features/support/pages/flow_diff_page.rb14
-rw-r--r--Flow/tests/browser/features/support/pages/flow_page.rb2
-rw-r--r--Flow/tests/browser/features/support/pages/new_flow_page.rb7
-rw-r--r--Flow/tests/browser/features/support/pages/special_notifications_page.rb2
-rw-r--r--Flow/tests/browser/features/support/pages/special_preferences_page.rb2
-rw-r--r--Flow/tests/browser/features/support/pages/topic_history_page.rb6
-rw-r--r--Flow/tests/browser/features/suppress.feature6
-rw-r--r--Flow/tests/browser/features/thank.feature6
-rw-r--r--Flow/tests/browser/features/undo.feature21
-rw-r--r--Flow/tests/browser/features/watch.feature4
-rw-r--r--Flow/tests/phpunit/Block/TopicListTest.php28
-rw-r--r--Flow/tests/phpunit/BlockFactoryTest.php18
-rw-r--r--Flow/tests/phpunit/Collection/PostCollectionTest.php14
-rw-r--r--Flow/tests/phpunit/Collection/RevisionCollectionPermissionsTest.php129
-rw-r--r--Flow/tests/phpunit/ContainerTest.php4
-rw-r--r--Flow/tests/phpunit/Conversion/UtilsTest.php169
-rw-r--r--Flow/tests/phpunit/Data/CachingObjectMapperTest.php14
-rw-r--r--Flow/tests/phpunit/Data/IndexTest.php106
-rw-r--r--Flow/tests/phpunit/Data/Listener/RecentChangesListenerTest.php18
-rw-r--r--Flow/tests/phpunit/Data/ManagerGroupTest.php7
-rw-r--r--Flow/tests/phpunit/Data/NothingTest.php64
-rw-r--r--Flow/tests/phpunit/Data/ObjectLocatorTest.php7
-rw-r--r--Flow/tests/phpunit/Data/Pager/PagerTest.php548
-rw-r--r--Flow/tests/phpunit/Data/Storage/RevisionStorageTest.php152
-rw-r--r--Flow/tests/phpunit/Data/UserNameBatchTest.php26
-rw-r--r--Flow/tests/phpunit/Data/UserNameListenerTest.php18
-rw-r--r--Flow/tests/phpunit/FlowActionsTest.php8
-rw-r--r--Flow/tests/phpunit/FlowTestCase.php28
-rw-r--r--Flow/tests/phpunit/Formatter/FormatterTest.php22
-rw-r--r--Flow/tests/phpunit/Formatter/RevisionFormatterTest.php261
-rw-r--r--Flow/tests/phpunit/Handlebars/FlowPostMetaActionsTest.php1
-rw-r--r--Flow/tests/phpunit/HookTest.php131
-rw-r--r--Flow/tests/phpunit/Import/ArchiveNameHelperTest.php54
-rw-r--r--Flow/tests/phpunit/Import/HistoricalUIDGeneratorTest.php8
-rw-r--r--Flow/tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php27
-rw-r--r--Flow/tests/phpunit/Import/PageImportStateTest.php14
-rw-r--r--Flow/tests/phpunit/Import/TalkpageImportOperationTest.php76
-rw-r--r--Flow/tests/phpunit/Import/TemplateHelperTest.php26
-rw-r--r--Flow/tests/phpunit/Import/Wikitext/ConversionStrategyTest.php41
-rw-r--r--Flow/tests/phpunit/Import/Wikitext/ImportSourceTest.php61
-rw-r--r--Flow/tests/phpunit/LinksTableTest.php317
-rw-r--r--Flow/tests/phpunit/Mock/MockImportPost.php1
-rw-r--r--Flow/tests/phpunit/Mock/MockImportRevision.php6
-rw-r--r--Flow/tests/phpunit/Mock/MockImportSource.php4
-rw-r--r--Flow/tests/phpunit/Mock/MockImportSummary.php3
-rw-r--r--Flow/tests/phpunit/Mock/MockImportTopic.php2
-rw-r--r--Flow/tests/phpunit/Model/PostRevisionTest.php4
-rw-r--r--Flow/tests/phpunit/Model/UUIDTest.php114
-rw-r--r--Flow/tests/phpunit/Model/UserTupleTest.php30
-rw-r--r--Flow/tests/phpunit/Notifications/NotificationControllerTest.php170
-rw-r--r--Flow/tests/phpunit/Notifications/NotifiedUsersTest.php68
-rw-r--r--Flow/tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php29
-rw-r--r--Flow/tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php10
-rw-r--r--Flow/tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php31
-rw-r--r--Flow/tests/phpunit/Parsoid/ReferenceExtractorTest.php44
-rw-r--r--Flow/tests/phpunit/PermissionsTest.php337
-rw-r--r--Flow/tests/phpunit/PostRevisionTestCase.php56
-rw-r--r--Flow/tests/phpunit/Repository/TreeRepositoryDbTest.php28
-rw-r--r--Flow/tests/phpunit/Repository/TreeRepositoryTest.php37
-rw-r--r--Flow/tests/phpunit/SpamFilter/AbuseFilterTest.php93
-rw-r--r--Flow/tests/phpunit/SpamFilter/ConfirmEditTest.php10
-rw-r--r--Flow/tests/phpunit/SpamFilter/ContentLengthFilterTest.php19
-rw-r--r--Flow/tests/phpunit/SpamFilter/SpamBlacklistTest.php45
-rw-r--r--Flow/tests/phpunit/SpamFilter/SpamRegexTest.php18
-rw-r--r--Flow/tests/phpunit/TalkpageManagerTest.php93
-rw-r--r--Flow/tests/phpunit/TemplateHelperTest.php29
-rw-r--r--Flow/tests/phpunit/TemplatingTest.php2
-rw-r--r--Flow/tests/phpunit/UrlGeneratorTest.php40
-rw-r--r--Flow/tests/phpunit/WatchedTopicItemsTest.php17
-rw-r--r--Flow/tests/phpunit/api/ApiFlowEditHeaderTest.php63
-rw-r--r--Flow/tests/phpunit/api/ApiFlowEditPostTest.php14
-rw-r--r--Flow/tests/phpunit/api/ApiFlowEditTitleTest.php16
-rw-r--r--Flow/tests/phpunit/api/ApiFlowEditTopicSummaryTest.php20
-rw-r--r--Flow/tests/phpunit/api/ApiFlowLockTopicTest.php24
-rw-r--r--Flow/tests/phpunit/api/ApiFlowModeratePostTest.php42
-rw-r--r--Flow/tests/phpunit/api/ApiFlowModerateTopicTest.php55
-rw-r--r--Flow/tests/phpunit/api/ApiFlowReplyTest.php14
-rw-r--r--Flow/tests/phpunit/api/ApiFlowViewHeaderTest.php20
-rw-r--r--Flow/tests/phpunit/api/ApiFlowViewTopicListTest.php202
-rw-r--r--Flow/tests/phpunit/api/ApiTestCase.php63
-rw-r--r--Flow/tests/phpunit/api/ApiWatchTopicTest.php32
-rw-r--r--Flow/tests/phpunit/bootstrap.php3
-rw-r--r--Flow/tests/qunit/engine/misc/test_flow-handlebars.js294
-rw-r--r--Flow/tests/qunit/flow/dm/test_mw.flow.dm.Board.js50
-rw-r--r--Flow/tests/qunit/flow/dm/test_mw.flow.dm.Content.js29
-rw-r--r--Flow/tests/qunit/flow/dm/test_mw.flow.dm.Post.js2
-rw-r--r--Flow/tests/qunit/flow/dm/test_mw.flow.dm.System.js6
-rw-r--r--Flow/tests/qunit/flow/dm/test_mw.flow.dm.Topic.js16
-rw-r--r--Flow/vendor/autoload.php4
-rw-r--r--Flow/vendor/composer/ClassLoader.php68
-rw-r--r--Flow/vendor/composer/autoload_namespaces.php3
-rw-r--r--Flow/vendor/composer/autoload_real.php46
-rw-r--r--Flow/vendor/composer/installed.json94
-rw-r--r--Flow/version6
807 files changed, 39464 insertions, 17515 deletions
diff --git a/Flow/.eslintrc.json b/Flow/.eslintrc.json
new file mode 100644
index 00000000..e25b9c36
--- /dev/null
+++ b/Flow/.eslintrc.json
@@ -0,0 +1,22 @@
+{
+ "extends": "wikimedia",
+ "env": {
+ "browser": true,
+ "jquery": true,
+ "qunit": true
+ },
+ "globals": {
+ "mw": true,
+ "ve": false,
+ "mediaWiki": false,
+ "OO": false,
+ "Handlebars": false,
+ "moment": false
+ },
+ "rules": {
+ "dot-notation": [ "error", { "allowKeywords": true } ],
+ "no-underscore-dangle": 0,
+ "camelcase": 0,
+ "no-use-before-define": 0
+ }
+}
diff --git a/Flow/.gitignore b/Flow/.gitignore
index a12473f8..9e215aed 100644
--- a/Flow/.gitignore
+++ b/Flow/.gitignore
@@ -3,7 +3,10 @@
.*.swp
scripts/hhvm-wrapper.phar
scripts/remotes
+node_modules/
tests/browser/.gem
tests/browser/screenshots
+vendor/
\#*#
-node_modules/
+/composer.lock
+/docs
diff --git a/Flow/.gitreview b/Flow/.gitreview
index abf3b9e9..aef1a0e1 100644
--- a/Flow/.gitreview
+++ b/Flow/.gitreview
@@ -2,5 +2,5 @@
host=gerrit.wikimedia.org
port=29418
project=mediawiki/extensions/Flow.git
-defaultbranch=REL1_26
+track=1
defaultrebase=0
diff --git a/Flow/.stylelintrc.json b/Flow/.stylelintrc.json
new file mode 100644
index 00000000..c89f6afb
--- /dev/null
+++ b/Flow/.stylelintrc.json
@@ -0,0 +1,8 @@
+{
+ "extends": "stylelint-config-wikimedia",
+ "rules": {
+ "no-descending-specificity": null,
+ "selector-no-vendor-prefix": null,
+ "value-keyword-case": null
+ }
+}
diff --git a/Flow/CODE_OF_CONDUCT.md b/Flow/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..d8e5d087
--- /dev/null
+++ b/Flow/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/Flow/CONTRIBUTING.md b/Flow/CONTRIBUTING.md
new file mode 100644
index 00000000..b403e887
--- /dev/null
+++ b/Flow/CONTRIBUTING.md
@@ -0,0 +1,30 @@
+## Getting started
+
+The easiest way to help develop Flow is to use MediaWiki-Vagrant.
+
+Start at https://www.mediawiki.org/wiki/MediaWiki-Vagrant
+
+Enable the Flow role (you may need to run `vagrant provision` afterwards).
+
+If you do not use MediaWiki-Vagrant, you will need to set up all the
+required dependencies listed at
+https://www.mediawiki.org/wiki/Extension:Flow#Dependencies .
+
+You can find the Collaboration team, which maintains Flow, in
+#wikimedia-collaboration on Freenode.
+
+## Libraries
+Flow primarily uses two libraries, OOjs UI/OO UI PHP and Handlebars. Handlebars
+is a templating language used on both the client and server.
+
+When developing, it is recommended to set:
+$wgFlowServerCompileTemplates = true;
+
+so templates are automatically updated.
+
+Before committing a change that affects templates,
+run:
+
+make compile-lightncandy
+
+to make sure all the PHP templates are updated.
diff --git a/Flow/Flow.alias.php b/Flow/Flow.alias.php
index 17081345..2f45fa68 100644
--- a/Flow/Flow.alias.php
+++ b/Flow/Flow.alias.php
@@ -1,101 +1,112 @@
<?php
/**
- * Aliases for Special:Flow
+ * Aliases for Special:StructuredDiscussions and Special:EnableStructuredDiscussions
* @file
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
-// @codingStandardsIgnoreFile
-$specialPageAliases = array();
+$specialPageAliases = [];
/** English (English) */
-$specialPageAliases['en'] = array(
- 'Flow' => array( 'Flow' ),
- 'EnableFlow' => array( 'EnableFlow' ),
-);
+$specialPageAliases['en'] = [
+ 'StructuredDiscussions' => [ 'StructuredDiscussions', 'Flow' ],
+ 'EnableStructuredDiscussions' => [ 'EnableStructuredDiscussions', 'EnableFlow' ],
+];
/** Arabic (العربية) */
-$specialPageAliases['ar'] = array(
- 'Flow' => array( 'سريان' ),
- 'EnableFlow' => array( 'فعل_سريان' ),
-);
+$specialPageAliases['ar'] = [
+ 'StructuredDiscussions' => [ 'سريان' ],
+ 'EnableStructuredDiscussions' => [ 'فعل_سريان' ],
+];
/** Egyptian Arabic (مصرى) */
-$specialPageAliases['arz'] = array(
- 'Flow' => array( 'سريان' ),
-);
+$specialPageAliases['arz'] = [
+ 'StructuredDiscussions' => [ 'سريان' ],
+];
+
+/** Bengali (বাংলা) */
+$specialPageAliases['bn'] = [
+ 'StructuredDiscussions' => [ 'ফ্লো' ],
+ 'EnableStructuredDiscussions' => [ 'ফ্লো_সক্রিয়করণ' ],
+];
/** German (Deutsch) */
-$specialPageAliases['de'] = array(
- 'EnableFlow' => array( 'Flow_aktivieren' ),
-);
+$specialPageAliases['de'] = [
+ 'EnableStructuredDiscussions' => [ 'Flow_aktivieren' ],
+];
/** Zazaki (Zazaki) */
-$specialPageAliases['diq'] = array(
- 'Flow' => array( 'Rodayış' ),
-);
+$specialPageAliases['diq'] = [
+ 'StructuredDiscussions' => [ 'Rodayış' ],
+];
/** Persian (فارسی) */
-$specialPageAliases['fa'] = array(
- 'Flow' => array( 'جریان' ),
- 'EnableFlow' => array( 'فعال‌سازی_جریان' ),
-);
+$specialPageAliases['fa'] = [
+ 'StructuredDiscussions' => [ 'جریان' ],
+ 'EnableStructuredDiscussions' => [ 'فعال‌سازی_جریان' ],
+];
/** Hebrew (עברית) */
-$specialPageAliases['he'] = array(
- 'Flow' => array( 'זרימה' ),
- 'EnableFlow' => array( 'הפעלת_זרימה' ),
-);
+$specialPageAliases['he'] = [
+ 'StructuredDiscussions' => [ 'זרימה' ],
+ 'EnableStructuredDiscussions' => [ 'הפעלת_זרימה' ],
+];
+
+/** Hungarian (magyar) */
+$specialPageAliases['hu'] = [
+ 'EnableStructuredDiscussions' => [ 'Flow bekapcsolása' ],
+];
/** Korean (한국어) */
-$specialPageAliases['ko'] = array(
- 'Flow' => array( '플로우' ),
-);
+$specialPageAliases['ko'] = [
+ 'StructuredDiscussions' => [ '플로우' ],
+ 'EnableStructuredDiscussions' => [ '플로우활성화' ],
+];
/** Northern Luri (لۊری شومالی) */
-$specialPageAliases['lrc'] = array(
- 'Flow' => array( 'جأریان' ),
-);
+$specialPageAliases['lrc'] = [
+ 'StructuredDiscussions' => [ 'جأریان' ],
+];
/** Macedonian (македонски) */
-$specialPageAliases['mk'] = array(
- 'Flow' => array( 'Тек' ),
- 'EnableFlow' => array( 'ОвозможиТек' ),
-);
+$specialPageAliases['mk'] = [
+ 'StructuredDiscussions' => [ 'Тек' ],
+ 'EnableStructuredDiscussions' => [ 'ОвозможиТек' ],
+];
/** Malayalam (മലയാളം) */
-$specialPageAliases['ml'] = array(
- 'Flow' => array( 'പ്രവാഹം' ),
-);
+$specialPageAliases['ml'] = [
+ 'StructuredDiscussions' => [ 'പ്രവാഹം' ],
+];
/** Portuguese (português) */
-$specialPageAliases['pt'] = array(
- 'Flow' => array( 'Fluência', 'Fluencia' ),
-);
+$specialPageAliases['pt'] = [
+ 'StructuredDiscussions' => [ 'Fluência', 'Fluencia' ],
+];
/** Brazilian Portuguese (português do Brasil) */
-$specialPageAliases['pt-br'] = array(
- 'EnableFlow' => array( 'Habilitar_Flow' ),
-);
+$specialPageAliases['pt-br'] = [
+ 'EnableStructuredDiscussions' => [ 'Habilitar_Flow' ],
+];
/** Swedish (svenska) */
-$specialPageAliases['sv'] = array(
- 'Flow' => array( 'Flöde' ),
-);
+$specialPageAliases['sv'] = [
+ 'StructuredDiscussions' => [ 'Flöde' ],
+];
/** Vietnamese (Tiếng Việt) */
-$specialPageAliases['vi'] = array(
- 'Flow' => array( 'Flow' ),
- 'EnableFlow' => array( 'Kích_hoạt_Flow' ),
-);
+$specialPageAliases['vi'] = [
+ 'StructuredDiscussions' => [ 'Flow' ],
+ 'EnableStructuredDiscussions' => [ 'Kích_hoạt_Flow' ],
+];
/** Simplified Chinese (中文(简体)‎) */
-$specialPageAliases['zh-hans'] = array(
- 'EnableFlow' => array( '启用Flow' ),
-);
+$specialPageAliases['zh-hans'] = [
+ 'EnableStructuredDiscussions' => [ '启用Flow' ],
+];
/** Traditional Chinese (中文(繁體)‎) */
-$specialPageAliases['zh-hant'] = array(
- 'Flow' => array( '流動量' ),
- 'EnableFlow' => array( '啟用流動量' ),
-); \ No newline at end of file
+$specialPageAliases['zh-hant'] = [
+ 'StructuredDiscussions' => [ '流動量' ],
+ 'EnableStructuredDiscussions' => [ '啟用流動量' ],
+];
diff --git a/Flow/Flow.namespaces.php b/Flow/Flow.namespaces.php
index c3ae1865..235a5260 100644
--- a/Flow/Flow.namespaces.php
+++ b/Flow/Flow.namespaces.php
@@ -7,163 +7,218 @@
require_once __DIR__ . '/defines.php';
-$namespaceNames = array();
+$namespaceNames = [];
+
+/** English */
+$namespaceNames['en'] = [
+ NS_TOPIC => 'Topic',
+];
/** Arabic */
-$namespaceNames['ar'] = array(
+$namespaceNames['ar'] = [
NS_TOPIC => 'موضوع',
-);
+];
/** Asturian */
-$namespaceNames['ast'] = array(
- NS_TOPIC => 'Asuntu',
-);
+$namespaceNames['ast'] = [
+ NS_TOPIC => 'Asuntu',
+];
/** South Azerbaijani */
-$namespaceNames['azb'] = array(
- NS_TOPIC => 'مبحث',
-);
+$namespaceNames['azb'] = [
+ NS_TOPIC => 'مبحث',
+];
+
+/** Bashkir **/
+$namespaceNames['ba'] = [
+ NS_TOPIC => 'Тема',
+];
/** Western Balochi */
-$namespaceNames['bgn'] = array(
- NS_TOPIC => 'سر_ئو_بُن',
-);
+$namespaceNames['bgn'] = [
+ NS_TOPIC => 'سر_ئو_بُن',
+];
+
+/** Bengali */
+$namespaceNames['bn'] = [
+ NS_TOPIC => 'প্রসঙ্গ',
+];
/** Catalan */
-$namespaceNames['ca'] = array(
- NS_TOPIC => 'Tema',
-);
+$namespaceNames['ca'] = [
+ NS_TOPIC => 'Tema',
+];
/** Central Kurdish */
-$namespaceNames['ckb'] = array(
- NS_TOPIC => 'بابه‌ت',
-);
+$namespaceNames['ckb'] = [
+ NS_TOPIC => 'بابه‌ت',
+];
/** German */
-$namespaceNames['de'] = array(
- NS_TOPIC => 'Thema',
-);
+$namespaceNames['de'] = [
+ NS_TOPIC => 'Thema',
+];
-/** English */
-$namespaceNames['en'] = array(
- NS_TOPIC => 'Topic',
-);
+/** Dinka */
+$namespaceNames['din'] = [
+ NS_TOPIC => 'Këjamic',
+];
+
+/** Zazaki */
+$namespaceNames['diq'] = [
+ NS_TOPIC => 'Mewzu',
+];
/** Spanish */
-$namespaceNames['es'] = array(
- NS_TOPIC => 'Tema',
-);
+$namespaceNames['es'] = [
+ NS_TOPIC => 'Tema',
+];
+
+/** Estonian */
+$namespaceNames['et'] = [
+ NS_TOPIC => 'Teema',
+];
/** Persian */
-$namespaceNames['fa'] = array(
- NS_TOPIC => 'مبحث',
-);
+$namespaceNames['fa'] = [
+ NS_TOPIC => 'مبحث',
+];
/** Finnish */
-$namespaceNames['fi'] = array(
- NS_TOPIC => 'Aihe',
-);
+$namespaceNames['fi'] = [
+ NS_TOPIC => 'Aihe',
+];
/** French */
-$namespaceNames['fr'] = array(
- NS_TOPIC => 'Sujet',
-);
+$namespaceNames['fr'] = [
+ NS_TOPIC => 'Sujet',
+];
+
+$namespaceNames['gom'] = [
+ NS_TOPIC => 'विशय',
+];
/** Hebrew */
-$namespaceNames['he'] = array(
- NS_TOPIC => 'נושא',
-);
+$namespaceNames['he'] = [
+ NS_TOPIC => 'נושא',
+];
+
+/** Hindi */
+$namespaceNames['hi'] = [
+ NS_TOPIC => 'प्रकरण',
+];
+
+/** Hungarian */
+$namespaceNames['hu'] = [
+ NS_TOPIC => 'Téma',
+];
+
+/** Indonesian */
+$namespaceNames['id'] = [
+ NS_TOPIC => 'Topik',
+];
/** Italian */
-$namespaceNames['it'] = array(
- NS_TOPIC => 'Argomento',
-);
+$namespaceNames['it'] = [
+ NS_TOPIC => 'Argomento',
+];
/** Korean */
-$namespaceNames['ko'] = array(
+$namespaceNames['ko'] = [
NS_TOPIC => '주제',
-);
+];
+
/** Luxembourgish */
-$namespaceNames['lb'] = array(
- NS_TOPIC => 'Thema',
-);
+$namespaceNames['lb'] = [
+ NS_TOPIC => 'Thema',
+];
/** Northern Luri */
-$namespaceNames['lrc'] = array(
- NS_TOPIC => 'گأپئسئن',
-);
+$namespaceNames['lrc'] = [
+ NS_TOPIC => 'گأپئسئن',
+];
/** Latvian */
-$namespaceNames['lv'] = array(
- NS_TOPIC => 'Tēma',
-);
+$namespaceNames['lv'] = [
+ NS_TOPIC => 'Tēma',
+];
/** Macedonian */
-$namespaceNames['mk'] = array(
- NS_TOPIC => 'Тема',
-);
+$namespaceNames['mk'] = [
+ NS_TOPIC => 'Тема',
+];
/** Mazandarani */
-$namespaceNames['mzn'] = array(
- NS_TOPIC => 'تاپیک',
-);
+$namespaceNames['mzn'] = [
+ NS_TOPIC => 'تاپیک',
+];
+
+/** Norwegian Bokmål (norsk bokmål) */
+$namespaceNames['nb'] = [
+ NS_TOPIC => 'Sak',
+];
/** Dutch */
-$namespaceNames['nl'] = array(
- NS_TOPIC => 'Onderwerp',
-);
+$namespaceNames['nl'] = [
+ NS_TOPIC => 'Onderwerp',
+];
/** Occitan */
-$namespaceNames['oc'] = array(
- NS_TOPIC => 'Subjècte',
-);
+$namespaceNames['oc'] = [
+ NS_TOPIC => 'Subjècte',
+];
/** Orya */
-$namespaceNames['or'] = array(
- NS_TOPIC => 'ବିଷୟ',
-);
+$namespaceNames['or'] = [
+ NS_TOPIC => 'ବିଷୟ',
+];
/** Polish */
-$namespaceNames['pl'] = array(
- NS_TOPIC => 'Wątek',
-);
+$namespaceNames['pl'] = [
+ NS_TOPIC => 'Wątek',
+];
+
+/** Western Punjabi */
+$namespaceNames['pnb'] = [
+ NS_TOPIC => 'موضوع',
+];
/** Portuguese */
-$namespaceNames['pt'] = array(
- NS_TOPIC => 'Tópico',
-);
+$namespaceNames['pt'] = [
+ NS_TOPIC => 'Tópico',
+];
/** Russian */
-$namespaceNames['ru'] = array(
- NS_TOPIC => 'Тема',
-);
+$namespaceNames['ru'] = [
+ NS_TOPIC => 'Тема',
+];
/** Slovenian */
-$namespaceNames['sl'] = array(
- NS_TOPIC => 'Tema',
-);
+$namespaceNames['sl'] = [
+ NS_TOPIC => 'Tema',
+];
/** Swedish */
-$namespaceNames['sv'] = array(
- NS_TOPIC => 'Ämne',
-);
+$namespaceNames['sv'] = [
+ NS_TOPIC => 'Ämne',
+];
/** Ukrainian */
-$namespaceNames['uk'] = array(
- NS_TOPIC => 'Тема',
-);
+$namespaceNames['uk'] = [
+ NS_TOPIC => 'Тема',
+];
/** Urdu */
-$namespaceNames['ur'] = array(
- NS_TOPIC => 'موضوع',
-);
+$namespaceNames['ur'] = [
+ NS_TOPIC => 'موضوع',
+];
/** Vietnamese */
-$namespaceNames['vi'] = array(
- NS_TOPIC => 'Đề_tài',
-);
+$namespaceNames['vi'] = [
+ NS_TOPIC => 'Đề_tài',
+];
/** Yiddish */
-$namespaceNames['yi'] = array(
- NS_TOPIC => 'טעמע',
-);
+$namespaceNames['yi'] = [
+ NS_TOPIC => 'טעמע',
+];
diff --git a/Flow/Flow.php b/Flow/Flow.php
index 894bab9d..be35548c 100644
--- a/Flow/Flow.php
+++ b/Flow/Flow.php
@@ -44,374 +44,21 @@
* @file
* @ingroup Extensions
*/
-
-// Extension credits that will show up on Special:Version
-$wgExtensionCredits['other'][] = array(
- 'path' => __FILE__,
- 'name' => 'Flow',
- 'url' => 'https://www.mediawiki.org/wiki/Extension:Flow',
- 'author' => array(
- // Alphabetical by last name
- 'Erik Bernhardson',
- 'Stephane Bisson',
- 'Matthew Flaschen',
- 'Andrew Garrett',
- 'Shahyar Ghobadpour',
- 'Pau Giner',
- 'Roan Kattouw',
- 'Chris McMahon',
- 'Kunal Mehta',
- 'Matthias Mullie',
- 'S Page',
- 'Jon Robson',
- 'Moriel Schottlender',
- 'Benny Situ',
- ),
- 'descriptionmsg' => 'flow-desc',
- 'license-name' => 'GPL-2.0+', // Appears with link to COPYING on Special:Version
- 'version' => '1.1',
-);
-
-require_once __DIR__ . '/defines.php';
-
-// Only matters when $wgCapitalLinks has non-default setting, but always safe
-$wgCapitalLinkOverrides[NS_TOPIC] = true;
-
-define( 'CONTENT_MODEL_FLOW_BOARD', 'flow-board' );
-$wgNamespacesWithSubpages[NS_TOPIC] = false;
-$wgNamespaceContentModels[NS_TOPIC] = CONTENT_MODEL_FLOW_BOARD;
-
-$dir = __DIR__ . '/';
-require $dir . 'Resources.php';
-
-$wgHooks['ResourceLoaderRegisterModules'][] = 'FlowHooks::onResourceLoaderRegisterModules';
-$wgHooks['BeforePageDisplay'][] = 'FlowHooks::onBeforePageDisplay';
-
-$wgMessagesDirs['Flow'] = __DIR__ . '/i18n';
-$wgExtensionMessagesFiles['FlowNamespaces'] = $dir . '/Flow.namespaces.php';
-
-// This file is autogenerated by scripts/gen-autoload.php
-require __DIR__ . '/autoload.php';
-
-$wgAPIModules['flow-parsoid-utils'] = 'Flow\Api\ApiParsoidUtilsFlow';
-$wgAPIModules['flow'] = 'Flow\Api\ApiFlow';
-$wgAPIPropModules['flowinfo'] = 'Flow\Api\ApiQueryPropFlowInfo';
-
-// Special:Flow
-$wgExtensionMessagesFiles['FlowAlias'] = $dir . 'Flow.alias.php';
-$wgSpecialPages['Flow'] = 'Flow\Specials\SpecialFlow';
-$wgSpecialPages['EnableFlow'] = 'Flow\Specials\SpecialEnableFlow';
-
-// Housekeeping hooks
-$wgHooks['LoadExtensionSchemaUpdates'][] = 'FlowHooks::getSchemaUpdates';
-$wgHooks['GetPreferences'][] = 'FlowHooks::onGetPreferences';
-$wgHooks['UnitTestsList'][] = 'FlowHooks::getUnitTests';
-$wgHooks['OldChangesListRecentChangesLine'][] = 'FlowHooks::onOldChangesListRecentChangesLine';
-$wgHooks['ChangesListInsertArticleLink'][] = 'FlowHooks::onChangesListInsertArticleLink';
-$wgHooks['ChangesListInitRows'][] = 'FlowHooks::onChangesListInitRows';
-$wgHooks['EnhancedChangesList::getLogText'][] = 'FlowHooks::onGetLogText';
-$wgHooks['EnhancedChangesListModifyLineData'][] = 'FlowHooks::onEnhancedChangesListModifyLineData';
-$wgHooks['EnhancedChangesListModifyBlockLineData'][] = 'FlowHooks::onEnhancedChangesListModifyBlockLineData';
-$wgHooks['SkinTemplateNavigation::Universal'][] = 'FlowHooks::onSkinTemplateNavigation';
-$wgHooks['Article::MissingArticleConditions'][] = 'FlowHooks::onMissingArticleConditions';
-$wgHooks['SpecialWatchlistGetNonRevisionTypes'][] = 'FlowHooks::onSpecialWatchlistGetNonRevisionTypes';
-$wgHooks['UserGetReservedNames'][] = 'FlowHooks::onUserGetReservedNames';
-$wgHooks['ResourceLoaderGetConfigVars'][] = 'FlowHooks::onResourceLoaderGetConfigVars';
-$wgHooks['ContribsPager::reallyDoQuery'][] = 'FlowHooks::onContributionsQuery';
-$wgHooks['DeletedContribsPager::reallyDoQuery'][] = 'FlowHooks::onDeletedContributionsQuery';
-$wgHooks['ContributionsLineEnding'][] = 'FlowHooks::onContributionsLineEnding';
-$wgHooks['DeletedContributionsLineEnding'][] = 'FlowHooks::onDeletedContributionsLineEnding';
-$wgHooks['ApiFeedContributions::feedItem'][] = 'FlowHooks::onContributionsFeedItem';
-$wgHooks['AbuseFilter-computeVariable'][] = 'FlowHooks::onAbuseFilterComputeVariable';
-$wgHooks['AbortEmailNotification'][] = 'FlowHooks::onAbortEmailNotification';
-$wgHooks['EchoAbortEmailNotification'][] = 'FlowHooks::onEchoAbortEmailNotification';
-$wgHooks['BeforeEchoEventInsert'][] = 'FlowHooks::onBeforeEchoEventInsert';
-$wgHooks['ArticleEditUpdateNewTalk'][] = 'FlowHooks::onArticleEditUpdateNewTalk';
-$wgHooks['InfoAction'][] = 'FlowHooks::onInfoAction';
-$wgHooks['SpecialCheckUserGetLinksFromRow'][] = 'FlowHooks::onSpecialCheckUserGetLinksFromRow';
-$wgHooks['CheckUserInsertForRecentChange'][] = 'FlowHooks::onCheckUserInsertForRecentChange';
-$wgHooks['SkinMinervaDefaultModules'][] = 'FlowHooks::onSkinMinervaDefaultModules';
-$wgHooks['IRCLineURL'][] = 'FlowHooks::onIRCLineURL';
-$wgHooks['WhatLinksHereProps'][] = 'FlowHooks::onWhatLinksHereProps';
-$wgHooks['ResourceLoaderTestModules'][] = 'FlowHooks::onResourceLoaderTestModules';
-$wgHooks['ShowMissingArticle'][] = 'FlowHooks::onShowMissingArticle';
-$wgHooks['MessageCache::get'][] = 'FlowHooks::onMessageCacheGet';
-$wgHooks['WatchArticle'][] = 'FlowHooks::onWatchArticle';
-$wgHooks['UnwatchArticle'][] = 'FlowHooks::onWatchArticle';
-$wgHooks['CanonicalNamespaces'][] = 'FlowHooks::onCanonicalNamespaces';
-$wgHooks['MovePageIsValidMove'][] = 'FlowHooks::onMovePageIsValidMove';
-$wgHooks['AbortMove'][] = 'FlowHooks::onAbortMove';
-$wgHooks['TitleMove'][] = 'FlowHooks::onTitleMove';
-$wgHooks['TitleMoveComplete'][] = 'FlowHooks::onTitleMoveComplete';
-$wgHooks['TitleSquidURLs'][] = 'FlowHooks::onTitleSquidURLs';
-$wgHooks['WatchlistEditorBuildRemoveLine'][] = 'FlowHooks::onWatchlistEditorBuildRemoveLine';
-$wgHooks['WatchlistEditorBeforeFormRender'][] = 'FlowHooks::onWatchlistEditorBeforeFormRender';
-$wgHooks['NamespaceIsMovable'][] = 'FlowHooks::onNamespaceIsMovable';
-$wgHooks['CategoryViewer::doCategoryQuery'][] = 'FlowHooks::onCategoryViewerDoCategoryQuery';
-$wgHooks['CategoryViewer::generateLink'][] = 'FlowHooks::onCategoryViewerGenerateLink';
-$wgHooks['ArticleConfirmDelete'][] = 'FlowHooks::onArticleConfirmDelete';
-$wgHooks['ArticleDelete'][] = 'FlowHooks::onArticleDelete';
-$wgHooks['ArticleUndelete'][] = 'FlowHooks::onArticleUndelete';
-$wgHooks['SearchableNamespaces'][] = 'FlowHooks::onSearchableNamespaces';
-
-// Extension:UserMerge support
-$wgHooks['UserMergeAccountFields'][] = 'FlowHooks::onUserMergeAccountFields';
-$wgHooks['MergeAccountFromTo'][] = 'FlowHooks::onMergeAccountFromTo';
-
-// Special case: Flow is the successor to LiquidThreads and any Flow boards should automatically
-// not be LiquidThreads talk pages.
-$wgHooks['LiquidThreadsIsLqtPage'][] = 'FlowHooks::onIsLiquidThreadsPage';
-
-// Echo integration
-$wgHooks['BeforeCreateEchoEvent'][] = 'Flow\NotificationController::onBeforeCreateEchoEvent';
-$wgHooks['EchoGetDefaultNotifiedUsers'][] = 'Flow\NotificationController::getDefaultNotifiedUsers';
-$wgHooks['EchoGetBundleRules'][] = 'Flow\NotificationController::onEchoGetBundleRules';
-
-// Beta feature Flow on user talk page
-$wgHooks['GetBetaFeaturePreferences'][] = 'FlowHooks::onGetBetaFeaturePreferences';
-$wgHooks['UserSaveOptions'][] = 'FlowHooks::onUserSaveOptions';
-
-// Extension initialization
-$wgExtensionFunctions[] = 'FlowHooks::initFlowExtension';
-
-// Flow Content Type
-$wgContentHandlers['flow-board'] = 'Flow\Content\BoardContentHandler';
-
-// User permissions
-// Added to $wgFlowGroupPermissions instead of $wgGroupPermissions immediately,
-// to easily fetch Flow-specific permissions in tests/PermissionsTest.php.
-// If you wish to make local permission changes, add them to $wgGroupPermissions
-// directly - tests will fail otherwise, since they'll be based on a different
-// permissions config than what's assumed to test.
-$wgFlowGroupPermissions = array();
-$wgFlowGroupPermissions['*']['flow-hide'] = true;
-$wgFlowGroupPermissions['user']['flow-lock'] = true;
-$wgFlowGroupPermissions['sysop']['flow-lock'] = true;
-$wgFlowGroupPermissions['sysop']['flow-delete'] = true;
-$wgFlowGroupPermissions['sysop']['flow-edit-post'] = true;
-$wgFlowGroupPermissions['oversight']['flow-suppress'] = true;
-$wgFlowGroupPermissions['flow-bot']['flow-create-board'] = true;
-$wgGroupPermissions = array_merge_recursive( $wgGroupPermissions, $wgFlowGroupPermissions );
-
-// Make sure all of these are granted via OAuth in Hooks.php
-$wgAvailableRights[] = 'flow-hide';
-$wgAvailableRights[] = 'flow-lock';
-$wgAvailableRights[] = 'flow-delete';
-$wgAvailableRights[] = 'flow-suppress';
-$wgAvailableRights[] = 'flow-edit-post';
-$wgAvailableRights[] = 'flow-create-board';
-
-// Register Flow import paths
-$wgResourceLoaderLESSImportPaths = array_merge( $wgResourceLoaderLESSImportPaths, array(
- $dir . "modules/styles/flow.less/",
-) );
-
-// Configuration
-
-// URL for more information about the Flow notification system
-$wgFlowHelpPage = '//www.mediawiki.org/wiki/Special:MyLanguage/Extension:Flow';
-
-// $wgFlowCluster will define what external DB server should be used.
-// If set to false, the current database (wfGetDB) will be used to read/write
-// data from/to. If Flow data is supposed to be stored on an external database,
-// set the value of this variable to the $wgExternalServers key representing
-// that external connection.
-$wgFlowCluster = false;
-
-// Database to use for Flow metadata. Set to false to use the wiki db. Any number of wikis can
-// and should share the same Flow database.
-$wgFlowDefaultWikiDb = false;
-
-// Used for content storage. False to store content in flow db. Otherwise a cluster or
-// list of clusters to use with ExternalStore. Provided clusters must exist in
-// $wgExternalStores. Multiple clusters required for HA, so inserts can continue
-// if one of the masters is down for maint or any other reason.
-// ex:
-// $wgFlowExternalStore = array( 'DB://cluster24', 'DB://cluster25' );
-$wgFlowExternalStore = false;
-
-// By default, Flow will store content in HTML. However, this requires having Parsoid up
-// and running, as it'll be necessary to convert HTML to wikitext for the basic editor.
-// (n.b. to use VisualEditor, you'll definitely need Parsoid, so if you do support VE,
-// might as well set this to HTML right away)
-// If $wgFlowParsoidURL is null, $wgFlowContentFormat will be forced to wikitext.
-//
-// The 'wikitext' format is likely to be deprecated in the future.
-$wgFlowContentFormat = 'html'; // possible values: html|wikitext XXX bug 70148 with wikitext
-
-// Flow Parsoid config
-// THESE VARIABLES ARE DEPRECATED.
-// Use the VirtualRESTService ($wgVirtualRestConfig) to configure
-// Parsoid and/or RESTBase.
-// Please note that this configuration is separate from VE's Parsoid config:
-// you'll have to fill out these variables too if you want to use Parsoid.
-$wgFlowParsoidURL = null; // also see $wgVisualEditorParsoidURL
-$wgFlowParsoidPrefix = null; // also see $wgVisualEditorParsoidPrefix
-$wgFlowParsoidTimeout = null; // In seconds; also see $wgVisualEditorParsoidTimeout
-$wgFlowParsoidHTTPProxy = null; // see also $wgVisualEditorParsoidHTTPProxy
-// Forward users' Cookie: headers to Parsoid. Required for private wikis (login required to read).
-// If the wiki is not private (i.e. $wgGroupPermissions['*']['read'] is true) this configuration
-// variable will be ignored.
-//
-// This feature requires a non-locking session store. The default session store will not work and
-// will cause deadlocks when trying to use this feature. If you experience deadlock issues, enable
-// $wgSessionsInObjectCache.
-//
-// WARNING: ONLY enable this on private wikis and ONLY IF you understand the SECURITY IMPLICATIONS
-// of sending Cookie headers to Parsoid over HTTP. For security reasons, it is strongly recommended
-// that $wgVisualEditorParsoidURL be pointed to localhost if this setting is enabled.
-$wgFlowParsoidForwardCookies = false;
-
-// When visiting the flow for an article but not specifying what type of workflow should be viewed,
-// use this workflow
-$wgFlowDefaultWorkflow = 'discussion';
-
-// Limits for paging
-$wgFlowDefaultLimit = 10;
-$wgFlowMaxLimit = 100;
-
-// Echo notification subscription preference
-$wgDefaultUserOptions['echo-subscriptions-web-flow-discussion'] = true;
-$wgDefaultUserOptions['echo-subscriptions-email-flow-discussion'] = false;
-
-// Default sort order of a topiclist view. See TopicListBlock::getFindOptions()
-// for more information.
-$wgDefaultUserOptions['flow-topiclist-sortby'] = 'updated';
-
-// Default editor to use in Flow
-$wgDefaultUserOptions['flow-editor'] = 'wikitext';
-
-// Default state of the side rail
-$wgDefaultUserOptions['flow-side-rail-state'] = 'expanded';
-
-// Maximum number of users that can be mentioned in one comment
-$wgFlowMaxMentionCount = 100;
-
-// Max threading depth
-$wgFlowMaxThreadingDepth = 8;
-
-// A list of editors to use, in priority order
-$wgFlowEditorList = array( 'visualeditor', 'wikitext' );
-
-// Action details config file
-require $dir . 'FlowActions.php';
-
-// Register activity log formatter hooks
-foreach( $wgFlowActions as $action => $options ) {
- if ( is_string( $options ) ) {
- continue;
- }
- if ( isset( $options['log_type'] ) ) {
- $log = $options['log_type'];
-
- // Some actions are more complex closures - to be added manually.
- if ( is_string( $log ) ) {
- $wgLogActionsHandlers["$log/flow-$action"] = 'Flow\Log\ActionFormatter';
- }
- }
-}
-// Manually add that more complex actions
-$wgLogActionsHandlers['delete/flow-restore-post'] = 'Flow\Log\ActionFormatter';
-$wgLogActionsHandlers['suppress/flow-restore-post'] = 'Flow\Log\ActionFormatter';
-$wgLogActionsHandlers['delete/flow-restore-topic'] = 'Flow\Log\ActionFormatter';
-$wgLogActionsHandlers['suppress/flow-restore-topic'] = 'Flow\Log\ActionFormatter';
-$wgLogActionsHandlers['import/lqt-to-flow-topic'] = 'Flow\Log\LqtImportFormatter';
-
-// Register URL actions
-foreach( $wgFlowActions as $action => $options ) {
- if ( is_array( $options ) && isset( $options['handler-class'] ) ) {
- $wgActions[$action] = true;
- }
+if ( function_exists( 'wfLoadExtension' ) ) {
+ wfLoadExtension( 'Flow' );
+ // Keep i18n globals so mergeMessageFileList.php doesn't break
+ $wgMessagesDirs['Flow'] = [
+ __DIR__ . '/i18n',
+ __DIR__ . '/i18n/api',
+ ];
+ $wgExtensionMessagesFiles['FlowAlias'] = __DIR__ . '/Flow.alias.php';
+ $wgExtensionMessagesFiles['FlowNamespaces'] = __DIR__ . '/Flow.namespaces.php';
+ /* wfWarn(
+ 'Deprecated PHP entry point used for Flow extension. ' .
+ 'Please use wfLoadExtension instead, ' .
+ 'see https://www.mediawiki.org/wiki/Extension_registration for more details.'
+ ); */
+ return;
+} else {
+ die( 'This version of the Flow extension requires MediaWiki 1.25+' );
}
-
-// Set this to false to disable all memcache usage. Do not just turn the cache
-// back on, it will be out of sync with the database. There is not yet an official
-// process for re-sync'ing the cache yet, currently the per-index versions would
-// need to incremented(ask the flow team).
-//
-// This will reduce, but not necessarily kill, performance. The queries issued
-// will be the queries necessary to fill the cache rather than only the queries
-// needed to answer the request. A bit of a refactor in ObjectManager::findMulti
-// to allow query without indexes, along with adjusting container.php to only
-// include the indexes when this is true, would get most of the way towards making
-// this a reasonably performant option.
-$wgFlowUseMemcache = true;
-
-// The default length of time to cache flow data in memcache. This value can be tuned
-// in conjunction with measurements of cache hit/miss ratios to achieve the desired
-// tradeoff between memory usage, db queries, and response time. The initial default
-// of 3 days means Flow will attempt to keep in memcache all data models requested in
-// the last 3 days.
-$wgFlowCacheTime = 60 * 60 * 24 * 3;
-// A version string appended to cache keys. Bump this if cache format or logic changes.
-// Flow can be a cross-wiki database accessed by wikis running different versions of the
-// Flow code; WMF sometimes overrides this globally in wmf-config/CommonSettings.php
-$wgFlowCacheVersion = '4.7';
-
-// ElasticSearch servers
-$wgFlowSearchServers = array( 'localhost' );
-
-// Flow search config setting - akin to CirrusSearch
-// See CirrusSearch.php for documentation for these params, which have similar
-// variable names (s/FlowSearch/CirrusSearch/)
-$wgFlowSearchConnectionAttempts = 1; // see $wgCirrusSearchConnectionAttempts
-$wgFlowSearchBannedPlugins = array(); // see $wgCirrusSearchBannedPlugins
-$wgFlowSearchOptimizeIndexForExperimentalHighlighter = false; // see $wgCirrusSearchOptimizeIndexForExperimentalHighlighter
-$wgFlowSearchMaxShardsPerNode = array(); // see $wgCirrusSearchMaxShardsPerNode
-$wgFlowSearchRefreshInterval = 1; // see $wgCirrusSearchRefreshInterval
-$wgFlowSearchMaintenanceTimeout = 3600; // see $wgCirrusSearchMaintenanceTimeout
-$wgFlowSearchReplicas = '0-2'; // see $wgCirrusSearchReplicas
-$wgFlowSearchShardCount = array( 'flow' => 4 ); // see $wgCirrusSearchShardCount
-$wgFlowSearchCacheWarmers = array(); // see $wgCirrusSearchCacheWarmers
-$wgFlowSearchMergeSettings = array(
- 'flow' => array(
- 'max_merge_at_once' => 10,
- 'segments_per_tier' => 10,
- 'reclaim_deletes_weight' => 2.0,
- 'max_merged_segment' => '5g',
- ),
-); // see $wgCirrusSearchMergeSettings
-$wgFlowSearchIndexAllocation = array(
- 'include' => array(),
- 'exclude' => array(),
- 'require' => array(),
-); // see $wgCirrusSearchIndexAllocation
-
-// This allows running Flow without the search functionality. Right now, it's because
-// the search functionality isn't ready for production, but we need to test it locally.
-// We can decide later (after it's in production) whether to get rid of this setting.
-// For example, this controls whether ApiFlowSearch is available.
-$wgFlowSearchEnabled = false;
-
-// Custom group name for AbuseFilter
-// Acceptable values:
-// * a specific value for flow-specific filters
-// * 'default' to use core filters; make sure they are compatible with both core
-// and Flow (e.g. Flow has no 'summary' variable to test on)
-// * false to not use AbuseFilter
-$wgFlowAbuseFilterGroup = 'flow';
-
-// AbuseFilter emergency disable values for Flow
-$wgFlowAbuseFilterEmergencyDisableThreshold = 0.10;
-$wgFlowAbuseFilterEmergencyDisableCount = 50;
-$wgFlowAbuseFilterEmergencyDisableAge = 86400; // One day.
-
-// Timeout for Flow's AJAX requests (only affects ones that go through flow-api.js), in seconds
-$wgFlowAjaxTimeout = 30;
-
-// Actions that must pass through to MediaWiki on Flow-enabled pages
-$wgFlowCoreActionWhitelist = array( 'info', 'protect', 'unprotect', 'unwatch', 'watch', 'history', 'wikilove', 'move', 'delete' );
-
-// When set to true Flow will compile templates into their intermediate forms
-// on every run. When set to false Flow will use the versions already written
-// to disk. Production should always have this set to false.
-$wgFlowServerCompileTemplates = false;
-
-// Enable/disable event logging
-$wgFlowEventLogging = false;
-
-// Temporary field to allow source wiki to be null for references until it's backfilled.
-$wgFlowMigrateReferenceWiki = false;
-
-// Enable/Disable Opt-in beta feature
-$wgFlowEnableOptInBetaFeature = false;
diff --git a/Flow/FlowActions.php b/Flow/FlowActions.php
index 3e696b9a..7543299a 100644
--- a/Flow/FlowActions.php
+++ b/Flow/FlowActions.php
@@ -21,8 +21,11 @@ use Flow\Data\Listener\RecentChangesListener;
* no one can perform the action described by that key.
* * root-permissions: similar to 'permissions', but applies to the last revision
* of the root post (= the topic) for the revision the action is executed against.
+ * If root-permissions is omitted entirely, it doesn't affect what is allowed.
+ * However, if any keys are set, omitted keys are treated as prohibited.
* * core-delete-permissions: array of rights, where any of those rights will
- * give you permission to do the action on a deleted board (isAllowedAny).
+ * give you permission to do the action on a deleted board (isAllowedAny).
+ * Empty string and omitted behave like 'permissions'.
* * links: the set of read links to generate and return in API responses
* * actions: the set of write links to generate and return in API responses
* * history: all history-related information:
@@ -39,75 +42,79 @@ use Flow\Data\Listener\RecentChangesListener;
* * rc_title: Either 'article' or 'owner' to select between Workflow::getArticleTitle
* or Workflow::getOwnerTitle being used as the related recentchanges entry on insert
* * editcount: True to increment user's edit count for this action
- * * modules: Modules to insert with RL to html page for this action instead of the defaults
+ * * modules: Modules to insert with RL to html page for this action instead of the defaults.
+ * * All actions other than view should have an array here, unless the default
+ * * modules are known to work. You can specify an empty array, or a custom set of modules.
* * moduleStyles: Style modules to insert with RL to html page for this action instead of the defaults
*/
-$wgFlowActions = array(
- 'create-header' => array(
+$wgFlowActions = [
+ 'create-header' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
Header::MODERATED_NONE => '',
- ),
- 'links' => array( 'board-history', 'workflow', 'header-revision' ),
- 'actions' => array( 'edit-header' ),
- 'history' => array(
+ ],
+ 'links' => [ 'board-history', 'workflow', 'header-revision' ],
+ 'actions' => [ 'edit-header' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-create-header',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
- ),
+ ],
'class' => 'flow-history-create-header',
- ),
+ ],
'editcount' => true,
- ),
+ ],
- 'edit-header' => array(
+ 'edit-header' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
Header::MODERATED_NONE => '',
- ),
- 'links' => array( 'board-history', 'diff-header', 'workflow', 'header-revision' ),
- 'actions' => array( 'edit-header', 'undo-edit-header' ),
- 'history' => array(
+ ],
+ 'links' => [ 'board-history', 'diff-header', 'workflow', 'header-revision' ],
+ 'actions' => [ 'edit-header', 'undo-edit-header' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-header',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
- ),
+ ],
'class' => 'flow-history-edit-header',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
+ 'modules' => [],
'editcount' => true,
- ),
+ ],
// @todo this is almost copy/paste from edit-header except the handler-class. find
// a way to share.
- 'undo-edit-header' => array(
+ 'undo-edit-header' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
Header::MODERATED_NONE => '',
- ),
- 'links' => array( 'board-history', 'diff-header', 'workflow', 'header-revision' ),
- 'actions' => array( 'edit-header', 'undo-edit-header' ),
- 'history' => array(
+ ],
+ 'links' => [ 'board-history', 'diff-header', 'workflow', 'header-revision' ],
+ 'actions' => [ 'edit-header', 'undo-edit-header' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-header',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
- ),
+ ],
'class' => 'flow-history-edit-header',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
+ 'modules' => [],
'editcount' => true,
// theis modules/moduleStyles is repeated in all the undo-* actions. Find a way to share.
- 'modules' => array( 'ext.flow.undo' ),
- 'moduleStyles' => array(
+ 'modules' => [ 'ext.flow.undo' ],
+ 'moduleStyles' => [
'mediawiki.ui.button',
'mediawiki.ui.input',
'ext.flow.styles.base',
@@ -115,99 +122,101 @@ $wgFlowActions = array(
'ext.flow.board.topic.styles',
// Needed for pending texture while switching editors
'oojs-ui.styles.textures'
- ),
- ),
+ ],
+ ],
- 'create-topic-summary' => array(
+ 'create-topic-summary' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
PostSummary::MODERATED_NONE => '',
- PostSummary::MODERATED_LOCKED => array( 'flow-lock', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_HIDDEN => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_SUPPRESSED => array( 'flow-suppress' ),
- ),
- 'root-permissions' => array(
+ PostSummary::MODERATED_LOCKED => [ 'flow-lock', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_HIDDEN => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_SUPPRESSED => [ 'flow-suppress' ],
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
PostRevision::MODERATED_LOCKED => '',
- ),
- 'links' => array( 'topic', 'topic-history', 'watch-topic', 'unwatch-topic', 'summary-revision' ),
- 'actions' => array( 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'diff-post-summary', 'watch-topic', 'unwatch-topic', 'summary-revision' ],
+ 'actions' => [ 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-create-topic-summary',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-of-summary',
- ),
+ ],
'class' => 'flow-history-create-topic-summary',
- ),
+ ],
'editcount' => true,
- ),
+ ],
- 'edit-topic-summary' => array(
+ 'edit-topic-summary' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
PostSummary::MODERATED_NONE => '',
- PostSummary::MODERATED_LOCKED => array( 'flow-lock', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_HIDDEN => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_SUPPRESSED => array( 'flow-suppress' ),
- ),
- 'root-permissions' => array(
+ PostSummary::MODERATED_LOCKED => [ 'flow-lock', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_HIDDEN => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_SUPPRESSED => [ 'flow-suppress' ],
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
PostRevision::MODERATED_LOCKED => '',
- ),
- 'links' => array( 'topic', 'topic-history', 'diff-post-summary', 'watch-topic', 'unwatch-topic', 'summary-revision' ),
- 'actions' => array( 'edit-topic-summary', 'lock-topic', 'restore-topic', 'undo-edit-topic-summary' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'diff-post-summary', 'watch-topic', 'unwatch-topic', 'summary-revision' ],
+ 'actions' => [ 'edit-topic-summary', 'lock-topic', 'restore-topic', 'undo-edit-topic-summary' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-topic-summary',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-of-summary',
- ),
+ ],
'class' => 'flow-history-edit-topic-summary',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
+ 'modules' => [],
'editcount' => true,
- ),
+ ],
// @todo this is almost copy/paste from edit-topic-summary except the handler class. find a
// way to share
- 'undo-edit-topic-summary' => array(
+ 'undo-edit-topic-summary' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
PostSummary::MODERATED_NONE => '',
- PostSummary::MODERATED_LOCKED => array( 'flow-lock', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_HIDDEN => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
- PostSummary::MODERATED_SUPPRESSED => array( 'flow-suppress' ),
- ),
- 'root-permissions' => array(
+ PostSummary::MODERATED_LOCKED => [ 'flow-lock', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_HIDDEN => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
+ PostSummary::MODERATED_SUPPRESSED => [ 'flow-suppress' ],
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'topic', 'topic-history', 'diff-post-summary', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'edit-topic-summary', 'lock-topic', 'restore-topic', 'undo-edit-topic-summary' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'diff-post-summary', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'edit-topic-summary', 'lock-topic', 'restore-topic', 'undo-edit-topic-summary' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-topic-summary',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-of-summary',
- ),
+ ],
'class' => 'flow-history-edit-topic-summary',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
+ 'modules' => [],
'editcount' => true,
- 'modules' => array( 'ext.flow.undo' ),
- 'moduleStyles' => array(
+ 'modules' => [ 'ext.flow.undo' ],
+ 'moduleStyles' => [
'mediawiki.ui.button',
'mediawiki.ui.input',
'ext.flow.styles.base',
@@ -215,133 +224,141 @@ $wgFlowActions = array(
'ext.flow.board.topic.styles',
// Needed for pending texture while switching editors
'oojs-ui.styles.textures'
- ),
- ),
+ ],
+ ],
- 'edit-title' => array(
+ 'edit-title' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'topic', 'topic-history', 'diff-post', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'lock-topic', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'diff-post', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'lock-topic', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-title',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'workflow-url',
- 'wikitext',
- 'prev-wikitext',
- ),
+ 'plaintext',
+ 'prev-plaintext',
+ ],
'class' => 'flow-history-edit-title',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- 'watch' => array(
- 'immediate' => array( 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ),
- ),
+ 'modules' => [],
+ 'watch' => [
+ 'immediate' => [ 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ],
+ ],
'editcount' => true,
- ),
+ ],
- // Normal posts are the 'reply' type.
- 'new-topic' => array(
+ 'new-topic' => [
'performs-writes' => true,
'log_type' => false,
'rc_title' => 'owner',
'rc_insert' => true,
'exclude_from_contributions' => true,
+
+ // If you add exclude_from_history to new change types, you *must* update
+ // the *HistoryQuery's (to use doInternalQueries with a good overfetch factor).
+ // You should also adjust the memcached indices for best results.
'exclude_from_history' => true,
+
// exclude_from_recentchanges only refers to the actual Special:RecentChanges. It does not affect Special:Watchlist.
'exclude_from_recentchanges' => true,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'topic-history', 'topic', 'post', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic-history', 'topic', 'post', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-new-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'workflow-url',
'wikitext',
- ),
+ ],
'class' => 'flow-history-new-post',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- 'watch' => array(
- 'immediate' => array( 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ),
- ),
+ 'modules' => [],
+ 'watch' => [
+ 'immediate' => [ 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ],
+ ],
'editcount' => true,
- ),
+ ],
- 'edit-post' => array(
+ 'edit-post' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
// no permissions needed for own posts
- PostRevision::MODERATED_NONE => function( PostRevision $post, RevisionActionPermissions $permissions ) {
- return $post->isCreator( $permissions->getUser() ) ? '' : 'flow-edit-post';
- }
- ),
- 'root-permissions' => array(
+ PostRevision::MODERATED_NONE => function ( PostRevision $post, RevisionActionPermissions $permissions ) {
+ return $post->isCreator( $permissions->getUser() ) ? '' : 'flow-edit-post';
+ }
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'post-history', 'topic-history', 'topic', 'post', 'diff-post', 'post-revision' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post', 'undo-edit-post' ),
- 'history' => array(
+ ],
+ 'links' => [ 'post-history', 'topic-history', 'topic', 'post', 'diff-post', 'post-revision' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post', 'undo-edit-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-url',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-edit-post',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- 'watch' => array(
- 'immediate' => array( 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ),
- ),
+ 'modules' => [],
+ 'watch' => [
+ 'immediate' => [ 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ],
+ ],
'editcount' => true,
- ),
+ ],
// @todo this is almost (but not quite) copy/paste from 'edit-post'. find a way to share?
- 'undo-edit-post' => array(
+ 'undo-edit-post' => [
'performs-writes' => true,
'log_type' => false, // maybe?
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
// no permissions needed for own posts
- PostRevision::MODERATED_NONE => function( PostRevision $post, RevisionActionPermissions $permissions ) {
- return $post->isCreator( $permissions->getUser() ) ? '' : 'flow-edit-post';
- }
- ),
- 'root-permissions' => array(
+ PostRevision::MODERATED_NONE => function ( PostRevision $post, RevisionActionPermissions $permissions ) {
+ return $post->isCreator( $permissions->getUser() ) ? '' : 'flow-edit-post';
+ }
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'post-history', 'topic-history', 'topic', 'post', 'diff-post', 'post-revision' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post', 'undo-edit-post' ),
- 'history' => array(
+ ],
+ 'links' => [ 'post-history', 'topic-history', 'topic', 'post', 'diff-post', 'post-revision' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post', 'undo-edit-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-edit-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-url',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-edit-post',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- 'watch' => array(
- 'immediate' => array( 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ),
- ),
+ 'modules' => [],
+ 'watch' => [
+ 'immediate' => [ 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ],
+ ],
'editcount' => true,
- 'modules' => array( 'ext.flow.undo' ),
- 'moduleStyles' => array(
+ 'modules' => [ 'ext.flow.undo' ],
+ 'moduleStyles' => [
'mediawiki.ui.button',
'mediawiki.ui.input',
'ext.flow.styles.base',
@@ -349,193 +366,194 @@ $wgFlowActions = array(
'ext.flow.board.topic.styles',
// Needed for pending texture while switching editors
'oojs-ui.styles.textures'
- ),
- ),
+ ],
+ ],
- 'hide-post' => array(
+ 'hide-post' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
// Permissions required to perform action. The key is the moderation state
// of the post to perform the action against. The value is a string or array
// of user rights that can allow this action.
- PostRevision::MODERATED_NONE => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- ),
- 'root-permissions' => array(
+ PostRevision::MODERATED_NONE => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ ],
+ 'root-permissions' => [
// Can only hide within an unmoderated or hidden topic. This doesn't check for a specific
// permissions because thats already done above in 'permissions', this just ensures the
// topic is in an appropriate state.
PostRevision::MODERATED_NONE => '',
PostRevision::MODERATED_HIDDEN => '',
- ),
- 'links' => array( 'topic', 'post', 'post-history', 'topic-history', 'post-revision' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'post', 'post-history', 'topic-history', 'post-revision' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-hid-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'post-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-hide-post',
- ),
- ),
+ ],
+ ],
- 'hide-topic' => array(
+ 'hide-topic' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
- PostRevision::MODERATED_NONE => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- ),
- 'links' => array( 'topic', 'post', 'topic-history', 'post-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'restore-topic', 'hide-topic', 'delete-topic', 'suppress-topic' ),
- 'history' => array(
+ 'permissions' => [
+ PostRevision::MODERATED_NONE => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ ],
+ 'links' => [ 'topic', 'post', 'topic-history', 'post-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'restore-topic', 'hide-topic', 'delete-topic', 'suppress-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-hid-topic',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'workflow-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-hide-topic',
- ),
- ),
+ ],
+ ],
- 'delete-post' => array(
+ 'delete-post' => [
'performs-writes' => true,
'log_type' => 'delete',
'rc_insert' => true,
- 'permissions' => array(
- PostRevision::MODERATED_NONE => array( 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_HIDDEN => array( 'flow-delete', 'flow-suppress' ),
- ),
- 'links' => array( 'topic', 'post', 'post-history', 'topic-history', 'post-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ),
- 'history' => array(
+ 'permissions' => [
+ PostRevision::MODERATED_NONE => [ 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_HIDDEN => [ 'flow-delete', 'flow-suppress' ],
+ ],
+ 'links' => [ 'topic', 'post', 'post-history', 'topic-history', 'post-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-deleted-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'post-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-delete-post',
- ),
- ),
+ ],
+ ],
- 'delete-topic' => array(
+ 'delete-topic' => [
'performs-writes' => true,
'log_type' => 'delete',
'rc_insert' => true,
- 'permissions' => array(
- PostRevision::MODERATED_NONE => array( 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_HIDDEN => array( 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_LOCKED => array( 'flow-delete', 'flow-suppress' ),
- ),
- 'links' => array( 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ 'permissions' => [
+ PostRevision::MODERATED_NONE => [ 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_HIDDEN => [ 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_LOCKED => [ 'flow-delete', 'flow-suppress' ],
+ ],
+ 'links' => [ 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-deleted-topic',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'workflow-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-delete-topic',
- ),
- ),
+ ],
+ ],
- 'suppress-post' => array(
+ 'suppress-post' => [
'performs-writes' => true,
'log_type' => 'suppress',
'rc_insert' => false,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => 'flow-suppress',
PostRevision::MODERATED_HIDDEN => 'flow-suppress',
PostRevision::MODERATED_DELETED => 'flow-suppress',
- ),
- 'links' => array( 'topic', 'post', 'topic-history', 'post-revision' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'post', 'topic-history', 'post-revision' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-suppressed-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'post-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-suppress-post',
- ),
- ),
+ ],
+ ],
- 'suppress-topic' => array(
+ 'suppress-topic' => [
'performs-writes' => true,
'log_type' => 'suppress',
'rc_insert' => false,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => 'flow-suppress',
PostRevision::MODERATED_HIDDEN => 'flow-suppress',
PostRevision::MODERATED_DELETED => 'flow-suppress',
PostRevision::MODERATED_LOCKED => 'flow-suppress',
- ),
- 'links' => array( 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-suppressed-topic',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'workflow-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-suppress-topic',
- ),
- ),
+ ],
+ ],
- 'lock-topic' => array(
+ 'lock-topic' => [
'performs-writes' => true,
'log_type' => 'lock',
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
// Only non-moderated topic can be locked
- PostRevision::MODERATED_NONE => array( 'flow-lock', 'flow-delete', 'flow-suppress' ),
- ),
- 'links' => array( 'topic', 'topic-history', 'watch-topic', 'unwatch-topic', 'topic-revision' ),
- 'actions' => array( 'edit-topic-summary', 'restore-topic' ),
- 'history' => array(
+ PostRevision::MODERATED_NONE => [ 'flow-lock', 'flow-delete', 'flow-suppress' ],
+ ],
+ 'links' => [ 'topic', 'topic-history', 'watch-topic', 'unwatch-topic', 'topic-revision' ],
+ 'actions' => [ 'edit-topic-summary', 'restore-topic', 'delete-topic', 'suppress-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-locked-topic',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'workflow-url',
'moderated-reason',
- 'topic-of-post',
- ),
+ 'topic-of-post-text-from-html',
+ ],
'class' => 'flow-history-locked-topic',
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ 'modules' => [],
+ ],
- 'restore-post' => array(
+ 'restore-post' => [
'performs-writes' => true,
- 'log_type' => function( PostRevision $revision, ModerationLogger $logger ) {
+ 'log_type' => function ( PostRevision $revision, ModerationLogger $logger ) {
$post = $revision->getCollection();
$previousRevision = $post->getPrevRevision( $revision );
if ( $previousRevision ) {
@@ -548,7 +566,7 @@ $wgFlowActions = array(
return '';
},
- 'rc_insert' => function( PostRevision $revision, RecentChangesListener $recentChanges ) {
+ 'rc_insert' => function ( PostRevision $revision, RecentChangesListener $recentChanges ) {
$post = $revision->getCollection();
$previousRevision = $post->getPrevRevision( $revision );
if ( $previousRevision ) {
@@ -560,35 +578,36 @@ $wgFlowActions = array(
return true;
},
- 'permissions' => array(
- PostRevision::MODERATED_HIDDEN => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
+ 'permissions' => [
+ PostRevision::MODERATED_HIDDEN => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'links' => array( 'topic', 'post', 'post-history', 'post-revision' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'post', 'post-history', 'post-revision' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'restore-post', 'hide-post', 'delete-post', 'suppress-post' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-restored-post',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'post-url',
'moderated-reason',
- 'topic-of-post',
- ),
- 'class' => function( PostRevision $revision ) {
+ 'topic-of-post-text-from-html',
+ ],
+ 'class' => function ( PostRevision $revision ) {
$previous = $revision->getCollection()->getPrevRevision( $revision );
$state = $previous->getModerationState();
return "flow-history-un$state-post";
}
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ 'modules' => [],
+ ],
- 'restore-topic' => array(
+ 'restore-topic' => [
'performs-writes' => true,
- 'log_type' => function( PostRevision $revision, ModerationLogger $logger ) {
+ 'log_type' => function ( PostRevision $revision, ModerationLogger $logger ) {
$post = $revision->getCollection();
$previousRevision = $post->getPrevRevision( $revision );
if ( $previousRevision ) {
@@ -601,112 +620,114 @@ $wgFlowActions = array(
return '';
},
- 'rc_insert' => function( PostRevision $revision, RecentChangesListener $recentChanges ) {
- $post = $revision->getCollection();
- $previousRevision = $post->getPrevRevision( $revision );
- if ( $previousRevision ) {
- // * if topic was hidden/deleted, restore can go to RC
- // * if topic was suppressed, restore can not go to RC
- global $wgFlowActions;
- return $wgFlowActions[$previousRevision->getModerationState() . '-topic']['rc_insert'];
- }
+ 'rc_insert' => function ( PostRevision $revision, RecentChangesListener $recentChanges ) {
+ $post = $revision->getCollection();
+ $previousRevision = $post->getPrevRevision( $revision );
+ if ( $previousRevision ) {
+ // * if topic was hidden/deleted, restore can go to RC
+ // * if topic was suppressed, restore can not go to RC
+ global $wgFlowActions;
+ return $wgFlowActions[$previousRevision->getModerationState() . '-topic']['rc_insert'];
+ }
- return true;
- },
- 'permissions' => array(
- PostRevision::MODERATED_LOCKED => array( 'flow-lock', 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_HIDDEN => array( 'flow-hide', 'flow-delete', 'flow-suppress' ),
- PostRevision::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
+ return true;
+ },
+ 'permissions' => [
+ PostRevision::MODERATED_LOCKED => [ 'flow-lock', 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_HIDDEN => [ 'flow-hide', 'flow-delete', 'flow-suppress' ],
+ PostRevision::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'links' => array( 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic', 'topic-history', 'topic-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-title', 'hide-topic', 'delete-topic', 'suppress-topic', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-restored-topic',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'creator-text',
'workflow-url',
'moderated-reason',
- 'topic-of-post',
- ),
- 'class' => function( PostRevision $revision ) {
+ 'topic-of-post-text-from-html',
+ ],
+ 'class' => function ( PostRevision $revision ) {
$previous = $revision->getCollection()->getPrevRevision( $revision );
$state = $previous->getModerationState();
return "flow-history-un$state-topic";
}
- ),
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ 'modules' => [],
+ ],
- 'view' => array(
+ 'view' => [
'performs-writes' => false,
'log_type' => false, // don't log views
'rc_insert' => false, // won't even be called, actually; only for writes
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
// Everyone has permission to see this, but hidden comments are only visible (collapsed) on permalinks directly to them.
PostRevision::MODERATED_HIDDEN => '',
PostRevision::MODERATED_LOCKED => '',
- PostRevision::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
+ PostRevision::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'core-delete-permissions' => array( 'deletedtext' ),
- 'links' => array(), // @todo
- 'actions' => array(), // view is not a recorded change type, no actions will be requested
- 'history' => array(), // views don't generate history
+ ],
+ 'core-delete-permissions' => [ 'deletedtext' ],
+ 'links' => [], // @todo
+ 'actions' => [], // view is not a recorded change type, no actions will be requested
+ 'history' => [], // views don't generate history
'handler-class' => 'Flow\Actions\ViewAction',
- ),
+ ],
- 'reply' => array(
+ 'reply' => [
'performs-writes' => true,
'log_type' => false,
'rc_insert' => true,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'root-permissions' => array(
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
- ),
- 'links' => array( 'topic-history', 'topic', 'post', 'post-revision', 'watch-topic', 'unwatch-topic' ),
- 'actions' => array( 'reply', 'thank', 'edit-post', 'hide-post', 'delete-post', 'suppress-post', 'edit-topic-summary', 'lock-topic', 'restore-topic' ),
- 'history' => array(
+ ],
+ 'links' => [ 'topic-history', 'topic', 'post', 'post-revision', 'watch-topic', 'unwatch-topic' ],
+ 'actions' => [ 'reply', 'thank', 'edit-post', 'hide-post', 'delete-post', 'suppress-post', 'edit-topic-summary', 'lock-topic', 'restore-topic' ],
+ 'history' => [
'i18n-message' => 'flow-rev-message-reply',
- 'i18n-params' => array(
+ 'i18n-params' => [
'user-links',
'user-text',
'post-url',
- 'topic-of-post',
+ 'topic-of-post-text-from-html',
'summary',
- ),
+ ],
'class' => 'flow-history-reply',
- 'bundle' => array(
+ 'bundle' => [
'i18n-message' => 'flow-rev-message-reply-bundle',
- 'i18n-params' => array(
+ 'i18n-params' => [
'bundle-count'
- ),
+ ],
'class' => 'flow-history-bundle',
- ),
- ),
+ ],
+ ],
'handler-class' => 'Flow\Actions\FlowAction',
- 'watch' => array(
- 'immediate' => array( 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ),
- ),
+ 'modules' => [],
+ 'watch' => [
+ 'immediate' => [ 'Flow\\Data\\Listener\\ImmediateWatchTopicListener', 'getCurrentUser' ],
+ ],
'editcount' => true,
- ),
+ ],
- 'history' => array(
+ 'history' => [
'performs-writes' => false,
'log_type' => false,
'rc_insert' => false, // won't even be called, actually; only for writes
- 'permissions' => array(
- PostRevision::MODERATED_NONE => function( AbstractRevision $revision, RevisionActionPermissions $permissions ) {
+ 'permissions' => [
+ PostRevision::MODERATED_NONE => function ( AbstractRevision $revision, RevisionActionPermissions $permissions ) {
static $previousCollectionId;
/*
* To check permissions, both the current revision (revision-
- * specific moderation state)& the last revision (global
+ * specific moderation state) & the last revision (global
* collection moderation state) will always be checked.
* This one has special checks to make sure "restore" actions
* are hidden when the user has no permissions to see the
@@ -759,87 +780,126 @@ $wgFlowActions = array(
PostRevision::MODERATED_LOCKED => '',
PostRevision::MODERATED_DELETED => '',
PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'root-permissions' => array(
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
- PostRevision::MODERATED_HIDDEN => '',
PostRevision::MODERATED_LOCKED => '',
- PostRevision::MODERATED_DELETED => '',
- PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'core-delete-permissions' => array( 'deletedhistory' ),
- 'history' => array(), // views don't generate history
+ PostRevision::MODERATED_HIDDEN => '',
+ // No data should be shown for other moderation levels: if a topic
+ // has been deleted, we don't want a bunch of irrelevant
+ // "new reply", "edit", ... spam in there.
+ // All we want is the "topic has been deleted", which will still be
+ // displayed (root-permissions won't be tested for the topic, since
+ // it is the root)
+ ],
+ 'core-delete-permissions' => [ 'deletedhistory' ],
+ 'history' => [], // views don't generate history
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ ],
// Pseudo-action to determine when to show thank links,
// currently no limitation. if you can see revision you
// can thank.
- 'thank' => array(
+ 'thank' => [
'performs-writes' => false,
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
PostRevision::MODERATED_HIDDEN => '',
PostRevision::MODERATED_LOCKED => '',
PostRevision::MODERATED_DELETED => '',
PostRevision::MODERATED_SUPPRESSED => '',
- ),
- ),
+ ],
+ ],
- 'view-topic-summary' => array(
+ 'view-topic-summary' => [
'performs-writes' => false,
'log_type' => false, // don't log views
'rc_insert' => false, // won't even be called, actually; only for writes
- 'permissions' => array(
+ 'permissions' => [
PostRevision::MODERATED_NONE => '',
// Everyone has permission to see this, but hidden comments are only visible (collapsed) on permalinks directly to them.
PostRevision::MODERATED_HIDDEN => '',
PostRevision::MODERATED_LOCKED => '',
- PostRevision::MODERATED_DELETED => array( 'flow-delete', 'flow-suppress' ),
+ PostRevision::MODERATED_DELETED => [ 'flow-delete', 'flow-suppress' ],
PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
- ),
- 'root-permissions' => array(
+ ],
+ 'root-permissions' => [
PostRevision::MODERATED_NONE => '',
+ PostRevision::MODERATED_HIDDEN => '',
PostRevision::MODERATED_LOCKED => '',
- ),
- 'core-delete-permissions' => array( 'deletedtext' ),
- 'links' => array(), // @todo
- 'actions' => array(), // view is not a recorded change type, no actions will be requested
- 'history' => array(), // views don't generate history
+ ],
+ 'core-delete-permissions' => [ 'deletedtext' ],
+ 'links' => [], // @todo
+ 'actions' => [], // view is not a recorded change type, no actions will be requested
+ 'history' => [], // views don't generate history
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ 'modules' => [],
+ ],
+
+ // This is only used when we specifically want to see the topic title. If we're
+ // cascading from a post (to view a post we need to be able to view the topic),
+ // we'll use 'view' for both the post and topic root. Unprivileged users shouldn't
+ // be able to view a post in a deleted topic, but should be able to view the topic
+ // title.
+ 'view-topic-title' => [
+ 'performs-writes' => false,
+ 'log_type' => false, // don't log views
+ 'rc_insert' => false, // won't even be called, actually; only for writes
+ 'permissions' => [
+ // Everyone can see topic titles on existent boards, unless the
+ // version you're viewing is suppressed, or the most recent version
+ // is
+ PostRevision::MODERATED_NONE => '',
+ PostRevision::MODERATED_HIDDEN => '',
+ PostRevision::MODERATED_LOCKED => '',
+ PostRevision::MODERATED_DELETED => '',
+ PostRevision::MODERATED_SUPPRESSED => 'flow-suppress',
+ ],
+ 'core-delete-permissions' => [ 'deletedtext' ],
+ 'links' => [], // @todo
+ 'actions' => [], // view is not a recorded change type, no actions will be requested
+ 'history' => [], // views don't generate history
+ 'modules' => [],
+ ],
// Actions not tied to a particular revision change_type
// or just move these to a different file
// @todo: we should probably at least add 'permissions' in these below
- 'compare-header-revisions' => array(
+ 'compare-header-revisions' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'view-header' => array(
+ 'modules' => [],
+ ],
+ 'view-header' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'compare-post-revisions' => array(
+ 'modules' => [],
+ ],
+ 'compare-post-revisions' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
+ 'modules' => [],
+ ],
// @todo - This is a very bad action name, consolidate with view-post action
- 'single-view' => array(
+ 'single-view' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'compare-postsummary-revisions' => array(
+ 'modules' => [],
+ ],
+ 'compare-postsummary-revisions' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'moderate-topic' => array(
+ 'modules' => [],
+ ],
+ 'moderate-topic' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'moderate-post' => array(
+ 'modules' => [],
+ ],
+ 'moderate-post' => [
'handler-class' => 'Flow\Actions\FlowAction',
- ),
- 'purge' => array(
+ 'modules' => [],
+ ],
+ 'purge' => [
'handler-class' => 'Flow\Actions\PurgeAction',
- ),
+ 'modules' => [],
+ ],
- // log & all other formatters have same config as history
- 'log' => 'history',
+ // Other formatters have the same config as history
'recentchanges' => 'history',
'contributions' => 'history',
'checkuser' => 'history',
@@ -891,4 +951,4 @@ $wgFlowActions = array(
// BC for lock-topic, which used to be called differently
'close-topic' => 'lock-topic',
'close-open-topic' => 'lock-topic',
-);
+];
diff --git a/Flow/Gemfile b/Flow/Gemfile
index 861b8f59..b5a34973 100644
--- a/Flow/Gemfile
+++ b/Flow/Gemfile
@@ -1,8 +1,6 @@
-#ruby=ruby-2.1.1
-#ruby-gemset=Flow
-
source "https://rubygems.org"
-gem "csscss"
-gem 'mediawiki_selenium', '~> 1.4.0'
-gem "rubocop", require: false
+gem "csscss", "~> 1.3.3"
+gem 'mediawiki_selenium', '~> 1.8'
+gem 'rake', '~> 11.1', '>= 11.1.1'
+gem "rubocop", "~> 0.32.1", require: false
diff --git a/Flow/Gemfile.lock b/Flow/Gemfile.lock
index a69714ac..5e814ab8 100644
--- a/Flow/Gemfile.lock
+++ b/Flow/Gemfile.lock
@@ -1,12 +1,12 @@
GEM
remote: https://rubygems.org/
specs:
- ast (2.0.0)
+ ast (2.1.0)
astrolabe (1.3.1)
parser (~> 2.2)
blankslate (3.1.3)
- builder (3.2.2)
- childprocess (0.5.6)
+ builder (3.2.3)
+ childprocess (0.6.2)
ffi (~> 1.0, >= 1.0.11)
colorize (0.7.7)
csscss (1.3.3)
@@ -18,61 +18,70 @@ GEM
gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
multi_test (>= 0.1.2)
- data_magic (0.21)
+ data_magic (1.0)
faker (>= 1.1.2)
- yml_reader (>= 0.4)
- diff-lcs (1.2.5)
- domain_name (0.5.24)
+ 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.10)
+ 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.3)
- mediawiki_api (0.4.1)
+ 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 (1.4.0)
+ faraday_middleware (~> 0.10, >= 0.10.0)
+ mediawiki_selenium (1.8.0)
cucumber (~> 1.3, >= 1.3.20)
- headless (~> 1.0, >= 1.0.1)
- json (~> 1.8, >= 1.8.1)
- mediawiki_api (~> 0.4, >= 0.4.1)
- page-object (~> 1.0)
+ 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)
thor (~> 0.19, >= 0.19.1)
- mime-types (2.6.1)
- multi_json (1.11.2)
+ mime-types (2.99.3)
+ multi_json (1.12.1)
multi_test (0.1.2)
multipart-post (2.0.0)
- netrc (0.10.3)
- page-object (1.1.0)
+ 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)
+ 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.7.0)
+ parslet (1.7.1)
blankslate (>= 2.0, <= 4.0)
powerpack (0.1.1)
rainbow (2.0.0)
+ 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.32.1)
@@ -82,26 +91,29 @@ GEM
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.7.5)
- rubyzip (1.1.7)
- selenium-webdriver (2.46.2)
+ 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)
- thor (0.19.1)
+ syntax (1.2.1)
+ thor (0.19.4)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.1)
- watir-webdriver (0.8.0)
- selenium-webdriver (>= 2.46.2)
- websocket (1.2.2)
- 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
- csscss
- mediawiki_selenium (~> 1.4.0)
- rubocop
+ csscss (~> 1.3.3)
+ mediawiki_selenium (~> 1.8)
+ rake (~> 11.1, >= 11.1.1)
+ rubocop (~> 0.32.1)
+
+BUNDLED WITH
+ 1.14.5
diff --git a/Flow/Gruntfile.js b/Flow/Gruntfile.js
index 62d6a540..b76e0392 100644
--- a/Flow/Gruntfile.js
+++ b/Flow/Gruntfile.js
@@ -4,14 +4,15 @@
* @package Flow
*/
-/*jshint node:true */
+/* eslint-env node: */
module.exports = function ( grunt ) {
+ var conf = grunt.file.readJSON( 'extension.json' );
+
grunt.loadNpmTasks( 'grunt-banana-checker' );
- grunt.loadNpmTasks( 'grunt-contrib-csslint' );
- grunt.loadNpmTasks( 'grunt-contrib-jshint' );
grunt.loadNpmTasks( 'grunt-contrib-watch' );
- grunt.loadNpmTasks( 'grunt-jscs' );
+ grunt.loadNpmTasks( 'grunt-eslint' );
grunt.loadNpmTasks( 'grunt-jsonlint' );
+ grunt.loadNpmTasks( 'grunt-stylelint' );
grunt.loadNpmTasks( 'grunt-tyops' );
grunt.initConfig( {
@@ -21,45 +22,31 @@ module.exports = function ( grunt ) {
},
src: [
'**/*',
- '!{node_modules,vendor}/**',
+ '!{node_modules,vendor,docs}/**',
'!build/typos.json'
]
},
- jshint: {
- options: {
- jshintrc: true
- },
+ eslint: {
all: [
- '*.js',
- 'modules/**/*.js',
- 'tests/qunit/**/*.js'
+ '**/*.js',
+ '!{node_modules,vendor,docs}/**/*.js'
]
},
- jscs: {
- fix: {
- options: {
- fix: true
- },
- src: '<%= jshint.all %>'
- },
- main: {
- src: '<%= jshint.all %>'
- }
- },
- csslint: {
+ 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 %>'
+ '.{stylelintlintrc,eslintrc.json}',
+ '<%= eslint.all %>',
+ '<%= stylelintlint.all %>'
],
tasks: 'test'
},
@@ -71,8 +58,7 @@ module.exports = function ( grunt ) {
}
} );
- grunt.registerTask( 'lint', [ 'tyops', 'jshint', 'jscs:main', 'csslint', 'jsonlint', 'banana' ] );
- grunt.registerTask( 'fix', 'jscs:fix' );
+ grunt.registerTask( 'lint', [ 'tyops', 'eslint', 'stylelint', 'jsonlint', 'banana' ] );
grunt.registerTask( 'test', 'lint' );
grunt.registerTask( 'default', 'test' );
};
diff --git a/Flow/Hooks.php b/Flow/Hooks.php
index 12371da9..12b55970 100644
--- a/Flow/Hooks.php
+++ b/Flow/Hooks.php
@@ -2,16 +2,18 @@
use Flow\Collection\PostCollection;
use Flow\Container;
+use Flow\Conversion\Utils;
use Flow\Exception\FlowException;
use Flow\Exception\PermissionException;
+use Flow\Data\Listener\RecentChangesListener;
use Flow\Formatter\CheckUserQuery;
use Flow\Import\OptInUpdate;
use Flow\Model\UUID;
use Flow\OccupationController;
use Flow\SpamFilter\AbuseFilter;
use Flow\TalkpageManager;
+use Flow\WorkflowLoader;
use Flow\WorkflowLoaderFactory;
-use Flow\Data\Listener\RecentChangesListener;
class FlowHooks {
/**
@@ -24,37 +26,65 @@ class FlowHooks {
*/
protected static $abuseFilter;
+ public static function registerExtension() {
+ global $wgFlowActions, $wgLogActionsHandlers, $wgActions;
+
+ require_once __DIR__ . '/defines.php';
+
+ // Action details config file
+ require __DIR__ . '/FlowActions.php';
+
+ // Register URL actions and activity log formatter hooks
+ foreach ( $wgFlowActions as $action => $options ) {
+ if ( is_array( $options ) && isset( $options['handler-class'] ) ) {
+ $wgActions[$action] = true;
+ }
+
+ if ( !is_string( $options ) && isset( $options['log_type'] ) ) {
+ $log = $options['log_type'];
+
+ // Some actions are more complex closures - they are added manually in extension.json
+ if ( is_string( $log ) ) {
+ $wgLogActionsHandlers["$log/flow-$action"] = 'Flow\Log\ActionFormatter';
+ }
+ }
+ }
+ }
+
public static function onResourceLoaderRegisterModules( ResourceLoader &$resourceLoader ) {
- global $wgFlowEventLogging, $wgResourceModules;
+ global $wgFlowEventLogging;
// Only if EventLogging in Flow is enabled & EventLogging exists
if ( $wgFlowEventLogging && class_exists( 'ResourceLoaderSchemaModule' ) ) {
- $resourceLoader->register( 'schema.FlowReplies', array(
+ $resourceLoader->register( 'schema.FlowReplies', [
'class' => 'ResourceLoaderSchemaModule',
'schema' => 'FlowReplies',
// See https://meta.wikimedia.org/wiki/Schema:FlowReplies, below title
'revision' => 10561344,
- ) );
+ ] );
+ }
- // Add as dependency to Flow JS
- $wgResourceModules['ext.flow']['dependencies'][] = 'schema.FlowReplies';
+ // Register a dummy supportCheck module in case VE isn't loaded, as we attempt
+ // to load this module unconditionally on load.
+ if ( !$resourceLoader->isModuleRegistered( 'ext.visualEditor.supportCheck' ) ) {
+ $resourceLoader->register( 'ext.visualEditor.supportCheck', [] );
}
if ( class_exists( 'GuidedTourHooks' ) ) {
- $resourceLoader->register( 'ext.guidedTour.tour.flowOptIn', array(
+ $resourceLoader->register( 'ext.guidedTour.tour.flowOptIn', [
'localBasePath' => __DIR__ . '/modules',
'remoteExtPath' => 'Flow/modules',
'scripts' => 'tours/flowOptIn.js',
'styles' => 'tours/flowOptIn.less',
- 'messages' => array(
+ 'messages' => [
"flow-guidedtour-optin-welcome",
"flow-guidedtour-optin-welcome-description",
"flow-guidedtour-optin-find-old-conversations",
"flow-guidedtour-optin-find-old-conversations-description",
"flow-guidedtour-optin-feedback",
"flow-guidedtour-optin-feedback-description"
- )
- ) );
+ ]
+ ] );
}
return true;
@@ -78,7 +108,7 @@ class FlowHooks {
GuidedTourLauncher::launchTourByCookie( 'flowOptIn', 'newTopic' );
// Destroy Flow cookie
- $out->getRequest()->response()->setcookie( 'Flow_optIn_guidedTour', '', time() - 3600);
+ $out->getRequest()->response()->setcookie( 'Flow_optIn_guidedTour', '', time() - 3600 );
}
}
@@ -103,18 +133,17 @@ class FlowHooks {
*/
public static function getAbuseFilter() {
if ( self::$abuseFilter === null ) {
- global $wgUser,
- $wgFlowAbuseFilterGroup,
+ global $wgFlowAbuseFilterGroup,
$wgFlowAbuseFilterEmergencyDisableThreshold,
$wgFlowAbuseFilterEmergencyDisableCount,
$wgFlowAbuseFilterEmergencyDisableAge;
- self::$abuseFilter = new AbuseFilter( $wgUser, $wgFlowAbuseFilterGroup );
- self::$abuseFilter->setup( array(
+ self::$abuseFilter = new AbuseFilter( $wgFlowAbuseFilterGroup );
+ self::$abuseFilter->setup( [
'threshold' => $wgFlowAbuseFilterEmergencyDisableThreshold,
'count' => $wgFlowAbuseFilterEmergencyDisableCount,
'age' => $wgFlowAbuseFilterEmergencyDisableAge,
- ) );
+ ] );
}
return self::$abuseFilter;
}
@@ -135,7 +164,7 @@ class FlowHooks {
self::getAbuseFilter();
}
- if ( $wgFlowContentFormat === 'html' && !Flow\Parsoid\Utils::isParsoidConfigured() ) {
+ if ( $wgFlowContentFormat === 'html' && !Utils::isParsoidConfigured() ) {
wfDebugLog( 'Flow', __METHOD__ . ': Warning: $wgFlowContentFormat was set to \'html\', but you do not have Parsoid enabled. Changing $wgFlowContentFormat to \'wikitext\'' );
$wgFlowContentFormat = 'wikitext';
}
@@ -145,26 +174,24 @@ class FlowHooks {
require_once __DIR__ . '/vendor/autoload.php';
}
- if ( class_exists( 'MediaWiki\Extensions\OAuth\MWOAuthUtils' ) ) {
- global $wgMWOAuthGrantPermissions;
+ global $wgGrantPermissions;
- // This is semantically equivalent to editing a talk page and
- // blanking an offending post or topic.
- $wgMWOAuthGrantPermissions['editpage']['flow-hide'] = true;
+ // This is semantically equivalent to editing a talk page and
+ // blanking an offending post or topic.
+ $wgGrantPermissions['editpage']['flow-hide'] = true;
- // We might want to make a separate grant for this, so it can be
- // given out without giving out core 'protect'.
- $wgMWOAuthGrantPermissions['protect']['flow-lock'] = true;
+ // We might want to make a separate grant for this, so it can be
+ // given out without giving out core 'protect'.
+ $wgGrantPermissions['protect']['flow-lock'] = true;
- $wgMWOAuthGrantPermissions['delete']['flow-delete'] = true;
- $wgMWOAuthGrantPermissions['delete']['flow-suppress'] = true;
- $wgMWOAuthGrantPermissions['editpage']['flow-edit-post'] = true;
+ $wgGrantPermissions['delete']['flow-delete'] = true;
+ $wgGrantPermissions['delete']['flow-suppress'] = true;
+ $wgGrantPermissions['editpage']['flow-edit-post'] = true;
- // Creating a board somewhere it normally can't be created is sort
- // of like creating a page that can't normally be edited. But
- // maybe make a grant.
- $wgMWOAuthGrantPermissions['editprotected']['flow-create-board'] = true;
- }
+ // Creating a board somewhere it normally can't be created is sort
+ // of like creating a page that can't normally be edited. But
+ // maybe make a grant.
+ $wgGrantPermissions['editprotected']['flow-create-board'] = true;
}
/**
@@ -179,7 +206,7 @@ class FlowHooks {
/**
* Hook: LoadExtensionSchemaUpdates
*
- * @param $updater DatabaseUpdater object
+ * @param DatabaseUpdater $updater DatabaseUpdater object
* @return bool true in all cases
*/
public static function getSchemaUpdates( DatabaseUpdater $updater ) {
@@ -196,9 +223,6 @@ class FlowHooks {
$updater->addExtensionField( 'flow_workflow', 'workflow_type', "$dir/db_patches/patch-add_workflow_type.sqlite" );
$updater->modifyExtensionField( 'flow_workflow', 'workflow_user_id', "$dir/db_patches/patch-default_null_workflow_user.sqlite.sql" );
} else {
- // sqlite doesn't support alter table change, it also considers all types the same so
- // this patch doesn't matter to it.
- $updater->modifyExtensionField( 'flow_subscription', 'subscription_user_id', "$dir/db_patches/patch-subscription_user_id.sql" );
// renames columns, alternate patch is above for sqlite
$updater->modifyExtensionField( 'flow_summary_revision', 'summary_workflow_id', "$dir/db_patches/patch-summary2header.sql" );
// rename rev_change_type -> rev_comment, alternate patch is above for sqlite
@@ -231,6 +255,12 @@ class FlowHooks {
$updater->dropExtensionIndex( 'flow_ext_ref', 'flow_ext_ref_pk', "$dir/db_patches/patch-remove_unique_ref_indices.sql" );
$updater->addExtensionIndex( 'flow_workflow', 'flow_workflow_update_timestamp', "$dir/db_patches/patch-flow_workflow_update_timestamp_idx.sql" );
$updater->addExtensionField( 'flow_wiki_ref', 'ref_src_wiki', "$dir/db_patches/patch-reference_wiki.sql" );
+ $updater->addExtensionField( 'flow_wiki_ref', 'ref_id', "$dir/db_patches/patch-ref_id-phase1.sql" );
+ $updater->dropExtensionIndex( 'flow_ext_ref', 'flow_ext_ref_idx_v2', "$dir/db_patches/patch-dropindex-flow_ext_ref_idx_v2.sql" );
+ $updater->modifyExtensionField( 'flow_ext_ref', 'ref_target', "$dir/db_patches/patch-ref_target_not_null.sql" );
+ $updater->addExtensionIndex( 'flow_ext_ref', 'flow_ext_ref_idx_v3', "$dir/db_patches/patch-addindex_flow_ext_ref_idx_v3.sql" );
+ $updater->dropExtensionIndex( 'flow_topic_list', 'flow_topic_list_pk', "$dir/db_patches/patch-primary-keys.sql" );
+ $updater->dropExtensionTable( 'flow_subscription', "$dir/db_patches/patch-drop-flow_subscription.sql" );
require_once __DIR__.'/maintenance/FlowUpdateRecentChanges.php';
$updater->addPostDatabaseUpdateMaintenance( 'FlowUpdateRecentChanges' );
@@ -273,24 +303,24 @@ class FlowHooks {
require_once __DIR__.'/maintenance/FlowUpdateBetaFeaturePreference.php';
$updater->addPostDatabaseUpdateMaintenance( 'FlowUpdateBetaFeaturePreference' );
- return true;
- }
+ require_once __DIR__.'/maintenance/FlowPopulateRefId.php';
+ $updater->addPostDatabaseUpdateMaintenance( 'FlowPopulateRefId' );
- /**
- * Hook: UnitTestsList
- * @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 ) {
- $it = new RecursiveDirectoryIterator( __DIR__ . '/tests/phpunit' );
- $it = new RecursiveIteratorIterator( $it );
- foreach ( $it as $path => $file ) {
- if ( substr( $path, -8 ) === 'Test.php' ) {
- $files[] = $path;
+ require_once __DIR__.'/maintenance/FlowFixInconsistentBoards.php';
+ $updater->addPostDatabaseUpdateMaintenance( 'FlowFixInconsistentBoards' );
+
+ /*
+ * Add primary key, but only after we've made sure the newly added
+ * column has been populated (otherwise they'd all be null values)
+ */
+ if ( $updater->updateRowExists( 'FlowPopulateRefId' ) ) {
+ if ( $updater->getDB()->getType() === 'sqlite' ) {
+ $updater->addExtensionIndex( 'flow_wiki_ref', 'PRIMARY', "$dir/db_patches/patch-ref_id-phase2.sqlite.sql" );
+ } else {
+ $updater->addExtensionIndex( 'flow_wiki_ref', 'PRIMARY', "$dir/db_patches/patch-ref_id-phase2.sql" );
}
}
+
return true;
}
@@ -298,7 +328,7 @@ class FlowHooks {
* Loads RecentChanges list metadata into a temporary cache for later use.
*
* @param ChangesList $changesList
- * @param array $rows
+ * @param array $rows
*/
public static function onChangesListInitRows( ChangesList $changesList, $rows ) {
if ( !( $changesList instanceof OldChangesList || $changesList instanceof EnhancedChangesList ) ) {
@@ -322,12 +352,12 @@ class FlowHooks {
/**
* Updates the given Flow topic line in an enhanced changes list (grouped RecentChanges).
*
- * @param ChangesList $changesList
- * @param string $articlelink
- * @param string $s
- * @param RecentChange $rc
- * @param bool $unpatrolled
- * @param bool $isWatchlist
+ * @param ChangesList &$changesList
+ * @param string &$articlelink
+ * @param string &$s
+ * @param RecentChange &$rc
+ * @param bool $unpatrolled
+ * @param bool $isWatchlist
* @return bool
*/
public static function onChangesListInsertArticleLink(
@@ -351,17 +381,17 @@ class FlowHooks {
/**
* Updates a Flow line in the old changes list (standard RecentChanges).
*
- * @param ChangesList $changesList
- * @param string $s
+ * @param ChangesList &$changesList
+ * @param string &$s
* @param RecentChange $rc
- * @param array $classes
+ * @param array &$classes
* @return bool
*/
public static function onOldChangesListRecentChangesLine(
ChangesList &$changesList,
&$s,
RecentChange $rc,
- &$classes = array()
+ &$classes = []
) {
return self::processRecentChangesLine( $changesList, $s, $rc, $classes );
}
@@ -372,11 +402,11 @@ class FlowHooks {
* line with meta info (old changes), or simply updates the link to
* the topic (enhanced).
*
- * @param ChangesList $changesList
- * @param string $s
- * @param RecentChange $rc
- * @param array|null $classes
- * @param bool $topicOnly
+ * @param ChangesList &$changesList
+ * @param string &$s
+ * @param RecentChange $rc
+ * @param array|null &$classes
+ * @param bool $topicOnly
* @return bool
*/
protected static function processRecentChangesLine(
@@ -388,7 +418,7 @@ class FlowHooks {
) {
$source = $rc->getAttribute( 'rc_source' );
if ( $source === null ) {
- $rcType = (int) $rc->getAttribute( 'rc_type' );
+ $rcType = (int)$rc->getAttribute( 'rc_type' );
if ( $rcType !== RC_FLOW ) {
return true;
}
@@ -410,13 +440,18 @@ class FlowHooks {
/** @var Flow\Formatter\ChangesListFormatter $formatter */
$formatter = Container::get( 'formatter.changeslist' );
$line = $formatter->format( $row, $changesList, $topicOnly );
+ } catch ( PermissionException $pe ) {
+ // It is expected that some rows won't be formatted because the current user
+ // doesn't have permission to see some of the data they contain.
+ return false;
} catch ( Exception $e ) {
wfDebugLog( 'Flow', __METHOD__ . ': Exception formatting rc ' . $rc->getAttribute( 'rc_id' ) . ' ' . $e );
MWExceptionHandler::logException( $e );
- restore_error_handler();
return false;
}
- restore_error_handler();
+ finally {
+ restore_error_handler();
+ }
if ( $line === false ) {
return false;
@@ -425,6 +460,7 @@ class FlowHooks {
if ( is_array( $classes ) ) {
// Add the flow class to <li>
$classes[] = 'flow-recentchanges-line';
+ $classes[] = 'mw-changeslist-src-mw-edit';
}
// Update the line markup
$s = $line;
@@ -437,7 +473,7 @@ class FlowHooks {
* The default diff links are incorrect!
*
* @param EnhancedChangesList $changesList
- * @param array $links
+ * @param array &$links
* @param RecentChange[] $block
* @return bool
*/
@@ -445,7 +481,7 @@ class FlowHooks {
$rc = $block[0];
// quit if non-flow
- if ( !FlowHooks::isFlow( $rc ) ) {
+ if ( !self::isFlow( $rc ) ) {
return true;
}
@@ -471,7 +507,7 @@ class FlowHooks {
}
restore_error_handler();
- if ($logTextLinks === false) {
+ if ( $logTextLinks === false ) {
return false;
}
@@ -481,24 +517,30 @@ class FlowHooks {
/**
* @param EnhancedChangesList $changesList
- * @param array $data
+ * @param array &$data
* @param RecentChange[] $block
* @param RecentChange $rc
+ * @param array &$classes
* @return bool
*/
- public static function onEnhancedChangesListModifyLineData( $changesList, &$data, $block, $rc ) {
- return static::onEnhancedChangesListModifyBlockLineData( $changesList, $data, $rc );
+ public static function onEnhancedChangesListModifyLineData( $changesList, &$data, $block, $rc, &$classes ) {
+ return static::modifyChangesListLine( $changesList, $data, $rc, $classes );
}
/**
* @param EnhancedChangesList $changesList
- * @param array $data
+ * @param array &$data
* @param RecentChange $rc
* @return bool
*/
public static function onEnhancedChangesListModifyBlockLineData( $changesList, &$data, $rc ) {
+ $classes = null;
+ return static::modifyChangesListLine( $changesList, $data, $rc, $classes );
+ }
+
+ private static function modifyChangesListLine( $changesList, &$data, $rc, &$classes ) {
// quit if non-flow
- if ( !FlowHooks::isFlow( $rc ) ) {
+ if ( !self::isFlow( $rc ) ) {
return true;
}
@@ -512,7 +554,13 @@ class FlowHooks {
$formatter = Container::get( 'formatter.changeslist' );
try {
$data['timestampLink'] = $formatter->getTimestampLink( $row, $changesList );
- $data['recentChangesFlags'] = $formatter->getFlags( $row, $changesList );
+ $data['recentChangesFlags'] = array_merge(
+ $data['recentChangesFlags'],
+ $formatter->getFlags( $row, $changesList )
+ );
+ if ( $classes ) {
+ $classes[] = 'mw-changeslist-src-mw-edit';
+ }
} catch ( PermissionException $e ) {
return false;
}
@@ -528,7 +576,7 @@ class FlowHooks {
private static function isFlow( $rc ) {
$source = $rc->getAttribute( 'rc_source' );
if ( $source === null ) {
- $rcType = (int) $rc->getAttribute( 'rc_type' );
+ $rcType = (int)$rc->getAttribute( 'rc_type' );
return $rcType === RC_FLOW;
} else {
return $source === RecentChangesListener::SRC_FLOW;
@@ -546,7 +594,7 @@ class FlowHooks {
/** @var CheckUserQuery $query */
$query = Container::get( 'query.checkuser' );
// @todo: create hook to allow batch-loading this data, instead of doing piecemeal like this
- $query->loadMetadataBatch( array( $row ) );
+ $query->loadMetadataBatch( [ $row ] );
$row = $query->getResult( $checkUser, $row );
if ( $row !== false ) {
/** @var Flow\Formatter\CheckUserFormatter $formatter */
@@ -575,8 +623,8 @@ class FlowHooks {
* Regular talk page "Create source" and "Add topic" links are quite useless
* in the context of Flow boards. Let's get rid of them.
*
- * @param SkinTemplate $template
- * @param array $links
+ * @param SkinTemplate &$template
+ * @param array &$links
* @return bool
*/
public static function onSkinTemplateNavigation( SkinTemplate &$template, &$links ) {
@@ -589,7 +637,7 @@ class FlowHooks {
if ( $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
// Turn off page actions in MobileFrontend.
// FIXME: Find more elegant standard way of doing this.
- $wgMFPageActions = array();
+ $wgMFPageActions = [];
// watch star & delete links are inside the topic itself
if ( $title->getNamespace() === NS_TOPIC ) {
@@ -629,25 +677,14 @@ class FlowHooks {
* Interact with the mobile skin's default modules on Flow enabled pages
*
* @param Skin $skin
- * @param array $modules
- * @return bool
+ * @param array &$modules
*/
public static function onSkinMinervaDefaultModules( Skin $skin, array &$modules ) {
// Disable toggling on occupied talk pages in mobile
$title = $skin->getTitle();
if ( $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
- $modules['toggling'] = array();
- }
- // Turn off default mobile talk overlay for these pages
- if ( $title->canTalk() ) {
- $talkPage = $title->getTalkPage();
- if ( $talkPage->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
- // TODO: Insert lightweight JavaScript that opens flow via ajax
- $modules['talk'] = array();
- }
+ $modules['toggling'] = [];
}
-
- return true;
}
/**
@@ -664,7 +701,7 @@ class FlowHooks {
* related to that talk page (rather: they were actions on the board)
*
* @param array &$conds Array of conditions
- * @param array &$logTypes Array of log types
+ * @param array $logTypes Array of log types
* @return bool
*/
public static function onMissingArticleConditions( array &$conds, array $logTypes ) {
@@ -689,7 +726,7 @@ class FlowHooks {
* Adds Flow entries to watchlists
*
* @param array &$types Type array to modify
- * @return boolean true
+ * @return bool true
*/
public static function onSpecialWatchlistGetNonRevisionTypes( &$types ) {
$types[] = RC_FLOW;
@@ -702,7 +739,7 @@ class FlowHooks {
* username. Additionally reserve the username used to add a revision on
* taking over a page.
*
- * @param array $names
+ * @param array &$names
* @return bool
*/
public static function onUserGetReservedNames( &$names ) {
@@ -740,9 +777,6 @@ class FlowHooks {
* @return bool
*/
public static function onDeletedContributionsLineEnding( $pager, &$ret, $row, &$classes ) {
- global $wgHooks;
- static $javascriptIncluded = false;
-
if ( !$row instanceof Flow\Formatter\FormatterRow ) {
return true;
}
@@ -768,14 +802,8 @@ class FlowHooks {
// If we output one or more lines of contributions entries we also need to include
// the javascript that hooks into moderation actions.
- // @todo not a huge fan of this static variable, what else though?
- if ( !$javascriptIncluded ) {
- $javascriptIncluded = true;
- $wgHooks['SpecialPageAfterExecute'][] = function( $specialPage, $subPage ) {
- $specialPage->getOutput()->addModules( array( 'ext.flow.contributions' ) );
- $specialPage->getOutput()->addModuleStyles( array( 'ext.flow.contributions.styles' ) );
- };
- }
+ $pager->getOutput()->addModules( [ 'ext.flow.contributions' ] );
+ $pager->getOutput()->addModuleStyles( [ 'ext.flow.contributions.styles' ] );
return true;
}
@@ -832,7 +860,7 @@ class FlowHooks {
/**
* Adds Flow contributions to the DeletedContributions special page
*
- * @param $data array an array of results of all contribs queries, to be
+ * @param array $data an array of results of all contribs queries, to be
* merged to form all contributions data
* @param ContribsPager $pager Object hooked into
* @param string $offset Index offset, inclusive
@@ -865,7 +893,7 @@ class FlowHooks {
/**
* Adds Flow contributions to the Contributions special page
*
- * @param $data array an array of results of all contribs queries, to be
+ * @param array $data an array of results of all contribs queries, to be
* merged to form all contributions data
* @param ContribsPager $pager Object hooked into
* @param string $offset Index offset, inclusive
@@ -883,9 +911,24 @@ class FlowHooks {
}
/**
+ * Define and add descriptions for board-related variables
+ * @param array $realValues
+ * @return bool
+ */
+ public static function onAbuseFilterBuilder( &$realValues ) {
+ $realValues['vars'] += [
+ 'board_articleid' => 'board-articleid',
+ 'board_namespace' => 'board-namespace',
+ 'board_text' => 'board-text',
+ 'board_prefixedtext' => 'board-prefixedtext',
+ ];
+ return true;
+ }
+
+ /**
* Adds lazy-load methods for AbstractRevision objects.
*
- * @param string $method: Method to generate the variable
+ * @param string $method Method to generate the variable
* @param AbuseFilterVariableHolder $vars
* @param array $parameters Parameters with data to compute the value
* @param mixed &$result Result of the computation
@@ -985,7 +1028,6 @@ class FlowHooks {
* still be in their web notifications (if enabled), but they will never be
* notified via email (regardless of batching settings) for this particular
* notification.
- *
*/
public static function onEchoAbortEmailNotification( User $user, EchoEvent $event ) {
$extra = $event->getExtra();
@@ -996,6 +1038,27 @@ class FlowHooks {
return true;
}
+ /**
+ * Hides the orange alert indicating 'You have a new message'
+ * when the user reads flow-topic replies.
+ *
+ * @param User $user
+ * @param Title $title
+ * @return bool true to show the alert, false to hide(abort) the alert
+ */
+ public static function onBeforeDisplayOrangeAlert( User $user, Title $title ) {
+ if ( $title->getNamespace() === NS_TOPIC ) {
+ $storage = Container::get( 'storage.workflow' );
+ $uuid = WorkflowLoaderFactory::uuidFromTitle( $title );
+ $workflow = $storage->get( $uuid );
+ if ( $workflow ) {
+ $boardTitle = $workflow->getOwnerTitle();
+ }
+ if ( $user->getTalkPage()->equals( $boardTitle ) ) {
+ return false;
+ }
+ }
+ }
public static function onInfoAction( IContextSource $ctx, &$pageinfo ) {
if ( $ctx->getTitle()->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
@@ -1007,55 +1070,17 @@ class FlowHooks {
unset( $pageinfo['header-edits'] );
// These keys are wrong on Flow pages, so we'll remove them
- static $badMessageKeys = array( 'pageinfo-length', 'pageinfo-content-model' );
+ static $badMessageKeys = [ 'pageinfo-length' ];
foreach ( $pageinfo['header-basic'] as $num => $val ) {
if ( $val[0] instanceof Message && in_array( $val[0]->getKey(), $badMessageKeys ) ) {
- unset($pageinfo['header-basic'][$num]);
+ unset( $pageinfo['header-basic'][$num] );
}
}
return true;
}
/**
- * Overwrite terms of use message if the overwrite exits
- *
- * @param string &$key
- * @return bool
- */
- public static function onMessageCacheGet( &$key ) {
- global $wgResourceModules;
-
- static $terms = array (
- 'flow-terms-of-use-new-topic' => null,
- 'flow-terms-of-use-reply' => null,
- 'flow-terms-of-use-edit' => null,
- 'flow-terms-of-use-summarize' => null,
- 'flow-terms-of-use-lock-topic' => null,
- 'flow-terms-of-use-unlock-topic' => null
- );
-
- if ( !array_key_exists( $key, $terms ) ) {
- return true;
- }
-
- if ( $terms[$key] === null ) {
- $message = wfMessage( "wikimedia-$key" );
- if ( $message->exists() ) {
- $terms[$key] = "wikimedia-$key";
- $wgResourceModules['ext.flow.templating']['messages'][] = "wikimedia-$key";
- } else {
- $terms[$key] = false;
- }
- }
-
- if ( $terms[$key] ) {
- $key = $terms[$key];
- }
- return true;
- }
-
- /**
* @param RecentChange $rc
* @param array &$rcRow
* @return bool
@@ -1133,22 +1158,22 @@ class FlowHooks {
/**
* Add topiclist sortby to preferences.
*
- * @param $user User object
- * @param &$preferences array Preferences object
+ * @param User $user User object
+ * @param array &$preferences Preferences object
* @return bool
*/
public static function onGetPreferences( $user, &$preferences ) {
- $preferences['flow-topiclist-sortby'] = array(
+ $preferences['flow-topiclist-sortby'] = [
'type' => 'api',
- );
+ ];
- $preferences['flow-editor'] = array(
+ $preferences['flow-editor'] = [
'type' => 'api'
- );
+ ];
- $preferences['flow-side-rail-state'] = array(
+ $preferences['flow-side-rail-state'] = [
'type' => 'api'
- );
+ ];
return true;
}
@@ -1157,8 +1182,8 @@ class FlowHooks {
* ResourceLoaderTestModules hook handler
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderTestModules
*
- * @param array $testModules
- * @param ResourceLoader $resourceLoader
+ * @param array &$testModules
+ * @param ResourceLoader &$resourceLoader
* @return bool
*/
public static function onResourceLoaderTestModules( array &$testModules,
@@ -1169,9 +1194,9 @@ class FlowHooks {
// find test files for every RL module
foreach ( $wgResourceModules as $key => $module ) {
if ( preg_match( '/ext.flow(?:\.|$)/', $key ) && isset( $module['scripts'] ) ) {
- $testFiles = array();
+ $testFiles = [];
- $scripts = (array) $module['scripts'];
+ $scripts = (array)$module['scripts'];
foreach ( $scripts as $script ) {
$testFile = 'tests/qunit/' . dirname( $script ) . '/test_' . basename( $script );
// if a test file exists for a given JS file, add it
@@ -1181,12 +1206,12 @@ class FlowHooks {
}
// if test files exist for given module, create a corresponding test module
if ( count( $testFiles ) > 0 ) {
- $module = array(
+ $module = [
'remoteExtPath' => 'Flow',
- 'dependencies' => array( $key ),
+ 'dependencies' => [ $key ],
'localBasePath' => __DIR__,
'scripts' => $testFiles,
- );
+ ];
$testModules['qunit']["$key.tests"] = $module;
}
}
@@ -1198,9 +1223,9 @@ class FlowHooks {
/**
* Don't (un)watch a non-existing flow topic
*
- * @param User $user
- * @param WikiPage $page
- * $param Status $status
+ * @param User &$user
+ * @param WikiPage &$page
+ * $param Status &$status
*/
public static function onWatchArticle( &$user, WikiPage &$page, &$status ) {
$title = $page->getTitle();
@@ -1210,8 +1235,8 @@ class FlowHooks {
$storage = Container::get( 'storage' );
$found = $storage->find(
'PostRevision',
- array( 'rev_type_id' => strtolower( $title->getDBkey() ) ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => strtolower( $title->getDBkey() ) ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( !$found ) {
return false;
@@ -1225,68 +1250,71 @@ class FlowHooks {
}
/**
- * Adds the topic namespace.
+ * Checks whether this is a valid move technically. MovePageIsValidMove should not
+ * be affected by the specific user, or user permissions.
+ *
+ * Those are handled in onMovePageCheckPermissions, called later.
+ *
+ * @param Title $oldTitle Old title
+ * @param Title $newTitle New title
+ * @param Status $status Status to update with any technical issues
+ *
+ * @return true to continue, false to abort the hook
*/
- public static function onCanonicalNamespaces( &$list ) {
- $list[NS_TOPIC] = 'Topic';
- return true;
- }
-
public static function onMovePageIsValidMove( Title $oldTitle, Title $newTitle, Status $status ) {
- global $wgUser;
-
- // We only care about moving flow boards
+ // We only care about moving Flow boards, and *not* moving Flow topics
+ // (but both are CONTENT_MODEL_FLOW_BOARD)
if ( $oldTitle->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
return true;
}
- // pages within the Topic namespace are not movable
+ // Pages within the Topic namespace are not movable
+ // This is also checked by NamespaceIsMovable.
if ( $oldTitle->getNamespace() === NS_TOPIC ) {
$status->fatal( 'flow-error-move-topic' );
return false;
}
- // valid if the destination is already a valid flow location (=default flow-board model)
- if ( ContentHandler::getDefaultModelFor( $newTitle ) === CONTENT_MODEL_FLOW_BOARD ) {
- return true;
- }
-
- // valid if the user has permissions to create a new board wherever
$occupationController = self::getOccupationController();
- $creationStatus = $occupationController->allowCreation( $newTitle, $wgUser );
- if ( !$creationStatus->isGood() ) {
- $status->fatal( 'flow-error-move-no-create-permissions' );
- return false;
- }
+ $flowStatus = $occupationController->checkIfCreationIsPossible( $newTitle, /*mustNotExist*/ true );
+ $status->merge( $flowStatus );
return true;
}
/**
- * Moves of Flow topic pages (NS_TOPIC) are never permitted, and board moves
- * are not always permitted.
+ * Checks whether user has permission to move the board.
*
- * @param Title $oldTitle
- * @param Title $newTitle
- * @param User $user
- * @param string|null $error Null coming in; assign (textual) error message when failing
- * @param string $reason
- * @return bool
+ * Technical restrictions are handled in onMovePageIsValidMove, called earlier.
+ *
+ * @param Title $oldTitle Old title
+ * @param Title $newTitle New title
+ * @param User $user User doing the move
+ * @param string $reason Reason for the move
+ * @param Status $status Status updated with any permissions issue
+ *
+ * @return true to continue, false to abort the hook
*/
- public static function onAbortMove( $oldTitle, $newTitle, $user, &$error, $reason ) {
- $status = new Status();
- self::onMovePageIsValidMove( $oldTitle, $newTitle, $status );
- if ( !$status->isOK() ) {
- $error = $status->getHTML();
- return false;
+ public static function onMovePageCheckPermissions( Title $oldTitle, Title $newTitle, User $user, $reason, Status $status ) {
+ // Only affect moves if the source has Flow content model
+ if ( $oldTitle->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
+ return true;
}
+ $occupationController = self::getOccupationController();
+
+ $permissionStatus = $occupationController->checkIfUserHasPermission(
+ $newTitle,
+ $user
+ );
+ $status->merge( $permissionStatus );
+
return true;
}
/**
* @param Title $title
- * @param string[] $urls
+ * @param string[] &$urls
* @return bool
*/
public static function onTitleSquidURLs( Title $title, array &$urls ) {
@@ -1309,18 +1337,18 @@ class FlowHooks {
}
$urls = array_merge(
$urls,
- $workflow->getOwnerTitle()->getSquidURLs()
+ $workflow->getOwnerTitle()->getCdnUrls()
);
return true;
}
/**
- * @param array $tools Extra links
+ * @param array &$tools Extra links
* @param Title $title
* @param bool $redirect Whether the page is a redirect
* @param Skin $skin
- * @param string $link
+ * @param string &$link
* @return bool
*/
public static function onWatchlistEditorBuildRemoveLine( &$tools, $title, $redirect, $skin, &$link = '' ) {
@@ -1356,15 +1384,14 @@ class FlowHooks {
return true;
}
- // Titles are never parsed, so request as wikitext
- $content = $revision->getContent( 'wikitext' );
+ $content = $revision->getContent( 'topic-title-plaintext' );
$link = Linker::link( $title, htmlspecialchars( $content ) );
return true;
}
/**
- * @param array $watchlistInfo Watchlisted pages
+ * @param array &$watchlistInfo Watchlisted pages
* @return bool
*/
public static function onWatchlistEditorBeforeFormRender( &$watchlistInfo ) {
@@ -1376,11 +1403,11 @@ class FlowHooks {
$ids = array_keys( $watchlistInfo[NS_TOPIC] );
// build array of queries to be executed all at once
- $queries = array();
- foreach( $ids as $id ) {
+ $queries = [];
+ foreach ( $ids as $id ) {
try {
$uuid = WorkflowLoaderFactory::uuidFromTitlePair( NS_TOPIC, $id );
- $queries[] = array( 'rev_type_id' => $uuid );
+ $queries[] = [ 'rev_type_id' => $uuid ];
} catch ( Exception $e ) {
// invalid id
unset( $watchlistInfo[NS_TOPIC][$id] );
@@ -1399,7 +1426,7 @@ class FlowHooks {
$storage->findMulti(
'PostRevision',
$queries,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
return true;
@@ -1409,7 +1436,7 @@ class FlowHooks {
* For integration with the UserMerge extension. Provides the database and
* sets of table/column pairs to update user id's within.
*
- * @param array $updateFields
+ * @param array &$updateFields
* @return bool
*/
public static function onUserMergeAccountFields( &$updateFields ) {
@@ -1446,11 +1473,14 @@ class FlowHooks {
/**
* @param int $namespace
- * @param bool $movable
+ * @param bool &$movable
* @return bool
*/
public static function onNamespaceIsMovable( $namespace, &$movable ) {
- $movable &= $namespace !== NS_TOPIC;
+ if ( $namespace === NS_TOPIC ) {
+ $movable = false;
+ }
+
return true;
}
@@ -1495,9 +1525,9 @@ class FlowHooks {
*/
protected static function getTopicDeletionError( Title $title ) {
$error = wfMessage( 'flow-error-core-topic-deletion', $title->getFullURL() )->parse();
- $wrappedError = Html::rawElement( 'span', array(
+ $wrappedError = Html::rawElement( 'span', [
'class' => 'plainlinks',
- ), $error );
+ ], $error );
return $wrappedError;
}
@@ -1508,7 +1538,7 @@ class FlowHooks {
* the Topic namespace.
*
* @param WikiPage $article Page the user requested to delete
- * @param OutputPage $out Output page
+ * @param OutputPage $output Output page
* @param string &$reason Pre-filled reason given for deletion (note, this could
* be used to customize this for boards and/or topics later)
* @return bool False if it is a Topic; otherwise, true
@@ -1516,7 +1546,7 @@ class FlowHooks {
public static function onArticleConfirmDelete( $article, $output, &$reason ) {
$title = $article->getTitle();
if ( $title->inNamespace( NS_TOPIC ) ) {
- $output->addHTML( FlowHooks::getTopicDeletionError( $title ) );
+ $output->addHTML( self::getTopicDeletionError( $title ) );
return false;
}
@@ -1536,7 +1566,7 @@ class FlowHooks {
public static function onArticleDelete( WikiPage &$article, User &$user, &$reason, &$error ) {
$title = $article->getTitle();
if ( $title->inNamespace( NS_TOPIC ) ) {
- $error = FlowHooks::getTopicDeletionError( $title );
+ $error = self::getTopicDeletionError( $title );
return false;
}
@@ -1544,31 +1574,91 @@ class FlowHooks {
}
/**
+ * Evicts topics from Squid/Varnish when the board is deleted.
+ * We do permission checks for this scenario, but since the topic isn't deleted
+ * at the core level, we need to evict it from Varnish ourselves.
+ *
+ * @param WikiPage &$article Deleted article
+ * @param User &$user User that deleted article
+ * @param string $reason Reason given
+ * @param int $articleId Article ID of deleted article
+ * @param Content $content Content that was deleted, or null on error
+ * @param LogEntry $logEntry Log entry for deletion
+ */
+ public static function onArticleDeleteComplete( WikiPage &$article, User &$user, $reason, $articleId, Content $content = null, LogEntry $logEntry ) {
+ $title = $article->getTitle();
+
+ // Topics use the same content model, but can't be deleted at the core
+ // level currently.
+ if ( $content !== null &&
+ $title->getNamespace() !== NS_TOPIC &&
+ $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
+ $storage = Container::get( 'storage' );
+
+ DeferredUpdates::addCallableUpdate( function () use ( $storage, $articleId ) {
+ /** @var \Flow\Model\Workflow[] $workflows */
+ $workflows = $storage->find( 'Workflow', [
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_page_id' => $articleId,
+ ] );
+ if ( !$workflows ) {
+ return;
+ }
+
+ $topicTitles = [];
+ foreach ( $workflows as $workflow ) {
+ if ( $workflow->getType() === 'topic' ) {
+ $topicTitles[] = $workflow->getArticleTitle();
+ }
+ }
+
+ $update = CdnCacheUpdate::newFromTitles( $topicTitles );
+ DeferredUpdates::addUpdate( $update ); // run right after this
+ } );
+ }
+
+ return true;
+ }
+
+ /**
* @param Title $title Title corresponding to the article restored
- * @param bool $create Whether or not the restoration caused the page to be created (i.e. it didn't exist before).
- * @param string $comment The comment associated with the undeletion.
- * @param int $oldPageId ID of page previously deleted (from archive table)
+ * @param Revision $revision Revision just undeleted
+ * @param string $oldPageId Old page ID stored with that revision when it was in the archive table
* @return bool
*/
- public static function onArticleUndelete( Title $title, $created, $comment, $oldPageId ) {
- if ( $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
+ public static function onArticleRevisionUndeleted( Title $title, Revision $revision, $oldPageId ) {
+ if ( $revision->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
// complete hack to make sure that when the page is saved to new
// location and rendered it doesn't throw an error about the wrong title
Container::get( 'factory.loader.workflow' )->pageMoveInProgress();
- // open a database transaction and prepare everything for the move & commit
+
+ // Reassociate the Flow board associated with this undeleted revision.
$boardMover = Container::get( 'board_mover' );
- $boardMover->prepareMove( $oldPageId, $title );
- $boardMover->commit();
+ $boardMover->move( intval( $oldPageId ), $title );
}
return true;
}
/**
- * Occurs at the beginning of the MovePage process. Perhaps ContentModel should be
- * extended to be notified about moves explicitly.
+ * @param Title $title Title corresponding to the article restored
+ * @param bool $create Whether or not the restoration caused the page to be created (i.e. it didn't exist before).
+ * @param string $comment The comment associated with the undeletion.
+ * @param int $oldPageId ID of page previously deleted (from archive table)
+ * @throws InvalidUndeleteException
+ * @return bool
*/
- public static function onTitleMove( Title $oldTitle, Title $newTitle, User $user ) {
+ public static function onArticleUndelete( Title $title, $create, $comment, $oldPageId ) {
+ $boardMover = Container::get( 'board_mover' );
+ $boardMover->commit();
+ }
+
+ /**
+ * Occurs at the beginning of the MovePage process (just after the startAtomic).
+ *
+ * Perhaps ContentModel should be extended to be notified about moves explicitly.
+ */
+ public static function onTitleMoveStarting( Title $oldTitle, Title $newTitle, User $user ) {
if ( $oldTitle->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
// $newTitle doesn't yet exist, but after the move it'll still have
// the same ID $oldTitle used to have
@@ -1578,18 +1668,22 @@ class FlowHooks {
$bogusTitle = clone $newTitle;
$bogusTitle->resetArticleID( $oldTitle->getArticleID() );
+ // This is only safe because we have called
+ // checkIfCreationIsPossible and (usually) checkIfUserHasPermission.
+ Container::get( 'occupation_controller' )->forceAllowCreation( $bogusTitle );
// complete hack to make sure that when the page is saved to new
// location and rendered it doesn't throw an error about the wrong title
Container::get( 'factory.loader.workflow' )->pageMoveInProgress();
// open a database transaction and prepare everything for the move, but
- // don't commit yet. That is done below in self::onTitleMoveComplete
- Container::get( 'board_mover' )->prepareMove( $oldTitle->getArticleID(), $bogusTitle );
+ // don't commit yet. That is done below in self::onTitleMoveCompleting
+ $boardMover = Container::get( 'board_mover' );
+ $boardMover->move( $oldTitle->getArticleID(), $bogusTitle );
}
return true;
}
- public static function onTitleMoveComplete( Title $oldTitle, Title $newTitle, User $user, $pageid, $redirid, $reason ) {
+ public static function onTitleMoveCompleting( Title $oldTitle, Title $newTitle, User $user, $pageid, $redirid, $reason, Revision $revision ) {
if ( $newTitle->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
Container::get( 'board_mover' )->commit();
}
@@ -1617,7 +1711,7 @@ class FlowHooks {
/**
* Excludes NS_TOPIC from the list of searchable namespaces
*
- * @param array $namespaces Associative array mapping namespace index
+ * @param array &$namespaces Associative array mapping namespace index
* to name
* @return bool
*/
@@ -1631,13 +1725,13 @@ class FlowHooks {
*/
private static function isBetaFeatureAvailable() {
global $wgBetaFeaturesWhitelist, $wgFlowEnableOptInBetaFeature;
- return $wgFlowEnableOptInBetaFeature &&
+ return $wgFlowEnableOptInBetaFeature && class_exists( BetaFeatures::class ) &&
( !is_array( $wgBetaFeaturesWhitelist ) || in_array( BETA_FEATURE_FLOW_USER_TALK_PAGE, $wgBetaFeaturesWhitelist ) );
}
/**
* @param User $user
- * @param array $prefs
+ * @param array &$prefs
* @return bool
*/
public static function onGetBetaFeaturePreferences( $user, &$prefs ) {
@@ -1647,37 +1741,25 @@ class FlowHooks {
return true;
}
- $defaultProjectUrl = 'https://www.mediawiki.org/wiki/Extension:Flow';
- $defaultProjectTalkUrl = 'https://www.mediawiki.org/wiki/Extension_talk:Flow';
-
- $prefs[BETA_FEATURE_FLOW_USER_TALK_PAGE] = array(
+ $prefs[BETA_FEATURE_FLOW_USER_TALK_PAGE] = [
// The first two are message keys
'label-message' => 'flow-talk-page-beta-feature-message',
'desc-message' => 'flow-talk-page-beta-feature-description',
- 'screenshot' => array(
+ 'screenshot' => [
'ltr' => "$wgExtensionAssetsPath/Flow/images/betafeature-flow-ltr.svg",
'rtl' => "$wgExtensionAssetsPath/Flow/images/betafeature-flow-rtl.svg",
- ),
- 'info-link' => self::getTitleUrlOrDefault( 'Project:Flow', $defaultProjectUrl ),
- 'discussion-link' => self::getTitleUrlOrDefault( 'Project_talk:Flow', $defaultProjectTalkUrl ),
- );
+ ],
+ 'info-link' => 'https://www.mediawiki.org/wiki/Flow',
+ 'discussion-link' => 'https://www.mediawiki.org/wiki/Talk:Flow',
+ 'exempt-from-auto-enrollment' => true,
+ ];
return true;
}
/**
- * @param string $titleText
- * @param string $default
- * @return string
- */
- private static function getTitleUrlOrDefault( $titleText, $default ) {
- $title = Title::newFromText( $titleText );
- return $title->exists() ? $title->getLocalURL() : $default;
- }
-
- /**
* @param User $user
- * @param array $options
+ * @param array &$options
* @return bool
*/
public static function onUserSaveOptions( $user, &$options ) {
@@ -1700,7 +1782,7 @@ class FlowHooks {
$c = new Flow\Import\OptInController();
if ( !$c->hasFlowBoardArchive( $user ) ) {
// Enable the guided tour by setting the cookie
- RequestContext::getMain()->getRequest()->response()->setcookie( 'Flow_optIn_guidedTour', '1' );
+ RequestContext::getMain()->getRequest()->response()->setCookie( 'Flow_optIn_guidedTour', '1' );
}
} elseif ( $before && !$after ) {
$action = OptInUpdate::$DISABLE;
@@ -1713,4 +1795,302 @@ class FlowHooks {
return true;
}
+ /**
+ * @param WikiImporter $importer
+ * @return bool
+ */
+ public static function onImportHandleToplevelXMLTag( WikiImporter $importer ) {
+ // only init Flow's importer once, then re-use it
+ static $flowImporter = null;
+ if ( $flowImporter === null ) {
+ // importer can be dry-run (= parse, but don't store), but we can only
+ // derive that from mPageOutCallback. I'll set a new value (which will
+ // return the existing value) to see if it's in dry-run mode (= null)
+ $callback = $importer->setPageOutCallback( null );
+ // restore previous mPageOutCallback value
+ $importer->setPageOutCallback( $callback );
+
+ $flowImporter = new \Flow\Dump\Importer( $importer );
+ if ( $callback !== null ) {
+ // not in dry-run mode
+ $flowImporter->setStorage( Container::get( 'storage' ) );
+ }
+ }
+
+ $reader = $importer->getReader();
+ $tag = $reader->localName;
+ $type = $reader->nodeType;
+
+ if ( $tag == 'board' ) {
+ if ( $type === XMLReader::ELEMENT ) {
+ $flowImporter->handleBoard();
+ }
+ return false;
+ } elseif ( $tag == 'description' ) {
+ if ( $type === XMLReader::ELEMENT ) {
+ $flowImporter->handleHeader();
+ }
+ return false;
+ } elseif ( $tag == 'topic' ) {
+ if ( $type === XMLReader::ELEMENT ) {
+ $flowImporter->handleTopic();
+ }
+ return false;
+ } elseif ( $tag == 'post' ) {
+ if ( $type === XMLReader::ELEMENT ) {
+ $flowImporter->handlePost();
+ }
+ return false;
+ } elseif ( $tag == 'summary' ) {
+ if ( $type === XMLReader::ELEMENT ) {
+ $flowImporter->handleSummary();
+ }
+ return false;
+ } elseif ( $tag == 'children' ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static function onNukeGetNewPages( $username, $pattern, $namespace, $limit, &$pages ) {
+ if ( $namespace && $namespace !== NS_TOPIC ) {
+ // not interested in any Topics
+ return true;
+ }
+
+ // Remove any pre-existing Topic pages.
+ // They are coming from the recentchanges table.
+ // Most likely the filters were not applied correctly.
+ $pages = array_filter( $pages, function ( $entry ) {
+ /** @var Title $title */
+ $title = $entry[0];
+ return $title->getNamespace() !== NS_TOPIC;
+ } );
+
+ if ( $pattern ) {
+ // pattern is not supported
+ return true;
+ }
+
+ if ( !RequestContext::getMain()->getUser()->isAllowed( 'flow-delete' ) ) {
+ // there's no point adding topics since the current user won't be allowed to delete them
+ return true;
+ }
+
+ // how many are we allowed to retrieve now
+ $newLimit = $limit - count( $pages );
+
+ // we can't add anything
+ if ( $newLimit < 1 ) {
+ return true;
+ }
+
+ $dbFactory = Container::get( 'db.factory' );
+ /** @var Database $dbr */
+ $dbr = $dbFactory->getDB( DB_SLAVE );
+
+ // if a username is specified, search only for that user
+ $userWhere = [];
+ if ( $username ) {
+ $user = User::newFromName( $username );
+ if ( $user && $user->isLoggedIn() ) {
+ $userWhere = [ 'tree_orig_user_id' => $user->getId() ];
+ } else {
+ $userWhere = [ 'tree_orig_user_ip' => $username ];
+ }
+ }
+
+ // limit results to the range of RC
+ global $wgRCMaxAge;
+ $rcTimeLimit = UUID::getComparisonUUID( strtotime( "-$wgRCMaxAge seconds" ) );
+
+ // get latest revision id for each topic
+ $result = $dbr->select(
+ [
+ 'r' => 'flow_revision',
+ 'flow_tree_revision',
+ 'flow_workflow',
+ ],
+ [
+ 'revId' => 'MAX(r.rev_id)',
+ 'userIp' => "tree_orig_user_ip",
+ 'userId' => "tree_orig_user_id",
+ ],
+ array_merge( [
+ 'tree_parent_id' => null,
+ 'r.rev_type' => 'post',
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_id > ' . $dbr->addQuotes( $rcTimeLimit->getBinary() )
+ ], $userWhere ),
+ __METHOD__,
+ [
+ 'GROUP BY' => 'r.rev_type_id'
+ ],
+ [
+ 'flow_tree_revision' => [ 'INNER JOIN', 'r.rev_type_id=tree_rev_descendant_id' ],
+ 'flow_workflow' => [ 'INNER JOIN', 'r.rev_type_id=workflow_id' ],
+ ]
+ );
+
+ if ( $result->numRows() < 1 ) {
+ return true;
+ }
+
+ $revIds = [];
+ foreach ( $result as $r ) {
+ $revIds[$r->revId] = [ 'userIp' => $r->userIp, 'userId' => $r->userId, 'name' => false ];
+ }
+
+ // get non-moderated revisions
+ $result = $dbr->select(
+ 'flow_revision',
+ [
+ 'topicId' => 'rev_type_id',
+ 'revId' => 'rev_id'
+ ],
+ [
+ 'rev_mod_state' => '',
+ 'rev_id' => array_keys( $revIds )
+ ],
+ __METHOD__,
+ [
+ 'LIMIT' => $newLimit,
+ 'ORDER BY' => 'rev_type_id DESC'
+ ]
+ );
+
+ // all topics previously found appear to be moderated
+ if ( $result->numRows() < 1 ) {
+ return true;
+ }
+
+ // keep only the relevant topics in [topicId => userInfo] format
+ $limitedRevIds = [];
+ foreach ( $result as $r ) {
+ $limitedRevIds[$r->topicId] = $revIds[$r->revId];
+ }
+
+ // fill usernames if no $username filter was specified
+ if ( !$username ) {
+ $userIds = array_map(
+ function ( $userInfo ) {
+ return $userInfo['userId'];
+ },
+ array_values( $limitedRevIds )
+ );
+ $userIds = array_filter( $userIds );
+
+ $userMap = [];
+ if ( $userIds ) {
+ $wikiDbr = $dbFactory->getWikiDB( DB_SLAVE );
+ $result = $wikiDbr->select(
+ 'user',
+ [ 'user_id', 'user_name' ],
+ [ 'user_id' => array_values( $userIds ) ]
+ );
+ foreach ( $result as $r ) {
+ $userMap[$r->user_id] = $r->user_name;
+ }
+ }
+
+ // set name in userInfo structure
+ foreach ( $limitedRevIds as $topicId => &$userInfo ) {
+ if ( $userInfo['userIp'] ) {
+ $userInfo['name'] = $userInfo['userIp'];
+ } elseif ( $userInfo['userId'] ) {
+ $userInfo['name'] = $userMap[$userInfo['userId']];
+ } else {
+ $userInfo['name'] = false;
+ $topicIdAlpha = UUID::create( $topicId )->getAlphadecimal();
+ wfLogWarning( __METHOD__ . ": Cannot find user information for topic {$topicIdAlpha}" );
+ }
+ }
+ }
+
+ // add results to the list of pages to nuke
+ foreach ( $limitedRevIds as $topicId => $userInfo ) {
+ $pages[] = [
+ Title::makeTitle( NS_TOPIC, UUID::create( $topicId )->getAlphadecimal() ),
+ $userInfo['name']
+ ];
+ }
+
+ return true;
+ }
+
+ public static function onNukeDeletePage( Title $title, $reason, &$deletionResult ) {
+ if ( $title->getNamespace() !== NS_TOPIC ) {
+ // we don't handle it
+ return true;
+ }
+
+ $action = 'moderate-topic';
+ $params = [
+ 'topic' => [
+ 'moderationState' => 'delete',
+ 'reason' => $reason,
+ 'page' => $title->getPrefixedText()
+ ],
+ ];
+
+ /** @var WorkflowLoaderFactory $factory */
+ $factory = Container::get( 'factory.loader.workflow' );
+
+ $workflowId = WorkflowLoaderFactory::uuidFromTitle( $title );
+ /** @var WorkflowLoader $loader */
+ $loader = $factory->createWorkflowLoader( $title, $workflowId );
+
+ $blocks = $loader->getBlocks();
+
+ $blocksToCommit = $loader->handleSubmit(
+ RequestContext::getMain(),
+ $action,
+ $params
+ );
+
+ $result = true;
+ $errors = [];
+ foreach ( $blocks as $block ) {
+ if ( $block->hasErrors() ) {
+ $result = false;
+ $errorKeys = $block->getErrors();
+ foreach ( $errorKeys as $errorKey ) {
+ $errors[] = $block->getErrorMessage( $errorKey );
+ }
+ }
+ }
+
+ if ( $result ) {
+ $loader->commit( $blocksToCommit );
+ $deletionResult = true;
+ } else {
+ $deletionResult = false;
+ $msg = "Failed to delete {$title->getPrefixedText()}. Errors: " . implode( '. ', $errors );
+ wfLogWarning( $msg );
+ }
+
+ // we've handled the deletion, abort the hook
+ return false;
+ }
+
+ /**
+ * Filter out all Flow changes when hidepageedits=1
+ *
+ * @param string $name
+ * @param array &$tables
+ * @param array &$fields
+ * @param array &$conds
+ * @param array &$query_options
+ * @param array &$join_conds
+ * @param FormOptions $opts
+ */
+ public static function onChangesListSpecialPageQuery(
+ $name, array &$tables, array &$fields, array &$conds,
+ array &$query_options, array &$join_conds, FormOptions $opts
+ ) {
+ if ( $opts['hidepageedits'] ) {
+ $conds[] = 'rc_type != ' . RC_FLOW;
+ }
+ }
}
diff --git a/Flow/Makefile b/Flow/Makefile
index 05b441e3..14fdedfe 100644
--- a/Flow/Makefile
+++ b/Flow/Makefile
@@ -1,6 +1,10 @@
MW_INSTALL_PATH ?= ../..
MEDIAWIKI_LOAD_URL ?= http://localhost:8080/w/load.php
+ifneq ("$(wildcard /vagrant)","")
+IS_VAGRANT = 1
+endif
+
# Flow files to analyze
ANALYZE=container.php Flow.php Resources.php includes/
@@ -10,23 +14,10 @@ ANALYZE_EXTRA=../../includes/GlobalFunctions.php ../../includes/Defines.php ../.
../../includes/db/DatabaseUtility.php \
../Echo/formatters/BasicFormatter.php ../Echo/formatters/NotificationFormatter.php
-# mediawiki-vagrant default to hhvm rather than php5, which is mostly
-# fine but really slow for commands like phplint
+# Make sure we use php5
PHP=`command -v php5 || command -v php`
###
-# Labs maintenance
-###
-ee-flow:
- ssh ee-flow.eqiad.wmflabs 'cd /srv/mediawiki/extensions/Flow && make master'
-ee-flow-extra:
- ssh ee-flow-extra.eqiad.wmflabs 'cd /vagrant/mediawiki/extensions/Flow && make master'
-# Used to be ee-flow-big, not so big any more
-ee-flow-extra2:
- ssh ee-flow-extra2.eqiad.wmflabs 'cd /srv/mediawiki/extensions/Flow && make master'
-update-labs: ee-flow ee-flow-extra ee-flow-extra2
-
-###
# Meta stuff
###
installhooks:
@@ -51,7 +42,7 @@ messagecheck: remotes
lint: grunt phplint checkless messagecheck
phplint:
- @find ./ -type f -iname '*.php' -print0 | xargs -0 -P 12 -L 1 ${PHP} -l
+ @. scripts/hooks-shared.sh; list_files_changed_in_commit '\.php' | xargs -P 12 -L 1 ${PHP} -l
nodecheck:
@which npm > /dev/null && npm install \
@@ -61,7 +52,14 @@ grunt: nodecheck
@npm test
checkless:
+ifdef IS_VAGRANT
+ mwscript maintenance/checkLess.php --wiki=wiki
+else
@${PHP} ../../maintenance/checkLess.php
+endif
+
+jsduck:
+ jsduck
csscss: gems
echo "Generating CSS file..."
@@ -73,9 +71,6 @@ csscss: gems
phpunit:
cd ${MW_INSTALL_PATH}/tests/phpunit && ${PHP} phpunit.php --configuration ${MW_INSTALL_PATH}/extensions/Flow/tests/phpunit/flow.suite.xml --group=Flow
-qunit:
- @scripts/qunit.sh
-
vagrant-browsertests:
@vagrant ssh -- -X cd /vagrant/mediawiki/extensions/Flow/tests/browser '&&' MEDIAWIKI_URL=http://127.0.0.1:8080/wiki/ MEDIAWIKI_USER=Admin MEDIAWIKI_PASSWORD=vagrant MEDIAWIKI_API_URL=http://127.0.0.1:8080/w/api.php bundle exec cucumber /vagrant/mediawiki/extensions/Flow/tests/browser/features/ -f pretty
@@ -99,8 +94,11 @@ analyze: analyze-hhvm analyze-phpstorm
# Compile lightncandy templates
###
compile-lightncandy:
+ifdef IS_VAGRANT
+ mwscript extensions/Flow/maintenance/compileLightncandy.php --wiki=wiki
+else
@${PHP} maintenance/compileLightncandy.php
-
+endif
###
# Automatically rename/move files based on fully-qualified classname &
# compile class autoloader for $wgAutoloadClasses
@@ -115,14 +113,3 @@ autoload:
###
gems:
bundle install
-
-master:
- git fetch
- @echo Here is what is new on origin/master:
- @git log HEAD..origin/master
- @echo Checkout and update master:
- git checkout master && git pull --ff-only
- @echo 'exit( ( $$wgFlowCluster === false && $$wgFlowDefaultWikiDb === false) ? 0 : 1 )' | php ../../maintenance/eval.php && echo Apply DB updates \(if any\) && php $(MW_INSTALL_PATH)/maintenance/update.php --quick | sed -n '/^[^.]/p' || echo DB updates must be applied manually.
- @echo TODO Update Parsoid and restart it\? Other extensions\?
- @echo Run some tests\!\!\!
-
diff --git a/Flow/Rakefile b/Flow/Rakefile
index 6eef1216..2877bf69 100644
--- a/Flow/Rakefile
+++ b/Flow/Rakefile
@@ -8,6 +8,9 @@ RuboCop::RakeTask.new(:rubocop) do |task|
task.options = ['-c', '.rubocop.yml']
end
+require 'mediawiki_selenium/rake_task'
+MediawikiSelenium::RakeTask.new
+
task default: [:test]
desc 'Run all build/tests commands (CI entry point)'
diff --git a/Flow/build/typos.json b/Flow/build/typos.json
index 8a70441e..c7fe6796 100644
--- a/Flow/build/typos.json
+++ b/Flow/build/typos.json
@@ -14,6 +14,7 @@
[ "durring", "during" ],
[ "contian", "contain" ],
[ "occured", "occurred" ],
- [ "inital", "initial" ]
+ [ "inital", "initial" ],
+ [ "desciption", "description" ]
]
}
diff --git a/Flow/composer.json b/Flow/composer.json
index 2672528e..df390751 100644
--- a/Flow/composer.json
+++ b/Flow/composer.json
@@ -2,17 +2,21 @@
"name": "mediawiki/flow",
"description": "Discussion and collaboration system extension for MediaWiki",
"license": "GPL-2.0+",
- "require": {},
- "require-dev": {
- "symfony/dom-crawler": "~2.5",
- "symfony/css-selector": "~2.5"
+ "require": {
+ "pimple/pimple": "3.0.2"
},
"require-dev": {
- "jakub-onderka/php-parallel-lint": "0.9"
+ "symfony/dom-crawler": "~2.5",
+ "symfony/css-selector": "~2.5",
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "mediawiki/mediawiki-codesniffer": "0.12.0"
},
"scripts": {
+ "fix": "phpcbf",
"test": [
- "parallel-lint . --exclude vendor"
+ "parallel-lint . --exclude vendor --exclude node_modules",
+ "phpcs -p -s"
]
}
}
diff --git a/Flow/composer.lock b/Flow/composer.lock
index 02da5678..9e859cc5 100644
--- a/Flow/composer.lock
+++ b/Flow/composer.lock
@@ -1,39 +1,37 @@
{
"_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",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "hash": "430513e3e3fc840fc6d08892687cbc2d",
- "packages": [],
- "packages-dev": [
+ "content-hash": "04ad55ce976855d46724d0ec086aa4d5",
+ "packages": [
{
- "name": "symfony/css-selector",
- "version": "v2.5.6",
- "target-dir": "Symfony/Component/CssSelector",
+ "name": "pimple/pimple",
+ "version": "v3.0.2",
"source": {
"type": "git",
- "url": "https://github.com/symfony/CssSelector.git",
- "reference": "7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc"
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/CssSelector/zipball/7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc",
- "reference": "7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.5-dev"
+ "dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-0": {
- "Symfony\\Component\\CssSelector\\": ""
+ "Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -42,9 +40,276 @@
],
"authors": [
{
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "http://pimple.sensiolabs.org",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ],
+ "time": "2015-09-11T15:10:35+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "jakub-onderka/php-console-color",
+ "version": "v0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JakubOnderka/PHP-Console-Color.git",
+ "reference": "d5deaecff52a0d61ccb613bb3804088da0307191"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/d5deaecff52a0d61ccb613bb3804088da0307191",
+ "reference": "d5deaecff52a0d61ccb613bb3804088da0307191",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "jakub-onderka/php-code-style": "1.0",
+ "jakub-onderka/php-parallel-lint": "1.0",
+ "jakub-onderka/php-var-dump-check": "0.*",
+ "phpunit/phpunit": "~4.3",
+ "squizlabs/php_codesniffer": "1.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "JakubOnderka\\PhpConsoleColor\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jakub Onderka",
+ "email": "jakub.onderka@gmail.com"
+ }
+ ],
+ "time": "2018-09-29T17:23:10+00:00"
+ },
+ {
+ "name": "jakub-onderka/php-console-highlighter",
+ "version": "v0.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git",
+ "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5",
+ "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5",
+ "shasum": ""
+ },
+ "require": {
+ "jakub-onderka/php-console-color": "~0.1",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "jakub-onderka/php-code-style": "~1.0",
+ "jakub-onderka/php-parallel-lint": "~0.5",
+ "jakub-onderka/php-var-dump-check": "~0.1",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "~1.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "JakubOnderka\\PhpConsoleHighlighter": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jakub Onderka",
+ "email": "acci@acci.cz",
+ "homepage": "http://www.acci.cz/"
+ }
+ ],
+ "time": "2015-04-20T18:58:01+00:00"
+ },
+ {
+ "name": "jakub-onderka/php-parallel-lint",
+ "version": "v0.9.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
+ "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+ "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+ "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-2-Clause"
+ ],
+ "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-12-15T10:42:16+00:00"
+ },
+ {
+ "name": "mediawiki/mediawiki-codesniffer",
+ "version": "v0.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wikimedia/mediawiki-tools-codesniffer.git",
+ "reference": "ca7d4d1c54c28e3a25072e6455f4c56ddf47eaf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wikimedia/mediawiki-tools-codesniffer/zipball/ca7d4d1c54c28e3a25072e6455f4c56ddf47eaf8",
+ "reference": "ca7d4d1c54c28e3a25072e6455f4c56ddf47eaf8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">= 5.5.9",
+ "squizlabs/php_codesniffer": "3.0.2"
+ },
+ "require-dev": {
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "phpunit/phpunit": "~4.1"
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "description": "MediaWiki CodeSniffer Standards",
+ "homepage": "https://www.mediawiki.org/wiki/Manual:Coding_conventions/PHP",
+ "keywords": [
+ "codesniffer",
+ "mediawiki"
+ ],
+ "time": "2017-08-30T06:01:51+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+ "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c7594a88ae75401e8f8d0bd4deb8431b39045c51",
+ "reference": "c7594a88ae75401e8f8d0bd4deb8431b39045c51",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "bin": [
+ "bin/phpcs",
+ "bin/phpcbf"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "lead"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "keywords": [
+ "phpcs",
+ "standards"
+ ],
+ "time": "2017-07-18T01:12:32+00:00"
+ },
+ {
+ "name": "symfony/css-selector",
+ "version": "v2.8.46",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/css-selector.git",
+ "reference": "4cca41ebe83cd5b4bd0c1a9f6bdfaec7103f97fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/4cca41ebe83cd5b4bd0c1a9f6bdfaec7103f97fb",
+ "reference": "4cca41ebe83cd5b4bd0c1a9f6bdfaec7103f97fb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\CssSelector\\": ""
},
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
{
"name": "Jean-François Simon",
"email": "jeanfrancois.simon@sensiolabs.com"
@@ -52,32 +317,37 @@
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony CssSelector Component",
- "homepage": "http://symfony.com",
- "time": "2014-10-09 16:00:03"
+ "homepage": "https://symfony.com",
+ "time": "2018-09-08T12:44:02+00:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v2.5.6",
- "target-dir": "Symfony/Component/DomCrawler",
+ "version": "v2.8.46",
"source": {
"type": "git",
- "url": "https://github.com/symfony/DomCrawler.git",
- "reference": "5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e"
+ "url": "https://github.com/symfony/dom-crawler.git",
+ "reference": "ba0b706b5ac1c1afcf7d34507a5a272f51cc7721"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e",
- "reference": "5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ba0b706b5ac1c1afcf7d34507a5a272f51cc7721",
+ "reference": "ba0b706b5ac1c1afcf7d34507a5a272f51cc7721",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
- "symfony/css-selector": "~2.0"
+ "symfony/css-selector": "~2.8|~3.0.0"
},
"suggest": {
"symfony/css-selector": ""
@@ -85,13 +355,68 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.5-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
+ "psr-4": {
"Symfony\\Component\\DomCrawler\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
+ ],
+ "description": "Symfony DomCrawler Component",
+ "homepage": "https://symfony.com",
+ "time": "2018-09-21T12:46:38+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
+ "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.9-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -100,22 +425,88 @@
"authors": [
{
"name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
+ "homepage": "https://symfony.com/contributors"
},
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
}
],
- "description": "Symfony DomCrawler Component",
- "homepage": "http://symfony.com",
- "time": "2014-10-01 05:50:18"
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "time": "2018-08-06T14:22:27+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
+ "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.9-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2018-08-06T14:22:27+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
+ "prefer-lowest": false,
"platform": [],
"platform-dev": []
}
diff --git a/Flow/container.php b/Flow/container.php
index dba21eb1..a63522db 100644
--- a/Flow/container.php
+++ b/Flow/container.php
@@ -10,7 +10,7 @@ if ( defined( 'RUN_MAINTENANCE_IF_MAIN' ) ) {
}
$c['output'] = $GLOBALS['wgOut'];
$c['request'] = $GLOBALS['wgRequest'];
-$c['memcache'] = function( $c ) {
+$c['memcache'] = function ( $c ) {
global $wgFlowUseMemcache, $wgMemc;
if ( $wgFlowUseMemcache ) {
@@ -21,52 +21,62 @@ $c['memcache'] = function( $c ) {
};
$c['cache.version'] = $GLOBALS['wgFlowCacheVersion'];
+// This lets the index handle the initial query from HistoryPager,
+// even when the UI limit is 500. An extra item is requested
+// so we know whether to link the pagination.
+$c['history_index_limit'] = 501;
+
+// 501 * OVERFETCH_FACTOR from HistoryQuery + 1
+// Basically, this is so we can try to fetch enough extra to handle
+// exclude_from_history without retrying.
+$c['board_topic_history_post_index_limit'] = 682;
+
// Flow config
-$c['flow_actions'] = function( $c ) {
+$c['flow_actions'] = function ( $c ) {
global $wgFlowActions;
return new Flow\FlowActions( $wgFlowActions );
};
// Always returns the correct database for flow storage
-$c['db.factory'] = function( $c ) {
+$c['db.factory'] = function ( $c ) {
global $wgFlowDefaultWikiDb, $wgFlowCluster;
return new Flow\DbFactory( $wgFlowDefaultWikiDb, $wgFlowCluster );
};
// Database Access Layer external from main implementation
-$c['repository.tree'] = function( $c ) {
+$c['repository.tree'] = function ( $c ) {
return new Flow\Repository\TreeRepository(
$c['db.factory'],
- $c['memcache.local_buffered']
+ $c['flowcache']
);
};
-$c['url_generator'] = function( $c ) {
+$c['url_generator'] = function ( $c ) {
return new Flow\UrlGenerator(
$c['storage.workflow.mapper']
);
};
-$c['watched_items'] = function( $c ) {
+$c['watched_items'] = function ( $c ) {
return new Flow\WatchedTopicItems(
$c['user'],
wfGetDB( DB_SLAVE, 'watchlist' )
);
};
-$c['link_batch'] = function() {
+$c['link_batch'] = function () {
return new LinkBatch;
};
-$c['wiki_link_fixer'] = function( $c ) {
+$c['wiki_link_fixer'] = function ( $c ) {
return new Flow\Parsoid\Fixer\WikiLinkFixer( $c['link_batch'] );
};
-$c['bad_image_remover'] = function( $c ) {
+$c['bad_image_remover'] = function ( $c ) {
return new Flow\Parsoid\Fixer\BadImageRemover( 'wfIsBadImage' );
};
-$c['base_href_fixer'] = function( $c ) {
+$c['base_href_fixer'] = function ( $c ) {
global $wgArticlePath;
return new Flow\Parsoid\Fixer\BaseHrefFixer( $wgArticlePath );
@@ -76,7 +86,7 @@ $c['ext_link_fixer'] = function ( $c ) {
return new Flow\Parsoid\Fixer\ExtLinkFixer();
};
-$c['content_fixer'] = function( $c ) {
+$c['content_fixer'] = function ( $c ) {
return new Flow\Parsoid\ContentFixer(
$c['wiki_link_fixer'],
$c['bad_image_remover'],
@@ -85,12 +95,12 @@ $c['content_fixer'] = function( $c ) {
);
};
-$c['permissions'] = function( $c ) {
+$c['permissions'] = function ( $c ) {
return new Flow\RevisionActionPermissions( $c['flow_actions'], $c['user'] );
};
$c['lightncandy.template_dir'] = __DIR__ . '/handlebars';
-$c['lightncandy'] = function( $c ) {
+$c['lightncandy'] = function ( $c ) {
global $wgFlowServerCompileTemplates;
return new Flow\TemplateHelper(
@@ -99,7 +109,7 @@ $c['lightncandy'] = function( $c ) {
);
};
-$c['templating'] = function( $c ) {
+$c['templating'] = function ( $c ) {
return new Flow\Templating(
$c['repository.username'],
$c['url_generator'],
@@ -110,137 +120,121 @@ $c['templating'] = function( $c ) {
};
// New Storage Impl
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Data\Mapper\BasicObjectMapper;
use Flow\Data\Mapper\CachingObjectMapper;
use Flow\Data\Storage\BasicDbStorage;
use Flow\Data\Storage\TopicListStorage;
-use Flow\Data\Storage\TopicListLastUpdatedStorage;
+use Flow\Data\Storage\PostRevisionBoardHistoryStorage;
use Flow\Data\Storage\PostRevisionStorage;
use Flow\Data\Storage\HeaderRevisionStorage;
+use Flow\Data\Storage\PostSummaryRevisionBoardHistoryStorage;
use Flow\Data\Storage\PostSummaryRevisionStorage;
-use Flow\Data\Storage\TopicHistoryStorage;
use Flow\Data\Index\UniqueFeatureIndex;
use Flow\Data\Index\TopKIndex;
-use Flow\Data\Index\TopicListTopKIndex;
-use Flow\Data\Index\TopicHistoryIndex;
-use Flow\Data\Storage\BoardHistoryStorage;
-use Flow\Data\Index\BoardHistoryIndex;
+use Flow\Data\Storage\PostRevisionTopicHistoryStorage;
+use Flow\Data\Index\PostRevisionBoardHistoryIndex;
+use Flow\Data\Index\PostRevisionTopicHistoryIndex;
+use Flow\Data\Index\PostSummaryRevisionBoardHistoryIndex;
use Flow\Data\ObjectManager;
use Flow\Data\ObjectLocator;
-use Flow\Model\Header;
-use Flow\Model\PostRevision;
-use Flow\Model\PostSummary;
+use MediaWiki\MediaWikiServices;
-// This currently never clears $this->bag, which makes it unusuable for long-running batch.
-// Use 'memcache.non_local_buffered' for those instead.
-$c['memcache.local_buffered'] = function( $c ) {
- global $wgFlowCacheTime;
-
- // This is the real buffered cached that will allow transactional-like cache.
- // It also caches all reads in-memory.
- $bufferedCache = new Flow\Data\BagOStuff\LocalBufferedBagOStuff( $c['memcache'] );
- // This is Flow's wrapper around it, to have a fixed cache expiry time
- return new BufferedCache( $bufferedCache, $wgFlowCacheTime );
+$c['wancache'] = function ( $c ) {
+ return MediaWikiServices::getInstance()->getMainWANObjectCache();
};
-$c['memcache.non_local_buffered'] = function( $c ) {
+$c['ttl.default'] = function ( $c ) {
global $wgFlowCacheTime;
+ return $wgFlowCacheTime;
+};
- // This is the real buffered cached that will allow transactional-like cache
- $bufferedCache = new Flow\Data\BagOStuff\BufferedBagOStuff( $c['memcache'] );
-
- // This is Flow's wrapper around it, to have a fixed cache expiry time
- return new BufferedCache( $bufferedCache, $wgFlowCacheTime );
+$c['flowcache'] = function ( $c ) {
+ return new FlowObjectCache( $c['wancache'], $c['db.factory'], $c['ttl.default'] );
};
// Batched username loader
-$c['repository.username.query'] = function( $c ) {
+$c['repository.username.query'] = function ( $c ) {
return new Flow\Repository\UserName\TwoStepUserNameQuery(
$c['db.factory']
);
};
-$c['repository.username'] = function( $c ) {
+$c['repository.username'] = function ( $c ) {
return new Flow\Repository\UserNameBatch(
$c['repository.username.query']
);
};
-$c['collection.cache'] = function( $c ) {
+$c['collection.cache'] = function ( $c ) {
return new Flow\Collection\CollectionCache();
};
// Individual workflow instances
$c['storage.workflow.class'] = 'Flow\Model\Workflow';
$c['storage.workflow.table'] = 'flow_workflow';
-$c['storage.workflow.primary_key'] = array( 'workflow_id' );
-$c['storage.workflow.mapper'] = function( $c ) {
+$c['storage.workflow.primary_key'] = [ 'workflow_id' ];
+$c['storage.workflow.mapper'] = function ( $c ) {
return CachingObjectMapper::model(
$c['storage.workflow.class'],
$c['storage.workflow.primary_key']
);
};
-$c['storage.workflow.backend'] = function( $c ) {
+$c['storage.workflow.backend'] = function ( $c ) {
return new BasicDbStorage(
$c['db.factory'],
$c['storage.workflow.table'],
$c['storage.workflow.primary_key']
);
};
-$c['storage.workflow.indexes.primary'] = function( $c ) {
+$c['storage.workflow.indexes.primary'] = function ( $c ) {
return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.workflow.backend'],
$c['storage.workflow.mapper'],
'flow_workflow:v2:pk',
$c['storage.workflow.primary_key']
);
};
-$c['storage.workflow.indexes.title_lookup'] = function( $c ) {
+$c['storage.workflow.indexes.title_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.workflow.backend'],
$c['storage.workflow.mapper'],
'flow_workflow:title:v2:',
- array( 'workflow_wiki', 'workflow_namespace', 'workflow_title_text', 'workflow_type' ),
- array(
+ [ 'workflow_wiki', 'workflow_namespace', 'workflow_title_text', 'workflow_type' ],
+ [
'shallow' => $c['storage.workflow.indexes.primary'],
'limit' => 1,
'sort' => 'workflow_id'
- )
+ ]
);
};
-$c['storage.workflow.indexes'] = function( $c ) {
- return array(
+$c['storage.workflow.indexes'] = function ( $c ) {
+ return [
$c['storage.workflow.indexes.primary'],
$c['storage.workflow.indexes.title_lookup']
- );
+ ];
};
-$c['storage.workflow.listeners.topiclist'] = function( $c ) {
+$c['storage.workflow.listeners.topiclist'] = function ( $c ) {
return new Flow\Data\Listener\WorkflowTopicListListener(
$c['storage.topic_list'],
$c['storage.topic_list.indexes.last_updated']
);
};
-$c['storage.workflow.listeners'] = function( $c ) {
- return array(
+$c['storage.workflow.listeners'] = function ( $c ) {
+ return [
'listener.topicpagecreation' => $c['listener.topicpagecreation'],
-
- // The storage.topic_list.indexes are primarily for TopicListEntry insertions, but they
- // also listen for discussion workflow insertions so they can initialize for new boards.
- 'storage.topic_list.indexes.reverse_lookup' => $c['storage.topic_list.indexes.reverse_lookup'],
- 'storage.topic_list.indexes.last_updated' => $c['storage.topic_list.indexes.last_updated'],
-
'storage.workflow.listeners.topiclist' => $c['storage.workflow.listeners.topiclist'],
- );
+ ];
};
-$c['storage.workflow'] = function( $c ) {
+$c['storage.workflow'] = function ( $c ) {
return new ObjectManager(
$c['storage.workflow.mapper'],
$c['storage.workflow.backend'],
+ $c['db.factory'],
$c['storage.workflow.indexes'],
$c['storage.workflow.listeners']
);
};
-$c['listener.recentchanges'] = function( $c ) {
+$c['listener.recentchanges'] = function ( $c ) {
// Recent change listeners go out to external services and
// as such must only be run after the transaction is commited.
return new Flow\Data\Listener\DeferredInsertLifecycleHandler(
@@ -253,225 +247,243 @@ $c['listener.recentchanges'] = function( $c ) {
)
);
};
-$c['listener.topicpagecreation'] = function( $c ) {
- global $wgFlowDefaultWorkflow;
-
+$c['listener.topicpagecreation'] = function ( $c ) {
return new Flow\Data\Listener\TopicPageCreationListener(
$c['occupation_controller'],
+ $c['deferred_queue']
+ );
+};
+$c['listeners.notification'] = function ( $c ) {
+ // Defer notifications triggering till end of request so we could get
+ // article_id in the case of a new topic
+ return new Flow\Data\Listener\DeferredInsertLifecycleHandler(
$c['deferred_queue'],
- $wgFlowDefaultWorkflow
+ new Flow\Data\Listener\NotificationListener(
+ $c['controller.notification']
+ )
+ );
+};
+
+$c['storage.post_board_history.backend'] = function ( $c ) {
+ return new PostRevisionBoardHistoryStorage( $c['db.factory'] );
+};
+$c['storage.post_board_history.indexes.primary'] = function ( $c ) {
+ return new PostRevisionBoardHistoryIndex(
+ $c['flowcache'],
+ // backend storage
+ $c['storage.post_board_history.backend'],
+ // data mapper
+ $c['storage.post.mapper'],
+ // key prefix
+ 'flow_revision:topic_list_history:post:v2',
+ // primary key
+ [ 'topic_list_id' ],
+ // index options
+ [
+ 'limit' => $c['board_topic_history_post_index_limit'],
+ 'sort' => 'rev_id',
+ 'order' => 'DESC'
+ ],
+ $c['storage.topic_list']
+ );
+};
+
+$c['storage.post_board_history.indexes'] = function ( $c ) {
+ return [ $c['storage.post_board_history.indexes.primary'] ];
+};
+
+$c['storage.post_board_history'] = function ( $c ) {
+ return new ObjectLocator(
+ $c['storage.post.mapper'],
+ $c['storage.post_board_history.backend'],
+ $c['db.factory'],
+ $c['storage.post_board_history.indexes']
);
};
-$c['storage.board_history.backend'] = function( $c ) {
- return new BoardHistoryStorage( $c['db.factory'] );
+$c['storage.post_summary_board_history.backend'] = function ( $c ) {
+ return new PostSummaryRevisionBoardHistoryStorage( $c['db.factory'] );
};
-$c['storage.board_history.indexes.primary'] = function( $c ) {
- return new BoardHistoryIndex(
- $c['memcache.local_buffered'],
+$c['storage.post_summary_board_history.indexes.primary'] = function ( $c ) {
+ return new PostSummaryRevisionBoardHistoryIndex(
+ $c['flowcache'],
// backend storage
- $c['storage.board_history.backend'],
+ $c['storage.post_summary_board_history.backend'],
// data mapper
- $c['storage.board_history.mapper'],
+ $c['storage.post_summary.mapper'],
// key prefix
- 'flow_revision:topic_list_history',
+ 'flow_revision:topic_list_history:post_summary:v2',
// primary key
- array( 'topic_list_id' ),
+ [ 'topic_list_id' ],
// index options
- array(
- 'limit' => 500,
+ [
+ 'limit' => $c['history_index_limit'],
'sort' => 'rev_id',
'order' => 'DESC'
- ),
+ ],
$c['storage.topic_list']
);
};
-$c['storage.board_history.mapper'] = function( $c ) {
- return new BasicObjectMapper(
- function( $rev ) use( $c ) {
- if ( $rev instanceof PostRevision ) {
- return $c['storage.post.mapper']->toStorageRow( $rev );
- } elseif ( $rev instanceof Header ) {
- return $c['storage.header.mapper']->toStorageRow( $rev );
- } elseif ( $rev instanceof PostSummary ) {
- return $c['storage.post_summary.mapper']->toStorageRow( $rev );
- } else {
- throw new \Flow\Exception\InvalidDataException( 'Invalid class for board history entry: ' . get_class( $rev ), 'fail-load-data' );
- }
- },
- function( array $row, $obj = null ) use( $c ) {
- if ( $row['rev_type'] === 'header' ) {
- return $c['storage.header.mapper']->fromStorageRow( $row, $obj );
- } elseif ( $row['rev_type'] === 'post' ) {
- return $c['storage.post.mapper']->fromStorageRow( $row, $obj );
- } elseif ( $row['rev_type'] === 'post-summary' ) {
- return $c['storage.post_summary.mapper']->fromStorageRow( $row, $obj );
- } else {
- throw new \Flow\Exception\InvalidDataException( 'Invalid rev_type for board history entry: ' . $row['rev_type'], 'fail-load-data' );
- }
- }
- );
-};
-$c['storage.board_history.indexes'] = function( $c ) {
- return array( $c['storage.board_history.indexes.primary'] );
-};
-$c['storage.board_history'] = function( $c ) {
+
+$c['storage.post_summary_board_history.indexes'] = function ( $c ) {
+ return [ $c['storage.post_summary_board_history.indexes.primary'] ];
+};
+
+$c['storage.post_summary_board_history'] = function ( $c ) {
return new ObjectLocator(
- $c['storage.board_history.mapper'],
- $c['storage.board_history.backend'],
- $c['storage.board_history.indexes']
+ $c['storage.post_summary.mapper'],
+ $c['storage.post_summary_board_history.backend'],
+ $c['db.factory'],
+ $c['storage.post_summary_board_history.indexes']
);
};
-$c['storage.header.listeners.username'] = function( $c ) {
+$c['storage.header.listeners.username'] = function ( $c ) {
return new Flow\Data\Listener\UserNameListener(
$c['repository.username'],
- array(
+ [
'rev_user_id' => 'rev_user_wiki',
'rev_mod_user_id' => 'rev_mod_user_wiki',
'rev_edit_user_id' => 'rev_edit_user_wiki'
- )
+ ]
);
};
-$c['storage.header.listeners'] = function( $c ) {
- return array(
+$c['storage.header.listeners'] = function ( $c ) {
+ return [
'reference.recorder' => $c['reference.recorder'],
- 'storage.board_history.indexes.primary' => $c['storage.board_history.indexes.primary'],
'storage.header.listeners.username' => $c['storage.header.listeners.username'],
+ 'listeners.notification' => $c['listeners.notification'],
'listener.recentchanges' => $c['listener.recentchanges'],
'listener.editcount' => $c['listener.editcount'],
- );
+ ];
};
-$c['storage.header.primary_key'] = array( 'rev_id' );
-$c['storage.header.mapper'] = function( $c ) {
- return CachingObjectMapper::model( 'Flow\\Model\\Header', array( 'rev_id' ) );
+$c['storage.header.primary_key'] = [ 'rev_id' ];
+$c['storage.header.mapper'] = function ( $c ) {
+ return CachingObjectMapper::model( 'Flow\\Model\\Header', [ 'rev_id' ] );
};
-$c['storage.header.backend'] = function( $c ) {
+$c['storage.header.backend'] = function ( $c ) {
global $wgFlowExternalStore;
return new HeaderRevisionStorage(
$c['db.factory'],
$wgFlowExternalStore
);
-
};
-$c['storage.header.indexes.primary'] = function( $c ) {
+$c['storage.header.indexes.primary'] = function ( $c ) {
return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.header.backend'],
$c['storage.header.mapper'],
'flow_header:v2:pk',
$c['storage.header.primary_key']
);
};
-$c['storage.header.indexes.topic_lookup'] = function( $c ) {
+$c['storage.header.indexes.header_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.header.backend'],
$c['storage.header.mapper'],
- 'flow_header:workflow',
- array( 'rev_type_id' ),
- array(
- 'limit' => 100,
+ 'flow_header:workflow:v3',
+ [ 'rev_type_id' ],
+ [
+ 'limit' => $c['history_index_limit'],
'sort' => 'rev_id',
'order' => 'DESC',
'shallow' => $c['storage.header.indexes.primary'],
- 'create' => function( array $row ) {
+ 'create' => function ( array $row ) {
return $row['rev_parent_id'] === null;
},
- )
+ ]
);
};
-$c['storage.header.indexes'] = function( $c ) {
- return array(
+$c['storage.header.indexes'] = function ( $c ) {
+ return [
$c['storage.header.indexes.primary'],
- $c['storage.header.indexes.topic_lookup']
- );
+ $c['storage.header.indexes.header_lookup']
+ ];
};
-$c['storage.header'] = function( $c ) {
+$c['storage.header'] = function ( $c ) {
return new ObjectManager(
$c['storage.header.mapper'],
$c['storage.header.backend'],
+ $c['db.factory'],
$c['storage.header.indexes'],
$c['storage.header.listeners']
);
};
$c['storage.post_summary.class'] = 'Flow\Model\PostSummary';
-$c['storage.post_summary.primary_key'] = array( 'rev_id' );
-$c['storage.post_summary.mapper'] = function( $c ) {
+$c['storage.post_summary.primary_key'] = [ 'rev_id' ];
+$c['storage.post_summary.mapper'] = function ( $c ) {
return CachingObjectMapper::model(
$c['storage.post_summary.class'],
$c['storage.post_summary.primary_key']
);
};
-$c['storage.post_summary.listeners.username'] = function( $c ) {
+$c['storage.post_summary.listeners.username'] = function ( $c ) {
return new Flow\Data\Listener\UserNameListener(
$c['repository.username'],
- array(
+ [
'rev_user_id' => 'rev_user_wiki',
'rev_mod_user_id' => 'rev_mod_user_wiki',
'rev_edit_user_id' => 'rev_edit_user_wiki'
- )
+ ]
);
};
-$c['storage.post_summary.listeners'] = function( $c ) {
- return array(
+$c['storage.post_summary.listeners'] = function ( $c ) {
+ return [
'listener.recentchanges' => $c['listener.recentchanges'],
'storage.post_summary.listeners.username' => $c['storage.post_summary.listeners.username'],
- 'storage.board_history.indexes.primary' => $c['storage.board_history.indexes.primary'],
+ 'listeners.notification' => $c['listeners.notification'],
+ 'storage.post_summary_board_history.indexes.primary' => $c['storage.post_summary_board_history.indexes.primary'],
'listener.editcount' => $c['listener.editcount'],
- // topic history -- to keep a history by topic we have to know what topic every post
- // belongs to, not just its parent. TopicHistoryIndex is a slight tweak to TopKIndex
- // using TreeRepository for extra information and stuffing it into topic_root while indexing
- 'storage.topic_history.indexes.primary' => $c['storage.topic_history.indexes.primary'],
'reference.recorder' => $c['reference.recorder'],
- );
+ ];
};
-$c['storage.post_summary.backend'] = function( $c ) {
+$c['storage.post_summary.backend'] = function ( $c ) {
global $wgFlowExternalStore;
return new PostSummaryRevisionStorage(
$c['db.factory'],
$wgFlowExternalStore
);
};
-$c['storage.post_summary.indexes.primary'] = function( $c ) {
+$c['storage.post_summary.indexes.primary'] = function ( $c ) {
return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.post_summary.backend'],
$c['storage.post_summary.mapper'],
'flow_post_summary:v2:pk',
$c['storage.post_summary.primary_key']
);
};
-$c['storage.post_summary.indexes.topic_lookup'] = function( $c ) {
+$c['storage.post_summary.indexes.topic_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.post_summary.backend'],
$c['storage.post_summary.mapper'],
- 'flow_post_summary:workflow',
- array( 'rev_type_id' ),
- array(
- 'limit' => 100,
+ 'flow_post_summary:workflow:v3',
+ [ 'rev_type_id' ],
+ [
+ 'limit' => $c['history_index_limit'],
'sort' => 'rev_id',
'order' => 'DESC',
'shallow' => $c['storage.post_summary.indexes.primary'],
- 'create' => function( array $row ) {
+ 'create' => function ( array $row ) {
return $row['rev_parent_id'] === null;
},
- )
+ ]
);
};
-$c['storage.post_summary.indexes'] = function( $c ) {
- return array(
+$c['storage.post_summary.indexes'] = function ( $c ) {
+ return [
$c['storage.post_summary.indexes.primary'],
$c['storage.post_summary.indexes.topic_lookup'],
- $c['storage.topic_history.indexes.topic_lookup']
- );
+ ];
};
-$c['storage.post_summary'] = function( $c ) {
+$c['storage.post_summary'] = function ( $c ) {
return new ObjectManager(
$c['storage.post_summary.mapper'],
$c['storage.post_summary.backend'],
+ $c['db.factory'],
$c['storage.post_summary.indexes'],
$c['storage.post_summary.listeners']
);
@@ -479,21 +491,16 @@ $c['storage.post_summary'] = function( $c ) {
$c['storage.topic_list.class'] = 'Flow\Model\TopicListEntry';
$c['storage.topic_list.table'] = 'flow_topic_list';
-$c['storage.topic_list.primary_key'] = array( 'topic_list_id', 'topic_id' );
-$c['storage.topic_list.indexes.last_updated.backend'] = function( $c ) {
- return new TopicListLastUpdatedStorage(
- $c['db.factory'],
- $c['storage.topic_list.table'],
- $c['storage.topic_list.primary_key']
- );
-};
-$c['storage.topic_list.mapper'] = function( $c ) {
- return CachingObjectMapper::model(
+$c['storage.topic_list.primary_key'] = [ 'topic_list_id', 'topic_id' ];
+$c['storage.topic_list.mapper'] = function ( $c ) {
+ // Must be BasicObjectMapper, due to variance in when
+ // we have workflow_last_update_timestamp
+ return BasicObjectMapper::model(
$c['storage.topic_list.class'],
$c['storage.topic_list.primary_key']
);
};
-$c['storage.topic_list.backend'] = function( $c ) {
+$c['storage.topic_list.backend'] = function ( $c ) {
return new TopicListStorage(
// factory and table
$c['db.factory'],
@@ -502,65 +509,66 @@ $c['storage.topic_list.backend'] = function( $c ) {
);
};
// Lookup from topic_id to its owning board id
-$c['storage.topic_list.indexes.primary'] = function( $c ) {
+$c['storage.topic_list.indexes.primary'] = function ( $c ) {
return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.topic_list.backend'],
$c['storage.topic_list.mapper'],
'flow_topic_list:topic',
- array( 'topic_id' )
+ [ 'topic_id' ]
);
};
// Lookup from board to contained topics
/// In reverse order by topic_id
-$c['storage.topic_list.indexes.reverse_lookup'] = function( $c ) {
- return new TopicListTopKIndex(
- $c['memcache.local_buffered'],
+$c['storage.topic_list.indexes.reverse_lookup'] = function ( $c ) {
+ return new TopKIndex(
+ $c['flowcache'],
$c['storage.topic_list.backend'],
$c['storage.topic_list.mapper'],
'flow_topic_list:list',
- array( 'topic_list_id' ),
- array( 'sort' => 'topic_id' )
+ [ 'topic_list_id' ],
+ [ 'sort' => 'topic_id' ]
);
};
/// In reverse order by topic last_updated
-$c['storage.topic_list.indexes.last_updated'] = function( $c ) {
- return new TopicListTopKIndex(
- $c['memcache.local_buffered'],
- $c['storage.topic_list.indexes.last_updated.backend'],
+$c['storage.topic_list.indexes.last_updated'] = function ( $c ) {
+ return new TopKIndex(
+ $c['flowcache'],
+ $c['storage.topic_list.backend'],
$c['storage.topic_list.mapper'],
'flow_topic_list_last_updated:list',
- array( 'topic_list_id' ),
- array(
+ [ 'topic_list_id' ],
+ [
'sort' => 'workflow_last_update_timestamp',
'order' => 'desc'
- )
+ ]
);
};
-$c['storage.topic_list.indexes'] = function( $c ) {
- return array(
+$c['storage.topic_list.indexes'] = function ( $c ) {
+ return [
$c['storage.topic_list.indexes.primary'],
$c['storage.topic_list.indexes.reverse_lookup'],
$c['storage.topic_list.indexes.last_updated'],
- );
+ ];
};
-$c['storage.topic_list'] = function( $c ) {
+$c['storage.topic_list'] = function ( $c ) {
return new ObjectManager(
$c['storage.topic_list.mapper'],
$c['storage.topic_list.backend'],
+ $c['db.factory'],
$c['storage.topic_list.indexes']
);
};
$c['storage.post.class'] = 'Flow\Model\PostRevision';
-$c['storage.post.primary_key'] = array( 'rev_id' );
-$c['storage.post.mapper'] = function( $c ) {
+$c['storage.post.primary_key'] = [ 'rev_id' ];
+$c['storage.post.mapper'] = function ( $c ) {
return CachingObjectMapper::model(
$c['storage.post.class'],
$c['storage.post.primary_key']
);
};
-$c['storage.post.backend'] = function( $c ) {
+$c['storage.post.backend'] = function ( $c ) {
global $wgFlowExternalStore;
return new PostRevisionStorage(
$c['db.factory'],
@@ -568,59 +576,44 @@ $c['storage.post.backend'] = function( $c ) {
$c['repository.tree']
);
};
-$c['storage.post.listeners.moderation_logging'] = function( $c ) {
+$c['storage.post.listeners.moderation_logging'] = function ( $c ) {
return new Flow\Data\Listener\ModerationLoggingListener(
$c['logger.moderation']
);
};
-$c['storage.post.listeners.username'] = function( $c ) {
+$c['storage.post.listeners.username'] = function ( $c ) {
return new Flow\Data\Listener\UserNameListener(
$c['repository.username'],
- array(
+ [
'rev_user_id' => 'rev_user_wiki',
'rev_mod_user_id' => 'rev_mod_user_wiki',
'rev_edit_user_id' => 'rev_edit_user_wiki',
'tree_orig_user_id' => 'tree_orig_user_wiki'
- )
+ ]
);
};
-$c['storage.post.listeners.watch_topic'] = function( $c ) {
+$c['storage.post.listeners.watch_topic'] = function ( $c ) {
// Auto-subscribe users to the topic after performing specific actions
return new Flow\Data\Listener\ImmediateWatchTopicListener(
$c['watched_items']
);
};
-$c['storage.post.listeners.notification'] = function( $c ) {
- // Defer notifications triggering till end of request so we could get
- // article_id in the case of a new topic, this will need support of
- // adding deferred update when running deferred update
- return new Flow\Data\Listener\DeferredInsertLifecycleHandler(
- $c['deferred_queue'],
- new Flow\Data\Listener\NotificationListener(
- $c['controller.notification']
- )
- );
-};
-$c['storage.post.listeners'] = function( $c ) {
- return array(
+$c['storage.post.listeners'] = function ( $c ) {
+ return [
'reference.recorder' => $c['reference.recorder'],
'collection.cache' => $c['collection.cache'],
'storage.post.listeners.username' => $c['storage.post.listeners.username'],
'storage.post.listeners.watch_topic' => $c['storage.post.listeners.watch_topic'],
- 'storage.post.listeners.notification' => $c['storage.post.listeners.notification'],
+ 'listeners.notification' => $c['listeners.notification'],
'storage.post.listeners.moderation_logging' => $c['storage.post.listeners.moderation_logging'],
'listener.recentchanges' => $c['listener.recentchanges'],
'listener.editcount' => $c['listener.editcount'],
- // topic history -- to keep a history by topic we have to know what topic every post
- // belongs to, not just its parent. TopicHistoryIndex is a slight tweak to TopKIndex
- // using TreeRepository for extra information and stuffing it into topic_root while indexing
- 'storage.board_history.indexes.primary' => $c['storage.board_history.indexes.primary'],
- 'storage.topic_history.indexes.primary' => $c['storage.topic_history.indexes.primary'],
- );
+ 'storage.post_board_history.indexes.primary' => $c['storage.post_board_history.indexes.primary'],
+ ];
};
-$c['storage.post.indexes.primary'] = function( $c ) {
+$c['storage.post.indexes.primary'] = function ( $c ) {
return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.post.backend'],
$c['storage.post.mapper'],
'flow_revision:v4:pk',
@@ -628,71 +621,63 @@ $c['storage.post.indexes.primary'] = function( $c ) {
);
};
// Each bucket holds a list of revisions in a single post
-$c['storage.post.indexes.post_lookup'] = function( $c ) {
+$c['storage.post.indexes.post_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.post.backend'],
$c['storage.post.mapper'],
'flow_revision:descendant',
- array( 'rev_type_id' ),
- array(
+ [ 'rev_type_id' ],
+ [
'limit' => 100,
'sort' => 'rev_id',
'order' => 'DESC',
'shallow' => $c['storage.post.indexes.primary'],
- 'create' => function( array $row ) {
+ 'create' => function ( array $row ) {
// return true to create instead of merge index
return $row['rev_parent_id'] === null;
},
- )
+ ]
);
};
-$c['storage.post.indexes'] = function( $c ) {
- return array(
+$c['storage.post.indexes'] = function ( $c ) {
+ return [
$c['storage.post.indexes.primary'],
$c['storage.post.indexes.post_lookup'],
- $c['storage.topic_history.indexes.topic_lookup']
- );
+ $c['storage.post_topic_history.indexes.topic_lookup']
+ ];
};
-$c['storage.post'] = function( $c ) {
+$c['storage.post'] = function ( $c ) {
return new ObjectManager(
$c['storage.post.mapper'],
$c['storage.post.backend'],
+ $c['db.factory'],
$c['storage.post.indexes'],
$c['storage.post.listeners']
);
};
-$c['storage.topic_history.primary_key'] = array( 'rev_id' );
-$c['storage.topic_history.backend'] = function( $c ) {
- return new TopicHistoryStorage(
+
+$c['storage.post_topic_history.backend'] = function ( $c ) {
+ return new PostRevisionTopicHistoryStorage(
$c['storage.post.backend'],
- $c['storage.post_summary.backend'],
$c['repository.tree']
);
};
-$c['storage.topic_history.indexes.primary'] = function( $c ) {
- return new UniqueFeatureIndex(
- $c['memcache.local_buffered'],
- $c['storage.topic_history.backend'],
- $c['storage.topic_history.mapper'],
- 'flow_revision:v4:pk',
- $c['storage.topic_history.primary_key']
- );
-};
-$c['storage.topic_history.indexes.topic_lookup'] = function( $c ) {
- return new TopicHistoryIndex(
- $c['memcache.local_buffered'],
- $c['storage.topic_history.backend'],
- $c['storage.topic_history.mapper'],
- $c['repository.tree'],
- 'flow_revision:topic:v2',
- array( 'topic_root_id' ),
- array(
- 'limit' => 500,
+
+$c['storage.post_topic_history.indexes.topic_lookup'] = function ( $c ) {
+ return new PostRevisionTopicHistoryIndex(
+ $c['flowcache'],
+ $c['storage.post_topic_history.backend'],
+ $c['storage.post.mapper'],
+ 'flow_revision:topic_history:post:v2',
+ [ 'topic_root_id' ],
+ [
+ 'limit' => $c['board_topic_history_post_index_limit'],
'sort' => 'rev_id',
'order' => 'DESC',
- 'shallow' => $c['storage.topic_history.indexes.primary'],
- 'create' => function( array $row ) {
+ // Why does topic history have a shallow compactor, but not board history?
+ 'shallow' => $c['storage.post.indexes.primary'],
+ 'create' => function ( array $row ) {
// only create new indexes for new topics, so it has to be
// of type 'post' and have no parent post & revision
if ( $row['rev_type'] !== 'post' ) {
@@ -700,46 +685,27 @@ $c['storage.topic_history.indexes.topic_lookup'] = function( $c ) {
}
return $row['tree_parent_id'] === null && $row['rev_parent_id'] === null;
},
- )
+ ]
);
};
-$c['storage.topic_history.indexes'] = function( $c ) {
- return array(
- $c['storage.topic_history.indexes.primary'],
- $c['storage.topic_history.indexes.topic_lookup'],
- );
-};
-$c['storage.topic_history.mapper'] = function( $c ) {
- return new BasicObjectMapper(
- function( $rev ) use( $c ) {
- if ( $rev instanceof PostRevision ) {
- return $c['storage.post.mapper']->toStorageRow( $rev );
- } elseif ( $rev instanceof PostSummary ) {
- return $c['storage.post_summary.mapper']->toStorageRow( $rev );
- } else {
- throw new \Flow\Exception\InvalidDataException( 'Invalid class for board history entry: ' . get_class( $rev ), 'fail-load-data' );
- }
- },
- function( array $row, $obj = null ) use( $c ) {
- if ( $row['rev_type'] === 'post' ) {
- return $c['storage.post.mapper']->fromStorageRow( $row, $obj );
- } elseif ( $row['rev_type'] === 'post-summary' ) {
- return $c['storage.post_summary.mapper']->fromStorageRow( $row, $obj );
- } else {
- throw new \Flow\Exception\InvalidDataException( 'Invalid rev_type for board history entry: ' . $row['rev_type'], 'fail-load-data' );
- }
- }
- );
-};
-$c['storage.topic_history'] = function( $c ) {
+
+$c['storage.post_topic_history.indexes'] = function ( $c ) {
+ return [
+ $c['storage.post_topic_history.indexes.topic_lookup'],
+ ];
+};
+
+$c['storage.post_topic_history'] = function ( $c ) {
return new ObjectLocator(
- $c['storage.topic_history.mapper'],
- $c['storage.topic_history.backend'],
- $c['storage.topic_history.indexes']
+ $c['storage.post.mapper'],
+ $c['storage.post_topic_history.backend'],
+ $c['db.factory'],
+ $c['storage.post_topic_history.indexes']
);
};
-$c['storage.manager_list'] = function( $c ) {
- return array(
+
+$c['storage.manager_list'] = function ( $c ) {
+ return [
'Flow\\Model\\Workflow' => 'storage.workflow',
'Workflow' => 'storage.workflow',
@@ -758,24 +724,26 @@ $c['storage.manager_list'] = function( $c ) {
'Header' => 'storage.header',
'header' => 'storage.header',
- 'BoardHistoryEntry' => 'storage.board_history',
+ 'PostRevisionBoardHistoryEntry' => 'storage.post_board_history',
+
+ 'PostSummaryBoardHistoryEntry' => 'storage.post_summary_board_history',
- 'TopicHistoryEntry' => 'storage.topic_history',
+ 'PostRevisionTopicHistoryEntry' => 'storage.post_topic_history',
'Flow\\Model\\WikiReference' => 'storage.wiki_reference',
'WikiReference' => 'storage.wiki_reference',
'Flow\\Model\\URLReference' => 'storage.url_reference',
'URLReference' => 'storage.url_reference',
- );
+ ];
};
-$c['storage'] = function( $c ) {
+$c['storage'] = function ( $c ) {
return new \Flow\Data\ManagerGroup(
$c,
$c['storage.manager_list']
);
};
-$c['loader.root_post'] = function( $c ) {
+$c['loader.root_post'] = function ( $c ) {
return new \Flow\Repository\RootPostLoader(
$c['storage'],
$c['repository.tree']
@@ -784,33 +752,28 @@ $c['loader.root_post'] = function( $c ) {
// Queue of callbacks to run by DeferredUpdates, but only
// on successfull commit
-$c['deferred_queue'] = function( $c ) {
+$c['deferred_queue'] = function ( $c ) {
return new SplQueue;
};
-$c['submission_handler'] = function( $c ) {
+$c['submission_handler'] = function ( $c ) {
return new Flow\SubmissionHandler(
$c['storage'],
$c['db.factory'],
- $c['memcache.local_buffered'],
$c['deferred_queue']
);
};
-$c['factory.block'] = function( $c ) {
+$c['factory.block'] = function ( $c ) {
return new Flow\BlockFactory(
$c['storage'],
- $c['loader.root_post'],
- $c['flow_actions']
+ $c['loader.root_post']
);
};
-$c['factory.loader.workflow'] = function( $c ) {
- global $wgFlowDefaultWorkflow;
-
+$c['factory.loader.workflow'] = function ( $c ) {
return new Flow\WorkflowLoaderFactory(
$c['storage'],
$c['factory.block'],
- $c['submission_handler'],
- $wgFlowDefaultWorkflow
+ $c['submission_handler']
);
};
// Initialized in FlowHooks to facilitate only loading the flow container
@@ -818,9 +781,9 @@ $c['factory.loader.workflow'] = function( $c ) {
// must always happen before calling flow code.
$c['occupation_controller'] = FlowHooks::getOccupationController();
-$c['controller.notification'] = function( $c ) {
+$c['controller.notification'] = function ( $c ) {
global $wgContLang;
- return new Flow\NotificationController( $wgContLang );
+ return new Flow\NotificationController( $wgContLang, $c['repository.tree'] );
};
// Initialized in FlowHooks to faciliate only loading the flow container
@@ -828,19 +791,19 @@ $c['controller.notification'] = function( $c ) {
// must always happen before calling flow code.
$c['controller.abusefilter'] = FlowHooks::getAbuseFilter();
-$c['controller.spamregex'] = function( $c ) {
+$c['controller.spamregex'] = function ( $c ) {
return new Flow\SpamFilter\SpamRegex;
};
-$c['controller.spamblacklist'] = function( $c ) {
+$c['controller.spamblacklist'] = function ( $c ) {
return new Flow\SpamFilter\SpamBlacklist;
};
-$c['controller.confirmedit'] = function( $c ) {
+$c['controller.confirmedit'] = function ( $c ) {
return new Flow\SpamFilter\ConfirmEdit;
};
-$c['controller.contentlength'] = function( $c ) {
+$c['controller.contentlength'] = function ( $c ) {
global $wgMaxArticleSize;
// wgMaxArticleSize is in kilobytes,
@@ -851,66 +814,71 @@ $c['controller.contentlength'] = function( $c ) {
return new Flow\SpamFilter\ContentLengthFilter( $maxCharCount );
};
-$c['controller.spamfilter'] = function( $c ) {
+$c['controller.ratelimits'] = function ( $c ) {
+ return new Flow\SpamFilter\RateLimits;
+};
+
+$c['controller.spamfilter'] = function ( $c ) {
return new Flow\SpamFilter\Controller(
+ $c['controller.contentlength'],
$c['controller.spamregex'],
+ $c['controller.ratelimits'],
$c['controller.spamblacklist'],
$c['controller.abusefilter'],
- $c['controller.confirmedit'],
- $c['controller.contentlength']
+ $c['controller.confirmedit']
);
};
-$c['query.categoryviewer'] = function( $c ) {
+$c['query.categoryviewer'] = function ( $c ) {
return new Flow\Formatter\CategoryViewerQuery(
$c['storage'],
$c['repository.tree']
);
};
-$c['formatter.categoryviewer'] = function( $c ) {
+$c['formatter.categoryviewer'] = function ( $c ) {
return new Flow\Formatter\CategoryViewerFormatter(
$c['permissions']
);
};
-$c['query.singlepost'] = function( $c ) {
+$c['query.singlepost'] = function ( $c ) {
return new Flow\Formatter\SinglePostQuery(
$c['storage'],
$c['repository.tree']
);
};
-$c['query.checkuser'] = function( $c ) {
+$c['query.checkuser'] = function ( $c ) {
return new Flow\Formatter\CheckUserQuery(
$c['storage'],
$c['repository.tree']
);
};
-$c['formatter.irclineurl'] = function( $c ) {
+$c['formatter.irclineurl'] = function ( $c ) {
return new Flow\Formatter\IRCLineUrlFormatter(
$c['permissions'],
$c['formatter.revision']
);
};
-$c['formatter.checkuser'] = function( $c ) {
+$c['formatter.checkuser'] = function ( $c ) {
return new Flow\Formatter\CheckUserFormatter(
$c['permissions'],
$c['formatter.revision']
);
};
-$c['formatter.revisionview'] = function( $c ) {
+$c['formatter.revisionview'] = function ( $c ) {
return new Flow\Formatter\RevisionViewFormatter(
$c['url_generator'],
$c['formatter.revision']
);
};
-$c['formatter.revision.diff.view'] = function( $c ) {
+$c['formatter.revision.diff.view'] = function ( $c ) {
return new Flow\Formatter\RevisionDiffViewFormatter(
$c['formatter.revisionview'],
$c['url_generator']
);
};
-$c['query.topiclist'] = function( $c ) {
+$c['query.topiclist'] = function ( $c ) {
return new Flow\Formatter\TopicListQuery(
$c['storage'],
$c['repository.tree'],
@@ -918,19 +886,21 @@ $c['query.topiclist'] = function( $c ) {
$c['watched_items']
);
};
-$c['query.topic.history'] = function( $c ) {
+$c['query.topic.history'] = function ( $c ) {
return new Flow\Formatter\TopicHistoryQuery(
$c['storage'],
- $c['repository.tree']
+ $c['repository.tree'],
+ $c['flow_actions']
);
};
-$c['query.post.history'] = function( $c ) {
+$c['query.post.history'] = function ( $c ) {
return new Flow\Formatter\PostHistoryQuery(
$c['storage'],
- $c['repository.tree']
+ $c['repository.tree'],
+ $c['flow_actions']
);
};
-$c['query.changeslist'] = function( $c ) {
+$c['query.changeslist'] = function ( $c ) {
$query = new Flow\Formatter\ChangesListQuery(
$c['storage'],
$c['repository.tree'],
@@ -940,42 +910,42 @@ $c['query.changeslist'] = function( $c ) {
return $query;
};
-$c['query.postsummary'] = function( $c ) {
+$c['query.postsummary'] = function ( $c ) {
return new Flow\Formatter\PostSummaryQuery(
$c['storage'],
$c['repository.tree'],
$c['flow_actions']
);
};
-$c['query.header.view'] = function( $c ) {
+$c['query.header.view'] = function ( $c ) {
return new Flow\Formatter\HeaderViewQuery(
$c['storage'],
$c['repository.tree'],
$c['permissions']
);
};
-$c['query.post.view'] = function( $c ) {
+$c['query.post.view'] = function ( $c ) {
return new Flow\Formatter\PostViewQuery(
$c['storage'],
$c['repository.tree'],
$c['permissions']
);
};
-$c['query.postsummary.view'] = function( $c ) {
+$c['query.postsummary.view'] = function ( $c ) {
return new Flow\Formatter\PostSummaryViewQuery(
$c['storage'],
$c['repository.tree'],
$c['permissions']
);
};
-$c['formatter.changeslist'] = function( $c ) {
+$c['formatter.changeslist'] = function ( $c ) {
return new Flow\Formatter\ChangesListFormatter(
$c['permissions'],
$c['formatter.revision']
);
};
-$c['query.contributions'] = function( $c ) {
+$c['query.contributions'] = function ( $c ) {
return new Flow\Formatter\ContributionsQuery(
$c['storage'],
$c['repository.tree'],
@@ -984,22 +954,23 @@ $c['query.contributions'] = function( $c ) {
$c['flow_actions']
);
};
-$c['formatter.contributions'] = function( $c ) {
+$c['formatter.contributions'] = function ( $c ) {
return new Flow\Formatter\ContributionsFormatter(
$c['permissions'],
$c['formatter.revision']
);
};
-$c['formatter.contributions.feeditem'] = function( $c ) {
+$c['formatter.contributions.feeditem'] = function ( $c ) {
return new Flow\Formatter\FeedItemFormatter(
$c['permissions'],
$c['formatter.revision']
);
};
-$c['query.board-history'] = function( $c ) {
+$c['query.board.history'] = function ( $c ) {
return new Flow\Formatter\BoardHistoryQuery(
$c['storage'],
- $c['repository.tree']
+ $c['repository.tree'],
+ $c['flow_actions']
);
};
@@ -1008,7 +979,7 @@ $c['query.board-history'] = function( $c ) {
// properties. To prevent different code using the formatter
// from causing problems return a new RevisionFormatter every
// time it is requested.
-$c['formatter.revision'] = $c->factory( function( $c ) {
+$c['formatter.revision'] = $c->factory( function ( $c ) {
global $wgFlowMaxThreadingDepth;
return new Flow\Formatter\RevisionFormatter(
@@ -1018,7 +989,7 @@ $c['formatter.revision'] = $c->factory( function( $c ) {
$wgFlowMaxThreadingDepth
);
} );
-$c['formatter.topiclist'] = function( $c ) {
+$c['formatter.topiclist'] = function ( $c ) {
return new Flow\Formatter\TopicListFormatter(
$c['url_generator'],
$c['formatter.revision']
@@ -1029,22 +1000,45 @@ $c['formatter.topiclist.toc'] = function ( $c ) {
$c['templating']
);
};
-$c['formatter.topic'] = function( $c ) {
+$c['formatter.topic'] = function ( $c ) {
return new Flow\Formatter\TopicFormatter(
$c['url_generator'],
$c['formatter.revision']
);
};
-$c['searchindex.updaters'] = function( $c ) {
+$c['search.connection'] = function ( $c ) {
+ if ( defined( 'MW_PHPUNIT_TEST' ) && !class_exists( 'ElasticaConnection' ) ) {
+ /*
+ * ContainerTest::testInstantiateAll instantiates everything
+ * in container and doublechecks it's not null.
+ * Flow runs on Jenkins don't currently load Extension:Elastica,
+ * which is required to be able to construct this object.
+ * Because search is not currently in use, let's not add the
+ * dependency in Jenkins and just return a bogus value to not
+ * make the test fail ;)
+ */
+ return 'not-supported';
+ }
+
+ global $wgFlowSearchServers, $wgFlowSearchConnectionAttempts;
+ return new Flow\Search\Connection( $wgFlowSearchServers, $wgFlowSearchConnectionAttempts );
+};
+$c['search.index.iterators.header'] = function ( $c ) {
+ return new \Flow\Search\Iterators\HeaderIterator( $c['db.factory'] );
+};
+$c['search.index.iterators.topic'] = function ( $c ) {
+ return new \Flow\Search\Iterators\TopicIterator( $c['db.factory'], $c['loader.root_post'] );
+};
+$c['search.index.updaters'] = function ( $c ) {
// permissions for anon user
$anonPermissions = new Flow\RevisionActionPermissions( $c['flow_actions'], new User );
- return array(
- 'topic' => new \Flow\Search\TopicUpdater( $c['db.factory'], $anonPermissions, $c['loader.root_post'] ),
- 'header' => new \Flow\Search\HeaderUpdater( $c['db.factory'], $anonPermissions )
- );
+ return [
+ 'topic' => new \Flow\Search\Updaters\TopicUpdater( $c['search.index.iterators.topic'], $anonPermissions, $c['loader.root_post'] ),
+ 'header' => new \Flow\Search\Updaters\HeaderUpdater( $c['search.index.iterators.header'], $anonPermissions )
+ ];
};
-$c['logger.moderation'] = function( $c ) {
+$c['logger.moderation'] = function ( $c ) {
return new Flow\Log\ModerationLogger(
$c['flow_actions']
);
@@ -1053,153 +1047,96 @@ $c['logger.moderation'] = function( $c ) {
$c['storage.wiki_reference.class'] = 'Flow\Model\WikiReference';
$c['storage.wiki_reference.table'] = 'flow_wiki_ref';
$c['storage.wiki_reference.primary_key'] = function ( $c ) {
- global $wgFlowMigrateReferenceWiki;
-
- $pk = array(
+ return [
+ 'ref_src_wiki',
'ref_src_namespace',
'ref_src_title',
'ref_src_object_id',
'ref_type',
'ref_target_namespace',
'ref_target_title'
- );
-
- if ( !$wgFlowMigrateReferenceWiki ) {
- array_unshift( $pk, 'ref_src_wiki' );
- }
-
- return $pk;
+ ];
};
-$c['storage.wiki_reference.mapper'] = function( $c ) {
+$c['storage.wiki_reference.mapper'] = function ( $c ) {
return BasicObjectMapper::model(
$c['storage.wiki_reference.class']
);
};
-$c['storage.wiki_reference.backend'] = function( $c ) {
+$c['storage.wiki_reference.backend'] = function ( $c ) {
return new BasicDbStorage(
$c['db.factory'],
$c['storage.wiki_reference.table'],
$c['storage.wiki_reference.primary_key']
);
};
-$c['storage.wiki_reference.indexes.source_lookup'] = function( $c ) {
+$c['storage.wiki_reference.indexes.source_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.wiki_reference.backend'],
$c['storage.wiki_reference.mapper'],
'flow_ref:wiki:by-source:v3',
- array(
+ [
'ref_src_wiki',
'ref_src_namespace',
'ref_src_title',
- ),
- array(
+ ],
+ [
'order' => 'ASC',
'sort' => 'ref_src_object_id',
- )
+ ]
);
};
-$c['storage.wiki_reference.indexes.revision_lookup'] = function( $c ) {
+$c['storage.wiki_reference.indexes.revision_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.wiki_reference.backend'],
$c['storage.wiki_reference.mapper'],
'flow_ref:wiki:by-revision:v3',
- array(
+ [
'ref_src_wiki',
'ref_src_object_type',
'ref_src_object_id',
- ),
- array(
+ ],
+ [
'order' => 'ASC',
- 'sort' => array( 'ref_target_namespace', 'ref_target_title' ),
- )
+ 'sort' => [ 'ref_target_namespace', 'ref_target_title' ],
+ ]
);
};
-$c['storage.wiki_reference.indexes'] = function( $c ) {
- $indexes = array(
+$c['storage.wiki_reference.indexes'] = function ( $c ) {
+ return [
$c['storage.wiki_reference.indexes.source_lookup'],
$c['storage.wiki_reference.indexes.revision_lookup'],
- );
-
- global $wgFlowMigrateReferenceWiki;
-
- if ( $wgFlowMigrateReferenceWiki ) {
- // Until the backfill is done, keep using only the old indexes.
- // However, this means the new indexes will not be populated
- // at all until the backfill is fully done, and the global is off.
- // We can't start using them, because the indexes listen to removal
- // events, and we can't properly remove it from the full index
- // e.g. (ref_src_wiki, ref_src_namespace, ref_src_title) when
- // we're not passing in ref_src_wiki.
- $indexes = array(
- new TopKIndex(
- $c['memcache.local_buffered'],
- $c['storage.wiki_reference.backend'],
- $c['storage.wiki_reference.mapper'],
- 'flow_ref:wiki:by-source:v2b',
- array(
- 'ref_src_namespace',
- 'ref_src_title',
- ),
- array(
- 'order' => 'ASC',
- 'sort' => 'ref_src_object_id',
- )
- ),
- new TopKIndex(
- $c['memcache.local_buffered'],
- $c['storage.wiki_reference.backend'],
- $c['storage.wiki_reference.mapper'],
- 'flow_ref:wiki:by-revision:v2b',
- array(
- 'ref_src_object_type',
- 'ref_src_object_id',
- ),
- array(
- 'order' => 'ASC',
- 'sort' => array( 'ref_target_namespace', 'ref_target_title' ),
- )
- )
- );
- }
-
- return $indexes;
+ ];
};
-$c['storage.wiki_reference'] = function( $c ) {
+$c['storage.wiki_reference'] = function ( $c ) {
return new ObjectManager(
$c['storage.wiki_reference.mapper'],
$c['storage.wiki_reference.backend'],
+ $c['db.factory'],
$c['storage.wiki_reference.indexes'],
- array()
+ []
);
};
$c['storage.url_reference.class'] = 'Flow\Model\URLReference';
$c['storage.url_reference.table'] = 'flow_ext_ref';
$c['storage.url_reference.primary_key'] = function ( $c ) {
- global $wgFlowMigrateReferenceWiki;
-
- $pk = array(
+ return [
+ 'ref_src_wiki',
'ref_src_namespace',
'ref_src_title',
'ref_src_object_id',
'ref_type',
'ref_target',
- );
-
- if ( !$wgFlowMigrateReferenceWiki ) {
- array_unshift( $pk, 'ref_src_wiki' );
- }
-
- return $pk;
+ ];
};
-$c['storage.url_reference.mapper'] = function( $c ) {
+$c['storage.url_reference.mapper'] = function ( $c ) {
return BasicObjectMapper::model(
$c['storage.url_reference.class']
);
};
-$c['storage.url_reference.backend'] = function( $c ) {
+$c['storage.url_reference.backend'] = function ( $c ) {
return new BasicDbStorage(
// factory and table
$c['db.factory'],
@@ -1208,113 +1145,77 @@ $c['storage.url_reference.backend'] = function( $c ) {
);
};
-$c['storage.url_reference.indexes.source_lookup'] = function( $c ) {
+$c['storage.url_reference.indexes.source_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.url_reference.backend'],
$c['storage.url_reference.mapper'],
'flow_ref:url:by-source:v3',
- array(
+ [
'ref_src_wiki',
'ref_src_namespace',
'ref_src_title',
- ),
- array(
+ ],
+ [
'order' => 'ASC',
'sort' => 'ref_src_object_id',
- )
+ ]
);
};
-$c['storage.url_reference.indexes.revision_lookup'] = function( $c ) {
+$c['storage.url_reference.indexes.revision_lookup'] = function ( $c ) {
return new TopKIndex(
- $c['memcache.local_buffered'],
+ $c['flowcache'],
$c['storage.url_reference.backend'],
$c['storage.url_reference.mapper'],
'flow_ref:url:by-revision:v3',
- array(
+ [
'ref_src_wiki',
'ref_src_object_type',
'ref_src_object_id',
- ),
- array(
+ ],
+ [
'order' => 'ASC',
- 'sort' => array( 'ref_target' ),
- )
+ 'sort' => [ 'ref_target' ],
+ ]
);
};
-$c['storage.url_reference.indexes'] = function( $c ) {
- $indexes = array(
+$c['storage.url_reference.indexes'] = function ( $c ) {
+ return [
$c['storage.url_reference.indexes.source_lookup'],
$c['storage.url_reference.indexes.revision_lookup'],
- );
-
- global $wgFlowMigrateReferenceWiki;
- if ( $wgFlowMigrateReferenceWiki ) {
- // See 'storage.wiki_reference.indexes'.
- $indexes = array(
- new TopKIndex(
- $c['memcache.local_buffered'],
- $c['storage.url_reference.backend'],
- $c['storage.url_reference.mapper'],
- 'flow_ref:url:by-source:v2b',
- array(
- 'ref_src_namespace',
- 'ref_src_title',
- ),
- array(
- 'order' => 'ASC',
- 'sort' => 'ref_src_object_id',
- )
- ),
- new TopKIndex(
- $c['memcache.local_buffered'],
- $c['storage.url_reference.backend'],
- $c['storage.url_reference.mapper'],
- 'flow_ref:url:by-revision:v2b',
- array(
- 'ref_src_object_type',
- 'ref_src_object_id',
- ),
- array(
- 'order' => 'ASC',
- 'sort' => array( 'ref_target' ),
- )
- )
- );
- }
-
- return $indexes;
+ ];
};
-$c['storage.url_reference'] = function( $c ) {
+$c['storage.url_reference'] = function ( $c ) {
return new ObjectManager(
$c['storage.url_reference.mapper'],
$c['storage.url_reference.backend'],
+ $c['db.factory'],
$c['storage.url_reference.indexes'],
- array()
+ []
);
};
-$c['reference.updater.links-tables'] = function( $c ) {
+$c['reference.updater.links-tables'] = function ( $c ) {
return new Flow\LinksTableUpdater( $c['storage'] );
};
-$c['reference.clarifier'] = function( $c ) {
+$c['reference.clarifier'] = function ( $c ) {
return new Flow\ReferenceClarifier( $c['storage'], $c['url_generator'] );
};
-$c['reference.extractor'] = function( $c ) {
- $default = array(
+$c['reference.extractor'] = function ( $c ) {
+ $default = [
new Flow\Parsoid\Extractor\ImageExtractor,
new Flow\Parsoid\Extractor\PlaceholderExtractor,
new Flow\Parsoid\Extractor\WikiLinkExtractor,
new Flow\Parsoid\Extractor\ExtLinkExtractor,
new Flow\Parsoid\Extractor\TransclusionExtractor,
- );
- $extractors = array(
+ ];
+ $extractors = [
'header' => $default,
'post-summary' => $default,
'post' => $default,
- );
+ ];
// In addition to the defaults header and summaries collect
// the related categories.
$extractors['header'][] = $extractors['post-summary'][] = new Flow\Parsoid\Extractor\CategoryExtractor;
@@ -1322,7 +1223,7 @@ $c['reference.extractor'] = function( $c ) {
return new Flow\Parsoid\ReferenceExtractor( $extractors );
};
-$c['reference.recorder'] = function( $c ) {
+$c['reference.recorder'] = function ( $c ) {
return new Flow\Data\Listener\ReferenceRecorder(
$c['reference.extractor'],
$c['reference.updater.links-tables'],
@@ -1332,18 +1233,17 @@ $c['reference.recorder'] = function( $c ) {
);
};
-$c['user_merger'] = function( $c ) {
+$c['user_merger'] = function ( $c ) {
return new Flow\Data\Utils\UserMerger(
$c['db.factory'],
$c['storage']
);
};
-$c['importer'] = function( $c ) {
+$c['importer'] = function ( $c ) {
$importer = new Flow\Import\Importer(
$c['storage'],
$c['factory.loader.workflow'],
- $c['memcache.local_buffered'],
$c['db.factory'],
$c['deferred_queue'],
$c['occupation_controller']
@@ -1356,31 +1256,30 @@ $c['importer'] = function( $c ) {
return $importer;
};
-$c['listener.editcount'] = function( $c ) {
+$c['listener.editcount'] = function ( $c ) {
return new \Flow\Data\Listener\EditCountListener( $c['flow_actions'] );
};
-$c['formatter.undoedit'] = function( $c ) {
+$c['formatter.undoedit'] = function ( $c ) {
return new Flow\Formatter\RevisionUndoViewFormatter(
$c['formatter.revisionview']
);
};
-$c['board_mover'] = function( $c ) {
+$c['board_mover'] = function ( $c ) {
return new Flow\BoardMover(
$c['db.factory'],
- $c['memcache.local_buffered'],
$c['storage'],
$c['occupation_controller']->getTalkpageManager()
);
};
-$c['parser'] = function() {
+$c['parser'] = function () {
global $wgParser;
return $wgParser;
};
-$c['default_logger'] = function() {
+$c['default_logger'] = function () {
return MediaWiki\Logger\LoggerFactory::getInstance( 'Flow' );
};
diff --git a/Flow/db_patches/patch-add-wiki.sql b/Flow/db_patches/patch-add-wiki.sql
index 969fd32f..4337c8c9 100644
--- a/Flow/db_patches/patch-add-wiki.sql
+++ b/Flow/db_patches/patch-add-wiki.sql
@@ -1,6 +1,3 @@
-
-ALTER TABLE /*_*/flow_subscription ADD subscription_user_wiki varchar(32) binary not null;
-
ALTER TABLE /*_*/flow_tree_revision ADD tree_orig_user_wiki varchar(32) binary not null;
ALTER TABLE /*_*/flow_revision ADD rev_user_wiki varchar(32) binary not null;
@@ -8,9 +5,3 @@ ALTER TABLE /*_*/flow_revision ADD rev_user_wiki varchar(32) binary not null;
ALTER TABLE /*_*/flow_revision ADD rev_mod_user_wiki varchar(32) binary default null;
ALTER TABLE /*_*/flow_revision ADD rev_edit_user_wiki varchar(32) binary default null;
-
-DROP INDEX /*i*/flow_subscription_unique_user_workflow ON /*_*/flow_subscription;
-CREATE UNIQUE INDEX /*i*/flow_subscription_unique_user_workflow ON /*_*/flow_subscription (subscription_workflow_id, subscription_user_id, subscription_user_wiki );
-
-DROP INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription;
-CREATE INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription (subscription_user_id, subscription_user_wiki, subscription_last_updated, subscription_workflow_id);
diff --git a/Flow/db_patches/patch-addindex_flow_ext_ref_idx_v3.sql b/Flow/db_patches/patch-addindex_flow_ext_ref_idx_v3.sql
new file mode 100644
index 00000000..c2102bad
--- /dev/null
+++ b/Flow/db_patches/patch-addindex_flow_ext_ref_idx_v3.sql
@@ -0,0 +1,2 @@
+CREATE INDEX /*i*/flow_ext_ref_idx_v3 ON /*_*/flow_ext_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_type, ref_target(255), ref_src_object_type, ref_src_object_id);
diff --git a/Flow/db_patches/patch-drop-flow_subscription.sql b/Flow/db_patches/patch-drop-flow_subscription.sql
new file mode 100644
index 00000000..03f1d7a5
--- /dev/null
+++ b/Flow/db_patches/patch-drop-flow_subscription.sql
@@ -0,0 +1 @@
+DROP TABLE /*_*/flow_subscription;
diff --git a/Flow/db_patches/patch-dropindex-flow_ext_ref_idx_v2.sql b/Flow/db_patches/patch-dropindex-flow_ext_ref_idx_v2.sql
new file mode 100644
index 00000000..22a47c68
--- /dev/null
+++ b/Flow/db_patches/patch-dropindex-flow_ext_ref_idx_v2.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/flow_ext_ref DROP INDEX flow_ext_ref_idx_v2;
diff --git a/Flow/db_patches/patch-increase_width_wiki_fields.sql b/Flow/db_patches/patch-increase_width_wiki_fields.sql
index 9b0d499e..c6396c1b 100644
--- a/Flow/db_patches/patch-increase_width_wiki_fields.sql
+++ b/Flow/db_patches/patch-increase_width_wiki_fields.sql
@@ -2,8 +2,6 @@
-- for SQLite) since SQLite doesn't care about column widths anyway.
ALTER TABLE /*_*/flow_workflow MODIFY workflow_wiki varchar(64) binary not null;
-ALTER TABLE /*_*/flow_subscription MODIFY subscription_user_wiki varchar(64) binary not null;
-
ALTER TABLE /*_*/flow_tree_revision MODIFY tree_orig_user_wiki varchar(64) binary not null;
ALTER TABLE /*_*/flow_revision MODIFY rev_user_wiki varchar(64) binary not null,
diff --git a/Flow/db_patches/patch-primary-keys.sql b/Flow/db_patches/patch-primary-keys.sql
new file mode 100644
index 00000000..034508f8
--- /dev/null
+++ b/Flow/db_patches/patch-primary-keys.sql
@@ -0,0 +1,5 @@
+DROP INDEX /*i*/flow_topic_list_pk ON /*_*/flow_topic_list;
+ALTER TABLE /*_*/flow_topic_list ADD PRIMARY KEY (topic_list_id, topic_id);
+
+DROP INDEX /*i*/flow_tree_node_pk ON /*_*/flow_tree_node;
+ALTER TABLE /*_*/flow_tree_node ADD PRIMARY KEY (tree_ancestor_id, tree_descendant_id);
diff --git a/Flow/db_patches/patch-ref_id-phase1.sql b/Flow/db_patches/patch-ref_id-phase1.sql
new file mode 100644
index 00000000..4ab5393b
--- /dev/null
+++ b/Flow/db_patches/patch-ref_id-phase1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/flow_wiki_ref ADD COLUMN ref_id binary(11) null;
+ALTER TABLE /*_*/flow_ext_ref ADD COLUMN ref_id binary(11) null;
diff --git a/Flow/db_patches/patch-ref_id-phase2.sql b/Flow/db_patches/patch-ref_id-phase2.sql
new file mode 100644
index 00000000..6ae67e50
--- /dev/null
+++ b/Flow/db_patches/patch-ref_id-phase2.sql
@@ -0,0 +1,5 @@
+ALTER TABLE /*_*/flow_wiki_ref CHANGE ref_id ref_id BINARY(11) NOT NULL;
+ALTER TABLE /*_*/flow_ext_ref CHANGE ref_id ref_id BINARY(11) NOT NULL;
+
+ALTER TABLE /*_*/flow_wiki_ref ADD PRIMARY KEY (ref_id);
+ALTER TABLE /*_*/flow_ext_ref ADD PRIMARY KEY (ref_id);
diff --git a/Flow/db_patches/patch-ref_id-phase2.sqlite.sql b/Flow/db_patches/patch-ref_id-phase2.sqlite.sql
new file mode 100644
index 00000000..de87b46a
--- /dev/null
+++ b/Flow/db_patches/patch-ref_id-phase2.sqlite.sql
@@ -0,0 +1,73 @@
+-- SQLite won't allow us to just alter the columns, so we'll move this table
+-- out of the way, create it anew the way we want it, and then copy the
+-- data over before dropping the old table
+ALTER TABLE /*_*/flow_wiki_ref RENAME TO /*_*/temp_flow_wiki_ref;
+ALTER TABLE /*_*/flow_ext_ref RENAME TO /*_*/temp_flow_ext_ref;
+
+-- SQLite also doesn't allow multiple indexes with the same name (even if
+-- they're on separate tables.
+-- Since we're going to recreate these same tables with the same indexes, we
+-- first need to drop them from the other table.
+DROP INDEX /*i*/flow_wiki_ref_idx_v2;
+DROP INDEX /*i*/flow_wiki_ref_revision_v2;
+DROP INDEX /*i*/flow_ext_ref_idx_v2;
+DROP INDEX /*i*/flow_ext_ref_revision_v2;
+
+CREATE TABLE /*_*/flow_wiki_ref (
+ ref_id binary(11) not null,
+ ref_src_wiki varchar(16) binary not null,
+ ref_src_object_id binary(11) not null,
+ ref_src_object_type varbinary(32) not null,
+ ref_src_workflow_id binary(11) not null,
+ ref_src_namespace int not null,
+ ref_src_title varbinary(255) not null,
+ ref_target_namespace int not null,
+ ref_target_title varbinary(255) not null,
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX /*i*/flow_wiki_ref_idx_v2 ON /*_*/flow_wiki_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_type, ref_target_namespace, ref_target_title, ref_src_object_type, ref_src_object_id);
+
+CREATE INDEX /*i*/flow_wiki_ref_revision_v2 ON /*_*/flow_wiki_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type, ref_src_object_id, ref_type, ref_target_namespace, ref_target_title);
+
+CREATE TABLE /*_*/flow_ext_ref (
+ ref_id binary(11) not null,
+ ref_src_wiki varchar(16) binary not null,
+ ref_src_object_id binary(11) not null,
+ ref_src_object_type varbinary(32) not null,
+ ref_src_workflow_id binary(11) not null,
+ ref_src_namespace int not null,
+ ref_src_title varbinary(255) not null,
+ ref_target blob not null,
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX /*i*/flow_ext_ref_idx_v2 ON /*_*/flow_ext_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_type, ref_target(255), ref_src_object_type, ref_src_object_id);
+
+CREATE INDEX /*i*/flow_ext_ref_revision_v2 ON /*_*/flow_ext_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type, ref_src_object_id, ref_type, ref_target(255));
+
+
+INSERT INTO /*_*/flow_wiki_ref
+ (ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type, ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target_namespace, ref_target_title, ref_type)
+SELECT
+ ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type, ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target_namespace, ref_target_title, ref_type
+FROM
+ /*_*/temp_flow_wiki_ref;
+
+INSERT INTO /*_*/flow_ext_ref
+ (ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type, ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target, ref_type)
+SELECT
+ ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type, ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target, ref_type
+FROM
+ /*_*/temp_flow_ext_ref;
+
+DROP TABLE /*_*/temp_flow_wiki_ref;
+DROP TABLE /*_*/temp_flow_ext_ref;
diff --git a/Flow/db_patches/patch-ref_target_not_null.sql b/Flow/db_patches/patch-ref_target_not_null.sql
new file mode 100644
index 00000000..da88d328
--- /dev/null
+++ b/Flow/db_patches/patch-ref_target_not_null.sql
@@ -0,0 +1 @@
+ALTER TABLE /*_*/flow_ext_ref CHANGE ref_target ref_target BLOB NOT NULL;
diff --git a/Flow/db_patches/patch-reference_wiki-phase3.sql b/Flow/db_patches/patch-reference_wiki-phase3.sql
index b5117217..eb8b1aab 100644
--- a/Flow/db_patches/patch-reference_wiki-phase3.sql
+++ b/Flow/db_patches/patch-reference_wiki-phase3.sql
@@ -10,12 +10,12 @@ UPDATE
SELECT ref_src_workflow_id, workflow_wiki
FROM /*_*/flow_wiki_ref, /*_*/flow_workflow
WHERE
- flow_wiki_ref.ref_src_workflow_id = flow_workflow.workflow_id AND
- ( flow_wiki_ref.ref_src_wiki = '' OR flow_wiki_ref.ref_src_wiki IS NULL )
+ ref_src_workflow_id = workflow_id AND
+ ( ref_src_wiki = '' OR ref_src_wiki IS NULL )
LIMIT 1000
) tmp
- SET flow_wiki_ref.ref_src_wiki = tmp.workflow_wiki
- WHERE flow_wiki_ref.ref_src_workflow_id = tmp.ref_src_workflow_id;
+ SET /*_*/flow_wiki_ref.ref_src_wiki = tmp.workflow_wiki
+ WHERE /*_*/flow_wiki_ref.ref_src_workflow_id = tmp.ref_src_workflow_id;
-- Populate external references with the appropriate wiki.
@@ -24,9 +24,9 @@ UPDATE
SELECT ref_src_workflow_id, workflow_wiki
FROM /*_*/flow_ext_ref, /*_*/flow_workflow
WHERE
- flow_ext_ref.ref_src_workflow_id = flow_workflow.workflow_id AND
- ( flow_ext_ref.ref_src_wiki = '' OR flow_ext_ref.ref_src_wiki IS NULL )
+ ref_src_workflow_id = workflow_id AND
+ ( ref_src_wiki = '' OR ref_src_wiki IS NULL )
LIMIT 1000
) tmp
- SET flow_ext_ref.ref_src_wiki = tmp.workflow_wiki
- WHERE flow_ext_ref.ref_src_workflow_id = tmp.ref_src_workflow_id;
+ SET /*_*/flow_ext_ref.ref_src_wiki = tmp.workflow_wiki
+ WHERE /*_*/flow_ext_ref.ref_src_workflow_id = tmp.ref_src_workflow_id;
diff --git a/Flow/db_patches/patch-reference_wiki.sql b/Flow/db_patches/patch-reference_wiki.sql
index 63b77787..27f36ad2 100644
--- a/Flow/db_patches/patch-reference_wiki.sql
+++ b/Flow/db_patches/patch-reference_wiki.sql
@@ -10,9 +10,9 @@ DROP INDEX /*i*/flow_wiki_ref_revision ON /*_*/flow_wiki_ref;
-- Populate wiki references with the appropriate wiki
UPDATE /*_*/flow_wiki_ref, /*_*/flow_workflow
- SET flow_wiki_ref.ref_src_wiki = flow_workflow.workflow_wiki
+ SET ref_src_wiki = workflow_wiki
WHERE
- flow_wiki_ref.ref_src_workflow_id = flow_workflow.workflow_id;
+ ref_src_workflow_id = workflow_id;
-- Recreate new indexes
CREATE INDEX /*i*/flow_wiki_ref_idx_v2 ON /*_*/flow_wiki_ref
@@ -30,9 +30,9 @@ DROP INDEX /*i*/flow_ext_ref_revision ON /*_*/flow_ext_ref;
-- Populate external references with the appropriate wiki
UPDATE /*_*/flow_ext_ref, /*_*/flow_workflow
- SET flow_ext_ref.ref_src_wiki = flow_workflow.workflow_wiki
+ SET ref_src_wiki = workflow_wiki
WHERE
- flow_ext_ref.ref_src_workflow_id = flow_workflow.workflow_id;
+ ref_src_workflow_id = workflow_id;
-- Recreate new indexes
CREATE INDEX /*i*/flow_ext_ref_idx_v2 ON /*_*/flow_ext_ref
diff --git a/Flow/db_patches/patch-remove_unique_ref_indices.sql b/Flow/db_patches/patch-remove_unique_ref_indices.sql
index 7a0cc315..60f4518b 100644
--- a/Flow/db_patches/patch-remove_unique_ref_indices.sql
+++ b/Flow/db_patches/patch-remove_unique_ref_indices.sql
@@ -9,7 +9,7 @@ CREATE INDEX /*i*/flow_wiki_ref_revision ON /*_*/flow_wiki_ref ( ref_src_namespa
DROP INDEX /*i*/flow_ext_ref_pk ON /*_*/flow_ext_ref;
DROP INDEX /*i*/flow_ext_ref_revision ON /*_*/flow_ext_ref;
-ALTER TABLE /*_*/flow_ext_ref CHANGE ref_target ref_target BLOB;
+ALTER TABLE /*_*/flow_ext_ref CHANGE ref_target ref_target BLOB NOT NULL;
CREATE INDEX /*i*/flow_ext_ref_idx ON /*_*/flow_ext_ref ( ref_src_namespace, ref_src_title, ref_type, ref_target(255), ref_src_object_type, ref_src_object_id );
CREATE INDEX /*i*/flow_ext_ref_revision ON /*_*/flow_ext_ref ( ref_src_namespace, ref_src_title, ref_src_object_type, ref_src_object_id, ref_type, ref_target(255) );
diff --git a/Flow/defines.php b/Flow/defines.php
index 72b0196d..cd300287 100644
--- a/Flow/defines.php
+++ b/Flow/defines.php
@@ -2,6 +2,9 @@
// Constants
define( 'RC_FLOW', 142 ); // Random number chosen. Can be replaced with rc_source; see bug 72157.
-define( 'NS_TOPIC', 2600 );
+if ( !defined( 'NS_TOPIC' ) ) {
+ define( 'NS_TOPIC', 2600 );
+}
+define( 'CONTENT_MODEL_FLOW_BOARD', 'flow-board' );
define( 'FLOW_TALK_PAGE_MANAGER_USER', 'Flow talk page manager' );
define( 'BETA_FEATURE_FLOW_USER_TALK_PAGE', 'beta-feature-flow-user-talk-page' );
diff --git a/Flow/extension.json b/Flow/extension.json
new file mode 100644
index 00000000..948e9922
--- /dev/null
+++ b/Flow/extension.json
@@ -0,0 +1,1371 @@
+{
+ "name": "Flow",
+ "version": "1.1",
+ "author": [
+ "Erik Bernhardson",
+ "Stephane Bisson",
+ "Matthew Flaschen",
+ "Andrew Garrett",
+ "Shahyar Ghobadpour",
+ "Pau Giner",
+ "Roan Kattouw",
+ "Chris McMahon",
+ "Kunal Mehta",
+ "Matthias Mullie",
+ "S Page",
+ "Jon Robson",
+ "Moriel Schottlender",
+ "Benny Situ"
+ ],
+ "url": "https://www.mediawiki.org/wiki/Extension:Flow",
+ "descriptionmsg": "flow-desc",
+ "license-name": "GPL-2.0+",
+ "type": "other",
+ "requires": {
+ "MediaWiki": ">= 1.29.0"
+ },
+ "callback": "FlowHooks::registerExtension",
+ "APIModules": {
+ "flow-parsoid-utils": "Flow\\Api\\ApiParsoidUtilsFlow",
+ "flow": "Flow\\Api\\ApiFlow"
+ },
+ "APIPropModules": {
+ "flowinfo": "Flow\\Api\\ApiQueryPropFlowInfo"
+ },
+ "AvailableRights": [
+ "flow-hide",
+ "flow-lock",
+ "flow-delete",
+ "flow-suppress",
+ "flow-edit-post",
+ "flow-create-board"
+ ],
+ "ContentHandlers": {
+ "flow-board": "Flow\\Content\\BoardContentHandler"
+ },
+ "DefaultUserOptions": {
+ "echo-subscriptions-web-flow-discussion": true,
+ "echo-subscriptions-email-flow-discussion": false,
+ "flow-topiclist-sortby": "updated",
+ "flow-editor": "wikitext",
+ "flow-side-rail-state": "expanded"
+ },
+ "ExtensionFunctions": [
+ "FlowHooks::initFlowExtension"
+ ],
+ "GroupPermissions": {
+ "*": {
+ "flow-hide": true
+ },
+ "user": {
+ "flow-lock": true
+ },
+ "sysop": {
+ "flow-lock": true,
+ "flow-delete": true,
+ "flow-edit-post": true
+ },
+ "oversight": {
+ "flow-suppress": true
+ },
+ "flow-bot": {
+ "flow-create-board": true
+ }
+ },
+ "LogActionsHandlers": {
+ "delete/flow-restore-post": "Flow\\Log\\ActionFormatter",
+ "suppress/flow-restore-post": "Flow\\Log\\ActionFormatter",
+ "delete/flow-restore-topic": "Flow\\Log\\ActionFormatter",
+ "suppress/flow-restore-topic": "Flow\\Log\\ActionFormatter",
+ "lock/flow-restore-topic": "Flow\\Log\\ActionFormatter",
+ "import/lqt-to-flow-topic": "Flow\\Log\\LqtImportFormatter"
+ },
+ "SpecialPages": {
+ "StructuredDiscussions": "Flow\\Specials\\SpecialStructuredDiscussions",
+ "EnableStructuredDiscussions": "Flow\\Specials\\SpecialEnableStructuredDiscussions"
+ },
+ "MessagesDirs": {
+ "Flow": [
+ "i18n",
+ "i18n/api"
+ ]
+ },
+ "ExtensionMessagesFiles": {
+ "FlowNamespaces": "Flow.namespaces.php",
+ "FlowAlias": "Flow.alias.php"
+ },
+ "ResourceModules": {
+ "ext.flow.contributions": {
+ "scripts": [
+ "contributions/base.js"
+ ]
+ },
+ "ext.flow.contributions.styles": {
+ "position": "top",
+ "styles": [
+ "styles/history/history-line.less"
+ ]
+ },
+ "ext.flow.templating": {
+ "localBasePath": "",
+ "remoteExtPath": "Flow",
+ "scripts": [
+ "modules/engine/misc/flow-handlebars.js"
+ ],
+ "dependencies": [
+ "mediawiki.template.handlebars",
+ "mediawiki.user",
+ "mediawiki.util",
+ "moment"
+ ],
+ "templates": [
+ "handlebars/flow_anon_warning.partial.handlebars",
+ "handlebars/flow_block_board-history.handlebars",
+ "handlebars/flow_block_header.handlebars",
+ "handlebars/flow_block_header_diff_view.handlebars",
+ "handlebars/flow_block_header_edit.handlebars",
+ "handlebars/flow_block_header_single_view.handlebars",
+ "handlebars/flow_block_loop.handlebars",
+ "handlebars/flow_block_topic.handlebars",
+ "handlebars/flow_block_topic_diff_view.handlebars",
+ "handlebars/flow_block_topic_edit_title.handlebars",
+ "handlebars/flow_block_topic_history.handlebars",
+ "handlebars/flow_block_topic_moderate_post.handlebars",
+ "handlebars/flow_block_topic_moderate_topic.handlebars",
+ "handlebars/flow_block_topic_single_view.handlebars",
+ "handlebars/flow_block_topiclist.handlebars",
+ "handlebars/flow_block_topicsummary_diff_view.handlebars",
+ "handlebars/flow_block_topicsummary_edit.handlebars",
+ "handlebars/flow_block_topicsummary_single_view.handlebars",
+ "handlebars/flow_board_navigation.partial.handlebars",
+ "handlebars/flow_edit_post.partial.handlebars",
+ "handlebars/flow_edit_topic_title.partial.handlebars",
+ "handlebars/flow_editor_switcher.partial.handlebars",
+ "handlebars/flow_errors.partial.handlebars",
+ "handlebars/flow_form_cancel_button.partial.handlebars",
+ "handlebars/flow_header_title.partial.handlebars",
+ "handlebars/flow_header_detail.partial.handlebars",
+ "handlebars/flow_header_categories.partial.handlebars",
+ "handlebars/flow_header_footer.partial.handlebars",
+ "handlebars/flow_load_more.partial.handlebars",
+ "handlebars/flow_moderate_post_confirmation.partial.handlebars",
+ "handlebars/flow_moderate_post.partial.handlebars",
+ "handlebars/flow_moderate_topic_confirmation.partial.handlebars",
+ "handlebars/flow_moderate_topic.partial.handlebars",
+ "handlebars/flow_moderation_actions_list.partial.handlebars",
+ "handlebars/flow_newtopic_form.partial.handlebars",
+ "handlebars/flow_post_actions.partial.handlebars",
+ "handlebars/flow_post_author.partial.handlebars",
+ "handlebars/flow_post_inner.partial.handlebars",
+ "handlebars/flow_post_meta_actions.partial.handlebars",
+ "handlebars/flow_post_moderation_state.partial.handlebars",
+ "handlebars/flow_post_replies.partial.handlebars",
+ "handlebars/flow_post_partial.partial.handlebars",
+ "handlebars/flow_post.handlebars",
+ "handlebars/flow_reply_form.partial.handlebars",
+ "handlebars/flow_subscribed.partial.handlebars",
+ "handlebars/flow_tooltip_subscribed.partial.handlebars",
+ "handlebars/flow_tooltip.handlebars",
+ "handlebars/flow_topic.partial.handlebars",
+ "handlebars/flow_topic_titlebar_content.partial.handlebars",
+ "handlebars/flow_topic_titlebar_lock.partial.handlebars",
+ "handlebars/flow_topic_titlebar_summary.partial.handlebars",
+ "handlebars/flow_topic_titlebar_watch.partial.handlebars",
+ "handlebars/flow_topic_titlebar.partial.handlebars",
+ "handlebars/flow_topic_moderation_flag.partial.handlebars",
+ "handlebars/flow_topiclist_loop.partial.handlebars",
+ "handlebars/form_element.partial.handlebars",
+ "handlebars/timestamp.handlebars"
+ ],
+ "messages": [
+ "flow-anon-warning",
+ "flow-cancel",
+ "flow-skip-summary",
+ "flow-edit-summary-placeholder",
+ "flow-summary-authored",
+ "flow-summary-edited",
+ "flow-board-header",
+ "flow-board-collapse-description",
+ "flow-board-expand-description",
+ "flow-edit-header-link",
+ "flow-edit-header-placeholder",
+ "flow-edit-header-submit",
+ "flow-edit-header-submit-anonymously",
+ "flow-edit-title-submit",
+ "flow-edit-title-submit-anonymously",
+ "flow-edit-post-submit",
+ "flow-edit-post-submit-anonymously",
+ "flow-load-more",
+ "flow-newest-topics",
+ "flow-newtopic-content-placeholder",
+ "flow-newtopic-save",
+ "flow-newtopic-save-anonymously",
+ "flow-newtopic-start-placeholder",
+ "flow-post-action-delete-post",
+ "flow-post-action-undelete-post",
+ "flow-post-action-edit-post",
+ "flow-post-action-edit-post-submit",
+ "flow-post-action-edit-post-submit-anonymously",
+ "flow-post-action-hide-post",
+ "flow-post-action-unhide-post",
+ "flow-post-action-post-history",
+ "flow-post-action-view",
+ "flow-post-action-suppress-post",
+ "flow-post-action-unsuppress-post",
+ "flow-post-action-restore-post",
+ "flow-post-action-undo-moderation",
+ "flow-recent-topics",
+ "flow-reply-topic-title-placeholder",
+ "flow-sorting-tooltip-newest",
+ "flow-sorting-tooltip-recent",
+ "flow-toggle-small-topics",
+ "flow-toggle-topics",
+ "flow-toggle-topics-posts",
+ "flow-topic-collapse-siderail",
+ "flow-topic-comments",
+ "flow-topic-expand-siderail",
+ "flow-show-comments-title",
+ "flow-hide-comments-title",
+ "flow-topic-action-hide-topic",
+ "flow-topic-action-lock-topic",
+ "flow-topic-action-delete-topic",
+ "flow-topic-action-edit-title",
+ "flow-topic-action-hide-topic",
+ "flow-topic-action-history",
+ "flow-topic-action-resummarize-topic",
+ "flow-topic-action-summarize-topic",
+ "flow-topic-action-update-topic-summary",
+ "flow-topic-action-unlock-topic",
+ "flow-topic-action-suppress-topic",
+ "flow-topic-action-view",
+ "flow-topic-action-hide-topic",
+ "flow-topic-action-unhide-topic",
+ "flow-topic-action-delete-topic",
+ "flow-topic-action-undelete-topic",
+ "flow-topic-action-suppress-topic",
+ "flow-topic-action-unsuppress-topic",
+ "flow-topic-action-restore-topic",
+ "flow-topic-action-undo-moderation",
+ "flow-topic-action-watchlist-add",
+ "flow-topic-action-watchlist-remove",
+ "flow-hide-post-content",
+ "flow-delete-post-content",
+ "flow-suppress-post-content",
+ "flow-hide-title-content",
+ "flow-delete-title-content",
+ "flow-suppress-title-content",
+ "talkpagelinktext",
+ "flow-cancel-warning",
+ "flow-hide-title-content",
+ "flow-hide-post-content",
+ "flow-delete-title-content",
+ "flow-delete-post-content",
+ "flow-suppress-title-content",
+ "flow-suppress-post-content",
+ "blocklink",
+ "contribslink",
+ "flow-terms-of-use-new-topic",
+ "flow-terms-of-use-reply",
+ "flow-terms-of-use-edit",
+ "flow-terms-of-use-summarize",
+ "flow-terms-of-use-lock-topic",
+ "flow-terms-of-use-unlock-topic",
+ "flow-no-more-fwd",
+ "flow-topic-notification-subscribe-title",
+ "flow-topic-notification-subscribe-description",
+ "flow-board-notification-subscribe-title",
+ "flow-board-notification-subscribe-description",
+ "flow-moderation-title-unhide-post",
+ "flow-moderation-title-undelete-post",
+ "flow-moderation-title-unsuppress-post",
+ "flow-moderation-title-unhide-topic",
+ "flow-moderation-title-undelete-topic",
+ "flow-moderation-title-unsuppress-topic",
+ "flow-moderation-title-hide-post",
+ "flow-moderation-title-delete-post",
+ "flow-moderation-title-suppress-post",
+ "flow-moderation-title-hide-topic",
+ "flow-moderation-title-delete-topic",
+ "flow-moderation-title-suppress-topic",
+ "flow-moderation-placeholder-unhide-post",
+ "flow-moderation-placeholder-undelete-post",
+ "flow-moderation-placeholder-unsuppress-post",
+ "flow-moderation-placeholder-unhide-topic",
+ "flow-moderation-placeholder-undelete-topic",
+ "flow-moderation-placeholder-unsuppress-topic",
+ "flow-moderation-placeholder-hide-post",
+ "flow-moderation-placeholder-delete-post",
+ "flow-moderation-placeholder-suppress-post",
+ "flow-moderation-placeholder-hide-topic",
+ "flow-moderation-placeholder-delete-topic",
+ "flow-moderation-placeholder-suppress-topic",
+ "flow-moderation-confirm-unhide-post",
+ "flow-moderation-confirm-undelete-post",
+ "flow-moderation-confirm-unsuppress-post",
+ "flow-moderation-confirm-unhide-topic",
+ "flow-moderation-confirm-undelete-topic",
+ "flow-moderation-confirm-unsuppress-topic",
+ "flow-moderation-confirm-hide-post",
+ "flow-moderation-confirm-delete-post",
+ "flow-moderation-confirm-suppress-post",
+ "flow-moderation-confirm-hide-topic",
+ "flow-moderation-confirm-delete-topic",
+ "flow-moderation-confirm-suppress-topic",
+ "flow-moderation-confirmation-hide-topic",
+ "flow-moderation-confirmation-delete-topic",
+ "flow-moderation-confirmation-suppress-topic",
+ "flow-topic-moderated-reason-prefix",
+ "flow-rev-message-lock-topic-reason",
+ "flow-rev-message-restore-topic-reason",
+ "flow-post-undo-hide",
+ "flow-post-undo-delete",
+ "flow-post-undo-suppress",
+ "flow-topic-undo-hide",
+ "flow-topic-undo-delete",
+ "flow-topic-undo-suppress",
+ "flow-edited",
+ "flow-edited-by",
+ "flow-board-header-browse-topics-link",
+ "flow-wikitext-editor-help",
+ "flow-wikitext-editor-help-and-preview",
+ "flow-wikitext-editor-help-uses-wikitext",
+ "flow-wikitext-editor-help-preview-the-result"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.mediawiki.ui.text": {
+ "position": "top",
+ "styles": [
+ "styles/mediawiki.ui/text.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.mediawiki.ui.form": {
+ "position": "top",
+ "styles": [
+ "styles/mediawiki.ui/forms.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.styles.base": {
+ "position": "top",
+ "styles": [
+ "styles/common.less",
+ "styles/errors.less",
+ "styles/history/history-line.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.board.styles": {
+ "position": "top",
+ "styles": [
+ "styles/board/header.less",
+ "styles/board/menu.less",
+ "styles/board/navigation.less",
+ "styles/board/moderated.less",
+ "styles/board/timestamps.less",
+ "styles/board/replycount.less",
+ "styles/nojs.less",
+ "styles/js.less",
+ "styles/board/form-actions.less",
+ "styles/board/terms-of-use.less",
+ "styles/board/editor-switcher.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.board.topic.styles": {
+ "position": "top",
+ "styles": [
+ "styles/board/topic/titlebar.less",
+ "styles/board/topic/meta.less",
+ "styles/board/topic/post.less",
+ "styles/board/topic/summary.less",
+ "styles/board/topic/watchlist.less"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "mediawiki.template.handlebars": {
+ "localBasePath": "",
+ "remoteExtPath": "Flow",
+ "scripts": [
+ "vendor/modules/handlebars-v3.0.0.js",
+ "modules/handlebars.js"
+ ],
+ "dependencies": [
+ "mediawiki.template"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.components": {
+ "scripts": [
+ "engine/components/flow-registry.js",
+ "engine/components/flow-component.js",
+ "engine/misc/flow-api.js",
+ "engine/misc/flow-eventlog.js",
+ "engine/components/common/flow-component-engines.js",
+ "engine/components/common/flow-component-events.js",
+ "engine/components/board/base/flow-boardandhistory-base.js",
+ "engine/components/board/flow-board.js"
+ ],
+ "dependencies": [
+ "oojs",
+ "ext.flow.templating",
+ "ext.flow.jquery.findWithParent",
+ "mediawiki.api",
+ "mediawiki.Title",
+ "mediawiki.user",
+ "mediawiki.Uri",
+ "jquery.throttle-debounce"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.dm": {
+ "scripts": [
+ "flow/mw.flow.js",
+ "flow/dm/mw.flow.dm.js",
+ "flow/dm/mw.flow.dm.Content.js",
+ "flow/dm/mw.flow.dm.Item.js",
+ "flow/dm/mixins/mw.flow.dm.List.js",
+ "flow/dm/api/mw.flow.dm.APIHandler.js",
+ "flow/dm/mw.flow.dm.Captcha.js",
+ "flow/dm/mw.flow.dm.RevisionedContent.js",
+ "flow/dm/mw.flow.dm.ModeratedRevisionedContent.js",
+ "flow/dm/mw.flow.dm.BoardDescription.js",
+ "flow/dm/mw.flow.dm.System.js",
+ "flow/dm/mw.flow.dm.Post.js",
+ "flow/dm/mw.flow.dm.Topic.js",
+ "flow/dm/mw.flow.dm.Board.js",
+ "flow/dm/mw.flow.dm.CategoryItem.js",
+ "flow/dm/mw.flow.dm.Categories.js"
+ ],
+ "dependencies": [
+ "mediawiki.api",
+ "oojs"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.ui": {
+ "scripts": [
+ "flow/ui/mw.flow.ui.js",
+ "flow/ui/widgets/mw.flow.ui.CaptchaWidget.js",
+ "flow/ui/mw.flow.ui.Overlay.js",
+ "flow/ui/mw.flow.ui.CancelConfirmDialog.js",
+ "flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js",
+ "flow/ui/widgets/mw.flow.ui.ToCWidget.js",
+ "flow/ui/widgets/mw.flow.ui.ReorderTopicsWidget.js",
+ "flow/ui/widgets/mw.flow.ui.NavigationWidget.js",
+ "flow/ui/widgets/mw.flow.ui.ReplyWidget.js",
+ "flow/ui/widgets/mw.flow.ui.EditPostWidget.js",
+ "flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js",
+ "flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js",
+ "flow/ui/widgets/mw.flow.ui.NewTopicWidget.js",
+ "flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js",
+ "flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js",
+ "flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js",
+ "flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js",
+ "flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js",
+ "flow/ui/widgets/editor/mw.flow.ui.CanNotEditWidget.js",
+ "flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js",
+ "flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js",
+ "flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js",
+ "flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js",
+ "flow/ui/widgets/mw.flow.ui.CategoryItemWidget.js",
+ "flow/ui/widgets/mw.flow.ui.CategoriesWidget.js"
+ ],
+ "styles": [
+ "styles/flow/mw.flow.ui.Overlay.less",
+ "styles/flow/widgets/mw.flow.ui.NavigationWidget.less",
+ "styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less",
+ "styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less",
+ "styles/flow/widgets/mw.flow.ui.ReplyWidget.less",
+ "styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less",
+ "styles/flow/widgets/mw.flow.ui.NewTopicWidget.less",
+ "styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less",
+ "styles/flow/widgets/editor/mw.flow.ui.CanNotEditWidget.less",
+ "styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less",
+ "styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less",
+ "styles/flow/widgets/editor/mw.flow.ui.EditorWidget.less",
+ "styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less",
+ "styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less",
+ "styles/flow/widgets/mw.flow.ui.CategoriesWidget.less",
+ "styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less"
+ ],
+ "skinStyles": {
+ "vector": [
+ "styles/flow/widgets/editor/mw.flow.ui.editor-vector.less"
+ ],
+ "monobook": [
+ "styles/flow/widgets/editor/mw.flow.ui.editor-monobook.less"
+ ]
+ },
+ "messages": [
+ "flow-error-can-not-edit-logged-in",
+ "flow-error-can-not-edit-logged-out",
+ "flow-error-protected-autoconfirmed-logged-in",
+ "flow-error-protected-autoconfirmed-logged-out",
+ "flow-error-protected-sysop-logged-in",
+ "flow-error-protected-sysop-logged-out",
+ "flow-error-protected-unknown-reason",
+ "flow-error-parsoid-failure",
+ "flow-error-default",
+ "flow-dialog-cancelconfirm-title",
+ "flow-dialog-cancelconfirm-message",
+ "flow-dialog-cancelconfirm-keep",
+ "flow-dialog-cancelconfirm-discard",
+ "flow-spam-confirmedit-using-failure",
+ "flow-wikitext-switch-editor-tooltip",
+ "flow-cancel-warning",
+ "red-link-title",
+ "pagecategories",
+ "colon-separator"
+ ],
+ "dependencies": [
+ "oojs-ui",
+ "ext.flow.dm",
+ "oojs-ui.styles.icons-editing-advanced",
+ "mediawiki.api",
+ "mediawiki.api.options",
+ "mediawiki.Title",
+ "mediawiki.user",
+ "mediawiki.util",
+ "ext.visualEditor.supportCheck"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow": {
+ "position": "top",
+ "styles": [
+ "styles/mediawiki.ui/modal.less",
+ "styles/mediawiki.ui/tooltips.less",
+ "styles/js.less"
+ ],
+ "scripts": [
+ "engine/misc/mw-ui.enhance.js",
+ "engine/misc/mw-ui.modal.js",
+ "engine/components/common/flow-component-menus.js",
+ "engine/components/board/base/flow-board-api-events.js",
+ "engine/components/board/base/flow-board-interactive-events.js",
+ "engine/components/board/base/flow-board-load-events.js",
+ "engine/components/board/features/flow-board-loadmore.js",
+ "engine/components/board/features/flow-board-navigation.js",
+ "engine/components/board/features/flow-board-side-rail.js",
+ "engine/components/board/features/flow-board-visualeditor.js",
+ "engine/components/board/features/flow-board-switcheditor.js",
+ "engine/components/board/flow-boardhistory.js",
+ "mw.flow.Initializer.js",
+ "flow-initialize.js"
+ ],
+ "dependencies": [
+ "ext.flow.components",
+ "ext.flow.editor",
+ "jquery.throttle-debounce",
+ "mediawiki.jqueryMsg",
+ "ext.flow.jquery.conditionalScroll",
+ "ext.flow.ui",
+ "mediawiki.api",
+ "mediawiki.api.options",
+ "mediawiki.user",
+ "mediawiki.util"
+ ],
+ "messages": [
+ "flow-error-external",
+ "flow-error-http",
+ "mw-ui-unsubmitted-confirm",
+ "flow-reply-link",
+ "flow-reply-link-anonymously"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.undo": {
+ "position": "bottom",
+ "scripts": [
+ "engine/components/flow-undo-page.js"
+ ],
+ "dependencies": [
+ "ext.flow"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.editor": {
+ "scripts": [
+ "editor/editors/ext.flow.editors.AbstractEditor.js",
+ "editor/ext.flow.editor.js"
+ ],
+ "dependencies": [
+ "oojs",
+ "mediawiki.api",
+ "mediawiki.api.options",
+ "mediawiki.user"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.editors.none": {
+ "scripts": [
+ "editor/editors/ext.flow.editors.none.js"
+ ],
+ "messages": [
+ "flow-wikitext-switch-editor-tooltip"
+ ],
+ "dependencies": [
+ "oojs-ui"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.switching": {
+ "scripts": [
+ "flow/ui/tools/mw.flow.ui.MWEditModeTool.js"
+ ],
+ "dependencies": [
+ "ext.visualEditor.switching"
+ ]
+ },
+ "ext.flow.visualEditor": {
+ "scripts": [
+ "editor/editors/visualeditor/mw.flow.ve.Target.js",
+ "editor/editors/visualeditor/mw.flow.ve.UserCache.js",
+ "editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js",
+ "editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js",
+ "editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js",
+ "editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js",
+ "editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js",
+ "editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js",
+ "editor/editors/visualeditor/mw.flow.ve.SequenceRegistry.js"
+ ],
+ "styles": [
+ "editor/editors/visualeditor/mw.flow.ve.Target.less",
+ "editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less"
+ ],
+ "dependencies": [
+ "ext.visualEditor.core",
+ "ext.visualEditor.core.desktop",
+ "ext.visualEditor.mediawiki",
+ "ext.visualEditor.desktopTarget",
+ "ext.visualEditor.mwextensions.desktop",
+ "ext.flow.switching",
+ "oojs-ui.styles.icons-editing-advanced",
+ "site",
+ "user",
+ "mediawiki.api",
+ "mediawiki.util",
+ "ext.flow.editors.none"
+ ],
+ "messages": [
+ "flow-ve-mention-context-item-label",
+ "flow-ve-mention-inspector-title",
+ "flow-ve-mention-inspector-remove-label",
+ "flow-ve-mention-inspector-invalid-user",
+ "flow-ve-mention-placeholder",
+ "flow-ve-mention-tool-title",
+ "flow-ve-switch-editor-tool-title"
+ ]
+ },
+ "ext.flow.editors.visualeditor": {
+ "scripts": "editor/editors/visualeditor/ext.flow.editors.visualeditor.js",
+ "dependencies": [],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "mediawiki.messagePoster.flow-board": {
+ "scripts": [
+ "messagePoster/ext.flow.messagePoster.js"
+ ],
+ "dependencies": [
+ "oojs",
+ "mediawiki.api",
+ "mediawiki.messagePoster"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.jquery.conditionalScroll": {
+ "scripts": [
+ "engine/misc/jquery.conditionalScroll.js"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ },
+ "ext.flow.jquery.findWithParent": {
+ "scripts": [
+ "engine/misc/jquery.findWithParent.js"
+ ],
+ "targets": [
+ "desktop",
+ "mobile"
+ ]
+ }
+ },
+ "ResourceFileModulePaths": {
+ "localBasePath": "modules",
+ "remoteExtPath": "Flow/modules"
+ },
+ "Hooks": {
+ "ResourceLoaderRegisterModules": "FlowHooks::onResourceLoaderRegisterModules",
+ "BeforePageDisplay": "FlowHooks::onBeforePageDisplay",
+ "LoadExtensionSchemaUpdates": "FlowHooks::getSchemaUpdates",
+ "GetPreferences": "FlowHooks::onGetPreferences",
+ "OldChangesListRecentChangesLine": "FlowHooks::onOldChangesListRecentChangesLine",
+ "ChangesListInsertArticleLink": "FlowHooks::onChangesListInsertArticleLink",
+ "ChangesListInitRows": "FlowHooks::onChangesListInitRows",
+ "EnhancedChangesList::getLogText": "FlowHooks::onGetLogText",
+ "EnhancedChangesListModifyLineData": "FlowHooks::onEnhancedChangesListModifyLineData",
+ "EnhancedChangesListModifyBlockLineData": "FlowHooks::onEnhancedChangesListModifyBlockLineData",
+ "ChangesListSpecialPageQuery": "FlowHooks::onChangesListSpecialPageQuery",
+ "SkinTemplateNavigation::Universal": "FlowHooks::onSkinTemplateNavigation",
+ "Article::MissingArticleConditions": "FlowHooks::onMissingArticleConditions",
+ "SpecialWatchlistGetNonRevisionTypes": "FlowHooks::onSpecialWatchlistGetNonRevisionTypes",
+ "UserGetReservedNames": "FlowHooks::onUserGetReservedNames",
+ "ResourceLoaderGetConfigVars": "FlowHooks::onResourceLoaderGetConfigVars",
+ "ContribsPager::reallyDoQuery": "FlowHooks::onContributionsQuery",
+ "DeletedContribsPager::reallyDoQuery": "FlowHooks::onDeletedContributionsQuery",
+ "ContributionsLineEnding": "FlowHooks::onContributionsLineEnding",
+ "DeletedContributionsLineEnding": "FlowHooks::onDeletedContributionsLineEnding",
+ "ApiFeedContributions::feedItem": "FlowHooks::onContributionsFeedItem",
+ "AbuseFilter-builder": "FlowHooks::onAbuseFilterBuilder",
+ "AbuseFilter-computeVariable": "FlowHooks::onAbuseFilterComputeVariable",
+ "AbortEmailNotification": "FlowHooks::onAbortEmailNotification",
+ "BeforeDisplayOrangeAlert": "FlowHooks::onBeforeDisplayOrangeAlert",
+ "EchoAbortEmailNotification": "FlowHooks::onEchoAbortEmailNotification",
+ "BeforeEchoEventInsert": "FlowHooks::onBeforeEchoEventInsert",
+ "ArticleEditUpdateNewTalk": "FlowHooks::onArticleEditUpdateNewTalk",
+ "InfoAction": "FlowHooks::onInfoAction",
+ "SpecialCheckUserGetLinksFromRow": "FlowHooks::onSpecialCheckUserGetLinksFromRow",
+ "CheckUserInsertForRecentChange": "FlowHooks::onCheckUserInsertForRecentChange",
+ "SkinMinervaDefaultModules": "FlowHooks::onSkinMinervaDefaultModules",
+ "IRCLineURL": "FlowHooks::onIRCLineURL",
+ "WhatLinksHereProps": "FlowHooks::onWhatLinksHereProps",
+ "ResourceLoaderTestModules": "FlowHooks::onResourceLoaderTestModules",
+ "ShowMissingArticle": "FlowHooks::onShowMissingArticle",
+ "WatchArticle": "FlowHooks::onWatchArticle",
+ "UnwatchArticle": "FlowHooks::onWatchArticle",
+ "MovePageCheckPermissions": "FlowHooks::onMovePageCheckPermissions",
+ "MovePageIsValidMove": "FlowHooks::onMovePageIsValidMove",
+ "TitleMoveStarting": "FlowHooks::onTitleMoveStarting",
+ "TitleMoveCompleting": "FlowHooks::onTitleMoveCompleting",
+ "TitleSquidURLs": "FlowHooks::onTitleSquidURLs",
+ "WatchlistEditorBuildRemoveLine": "FlowHooks::onWatchlistEditorBuildRemoveLine",
+ "WatchlistEditorBeforeFormRender": "FlowHooks::onWatchlistEditorBeforeFormRender",
+ "NamespaceIsMovable": "FlowHooks::onNamespaceIsMovable",
+ "CategoryViewer::doCategoryQuery": "FlowHooks::onCategoryViewerDoCategoryQuery",
+ "CategoryViewer::generateLink": "FlowHooks::onCategoryViewerGenerateLink",
+ "ArticleConfirmDelete": "FlowHooks::onArticleConfirmDelete",
+ "ArticleDelete": "FlowHooks::onArticleDelete",
+ "ArticleDeleteComplete": "FlowHooks::onArticleDeleteComplete",
+ "ArticleRevisionUndeleted": "FlowHooks::onArticleRevisionUndeleted",
+ "ArticleUndelete": "FlowHooks::onArticleUndelete",
+ "SearchableNamespaces": "FlowHooks::onSearchableNamespaces",
+ "ImportHandleToplevelXMLTag": "FlowHooks::onImportHandleToplevelXMLTag",
+ "UserMergeAccountFields": "FlowHooks::onUserMergeAccountFields",
+ "MergeAccountFromTo": "FlowHooks::onMergeAccountFromTo",
+ "LiquidThreadsIsLqtPage": "FlowHooks::onIsLiquidThreadsPage",
+ "BeforeCreateEchoEvent": "Flow\\NotificationController::onBeforeCreateEchoEvent",
+ "EchoGetBundleRules": "Flow\\NotificationController::onEchoGetBundleRules",
+ "GetBetaFeaturePreferences": "FlowHooks::onGetBetaFeaturePreferences",
+ "UserSaveOptions": "FlowHooks::onUserSaveOptions",
+ "NukeGetNewPages": "FlowHooks::onNukeGetNewPages",
+ "NukeDeletePage": "FlowHooks::onNukeDeletePage"
+ },
+ "namespaces": [
+ {
+ "id": 2600,
+ "constant": "NS_TOPIC",
+ "name": "Topic",
+ "subpages": false,
+ "defaultcontentmodel": "flow-board",
+ "capitallinkoverride": true
+ }
+ ],
+ "config": {
+ "FlowHelpPage": {
+ "value": "//www.mediawiki.org/wiki/Special:MyLanguage/Extension:Flow"
+ },
+ "FlowCluster": {
+ "value": false
+ },
+ "FlowDefaultWikiDb": {
+ "value": false
+ },
+ "FlowExternalStore": {
+ "value": false
+ },
+ "FlowContentFormat": {
+ "value": "html"
+ },
+ "FlowParsoidURL": {
+ "value": null
+ },
+ "FlowParsoidPrefix": {
+ "value": null
+ },
+ "FlowParsoidTimeout": {
+ "value": null
+ },
+ "FlowParsoidHTTPProxy": {
+ "value": null
+ },
+ "FlowParsoidForwardCookies": {
+ "value": false
+ },
+ "FlowDefaultLimit": {
+ "value": 10
+ },
+ "FlowMaxLimit": {
+ "value": 100
+ },
+ "FlowMaxMentionCount": {
+ "value": 50
+ },
+ "FlowMaxThreadingDepth": {
+ "value": 8
+ },
+ "FlowEditorList": {
+ "value": [
+ "visualeditor",
+ "wikitext"
+ ]
+ },
+ "FlowUseMemcache": {
+ "value": true
+ },
+ "FlowCacheTime": {
+ "value": 259200
+ },
+ "FlowCacheVersion": {
+ "value": "4.9"
+ },
+ "FlowSearchServers": {
+ "value": [
+ "localhost"
+ ]
+ },
+ "FlowSearchConnectionAttempts": {
+ "value": 1
+ },
+ "FlowSearchBannedPlugins": {
+ "value": []
+ },
+ "FlowSearchOptimizeIndexForExperimentalHighlighter": {
+ "value": false
+ },
+ "FlowSearchMaxShardsPerNode": {
+ "value": []
+ },
+ "FlowSearchRefreshInterval": {
+ "value": 1
+ },
+ "FlowSearchMaintenanceTimeout": {
+ "value": 3600
+ },
+ "FlowSearchReplicas": {
+ "value": "0-2"
+ },
+ "FlowSearchShardCount": {
+ "value": {
+ "flow": 4
+ }
+ },
+ "FlowSearchCacheWarmers": {
+ "value": []
+ },
+ "FlowSearchMergeSettings": {
+ "value": {
+ "flow": {
+ "max_merge_at_once": 10,
+ "segments_per_tier": 10,
+ "reclaim_deletes_weight": 2,
+ "max_merged_segment": "5g"
+ }
+ }
+ },
+ "FlowSearchIndexAllocation": {
+ "value": {
+ "include": [],
+ "exclude": [],
+ "require": []
+ }
+ },
+ "FlowSearchEnabled": {
+ "value": false
+ },
+ "FlowAbuseFilterGroup": {
+ "value": "flow"
+ },
+ "FlowAbuseFilterEmergencyDisableThreshold": {
+ "value": 0.1
+ },
+ "FlowAbuseFilterEmergencyDisableCount": {
+ "value": 50
+ },
+ "FlowAbuseFilterEmergencyDisableAge": {
+ "value": 86400
+ },
+ "FlowAjaxTimeout": {
+ "value": 30
+ },
+ "FlowCoreActionWhitelist": {
+ "value": [
+ "info",
+ "protect",
+ "unprotect",
+ "unwatch",
+ "watch",
+ "history",
+ "wikilove",
+ "move",
+ "delete"
+ ]
+ },
+ "FlowServerCompileTemplates": {
+ "value": false
+ },
+ "FlowEventLogging": {
+ "value": false
+ },
+ "FlowEnableOptInBetaFeature": {
+ "value": false
+ }
+ },
+ "load_composer_autoloader": true,
+ "manifest_version": 2,
+ "AutoloadClasses": {
+ "ExternalStoreFlowMock": "tests/phpunit/Mock/ExternalStoreFlowMock.php",
+ "FlowHooks": "Hooks.php",
+ "Flow\\Actions\\EditAction": "includes/Actions/EditAction.php",
+ "Flow\\Actions\\FlowAction": "includes/Actions/Action.php",
+ "Flow\\Actions\\PurgeAction": "includes/Actions/PurgeAction.php",
+ "Flow\\Actions\\ViewAction": "includes/Actions/ViewAction.php",
+ "Flow\\Api\\ApiFlow": "includes/Api/ApiFlow.php",
+ "Flow\\Api\\ApiFlowBase": "includes/Api/ApiFlowBase.php",
+ "Flow\\Api\\ApiFlowBaseGet": "includes/Api/ApiFlowBaseGet.php",
+ "Flow\\Api\\ApiFlowBasePost": "includes/Api/ApiFlowBasePost.php",
+ "Flow\\Api\\ApiFlowEditHeader": "includes/Api/ApiFlowEditHeader.php",
+ "Flow\\Api\\ApiFlowEditPost": "includes/Api/ApiFlowEditPost.php",
+ "Flow\\Api\\ApiFlowEditTitle": "includes/Api/ApiFlowEditTitle.php",
+ "Flow\\Api\\ApiFlowEditTopicSummary": "includes/Api/ApiFlowEditTopicSummary.php",
+ "Flow\\Api\\ApiFlowLockTopic": "includes/Api/ApiFlowLockTopic.php",
+ "Flow\\Api\\ApiFlowModeratePost": "includes/Api/ApiFlowModeratePost.php",
+ "Flow\\Api\\ApiFlowModerateTopic": "includes/Api/ApiFlowModerateTopic.php",
+ "Flow\\Api\\ApiFlowNewTopic": "includes/Api/ApiFlowNewTopic.php",
+ "Flow\\Api\\ApiFlowReply": "includes/Api/ApiFlowReply.php",
+ "Flow\\Api\\ApiFlowSearch": "includes/Api/ApiFlowSearch.php",
+ "Flow\\Api\\ApiFlowUndoEditHeader": "includes/Api/ApiFlowUndoEditHeader.php",
+ "Flow\\Api\\ApiFlowUndoEditPost": "includes/Api/ApiFlowUndoEditPost.php",
+ "Flow\\Api\\ApiFlowUndoEditTopicSummary": "includes/Api/ApiFlowUndoEditTopicSummary.php",
+ "Flow\\Api\\ApiFlowViewHeader": "includes/Api/ApiFlowViewHeader.php",
+ "Flow\\Api\\ApiFlowViewPost": "includes/Api/ApiFlowViewPost.php",
+ "Flow\\Api\\ApiFlowViewPostHistory": "includes/Api/ApiFlowViewPostHistory.php",
+ "Flow\\Api\\ApiFlowViewTopic": "includes/Api/ApiFlowViewTopic.php",
+ "Flow\\Api\\ApiFlowViewTopicHistory": "includes/Api/ApiFlowViewTopicHistory.php",
+ "Flow\\Api\\ApiFlowViewTopicList": "includes/Api/ApiFlowViewTopicList.php",
+ "Flow\\Api\\ApiFlowViewTopicSummary": "includes/Api/ApiFlowViewTopicSummary.php",
+ "Flow\\Api\\ApiParsoidUtilsFlow": "includes/Api/ApiParsoidUtilsFlow.php",
+ "Flow\\Api\\ApiQueryPropFlowInfo": "includes/Api/ApiQueryPropFlowInfo.php",
+ "Flow\\BlockFactory": "includes/BlockFactory.php",
+ "Flow\\Block\\AbstractBlock": "includes/Block/Block.php",
+ "Flow\\Block\\Block": "includes/Block/Block.php",
+ "Flow\\Block\\BoardHistoryBlock": "includes/Block/BoardHistory.php",
+ "Flow\\Block\\HeaderBlock": "includes/Block/Header.php",
+ "Flow\\Block\\TopicBlock": "includes/Block/Topic.php",
+ "Flow\\Block\\TopicListBlock": "includes/Block/TopicList.php",
+ "Flow\\Block\\TopicSummaryBlock": "includes/Block/TopicSummary.php",
+ "Flow\\BoardMover": "includes/BoardMover.php",
+ "Flow\\Collection\\AbstractCollection": "includes/Collection/AbstractCollection.php",
+ "Flow\\Collection\\CollectionCache": "includes/Collection/CollectionCache.php",
+ "Flow\\Collection\\HeaderCollection": "includes/Collection/HeaderCollection.php",
+ "Flow\\Collection\\LocalCacheAbstractCollection": "includes/Collection/LocalCacheAbstractCollection.php",
+ "Flow\\Collection\\PostCollection": "includes/Collection/PostCollection.php",
+ "Flow\\Collection\\PostSummaryCollection": "includes/Collection/PostSummaryCollection.php",
+ "Flow\\Container": "includes/Container.php",
+ "Flow\\Content\\BoardContent": "includes/Content/BoardContent.php",
+ "Flow\\Content\\BoardContentHandler": "includes/Content/BoardContentHandler.php",
+ "Flow\\Conversion\\Utils": "includes/Conversion/Utils.php",
+ "Flow\\Data\\Compactor": "includes/Data/Compactor.php",
+ "Flow\\Data\\Compactor\\FeatureCompactor": "includes/Data/Compactor/FeatureCompactor.php",
+ "Flow\\Data\\Compactor\\ShallowCompactor": "includes/Data/Compactor/ShallowCompactor.php",
+ "Flow\\Data\\FlowObjectCache": "includes/Data/FlowObjectCache.php",
+ "Flow\\Data\\Index": "includes/Data/Index.php",
+ "Flow\\Data\\Index\\BoardHistoryIndex": "includes/Data/Index/BoardHistoryIndex.php",
+ "Flow\\Data\\Index\\FeatureIndex": "includes/Data/Index/FeatureIndex.php",
+ "Flow\\Data\\Index\\PostRevisionBoardHistoryIndex": "includes/Data/Index/PostRevisionBoardHistoryIndex.php",
+ "Flow\\Data\\Index\\PostRevisionTopicHistoryIndex": "includes/Data/Index/PostRevisionTopicHistoryIndex.php",
+ "Flow\\Data\\Index\\PostSummaryRevisionBoardHistoryIndex": "includes/Data/Index/PostSummaryRevisionBoardHistoryIndex.php",
+ "Flow\\Data\\Index\\TopKIndex": "includes/Data/Index/TopKIndex.php",
+ "Flow\\Data\\Index\\UniqueFeatureIndex": "includes/Data/Index/UniqueFeatureIndex.php",
+ "Flow\\Data\\LifecycleHandler": "includes/Data/LifecycleHandler.php",
+ "Flow\\Data\\Listener\\AbstractListener": "includes/Data/Listener/AbstractListener.php",
+ "Flow\\Data\\Listener\\AbstractTopicInsertListener": "includes/Data/Listener/WatchTopicListener.php",
+ "Flow\\Data\\Listener\\DeferredInsertLifecycleHandler": "includes/Data/Listener/DeferredInsertLifecycleHandler.php",
+ "Flow\\Data\\Listener\\EditCountListener": "includes/Data/Listener/EditCountListener.php",
+ "Flow\\Data\\Listener\\ImmediateWatchTopicListener": "includes/Data/Listener/WatchTopicListener.php",
+ "Flow\\Data\\Listener\\ModerationLoggingListener": "includes/Data/Listener/ModerationLoggingListener.php",
+ "Flow\\Data\\Listener\\NotificationListener": "includes/Data/Listener/NotificationListener.php",
+ "Flow\\Data\\Listener\\RecentChangesListener": "includes/Data/Listener/RecentChangesListener.php",
+ "Flow\\Data\\Listener\\ReferenceRecorder": "includes/Data/Listener/ReferenceRecorder.php",
+ "Flow\\Data\\Listener\\TopicPageCreationListener": "includes/Data/Listener/TopicPageCreationListener.php",
+ "Flow\\Data\\Listener\\UserNameListener": "includes/Data/Listener/UserNameListener.php",
+ "Flow\\Data\\Listener\\WorkflowTopicListListener": "includes/Data/Listener/WorkflowTopicListListener.php",
+ "Flow\\Data\\ManagerGroup": "includes/Data/ManagerGroup.php",
+ "Flow\\Data\\Mapper\\BasicObjectMapper": "includes/Data/Mapper/BasicObjectMapper.php",
+ "Flow\\Data\\Mapper\\CachingObjectMapper": "includes/Data/Mapper/CachingObjectMapper.php",
+ "Flow\\Data\\ObjectLocator": "includes/Data/ObjectLocator.php",
+ "Flow\\Data\\ObjectManager": "includes/Data/ObjectManager.php",
+ "Flow\\Data\\ObjectMapper": "includes/Data/ObjectMapper.php",
+ "Flow\\Data\\ObjectStorage": "includes/Data/ObjectStorage.php",
+ "Flow\\Data\\Pager\\HistoryPager": "includes/Data/Pager/HistoryPager.php",
+ "Flow\\Data\\Pager\\Pager": "includes/Data/Pager/Pager.php",
+ "Flow\\Data\\Pager\\PagerPage": "includes/Data/Pager/PagerPage.php",
+ "Flow\\Data\\Storage\\BasicDbStorage": "includes/Data/Storage/BasicDbStorage.php",
+ "Flow\\Data\\Storage\\BoardHistoryStorage": "includes/Data/Storage/BoardHistoryStorage.php",
+ "Flow\\Data\\Storage\\DbStorage": "includes/Data/Storage/DbStorage.php",
+ "Flow\\Data\\Storage\\HeaderRevisionStorage": "includes/Data/Storage/HeaderRevisionStorage.php",
+ "Flow\\Data\\Storage\\PostRevisionBoardHistoryStorage": "includes/Data/Storage/PostRevisionBoardHistoryStorage.php",
+ "Flow\\Data\\Storage\\PostRevisionStorage": "includes/Data/Storage/PostRevisionStorage.php",
+ "Flow\\Data\\Storage\\PostRevisionTopicHistoryStorage": "includes/Data/Storage/PostRevisionTopicHistoryStorage.php",
+ "Flow\\Data\\Storage\\PostSummaryRevisionBoardHistoryStorage": "includes/Data/Storage/PostSummaryRevisionBoardHistoryStorage.php",
+ "Flow\\Data\\Storage\\PostSummaryRevisionStorage": "includes/Data/Storage/PostSummaryRevisionStorage.php",
+ "Flow\\Data\\Storage\\RevisionStorage": "includes/Data/Storage/RevisionStorage.php",
+ "Flow\\Data\\Storage\\TopicListStorage": "includes/Data/Storage/TopicListStorage.php",
+ "Flow\\Data\\Utils\\Merger": "includes/Data/Utils/Merger.php",
+ "Flow\\Data\\Utils\\MultiDimArray": "includes/Data/Utils/MultiDimArray.php",
+ "Flow\\Data\\Utils\\RawSql": "includes/Data/Utils/RawSql.php",
+ "Flow\\Data\\Utils\\RecentChangeFactory": "includes/Data/Utils/RecentChangeFactory.php",
+ "Flow\\Data\\Utils\\ResultDuplicator": "includes/Data/Utils/ResultDuplicator.php",
+ "Flow\\Data\\Utils\\SortArrayByKeys": "includes/Data/Utils/SortArrayByKeys.php",
+ "Flow\\Data\\Utils\\SortRevisionsByRevisionId": "includes/Data/Utils/SortRevisionsByRevisionId.php",
+ "Flow\\Data\\Utils\\UserMerger": "includes/Data/Utils/UserMerger.php",
+ "Flow\\DbFactory": "includes/DbFactory.php",
+ "Flow\\Dump\\Exporter": "includes/Dump/Exporter.php",
+ "Flow\\Dump\\Importer": "includes/Dump/Importer.php",
+ "Flow\\Exception\\CatchableFatalErrorException": "includes/Exception/CatchableFatalErrorException.php",
+ "Flow\\Exception\\CrossWikiException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\DataModelException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\DataPersistenceException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\FailCommitException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\FlowException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidActionException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidDataException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidInputException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidParameterException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidReferenceException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\InvalidTopicUuidException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\NoIndexException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\NoParserException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\PermissionException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\UnknownWorkflowIdException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\WikitextException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\Exception\\WrongNumberArgumentsException": "includes/Exception/ExceptionHandling.php",
+ "Flow\\FlowActions": "includes/FlowActions.php",
+ "Flow\\FlowEnabledOnTalkpagePresentationModel": "includes/Notifications/FlowEnabledOnTalkpagePresentationModel.php",
+ "Flow\\FlowPresentationModel": "includes/Notifications/FlowPresentationModel.php",
+ "Flow\\Formatter\\AbstractFormatter": "includes/Formatter/AbstractFormatter.php",
+ "Flow\\Formatter\\AbstractQuery": "includes/Formatter/AbstractQuery.php",
+ "Flow\\Formatter\\BaseTopicListFormatter": "includes/Formatter/BaseTopicListFormatter.php",
+ "Flow\\Formatter\\BoardHistoryQuery": "includes/Formatter/BoardHistoryQuery.php",
+ "Flow\\Formatter\\CategoryViewerFormatter": "includes/Formatter/CategoryViewerFormatter.php",
+ "Flow\\Formatter\\CategoryViewerQuery": "includes/Formatter/CategoryViewerQuery.php",
+ "Flow\\Formatter\\ChangesListFormatter": "includes/Formatter/ChangesListFormatter.php",
+ "Flow\\Formatter\\ChangesListQuery": "includes/Formatter/ChangesListQuery.php",
+ "Flow\\Formatter\\CheckUserFormatter": "includes/Formatter/CheckUserFormatter.php",
+ "Flow\\Formatter\\CheckUserQuery": "includes/Formatter/CheckUserQuery.php",
+ "Flow\\Formatter\\CheckUserRow": "includes/Formatter/CheckUserQuery.php",
+ "Flow\\Formatter\\ContributionsFormatter": "includes/Formatter/ContributionsFormatter.php",
+ "Flow\\Formatter\\ContributionsQuery": "includes/Formatter/ContributionsQuery.php",
+ "Flow\\Formatter\\ContributionsRow": "includes/Formatter/ContributionsQuery.php",
+ "Flow\\Formatter\\DeletedContributionsRow": "includes/Formatter/ContributionsQuery.php",
+ "Flow\\Formatter\\FeedItemFormatter": "includes/Formatter/FeedItemFormatter.php",
+ "Flow\\Formatter\\FormatterRow": "includes/Formatter/AbstractQuery.php",
+ "Flow\\Formatter\\HeaderViewQuery": "includes/Formatter/RevisionViewQuery.php",
+ "Flow\\Formatter\\HistoryQuery": "includes/Formatter/HistoryQuery.php",
+ "Flow\\Formatter\\IRCLineUrlFormatter": "includes/Formatter/IRCLineUrlFormatter.php",
+ "Flow\\Formatter\\PostHistoryQuery": "includes/Formatter/PostHistoryQuery.php",
+ "Flow\\Formatter\\PostSummaryQuery": "includes/Formatter/PostSummaryQuery.php",
+ "Flow\\Formatter\\PostSummaryViewQuery": "includes/Formatter/RevisionViewQuery.php",
+ "Flow\\Formatter\\PostViewQuery": "includes/Formatter/RevisionViewQuery.php",
+ "Flow\\Formatter\\RecentChangesRow": "includes/Formatter/ChangesListQuery.php",
+ "Flow\\Formatter\\RevisionDiffViewFormatter": "includes/Formatter/RevisionDiffViewFormatter.php",
+ "Flow\\Formatter\\RevisionFormatter": "includes/Formatter/RevisionFormatter.php",
+ "Flow\\Formatter\\RevisionUndoViewFormatter": "includes/Formatter/RevisionUndoViewFormatter.php",
+ "Flow\\Formatter\\RevisionViewFormatter": "includes/Formatter/RevisionViewFormatter.php",
+ "Flow\\Formatter\\RevisionViewQuery": "includes/Formatter/RevisionViewQuery.php",
+ "Flow\\Formatter\\SinglePostQuery": "includes/Formatter/SinglePostQuery.php",
+ "Flow\\Formatter\\TocTopicListFormatter": "includes/Formatter/TocTopicListFormatter.php",
+ "Flow\\Formatter\\TopicFormatter": "includes/Formatter/TopicFormatter.php",
+ "Flow\\Formatter\\TopicHistoryQuery": "includes/Formatter/TopicHistoryQuery.php",
+ "Flow\\Formatter\\TopicListFormatter": "includes/Formatter/TopicListFormatter.php",
+ "Flow\\Formatter\\TopicListQuery": "includes/Formatter/TopicListQuery.php",
+ "Flow\\Formatter\\TopicRow": "includes/Formatter/TopicRow.php",
+ "Flow\\HeaderEditedPresentationModel": "includes/Notifications/HeaderEditedPresentationModel.php",
+ "Flow\\Import\\ArchiveNameHelper": "includes/Import/ArchiveNameHelper.php",
+ "Flow\\Import\\Converter": "includes/Import/Converter.php",
+ "Flow\\Import\\EnableFlow\\EnableFlowWikitextConversionStrategy": "includes/Import/EnableFlow/EnableFlowWikitextConversionStrategy.php",
+ "Flow\\Import\\HistoricalUIDGenerator": "includes/Import/Importer.php",
+ "Flow\\Import\\IConversionStrategy": "includes/Import/IConversionStrategy.php",
+ "Flow\\Import\\IImportHeader": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IImportObject": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IImportPost": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IImportSource": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IImportSummary": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IImportTopic": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IObjectRevision": "includes/Import/ImportSource.php",
+ "Flow\\Import\\IRevisionableObject": "includes/Import/ImportSource.php",
+ "Flow\\Import\\ImportException": "includes/Import/Exception.php",
+ "Flow\\Import\\Importer": "includes/Import/Importer.php",
+ "Flow\\Import\\LiquidThreadsApi\\ApiBackend": "includes/Import/LiquidThreadsApi/Source.php",
+ "Flow\\Import\\LiquidThreadsApi\\ApiNotFoundException": "includes/Import/LiquidThreadsApi/Exception.php",
+ "Flow\\Import\\LiquidThreadsApi\\CachedApiData": "includes/Import/LiquidThreadsApi/CachedData.php",
+ "Flow\\Import\\LiquidThreadsApi\\CachedData": "includes/Import/LiquidThreadsApi/CachedData.php",
+ "Flow\\Import\\LiquidThreadsApi\\CachedPageData": "includes/Import/LiquidThreadsApi/CachedData.php",
+ "Flow\\Import\\LiquidThreadsApi\\CachedThreadData": "includes/Import/LiquidThreadsApi/CachedData.php",
+ "Flow\\Import\\LiquidThreadsApi\\ConversionStrategy": "includes/Import/LiquidThreadsApi/ConversionStrategy.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportHeader": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportPost": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportRevision": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportSource": "includes/Import/LiquidThreadsApi/Source.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportSummary": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\ImportTopic": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\LocalApiBackend": "includes/Import/LiquidThreadsApi/Source.php",
+ "Flow\\Import\\LiquidThreadsApi\\MovedImportPost": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\MovedImportRevision": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\MovedImportTopic": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\PageRevisionedObject": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\RemoteApiBackend": "includes/Import/LiquidThreadsApi/Source.php",
+ "Flow\\Import\\LiquidThreadsApi\\ReplyIterator": "includes/Import/LiquidThreadsApi/Iterators.php",
+ "Flow\\Import\\LiquidThreadsApi\\RevisionIterator": "includes/Import/LiquidThreadsApi/Iterators.php",
+ "Flow\\Import\\LiquidThreadsApi\\ScriptedImportRevision": "includes/Import/LiquidThreadsApi/Objects.php",
+ "Flow\\Import\\LiquidThreadsApi\\TopicIterator": "includes/Import/LiquidThreadsApi/Iterators.php",
+ "Flow\\Import\\OptInController": "includes/Import/OptInController.php",
+ "Flow\\Import\\OptInUpdate": "includes/Import/OptInUpdate.php",
+ "Flow\\Import\\PageImportState": "includes/Import/Importer.php",
+ "Flow\\Import\\Plain\\ImportHeader": "includes/Import/Plain/ImportHeader.php",
+ "Flow\\Import\\Plain\\ObjectRevision": "includes/Import/Plain/ObjectRevision.php",
+ "Flow\\Import\\Postprocessor\\LqtNotifications": "includes/Import/Postprocessor/LqtNotifications.php",
+ "Flow\\Import\\Postprocessor\\LqtRedirector": "includes/Import/Postprocessor/LqtRedirector.php",
+ "Flow\\Import\\Postprocessor\\PostprocessingException": "includes/Import/Postprocessor/PostprocessingException.php",
+ "Flow\\Import\\Postprocessor\\Postprocessor": "includes/Import/Postprocessor/Postprocessor.php",
+ "Flow\\Import\\Postprocessor\\ProcessorGroup": "includes/Import/Postprocessor/ProcessorGroup.php",
+ "Flow\\Import\\Postprocessor\\SpecialLogTopic": "includes/Import/Postprocessor/SpecialLogTopic.php",
+ "Flow\\Import\\SourceStore\\Exception": "includes/Import/SourceStore/Exception.php",
+ "Flow\\Import\\SourceStore\\FileImportSourceStore": "includes/Import/SourceStore/FileImportSourceStore.php",
+ "Flow\\Import\\SourceStore\\FlowRevisionsDb": "includes/Import/SourceStore/FlowRevisionsDb.php",
+ "Flow\\Import\\SourceStore\\NullImportSourceStore": "includes/Import/SourceStore/NullImportSourceStore.php",
+ "Flow\\Import\\SourceStore\\SourceStoreInterface": "includes/Import/SourceStore/SourceStoreInterface.php",
+ "Flow\\Import\\TalkpageImportOperation": "includes/Import/Importer.php",
+ "Flow\\Import\\TemplateHelper": "includes/Import/TemplateHelper.php",
+ "Flow\\Import\\TopicImportState": "includes/Import/Importer.php",
+ "Flow\\Import\\Wikitext\\ConversionStrategy": "includes/Import/Wikitext/ConversionStrategy.php",
+ "Flow\\Import\\Wikitext\\ImportSource": "includes/Import/Wikitext/ImportSource.php",
+ "Flow\\LinksTableUpdater": "includes/LinksTableUpdater.php",
+ "Flow\\Log\\ActionFormatter": "includes/Log/ActionFormatter.php",
+ "Flow\\Log\\LogQuery": "includes/Log/Query.php",
+ "Flow\\Log\\LqtImportFormatter": "includes/Log/LqtImportFormatter.php",
+ "Flow\\Log\\ModerationLogger": "includes/Log/ModerationLogger.php",
+ "Flow\\MentionPresentationModel": "includes/Notifications/MentionPresentationModel.php",
+ "Flow\\MentionStatusPresentationModel": "includes/Notifications/MentionStatusPresentationModel.php",
+ "Flow\\Model\\AbstractRevision": "includes/Model/AbstractRevision.php",
+ "Flow\\Model\\AbstractSummary": "includes/Model/AbstractSummary.php",
+ "Flow\\Model\\Anchor": "includes/Model/Anchor.php",
+ "Flow\\Model\\Header": "includes/Model/Header.php",
+ "Flow\\Model\\HtmlRenderingInformation": "includes/Model/HtmlRenderingInformation.php",
+ "Flow\\Model\\PostRevision": "includes/Model/PostRevision.php",
+ "Flow\\Model\\PostSummary": "includes/Model/PostSummary.php",
+ "Flow\\Model\\Reference": "includes/Model/Reference.php",
+ "Flow\\Model\\TopicListEntry": "includes/Model/TopicListEntry.php",
+ "Flow\\Model\\URLReference": "includes/Model/URLReference.php",
+ "Flow\\Model\\UUID": "includes/Model/UUID.php",
+ "Flow\\Model\\UUIDBlob": "includes/Model/UUID.php",
+ "Flow\\Model\\UserTuple": "includes/Model/UserTuple.php",
+ "Flow\\Model\\WikiReference": "includes/Model/WikiReference.php",
+ "Flow\\Model\\Workflow": "includes/Model/Workflow.php",
+ "Flow\\NewTopicPresentationModel": "includes/Notifications/NewTopicPresentationModel.php",
+ "Flow\\NotificationController": "includes/Notifications/Controller.php",
+ "Flow\\NotificationsUserLocator": "includes/Notifications/UserLocator.php",
+ "Flow\\OOUI\\BoardDescriptionWidget": "includes/OOUI/BoardDescriptionWidget.php",
+ "Flow\\OccupationController": "includes/TalkpageManager.php",
+ "Flow\\Parsoid\\ContentFixer": "includes/Parsoid/ContentFixer.php",
+ "Flow\\Parsoid\\Extractor": "includes/Parsoid/Extractor.php",
+ "Flow\\Parsoid\\Extractor\\CategoryExtractor": "includes/Parsoid/Extractor/CategoryExtractor.php",
+ "Flow\\Parsoid\\Extractor\\ExtLinkExtractor": "includes/Parsoid/Extractor/ExtLinkExtractor.php",
+ "Flow\\Parsoid\\Extractor\\ImageExtractor": "includes/Parsoid/Extractor/ImageExtractor.php",
+ "Flow\\Parsoid\\Extractor\\PlaceholderExtractor": "includes/Parsoid/Extractor/PlaceholderExtractor.php",
+ "Flow\\Parsoid\\Extractor\\TransclusionExtractor": "includes/Parsoid/Extractor/TransclusionExtractor.php",
+ "Flow\\Parsoid\\Extractor\\WikiLinkExtractor": "includes/Parsoid/Extractor/WikiLinkExtractor.php",
+ "Flow\\Parsoid\\Fixer": "includes/Parsoid/Fixer.php",
+ "Flow\\Parsoid\\Fixer\\BadImageRemover": "includes/Parsoid/Fixer/BadImageRemover.php",
+ "Flow\\Parsoid\\Fixer\\BaseHrefFixer": "includes/Parsoid/Fixer/BaseHrefFixer.php",
+ "Flow\\Parsoid\\Fixer\\ExtLinkFixer": "includes/Parsoid/Fixer/ExtLinkFixer.php",
+ "Flow\\Parsoid\\Fixer\\WikiLinkFixer": "includes/Parsoid/Fixer/WikiLinkFixer.php",
+ "Flow\\Parsoid\\ReferenceExtractor": "includes/Parsoid/ReferenceExtractor.php",
+ "Flow\\Parsoid\\ReferenceFactory": "includes/Parsoid/ReferenceFactory.php",
+ "Flow\\PostEditedPresentationModel": "includes/Notifications/PostEditedPresentationModel.php",
+ "Flow\\PostReplyPresentationModel": "includes/Notifications/PostReplyPresentationModel.php",
+ "Flow\\RecoverableErrorHandler": "includes/RecoverableErrorHandler.php",
+ "Flow\\ReferenceClarifier": "includes/ReferenceClarifier.php",
+ "Flow\\Repository\\MultiGetList": "includes/Repository/MultiGetList.php",
+ "Flow\\Repository\\RootPostLoader": "includes/Repository/RootPostLoader.php",
+ "Flow\\Repository\\TitleRepository": "includes/Repository/TitleRepository.php",
+ "Flow\\Repository\\TreeCacheKey": "includes/Repository/TreeCacheKey.php",
+ "Flow\\Repository\\TreeRepository": "includes/Repository/TreeRepository.php",
+ "Flow\\Repository\\UserNameBatch": "includes/Repository/UserNameBatch.php",
+ "Flow\\Repository\\UserName\\OneStepUserNameQuery": "includes/Repository/UserName/OneStepUserNameQuery.php",
+ "Flow\\Repository\\UserName\\TwoStepUserNameQuery": "includes/Repository/UserName/TwoStepUserNameQuery.php",
+ "Flow\\Repository\\UserName\\UserNameQuery": "includes/Repository/UserName/UserNameQuery.php",
+ "Flow\\RevisionActionPermissions": "includes/RevisionActionPermissions.php",
+ "Flow\\Search\\Connection": "includes/Search/Connection.php",
+ "Flow\\Search\\Iterators\\AbstractIterator": "includes/Search/Iterators/AbstractIterator.php",
+ "Flow\\Search\\Iterators\\HeaderIterator": "includes/Search/Iterators/HeaderIterator.php",
+ "Flow\\Search\\Iterators\\TopicIterator": "includes/Search/Iterators/TopicIterator.php",
+ "Flow\\Search\\Maintenance\\MappingConfigBuilder": "includes/Search/maintenance/MappingConfigBuilder.php",
+ "Flow\\Search\\SearchEngine": "includes/Search/SearchEngine.php",
+ "Flow\\Search\\Searcher": "includes/Search/Searcher.php",
+ "Flow\\Search\\Updaters\\AbstractUpdater": "includes/Search/Updaters/AbstractUpdater.php",
+ "Flow\\Search\\Updaters\\HeaderUpdater": "includes/Search/Updaters/HeaderUpdater.php",
+ "Flow\\Search\\Updaters\\TopicUpdater": "includes/Search/Updaters/TopicUpdater.php",
+ "Flow\\SpamFilter\\AbuseFilter": "includes/SpamFilter/AbuseFilter.php",
+ "Flow\\SpamFilter\\ConfirmEdit": "includes/SpamFilter/ConfirmEdit.php",
+ "Flow\\SpamFilter\\ContentLengthFilter": "includes/SpamFilter/ContentLengthFilter.php",
+ "Flow\\SpamFilter\\Controller": "includes/SpamFilter/Controller.php",
+ "Flow\\SpamFilter\\RateLimits": "includes/SpamFilter/RateLimits.php",
+ "Flow\\SpamFilter\\SpamBlacklist": "includes/SpamFilter/SpamBlacklist.php",
+ "Flow\\SpamFilter\\SpamFilter": "includes/SpamFilter/SpamFilter.php",
+ "Flow\\SpamFilter\\SpamRegex": "includes/SpamFilter/SpamRegex.php",
+ "Flow\\Specials\\SpecialEnableStructuredDiscussions": "includes/Specials/SpecialEnableStructuredDiscussions.php",
+ "Flow\\Specials\\SpecialStructuredDiscussions": "includes/Specials/SpecialStructuredDiscussions.php",
+ "Flow\\SubmissionHandler": "includes/SubmissionHandler.php",
+ "Flow\\SummaryEditedPresentationModel": "includes/Notifications/SummaryEditedPresentationModel.php",
+ "Flow\\TalkpageManager": "includes/TalkpageManager.php",
+ "Flow\\TemplateHelper": "includes/TemplateHelper.php",
+ "Flow\\Templating": "includes/Templating.php",
+ "Flow\\Tests\\Api\\ApiFlowEditHeaderTest": "tests/phpunit/api/ApiFlowEditHeaderTest.php",
+ "Flow\\Tests\\Api\\ApiFlowEditPostTest": "tests/phpunit/api/ApiFlowEditPostTest.php",
+ "Flow\\Tests\\Api\\ApiFlowEditTitleTest": "tests/phpunit/api/ApiFlowEditTitleTest.php",
+ "Flow\\Tests\\Api\\ApiFlowEditTopicSummaryTest": "tests/phpunit/api/ApiFlowEditTopicSummaryTest.php",
+ "Flow\\Tests\\Api\\ApiFlowLockTopicTest": "tests/phpunit/api/ApiFlowLockTopicTest.php",
+ "Flow\\Tests\\Api\\ApiFlowModeratePostTest": "tests/phpunit/api/ApiFlowModeratePostTest.php",
+ "Flow\\Tests\\Api\\ApiFlowModerateTopicTest": "tests/phpunit/api/ApiFlowModerateTopicTest.php",
+ "Flow\\Tests\\Api\\ApiFlowReplyTest": "tests/phpunit/api/ApiFlowReplyTest.php",
+ "Flow\\Tests\\Api\\ApiFlowViewHeaderTest": "tests/phpunit/api/ApiFlowViewHeaderTest.php",
+ "Flow\\Tests\\Api\\ApiFlowViewTopicListTest": "tests/phpunit/api/ApiFlowViewTopicListTest.php",
+ "Flow\\Tests\\Api\\ApiTestCase": "tests/phpunit/api/ApiTestCase.php",
+ "Flow\\Tests\\Api\\ApiWatchTopicTest": "tests/phpunit/api/ApiWatchTopicTest.php",
+ "Flow\\Tests\\BlockFactoryTest": "tests/phpunit/BlockFactoryTest.php",
+ "Flow\\Tests\\Block\\TopicListTest": "tests/phpunit/Block/TopicListTest.php",
+ "Flow\\Tests\\Collection\\PostCollectionTest": "tests/phpunit/Collection/PostCollectionTest.php",
+ "Flow\\Tests\\Collection\\RevisionCollectionPermissionsTest": "tests/phpunit/Collection/RevisionCollectionPermissionsTest.php",
+ "Flow\\Tests\\ContainerTest": "tests/phpunit/ContainerTest.php",
+ "Flow\\Tests\\Conversion\\ConversionUtilsTest": "tests/phpunit/Conversion/UtilsTest.php",
+ "Flow\\Tests\\Data\\CachingObjectManagerTest": "tests/phpunit/Data/CachingObjectMapperTest.php",
+ "Flow\\Tests\\Data\\FlowNothingTest": "tests/phpunit/Data/NothingTest.php",
+ "Flow\\Tests\\Data\\IndexTest": "tests/phpunit/Data/IndexTest.php",
+ "Flow\\Tests\\Data\\Listener\\RecentChangesListenerTest": "tests/phpunit/Data/Listener/RecentChangesListenerTest.php",
+ "Flow\\Tests\\Data\\ManagerGroupTest": "tests/phpunit/Data/ManagerGroupTest.php",
+ "Flow\\Tests\\Data\\ObjectLocatorTest": "tests/phpunit/Data/ObjectLocatorTest.php",
+ "Flow\\Tests\\Data\\Pager\\PagerTest": "tests/phpunit/Data/Pager/PagerTest.php",
+ "Flow\\Tests\\Data\\Storage\\RevisionStorageTest": "tests/phpunit/Data/Storage/RevisionStorageTest.php",
+ "Flow\\Tests\\Data\\UserNameBatchTest": "tests/phpunit/Data/UserNameBatchTest.php",
+ "Flow\\Tests\\Data\\UserNameListenerTest": "tests/phpunit/Data/UserNameListenerTest.php",
+ "Flow\\Tests\\FlowActionsTest": "tests/phpunit/FlowActionsTest.php",
+ "Flow\\Tests\\FlowTestCase": "tests/phpunit/FlowTestCase.php",
+ "Flow\\Tests\\Formatter\\FormatterTest": "tests/phpunit/Formatter/FormatterTest.php",
+ "Flow\\Tests\\Formatter\\RevisionFormatterTest": "tests/phpunit/Formatter/RevisionFormatterTest.php",
+ "Flow\\Tests\\Handlebars\\FlowPostMetaActionsTest": "tests/phpunit/Handlebars/FlowPostMetaActionsTest.php",
+ "Flow\\Tests\\HookTest": "tests/phpunit/HookTest.php",
+ "Flow\\Tests\\Import\\ArchiveNameHelperTest": "tests/phpunit/Import/ArchiveNameHelperTest.php",
+ "Flow\\Tests\\Import\\ConverterTest": "tests/phpunit/Import/ConverterTest.php",
+ "Flow\\Tests\\Import\\HistoricalUIDGeneratorTest": "tests/phpunit/Import/HistoricalUIDGeneratorTest.php",
+ "Flow\\Tests\\Import\\LiquidThreadsApi\\ConversionStrategyTest": "tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php",
+ "Flow\\Tests\\Import\\PageImportStateTest": "tests/phpunit/Import/PageImportStateTest.php",
+ "Flow\\Tests\\Import\\TalkpageImportOperationTest": "tests/phpunit/Import/TalkpageImportOperationTest.php",
+ "Flow\\Tests\\Import\\TemplateHelperTest": "tests/phpunit/Import/TemplateHelperTest.php",
+ "Flow\\Tests\\Import\\Wikitext\\ConversionStrategyTest": "tests/phpunit/Import/Wikitext/ConversionStrategyTest.php",
+ "Flow\\Tests\\Import\\Wikitext\\ImportSourceTest": "tests/phpunit/Import/Wikitext/ImportSourceTest.php",
+ "Flow\\Tests\\LinksTableTest": "tests/phpunit/LinksTableTest.php",
+ "Flow\\Tests\\Mock\\MockImportHeader": "tests/phpunit/Mock/MockImportHeader.php",
+ "Flow\\Tests\\Mock\\MockImportPost": "tests/phpunit/Mock/MockImportPost.php",
+ "Flow\\Tests\\Mock\\MockImportRevision": "tests/phpunit/Mock/MockImportRevision.php",
+ "Flow\\Tests\\Mock\\MockImportSource": "tests/phpunit/Mock/MockImportSource.php",
+ "Flow\\Tests\\Mock\\MockImportSummary": "tests/phpunit/Mock/MockImportSummary.php",
+ "Flow\\Tests\\Mock\\MockImportTopic": "tests/phpunit/Mock/MockImportTopic.php",
+ "Flow\\Tests\\Model\\PostRevisionTest": "tests/phpunit/Model/PostRevisionTest.php",
+ "Flow\\Tests\\Model\\UUIDTest": "tests/phpunit/Model/UUIDTest.php",
+ "Flow\\Tests\\Model\\UserTupleTest": "tests/phpunit/Model/UserTupleTest.php",
+ "Flow\\Tests\\NotificationControllerTest": "tests/phpunit/Notifications/NotificationControllerTest.php",
+ "Flow\\Tests\\NotifiedUsersTest": "tests/phpunit/Notifications/NotifiedUsersTest.php",
+ "Flow\\Tests\\Parsoid\\BadImageRemoverTest": "tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php",
+ "Flow\\Tests\\Parsoid\\BaseHrefFixerTest": "tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php",
+ "Flow\\Tests\\Parsoid\\Fixer\\MethodReturnsConstraint": "tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php",
+ "Flow\\Tests\\Parsoid\\Fixer\\WikiLinkFixerTest": "tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php",
+ "Flow\\Tests\\Parsoid\\ReferenceExtractorTestCase": "tests/phpunit/Parsoid/ReferenceExtractorTest.php",
+ "Flow\\Tests\\Parsoid\\ReferenceFactoryTest": "tests/phpunit/Parsoid/ReferenceFactoryTest.php",
+ "Flow\\Tests\\PermissionsTest": "tests/phpunit/PermissionsTest.php",
+ "Flow\\Tests\\PostRevisionTestCase": "tests/phpunit/PostRevisionTestCase.php",
+ "Flow\\Tests\\Repository\\TreeRepositoryTest": "tests/phpunit/Repository/TreeRepositoryTest.php",
+ "Flow\\Tests\\Repository\\TreeRepositorydbTest": "tests/phpunit/Repository/TreeRepositoryDbTest.php",
+ "Flow\\Tests\\SpamFilter\\AbuseFilterTest": "tests/phpunit/SpamFilter/AbuseFilterTest.php",
+ "Flow\\Tests\\SpamFilter\\ConfirmEditTest": "tests/phpunit/SpamFilter/ConfirmEditTest.php",
+ "Flow\\Tests\\SpamFilter\\ContentLengthFilterTest": "tests/phpunit/SpamFilter/ContentLengthFilterTest.php",
+ "Flow\\Tests\\SpamFilter\\SpamBlacklistTest": "tests/phpunit/SpamFilter/SpamBlacklistTest.php",
+ "Flow\\Tests\\SpamFilter\\SpamRegexTest": "tests/phpunit/SpamFilter/SpamRegexTest.php",
+ "Flow\\Tests\\TalkpageManagerTest": "tests/phpunit/TalkpageManagerTest.php",
+ "Flow\\Tests\\TemplateHelperTest": "tests/phpunit/TemplateHelperTest.php",
+ "Flow\\Tests\\TemplatingTest": "tests/phpunit/TemplatingTest.php",
+ "Flow\\Tests\\UrlGeneratorTest": "tests/phpunit/UrlGeneratorTest.php",
+ "Flow\\Tests\\WatchedTopicItemTest": "tests/phpunit/WatchedTopicItemsTest.php",
+ "Flow\\TopicRenamedPresentationModel": "includes/Notifications/TopicRenamedPresentationModel.php",
+ "Flow\\TopicResolvedPresentationModel": "includes/Notifications/TopicResolvedPresentationModel.php",
+ "Flow\\UrlGenerator": "includes/UrlGenerator.php",
+ "Flow\\Utils\\NamespaceIterator": "includes/Utils/NamespaceIterator.php",
+ "Flow\\Utils\\PagesWithPropertyIterator": "includes/Utils/PagesWithPropertyIterator.php",
+ "Flow\\View": "includes/View.php",
+ "Flow\\WatchedTopicItems": "includes/WatchedTopicItems.php",
+ "Flow\\WorkflowLoader": "includes/WorkflowLoader.php",
+ "Flow\\WorkflowLoaderFactory": "includes/WorkflowLoaderFactory.php",
+ "MaintenanceDebugLogger": "maintenance/MaintenanceDebugLogger.php"
+ }
+}
diff --git a/Flow/flow.sql b/Flow/flow.sql
index cb480503..9f82fe70 100644
--- a/Flow/flow.sql
+++ b/Flow/flow.sql
@@ -7,9 +7,9 @@ CREATE TABLE /*_*/flow_workflow (
workflow_namespace int not null,
workflow_page_id int unsigned not null,
workflow_title_text varchar(255) binary not null,
- workflow_name varchar(255) binary not null,
+ workflow_name varchar(255) binary not null,
workflow_last_update_timestamp binary(14) not null,
- -- TODO: is this usefull as a bitfield? may be premature optimization, a string
+ -- TODO: is this useful as a bitfield? may be premature optimization, a string
-- or list of strings may be simpler and use only a little more space.
workflow_lock_state int unsigned not null,
workflow_type varbinary(16) not null,
@@ -19,24 +19,13 @@ CREATE TABLE /*_*/flow_workflow (
CREATE INDEX /*i*/flow_workflow_lookup ON /*_*/flow_workflow (workflow_wiki, workflow_namespace, workflow_title_text);
CREATE INDEX /*i*/flow_workflow_update_timestamp ON /*_*/flow_workflow (workflow_last_update_timestamp);
-CREATE TABLE /*_*/flow_subscription (
- subscription_workflow_id int unsigned not null,
- subscription_user_id bigint unsigned not null,
- subscription_user_wiki varchar(64) binary not null,
- subscription_create_timestamp varchar(14) binary not null,
- subscription_last_updated varchar(14) binary not null
-) /*$wgDBTableOptions*/;
-
-CREATE UNIQUE INDEX /*i*/flow_subscription_unique_user_workflow ON /*_*/flow_subscription (subscription_workflow_id, subscription_user_id, subscription_user_wiki );
-CREATE INDEX /*i*/flow_subscription_lookup ON /*_*/flow_subscription (subscription_user_id, subscription_user_wiki, subscription_last_updated, subscription_workflow_id);
-
-- TopicList Tables
CREATE TABLE /*_*/flow_topic_list (
topic_list_id binary(11) not null,
- topic_id binary(11)
+ topic_id binary(11),
+ PRIMARY KEY (topic_list_id, topic_id)
) /*$wgDBTableOptions*/;
-CREATE UNIQUE INDEX /*i*/flow_topic_list_pk ON /*_*/flow_topic_list( topic_list_id, topic_id);
CREATE INDEX /*i*/flow_topic_list_topic_id ON /*_*/flow_topic_list (topic_id);
-- Post Content Revisions. Connects 1 Post to Many revisions.
@@ -53,11 +42,10 @@ CREATE TABLE /*_*/flow_tree_revision (
-- denormalize post parent as well? Prevents an extra query when building
-- tree from closure table. unnecessary?
tree_parent_id binary(11),
- PRIMARY KEY( tree_rev_id )
+ PRIMARY KEY(tree_rev_id)
) /*$wgDBTableOptions*/;
-CREATE INDEX /*i*/flow_tree_descendant_rev_id
- ON /*_*/flow_tree_revision ( tree_rev_descendant_id, tree_rev_id );
+CREATE INDEX /*i*/flow_tree_descendant_rev_id ON /*_*/flow_tree_revision (tree_rev_descendant_id, tree_rev_id);
-- Content
-- This is completely unoptimized right now, just a quick get-it-done for
@@ -132,13 +120,14 @@ CREATE INDEX /*i*/flow_revision_user ON
CREATE TABLE /*_*/flow_tree_node (
tree_ancestor_id binary(11) not null,
tree_descendant_id binary(11) not null,
- tree_depth smallint not null
+ tree_depth smallint not null,
+ PRIMARY KEY (tree_ancestor_id, tree_descendant_id)
) /*$wgDBTableOptions*/;
-CREATE UNIQUE INDEX /*i*/flow_tree_node_pk ON /*_*/flow_tree_node (tree_ancestor_id, tree_descendant_id);
CREATE UNIQUE INDEX /*i*/flow_tree_constraint ON /*_*/flow_tree_node (tree_descendant_id, tree_depth);
CREATE TABLE /*_*/flow_wiki_ref (
+ ref_id binary(11) not null,
ref_src_wiki varchar(16) binary not null,
ref_src_object_id binary(11) not null,
ref_src_object_type varbinary(32) not null,
@@ -147,7 +136,9 @@ CREATE TABLE /*_*/flow_wiki_ref (
ref_src_title varbinary(255) not null,
ref_target_namespace int not null,
ref_target_title varbinary(255) not null,
- ref_type varbinary(16) not null
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/flow_wiki_ref_idx_v2 ON /*_*/flow_wiki_ref
@@ -157,6 +148,7 @@ CREATE INDEX /*i*/flow_wiki_ref_revision_v2 ON /*_*/flow_wiki_ref
(ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type, ref_src_object_id, ref_type, ref_target_namespace, ref_target_title);
CREATE TABLE /*_*/flow_ext_ref (
+ ref_id binary(11) not null,
ref_src_wiki varchar(16) binary not null,
ref_src_object_id binary(11) not null,
ref_src_object_type varbinary(32) not null,
@@ -164,10 +156,12 @@ CREATE TABLE /*_*/flow_ext_ref (
ref_src_namespace int not null,
ref_src_title varbinary(255) not null,
ref_target blob not null,
- ref_type varbinary(16) not null
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
) /*$wgDBTableOptions*/;
-CREATE INDEX /*i*/flow_ext_ref_idx_v2 ON /*_*/flow_ext_ref
+CREATE INDEX /*i*/flow_ext_ref_idx_v3 ON /*_*/flow_ext_ref
(ref_src_wiki, ref_src_namespace, ref_src_title, ref_type, ref_target(255), ref_src_object_type, ref_src_object_id);
CREATE INDEX /*i*/flow_ext_ref_revision_v2 ON /*_*/flow_ext_ref
diff --git a/Flow/gitinfo.json b/Flow/gitinfo.json
new file mode 100644
index 00000000..3ef1dea2
--- /dev/null
+++ b/Flow/gitinfo.json
@@ -0,0 +1 @@
+{"headSHA1": "f75fa788a2cd7fe670f0cc108881ffddbda36864\n", "head": "f75fa788a2cd7fe670f0cc108881ffddbda36864\n", "remoteURL": "https://gerrit.wikimedia.org/r/mediawiki/extensions/Flow", "branch": "f75fa788a2cd7fe670f0cc108881ffddbda36864\n", "headCommitDate": "1540078664"} \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_board-history.handlebars.php b/Flow/handlebars/compiled/flow_block_board-history.handlebars.php
index 8e2feb03..da21c044 100644
--- a/Flow/handlebars/compiled/flow_block_board-history.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_board-history.handlebars.php
@@ -28,88 +28,53 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
diff --git a/Flow/handlebars/compiled/flow_block_header.handlebars.php b/Flow/handlebars/compiled/flow_block_header.handlebars.php
index 7995af22..6887a395 100644
--- a/Flow/handlebars/compiled/flow_block_header.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_header.handlebars.php
@@ -13,7 +13,6 @@
'constants' => array(),
'helpers' => array( 'l10n' => 'Flow\TemplateHelper::l10n',
'html' => 'Flow\TemplateHelper::htmlHelper',
- 'escapeContent' => 'Flow\TemplateHelper::escapeContent',
'oouify' => 'Flow\TemplateHelper::oouify',
),
'blockhelpers' => array(),
@@ -22,38 +21,19 @@
'.$sp.' <span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-speechBubbles"></span>
'.$sp.' '.LCRun3::ch($cx, 'l10n', array(array('flow-board-header'),array()), 'encq').'
'.$sp.'</h2>
-';},'flow_errors' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-error-container">
+';},'flow_header_edit_restrictions' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['revision']['actions']['edit']) && is_array($in['revision']['actions'])) ? $in['revision']['actions']['edit'] : null))) ? ' <p class="flow-board-header-restricted">
+'.$sp.' '.LCRun3::ch($cx, 'oouify', array(array('lock'),array('type'=>'IconWidget','classes'=>'flow-board-header-restricted-icon')), 'raw').'
+'.$sp.'
+'.$sp.' <span class="flow-board-header-restricted-label">'.LCRun3::ch($cx, 'l10n', array(array('flow-board-description-can-not-edit'),array()), 'encq').'</span>
+'.$sp.' </p>
+'.$sp.'' : '').'';},'flow_errors' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-error-container">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['errors']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null))) ? ' <div class="flow-errors errorbox">
'.$sp.' <ul>
'.$sp.''.LCRun3::sec($cx, ((isset($cx['sp_vars']['root']['errors']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null), $in, true, function($cx, $in)use($sp){return ' <li>'.LCRun3::ch($cx, 'html', array(array(((isset($in['message']) && is_array($in)) ? $in['message'] : null)),array()), 'encq').'</li>
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_header_detail_oldsystem' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-board-header-detail-view">
-'.$sp.' <div class="flow-board-header-nav">
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['actions']['edit']) && is_array($in['revision']['actions'])) ? $in['revision']['actions']['edit'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['revision']['actions']['edit']['url']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-handler="activateEditHeader"
-'.$sp.' data-flow-api-target="< .flow-board-header"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' class="mw-ui-button mw-ui-progressive mw-ui-quiet flow-ui-tooltip-target"
-'.$sp.' title="'.htmlentities((string)((isset($in['revision']['actions']['edit']['title']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'">
-'.$sp.' <span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit flow-board-header-icon"></span>'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-header-link'),array()), 'encq').'
-'.$sp.' </a>
-'.$sp.'' : '').' </div>
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['content']) && is_array($in['revision'])) ? $in['revision']['content'] : null))) ? ' <div class="flow-board-header-content">
-'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['revision']['content']['format']) && is_array($in['revision']['content'])) ? $in['revision']['content']['format'] : null),((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null)),array()), 'encq').'
-'.$sp.' </div>
-'.$sp.'' : '').'
-'.$sp.'</div>
-'.$sp.'<a href="javascript:void(0);"
-'.$sp.' class="mw-ui-button mw-ui-quiet side-rail-toggle-button"
-'.$sp.' data-flow-interactive-handler="toggleSideRail">
-'.$sp.' <span class="wikiglyph wikiglyph-x pull-right collapse-button"
-'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-board-collapse-description'),array()), 'encq').'"></span>
-'.$sp.' <span class="wikiglyph wikiglyph-speech-bubbles pull-right expand-button"
-'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-board-expand-description'),array()), 'encq').'"></span>
-'.$sp.'</a>
-';},'flow_header_detail' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::ch($cx, 'oouify', array(array(((isset($in['revision']['content']['format']) && is_array($in['revision']['content'])) ? $in['revision']['content']['format'] : null),((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null),((isset($in['revision']['actions']['edit']['url']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['url'] : null),((isset($in['revision']['actions']['edit']['title']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['title'] : null)),array('label'=>((isset($in['flow-edit-header-link']) && is_array($in)) ? $in['flow-edit-header-link'] : null),'type'=>'BoardDescriptionWidget','name'=>'flow-board-description')), 'raw').'
+';},'flow_header_detail' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::ch($cx, 'oouify', array(array(((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null),((isset($in['revision']['actions']['edit']['url']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['url'] : null),((isset($in['revision']['actions']['edit']['title']) && is_array($in['revision']['actions']['edit'])) ? $in['revision']['actions']['edit']['title'] : null)),array('type'=>'BoardDescriptionWidget','name'=>'flow-board-description')), 'raw').'
'.$sp.'<a href="javascript:void(0);"
'.$sp.' class="mw-ui-button mw-ui-quiet side-rail-toggle-button"
'.$sp.' data-flow-interactive-handler="toggleSideRail">
@@ -62,7 +42,11 @@
'.$sp.' <span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-speechBubbles pull-right expand-button"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-board-expand-description'),array()), 'encq').'"></span>
'.$sp.'</a>
-';},'flow_header_footer' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-board-header-footer">
+';},'flow_header_categories' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['categories']['items']) && is_array($cx['sp_vars']['root']['categories'])) ? $cx['sp_vars']['root']['categories']['items'] : null))) ? '<div id="catlinks" class="catlinks flow-board-header-category-view-nojs">
+'.$sp.' <div id="mw-normal-catlinks" class="mw-normal-catlinks">'.LCRun3::ch($cx, 'html', array(array(((isset($cx['sp_vars']['root']['categories']['link']) && is_array($cx['sp_vars']['root']['categories'])) ? $cx['sp_vars']['root']['categories']['link'] : null)),array()), 'encq').'<ul class="flow-board-header-category-list">'.LCRun3::sec($cx, ((isset($cx['sp_vars']['root']['categories']['items']) && is_array($cx['sp_vars']['root']['categories'])) ? $cx['sp_vars']['root']['categories']['items'] : null), $in, true, function($cx, $in)use($sp){return '<li class="flow-board-header-category-item">'.LCRun3::ch($cx, 'html', array(array($in),array()), 'encq').'</li>';}).'</ul>
+'.$sp.' </div>
+'.$sp.'</div>
+'.$sp.'' : '').'';},'flow_header_footer' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-board-header-footer">
'.$sp.' <hr />
'.$sp.' <p>
'.$sp.' '.LCRun3::ch($cx, 'html', array(array(((isset($in['copyrightMessage']) && is_array($in)) ? $in['copyrightMessage'] : null)),array()), 'encq').'
@@ -76,7 +60,7 @@
);
return '<div class="flow-board-header flow-load-interactive" data-flow-load-handler="loadSideRail">
-'.LCRun3::p($cx, 'flow_header_title', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').''.((LCRun3::ifvar($cx, ((isset($in['oldSystem']) && is_array($in)) ? $in['oldSystem'] : null))) ? ''.LCRun3::p($cx, 'flow_header_detail_oldsystem', array(array($in),array()), ' ').'' : ''.LCRun3::p($cx, 'flow_header_detail', array(array($in),array()), ' ').'').''.LCRun3::p($cx, 'flow_header_footer', array(array($in),array()), ' ').'</div>
+'.LCRun3::p($cx, 'flow_header_title', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_header_edit_restrictions', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_header_detail', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_header_categories', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_header_footer', array(array($in),array()), ' ').'</div>
';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_header_edit.handlebars.php b/Flow/handlebars/compiled/flow_block_header_edit.handlebars.php
index a7318c23..0d4823a7 100644
--- a/Flow/handlebars/compiled/flow_block_header_edit.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_header_edit.handlebars.php
@@ -58,13 +58,12 @@
<div class="flow-form-actions flow-form-collapsible">
<button data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="submitHeader">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-header-submit'),array()), 'encq').'</button>
+ class="mw-ui-button mw-ui-progressive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-header-submit'),array()), 'encq').'</button>
'.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
</div>
</form>
</div>
-</div>';
+</div>
+';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_header_single_view.handlebars.php b/Flow/handlebars/compiled/flow_block_header_single_view.handlebars.php
index 25017195..d2bd39a5 100644
--- a/Flow/handlebars/compiled/flow_block_header_single_view.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_header_single_view.handlebars.php
@@ -26,7 +26,7 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_patrol_action' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div class="patrollink">
+';},'flow_patrol_action' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div class="patrollink" data-mw="interface">
'.$sp.' [<a class="mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['revision']['rev_view_links']['markPatrolled']['url']) && is_array($in['revision']['rev_view_links']['markPatrolled'])) ? $in['revision']['rev_view_links']['markPatrolled']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-mark-revision-patrolled-link-title'),array()), 'encq').'"
diff --git a/Flow/handlebars/compiled/flow_block_header_undo_edit.handlebars.php b/Flow/handlebars/compiled/flow_block_header_undo_edit.handlebars.php
index 284e010a..256f1222 100644
--- a/Flow/handlebars/compiled/flow_block_header_undo_edit.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_header_undo_edit.handlebars.php
@@ -48,7 +48,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-header-submit'),array()), 'encq').'</button>
+ <button class="mw-ui-button mw-ui-progressive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-header-submit'),array()), 'encq').'</button>
<small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'
</small>
</div>
diff --git a/Flow/handlebars/compiled/flow_block_topic.handlebars.php b/Flow/handlebars/compiled/flow_block_topic.handlebars.php
index b332d5be..006d35ff 100644
--- a/Flow/handlebars/compiled/flow_block_topic.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic.handlebars.php
@@ -35,17 +35,17 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_topic_moderation_flag' => function ($cx, $in, $sp) {return ''.$sp.'<span class="mw-ui-icon mw-ui-icon-before'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','lock'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-check';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','hide'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-flag';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','delete'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-remove';}).'"></span>
+';},'flow_topic_moderation_flag' => function ($cx, $in, $sp) {return ''.$sp.'<span class="mw-ui-icon mw-ui-icon-before'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','lock'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-check';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','hide'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-flag';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','delete'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-trash';}).'"></span>
';},'flow_post_moderation_state' => function ($cx, $in, $sp) {return ''.$sp.'<span class="plainlinks">'.((LCRun3::ifvar($cx, ((isset($in['replyToId']) && is_array($in)) ? $in['replyToId'] : null))) ? ''.LCRun3::ch($cx, 'l10nParse', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'-post-content'),array()), 'raw'),((isset($in['moderator']['name']) && is_array($in['moderator'])) ? $in['moderator']['name'] : null),((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null)),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10nParse', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'-title-content'),array()), 'raw'),((isset($in['moderator']['name']) && is_array($in['moderator'])) ? $in['moderator']['name'] : null),((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null)),array()), 'encq').'').'</span>
';},'flow_topic_titlebar_content' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-titlebar-container">
-'.$sp.' <h2 class="flow-topic-title flow-load-interactive '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-click-interactive' : '').'"
+'.$sp.' <h2 class="flow-topic-title flow-load-interactive '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-collapse-toggle flow-click-interactive' : '').'"
'.$sp.' data-flow-topic-title="'.htmlentities((string)((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-load-handler="topicTitle"
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' data-flow-interactive-handler="collapserCollapsibleToggle"
'.$sp.'' : '').' >
'.$sp.' '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check"></span> ' : '').''.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['content']['format']) && is_array($in['content'])) ? $in['content']['format'] : null),((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null)),array()), 'encq').'</h2>
'.$sp.' <div class="flow-topic-meta">
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<a class="expand-collapse-posts-link flow-click-interactive"
+'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<a class="expand-collapse-posts-link flow-collapse-toggle flow-click-interactive"
'.$sp.' href="javascript:void(0);"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-show-comments-title',((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null)),array()), 'encq').'"
'.$sp.' data-collapsed-title="'.LCRun3::ch($cx, 'l10n', array(array('flow-show-comments-title',((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null)),array()), 'encq').'"
@@ -65,7 +65,7 @@
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['moderateReason']['format']) && is_array($in['moderateReason'])) ? $in['moderateReason']['format'] : null),((isset($in['moderateReason']['content']) && is_array($in['moderateReason'])) ? $in['moderateReason']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
'.$sp.'' : '').' <span class="flow-reply-count"><span class="flow-reply-count-number">'.htmlentities((string)((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null), ENT_QUOTES, 'UTF-8').'</span></span>
-'.$sp.'</div>';},'flow_topic_titlebar_summary' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-summary-container '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-click-interactive' : '').'"
+'.$sp.'</div>';},'flow_topic_titlebar_summary' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-summary-container '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-collapse-toggle flow-click-interactive' : '').'"
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' data-flow-interactive-handler="collapserCollapsibleToggle"
'.$sp.'' : '').' >
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').''.((LCRun3::ifvar($cx, ((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null))) ? ' <div class="flow-topic-summary">
@@ -74,102 +74,68 @@
'.$sp.'';}, function($cx, $in)use($sp){return ' '.LCRun3::ch($cx, 'l10n', array(array('flow-summary-edited',((isset($in['revision']['author']['name']) && is_array($in['revision']['author'])) ? $in['revision']['author']['name'] : null)),array()), 'encq').'
'.$sp.' <a href="'.htmlentities((string)((isset($in['revision']['links']['diff-prev']['url']) && is_array($in['revision']['links']['diff-prev'])) ? $in['revision']['links']['diff-prev']['url'] : null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 'uuidTimestamp', array(array(((isset($in['revision']['lastEditId']) && is_array($in['revision'])) ? $in['revision']['lastEditId'] : null)),array()), 'encq').'</a>
'.$sp.'';}).' </div>
-'.$sp.' <div class="flow-topic-summary-content">
+'.$sp.' <div class="flow-topic-summary-content mw-parser-output">
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['revision']['content']['format']) && is_array($in['revision']['content'])) ? $in['revision']['content']['format'] : null),((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
+'.$sp.' <div style="clear: both;"></div>
'.$sp.' </div>
'.$sp.'' : '').'</div>
';},'flow_topic_titlebar_watch' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-watchlist flow-watch-link">
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
'.$sp.' <a href="'.((LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? ''.htmlentities((string)((isset($in['links']['unwatch-topic']['url']) && is_array($in['links']['unwatch-topic'])) ? $in['links']['unwatch-topic']['url'] : null), ENT_QUOTES, 'UTF-8').'' : ''.htmlentities((string)((isset($in['links']['watch-topic']['url']) && is_array($in['links']['watch-topic'])) ? $in['links']['watch-topic']['url'] : null), ENT_QUOTES, 'UTF-8').'').'"
-'.$sp.' class="mw-ui-anchor mw-ui-hovericon mw-ui-constructive '.((!LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'mw-ui-quiet' : '').'
+'.$sp.' class="mw-ui-anchor mw-ui-hovericon '.((!LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'mw-ui-quiet' : '').'
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'flow-watch-link-unwatch' : 'flow-watch-link-watch').'"
'.$sp.' data-flow-api-handler="watchItem"
'.$sp.' data-flow-api-target="< .flow-topic-watchlist"
-'.$sp.' data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar-constructive" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-remove'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-constructive-hover" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-add'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
+'.$sp.' data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar mw-ui-icon-unStar-progressive" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-remove'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-progressive-hover" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-add'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
'.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
@@ -194,41 +160,37 @@
'.$sp.'
'.$sp.'>
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['msg']) && is_array($in)) ? $in['msg'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(((isset($in['msg']) && is_array($in)) ? $in['msg'] : null)),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-cancel'),array()), 'encq').'').'</button>
-';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <form class="flow-post flow-reply-form"
-'.$sp.' method="POST"
-'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-initial-state="collapsed"
-'.$sp.' >
-'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
-'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
-'.$sp.' <div class="flow-editor">
-'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
-'.$sp.' name="topic_content"
-'.$sp.' required
-'.$sp.' data-flow-expandable="true"
-'.$sp.' class="mw-ui-input flow-click-interactive"
-'.$sp.' type="text"
-'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'"
-'.$sp.' data-role="content"
+';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '
+'.$sp.'<form class="flow-post flow-reply-form"
+'.$sp.' method="POST"
+'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' data-flow-initial-state="collapsed"
+'.$sp.'>
+'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
+'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
+'.$sp.' <div class="flow-editor">
+'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
+'.$sp.' name="topic_content"
+'.$sp.' required
+'.$sp.' data-flow-expandable="true"
+'.$sp.' class="mw-ui-input flow-click-interactive"
+'.$sp.' type="text"
+'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'"
+'.$sp.' data-role="content"
'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateReplyTopic"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
-'.$sp.' </div>
+'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
+'.$sp.' </div>
'.$sp.'
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="submitReply"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
-'.$sp.' </div>
-'.$sp.' </form>
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-link'),array()), 'encq').'</button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
+'.$sp.' </div>
+'.$sp.'</form>
'.$sp.'' : '').'';},'flow_topic' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic flow-load-interactive'.((LCRun3::ifvar($cx, ((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null))) ? ' flow-topic-moderatestate-'.htmlentities((string)((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null), ENT_QUOTES, 'UTF-8').' ' : '').''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ' flow-topic-moderated ' : '').''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-element-collapsible flow-element-collapsed' : '').'"
'.$sp.' id="flow-topic-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
@@ -243,8 +205,8 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array('type'=>'replace','target'=>'~ a')), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).' <a href="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['reply']['title']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="flow-ui-input-replacement-anchor mw-ui-input"
-'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'</a>
-'.$sp.'';}).'' : '').'</div>
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'</a>
+'.$sp.'';}).'' : ''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array('type'=>'insert')), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).'').'</div>
';},'flow_topiclist_loop' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::sec($cx, ((isset($in['roots']) && is_array($in)) ? $in['roots'] : null), $in, true, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),$in),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_topic', array(array($in),array()), ' ').'';}).'';}).'';},),
'scopes' => array(),
'sp_vars' => array('root' => $in),
diff --git a/Flow/handlebars/compiled/flow_block_topic_diff_view.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_diff_view.handlebars.php
index 83264603..85727bce 100644
--- a/Flow/handlebars/compiled/flow_block_topic_diff_view.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_diff_view.handlebars.php
@@ -25,7 +25,7 @@
return '<div class="flow-board">
<div class="flow-compare-revisions-header plainlinks">
- '.LCRun3::ch($cx, 'l10nParse', array(array('flow-compare-revisions-header-post',((isset($in['revision']['new']['rev_view_links']['board']['title']) && is_array($in['revision']['new']['rev_view_links']['board'])) ? $in['revision']['new']['rev_view_links']['board']['title'] : null),((isset($in['revision']['new']['properties']['topic-of-post']) && is_array($in['revision']['new']['properties'])) ? $in['revision']['new']['properties']['topic-of-post'] : null),((isset($in['revision']['new']['author']['name']) && is_array($in['revision']['new']['author'])) ? $in['revision']['new']['author']['name'] : null),((isset($in['revision']['new']['rev_view_links']['board']['url']) && is_array($in['revision']['new']['rev_view_links']['board'])) ? $in['revision']['new']['rev_view_links']['board']['url'] : null),((isset($in['revision']['new']['rev_view_links']['root']['url']) && is_array($in['revision']['new']['rev_view_links']['root'])) ? $in['revision']['new']['rev_view_links']['root']['url'] : null),((isset($in['revision']['new']['rev_view_links']['hist']['url']) && is_array($in['revision']['new']['rev_view_links']['hist'])) ? $in['revision']['new']['rev_view_links']['hist']['url'] : null)),array()), 'encq').'
+ '.LCRun3::ch($cx, 'l10nParse', array(array('flow-compare-revisions-header-post',((isset($in['revision']['new']['rev_view_links']['board']['title']) && is_array($in['revision']['new']['rev_view_links']['board'])) ? $in['revision']['new']['rev_view_links']['board']['title'] : null),((isset($in['revision']['new']['properties']['topic-of-post-text-from-html']) && is_array($in['revision']['new']['properties'])) ? $in['revision']['new']['properties']['topic-of-post-text-from-html'] : null),((isset($in['revision']['new']['author']['name']) && is_array($in['revision']['new']['author'])) ? $in['revision']['new']['author']['name'] : null),((isset($in['revision']['new']['rev_view_links']['board']['url']) && is_array($in['revision']['new']['rev_view_links']['board'])) ? $in['revision']['new']['rev_view_links']['board']['url'] : null),((isset($in['revision']['new']['rev_view_links']['root']['url']) && is_array($in['revision']['new']['rev_view_links']['root'])) ? $in['revision']['new']['rev_view_links']['root']['url'] : null),((isset($in['revision']['new']['rev_view_links']['hist']['url']) && is_array($in['revision']['new']['rev_view_links']['hist'])) ? $in['revision']['new']['rev_view_links']['hist']['url'] : null)),array()), 'encq').'
</div>
<div class="flow-compare-revisions">
'.LCRun3::ch($cx, 'diffRevision', array(array(((isset($in['revision']) && is_array($in)) ? $in['revision'] : null)),array()), 'encq').'
diff --git a/Flow/handlebars/compiled/flow_block_topic_edit_title.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
index f2ca4aa1..d7f3108c 100644
--- a/Flow/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_edit_title.handlebars.php
@@ -13,11 +13,9 @@
'constants' => array(),
'helpers' => array( 'l10n' => 'Flow\TemplateHelper::l10n',
'html' => 'Flow\TemplateHelper::htmlHelper',
- 'l10nParse' => 'Flow\TemplateHelper::l10nParse',
),
'blockhelpers' => array(),
'hbhelpers' => array( 'eachPost' => 'Flow\TemplateHelper::eachPost',
- 'progressiveEnhancement' => 'Flow\TemplateHelper::progressiveEnhancement',
),
'partials' => array('flow_errors' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-error-container">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['errors']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null))) ? ' <div class="flow-errors errorbox">
@@ -32,16 +30,8 @@
'.$sp.' <input name="topic_content" class="mw-ui-input" value="'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null))) ? ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'' : ''.htmlentities((string)((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null), ENT_QUOTES, 'UTF-8').'').'" />
'.$sp.' <div class="flow-form-actions">
'.$sp.' <button data-role="submit"
-'.$sp.' data-flow-api-handler="submitTopicTitle"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' class="mw-ui-button mw-ui-constructive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-title-submit'),array()), 'encq').'</button>
-'.$sp.'
-'.$sp.''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array()), $in, false, function($cx, $in)use($sp){return ' <button data-role="cancel"
-'.$sp.' type="reset"
-'.$sp.' data-flow-interactive-handler="cancelForm"
-'.$sp.' class="mw-ui-button mw-ui-destructive mw-ui-quiet">'.LCRun3::ch($cx, 'l10n', array(array('flow-cancel'),array()), 'encq').'</button>
-'.$sp.' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
-'.$sp.'';}).' </div>
+'.$sp.' class="mw-ui-button mw-ui-progressive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-title-submit'),array()), 'encq').'</button>
+'.$sp.' </div>
'.$sp.'</form>
';},),
'scopes' => array(),
diff --git a/Flow/handlebars/compiled/flow_block_topic_history.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_history.handlebars.php
index d07333c2..5442600a 100644
--- a/Flow/handlebars/compiled/flow_block_topic_history.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_history.handlebars.php
@@ -28,88 +28,53 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
diff --git a/Flow/handlebars/compiled/flow_block_topic_lock.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_lock.handlebars.php
index 9aa33b53..8eba7a90 100644
--- a/Flow/handlebars/compiled/flow_block_topic_lock.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_lock.handlebars.php
@@ -31,28 +31,27 @@
'.$sp.'
'.$sp.'>
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['msg']) && is_array($in)) ? $in['msg'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(((isset($in['msg']) && is_array($in)) ? $in['msg'] : null)),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-cancel'),array()), 'encq').'').'</button>
-';},'flow_topic_titlebar_lock' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-summary-container">
-'.$sp.' <div class="flow-topic-summary">
-'.$sp.' <form class="flow-edit-form" data-flow-initial-state="collapsed" method="POST"
-'.$sp.' action="'.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ''.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'' : ''.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'').'">
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['editToken']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="flow_reason" value="'.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array('flow-rev-message-restore-topic-reason'),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-rev-message-lock-topic-reason'),array()), 'encq').'').'" />
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' >
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' '.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-unlock-topic'),array()), 'encq').'
-'.$sp.'' : ' '.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-lock-topic'),array()), 'encq').'
-'.$sp.'').' </button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' '.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-unlock-topic'),array()), 'encq').'
-'.$sp.'' : ' '.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-lock-topic'),array()), 'encq').'
-'.$sp.'').' </small>
-'.$sp.' </div>
-'.$sp.' </form>
+';},'flow_topic_titlebar_lock' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-board">
+'.$sp.' <div class="flow-topic-summary-container">
+'.$sp.' <div class="flow-topic-summary">
+'.$sp.' <form class="flow-edit-form" data-flow-initial-state="expanded" method="POST"
+'.$sp.' action="'.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ''.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'' : ''.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'').'">
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['editToken']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="flow_reason" value="'.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array('flow-rev-message-restore-topic-reason'),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-rev-message-lock-topic-reason'),array()), 'encq').'').'" />
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >
+'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' '.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-unlock-topic'),array()), 'encq').'
+'.$sp.'' : ' '.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-lock-topic'),array()), 'encq').'
+'.$sp.'').' </button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">
+'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' '.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-unlock-topic'),array()), 'encq').'
+'.$sp.'' : ' '.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-lock-topic'),array()), 'encq').'
+'.$sp.'').' </small>
+'.$sp.' </div>
+'.$sp.' </form>
+'.$sp.' </div>
'.$sp.' </div>
'.$sp.'</div>
';},),
diff --git a/Flow/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
index 71dd19bd..e11d472a 100644
--- a/Flow/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_moderate_post.handlebars.php
@@ -37,18 +37,19 @@
'.$sp.'' : '').'</div>
';},'flow_moderate_post' => function ($cx, $in, $sp) {return ''.$sp.'<form method="POST" action="'.LCRun3::ch($cx, 'moderationAction', array(array(((isset($in['actions']) && is_array($in)) ? $in['actions'] : null),((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null)),array()), 'encq').'">
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['editToken']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <textarea name="topic_reason"
+'.$sp.' <input name="topic_reason"
+'.$sp.' type="text"
+'.$sp.' size="45"
'.$sp.' required
'.$sp.' data-flow-expandable="true"
'.$sp.' class="mw-ui-input"
'.$sp.' data-role="content"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-moderation-placeholder-',((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null),'-post'),array()), 'raw')),array()), 'encq').'"
-'.$sp.' autofocus
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null))) ? ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null), ENT_QUOTES, 'UTF-8').'' : '').'</textarea>
+'.$sp.' autofocus'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null))) ? 'value="'.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null), ENT_QUOTES, 'UTF-8').'"' : '').'>
'.$sp.' <div class="flow-form-actions flow-form-collapsible">
'.$sp.' <button data-flow-interactive-handler="apiRequest"
'.$sp.' data-flow-api-handler="moderatePost"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
'.$sp.' data-role="submit">'.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-moderation-confirm-',((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null),'-post'),array()), 'raw')),array()), 'encq').'</button>
'.$sp.' <a data-flow-interactive-handler="cancelForm"
'.$sp.' class="mw-ui-button mw-ui-destructive mw-ui-quiet"
@@ -60,7 +61,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['links']) && is_array($in)) ? $in['links'] : null))) ? ''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['links']['userpage']['url']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' '.((!LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? 'title="'.htmlentities((string)((isset($in['links']['userpage']['title']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['title'] : null), ENT_QUOTES, 'UTF-8').'"' : '').'
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['userpage']['exists']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['exists'] : null))) ? 'new ' : '').'mw-userlink">
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? ''.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? '<bdi>'.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'</bdi>' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
'.$sp.' ('.((LCRun3::ifvar($cx, ((isset($in['links']['talk']) && is_array($in['links'])) ? $in['links']['talk'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['talk']['url']) && is_array($in['links']['talk'])) ? $in['links']['talk']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['talk']['exists']) && is_array($in['links']['talk'])) ? $in['links']['talk']['exists'] : null))) ? 'new ' : '').'"
'.$sp.' title="'.htmlentities((string)((isset($in['links']['talk']['title']) && is_array($in['links']['talk'])) ? $in['links']['talk']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('talkpagelinktext'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['contribs']) && is_array($in['links'])) ? $in['links']['contribs'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['contribs']['url']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['url'] : null), ENT_QUOTES, 'UTF-8').'" title="'.htmlentities((string)((isset($in['links']['contribs']['title']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('contribslink'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['block']) && is_array($in['links'])) ? $in['links']['block'] : null))) ? '<span><a class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['block']['exists']) && is_array($in['links']['block'])) ? $in['links']['block']['exists'] : null))) ? 'new ' : '').'"
@@ -73,9 +74,7 @@
'.$sp.' <span class="flow-post-meta-actions">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['reply']['title']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet"
-'.$sp.' data-flow-interactive-handler="activateReplyPost"
-'.$sp.'
+'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet flow-reply-link"
'.$sp.' data-flow-eventlog-schema="FlowReplies"
'.$sp.' data-flow-eventlog-action="initiate"
'.$sp.' data-flow-eventlog-entrypoint="reply-post"
@@ -84,7 +83,7 @@
'.$sp.' < .flow-post:not([data-flow-post-max-depth=\'1\']) .flow-reply-form [data-role=\'submit\']
'.$sp.' "
'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-constructive mw-ui-quiet mw-thanks-flow-thank-link"
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-progressive mw-ui-quiet mw-thanks-flow-thank-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['thank']['url']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['thank']['title']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.htmlentities((string)((isset($in['actions']['thank']['text']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
'.$sp.'' : '').' </span>
@@ -100,88 +99,53 @@
'.$sp.' <a href="'.htmlentities((string)((isset($in['links']['diff-prev']['url']) && is_array($in['links']['diff-prev'])) ? $in['links']['diff-prev']['url'] : null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 'uuidTimestamp', array(array(((isset($in['lastEditId']) && is_array($in)) ? $in['lastEditId'] : null)),array()), 'encq').'</a>
'.$sp.'').' </span>
'.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
@@ -196,7 +160,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ' <div class="flow-moderated-post-content">
'.$sp.''.LCRun3::p($cx, 'flow_post_moderation_state', array(array($in),array()), ' ').' </div>
'.$sp.'' : '').'
-'.$sp.' <div class="flow-post-content">
+'.$sp.' <div class="flow-post-content mw-parser-output">
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['content']['format']) && is_array($in['content'])) ? $in['content']['format'] : null),((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
'.$sp.'
@@ -227,51 +191,47 @@
'.$sp.' </div>
'.$sp.'
'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button class="mw-ui-button mw-ui-constructive"
+'.$sp.' <button class="mw-ui-button mw-ui-progressive"
'.$sp.' data-flow-api-handler="submitEditPost">'.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post-submit'),array()), 'encq').'</button>
'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
'.$sp.' </div>
'.$sp.'</form>
-';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <form class="flow-post flow-reply-form"
-'.$sp.' method="POST"
-'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-initial-state="collapsed"
-'.$sp.' >
-'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
-'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
-'.$sp.' <div class="flow-editor">
-'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
-'.$sp.' name="topic_content"
-'.$sp.' required
-'.$sp.' data-flow-expandable="true"
-'.$sp.' class="mw-ui-input flow-click-interactive"
-'.$sp.' type="text"
-'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'"
-'.$sp.' data-role="content"
+';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '
+'.$sp.'<form class="flow-post flow-reply-form"
+'.$sp.' method="POST"
+'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' data-flow-initial-state="collapsed"
+'.$sp.'>
+'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
+'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
+'.$sp.' <div class="flow-editor">
+'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
+'.$sp.' name="topic_content"
+'.$sp.' required
+'.$sp.' data-flow-expandable="true"
+'.$sp.' class="mw-ui-input flow-click-interactive"
+'.$sp.' type="text"
+'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'"
+'.$sp.' data-role="content"
'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateReplyTopic"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
-'.$sp.' </div>
+'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
+'.$sp.' </div>
'.$sp.'
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="submitReply"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
-'.$sp.' </div>
-'.$sp.' </form>
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-link'),array()), 'encq').'</button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
+'.$sp.' </div>
+'.$sp.'</form>
'.$sp.'' : '').'';},'flow_post_replies' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-replies">
'.$sp.''.LCRun3::sec($cx, ((isset($in['replies']) && is_array($in)) ? $in['replies'] : null), $in, true, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), $in, false, function($cx, $in)use($sp){return ' <!-- eachPost nested replies -->
'.$sp.' '.LCRun3::ch($cx, 'post', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), 'encq').'
'.$sp.'';}).'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['postId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['action']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['action'] : null),'===','reply'),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).'';}).'</div>
-';},'flow_post' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in)use($sp){return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+';},'flow_post_partial' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in)use($sp){return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="flow-post'.((LCRun3::ifvar($cx, ((isset($in['isMaxThreadingDepth']) && is_array($in)) ? $in['isMaxThreadingDepth'] : null))) ? ' flow-post-max-depth' : '').'"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >
@@ -289,7 +249,7 @@
);
return '<div class="flow-board">
-'.LCRun3::sec($cx, ((isset($in['roots']) && is_array($in)) ? $in['roots'] : null), $in, true, function($cx, $in) {return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),$in),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_moderate_post', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_post', array(array($in),array()), ' ').'';}).'';}).'</div>
+'.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null)),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_moderate_post', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_post_partial', array(array($in),array()), ' ').'';}).'</div>
';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
index f50c57d7..f2d9bd62 100644
--- a/Flow/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_moderate_topic.handlebars.php
@@ -37,16 +37,17 @@
'.$sp.'' : '').'</div>
';},'flow_moderate_topic' => function ($cx, $in, $sp) {return ''.$sp.'<form method="POST" action="'.LCRun3::ch($cx, 'moderationAction', array(array(((isset($in['actions']) && is_array($in)) ? $in['actions'] : null),((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null)),array()), 'encq').'">
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['editToken']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <textarea name="topic_reason"
+'.$sp.' <input name="topic_reason"
+'.$sp.' type="text"
+'.$sp.' size="45"
'.$sp.' required
'.$sp.' data-flow-expandable="true"
'.$sp.' class="mw-ui-input"
'.$sp.' data-role="content"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-moderation-placeholder-',((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null),'-topic'),array()), 'raw')),array()), 'encq').'"
-'.$sp.' autofocus
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null))) ? ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null), ENT_QUOTES, 'UTF-8').'' : '').'</textarea>
+'.$sp.' autofocus'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null))) ? 'value="'.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['reason']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['reason'] : null), ENT_QUOTES, 'UTF-8').'"' : '').'>
'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button class="mw-ui-button mw-ui-constructive"
+'.$sp.' <button class="mw-ui-button mw-ui-progressive"
'.$sp.' data-flow-interactive-handler="apiRequest"
'.$sp.' data-flow-api-handler="moderateTopic"
'.$sp.' data-role="submit">'.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-moderation-confirm-',((isset($cx['sp_vars']['root']['submitted']['moderationState']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['moderationState'] : null),'-topic'),array()), 'raw')),array()), 'encq').'</button>
@@ -60,7 +61,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['links']) && is_array($in)) ? $in['links'] : null))) ? ''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['links']['userpage']['url']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' '.((!LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? 'title="'.htmlentities((string)((isset($in['links']['userpage']['title']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['title'] : null), ENT_QUOTES, 'UTF-8').'"' : '').'
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['userpage']['exists']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['exists'] : null))) ? 'new ' : '').'mw-userlink">
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? ''.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? '<bdi>'.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'</bdi>' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
'.$sp.' ('.((LCRun3::ifvar($cx, ((isset($in['links']['talk']) && is_array($in['links'])) ? $in['links']['talk'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['talk']['url']) && is_array($in['links']['talk'])) ? $in['links']['talk']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['talk']['exists']) && is_array($in['links']['talk'])) ? $in['links']['talk']['exists'] : null))) ? 'new ' : '').'"
'.$sp.' title="'.htmlentities((string)((isset($in['links']['talk']['title']) && is_array($in['links']['talk'])) ? $in['links']['talk']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('talkpagelinktext'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['contribs']) && is_array($in['links'])) ? $in['links']['contribs'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['contribs']['url']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['url'] : null), ENT_QUOTES, 'UTF-8').'" title="'.htmlentities((string)((isset($in['links']['contribs']['title']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('contribslink'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['block']) && is_array($in['links'])) ? $in['links']['block'] : null))) ? '<span><a class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['block']['exists']) && is_array($in['links']['block'])) ? $in['links']['block']['exists'] : null))) ? 'new ' : '').'"
@@ -73,9 +74,7 @@
'.$sp.' <span class="flow-post-meta-actions">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['reply']['title']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet"
-'.$sp.' data-flow-interactive-handler="activateReplyPost"
-'.$sp.'
+'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet flow-reply-link"
'.$sp.' data-flow-eventlog-schema="FlowReplies"
'.$sp.' data-flow-eventlog-action="initiate"
'.$sp.' data-flow-eventlog-entrypoint="reply-post"
@@ -84,7 +83,7 @@
'.$sp.' < .flow-post:not([data-flow-post-max-depth=\'1\']) .flow-reply-form [data-role=\'submit\']
'.$sp.' "
'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-constructive mw-ui-quiet mw-thanks-flow-thank-link"
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-progressive mw-ui-quiet mw-thanks-flow-thank-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['thank']['url']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['thank']['title']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.htmlentities((string)((isset($in['actions']['thank']['text']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
'.$sp.'' : '').' </span>
@@ -100,88 +99,53 @@
'.$sp.' <a href="'.htmlentities((string)((isset($in['links']['diff-prev']['url']) && is_array($in['links']['diff-prev'])) ? $in['links']['diff-prev']['url'] : null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 'uuidTimestamp', array(array(((isset($in['lastEditId']) && is_array($in)) ? $in['lastEditId'] : null)),array()), 'encq').'</a>
'.$sp.'').' </span>
'.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
@@ -196,7 +160,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ' <div class="flow-moderated-post-content">
'.$sp.''.LCRun3::p($cx, 'flow_post_moderation_state', array(array($in),array()), ' ').' </div>
'.$sp.'' : '').'
-'.$sp.' <div class="flow-post-content">
+'.$sp.' <div class="flow-post-content mw-parser-output">
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['content']['format']) && is_array($in['content'])) ? $in['content']['format'] : null),((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
'.$sp.'
@@ -227,51 +191,47 @@
'.$sp.' </div>
'.$sp.'
'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button class="mw-ui-button mw-ui-constructive"
+'.$sp.' <button class="mw-ui-button mw-ui-progressive"
'.$sp.' data-flow-api-handler="submitEditPost">'.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post-submit'),array()), 'encq').'</button>
'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
'.$sp.' </div>
'.$sp.'</form>
-';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <form class="flow-post flow-reply-form"
-'.$sp.' method="POST"
-'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-initial-state="collapsed"
-'.$sp.' >
-'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
-'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
-'.$sp.' <div class="flow-editor">
-'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
-'.$sp.' name="topic_content"
-'.$sp.' required
-'.$sp.' data-flow-expandable="true"
-'.$sp.' class="mw-ui-input flow-click-interactive"
-'.$sp.' type="text"
-'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'"
-'.$sp.' data-role="content"
+';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '
+'.$sp.'<form class="flow-post flow-reply-form"
+'.$sp.' method="POST"
+'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' data-flow-initial-state="collapsed"
+'.$sp.'>
+'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
+'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
+'.$sp.' <div class="flow-editor">
+'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
+'.$sp.' name="topic_content"
+'.$sp.' required
+'.$sp.' data-flow-expandable="true"
+'.$sp.' class="mw-ui-input flow-click-interactive"
+'.$sp.' type="text"
+'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'"
+'.$sp.' data-role="content"
'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateReplyTopic"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
-'.$sp.' </div>
+'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
+'.$sp.' </div>
'.$sp.'
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="submitReply"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
-'.$sp.' </div>
-'.$sp.' </form>
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-link'),array()), 'encq').'</button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
+'.$sp.' </div>
+'.$sp.'</form>
'.$sp.'' : '').'';},'flow_post_replies' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-replies">
'.$sp.''.LCRun3::sec($cx, ((isset($in['replies']) && is_array($in)) ? $in['replies'] : null), $in, true, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), $in, false, function($cx, $in)use($sp){return ' <!-- eachPost nested replies -->
'.$sp.' '.LCRun3::ch($cx, 'post', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), 'encq').'
'.$sp.'';}).'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['postId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['action']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['action'] : null),'===','reply'),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).'';}).'</div>
-';},'flow_post' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in)use($sp){return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+';},'flow_post_partial' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in)use($sp){return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="flow-post'.((LCRun3::ifvar($cx, ((isset($in['isMaxThreadingDepth']) && is_array($in)) ? $in['isMaxThreadingDepth'] : null))) ? ' flow-post-max-depth' : '').'"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >
@@ -289,7 +249,7 @@
);
return '<div class="flow-board">
-'.LCRun3::sec($cx, ((isset($in['roots']) && is_array($in)) ? $in['roots'] : null), $in, true, function($cx, $in) {return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),$in),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_moderate_topic', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_post', array(array($in),array()), ' ').'';}).'';}).'</div>
+'.LCRun3::sec($cx, ((isset($in['roots']) && is_array($in)) ? $in['roots'] : null), $in, true, function($cx, $in) {return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),$in),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_moderate_topic', array(array($in),array()), ' ').''.LCRun3::p($cx, 'flow_post_partial', array(array($in),array()), ' ').'';}).'';}).'</div>
';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_topic_single_view.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_single_view.handlebars.php
index d8018085..11babc28 100644
--- a/Flow/handlebars/compiled/flow_block_topic_single_view.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_single_view.handlebars.php
@@ -26,7 +26,7 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},'flow_patrol_action' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div class="patrollink">
+';},'flow_patrol_action' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div class="patrollink" data-mw="interface">
'.$sp.' [<a class="mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['revision']['rev_view_links']['markPatrolled']['url']) && is_array($in['revision']['rev_view_links']['markPatrolled'])) ? $in['revision']['rev_view_links']['markPatrolled']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-mark-revision-patrolled-link-title'),array()), 'encq').'"
diff --git a/Flow/handlebars/compiled/flow_block_topic_undo_edit.handlebars.php b/Flow/handlebars/compiled/flow_block_topic_undo_edit.handlebars.php
index 44171921..48ee8254 100644
--- a/Flow/handlebars/compiled/flow_block_topic_undo_edit.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topic_undo_edit.handlebars.php
@@ -49,7 +49,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-post-submit'),array()), 'encq').'</button>
+ <button class="mw-ui-button mw-ui-progressive">'.LCRun3::ch($cx, 'l10n', array(array('flow-edit-post-submit'),array()), 'encq').'</button>
<small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'
</small>
</div>
diff --git a/Flow/handlebars/compiled/flow_block_topiclist.handlebars.php b/Flow/handlebars/compiled/flow_block_topiclist.handlebars.php
index 541f8196..6ff4ffeb 100644
--- a/Flow/handlebars/compiled/flow_block_topiclist.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topiclist.handlebars.php
@@ -28,12 +28,11 @@
'tooltip' => 'Flow\TemplateHelper::tooltip',
'progressiveEnhancement' => 'Flow\TemplateHelper::progressiveEnhancement',
),
- 'partials' => array('flow_board_navigation' => function ($cx, $in, $sp) {return ''.$sp.'
-'.$sp.'<div class="flow-board-navigation" data-flow-load-handler="boardNavigation">
+ 'partials' => array('flow_board_navigation' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['links']['board-sort']) && is_array($in['links'])) ? $in['links']['board-sort'] : null))) ? '<div class="flow-board-navigation" data-flow-load-handler="boardNavigation">
'.$sp.' <div class="flow-error-container">
'.$sp.' </div>
'.$sp.'</div>
-';},'flow_errors' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-error-container">
+'.$sp.'' : '').'';},'flow_errors' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-error-container">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['errors']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null))) ? ' <div class="flow-errors errorbox">
'.$sp.' <ul>
'.$sp.''.LCRun3::sec($cx, ((isset($cx['sp_vars']['root']['errors']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['errors'] : null), $in, true, function($cx, $in)use($sp){return ' <li>'.LCRun3::ch($cx, 'html', array(array(((isset($in['message']) && is_array($in)) ? $in['message'] : null)),array()), 'encq').'</li>
@@ -65,12 +64,10 @@
'.$sp.' type="text"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-start-placeholder'),array()), 'encq').'"
'.$sp.' data-role="title"
-'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateNewTopic"
'.$sp.' />
'.$sp.' <div class="flow-editor">
'.$sp.' <textarea name="topiclist_content"
-'.$sp.' class="mw-ui-input flow-form-collapsible mw-ui-input-large'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'"
+'.$sp.' class="mw-ui-input flow-form-collapsible'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-content-placeholder',((isset($cx['sp_vars']['root']['title']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['title'] : null)),array()), 'encq').'"
'.$sp.' data-role="content"
'.$sp.' required
@@ -78,24 +75,22 @@
'.$sp.' </div>
'.$sp.'
'.$sp.' <div class="flow-form-actions flow-form-collapsible'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'">
-'.$sp.' <button data-role="submit" data-flow-api-handler="newTopic"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' class="mw-ui-button mw-ui-constructive mw-ui-flush-right">'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-save'),array()), 'encq').'</button>
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive mw-ui-flush-right">'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-save'),array()), 'encq').'</button>
'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-new-topic'),array()), 'encq').'</small>
'.$sp.' </div>
'.$sp.' </form>
-'.$sp.'' : '').'';},'flow_topic_moderation_flag' => function ($cx, $in, $sp) {return ''.$sp.'<span class="mw-ui-icon mw-ui-icon-before'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','lock'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-check';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','hide'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-flag';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','delete'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-remove';}).'"></span>
+'.$sp.'' : '').'';},'flow_topic_moderation_flag' => function ($cx, $in, $sp) {return ''.$sp.'<span class="mw-ui-icon mw-ui-icon-before'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','lock'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-check';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','hide'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-flag';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'===','delete'),array()), $in, false, function($cx, $in)use($sp){return ' mw-ui-icon-trash';}).'"></span>
';},'flow_post_moderation_state' => function ($cx, $in, $sp) {return ''.$sp.'<span class="plainlinks">'.((LCRun3::ifvar($cx, ((isset($in['replyToId']) && is_array($in)) ? $in['replyToId'] : null))) ? ''.LCRun3::ch($cx, 'l10nParse', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'-post-content'),array()), 'raw'),((isset($in['moderator']['name']) && is_array($in['moderator'])) ? $in['moderator']['name'] : null),((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null)),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10nParse', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null),'-title-content'),array()), 'raw'),((isset($in['moderator']['name']) && is_array($in['moderator'])) ? $in['moderator']['name'] : null),((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null)),array()), 'encq').'').'</span>
';},'flow_topic_titlebar_content' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-titlebar-container">
-'.$sp.' <h2 class="flow-topic-title flow-load-interactive '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-click-interactive' : '').'"
+'.$sp.' <h2 class="flow-topic-title flow-load-interactive '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-collapse-toggle flow-click-interactive' : '').'"
'.$sp.' data-flow-topic-title="'.htmlentities((string)((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-load-handler="topicTitle"
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' data-flow-interactive-handler="collapserCollapsibleToggle"
'.$sp.'' : '').' >
'.$sp.' '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check"></span> ' : '').''.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['content']['format']) && is_array($in['content'])) ? $in['content']['format'] : null),((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null)),array()), 'encq').'</h2>
'.$sp.' <div class="flow-topic-meta">
-'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<a class="expand-collapse-posts-link flow-click-interactive"
+'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? '<a class="expand-collapse-posts-link flow-collapse-toggle flow-click-interactive"
'.$sp.' href="javascript:void(0);"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-show-comments-title',((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null)),array()), 'encq').'"
'.$sp.' data-collapsed-title="'.LCRun3::ch($cx, 'l10n', array(array('flow-show-comments-title',((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null)),array()), 'encq').'"
@@ -115,7 +110,7 @@
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['moderateReason']['format']) && is_array($in['moderateReason'])) ? $in['moderateReason']['format'] : null),((isset($in['moderateReason']['content']) && is_array($in['moderateReason'])) ? $in['moderateReason']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
'.$sp.'' : '').' <span class="flow-reply-count"><span class="flow-reply-count-number">'.htmlentities((string)((isset($in['reply_count']) && is_array($in)) ? $in['reply_count'] : null), ENT_QUOTES, 'UTF-8').'</span></span>
-'.$sp.'</div>';},'flow_topic_titlebar_summary' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-summary-container '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-click-interactive' : '').'"
+'.$sp.'</div>';},'flow_topic_titlebar_summary' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-summary-container '.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-collapse-toggle flow-click-interactive' : '').'"
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? ' data-flow-interactive-handler="collapserCollapsibleToggle"
'.$sp.'' : '').' >
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').''.((LCRun3::ifvar($cx, ((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null))) ? ' <div class="flow-topic-summary">
@@ -124,102 +119,68 @@
'.$sp.'';}, function($cx, $in)use($sp){return ' '.LCRun3::ch($cx, 'l10n', array(array('flow-summary-edited',((isset($in['revision']['author']['name']) && is_array($in['revision']['author'])) ? $in['revision']['author']['name'] : null)),array()), 'encq').'
'.$sp.' <a href="'.htmlentities((string)((isset($in['revision']['links']['diff-prev']['url']) && is_array($in['revision']['links']['diff-prev'])) ? $in['revision']['links']['diff-prev']['url'] : null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 'uuidTimestamp', array(array(((isset($in['revision']['lastEditId']) && is_array($in['revision'])) ? $in['revision']['lastEditId'] : null)),array()), 'encq').'</a>
'.$sp.'';}).' </div>
-'.$sp.' <div class="flow-topic-summary-content">
+'.$sp.' <div class="flow-topic-summary-content mw-parser-output">
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['revision']['content']['format']) && is_array($in['revision']['content'])) ? $in['revision']['content']['format'] : null),((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
+'.$sp.' <div style="clear: both;"></div>
'.$sp.' </div>
'.$sp.'' : '').'</div>
';},'flow_topic_titlebar_watch' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic-watchlist flow-watch-link">
'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
'.$sp.' <a href="'.((LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? ''.htmlentities((string)((isset($in['links']['unwatch-topic']['url']) && is_array($in['links']['unwatch-topic'])) ? $in['links']['unwatch-topic']['url'] : null), ENT_QUOTES, 'UTF-8').'' : ''.htmlentities((string)((isset($in['links']['watch-topic']['url']) && is_array($in['links']['watch-topic'])) ? $in['links']['watch-topic']['url'] : null), ENT_QUOTES, 'UTF-8').'').'"
-'.$sp.' class="mw-ui-anchor mw-ui-hovericon mw-ui-constructive '.((!LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'mw-ui-quiet' : '').'
+'.$sp.' class="mw-ui-anchor mw-ui-hovericon '.((!LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'mw-ui-quiet' : '').'
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isWatched']) && is_array($in)) ? $in['isWatched'] : null))) ? 'flow-watch-link-unwatch' : 'flow-watch-link-watch').'"
'.$sp.' data-flow-api-handler="watchItem"
'.$sp.' data-flow-api-target="< .flow-topic-watchlist"
-'.$sp.' data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar-constructive" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-remove'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-constructive-hover" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-add'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
+'.$sp.' data-flow-api-method="POST">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar mw-ui-icon-unStar-progressive" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-remove'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').''.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-progressive-hover" title="'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-watchlist-add'),array()), 'encq').'"></span>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</a>
'.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
@@ -230,41 +191,37 @@
'.$sp.''.LCRun3::p($cx, 'flow_moderation_actions_list', array(array($in),array('moderationType'=>'topic','moderationTarget'=>'title','moderationTemplate'=>'topic','moderationContainerClass'=>'flow-menu','moderationMwUiClass'=>'mw-ui-button','moderationIcons'=>true)), ' ').' </ul>
'.$sp.' </div>
'.$sp.'</div>
-';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <form class="flow-post flow-reply-form"
-'.$sp.' method="POST"
-'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-initial-state="collapsed"
-'.$sp.' >
-'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
-'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
-'.$sp.' <div class="flow-editor">
-'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
-'.$sp.' name="topic_content"
-'.$sp.' required
-'.$sp.' data-flow-expandable="true"
-'.$sp.' class="mw-ui-input flow-click-interactive"
-'.$sp.' type="text"
-'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'"
-'.$sp.' data-role="content"
+';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '
+'.$sp.'<form class="flow-post flow-reply-form"
+'.$sp.' method="POST"
+'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' data-flow-initial-state="collapsed"
+'.$sp.'>
+'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
+'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
+'.$sp.' <div class="flow-editor">
+'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
+'.$sp.' name="topic_content"
+'.$sp.' required
+'.$sp.' data-flow-expandable="true"
+'.$sp.' class="mw-ui-input flow-click-interactive"
+'.$sp.' type="text"
+'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'"
+'.$sp.' data-role="content"
'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateReplyTopic"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
-'.$sp.' </div>
+'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
+'.$sp.' </div>
'.$sp.'
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="submitReply"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
-'.$sp.' </div>
-'.$sp.' </form>
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-link'),array()), 'encq').'</button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
+'.$sp.' </div>
+'.$sp.'</form>
'.$sp.'' : '').'';},'flow_topic' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-topic flow-load-interactive'.((LCRun3::ifvar($cx, ((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null))) ? ' flow-topic-moderatestate-'.htmlentities((string)((isset($in['moderateState']) && is_array($in)) ? $in['moderateState'] : null), ENT_QUOTES, 'UTF-8').' ' : '').''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ' flow-topic-moderated ' : '').''.((LCRun3::ifvar($cx, ((isset($in['isLocked']) && is_array($in)) ? $in['isLocked'] : null))) ? 'flow-element-collapsible flow-element-collapsed' : '').'"
'.$sp.' id="flow-topic-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
@@ -279,8 +236,8 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array('type'=>'replace','target'=>'~ a')), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).' <a href="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['reply']['title']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="flow-ui-input-replacement-anchor mw-ui-input"
-'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'</a>
-'.$sp.'';}).'' : '').'</div>
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'</a>
+'.$sp.'';}).'' : ''.LCRun3::hbch($cx, 'progressiveEnhancement', array(array(),array('type'=>'insert')), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).'').'</div>
';},'flow_topiclist_loop' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::sec($cx, ((isset($in['roots']) && is_array($in)) ? $in['roots'] : null), $in, true, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']) && is_array($cx['sp_vars'])) ? $cx['sp_vars']['root'] : null),$in),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_topic', array(array($in),array()), ' ').'';}).'';}).'';},'flow_load_more' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['loadMoreObject']) && is_array($in)) ? $in['loadMoreObject'] : null))) ? ' <div class="flow-load-more">
'.$sp.' <div class="flow-error-container">
'.$sp.' </div>
@@ -301,6 +258,7 @@
'.$sp.'' : ' <div class="flow-no-more">
'.$sp.' '.LCRun3::ch($cx, 'l10n', array(array('flow-no-more-fwd'),array()), 'encq').'
'.$sp.' </div>
+'.$sp.' <div class="flow-bottom-spacer"></div>
'.$sp.'').'';},),
'scopes' => array(),
'sp_vars' => array('root' => $in),
diff --git a/Flow/handlebars/compiled/flow_block_topiclist_newtopic.handlebars.php b/Flow/handlebars/compiled/flow_block_topiclist_newtopic.handlebars.php
index 083cbddc..00db7ef7 100644
--- a/Flow/handlebars/compiled/flow_block_topiclist_newtopic.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topiclist_newtopic.handlebars.php
@@ -53,12 +53,10 @@
'.$sp.' type="text"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-start-placeholder'),array()), 'encq').'"
'.$sp.' data-role="title"
-'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateNewTopic"
'.$sp.' />
'.$sp.' <div class="flow-editor">
'.$sp.' <textarea name="topiclist_content"
-'.$sp.' class="mw-ui-input flow-form-collapsible mw-ui-input-large'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'"
+'.$sp.' class="mw-ui-input flow-form-collapsible'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'"
'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-content-placeholder',((isset($cx['sp_vars']['root']['title']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['title'] : null)),array()), 'encq').'"
'.$sp.' data-role="content"
'.$sp.' required
@@ -66,10 +64,8 @@
'.$sp.' </div>
'.$sp.'
'.$sp.' <div class="flow-form-actions flow-form-collapsible'.((LCRun3::ifvar($cx, ((isset($in['isOnFlowBoard']) && is_array($in)) ? $in['isOnFlowBoard'] : null))) ? ' flow-form-collapsible-collapsed' : '').'">
-'.$sp.' <button data-role="submit" data-flow-api-handler="newTopic"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' class="mw-ui-button mw-ui-constructive mw-ui-flush-right">'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-save'),array()), 'encq').'</button>
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive mw-ui-flush-right">'.LCRun3::ch($cx, 'l10n', array(array('flow-newtopic-save'),array()), 'encq').'</button>
'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-new-topic'),array()), 'encq').'</small>
'.$sp.' </div>
'.$sp.' </form>
diff --git a/Flow/handlebars/compiled/flow_block_topicsummary_edit.handlebars.php b/Flow/handlebars/compiled/flow_block_topicsummary_edit.handlebars.php
index 2a785f1b..5130cf7a 100644
--- a/Flow/handlebars/compiled/flow_block_topicsummary_edit.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topicsummary_edit.handlebars.php
@@ -58,9 +58,7 @@
<div class="flow-form-actions flow-form-collapsible">
<button
data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="summarizeTopic"
+ class="mw-ui-button mw-ui-progressive"
data-flow-api-target="< .flow-topic-summary-container">
'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-update-topic-summary'),array()), 'encq').'
</button>
diff --git a/Flow/handlebars/compiled/flow_block_topicsummary_single_view.handlebars.php b/Flow/handlebars/compiled/flow_block_topicsummary_single_view.handlebars.php
index a0758048..13ed2d42 100644
--- a/Flow/handlebars/compiled/flow_block_topicsummary_single_view.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topicsummary_single_view.handlebars.php
@@ -11,9 +11,11 @@
'debug' => $debugopt,
),
'constants' => array(),
- 'helpers' => array( 'html' => 'Flow\TemplateHelper::htmlHelper',
+ 'helpers' => array( 'l10n' => 'Flow\TemplateHelper::l10n',
+ 'html' => 'Flow\TemplateHelper::htmlHelper',
'l10nParse' => 'Flow\TemplateHelper::l10nParse',
'escapeContent' => 'Flow\TemplateHelper::escapeContent',
+ 'enablePatrollingLink' => 'Flow\TemplateHelper::enablePatrollingLink',
),
'blockhelpers' => array(),
'hbhelpers' => array(),
@@ -24,7 +26,13 @@
'.$sp.'';}).' </ul>
'.$sp.' </div>
'.$sp.'' : '').'</div>
-';},),
+';},'flow_patrol_action' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div class="patrollink" data-mw="interface">
+'.$sp.' [<a class="mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['revision']['rev_view_links']['markPatrolled']['url']) && is_array($in['revision']['rev_view_links']['markPatrolled'])) ? $in['revision']['rev_view_links']['markPatrolled']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-mark-revision-patrolled-link-title'),array()), 'encq').'"
+'.$sp.' data-role="patrol">'.LCRun3::ch($cx, 'l10n', array(array('flow-mark-revision-patrolled-link-text'),array()), 'encq').'</a>]
+'.$sp.' </div>
+'.$sp.' '.LCRun3::ch($cx, 'enablePatrollingLink', array(array(),array()), 'encq').'' : '').'';},),
'scopes' => array(),
'sp_vars' => array('root' => $in),
'lcrun' => 'LCRun3',
@@ -40,7 +48,8 @@
<div class="flow-revision-content">
'.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['revision']['content']['format']) && is_array($in['revision']['content'])) ? $in['revision']['content']['format'] : null),((isset($in['revision']['content']['content']) && is_array($in['revision']['content'])) ? $in['revision']['content']['content'] : null)),array()), 'encq').'
</div>
-' : '').'</div>
+
+'.LCRun3::p($cx, 'flow_patrol_action', array(array($in),array()), ' ').'' : '').'</div>
';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_block_topicsummary_undo_edit.handlebars.php b/Flow/handlebars/compiled/flow_block_topicsummary_undo_edit.handlebars.php
index 5cd48904..aa0c6eb0 100644
--- a/Flow/handlebars/compiled/flow_block_topicsummary_undo_edit.handlebars.php
+++ b/Flow/handlebars/compiled/flow_block_topicsummary_undo_edit.handlebars.php
@@ -51,7 +51,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-summarize-topic'),array()), 'encq').'</button>
+ <button class="mw-ui-button mw-ui-progressive">'.LCRun3::ch($cx, 'l10n', array(array('flow-topic-action-summarize-topic'),array()), 'encq').'</button>
<small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-summarize'),array()), 'encq').'
</small>
</div>
diff --git a/Flow/handlebars/compiled/flow_post.handlebars.php b/Flow/handlebars/compiled/flow_post.handlebars.php
index 6500f4ec..4b5db3e1 100644
--- a/Flow/handlebars/compiled/flow_post.handlebars.php
+++ b/Flow/handlebars/compiled/flow_post.handlebars.php
@@ -38,7 +38,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['links']) && is_array($in)) ? $in['links'] : null))) ? ''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['links']['userpage']['url']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' '.((!LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? 'title="'.htmlentities((string)((isset($in['links']['userpage']['title']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['title'] : null), ENT_QUOTES, 'UTF-8').'"' : '').'
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['userpage']['exists']) && is_array($in['links']['userpage'])) ? $in['links']['userpage']['exists'] : null))) ? 'new ' : '').'mw-userlink">
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? ''.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['name']) && is_array($in)) ? $in['name'] : null))) ? '<bdi>'.htmlentities((string)((isset($in['name']) && is_array($in)) ? $in['name'] : null), ENT_QUOTES, 'UTF-8').'</bdi>' : ''.LCRun3::ch($cx, 'l10n', array(array('flow-anonymous'),array()), 'encq').'').''.((LCRun3::ifvar($cx, ((isset($in['links']['userpage']) && is_array($in['links'])) ? $in['links']['userpage'] : null))) ? '</a>' : '').'<span class="mw-usertoollinks flow-pipelist">
'.$sp.' ('.((LCRun3::ifvar($cx, ((isset($in['links']['talk']) && is_array($in['links'])) ? $in['links']['talk'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['talk']['url']) && is_array($in['links']['talk'])) ? $in['links']['talk']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['talk']['exists']) && is_array($in['links']['talk'])) ? $in['links']['talk']['exists'] : null))) ? 'new ' : '').'"
'.$sp.' title="'.htmlentities((string)((isset($in['links']['talk']['title']) && is_array($in['links']['talk'])) ? $in['links']['talk']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('talkpagelinktext'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['contribs']) && is_array($in['links'])) ? $in['links']['contribs'] : null))) ? '<span><a href="'.htmlentities((string)((isset($in['links']['contribs']['url']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['url'] : null), ENT_QUOTES, 'UTF-8').'" title="'.htmlentities((string)((isset($in['links']['contribs']['title']) && is_array($in['links']['contribs'])) ? $in['links']['contribs']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.LCRun3::ch($cx, 'l10n', array(array('contribslink'),array()), 'encq').'</a></span>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['block']) && is_array($in['links'])) ? $in['links']['block'] : null))) ? '<span><a class="'.((!LCRun3::ifvar($cx, ((isset($in['links']['block']['exists']) && is_array($in['links']['block'])) ? $in['links']['block']['exists'] : null))) ? 'new ' : '').'"
@@ -51,9 +51,7 @@
'.$sp.' <span class="flow-post-meta-actions">
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <a href="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['reply']['title']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet"
-'.$sp.' data-flow-interactive-handler="activateReplyPost"
-'.$sp.'
+'.$sp.' class="mw-ui-anchor mw-ui-progressive mw-ui-quiet flow-reply-link"
'.$sp.' data-flow-eventlog-schema="FlowReplies"
'.$sp.' data-flow-eventlog-action="initiate"
'.$sp.' data-flow-eventlog-entrypoint="reply-post"
@@ -62,7 +60,7 @@
'.$sp.' < .flow-post:not([data-flow-post-max-depth=\'1\']) .flow-reply-form [data-role=\'submit\']
'.$sp.' "
'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
-'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-constructive mw-ui-quiet mw-thanks-flow-thank-link"
+'.$sp.'' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['thank']) && is_array($in['actions'])) ? $in['actions']['thank'] : null))) ? ' <a class="mw-ui-anchor mw-ui-progressive mw-ui-quiet mw-thanks-flow-thank-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['thank']['url']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.htmlentities((string)((isset($in['actions']['thank']['title']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.htmlentities((string)((isset($in['actions']['thank']['text']) && is_array($in['actions']['thank'])) ? $in['actions']['thank']['text'] : null), ENT_QUOTES, 'UTF-8').'</a>
'.$sp.'' : '').' </span>
@@ -78,88 +76,53 @@
'.$sp.' <a href="'.htmlentities((string)((isset($in['links']['diff-prev']['url']) && is_array($in['links']['diff-prev'])) ? $in['links']['diff-prev']['url'] : null), ENT_QUOTES, 'UTF-8').'" class="flow-timestamp-anchor">'.LCRun3::ch($cx, 'uuidTimestamp', array(array(((isset($in['lastEditId']) && is_array($in)) ? $in['lastEditId'] : null)),array()), 'encq').'</a>
'.$sp.'').' </span>
'.$sp.'</div>
-';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li class="flow-js">'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateEditTitle"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic-history']['title']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['topic']['title']) && is_array($in['links']['topic'])) ? $in['links']['topic']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="activateSummarizeTopic"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['summarize']['title']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+';},'flow_moderation_actions_list' => function ($cx, $in, $sp) {return ''.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','topic'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-edit-title'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic-history']) && is_array($in['links'])) ? $in['links']['topic-history'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic-history']['url']) && is_array($in['links']['topic-history'])) ? $in['links']['topic-history']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-history'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['topic']) && is_array($in['links'])) ? $in['links']['topic'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['topic']['url']) && is_array($in['links']['topic'])) ? $in['links']['topic']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['summarize']) && is_array($in['actions'])) ? $in['actions']['summarize'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['summarize']['url']) && is_array($in['actions']['summarize'])) ? $in['actions']['summarize']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> ' : '').''.((LCRun3::ifvar($cx, ((isset($in['summary']['revision']['content']['content']) && is_array($in['summary']['revision']['content'])) ? $in['summary']['revision']['content']['content'] : null))) ? ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-resummarize-topic'),array()), 'raw')),array()), 'encq').'' : ''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-topic-action-summarize-topic'),array()), 'raw')),array()), 'encq').'').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockTopic"
-'.$sp.' data-flow-api-method="POST"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-role="unlock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['lock']) && is_array($in['actions'])) ? $in['actions']['lock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['lock']['title']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="lockAndSummarizeTopic"
+'.$sp.' data-role="lock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['lock']['url']) && is_array($in['actions']['lock'])) ? $in['actions']['lock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-lock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
-'.$sp.' data-flow-api-method="POST"
-'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unlock']['title']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
+'.$sp.' data-role="unlock"
+'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unlock']['url']) && is_array($in['actions']['unlock'])) ? $in['actions']['unlock']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unlock-topic'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','post'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['edit']) && is_array($in['actions'])) ? $in['actions']['edit'] : null))) ? '<li>
'.$sp.' <a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['edit']['url']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['edit']['title']) && is_array($in['actions']['edit'])) ? $in['actions']['edit']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post'),array()), 'encq').'</a>
'.$sp.' </li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['links']['post']) && is_array($in['links'])) ? $in['links']['post'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
-'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['links']['post']['title']) && is_array($in['links']['post'])) ? $in['links']['post']['title'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
+'.$sp.' href="'.htmlentities((string)((isset($in['links']['post']['url']) && is_array($in['links']['post'])) ? $in['links']['post']['url'] : null), ENT_QUOTES, 'UTF-8').'">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-post-action-view'),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).'</section>
'.$sp.'
'.$sp.'<section>'.LCRun3::hbch($cx, 'ifCond', array(array(((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'===','history'),array()), $in, false, function($cx, $in)use($sp){return ''.((LCRun3::ifvar($cx, ((isset($in['actions']['undo']) && is_array($in['actions'])) ? $in['actions']['undo'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undo']['url']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' >'.htmlentities((string)((isset($in['actions']['undo']['title']) && is_array($in['actions']['undo'])) ? $in['actions']['undo']['title'] : null), ENT_QUOTES, 'UTF-8').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'';}).''.((LCRun3::ifvar($cx, ((isset($in['actions']['hide']) && is_array($in['actions'])) ? $in['actions']['hide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['hide']['url']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['hide']['title']) && is_array($in['actions']['hide'])) ? $in['actions']['hide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="hide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-hide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unhide']) && is_array($in['actions'])) ? $in['actions']['unhide'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unhide']['url']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unhide']['title']) && is_array($in['actions']['unhide'])) ? $in['actions']['unhide']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unhide">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-flag"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unhide-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['delete']) && is_array($in['actions'])) ? $in['actions']['delete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['delete']['url']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['delete']['title']) && is_array($in['actions']['delete'])) ? $in['actions']['delete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="delete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-delete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['undelete']) && is_array($in['actions'])) ? $in['actions']['undelete'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['undelete']['url']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['undelete']['title']) && is_array($in['actions']['undelete'])) ? $in['actions']['undelete']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
-'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
+'.$sp.' data-role="undelete">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-undelete-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['suppress']) && is_array($in['actions'])) ? $in['actions']['suppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['suppress']['url']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['suppress']['title']) && is_array($in['actions']['suppress'])) ? $in['actions']['suppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="suppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-suppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').''.((LCRun3::ifvar($cx, ((isset($in['actions']['unsuppress']) && is_array($in['actions'])) ? $in['actions']['unsuppress'] : null))) ? '<li>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'<a class="'.htmlentities((string)((isset($in['moderationMwUiClass']) && is_array($in)) ? $in['moderationMwUiClass'] : null), ENT_QUOTES, 'UTF-8').' mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
'.$sp.' href="'.htmlentities((string)((isset($in['actions']['unsuppress']['url']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' title="'.htmlentities((string)((isset($in['actions']['unsuppress']['title']) && is_array($in['actions']['unsuppress'])) ? $in['actions']['unsuppress']['title'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' data-flow-interactive-handler="moderationDialog"
'.$sp.' data-flow-template="flow_moderate_'.htmlentities((string)((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null), ENT_QUOTES, 'UTF-8').'.partial"
'.$sp.' data-role="unsuppress">'.((LCRun3::ifvar($cx, ((isset($in['moderationIcons']) && is_array($in)) ? $in['moderationIcons'] : null))) ? '<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-block mw-ui-icon-block-destructive-hover"></span> ' : '').''.LCRun3::ch($cx, 'l10n', array(array(LCRun3::ch($cx, 'concat', array(array('flow-',((isset($in['moderationType']) && is_array($in)) ? $in['moderationType'] : null),'-action-unsuppress-',((isset($in['moderationTemplate']) && is_array($in)) ? $in['moderationTemplate'] : null)),array()), 'raw')),array()), 'encq').'</a>'.htmlentities((string)((isset($in['noop']) && is_array($in)) ? $in['noop'] : null), ENT_QUOTES, 'UTF-8').'</li>' : '').'</section>
@@ -174,7 +137,7 @@
'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ' <div class="flow-moderated-post-content">
'.$sp.''.LCRun3::p($cx, 'flow_post_moderation_state', array(array($in),array()), ' ').' </div>
'.$sp.'' : '').'
-'.$sp.' <div class="flow-post-content">
+'.$sp.' <div class="flow-post-content mw-parser-output">
'.$sp.' '.LCRun3::ch($cx, 'escapeContent', array(array(((isset($in['content']['format']) && is_array($in['content'])) ? $in['content']['format'] : null),((isset($in['content']['content']) && is_array($in['content'])) ? $in['content']['content'] : null)),array()), 'encq').'
'.$sp.' </div>
'.$sp.'
@@ -205,67 +168,63 @@
'.$sp.' </div>
'.$sp.'
'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button class="mw-ui-button mw-ui-constructive"
+'.$sp.' <button class="mw-ui-button mw-ui-progressive"
'.$sp.' data-flow-api-handler="submitEditPost">'.LCRun3::ch($cx, 'l10n', array(array('flow-post-action-edit-post-submit'),array()), 'encq').'</button>
'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-edit'),array()), 'encq').'</small>
'.$sp.' </div>
'.$sp.'</form>
-';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['actions']['reply']) && is_array($in['actions'])) ? $in['actions']['reply'] : null))) ? ' <form class="flow-post flow-reply-form"
-'.$sp.' method="POST"
-'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
-'.$sp.' data-flow-initial-state="collapsed"
-'.$sp.' >
-'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
-'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
-'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
-'.$sp.' <div class="flow-editor">
-'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
-'.$sp.' name="topic_content"
-'.$sp.' required
-'.$sp.' data-flow-expandable="true"
-'.$sp.' class="mw-ui-input flow-click-interactive"
-'.$sp.' type="text"
-'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post']) && is_array($in['properties'])) ? $in['properties']['topic-of-post'] : null)),array()), 'encq').'"
-'.$sp.' data-role="content"
+';},'flow_reply_form' => function ($cx, $in, $sp) {return ''.$sp.''.((!LCRun3::ifvar($cx, ((isset($in['actions']['unlock']) && is_array($in['actions'])) ? $in['actions']['unlock'] : null))) ? '
+'.$sp.'<form class="flow-post flow-reply-form"
+'.$sp.' method="POST"
+'.$sp.' action="'.htmlentities((string)((isset($in['actions']['reply']['url']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['url'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' id="flow-reply-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' data-flow-initial-state="collapsed"
+'.$sp.'>
+'.$sp.' <input type="hidden" name="wpEditToken" value="'.htmlentities((string)((isset($cx['sp_vars']['root']['rootBlock']['editToken']) && is_array($cx['sp_vars']['root']['rootBlock'])) ? $cx['sp_vars']['root']['rootBlock']['editToken'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.' <input type="hidden" name="topic_replyTo" value="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'" />
+'.$sp.''.LCRun3::p($cx, 'flow_errors', array(array($in),array()), ' ').'
+'.$sp.''.LCRun3::hbch($cx, 'ifAnonymous', array(array(),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_anon_warning', array(array($in),array()), ' ').'';}).'
+'.$sp.' <div class="flow-editor">
+'.$sp.' <textarea id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'-form-content"
+'.$sp.' name="topic_content"
+'.$sp.' required
+'.$sp.' data-flow-expandable="true"
+'.$sp.' class="mw-ui-input flow-click-interactive"
+'.$sp.' type="text"
+'.$sp.' placeholder="'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-topic-title-placeholder',((isset($in['properties']['topic-of-post-text-from-html']) && is_array($in['properties'])) ? $in['properties']['topic-of-post-text-from-html'] : null)),array()), 'encq').'"
+'.$sp.' data-role="content"
'.$sp.'
-'.$sp.' data-flow-interactive-handler-focus="activateReplyTopic"
-'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
-'.$sp.' </div>
+'.$sp.' >'.((LCRun3::ifvar($cx, ((isset($cx['sp_vars']['root']['submitted']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['submitted'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['submitted']['postId']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.htmlentities((string)((isset($cx['sp_vars']['root']['submitted']['content']) && is_array($cx['sp_vars']['root']['submitted'])) ? $cx['sp_vars']['root']['submitted']['content'] : null), ENT_QUOTES, 'UTF-8').'';}).'' : '').'</textarea>
+'.$sp.' </div>
'.$sp.'
-'.$sp.' <div class="flow-form-actions flow-form-collapsible">
-'.$sp.' <button data-role="submit"
-'.$sp.' class="mw-ui-button mw-ui-constructive"
-'.$sp.' data-flow-interactive-handler="apiRequest"
-'.$sp.' data-flow-api-handler="submitReply"
-'.$sp.' data-flow-api-target="< .flow-topic"
-'.$sp.' data-flow-eventlog-action="save-attempt"
-'.$sp.' >'.htmlentities((string)((isset($in['actions']['reply']['text']) && is_array($in['actions']['reply'])) ? $in['actions']['reply']['text'] : null), ENT_QUOTES, 'UTF-8').'</button>
-'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
-'.$sp.' </div>
-'.$sp.' </form>
+'.$sp.' <div class="flow-form-actions flow-form-collapsible">
+'.$sp.' <button data-role="submit"
+'.$sp.' class="mw-ui-button mw-ui-progressive"
+'.$sp.' >'.LCRun3::ch($cx, 'l10n', array(array('flow-reply-link'),array()), 'encq').'</button>
+'.$sp.''.LCRun3::p($cx, 'flow_form_cancel_button', array(array($in),array()), ' ').' <small class="flow-terms-of-use plainlinks">'.LCRun3::ch($cx, 'l10nParse', array(array('flow-terms-of-use-reply'),array()), 'encq').'</small>
+'.$sp.' </div>
+'.$sp.'</form>
'.$sp.'' : '').'';},'flow_post_replies' => function ($cx, $in, $sp) {return ''.$sp.'<div class="flow-replies">
'.$sp.''.LCRun3::sec($cx, ((isset($in['replies']) && is_array($in)) ? $in['replies'] : null), $in, true, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'eachPost', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), $in, false, function($cx, $in)use($sp){return ' <!-- eachPost nested replies -->
'.$sp.' '.LCRun3::ch($cx, 'post', array(array(((isset($cx['sp_vars']['root']['rootBlock']) && is_array($cx['sp_vars']['root'])) ? $cx['sp_vars']['root']['rootBlock'] : null),$in),array()), 'encq').'
'.$sp.'';}).'';}).''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['postId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['action']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['action'] : null),'===','reply'),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_reply_form', array(array($in),array()), ' ').'';}).'';}).'</div>
-';},),
+';},'flow_post_partial' => function ($cx, $in, $sp) {return ''.$sp.''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in)use($sp){return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' class="flow-post'.((LCRun3::ifvar($cx, ((isset($in['isMaxThreadingDepth']) && is_array($in)) ? $in['isMaxThreadingDepth'] : null))) ? ' flow-post-max-depth' : '').'"
+'.$sp.' data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
+'.$sp.' >
+'.$sp.''.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['showPostId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['showPostId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}, function($cx, $in)use($sp){return ' <div class="flow-post-main flow-post-moderated">
+'.$sp.' <span class="flow-moderated-post-content">
+'.$sp.''.LCRun3::p($cx, 'flow_post_moderation_state', array(array($in),array()), ' ').' </span>
+'.$sp.' </div>
+'.$sp.'';}).'' : ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['action']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['action'] : null),'===','edit-post'),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['postId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_edit_post', array(array($in),array()), ' ').'';}, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}).'';}, function($cx, $in)use($sp){return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}).'').'
+'.$sp.''.LCRun3::p($cx, 'flow_post_replies', array(array($in),array()), ' ').' </div>
+'.$sp.'';}).'';},),
'scopes' => array(),
'sp_vars' => array('root' => $in),
'lcrun' => 'LCRun3',
);
- return ''.LCRun3::wi($cx, ((isset($in['revision']) && is_array($in)) ? $in['revision'] : null), $in, function($cx, $in) {return ' <div id="flow-post-'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
- class="flow-post'.((LCRun3::ifvar($cx, ((isset($in['isMaxThreadingDepth']) && is_array($in)) ? $in['isMaxThreadingDepth'] : null))) ? ' flow-post-max-depth' : '').'"
- data-flow-id="'.htmlentities((string)((isset($in['postId']) && is_array($in)) ? $in['postId'] : null), ENT_QUOTES, 'UTF-8').'"
- >
-'.((LCRun3::ifvar($cx, ((isset($in['isModerated']) && is_array($in)) ? $in['isModerated'] : null))) ? ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['showPostId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['showPostId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}, function($cx, $in) {return ' <div class="flow-post-main flow-post-moderated">
- <span class="flow-moderated-post-content">
-'.LCRun3::p($cx, 'flow_post_moderation_state', array(array($in),array()), ' ').' </span>
- </div>
-';}).'' : ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['action']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['action'] : null),'===','edit-post'),array()), $in, false, function($cx, $in) {return ''.LCRun3::hbch($cx, 'ifCond', array(array(((isset($cx['sp_vars']['root']['rootBlock']['submitted']['postId']) && is_array($cx['sp_vars']['root']['rootBlock']['submitted'])) ? $cx['sp_vars']['root']['rootBlock']['submitted']['postId'] : null),'===',((isset($in['postId']) && is_array($in)) ? $in['postId'] : null)),array()), $in, false, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_edit_post', array(array($in),array()), ' ').'';}, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}).'';}, function($cx, $in) {return ''.LCRun3::p($cx, 'flow_post_inner', array(array($in),array()), ' ').'';}).'').'
-'.LCRun3::p($cx, 'flow_post_replies', array(array($in),array()), ' ').' </div>
-';}).'';
+ return ''.LCRun3::p($cx, 'flow_post_partial', array(array($in),array())).'';
}
?> \ No newline at end of file
diff --git a/Flow/handlebars/compiled/flow_revision_diff_header.handlebars.php b/Flow/handlebars/compiled/flow_revision_diff_header.handlebars.php
index 79313240..21bc1821 100644
--- a/Flow/handlebars/compiled/flow_revision_diff_header.handlebars.php
+++ b/Flow/handlebars/compiled/flow_revision_diff_header.handlebars.php
@@ -18,7 +18,7 @@
'blockhelpers' => array(),
'hbhelpers' => array(),
'partials' => array('flow_patrol_diff' => function ($cx, $in, $sp) {return ''.$sp.''.((LCRun3::ifvar($cx, ((isset($in['revision']['rev_view_links']['markPatrolled']) && is_array($in['revision']['rev_view_links'])) ? $in['revision']['rev_view_links']['markPatrolled'] : null))) ? '<div>
-'.$sp.' <span class="patrollink">
+'.$sp.' <span class="patrollink" data-mw="interface">
'.$sp.' [<a class="mw-ui-quiet"
'.$sp.' href="'.htmlentities((string)((isset($in['revision']['rev_view_links']['markPatrolled']['url']) && is_array($in['revision']['rev_view_links']['markPatrolled'])) ? $in['revision']['rev_view_links']['markPatrolled']['url'] : null), ENT_QUOTES, 'UTF-8').'"
'.$sp.' title="'.LCRun3::ch($cx, 'l10n', array(array('flow-mark-diff-patrolled-link-title'),array()), 'encq').'"
diff --git a/Flow/handlebars/flow_block_header.handlebars b/Flow/handlebars/flow_block_header.handlebars
index 5dd11cb6..337a8631 100644
--- a/Flow/handlebars/flow_block_header.handlebars
+++ b/Flow/handlebars/flow_block_header.handlebars
@@ -1,10 +1,8 @@
<div class="flow-board-header flow-load-interactive" data-flow-load-handler="loadSideRail">
{{> flow_header_title}}
+ {{> flow_header_edit_restrictions}}
{{> flow_errors}}
- {{#if oldSystem}}
- {{> flow_header_detail_oldsystem}}
- {{else}}
- {{> flow_header_detail}}
- {{/if}}
+ {{> flow_header_detail}}
+ {{> flow_header_categories}}
{{> flow_header_footer}}
</div>
diff --git a/Flow/handlebars/flow_block_header_edit.handlebars b/Flow/handlebars/flow_block_header_edit.handlebars
index 0df8655c..ac11e7bc 100644
--- a/Flow/handlebars/flow_block_header_edit.handlebars
+++ b/Flow/handlebars/flow_block_header_edit.handlebars
@@ -24,9 +24,7 @@
<div class="flow-form-actions flow-form-collapsible">
<button data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="submitHeader">
+ class="mw-ui-button mw-ui-progressive">
{{~l10n "flow-edit-header-submit"~}}
</button>
{{> flow_form_cancel_button }}
@@ -34,4 +32,4 @@
</div>
</form>
</div>
-</div> \ No newline at end of file
+</div>
diff --git a/Flow/handlebars/flow_block_header_undo_edit.handlebars b/Flow/handlebars/flow_block_header_undo_edit.handlebars
index 6ecdbaa2..84fb6206 100644
--- a/Flow/handlebars/flow_block_header_undo_edit.handlebars
+++ b/Flow/handlebars/flow_block_header_undo_edit.handlebars
@@ -30,7 +30,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">
+ <button class="mw-ui-button mw-ui-progressive">
{{~l10n "flow-edit-header-submit"~}}
</button>
<small class="flow-terms-of-use plainlinks">
diff --git a/Flow/handlebars/flow_block_topic_diff_view.handlebars b/Flow/handlebars/flow_block_topic_diff_view.handlebars
index cd98045d..208827e9 100644
--- a/Flow/handlebars/flow_block_topic_diff_view.handlebars
+++ b/Flow/handlebars/flow_block_topic_diff_view.handlebars
@@ -2,7 +2,7 @@
<div class="flow-compare-revisions-header plainlinks">
{{l10nParse "flow-compare-revisions-header-post"
revision.new.rev_view_links.board.title
- revision.new.properties.topic-of-post.
+ revision.new.properties.topic-of-post-text-from-html
revision.new.author.name
revision.new.rev_view_links.board.url
revision.new.rev_view_links.root.url
diff --git a/Flow/handlebars/flow_block_topic_moderate_post.handlebars b/Flow/handlebars/flow_block_topic_moderate_post.handlebars
index 0d63436b..5be2555c 100644
--- a/Flow/handlebars/flow_block_topic_moderate_post.handlebars
+++ b/Flow/handlebars/flow_block_topic_moderate_post.handlebars
@@ -1,9 +1,7 @@
<div class="flow-board">
{{!-- There is only one post, but the output format matches multi-post output --}}
- {{#each roots}}
- {{#eachPost @root this}}
- {{> flow_moderate_post}}
- {{> flow_post}}
- {{/eachPost}}
- {{/each}}
+ {{#eachPost @root @root.submitted.postId }}
+ {{> flow_moderate_post}}
+ {{> flow_post_partial}}
+ {{/eachPost}}
</div>
diff --git a/Flow/handlebars/flow_block_topic_moderate_topic.handlebars b/Flow/handlebars/flow_block_topic_moderate_topic.handlebars
index 687e3d52..e2ebfc15 100644
--- a/Flow/handlebars/flow_block_topic_moderate_topic.handlebars
+++ b/Flow/handlebars/flow_block_topic_moderate_topic.handlebars
@@ -3,7 +3,7 @@
{{#each roots}}
{{#eachPost @root this}}
{{> flow_moderate_topic}}
- {{> flow_post}}
+ {{> flow_post_partial}}
{{/eachPost}}
{{/each}}
</div>
diff --git a/Flow/handlebars/flow_block_topic_undo_edit.handlebars b/Flow/handlebars/flow_block_topic_undo_edit.handlebars
index 804f349c..91cc9bfe 100644
--- a/Flow/handlebars/flow_block_topic_undo_edit.handlebars
+++ b/Flow/handlebars/flow_block_topic_undo_edit.handlebars
@@ -31,7 +31,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">
+ <button class="mw-ui-button mw-ui-progressive">
{{~l10n "flow-edit-post-submit"~}}
</button>
<small class="flow-terms-of-use plainlinks">
diff --git a/Flow/handlebars/flow_block_topicsummary_edit.handlebars b/Flow/handlebars/flow_block_topicsummary_edit.handlebars
index e431a085..66d3aba0 100644
--- a/Flow/handlebars/flow_block_topicsummary_edit.handlebars
+++ b/Flow/handlebars/flow_block_topicsummary_edit.handlebars
@@ -28,9 +28,7 @@
<div class="flow-form-actions flow-form-collapsible">
<button
data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="summarizeTopic"
+ class="mw-ui-button mw-ui-progressive"
data-flow-api-target="< .flow-topic-summary-container">
{{l10n "flow-topic-action-update-topic-summary"}}
</button>
diff --git a/Flow/handlebars/flow_block_topicsummary_single_view.handlebars b/Flow/handlebars/flow_block_topicsummary_single_view.handlebars
index e8afa85c..53a5aacb 100644
--- a/Flow/handlebars/flow_block_topicsummary_single_view.handlebars
+++ b/Flow/handlebars/flow_block_topicsummary_single_view.handlebars
@@ -22,5 +22,7 @@
<div class="flow-revision-content">
{{escapeContent revision.content.format revision.content.content}}
</div>
+
+ {{> flow_patrol_action}}
{{/if}}
</div>
diff --git a/Flow/handlebars/flow_block_topicsummary_undo_edit.handlebars b/Flow/handlebars/flow_block_topicsummary_undo_edit.handlebars
index 03794f82..79ffad93 100644
--- a/Flow/handlebars/flow_block_topicsummary_undo_edit.handlebars
+++ b/Flow/handlebars/flow_block_topicsummary_undo_edit.handlebars
@@ -33,7 +33,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive">
+ <button class="mw-ui-button mw-ui-progressive">
{{~l10n "flow-topic-action-summarize-topic"~}}
</button>
<small class="flow-terms-of-use plainlinks">
diff --git a/Flow/handlebars/flow_board_navigation.partial.handlebars b/Flow/handlebars/flow_board_navigation.partial.handlebars
index 47b1de2e..ac407447 100644
--- a/Flow/handlebars/flow_board_navigation.partial.handlebars
+++ b/Flow/handlebars/flow_board_navigation.partial.handlebars
@@ -1,4 +1,4 @@
-
+{{#if links.board-sort}}
<div class="flow-board-navigation" data-flow-load-handler="boardNavigation">
<div class="flow-error-container">
{{!-- placeholder for javascript injected errors --}}
@@ -7,3 +7,4 @@
widget in PHP because the board navigation doesn't work in noJS mode
as it is. --}}
</div>
+{{/if}}
diff --git a/Flow/handlebars/flow_edit_post.partial.handlebars b/Flow/handlebars/flow_edit_post.partial.handlebars
index 60b6683b..bb6d42aa 100644
--- a/Flow/handlebars/flow_edit_post.partial.handlebars
+++ b/Flow/handlebars/flow_edit_post.partial.handlebars
@@ -20,7 +20,7 @@
</div>
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive"
+ <button class="mw-ui-button mw-ui-progressive"
data-flow-api-handler="submitEditPost">
{{~l10n "flow-post-action-edit-post-submit"~}}
</button>
diff --git a/Flow/handlebars/flow_edit_topic_title.partial.handlebars b/Flow/handlebars/flow_edit_topic_title.partial.handlebars
index 836501ee..6ba59611 100644
--- a/Flow/handlebars/flow_edit_topic_title.partial.handlebars
+++ b/Flow/handlebars/flow_edit_topic_title.partial.handlebars
@@ -12,16 +12,6 @@
" />
<div class="flow-form-actions">
<button data-role="submit"
- data-flow-api-handler="submitTopicTitle"
- data-flow-api-target="< .flow-topic"
- class="mw-ui-button mw-ui-constructive">{{l10n "flow-edit-title-submit"}}</button>
-
- {{#progressiveEnhancement}}
- <button data-role="cancel"
- type="reset"
- data-flow-interactive-handler="cancelForm"
- class="mw-ui-button mw-ui-destructive mw-ui-quiet">{{l10n "flow-cancel"}}</button>
- <small class="flow-terms-of-use plainlinks">{{l10nParse "flow-terms-of-use-edit"}}</small>
- {{/progressiveEnhancement}}
+ class="mw-ui-button mw-ui-progressive">{{l10n "flow-edit-title-submit"}}</button>
</div>
</form>
diff --git a/Flow/handlebars/flow_header_categories.partial.handlebars b/Flow/handlebars/flow_header_categories.partial.handlebars
new file mode 100644
index 00000000..9f66373f
--- /dev/null
+++ b/Flow/handlebars/flow_header_categories.partial.handlebars
@@ -0,0 +1,12 @@
+{{#if @root.categories.items}}
+<div id="catlinks" class="catlinks flow-board-header-category-view-nojs">
+ <div id="mw-normal-catlinks" class="mw-normal-catlinks">
+ {{~html @root.categories.link~}}
+ <ul class="flow-board-header-category-list">
+ {{~#each @root.categories.items~}}
+ <li class="flow-board-header-category-item">{{~html this~}}</li>
+ {{~/each~}}
+ </ul>
+ </div>
+</div>
+{{/if}}
diff --git a/Flow/handlebars/flow_header_detail.partial.handlebars b/Flow/handlebars/flow_header_detail.partial.handlebars
index 0dedce47..230c69dc 100644
--- a/Flow/handlebars/flow_header_detail.partial.handlebars
+++ b/Flow/handlebars/flow_header_detail.partial.handlebars
@@ -1,9 +1,7 @@
{{{ oouify
- revision.content.format
revision.content.content
revision.actions.edit.url
revision.actions.edit.title
- label=flow-edit-header-link
type="BoardDescriptionWidget"
name="flow-board-description"
}}}
diff --git a/Flow/handlebars/flow_header_edit_restrictions.partial.handlebars b/Flow/handlebars/flow_header_edit_restrictions.partial.handlebars
new file mode 100644
index 00000000..9488e2f1
--- /dev/null
+++ b/Flow/handlebars/flow_header_edit_restrictions.partial.handlebars
@@ -0,0 +1,11 @@
+{{#unless revision.actions.edit}}
+ <p class="flow-board-header-restricted">
+ {{{ oouify
+ 'lock'
+ type="IconWidget"
+ classes="flow-board-header-restricted-icon"
+ }}}
+
+ <span class="flow-board-header-restricted-label">{{l10n "flow-board-description-can-not-edit"}}</span>
+ </p>
+{{/unless}}
diff --git a/Flow/handlebars/flow_load_more.partial.handlebars b/Flow/handlebars/flow_load_more.partial.handlebars
index cbb0ab07..fc5976c1 100644
--- a/Flow/handlebars/flow_load_more.partial.handlebars
+++ b/Flow/handlebars/flow_load_more.partial.handlebars
@@ -22,4 +22,5 @@
{{!-- TODO: Does this i18n message need to be generalized? --}}
{{l10n "flow-no-more-fwd"}}
</div>
+ <div class="flow-bottom-spacer"></div>
{{/if}}
diff --git a/Flow/handlebars/flow_moderate_post.partial.handlebars b/Flow/handlebars/flow_moderate_post.partial.handlebars
index fb106ec6..54d69395 100644
--- a/Flow/handlebars/flow_moderate_post.partial.handlebars
+++ b/Flow/handlebars/flow_moderate_post.partial.handlebars
@@ -1,22 +1,23 @@
<form method="POST" action="{{moderationAction actions @root.submitted.moderationState}}">
{{> flow_errors}}
<input type="hidden" name="wpEditToken" value="{{@root.editToken}}" />
- <textarea name="topic_reason"
+ <input name="topic_reason"
+ type="text"
+ size="45"
required
data-flow-expandable="true"
class="mw-ui-input"
data-role="content"
placeholder="{{l10n (concat "flow-moderation-placeholder-" @root.submitted.moderationState "-post")}}"
autofocus
- >
- {{~#if @root.submitted.reason~}}
- {{~@root.submitted.reason~}}
- {{~/if~}}
- </textarea>
+ {{~#if @root.submitted.reason~}}
+ value="{{~@root.submitted.reason~}}"
+ {{~/if~}}
+ >
<div class="flow-form-actions flow-form-collapsible">
<button data-flow-interactive-handler="apiRequest"
data-flow-api-handler="moderatePost"
- class="mw-ui-button mw-ui-constructive"
+ class="mw-ui-button mw-ui-progressive"
data-role="submit">
{{~l10n (concat "flow-moderation-confirm-" @root.submitted.moderationState "-post")~}}
</button>
diff --git a/Flow/handlebars/flow_moderate_topic.partial.handlebars b/Flow/handlebars/flow_moderate_topic.partial.handlebars
index 493b18ab..38a0c750 100644
--- a/Flow/handlebars/flow_moderate_topic.partial.handlebars
+++ b/Flow/handlebars/flow_moderate_topic.partial.handlebars
@@ -1,20 +1,21 @@
<form method="POST" action="{{moderationAction actions @root.submitted.moderationState}}">
{{> flow_errors}}
<input type="hidden" name="wpEditToken" value="{{@root.editToken}}" />
- <textarea name="topic_reason"
+ <input name="topic_reason"
+ type="text"
+ size="45"
required
data-flow-expandable="true"
class="mw-ui-input"
data-role="content"
placeholder="{{l10n (concat "flow-moderation-placeholder-" @root.submitted.moderationState "-topic")}}"
autofocus
- >
- {{~#if @root.submitted.reason~}}
- {{~@root.submitted.reason~}}
- {{~/if~}}
- </textarea>
+ {{~#if @root.submitted.reason~}}
+ value="{{~@root.submitted.reason~}}"
+ {{~/if~}}
+ >
<div class="flow-form-actions flow-form-collapsible">
- <button class="mw-ui-button mw-ui-constructive"
+ <button class="mw-ui-button mw-ui-progressive"
data-flow-interactive-handler="apiRequest"
data-flow-api-handler="moderateTopic"
data-role="submit">
diff --git a/Flow/handlebars/flow_moderation_actions_list.partial.handlebars b/Flow/handlebars/flow_moderation_actions_list.partial.handlebars
index 5b392b5d..19f905d9 100644
--- a/Flow/handlebars/flow_moderation_actions_list.partial.handlebars
+++ b/Flow/handlebars/flow_moderation_actions_list.partial.handlebars
@@ -2,15 +2,10 @@
{{~#ifCond moderationType "===" "topic"~}}
{{!-- Topic only --}}
{{~#if actions.edit~}}
- <li class="flow-js">
+ <li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- href="{{actions.edit.url}}"
- title="{{actions.edit.title}}"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="activateEditTitle"
- data-flow-api-target="< .flow-topic-titlebar"
- >
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-title-link"
+ href="{{actions.edit.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> {{/if~}}
{{~l10n (concat "flow-topic-action-edit-title")~}}
</a>
@@ -21,8 +16,7 @@
<li>
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-quiet"
- href="{{links.topic-history.url}}"
- title="{{links.topic-history.title}}">
+ href="{{links.topic-history.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-clock"></span> {{/if~}}
{{~l10n (concat "flow-topic-action-history")~}}
</a>
@@ -33,8 +27,7 @@
<li>
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-quiet"
- href="{{links.topic.url}}"
- title="{{links.topic.title}}">
+ href="{{links.topic.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> {{/if~}}
{{~l10n (concat "flow-topic-action-view")~}}
</a>
@@ -44,12 +37,8 @@
{{~#if actions.summarize~}}
<li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="activateSummarizeTopic"
- data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
- href="{{actions.summarize.url}}"
- title="{{actions.summarize.title}}">
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-summarize-topic-link"
+ href="{{actions.summarize.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-stripeToC mw-ui-icon-stripeToC-progressive-hover"></span> {{/if~}}
{{~#if summary.revision.content.content~}}
{{~l10n (concat "flow-topic-action-resummarize-topic")~}}
@@ -68,14 +57,10 @@
{{~#if actions.lock~}}
<li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="lockTopic"
- data-flow-api-method="POST"
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
data-role="lock"
data-flow-id="{{postId}}"
- href="{{actions.lock.url}}"
- title="{{actions.lock.title}}">
+ href="{{actions.lock.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-lock-topic")~}}
</a>
@@ -85,14 +70,10 @@
{{~#if actions.unlock~}}
<li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="lockTopic"
- data-flow-api-method="POST"
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
data-role="unlock"
data-flow-id="{{postId}}"
- href="{{actions.unlock.url}}"
- title="{{actions.unlock.title}}">
+ href="{{actions.unlock.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-unlock-topic")~}}
</a>
@@ -104,14 +85,10 @@
{{~#if actions.lock~}}
<li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="lockAndSummarizeTopic"
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
data-flow-id="{{postId}}"
- data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
- data-flow-api-method="POST"
- href="{{actions.lock.url}}"
- title="{{actions.lock.title}}">
+ data-role="lock"
+ href="{{actions.lock.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check mw-ui-icon-check-progressive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-lock-topic")~}}
</a>
@@ -121,14 +98,10 @@
{{~#if actions.unlock~}}
<li>
{{~noop~}}
- <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="lockAndSummarizeTopic"
+ <a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-topicmenu-lock"
data-flow-id="{{postId}}"
- data-flow-api-target="< .flow-topic-titlebar .flow-topic-summary-container"
- data-flow-api-method="POST"
- href="{{actions.unlock.url}}"
- title="{{actions.unlock.title}}">
+ data-role="unlock"
+ href="{{actions.unlock.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ongoingConversation mw-ui-icon-ongoingConversation-progressive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-unlock-topic")~}}
</a>
@@ -143,7 +116,6 @@
<li>
<a class="{{moderationMwUiClass}} mw-ui-progressive mw-ui-quiet mw-ui-hovericon flow-ui-edit-post-link"
href="{{actions.edit.url}}"
- title="{{actions.edit.title}}"
>
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-edit mw-ui-icon-edit-progressive-hover"></span> {{/if~}}
{{~l10n "flow-post-action-edit-post"~}}
@@ -154,8 +126,7 @@
<li>
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-quiet"
- href="{{links.post.url}}"
- title="{{links.post.title}}">
+ href="{{links.post.url}}">
{{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-link"></span> {{/if~}}
{{~l10n (concat "flow-post-action-view")~}}
</a>
@@ -185,7 +156,6 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-quiet"
href="{{actions.hide.url}}"
- title="{{actions.hide.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="hide">
@@ -200,7 +170,6 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-quiet"
href="{{actions.unhide.url}}"
- title="{{actions.unhide.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="unhide">
@@ -215,11 +184,10 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
href="{{actions.delete.url}}"
- title="{{actions.delete.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="delete">
- {{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> {{/if~}}
+ {{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-delete-" moderationTemplate)~}}
</a>
{{~noop~}}
@@ -230,11 +198,10 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
href="{{actions.undelete.url}}"
- title="{{actions.undelete.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="undelete">
- {{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-remove mw-ui-icon-remove-destructive-hover"></span> {{/if~}}
+ {{~#if moderationIcons}}<span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-trash mw-ui-icon-trash-destructive-hover"></span> {{/if~}}
{{~l10n (concat "flow-" moderationType "-action-undelete-" moderationTemplate)~}}
</a>
{{~noop~}}
@@ -245,7 +212,6 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
href="{{actions.suppress.url}}"
- title="{{actions.suppress.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="suppress">
@@ -260,7 +226,6 @@
{{~noop~}}
<a class="{{moderationMwUiClass}} mw-ui-destructive mw-ui-quiet mw-ui-hovericon"
href="{{actions.unsuppress.url}}"
- title="{{actions.unsuppress.title}}"
data-flow-interactive-handler="moderationDialog"
data-flow-template="flow_moderate_{{moderationTemplate}}.partial"
data-role="unsuppress">
@@ -270,5 +235,4 @@
{{~noop~}}
</li>
{{~/if~}}
-
</section>
diff --git a/Flow/handlebars/flow_newtopic_form.partial.handlebars b/Flow/handlebars/flow_newtopic_form.partial.handlebars
index 08d9b08b..cd3b3e5c 100644
--- a/Flow/handlebars/flow_newtopic_form.partial.handlebars
+++ b/Flow/handlebars/flow_newtopic_form.partial.handlebars
@@ -14,18 +14,10 @@
type="text"
placeholder="{{l10n "flow-newtopic-start-placeholder"}}"
data-role="title"
-
- {{!--
- You'd expect data-flow-eventlog-* data here (this one
- needs to be clicked to expand the form). That stuff will be
- in JS though, since we only want it on initial focus (activating
- the form)
- --}}
- data-flow-interactive-handler-focus="activateNewTopic"
/>
<div class="flow-editor">
<textarea name="topiclist_content"
- class="mw-ui-input flow-form-collapsible mw-ui-input-large{{#if isOnFlowBoard}} flow-form-collapsible-collapsed{{/if}}"
+ class="mw-ui-input flow-form-collapsible{{#if isOnFlowBoard}} flow-form-collapsible-collapsed{{/if}}"
placeholder="{{l10n "flow-newtopic-content-placeholder" @root.title}}"
data-role="content"
required
@@ -35,10 +27,8 @@
</div>
<div class="flow-form-actions flow-form-collapsible{{#if isOnFlowBoard}} flow-form-collapsible-collapsed{{/if}}">
- <button data-role="submit" data-flow-api-handler="newTopic"
- data-flow-interactive-handler="apiRequest"
- data-flow-eventlog-action="save-attempt"
- class="mw-ui-button mw-ui-constructive mw-ui-flush-right">{{l10n "flow-newtopic-save"}}</button>
+ <button data-role="submit"
+ class="mw-ui-button mw-ui-progressive mw-ui-flush-right">{{l10n "flow-newtopic-save"}}</button>
{{> flow_form_cancel_button }}
<small class="flow-terms-of-use plainlinks">{{l10nParse "flow-terms-of-use-new-topic"}}</small>
</div>
diff --git a/Flow/handlebars/flow_patrol_action.partial.handlebars b/Flow/handlebars/flow_patrol_action.partial.handlebars
index 6c3a0e3a..74b55c4c 100644
--- a/Flow/handlebars/flow_patrol_action.partial.handlebars
+++ b/Flow/handlebars/flow_patrol_action.partial.handlebars
@@ -1,5 +1,5 @@
{{~#if revision.rev_view_links.markPatrolled~}}
- <div class="patrollink">
+ <div class="patrollink" data-mw="interface">
[<a class="mw-ui-quiet"
href="{{revision.rev_view_links.markPatrolled.url}}"
title="{{l10n 'flow-mark-revision-patrolled-link-title'}}"
diff --git a/Flow/handlebars/flow_patrol_diff.partial.handlebars b/Flow/handlebars/flow_patrol_diff.partial.handlebars
index 7cfc72a2..0789bc05 100644
--- a/Flow/handlebars/flow_patrol_diff.partial.handlebars
+++ b/Flow/handlebars/flow_patrol_diff.partial.handlebars
@@ -1,6 +1,6 @@
{{~#if revision.rev_view_links.markPatrolled~}}
<div>
- <span class="patrollink">
+ <span class="patrollink" data-mw="interface">
[<a class="mw-ui-quiet"
href="{{revision.rev_view_links.markPatrolled.url}}"
title="{{l10n 'flow-mark-diff-patrolled-link-title'}}"
diff --git a/Flow/handlebars/flow_post.handlebars b/Flow/handlebars/flow_post.handlebars
index 7306d1f9..e5832dc4 120000..100644
--- a/Flow/handlebars/flow_post.handlebars
+++ b/Flow/handlebars/flow_post.handlebars
@@ -1 +1,3 @@
-flow_post.partial.handlebars \ No newline at end of file
+{{!-- We used to use a symbolic link for this, but it was breaking for
+Windows and ExtensionDistributor users. --}}
+{{> flow_post_partial}}
diff --git a/Flow/handlebars/flow_post_author.partial.handlebars b/Flow/handlebars/flow_post_author.partial.handlebars
index 4521bb4c..53562a93 100644
--- a/Flow/handlebars/flow_post_author.partial.handlebars
+++ b/Flow/handlebars/flow_post_author.partial.handlebars
@@ -6,7 +6,7 @@
class="{{#unless links.userpage.exists}}new {{/unless}}mw-userlink">
{{/if}}
{{~#if name~}}
- {{~name~}}
+ <bdi>{{~name~}}</bdi>
{{~else~}}
{{~l10n "flow-anonymous"}}
{{~/if~}}
diff --git a/Flow/handlebars/flow_post_inner.partial.handlebars b/Flow/handlebars/flow_post_inner.partial.handlebars
index 6592c451..8722cd01 100644
--- a/Flow/handlebars/flow_post_inner.partial.handlebars
+++ b/Flow/handlebars/flow_post_inner.partial.handlebars
@@ -11,7 +11,7 @@
</div>
{{/if}}
- <div class="flow-post-content">
+ <div class="flow-post-content mw-parser-output">
{{escapeContent content.format content.content}}
</div>
diff --git a/Flow/handlebars/flow_post_meta_actions.partial.handlebars b/Flow/handlebars/flow_post_meta_actions.partial.handlebars
index 22435d7c..4a91016d 100644
--- a/Flow/handlebars/flow_post_meta_actions.partial.handlebars
+++ b/Flow/handlebars/flow_post_meta_actions.partial.handlebars
@@ -3,9 +3,7 @@
{{#if actions.reply}}
<a href="{{actions.reply.url}}"
title="{{actions.reply.title}}"
- class="mw-ui-anchor mw-ui-progressive mw-ui-quiet"
- data-flow-interactive-handler="activateReplyPost"
-
+ class="mw-ui-anchor mw-ui-progressive mw-ui-quiet flow-reply-link"
{{!--
Initialize EventLogging:
* action: name of the action param
@@ -36,7 +34,7 @@
progressive enhancement happens in the Thank extension
based on the mw-thanks-flow-thank-link class
--}}
- <a class="mw-ui-anchor mw-ui-constructive mw-ui-quiet mw-thanks-flow-thank-link"
+ <a class="mw-ui-anchor mw-ui-progressive mw-ui-quiet mw-thanks-flow-thank-link"
href="{{actions.thank.url}}"
title="{{actions.thank.title}}">
{{~actions.thank.text~}}
diff --git a/Flow/handlebars/flow_post_partial.partial.handlebars b/Flow/handlebars/flow_post_partial.partial.handlebars
new file mode 100644
index 00000000..df9613bb
--- /dev/null
+++ b/Flow/handlebars/flow_post_partial.partial.handlebars
@@ -0,0 +1,31 @@
+{{#with revision}}
+ <div id="flow-post-{{postId}}"
+ class="flow-post{{#if isMaxThreadingDepth}} flow-post-max-depth{{/if}}"
+ data-flow-id="{{postId}}"
+ >
+ {{#if isModerated}}
+ {{!-- TODO: T133133: This should show all posts newer than showPostId, for bundling --}}
+ {{#ifCond @root.rootBlock.submitted.showPostId "===" postId}}
+ {{> flow_post_inner}}
+ {{else}}
+ <div class="flow-post-main flow-post-moderated">
+ <span class="flow-moderated-post-content">
+ {{> flow_post_moderation_state}}
+ </span>
+ </div>
+ {{/ifCond}}
+ {{else}}
+ {{#ifCond @root.rootBlock.submitted.action "===" "edit-post"}}
+ {{#ifCond @root.rootBlock.submitted.postId "===" postId}}
+ {{> flow_edit_post}}
+ {{else}}
+ {{> flow_post_inner}}
+ {{/ifCond}}
+ {{else}}
+ {{> flow_post_inner}}
+ {{/ifCond}}
+ {{/if}}
+
+ {{> flow_post_replies}}
+ </div>
+{{/with}}
diff --git a/Flow/handlebars/flow_reply_form.partial.handlebars b/Flow/handlebars/flow_reply_form.partial.handlebars
index 618f3e46..a66ec3a2 100644
--- a/Flow/handlebars/flow_reply_form.partial.handlebars
+++ b/Flow/handlebars/flow_reply_form.partial.handlebars
@@ -1,61 +1,56 @@
-{{#if actions.reply}}
- <form class="flow-post flow-reply-form"
- method="POST"
- action="{{actions.reply.url}}"
- id="flow-reply-{{postId}}"
- data-flow-initial-state="collapsed"
- >
- <input type="hidden" name="wpEditToken" value="{{@root.rootBlock.editToken}}" />
- <input type="hidden" name="topic_replyTo" value="{{postId}}" />
- {{> flow_errors }}
+{{#unless actions.unlock}}{{!-- HACK: T135848 --}}
+<form class="flow-post flow-reply-form"
+ method="POST"
+ action="{{actions.reply.url}}"
+ id="flow-reply-{{postId}}"
+ data-flow-initial-state="collapsed"
+>
+ <input type="hidden" name="wpEditToken" value="{{@root.rootBlock.editToken}}" />
+ <input type="hidden" name="topic_replyTo" value="{{postId}}" />
+ {{> flow_errors }}
- {{#ifAnonymous}}
- {{> flow_anon_warning }}
- {{/ifAnonymous}}
+ {{#ifAnonymous}}
+ {{> flow_anon_warning }}
+ {{/ifAnonymous}}
- <div class="flow-editor">
- <textarea id="flow-post-{{postId}}-form-content"
- name="topic_content"
- required
- data-flow-expandable="true"
- class="mw-ui-input flow-click-interactive"
- type="text"
- placeholder="{{l10n "flow-reply-topic-title-placeholder" properties.topic-of-post}}"
- data-role="content"
+ <div class="flow-editor">
+ <textarea id="flow-post-{{postId}}-form-content"
+ name="topic_content"
+ required
+ data-flow-expandable="true"
+ class="mw-ui-input flow-click-interactive"
+ type="text"
+ placeholder="{{l10n "flow-reply-topic-title-placeholder" properties.topic-of-post-text-from-html}}"
+ data-role="content"
- {{!--
- You'd expect data-flow-eventlog-* data here (this one
- needs to be clicked to expand the form).
- However, this form is used in multiple places: as topic-
- level reply form (activated by clicking the textarea to
- expand), or to reply to a post (activated by clicking the
- "reply" link).
- We only want to track the former, so we'll do that in JS so
- we can ignore all focuses for this textarea when it's not
- used to activate the topic-level reply form.
- --}}
- data-flow-interactive-handler-focus="activateReplyTopic"
- >
- {{~#if @root.submitted~}}
- {{~#ifCond @root.submitted.postId "===" postId~}}
- {{~@root.submitted.content~}}
- {{~/ifCond~}}
- {{~/if~}}
- </textarea>
- </div>
+ {{!--
+ You'd expect data-flow-eventlog-* data here (this one
+ needs to be clicked to expand the form).
+ However, this form is used in multiple places: as topic-
+ level reply form (activated by clicking the textarea to
+ expand), or to reply to a post (activated by clicking the
+ "reply" link).
+ We only want to track the former, so we'll do that in JS so
+ we can ignore all focuses for this textarea when it's not
+ used to activate the topic-level reply form.
+ --}}
+ >
+ {{~#if @root.submitted~}}
+ {{~#ifCond @root.submitted.postId "===" postId~}}
+ {{~@root.submitted.content~}}
+ {{~/ifCond~}}
+ {{~/if~}}
+ </textarea>
+ </div>
- <div class="flow-form-actions flow-form-collapsible">
- <button data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-handler="submitReply"
- data-flow-api-target="< .flow-topic"
- data-flow-eventlog-action="save-attempt"
- >
- {{~actions.reply.text~}}
- </button>
- {{> flow_form_cancel_button }}
- <small class="flow-terms-of-use plainlinks">{{l10nParse "flow-terms-of-use-reply"}}</small>
- </div>
- </form>
-{{/if}}
+ <div class="flow-form-actions flow-form-collapsible">
+ <button data-role="submit"
+ class="mw-ui-button mw-ui-progressive"
+ >
+ {{~l10n "flow-reply-link"~}}
+ </button>
+ {{> flow_form_cancel_button }}
+ <small class="flow-terms-of-use plainlinks">{{l10nParse "flow-terms-of-use-reply"}}</small>
+ </div>
+</form>
+{{/unless}} \ No newline at end of file
diff --git a/Flow/handlebars/flow_subscribed.partial.handlebars b/Flow/handlebars/flow_subscribed.partial.handlebars
index 26a59474..cacf4891 100644
--- a/Flow/handlebars/flow_subscribed.partial.handlebars
+++ b/Flow/handlebars/flow_subscribed.partial.handlebars
@@ -1,7 +1,9 @@
-<div class="flow-notification-tooltip-icon"><span class="mw-ui-icon mw-ui-icon-element mw-ui-icon-watchlist"></span></div>
+<div class="flow-notification-tooltip-icon"><span class="mw-ui-icon mw-ui-icon-element mw-ui-icon-unStar"></span></div>
<p class="flow-notification-tooltip-title">
- {{!-- flow-topic-notification-subscribe-title and flow-board-notification-subscribe-title --}}
- {{l10n (concat "flow-" type "-notification-subscribe-title") user }}
+ <strong>
+ {{!-- flow-topic-notification-subscribe-title and flow-board-notification-subscribe-title --}}
+ {{l10n (concat "flow-" type "-notification-subscribe-title") user }}
+ </strong>
</p>
<p class="flow-notification-tooltip-content">
{{!-- flow-topic-notification-subscribe-description and flow-board-notification-subscribe-description --}}
diff --git a/Flow/handlebars/flow_topic.partial.handlebars b/Flow/handlebars/flow_topic.partial.handlebars
index c5af0334..581b6983 100644
--- a/Flow/handlebars/flow_topic.partial.handlebars
+++ b/Flow/handlebars/flow_topic.partial.handlebars
@@ -31,8 +31,17 @@
title="{{actions.reply.title}}"
class="flow-ui-input-replacement-anchor mw-ui-input"
>
- {{~l10n "flow-reply-topic-title-placeholder" properties.topic-of-post~}}
+ {{~l10n "flow-reply-topic-title-placeholder" properties.topic-of-post-text-from-html~}}
</a>
{{/ifCond}}
+ {{else}}
+ {{!--
+ The user can not post. This form is rendered only for Initializer to replace
+ it. Both old and new forms will be hidden in no-JS mode. The
+ after-replacement JS version of the form displays as a disabled form.
+ --}}
+ {{#progressiveEnhancement type="insert"}}
+ {{> flow_reply_form}}
+ {{/progressiveEnhancement}}
{{/if}}
</div>
diff --git a/Flow/handlebars/flow_topic_moderation_flag.partial.handlebars b/Flow/handlebars/flow_topic_moderation_flag.partial.handlebars
index 8446fde9..122ff6bd 100644
--- a/Flow/handlebars/flow_topic_moderation_flag.partial.handlebars
+++ b/Flow/handlebars/flow_topic_moderation_flag.partial.handlebars
@@ -1,4 +1,4 @@
<span class="mw-ui-icon mw-ui-icon-before
{{~#ifCond moderateState "===" "lock"}} mw-ui-icon-check{{/ifCond~}}
{{~#ifCond moderateState "===" "hide"}} mw-ui-icon-flag{{/ifCond~}}
- {{~#ifCond moderateState "===" "delete"}} mw-ui-icon-remove{{/ifCond~}}"></span>
+ {{~#ifCond moderateState "===" "delete"}} mw-ui-icon-trash{{/ifCond~}}"></span>
diff --git a/Flow/handlebars/flow_topic_titlebar_content.partial.handlebars b/Flow/handlebars/flow_topic_titlebar_content.partial.handlebars
index f41f0228..c196418c 100644
--- a/Flow/handlebars/flow_topic_titlebar_content.partial.handlebars
+++ b/Flow/handlebars/flow_topic_titlebar_content.partial.handlebars
@@ -1,5 +1,5 @@
<div class="flow-topic-titlebar-container">
- <h2 class="flow-topic-title flow-load-interactive {{#if isLocked}}flow-click-interactive{{/if}}"
+ <h2 class="flow-topic-title flow-load-interactive {{#if isLocked}}flow-collapse-toggle flow-click-interactive{{/if}}"
data-flow-topic-title="{{content.content}}"
data-flow-load-handler="topicTitle"
{{#if isLocked}}
@@ -11,7 +11,7 @@
</h2>
<div class="flow-topic-meta">
{{#if isLocked~}}
- <a class="expand-collapse-posts-link flow-click-interactive"
+ <a class="expand-collapse-posts-link flow-collapse-toggle flow-click-interactive"
href="javascript:void(0);"
title="{{l10n "flow-show-comments-title" reply_count}}"
data-collapsed-title="{{l10n "flow-show-comments-title" reply_count}}"
diff --git a/Flow/handlebars/flow_topic_titlebar_lock.partial.handlebars b/Flow/handlebars/flow_topic_titlebar_lock.partial.handlebars
index f08ed7de..9eda3e7c 100644
--- a/Flow/handlebars/flow_topic_titlebar_lock.partial.handlebars
+++ b/Flow/handlebars/flow_topic_titlebar_lock.partial.handlebars
@@ -1,43 +1,42 @@
-<div class="flow-topic-summary-container">
- <div class="flow-topic-summary">
- <form class="flow-edit-form" data-flow-initial-state="collapsed" method="POST"
- action="
+<div class="flow-board">
+ <div class="flow-topic-summary-container">
+ <div class="flow-topic-summary">
+ <form class="flow-edit-form" data-flow-initial-state="expanded" method="POST"
+ action="
+ {{~#if isLocked~}}
+ {{~actions.unlock.url~}}
+ {{~else~}}
+ {{~actions.lock.url~}}
+ {{~/if~}}">
+ {{> flow_errors }}
+ <input type="hidden" name="wpEditToken" value="{{@root.editToken}}" />
+ <input type="hidden" name="flow_reason" value="
{{~#if isLocked~}}
- {{~actions.unlock.url~}}
+ {{~l10n "flow-rev-message-restore-topic-reason"~}}
{{~else~}}
- {{~actions.lock.url~}}
- {{~/if~}}">
- {{> flow_errors }}
- <input type="hidden" name="wpEditToken" value="{{@root.editToken}}" />
- <input type="hidden" name="flow_reason" value="
- {{~#if isLocked~}}
- {{~l10n "flow-rev-message-restore-topic-reason"~}}
- {{~else~}}
- {{~l10n "flow-rev-message-lock-topic-reason"~}}
- {{~/if~}}
- " />
- <div class="flow-form-actions flow-form-collapsible">
- <button data-role="submit"
- class="mw-ui-button mw-ui-constructive"
- data-flow-interactive-handler="apiRequest"
- data-flow-api-target="< .flow-topic"
- data-flow-api-handler="lockTopic"
- >
- {{#if isLocked}}
- {{l10n "flow-topic-action-unlock-topic"}}
- {{else}}
- {{l10n "flow-topic-action-lock-topic"}}
- {{/if}}
- </button>
- {{> flow_form_cancel_button }}
- <small class="flow-terms-of-use plainlinks">
- {{#if isLocked}}
- {{l10nParse "flow-terms-of-use-unlock-topic"}}
- {{else}}
- {{l10nParse "flow-terms-of-use-lock-topic"}}
- {{/if}}
- </small>
- </div>
- </form>
+ {{~l10n "flow-rev-message-lock-topic-reason"~}}
+ {{~/if~}}
+ " />
+ <div class="flow-form-actions flow-form-collapsible">
+ <button data-role="submit"
+ class="mw-ui-button mw-ui-progressive"
+ >
+ {{#if isLocked}}
+ {{l10n "flow-topic-action-unlock-topic"}}
+ {{else}}
+ {{l10n "flow-topic-action-lock-topic"}}
+ {{/if}}
+ </button>
+ {{> flow_form_cancel_button }}
+ <small class="flow-terms-of-use plainlinks">
+ {{#if isLocked}}
+ {{l10nParse "flow-terms-of-use-unlock-topic"}}
+ {{else}}
+ {{l10nParse "flow-terms-of-use-lock-topic"}}
+ {{/if}}
+ </small>
+ </div>
+ </form>
+ </div>
</div>
</div>
diff --git a/Flow/handlebars/flow_topic_titlebar_summary.partial.handlebars b/Flow/handlebars/flow_topic_titlebar_summary.partial.handlebars
index d1cb3273..a075242a 100644
--- a/Flow/handlebars/flow_topic_titlebar_summary.partial.handlebars
+++ b/Flow/handlebars/flow_topic_titlebar_summary.partial.handlebars
@@ -1,4 +1,4 @@
-<div class="flow-topic-summary-container {{#if isLocked}}flow-click-interactive{{/if}}"
+<div class="flow-topic-summary-container {{#if isLocked}}flow-collapse-toggle flow-click-interactive{{/if}}"
{{#if isLocked}}
data-flow-interactive-handler="collapserCollapsibleToggle"
{{/if}}
@@ -16,9 +16,10 @@
</a>
{{/ifCond}}
</div>
- <div class="flow-topic-summary-content">
+ <div class="flow-topic-summary-content mw-parser-output">
{{escapeContent revision.content.format revision.content.content}}
</div>
+ <div style="clear: both;"></div>
</div>
{{/if}}
</div>
diff --git a/Flow/handlebars/flow_topic_titlebar_watch.partial.handlebars b/Flow/handlebars/flow_topic_titlebar_watch.partial.handlebars
index 933d1ed6..c68cef0d 100644
--- a/Flow/handlebars/flow_topic_titlebar_watch.partial.handlebars
+++ b/Flow/handlebars/flow_topic_titlebar_watch.partial.handlebars
@@ -2,7 +2,7 @@
{{> flow_errors}}
<a href="{{#if isWatched}}{{links.unwatch-topic.url}}{{else}}{{links.watch-topic.url}}{{/if}}"
- class="mw-ui-anchor mw-ui-hovericon mw-ui-constructive {{#unless isWatched}}mw-ui-quiet{{/unless}}
+ class="mw-ui-anchor mw-ui-hovericon {{#unless isWatched}}mw-ui-quiet{{/unless}}
{{#if isWatched~}}
flow-watch-link-unwatch
{{~else~}}
@@ -10,8 +10,8 @@
{{~/if~}}"
data-flow-api-handler="watchItem"
data-flow-api-target="< .flow-topic-watchlist"
- data-flow-api-method="POST">
- {{~noop~}}<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar-constructive" title="{{l10n "flow-topic-action-watchlist-remove"}}"></span>{{~noop~}}
- {{~noop~}}<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-constructive-hover" title="{{l10n "flow-topic-action-watchlist-add"}}"></span>{{~noop~}}
+ data-flow-api-method="POST">{{!-- HACK: using both unStar and unStar-progressive to work around the latter not working in monobook T164350 --}}
+ {{~noop~}}<span class="flow-unwatch mw-ui-icon mw-ui-icon-before mw-ui-icon-unStar mw-ui-icon-unStar-progressive" title="{{l10n "flow-topic-action-watchlist-remove"}}"></span>{{~noop~}}
+ {{~noop~}}<span class="flow-watch mw-ui-icon mw-ui-icon-before mw-ui-icon-star mw-ui-icon-star-progressive-hover" title="{{l10n "flow-topic-action-watchlist-add"}}"></span>{{~noop~}}
</a>
</div>
diff --git a/Flow/i18n/ady-cyrl.json b/Flow/i18n/ady-cyrl.json
index 3541357a..0256c5ba 100644
--- a/Flow/i18n/ady-cyrl.json
+++ b/Flow/i18n/ady-cyrl.json
@@ -1,8 +1,9 @@
{
"@metadata": {
"authors": [
- "TheRossatron"
+ "TheRossatron",
+ "Amire80"
]
},
- "flow-terms-of-use-summarize": "Мыщ уте1унк1эмэ \"{{int:flow-topic-action-update-topic-summary}}\", мы виким и гъэфедэ хабзэхэм адреогъаштэ."
+ "flow-terms-of-use-summarize": "Мыщ утеӀункӀэмэ \"{{int:flow-topic-action-update-topic-summary}}\", мы виким и гъэфедэ хабзэхэм адреогъаштэ."
}
diff --git a/Flow/i18n/aeb-arab.json b/Flow/i18n/aeb-arab.json
new file mode 100644
index 00000000..8cbacf24
--- /dev/null
+++ b/Flow/i18n/aeb-arab.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Csisc"
+ ]
+ },
+ "flow-post-action-edit-post": "بدّل"
+}
diff --git a/Flow/i18n/ais.json b/Flow/i18n/ais.json
new file mode 100644
index 00000000..e80ce1f0
--- /dev/null
+++ b/Flow/i18n/ais.json
@@ -0,0 +1,165 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bunukwiki",
+ "Tokoabibi",
+ "Benel"
+ ]
+ },
+ "flow-board-header-browse-topics-link": "azih sasakamuen",
+ "flow-board-header": "mahizaay tina matatengil a kakitizaan",
+ "flow-board-collapse-description": "midimut sapuelac",
+ "flow-board-expand-description": "paazih sapuelac",
+ "flow-edit-header-link": "mikawaway-kalumyiti a sapuelac",
+ "flow-topic-moderated-reason-prefix": "mahicaay:",
+ "flow-post-actions": "saungay",
+ "flow-cancel": "palawpes",
+ "flow-skip-summary": "sekipo",
+ "flow-show-change": "paazih ku masumaday",
+ "flow-newtopic-title-placeholder": "baluhay a sasakamuen",
+ "flow-newtopic-header": "baluhay micunus baluhay sasakamuen",
+ "flow-newtopic-save": "micunus sasakamuen",
+ "flow-newtopic-start-placeholder": "mililid baluhay sasakamuen",
+ "flow-newtopic-first-heading": "mililid baluhay sasakamuen i $1",
+ "flow-reply-topic-title-placeholder": "patubeli i \"$1\"",
+ "flow-history-action-suppress-post": "milangat",
+ "flow-history-action-delete-post": "misipu",
+ "flow-history-action-hide-post": "midimut",
+ "flow-history-action-unsuppress-post": "mihulak tu langat",
+ "flow-history-action-undelete-post": "palawpes tu masipuay",
+ "flow-history-action-unhide-post": "palawpes midimutay",
+ "flow-history-action-restore-post": "patiku",
+ "flow-history-action-lock-topic": "hulak",
+ "flow-history-action-unlock-topic": "liyaw miwawah",
+ "flow-post-action-view": "saluimengay masasiket",
+ "flow-post-action-post-history": "nasulitan nu nazipa’an",
+ "flow-post-action-suppress-post": "milangat",
+ "flow-post-action-delete-post": "misipu",
+ "flow-post-action-hide-post": "midimut",
+ "flow-post-action-edit-post-submit": "misuped tu sumad",
+ "flow-post-action-edit-post-submit-anonymously": "paceba panganganay a misaungayay misuped tu sumad",
+ "flow-post-action-unsuppress-post": "mihulak tu langat",
+ "flow-post-action-undelete-post": "palawpes tu masipuay",
+ "flow-post-action-unhide-post": "palawpes midimutay",
+ "flow-post-action-restore-post": "patiku",
+ "flow-post-action-undo-moderation": "patiku",
+ "flow-topic-action-view": "saluimengay masasiket",
+ "flow-topic-action-watchlist": "miazihay a piazihan tu sulit",
+ "flow-topic-action-edit-title": "satangahan mikawaway-kalumyiti",
+ "flow-topic-action-history": "nazipa’an",
+ "flow-topic-action-hide-topic": "midimut sasakamuen",
+ "flow-topic-action-delete-topic": "misipu tu sasakamuen",
+ "flow-topic-action-lock-topic": "silusi sanay siwantantu",
+ "flow-topic-action-unlock-topic": "miliyaw miwawah sasakamuen",
+ "flow-topic-action-summarize-topic": "pecu’ nu lacul",
+ "flow-topic-action-resummarize-topic": "sasakamuen pecu’ nu lacul nu mikawaway-kalumyiti",
+ "flow-topic-action-update-topic-summary": "misabaluh tu pecu’ nu lacul",
+ "flow-topic-action-suppress-topic": "milangat sasakamuen",
+ "flow-topic-action-unhide-topic": "palawpes midimutay sasakamuen",
+ "flow-topic-action-undelete-topic": "palawpes masipuay sasakamuen",
+ "flow-topic-action-unsuppress-topic": "palawpes milangatay a sasakamuen",
+ "flow-topic-action-restore-topic": "patiku sasakamuen",
+ "flow-topic-action-undo-moderation": "patiku",
+ "flow-topic-action-watchlist-add": "miaca aazihan wini a satangahan nu kamu",
+ "flow-topic-action-watchlist-remove": "palawpes miaca aazihan",
+ "flow-error-missing-summary": "kanca misulit pecu’ nu lacul kisu.",
+ "flow-error-protected-unknown-reason": "caay kapulita",
+ "flow-error-not-allowed-hide": "tina sasakamuen midimut tu",
+ "flow-error-not-allowed-delete": "tina sasakamuen masipu tu",
+ "flow-error-not-allowed-suppress": "tina sasakamuen masipu tu",
+ "flow-error-missing-header-content": "kanca misulit sapuelac kisu.",
+ "flow-error-prev-revision-does-not-exist": "caykatepa masumad nu ayaway.",
+ "flow-error-default": "mungangaw.",
+ "flow-error-fail-load-history": "pacumud nazipa’an a lacul mungangaw.",
+ "flow-error-invalid-topic-uuid-title": "la’cusay a pyawti",
+ "flow-error-unknown-workflow-id-title": "caay kapulita ku sasakamuen",
+ "flow-error-unknown-workflow-id": "inayi’ ku milungucay a sasakamuen.",
+ "flow-edit-header-submit": "misuped sapaelac",
+ "flow-edit-header-submit-anonymously": "paceba panganganay a misaungayay misuped tu sapuelac",
+ "flow-edit-title-submit": "misumad tu satangahan",
+ "flow-edit-title-submit-anonymously": "paceba panganganay a misaungayay misumad satangahan",
+ "flow-edit-post-submit-anonymously": "paceba panganganay a misaungayay pabeli tu sumad",
+ "flow-rev-message-lock-topic-reason": "silusi sanay siwantantu",
+ "flow-rev-message-restore-topic-reason": "liyaw miwawah",
+ "flow-rc-topic-of-board": "$1 i $2",
+ "flow-board-history": "\"$1\" nasulitan nu nazipa’an",
+ "flow-topic-history": "$1 sasakamuen nazipa’an",
+ "flow-history-day": "ayza a demiad",
+ "flow-history-week": "naayaway cacay a lipay",
+ "flow-comment-restored": "patiku tu buhci tu kamu",
+ "flow-comment-deleted": "masipuay a buhci tu kamu",
+ "flow-comment-hidden": "midimutay a buhci tu kamu",
+ "flow-comment-moderated": "nikuwanan a buhci tu kamu",
+ "flow-last-modified": "nuayaw a cacay misumad i $1",
+ "flow-workflow": "laylay nu kawaw",
+ "flow-notification-link-text-view-post": "ciwsace tu pazepit tu nisulitan",
+ "flow-notification-link-text-view-topic": "ciwsace tu sasakamuen",
+ "flow-notification-reply-email-subject": "$2 i $3",
+ "flow-link-post": "patiyak",
+ "flow-link-topic": "sasakamuen",
+ "flow-link-history": "nazipa’an",
+ "flow-link-post-revision": "pazepit tu nisulitan masumad nu ayaway",
+ "flow-link-topic-revision": "sasakamuen masumad nu ayaway",
+ "flow-link-header-revision": "misumad tu sapuelac nu ayaway",
+ "flow-link-summary-revision": "pecu’ nu lacul masumad nu ayaway",
+ "flow-moderation-title-suppress-post": "milangat pazepit tu nisulitan?",
+ "flow-moderation-title-delete-post": "misipu pazepit tu nisulitan?",
+ "flow-moderation-title-hide-post": "midimut pazepit tu nisulitan?",
+ "flow-moderation-confirm-suppress-post": "malangat",
+ "flow-moderation-confirm-delete-post": "misipu",
+ "flow-moderation-confirm-hide-post": "midimut",
+ "flow-moderation-confirm-unsuppress-post": "mihulak tu langat",
+ "flow-moderation-confirm-undelete-post": "palawpes tu masipuay",
+ "flow-moderation-confirm-unhide-post": "palawpes midimutay",
+ "flow-moderation-confirm-suppress-topic": "malangat",
+ "flow-moderation-confirm-delete-topic": "masipu",
+ "flow-moderation-confirm-hide-topic": "midimut",
+ "flow-moderation-confirm-unsuppress-topic": "mihulak tu langat",
+ "flow-moderation-confirm-undelete-topic": "palawpes tu masipuay",
+ "flow-moderation-confirm-unhide-topic": "palawpes midimutay",
+ "flow-moderation-confirmation-suppress-topic": "malahci malangat tina sasakamuen tuway.",
+ "flow-moderation-confirmation-delete-topic": "tina sasakamuen masipu tu",
+ "flow-moderation-confirmation-hide-topic": "tina sasakamuen midimut tu",
+ "flow-moderation-title-suppress-topic": "milangat sasakamuen?",
+ "flow-moderation-title-delete-topic": "misipu sasakamuen?",
+ "flow-moderation-title-hide-topic": "midimut sasakamuen?",
+ "flow-moderation-title-unsuppress-topic": "palawpes milangatay a sasakamuen?",
+ "flow-moderation-title-undelete-topic": "palawpes masipuay sasakamuen?",
+ "flow-moderation-title-unhide-topic": "palawpes midimutay sasakamuen?",
+ "flow-topic-first-heading": "itiza i $1 a sasakamuen",
+ "flow-topic-html-title": "i $2 a $1",
+ "flow-load-more": "kayadahan miasip",
+ "flow-newest-topics": "sabaluhay sasakamuen",
+ "flow-toggle-small-topics": "ketun mibalic miciwsace adidi’ay a sasakamuen",
+ "flow-toggle-topics": "ketun mibalic miciwsace sasakamuen a cacay",
+ "structureddiscussions": "Flow",
+ "flow-special-type": "nikalahizaan",
+ "flow-special-type-post": "patiyak",
+ "flow-special-type-workflow": "laylay nu kawaw",
+ "flow-special-uuid": "UUID",
+ "flow-post-undo-hide": "patiku midimutay",
+ "flow-post-undo-delete": "patiku masipuay",
+ "flow-topic-undo-hide": "patiku midimutay",
+ "flow-topic-undo-delete": "patiku masipuay",
+ "flow-topic-undo-suppress": "patiku malangat",
+ "flow-edited": "mikawaway-kalumyiti tuway i",
+ "flow-previous-diff": "← malumanay a mikawaway-kalumyiti",
+ "flow-next-diff": "baluhayay mikawaway-kalumyiti →",
+ "flow-undo": "patiku",
+ "flow-undo-latest-revision": "sabaluhay masumad",
+ "flow-undo-your-text": "numisuay a sulit",
+ "flow-undo-edit-header": "imahini mikawaway-kalumyiti myawsu",
+ "flow-undo-edit-topic-summary": "imahini mikawaway-kalumyiti sasakamuen a pecu’ nu lacul",
+ "flow-undo-edit-post": "imahini mikawaway-kalumyiti pazepit tu nisulitan",
+ "flow-ve-mention-context-item-label": "sakamu sa",
+ "flow-ve-mention-placeholder": "misaungayay a kalungangan",
+ "flow-wikitext-editor-help": "Wikitext $1.",
+ "flow-wikitext-editor-help-preview-the-result": "heci nu pataayaway miazih",
+ "flow-wikitext-switch-editor-tooltip": "ketun mibalic ta palakuliten ku aazihen sakawaw-kalumyiti",
+ "flow-mark-revision-patrolled-link-text": "silusi tina belih ku tayza-mikibi",
+ "flow-mark-diff-patrolled-link-text": "silusi natayza mikibi tuway",
+ "flow-mark-diff-patrolled-link-title": "silusi natayza mikibi tuway",
+ "flow-beta-feature-remove-archive-template-edit-summary": "imahini misipu misinga’ taazihan-mitudung",
+ "flow-dialog-cancelconfirm-keep": "palalid mikawaway-kalumyiti",
+ "flow-dialog-cancelconfirm-discard": "miales tu masumaday"
+}
diff --git a/Flow/i18n/api/ar.json b/Flow/i18n/api/ar.json
new file mode 100644
index 00000000..fe9a3d8d
--- /dev/null
+++ b/Flow/i18n/api/ar.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "محمد أحمد عبد الفتاح",
+ "بدارين"
+ ]
+ },
+ "apihelp-flow+edit-post-param-postId": "معرف المنشور.",
+ "apihelp-flow+edit-title-param-content": "محتوى العنوان، بنفس التنسيق المتاح لملخصات التعديل (موضوع-عنوان-نصوص ويكي).",
+ "apihelp-flow+view-topic-description": "اعرض الموضوع",
+ "apihelp-flow+view-topiclist-description": "عرض قائمة بالموضوعات"
+}
diff --git a/Flow/i18n/api/ast.json b/Flow/i18n/api/ast.json
new file mode 100644
index 00000000..7ae5d74e
--- /dev/null
+++ b/Flow/i18n/api/ast.json
@@ -0,0 +1,139 @@
+{
+ "@metadata": {
+ "authors": [
+ "Quiddity",
+ "Xuacu"
+ ]
+ },
+ "apihelp-flow-description": "Permite facer aiciones en páxines de Flow.",
+ "apihelp-flow-summary": "Permite facer aiciones en páxines de Flow.",
+ "apihelp-flow-param-submodule": "El submódulu de Flow a invocar.",
+ "apihelp-flow-param-page": "La páxina na que facer l'aición.",
+ "apihelp-flow-param-token": "Un pase recibíu dende [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Editar la descripción de «[[Talk:Sandbox]]»",
+ "apihelp-flow+close-open-topic-description": "Anticuao en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&#38;submodule=lock-topic]]",
+ "apihelp-flow+close-open-topic-summary": "Anticuao en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]",
+ "apihelp-flow+close-open-topic-param-moderationState": "Estáu nel que poner la tema, sía \"lock\" (bloquiáu) o \"unlock\" (desbloquiáu).",
+ "apihelp-flow+close-open-topic-param-reason": "El motivu pa bloquiar o desbloquiar la tema.",
+ "apihelp-flow+edit-header-description": "Edita la descripción d'un tableru.",
+ "apihelp-flow+edit-header-summary": "Edita la descripción d'un tableru.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID de revisión de la revisión actual de la descripción, pa comprobar conflictos d'edición.",
+ "apihelp-flow+edit-header-param-content": "Conteníu pa la descripción.",
+ "apihelp-flow+edit-header-param-format": "Formatu de la descripción (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Editar la descripción de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Editar el conteníu d'una publicación.",
+ "apihelp-flow+edit-post-summary": "Editar el conteníu d'una publicación.",
+ "apihelp-flow+edit-post-param-postId": "ID de la publicación.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID de revisión de la revisión actual de la publicación, pa comprobar conflictos d'edición.",
+ "apihelp-flow+edit-post-param-content": "Conteníu pa publicar.",
+ "apihelp-flow+edit-post-param-format": "Formatu del conteníu de la publicación (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Editar una publicación en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edita'l títulu d'una tema.",
+ "apihelp-flow+edit-title-summary": "Edita'l títulu d'una tema.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID de revisión de la revisión actual del títulu, pa comprobar conflictos d'edición.",
+ "apihelp-flow+edit-title-param-content": "Conteníu pal títulu, nel mesmu formatu permitíu pa editar resumes (asuntu-títulu-testu wiki).",
+ "apihelp-flow+edit-title-example-1": "Editar el títulu de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Editar el conteníu del resume d'una tema.",
+ "apihelp-flow+edit-topic-summary-summary": "Editar el conteníu del resume d'una tema.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID de revisión de la revisión actual del resume de la tema, si hubiera, pa comprobar conflictos d'edición.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Conteníu del resume.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formatu del resume (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Editar el resume de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Bloquiar o desbloquiar un asuntu de Flow.",
+ "apihelp-flow+lock-topic-summary": "Bloquiar o desbloquiar un asuntu de Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Estáu nel que poner la tema, sía <kbd>lock</kbd> (bloquiáu) o <kbd>unlock</kbd> (desbloquiáu).",
+ "apihelp-flow+lock-topic-param-reason": "El motivu pa bloquiar o desbloquiar l'asuntu. Ten en cuenta que'l veceru Flow de la wiki usa equí «Marcáu como resuelto», y pon otra información más nel resume.",
+ "apihelp-flow+lock-topic-example-1": "Bloquiar [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modera una publicación de Flow.",
+ "apihelp-flow+moderate-post-summary": "Modera una publicación de Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A qué nivel moderar.",
+ "apihelp-flow+moderate-post-param-reason": "Motivu de la moderación.",
+ "apihelp-flow+moderate-post-param-postId": "ID de la publicación a moderar.",
+ "apihelp-flow+moderate-post-example-1": "Desaniciar una publicación nel asuntu [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modera un asuntu de Flow.",
+ "apihelp-flow+moderate-topic-summary": "Modera un asuntu de Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A qué nivel moderar.",
+ "apihelp-flow+moderate-topic-param-reason": "Motivu de la moderación.",
+ "apihelp-flow+moderate-topic-example-1": "Desaniciar l'asuntu [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Crea un nuevu asuntu de Flow nel fluxu de trabayu indicáu.",
+ "apihelp-flow+new-topic-summary": "Crea un nuevu asuntu de Flow nel fluxu de trabayu indicáu.",
+ "apihelp-flow+new-topic-param-topic": "Testu pal nuevu títulu del asuntu.",
+ "apihelp-flow+new-topic-param-content": "Conteníu pa la respuesta inicial del asuntu.",
+ "apihelp-flow+new-topic-param-format": "Formatu de la respuesta inicial del nuevu asuntu (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Crear un asuntu nuevu en [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Respuestes a una publicación.",
+ "apihelp-flow+reply-summary": "Respuestes a una publicación.",
+ "apihelp-flow+reply-param-replyTo": "ID de la publicación a la que responder.",
+ "apihelp-flow+reply-param-content": "Conteníu de la nueva publicación.",
+ "apihelp-flow+reply-param-format": "Formatu de la nueva publicación (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Responder a una publicación en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-header-description": "Ver la descripción d'un tableru.",
+ "apihelp-flow+view-header-summary": "Ver la descripción d'un tableru.",
+ "apihelp-flow+view-header-param-revId": "Cargar esta revisión en cuenta de la más recién.",
+ "apihelp-flow+view-header-example-1": "Llograr la descripción de [[Talk:Sandbox]] como testu wiki",
+ "apihelp-flow+view-post-description": "Ver una publicación.",
+ "apihelp-flow+view-post-summary": "Ver una publicación.",
+ "apihelp-flow+view-post-param-postId": "ID de la publicación a ver.",
+ "apihelp-flow+view-post-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-post-example-1": "Llograr el conteníu d'una publicación en [[Topic:S2tycnas4hcucw8w]] como testu wiki",
+ "apihelp-flow+view-post-history-description": "Ver l'historial de revisiones d'una publicación.",
+ "apihelp-flow+view-post-history-summary": "Ver l'historial de revisiones d'una publicación.",
+ "apihelp-flow+view-post-history-param-postId": "Identificador de la publicación pa la que ver l'historial de revisiones.",
+ "apihelp-flow+view-post-history-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-post-history-example-1": "Llograr les revisiones d'una publicación en [[Topic:S2tycnas4hcucw8w]] como testu wiki",
+ "apihelp-flow+view-topic-description": "Ver un asuntu.",
+ "apihelp-flow+view-topic-summary": "Ver un asuntu.",
+ "apihelp-flow+view-topic-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Ver l'historial de revisiones d'un asuntu.",
+ "apihelp-flow+view-topic-history-summary": "Ver l'historial de revisiones d'un asuntu.",
+ "apihelp-flow+view-topic-history-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-topic-history-example-1": "Llograr les revisiones de les publicaciones en [[Topic:S2tycnas4hcucw8w]] como testu wiki",
+ "apihelp-flow+view-topic-summary-description": "Ver el resume d'un asuntu.",
+ "apihelp-flow+view-topic-summary-summary": "Ver el resume d'un asuntu.",
+ "apihelp-flow+view-topic-summary-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-topic-summary-param-revId": "Cargar esta revisión en cuenta de la más recién.",
+ "apihelp-flow+view-topic-summary-example-1": "Ver el resume de [[Topic:S2tycnas4hcucw8w]] como testu wiki",
+ "apihelp-flow+view-topiclist-description": "Ver una llista d'asuntos.",
+ "apihelp-flow+view-topiclist-summary": "Ver una llista d'asuntos.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Dirección d'ordenamientu de los asuntos.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opción d'ordenamientu de les temes. Puede ser <kbd>updated</kbd> (ordenáu pola hora d'anovamientu de tema), o bien <kbd>newest</kbd> (ordenáu pola hora de creación de tema).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Guardar la opción d'ordenamientu nes preferencies del usuariu, si se configura.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Valor d'allancia (en formatu UUID) dende'l qu'empezar a llograr temes; utilizáu solo col ordenamientu <kbd>más nuevos</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Valor d'allancia (como marca de tiempu d'actualización d'un asuntu, en formatu <code>TS_MW</code> (<code>AAAAMMDDHHMMSS</code>)), pa principiar a llograr asuntos; usáu solo col ordenamientu <kbd>anovamientu</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Incluye tamién la allancia del elementu nos resultaos.",
+ "apihelp-flow+view-topiclist-param-limit": "Númberu de temes a llograr.",
+ "apihelp-flow+view-topiclist-param-toconly": "Si hai que responder sólo cola información necesaria pal resume.",
+ "apihelp-flow+view-topiclist-param-format": "Formatu nel que devolver el conteníu.",
+ "apihelp-flow+view-topiclist-example-1": "Llista de temes en [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Convertir testu ente testu wiki y HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Convertir testu ente testu wiki y HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formatu del conteníu a convertir.",
+ "apihelp-flow-parsoid-utils-param-to": "Formatu al que convertir el conteníu.",
+ "apihelp-flow-parsoid-utils-param-content": "Conteníu a convertir.",
+ "apihelp-flow-parsoid-utils-param-title": "Títulu de la páxina Nun puede usase xunto con $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID de la páxina. Nun puede usase xunto con $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Convertir el testu wiki <nowiki>'''lorem''' ''blablabla''</nowiki> a HTML",
+ "apihelp-query+flowinfo-description": "Llograr información básica de Flow sobro una páxina.",
+ "apihelp-query+flowinfo-summary": "Llograr información básica de Flow sobro una páxina.",
+ "apihelp-query+flowinfo-example-1": "Llograr información de Flow sobro [[Talk:Sandbox]], [[Main Page]] y [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Algamar la información precisa pa desfacer ediciones de descripciones.",
+ "apihelp-flow+undo-edit-header-summary": "Algamar la información precisa pa desfacer ediciones de descripciones.",
+ "apihelp-flow+undo-edit-header-param-startId": "ID de revisión nel que principiar a desfacer.",
+ "apihelp-flow+undo-edit-header-param-endId": "ID de revisión nel que terminar de desfacer.",
+ "apihelp-flow+undo-edit-header-example-1": "Llograr información sobre desfaer una edición de descripción en [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Llograr la información necesaria pa desfaer la edición de la publicación.",
+ "apihelp-flow+undo-edit-post-summary": "Llograr la información necesaria pa desfaer la edición de la publicación.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID de la publicación a desfaer.",
+ "apihelp-flow+undo-edit-post-param-startId": "ID de revisión na que principiar a desfacer.",
+ "apihelp-flow+undo-edit-post-param-endId": "ID de revisión na que terminar de desfacer.",
+ "apihelp-flow+undo-edit-post-example-1": "Llograr información sobro cómo desfacer una edición de publicación d'una tema específica.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Algamar la información precisa pa desfacer ediciones de descripciones.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Algamar la información precisa pa desfacer ediciones de descripciones.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "ID de revisión na que principiar a desfacer.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "ID de revisión na que terminar de desfacer.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Llograr información sobro cómo desfacer una edición de resume d'una tema específica.",
+ "apierror-flow-safeallowcreationfailed": "La páxina dada nun tien activáu Flow y safeAllowCreation falló col mensaxe: $1",
+ "apierror-flow-notenabled": "La páxina dada nun tien activáu Flow."
+}
diff --git a/Flow/i18n/api/bn.json b/Flow/i18n/api/bn.json
new file mode 100644
index 00000000..aaa9b406
--- /dev/null
+++ b/Flow/i18n/api/bn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftabuzzaman"
+ ]
+ },
+ "apihelp-flow+view-topic-summary": "একটি প্রসঙ্গ দেখুন।",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] দেখুন"
+}
diff --git a/Flow/i18n/api/bs.json b/Flow/i18n/api/bs.json
new file mode 100644
index 00000000..3028cc1a
--- /dev/null
+++ b/Flow/i18n/api/bs.json
@@ -0,0 +1,109 @@
+{
+ "@metadata": {
+ "authors": [
+ "Semso98",
+ "Srdjan m"
+ ]
+ },
+ "apihelp-flow-description": "Dozvoljava da se izvrše radnje na Flow stranicama.",
+ "apihelp-flow-param-submodule": "Koji podmodul Flowa treba pozvati.",
+ "apihelp-flow-param-page": "Stranicu na koju treba izvršiti radnju.",
+ "apihelp-flow-example-1": "Uredi opis stranice \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Zastarijelo u korist [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Stanje u koje temu treba staviti, ili \"lock\" ili \"unlock\".",
+ "apihelp-flow+close-open-topic-param-reason": "Razlog za zaključavanje ili otključavanje teme.",
+ "apihelp-flow+edit-header-description": "Uređuje opis rasprave.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID izmjene trenutne verzije opisa kako bi se provjerilo ima li sukoba izmjena.",
+ "apihelp-flow+edit-header-param-content": "Sadržaj opisa.",
+ "apihelp-flow+edit-header-param-format": "Format opisa (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Uredi opis [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Uređuje sadržaj objave.",
+ "apihelp-flow+edit-post-param-postId": "ID objave.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID izmjene trenutne verzije objave kako bi se provjerilo ima li sukoba izmjena.",
+ "apihelp-flow+edit-post-param-content": "Sadržaj objave.",
+ "apihelp-flow+edit-post-param-format": "Format sadržaja objave (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Uredi objavu u [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Uređuje naslov objave.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID izmjene trenutne verzije naslova kako bi se provjerilo ima li sukoba izmjena.",
+ "apihelp-flow+edit-title-param-content": "Sadržaj naslova, u istom formatu koji je dozvoljen za sažetke izmjena (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Uredi naslov teme [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Uređuje sažetak sadržaja teme.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID izmjene trenutne verzije sažetka objave, ako postoji, kako bi se provjerilo ima li sukoba izmjena.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Sadržaj sažetka.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format sažetka (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Uredi sažetak teme [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Zaključaj ili otključaj Flow temu.",
+ "apihelp-flow+lock-topic-param-moderationState": "Stanje u koje treba postaviti temu. Može biti <kbd>lock</kbd> (zaključaj) ili <kbd>unlock</kbd> (otključaj).",
+ "apihelp-flow+lock-topic-param-reason": "Razlog za zaključavanje ili otključavanje teme. Napomena: Flow klijent na wikiju za ovo koristi \"Označi kao riješeno\" i dodaje dodatne informacije pod sažetak.",
+ "apihelp-flow+lock-topic-example-1": "Zaključaj temu [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Moderira Flow objavu.",
+ "apihelp-flow+moderate-post-param-moderationState": "Na koji nivo treba vršiti moderaciju.",
+ "apihelp-flow+moderate-post-param-reason": "Razlog za moderaciju.",
+ "apihelp-flow+moderate-post-param-postId": "ID objave koju treba moderirati.",
+ "apihelp-flow+moderate-post-example-1": "Obriši objavu na temi [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderira Flow teme.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Na koji nivo treba vršiti moderaciju.",
+ "apihelp-flow+moderate-topic-param-reason": "Razlog za moderaciju.",
+ "apihelp-flow+moderate-topic-example-1": "Obriši temu [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Stvara novu Flow temu na zadanoj raspravi.",
+ "apihelp-flow+new-topic-param-topic": "Tekst naslova nove teme.",
+ "apihelp-flow+new-topic-param-content": "Sadržaj prvobitnog odgovora teme.",
+ "apihelp-flow+new-topic-param-format": "Format prvobitnog odgovora teme (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Stvori novu temnu na stranici [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Odgovara na objavu.",
+ "apihelp-flow+reply-param-replyTo": "ID objave na koju treba odgovoriti.",
+ "apihelp-flow+reply-param-content": "Sadržaj nove objave.",
+ "apihelp-flow+reply-param-format": "Format nove objave (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Odgovori na objavu na temu [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format za prikaz sadržaja.",
+ "apihelp-flow+view-header-description": "Vidi opis rasprave.",
+ "apihelp-flow+view-header-param-revId": "Učitaj ovu verziju umjesto najnovije.",
+ "apihelp-flow+view-header-example-1": "Dobavi opis stranice [[Talk:Sandbox]] kao wikitekst",
+ "apihelp-flow+view-post-description": "Vidi objavu.",
+ "apihelp-flow+view-post-param-postId": "ID objave koju treba vidjeti.",
+ "apihelp-flow+view-post-param-format": "Format za prikaz sadržaja.",
+ "apihelp-flow+view-post-example-1": "Dobavi sadržaj objave [[Topic:S2tycnas4hcucw8w]] kao wikitekst",
+ "apihelp-flow+view-post-history-description": "Vidi historiju izmjena objave.",
+ "apihelp-flow+view-post-history-param-postId": "ID objave za koju treba vidjeti historiju izmjena.",
+ "apihelp-flow+view-post-history-param-format": "Format za prikaz sadržaja.",
+ "apihelp-flow+view-post-history-example-1": "Dobavi izmjene objave [[Topic:S2tycnas4hcucw8w]] kao wikitekst",
+ "apihelp-flow+view-topic-description": "Vidi temu.",
+ "apihelp-flow+view-topic-example-1": "Vidi [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Vidi historiju izmjena teme.",
+ "apihelp-flow+view-topic-history-param-format": "Format za prikaz sadržaja.",
+ "apihelp-flow+view-topic-history-example-1": "Vidi izmjene objava na temi [[Topic:S2tycnas4hcucw8w]] kao wikitekst",
+ "apihelp-flow+view-topic-summary-description": "Vidi opis teme.",
+ "apihelp-flow+view-topic-summary-param-format": "Format za prikaz sadržaja.",
+ "apihelp-flow+view-topic-summary-param-revId": "Učitaj ovu verziju umjesto najnovije.",
+ "apihelp-flow+view-topic-summary-example-1": "Vidi sažetak za [[Topic:S2tycnas4hcucw8w]] kao wikitekst",
+ "apihelp-flow+view-topiclist-description": "Vidi spisak tema.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Smjer za redanje tema.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opcije sortiranja tema. Može biti <kbd>updated</kbd> (sortira se po najaktivnijim izmjenama) ili <kbd>newest</kbd> (sortira se po najnovijim izmjenama).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Ako su postavljene, sačuvaj opcije za sortiranje u korisničke postavke.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Ofset vrijednost (u UUID formatu) za početak dobavljanja tema; jedino se koristi za sortiranje <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Ofset vrijednost (kao vremenska oznaka za ažuriranje objave u <code>TS_MW</code> formatu (<code>YYYYMMDDHHMMSS</code>)); koristi se za početak dobavljanja tema; također se jedino koristi sa sortiranjem <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-limit": "Broj tema za dobaviti",
+ "apihelp-flow+view-topiclist-example-1": "Izlistaj teme na [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Pretvori tekst sa wikiteksta na HTML i obratno.",
+ "apihelp-flow-parsoid-utils-param-from": "Format sa kojeg treba pretvoriti sadržaj.",
+ "apihelp-flow-parsoid-utils-param-to": "Format na koji treba pretvoriti sadržaj.",
+ "apihelp-flow-parsoid-utils-param-content": "Sadržaj koji treba biti pretvoren.",
+ "apihelp-flow-parsoid-utils-param-title": "Naslov stranice. Ne može se koristiti s $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID stranice. Ne može se koristiti s $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Pretvori wikitekst <nowiki>'''lorem''' ''blah''</nowiki> u HTML",
+ "apihelp-query+flowinfo-description": "Dobavi osnovne Flow informacije o stranici.",
+ "apihelp-query+flowinfo-example-1": "Dobavi Flow informacije o [[Talk:Sandbox]], [[Main Page]] i [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Dobavi potrebne informacije za poništenje uređivanja opisa.",
+ "apihelp-flow+undo-edit-header-param-startId": "ID izmjene za početak poništenja.",
+ "apihelp-flow+undo-edit-header-param-endId": "ID izmjene za kraj poništenja.",
+ "apihelp-flow+undo-edit-header-example-1": "Dobavi informacije o poništenju izmjena opisa na stranici [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Dobavi potrebne informacije za poništenje uređivanja objave.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID objave koju treba poništiti.",
+ "apihelp-flow+undo-edit-post-param-startId": "ID izmjene za početak poništenja.",
+ "apihelp-flow+undo-edit-post-param-endId": "ID izmjene za kraj poništenja.",
+ "apihelp-flow+undo-edit-post-example-1": "Dobavi informacije o poništenju izmjene objave u određenoj temi.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Dobavi potrebne informacije za poništenje uređivanja sažetka.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "ID izmjene za početak poništenja.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "ID izmjene za kraj poništenja.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Dobavi informacije o poništenju izmjene sažetka u određenoj temi"
+}
diff --git a/Flow/i18n/api/de.json b/Flow/i18n/api/de.json
new file mode 100644
index 00000000..14c3ed77
--- /dev/null
+++ b/Flow/i18n/api/de.json
@@ -0,0 +1,117 @@
+{
+ "@metadata": {
+ "authors": [
+ "Andreasburmeister",
+ "Inkowik",
+ "MarcoFalke",
+ "Metalhead64",
+ "Predatorix",
+ "Quiddity",
+ "Tiin"
+ ]
+ },
+ "apihelp-flow-description": "Erlaubt auszuführende Aktionen auf Flow-Seiten.",
+ "apihelp-flow-param-submodule": "Das aufzurufende Flow-Submodul.",
+ "apihelp-flow-param-page": "Die Seite, auf die die Aktion angewandt werden soll.",
+ "apihelp-flow-param-token": "Ein abgerufener Token von [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Die Beschreibung von „[[Talk:Sandbox]]“ bearbeiten",
+ "apihelp-flow+close-open-topic-description": "Zugunsten von [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]] aufgegeben.",
+ "apihelp-flow+close-open-topic-param-moderationState": "Status, in den das Thema versetzt werden soll. Entweder „lock“ oder „unlock“.",
+ "apihelp-flow+close-open-topic-param-reason": "Grund für das Sperren oder Freigeben des Themas.",
+ "apihelp-flow+edit-header-description": "Bearbeitet die Beschreibung eines Boards.",
+ "apihelp-flow+edit-header-param-prev_revision": "Kennung der aktuellen Beschreibungsversion, die auf Bearbeitungskonflikte überprüft werden soll.",
+ "apihelp-flow+edit-header-param-content": "Inhalt für die Beschreibung.",
+ "apihelp-flow+edit-header-param-format": "Format der Beschreibung (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Bearbeitet die Beschreibung von [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Bearbeitet den Inhalt eines Beitrags.",
+ "apihelp-flow+edit-post-summary": "Bearbeitet den Inhalt eines Beitrags.",
+ "apihelp-flow+edit-post-param-postId": "Beitragskennung.",
+ "apihelp-flow+edit-post-param-prev_revision": "Versionskennung der aktuellen Beitragsversion, die auf Bearbeitungskonflikte überprüft werden soll.",
+ "apihelp-flow+edit-post-param-content": "Inhalt für den Beitrag.",
+ "apihelp-flow+edit-post-param-format": "Format des Beitrags (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Bearbeitet einen Beitrag in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Bearbeitet den Titel eines Themas.",
+ "apihelp-flow+edit-title-summary": "Bearbeitet den Titel eines Themas.",
+ "apihelp-flow+edit-title-param-prev_revision": "Versionskennung der aktuellen Titelversion zum Erkennen von Bearbeitungskonflikten.",
+ "apihelp-flow+edit-title-param-content": "Inhalt für den Titel, im gleichen erlaubten Format für Bearbeitungszusammenfassungen (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Bearbeitet den Titel von [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Bearbeitet den Inhalt einer Themenzusammenfassung.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Inhalt für die Zusammenfassung.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format der Zusammenfassung (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Bearbeitet die Zusammenfassung von [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Sperrt ein Flow-Thema oder gibt es wieder frei.",
+ "apihelp-flow+lock-topic-param-reason": "Grund für das Sperren oder Freigeben des Themas. Beachte bitte, dass der Wiki-Flow-Client hier „Als erledigt markiert“ verwendet und optionale zusätzliche Informationen in die Zusammenfassung platziert.",
+ "apihelp-flow+lock-topic-example-1": "Sperrt [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Moderiert einen Flow-Beitrag.",
+ "apihelp-flow+moderate-post-param-moderationState": "Auf welcher Ebene moderiert werden soll.",
+ "apihelp-flow+moderate-post-param-reason": "Grund für die Moderation.",
+ "apihelp-flow+moderate-post-param-postId": "Kennung des zu moderierenden Beitrags.",
+ "apihelp-flow+moderate-post-example-1": "Löscht einen Beitrag im Thema [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderiert ein Flow-Thema.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Auf welcher Ebene moderiert werden soll.",
+ "apihelp-flow+moderate-topic-param-reason": "Grund für die Moderation.",
+ "apihelp-flow+moderate-topic-example-1": "Löscht das Thema [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Erstellt ein neues Flow-Thema auf dem angegebenen Workflow.",
+ "apihelp-flow+new-topic-param-topic": "Text für den Titel des neuen Themas.",
+ "apihelp-flow+new-topic-param-content": "Inhalt für die erste Antwort des Themas.",
+ "apihelp-flow+new-topic-param-format": "Format des Ausgangsbeitrags des neuen Themas (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Erstellt ein neues Thema auf [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Antwortet auf einen Beitrag.",
+ "apihelp-flow+reply-param-replyTo": "Kennung des Beitrags, auf den geantwortet werden soll.",
+ "apihelp-flow+reply-param-content": "Inhalt für den neuen Beitrag.",
+ "apihelp-flow+reply-param-format": "Format des neuen Beitrags (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Antwortet auf einen Beitrag in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-header-description": "Board-Beschreibung ansehen.",
+ "apihelp-flow+view-header-param-revId": "Lädt diese anstelle der aktuellsten Version.",
+ "apihelp-flow+view-header-example-1": "Ruft die Beschreibung von [[Talk:Sandbox]] als Wikitext ab",
+ "apihelp-flow+view-post-description": "Betrachtet einen Beitrag.",
+ "apihelp-flow+view-post-param-postId": "Kennung des anzuzeigenden Beitrags.",
+ "apihelp-flow+view-post-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-post-example-1": "Ruft den Inhalt in [[Topic:S2tycnas4hcucw8w]] als Wikitext ab",
+ "apihelp-flow+view-post-history-description": "Zeigt die Versionsgeschichte eines Beitrags an.",
+ "apihelp-flow+view-post-history-param-postId": "Kennung des Beitrags, für den die Versionsgeschichte angezeigt werden soll.",
+ "apihelp-flow+view-post-history-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-post-history-example-1": "Ruft die Versionen eines Beitrags in [[Topic:S2tycnas4hcucw8w]] als Wikitext ab",
+ "apihelp-flow+view-topic-description": "Betrachtet ein Thema.",
+ "apihelp-flow+view-topic-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] ansehen",
+ "apihelp-flow+view-topic-history-description": "Zeigt die Versionsgeschichte eines Themas an.",
+ "apihelp-flow+view-topic-history-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-topic-summary-description": "Betrachtet eine Themenzusammenfassung.",
+ "apihelp-flow+view-topic-summary-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-topic-summary-param-revId": "Lädt diese anstelle der aktuellsten Version.",
+ "apihelp-flow+view-topic-summary-example-1": "Zeigt die Zusammenfassung für [[Topic:S2tycnas4hcucw8w]] als Wikitext an",
+ "apihelp-flow+view-topiclist-description": "Betrachtet eine Liste der Themen.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Sortierrichtung der Themen.",
+ "apihelp-flow+view-topiclist-param-sortby": "Sortieroption der Themen, entweder <kbd>updated</kbd> (sortiert nach der Zeit der Aktualisierung des Themas) oder <kbd>newest</kbd> (sortiert nach der Zeit der Erstellung des Themas).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Speichert die Sortieroption in den Benutzereinstellungen, falls festgelegt.",
+ "apihelp-flow+view-topiclist-param-include-offset": "Bezieht auch das Versatzelement in die Ergebnisse mit ein.",
+ "apihelp-flow+view-topiclist-param-limit": "Anzahl der abzurufenden Themen.",
+ "apihelp-flow+view-topiclist-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
+ "apihelp-flow+view-topiclist-example-1": "Themen zu [[Talk:Sandbox]] auflisten",
+ "apihelp-flow-parsoid-utils-description": "Konvertiert Text zwischen Wikitext und HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format, aus dem Inhalte konvertiert werden.",
+ "apihelp-flow-parsoid-utils-param-to": "Format, zu dem Inhalte konvertiert werden.",
+ "apihelp-flow-parsoid-utils-param-content": "Zu konvertierender Inhalt.",
+ "apihelp-flow-parsoid-utils-param-title": "Titel der Seite. Kann nicht zusammen mit $1pageid verwendet werden.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Kennung der Seite. Kann nicht zusammen mit $1title verwendet werden.",
+ "apihelp-flow-parsoid-utils-example-1": "Wandelt den Wikitext <nowiki>'''lorem''' ''blah''</nowiki> in HTML um",
+ "apihelp-query+flowinfo-description": "Ruft Basis-Flow-Informationen über eine Seite ab.",
+ "apihelp-query+flowinfo-example-1": "Ruft Flow-Informationen über [[Talk:Sandbox]], [[Main Page]] und [[Talk:Flow]] ab",
+ "apihelp-flow+undo-edit-header-description": "Informationen beziehen, die zum Rückgängigmachen der Bearbeitung der Beschreibung nötig sind.",
+ "apihelp-flow+undo-edit-header-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
+ "apihelp-flow+undo-edit-header-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
+ "apihelp-flow+undo-edit-header-example-1": "Bezieht Informationen zum Rückgängigmachen einer Bearbeitung in der Beschreibung von [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Bezieht die zum Rückgängigmachen einer Beitragsbearbeitung nötigen Informationen.",
+ "apihelp-flow+undo-edit-post-param-postId": "Kennung des Beitrages, dessen Bearbeitung rückgängig gemacht werden soll.",
+ "apihelp-flow+undo-edit-post-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
+ "apihelp-flow+undo-edit-post-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
+ "apihelp-flow+undo-edit-post-example-1": "Bezieht Informationen zum Rückgängigmachen einer Beitragsbearbeitung in einem bestimmten Thema.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Bezieht die zum Rückgängigmachen einer Bearbeitung der Themenzusammenfassung nötigen Informationen.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Bezieht Informationen zum Rückgängigmachen einer Bearbeitung der Themenzusammenfassung eines bestimmten Themas",
+ "apierror-flow-safeallowcreationfailed": "Auf der angegebenen Seite ist Flow nicht aktiviert und safeAllowCreation schlug fehl mit der Meldung: $1",
+ "apierror-flow-notenabled": "Auf der angegebenen Seite ist Flow nicht aktiviert."
+}
diff --git a/Flow/i18n/api/diq.json b/Flow/i18n/api/diq.json
new file mode 100644
index 00000000..1ee4d719
--- /dev/null
+++ b/Flow/i18n/api/diq.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kumkumuk",
+ "Mirzali",
+ "Gırd"
+ ]
+ },
+ "apihelp-flow+edit-post-param-postId": "Kamiya mesaci",
+ "apihelp-flow+view-topic-summary-param-revId": "Şıma heruna tewr çım ra viyarnayışo peyên eno versiyon bar kerê."
+}
diff --git a/Flow/i18n/api/en.json b/Flow/i18n/api/en.json
new file mode 100644
index 00000000..ce515e77
--- /dev/null
+++ b/Flow/i18n/api/en.json
@@ -0,0 +1,145 @@
+{
+ "@metadata": {
+ "authors": [
+ "Brad Jorsch",
+ "Amir E. Aharoni",
+ "Matthew Flaschen",
+ "Matthias Mullie",
+ "Stephane Bisson",
+ "Alexander Jones",
+ "Siebrand Mazeland",
+ "Erik Bernhardson"
+ ]
+ },
+ "apihelp-flow-description": "Allows actions to be taken on Flow pages.",
+ "apihelp-flow-summary": "Allows actions to be taken on Flow pages.",
+ "apihelp-flow-param-submodule": "The Flow submodule to invoke.",
+ "apihelp-flow-param-page": "The page to take the action on.",
+ "apihelp-flow-param-token": "A token retrieved from [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Edit the description of \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Deprecated in favor of [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Deprecated in favor of [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "State to put topic in, either \"lock\" or \"unlock\".",
+ "apihelp-flow+close-open-topic-param-reason": "Reason for locking or unlocking the topic.",
+ "apihelp-flow+edit-header-description": "Edits a board description.",
+ "apihelp-flow+edit-header-summary": "Edits a board description.",
+ "apihelp-flow+edit-header-param-prev_revision": "Revision ID of the current description revision, to check for edit conflicts.",
+ "apihelp-flow+edit-header-param-content": "Content for description.",
+ "apihelp-flow+edit-header-param-format": "Format of the description (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Edit the description of [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Edits a post's content.",
+ "apihelp-flow+edit-post-summary": "Edits a post's content.",
+ "apihelp-flow+edit-post-param-postId": "Post ID.",
+ "apihelp-flow+edit-post-param-prev_revision": "Revision ID of the current post revision, to check for edit conflicts.",
+ "apihelp-flow+edit-post-param-content": "Content for post.",
+ "apihelp-flow+edit-post-param-format": "Format of the post content (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Edit a post in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edits a topic's title.",
+ "apihelp-flow+edit-title-summary": "Edits a topic's title.",
+ "apihelp-flow+edit-title-param-prev_revision": "Revision ID of the current title revision, to check for edit conflicts.",
+ "apihelp-flow+edit-title-param-content": "Content for title, in the same format allowed for edit summaries (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Edit the title of [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Edits a topic summary's content.",
+ "apihelp-flow+edit-topic-summary-summary": "Edits a topic summary's content.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Revision ID of the current topic summary revision, if any, to check for edit conflicts.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Content for the summary.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format of the summary (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Edit the summary of [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Lock or unlock a Flow topic.",
+ "apihelp-flow+lock-topic-summary": "Lock or unlock a Flow topic.",
+ "apihelp-flow+lock-topic-param-moderationState": "State to put topic in, either <kbd>lock</kbd> or <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Reason for locking or unlocking the topic. Note, the on-wiki Flow client uses \"Marked as resolved\" here, and puts optional additional information in the summary.",
+ "apihelp-flow+lock-topic-example-1": "Lock [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Moderates a Flow post.",
+ "apihelp-flow+moderate-post-summary": "Moderates a Flow post.",
+ "apihelp-flow+moderate-post-param-moderationState": "What level to moderate at.",
+ "apihelp-flow+moderate-post-param-reason": "Reason for moderation.",
+ "apihelp-flow+moderate-post-param-postId": "ID of the post to moderate.",
+ "apihelp-flow+moderate-post-example-1": "Delete a post in topic [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderates a Flow topic.",
+ "apihelp-flow+moderate-topic-summary": "Moderates a Flow topic.",
+ "apihelp-flow+moderate-topic-param-moderationState": "What level to moderate at.",
+ "apihelp-flow+moderate-topic-param-reason": "Reason for moderation.",
+ "apihelp-flow+moderate-topic-example-1": "Delete the topic [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Creates a new Flow topic on the given workflow.",
+ "apihelp-flow+new-topic-summary": "Creates a new Flow topic on the given workflow.",
+ "apihelp-flow+new-topic-param-topic": "Text for new topic title.",
+ "apihelp-flow+new-topic-param-content": "Content for the topic's initial reply.",
+ "apihelp-flow+new-topic-param-format": "Format of the new topic's initial reply (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Create a new topic on [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Replies to a post.",
+ "apihelp-flow+reply-summary": "Replies to a post.",
+ "apihelp-flow+reply-param-replyTo": "Post ID to reply to.",
+ "apihelp-flow+reply-param-content": "Content for new post.",
+ "apihelp-flow+reply-param-format": "Format of the new post (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Reply to a post in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format to return the content in.",
+ "apihelp-flow+view-header-description": "View a board description.",
+ "apihelp-flow+view-header-summary": "View a board description.",
+ "apihelp-flow+view-header-param-revId": "Load this revision, instead of the most recent.",
+ "apihelp-flow+view-header-example-1": "Fetch the description of [[Talk:Sandbox]] as wikitext",
+ "apihelp-flow+view-post-description": "View a post.",
+ "apihelp-flow+view-post-summary": "View a post.",
+ "apihelp-flow+view-post-param-postId": "ID of the post to view.",
+ "apihelp-flow+view-post-param-format": "Format to return the content in.",
+ "apihelp-flow+view-post-example-1": "Fetch the content of a post in [[Topic:S2tycnas4hcucw8w]] as wikitext",
+ "apihelp-flow+view-post-history-description": "View the revision history of a post.",
+ "apihelp-flow+view-post-history-summary": "View the revision history of a post.",
+ "apihelp-flow+view-post-history-param-postId": "ID of the post for which to view revision history.",
+ "apihelp-flow+view-post-history-param-format": "Format to return the content in.",
+ "apihelp-flow+view-post-history-example-1": "Fetch the revisions of a post in [[Topic:S2tycnas4hcucw8w]] as wikitext",
+ "apihelp-flow+view-topic-description": "View a topic.",
+ "apihelp-flow+view-topic-summary": "View a topic.",
+ "apihelp-flow+view-topic-param-format": "Format to return the content in.",
+ "apihelp-flow+view-topic-example-1": "View [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "View the revision history of a topic.",
+ "apihelp-flow+view-topic-history-summary": "View the revision history of a topic.",
+ "apihelp-flow+view-topic-history-param-format": "Format to return the content in.",
+ "apihelp-flow+view-topic-history-example-1": "View the revisions of the posts on [[Topic:S2tycnas4hcucw8w]] as wikitext",
+ "apihelp-flow+view-topic-summary-description": "View a topic summary.",
+ "apihelp-flow+view-topic-summary-summary": "View a topic summary.",
+ "apihelp-flow+view-topic-summary-param-format": "Format to return the content in.",
+ "apihelp-flow+view-topic-summary-param-revId": "Load this revision, instead of the most recent.",
+ "apihelp-flow+view-topic-summary-example-1": "View the summary for [[Topic:S2tycnas4hcucw8w]] as wikitext",
+ "apihelp-flow+view-topiclist-description": "View a list of topics.",
+ "apihelp-flow+view-topiclist-summary": "View a list of topics.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Direction to order the topics.",
+ "apihelp-flow+view-topiclist-param-sortby": "Sorting option of the topics, either <kbd>updated</kbd> (ordered by topic update time), or <kbd>newest</kbd> (ordered by topic creation time).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Save sortby option to user preferences, if set.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Offset value (in UUID format) to start fetching topics at; used only with <kbd>newest</kbd> ordering",
+ "apihelp-flow+view-topiclist-param-offset": "Offset value (as a topic update timestamp, in <code>TS_MW</code> format (<code>YYYYMMDDHHMMSS</code>)), to start fetching topics at; used only with <kbd>updated</kbd> ordering",
+ "apihelp-flow+view-topiclist-param-include-offset": "Includes the offset item in the results as well.",
+ "apihelp-flow+view-topiclist-param-limit": "Number of topics to fetch.",
+ "apihelp-flow+view-topiclist-param-toconly": "Whether to respond with only the information required for the TOC.",
+ "apihelp-flow+view-topiclist-param-format": "Format to return the content in.",
+ "apihelp-flow+view-topiclist-example-1": "List topics on [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Convert text between wikitext and HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Convert text between wikitext and HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format to convert content from.",
+ "apihelp-flow-parsoid-utils-param-to": "Format to convert content to.",
+ "apihelp-flow-parsoid-utils-param-content": "Content to be converted.",
+ "apihelp-flow-parsoid-utils-param-title": "Title of the page. Cannot be used together with $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID of the page. Cannot be used together with $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Convert wikitext <nowiki>'''lorem''' ''blah''</nowiki> to HTML",
+ "apihelp-query+flowinfo-description": "Get basic Flow information about a page.",
+ "apihelp-query+flowinfo-summary": "Get basic Flow information about a page.",
+ "apihelp-query+flowinfo-example-1": "Fetch Flow information about [[Talk:Sandbox]], [[Main Page]], and [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Retrieve information necessary to undo description edits.",
+ "apihelp-flow+undo-edit-header-summary": "Retrieve information necessary to undo description edits.",
+ "apihelp-flow+undo-edit-header-param-startId": "Revision ID to start undo at.",
+ "apihelp-flow+undo-edit-header-param-endId": "Revision ID to end undo at.",
+ "apihelp-flow+undo-edit-header-example-1": "Fetch information about undoing a description edit at [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Retrieve information necessary to undo post edit.",
+ "apihelp-flow+undo-edit-post-summary": "Retrieve information necessary to undo post edit.",
+ "apihelp-flow+undo-edit-post-param-postId": "Post ID to be undone.",
+ "apihelp-flow+undo-edit-post-param-startId": "Revision ID to start undo at.",
+ "apihelp-flow+undo-edit-post-param-endId": "Revision ID to end undo at.",
+ "apihelp-flow+undo-edit-post-example-1": "Fetch information about undoing a post edit in a specific topic.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Retrieve information necessary to undo topic summary edits.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Retrieve information necessary to undo topic summary edits.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Revision ID to start undo at.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Revision ID to end undo at.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Fetch information about undoing a topic summary edit in a specific topic",
+ "apierror-flow-safeallowcreationfailed": "Page provided does not have Flow enabled and safeAllowCreation failed with: $1",
+ "apierror-flow-notenabled": "Page provided does not have Flow enabled."
+}
diff --git a/Flow/i18n/api/es.json b/Flow/i18n/api/es.json
new file mode 100644
index 00000000..f82141a0
--- /dev/null
+++ b/Flow/i18n/api/es.json
@@ -0,0 +1,117 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ciencia Al Poder",
+ "Effy",
+ "Fitoschido",
+ "Macofe",
+ "Quiddity",
+ "Ryo567",
+ "Dgstranz"
+ ]
+ },
+ "apihelp-flow-description": "Permite realizar acciones en páginas Flows.",
+ "apihelp-flow-param-submodule": "El submódulo de Flow que se invocará.",
+ "apihelp-flow-param-page": "La página en la que tomar la acción.",
+ "apihelp-flow-example-1": "Editar la descripción de «[[Talk:Sandbox]]»",
+ "apihelp-flow+close-open-topic-description": "En desuso en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]",
+ "apihelp-flow+close-open-topic-param-moderationState": "Estado en el que poner el tema, ya sea \"lock\" (abierto) o \"unlock\" (cerrado).",
+ "apihelp-flow+close-open-topic-param-reason": "El motivo por el cual bloquear o desbloquear el tema.",
+ "apihelp-flow+edit-header-description": "Edita la descripción de un tablero.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID de revisión de la revisión actual de la descripción, para comprobar conflictos de edición.",
+ "apihelp-flow+edit-header-param-content": "Contenido para la descripción.",
+ "apihelp-flow+edit-header-param-format": "Formato de la descripción (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Editar la descripción de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Editar el contenido de una publicación.",
+ "apihelp-flow+edit-post-param-postId": "ID de la publicación.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID de revisión de la revisión actual de la publicación, para comprobar conflictos de edición.",
+ "apihelp-flow+edit-post-param-content": "Contenido para publicar.",
+ "apihelp-flow+edit-post-param-format": "Formato del contenido de la publicación (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Editar una publicación en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edita el título de un tema.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID de revisión de la revisión actual del título, para comprobar conflictos de edición.",
+ "apihelp-flow+edit-title-param-content": "Contenido para el título, en el mismo formato permitido para resúmenes de edición (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Editar el título de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Editar el contenido del resumen de un tema.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID de revisión de la revisión de la revisión actual del resumen del tema, si hubiera, para comprobar conflictos de edición.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Contenido del resumen.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formato del resumen (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Editar el resumen de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Bloquear o desbloquear un tema de Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Estado en el que poner el tema, ya sea <kbd>lock</kbd> (abierto) o <kbd>unlock</kbd> (cerrado).",
+ "apihelp-flow+lock-topic-param-reason": "El motivo por el cual bloquear o desbloquear el tema. Ten en cuenta que el cliente Flow de la wiki usa aquí «Marcado como resuelto» y, opcionalmente, añade información adicional en el resumen.",
+ "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modera una publicación de Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A qué nivel moderar.",
+ "apihelp-flow+moderate-post-param-reason": "Motivo de la moderación.",
+ "apihelp-flow+moderate-post-param-postId": "ID de la publicación a moderar.",
+ "apihelp-flow+moderate-post-example-1": "Eliminar una publicación en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modera un tema de Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A qué nivel moderar.",
+ "apihelp-flow+moderate-topic-param-reason": "Motivo de la moderación.",
+ "apihelp-flow+moderate-topic-example-1": "Eliminar el tema [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Crea un nuevo tema de Flow en el flujo de trabajo indicado.",
+ "apihelp-flow+new-topic-param-topic": "Texto para el nuevo título del tema.",
+ "apihelp-flow+new-topic-param-content": "Contenido para la respuesta inicial del tema.",
+ "apihelp-flow+new-topic-param-format": "Formato de la respuesta inicial del nuevo tema (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Crear un nuevo tema en [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Respuestas a una publicación.",
+ "apihelp-flow+reply-param-replyTo": "ID de la publicación a la que responder.",
+ "apihelp-flow+reply-param-content": "Contenido para una nueva publicación.",
+ "apihelp-flow+reply-param-format": "Formato de la publicación nueva (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Responder a una publicación en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formato en que se devolverá el contenido.",
+ "apihelp-flow+view-header-description": "Ver la descripción de un tablero.",
+ "apihelp-flow+view-header-param-revId": "Cargar esta revisión en vez de la más reciente.",
+ "apihelp-flow+view-header-example-1": "Obtener la descripción de [[Talk:Sandbox]] como wikitexto",
+ "apihelp-flow+view-post-description": "Ver una publicación.",
+ "apihelp-flow+view-post-param-postId": "Identificador de la publicación que se visualizará.",
+ "apihelp-flow+view-post-param-format": "Formato en que se devolverá el contenido.",
+ "apihelp-flow+view-post-example-1": "Obtener el contenido de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-post-history-description": "Ver el historial de revisión de una publicación.",
+ "apihelp-flow+view-post-history-param-postId": "Identificador de la publicación para el cual ver el historial de revisiones.",
+ "apihelp-flow+view-post-history-param-format": "Formato en que se devolverá el contenido.",
+ "apihelp-flow+view-post-history-example-1": "Obtener las revisiones de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-topic-description": "Ver un tema.",
+ "apihelp-flow+view-topic-param-format": "Formato en el que devolver el contenido.",
+ "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Ver el historial de revisión de un tema.",
+ "apihelp-flow+view-topic-history-param-format": "Formato en que se devolverá el contenido.",
+ "apihelp-flow+view-topic-history-example-1": "Ver las revisiones de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-topic-summary-description": "Ver el resumen de un tema.",
+ "apihelp-flow+view-topic-summary-param-format": "Formato en que se devolverá el contenido.",
+ "apihelp-flow+view-topic-summary-param-revId": "Cargar esta revisión en vez de la más reciente.",
+ "apihelp-flow+view-topic-summary-example-1": "Ver el resumen de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-topiclist-description": "Ver una lista de temas.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Dirección de ordenamiento de los temas.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opción de ordenamiento de los temas. Puede ser <kbd>updated</kbd> (ordenado por tiempo de actualización de tema), o bien <kbd>newest</kbd> (ordenado por tiempo de creación de tema).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Guardar la opción de ordenamiento en las preferencias del usuario, si se establece.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Valor de desplazmiento (en formato UUID) desde el que empezar a obtener temas; utilizado solo con el ordenamiento <kbd>más nuevos</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Valor de compensación (como un tema de actualización de sello de tiempo, en formato <code>TS_MW</code> (<code>AAAAMMDDHHMMSS</code>)), para empezar a buscar temas; usado solo con ordenamiento <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-limit": "Número de temas que se obtendrán.",
+ "apihelp-flow+view-topiclist-param-format": "Formato en el que devolver el contenido.",
+ "apihelp-flow+view-topiclist-example-1": "Lista de temas en [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Convertir texto entre wikitexto y HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formato de origen para conversión de contenido.",
+ "apihelp-flow-parsoid-utils-param-to": "Formato de destino para conversión de contenido.",
+ "apihelp-flow-parsoid-utils-param-content": "El contenido que se convertirá.",
+ "apihelp-flow-parsoid-utils-param-title": "Título de la página. No puede usarse en conjunto con $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Identificador de la página. No puede usarse en conjunto con $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Convertir wikitexto (<nowiki>'''un''' ''ejemplo''</nowiki>) en HTML",
+ "apihelp-query+flowinfo-description": "Obtener información básica de Flow acerca de una página.",
+ "apihelp-query+flowinfo-example-1": "Obtener información de Flow sobre [[Talk:Sandbox]], [[Main Page]] y [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Obtener la información necesaria para deshacer ediciones de descripciones.",
+ "apihelp-flow+undo-edit-header-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
+ "apihelp-flow+undo-edit-header-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
+ "apihelp-flow+undo-edit-header-example-1": "Obtener información sobre deshacer una edición de descripción en [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Obtener la información necesaria para deshacer ediciones de publicaciones.",
+ "apihelp-flow+undo-edit-post-param-postId": "Identificador de publicación para deshacer.",
+ "apihelp-flow+undo-edit-post-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
+ "apihelp-flow+undo-edit-post-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
+ "apihelp-flow+undo-edit-post-example-1": "Obtener información acerca de cómo deshacer una edición de publicación en un tema específico.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Recuperar información necesaria para deshacer las ediciones del resumen de este tema.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Obtener información acerca de cómo deshacer una edición de resumen en un tema específico.",
+ "apierror-flow-notenabled": "La página proporcionada no tiene habilitado Flow."
+}
diff --git a/Flow/i18n/api/eu.json b/Flow/i18n/api/eu.json
new file mode 100644
index 00000000..bcc3690e
--- /dev/null
+++ b/Flow/i18n/api/eu.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Subi",
+ "Mikel Ibaiba"
+ ]
+ },
+ "apihelp-flow+edit-topic-summary-param-summary": "Laburpenaren edukia.",
+ "apihelp-flow+edit-topic-summary-param-format": "Laburpaneren formatua (wikitestua|html)",
+ "apihelp-flow+undo-edit-post-description": "Editatzen ari zaren argitalpena desegiteko beharrezkoa den informazioa berriro lortu behar da.",
+ "apihelp-flow+undo-edit-post-summary": "Editatzen ari zaren argitalpena desegiteko beharrezkoa den informazioa berriro lortu behar da."
+}
diff --git a/Flow/i18n/api/fa.json b/Flow/i18n/api/fa.json
new file mode 100644
index 00000000..03c6776b
--- /dev/null
+++ b/Flow/i18n/api/fa.json
@@ -0,0 +1,47 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dalba",
+ "Ladsgroup",
+ "Mjbmr",
+ "Quiddity",
+ "Huji"
+ ]
+ },
+ "apihelp-flow-param-page": "صفحهٔ موضوع عمل.",
+ "apihelp-flow-param-token": "بلیطی که از [[Special:ApiHelp/query+tokens|action=query&meta=tokens]] دریافت شده",
+ "apihelp-flow-example-1": "ویرایش توضیحات \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-param-reason": "دلیل برای قفل کردن یا باز کردن مبحث.",
+ "apihelp-flow+edit-header-description": "توضیحات یک تالار را ویرایش می‌کند.",
+ "apihelp-flow+edit-header-param-prev_revision": "شناسهٔ نسخهٔ فعلی توضیحات، برای بررسی تعارض ویرایشی.",
+ "apihelp-flow+edit-header-param-content": "محتوا برای توضیحات",
+ "apihelp-flow+edit-header-param-format": "قالب توضیحات (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "ویرایش توضیحات [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "ویرایش محتوای یک ارسال.",
+ "apihelp-flow+edit-post-param-postId": "شناسهٔ ارسال.",
+ "apihelp-flow+edit-post-param-prev_revision": "شناسهٔ نسخهٔ فعلی ارسال، برای بررسی تعارض ویرایشی.",
+ "apihelp-flow+edit-post-param-content": "محتوا برای ارسال.",
+ "apihelp-flow+edit-post-param-format": "قالب محتوای ارسال (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "ویرایش یک ارسال در [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "ویرایش عنوان یک مبحث.",
+ "apihelp-flow+edit-title-param-prev_revision": "شناسهٔ نسخهٔ فعلی عنوان، برای بررسی تعارض ویرایشی.",
+ "apihelp-flow+edit-title-param-content": "محتوا برای عنوان، در همان قالب مجاز برای خلاصه ویرایش‌های (topic-title-wikitext)",
+ "apihelp-flow+edit-title-example-1": "ویرایش عنوان [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "ویرایش محتوای جمع‌بندی یک مبحث.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "شناسهٔ نسخهٔ فعلی جمع‌بندی، در صورت وجود، برای بررسی تعارض ویرایشی.",
+ "apihelp-flow+edit-topic-summary-param-summary": "محتوا برای جمع‌بندی.",
+ "apihelp-flow+edit-topic-summary-param-format": "قالب جمع‌بندی (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "ویرایش جمع‌بندی [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-example-1": "قفل [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-param-topic": "متن برای عنوان مبحث جدید.",
+ "apihelp-flow+reply-description": "پاسخ‌ها به یک ارسال.",
+ "apihelp-flow+reply-param-replyTo": "شناسهٔ ارسال برای پاسخ دادن.",
+ "apihelp-flow+reply-param-content": "متن یک ارسال جدید.",
+ "apihelp-flow+reply-param-format": "قالب ارسال جدید (wikitext|html)",
+ "apihelp-flow+view-post-description": "مشاهدهٔ ارسال.",
+ "apihelp-flow+view-post-param-postId": "شناسهٔ ارسال برای مشاهده.",
+ "apihelp-flow+view-topic-description": "مشاهدهٔ مبحث.",
+ "apihelp-flow+view-topiclist-description": "مشاهده فهرستی از مبحث‌ها.",
+ "apihelp-flow+view-topiclist-param-limit": "تعداد مبحث‌ها برای گرفتن.",
+ "apihelp-flow-parsoid-utils-example-1": "تبدیل ویکی‌متن <nowiki>'''فلان''' و ''بهمان''</nowiki> به HTML"
+}
diff --git a/Flow/i18n/api/fi.json b/Flow/i18n/api/fi.json
new file mode 100644
index 00000000..2d833c99
--- /dev/null
+++ b/Flow/i18n/api/fi.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Olimar",
+ "Quiddity"
+ ]
+ },
+ "apihelp-flow+close-open-topic-param-reason": "Syy aiheen lukitsemiselle tai avaamiselle lukituksesta.",
+ "apihelp-flow+edit-header-description": "Muokkaa palstan kuvausta.",
+ "apihelp-flow+edit-header-param-format": "Kuvauksen formaatti (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Muokkaa sivun [[Talk:Sandbox]] kuvausta",
+ "apihelp-flow+edit-post-description": "Muokkaa viestin sisältöä.",
+ "apihelp-flow+edit-post-param-postId": "Viestin tunniste.",
+ "apihelp-flow+edit-post-param-prev_revision": "Nykyisen viestiversion versiotunniste päällekkäisten muokkausten tarkistamiseksi.",
+ "apihelp-flow+edit-post-param-content": "Viestin sisältö.",
+ "apihelp-flow+edit-post-param-format": "Viestin sisällön formaatti (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Muokkaa viestiä aiheessa [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Muokkaa aiheen otsikkoa.",
+ "apihelp-flow+lock-topic-description": "Lukitse tai avaa Flow-aihe.",
+ "apihelp-flow+moderate-post-description": "Hallinnoi Flow-viestiä.",
+ "apihelp-flow+moderate-topic-example-1": "Poista aihe [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Luo uuden Flow-aiheen annettuun workflow'hun.",
+ "apihelp-flow+new-topic-param-topic": "Uuden aiheotsikon teksti.",
+ "apihelp-flow+new-topic-param-content": "Aiheen ensimmäisen vastauksen sisältö.",
+ "apihelp-flow+view-post-description": "Näytä viesti.",
+ "apihelp-flow+view-topic-description": "Näytä aihe.",
+ "apihelp-flow+view-topic-example-1": "Näytä [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Näytä aiheen versiohistoria.",
+ "apihelp-flow+view-topic-summary-description": "Näytä aiheen yhteenveto.",
+ "apihelp-flow+view-topic-summary-param-revId": "Lataa tämä versio uusimman sijasta.",
+ "apihelp-flow+view-topiclist-description": "Näytä luettelo aiheista."
+}
diff --git a/Flow/i18n/api/fr.json b/Flow/i18n/api/fr.json
new file mode 100644
index 00000000..e3902287
--- /dev/null
+++ b/Flow/i18n/api/fr.json
@@ -0,0 +1,150 @@
+{
+ "@metadata": {
+ "authors": [
+ "0x010C",
+ "Gomoko",
+ "MPlauche",
+ "Nclm",
+ "Nicolapps",
+ "Nnemo",
+ "Orlodrim",
+ "PifyZ",
+ "Quiddity",
+ "Trizek",
+ "Wladek92",
+ "Urhixidur",
+ "Thibaut120094"
+ ]
+ },
+ "apihelp-flow-description": "Permet d’effectuer des actions sur les pages Flow.",
+ "apihelp-flow-summary": "Autoriser la prise d'actions sur les pages Flow.",
+ "apihelp-flow-param-submodule": "Le sous-module Flow à invoquer.",
+ "apihelp-flow-param-page": "La page sur laquelle effectuer l’action.",
+ "apihelp-flow-param-token": "Un jeton obtenu via [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Modifier la description de « [[Talk:Sandbox]] »",
+ "apihelp-flow+close-open-topic-description": "Rendu désuet par [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Obsolète, remplacé par [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "État dans lequel mettre le sujet, « lock » ou « unlock ».",
+ "apihelp-flow+close-open-topic-param-reason": "Motif pour verrouiller ou déverrouiller ce sujet.",
+ "apihelp-flow+edit-header-description": "Modifie la description d’un flux de discussion.",
+ "apihelp-flow+edit-header-summary": "Modifier la description d'un tableau.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID de la révision actuelle de la description, pour vérifier qu’il n’existe aucun conflit de modification.",
+ "apihelp-flow+edit-header-param-content": "Le contenu de la description.",
+ "apihelp-flow+edit-header-param-format": "Le format de la description (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Modifier la description de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Modifier le contenu d’un message.",
+ "apihelp-flow+edit-post-summary": "Modifier le contenu d'un billet.",
+ "apihelp-flow+edit-post-param-postId": "ID du message.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID de la révision actuelle du message, pour vérifier les conflits de modification.",
+ "apihelp-flow+edit-post-param-content": "Contenu pour le message.",
+ "apihelp-flow+edit-post-param-format": "Format du contenu du message (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Modifier un message dans [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Modifie un titre de sujet.",
+ "apihelp-flow+edit-title-summary": "Modifier le titre d'un article.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID de la révision actuelle du titre, pour vérifier les conflits de modification.",
+ "apihelp-flow+edit-title-param-content": "Contenu pour le titre, dans le format autorisé pour la modification de résumés (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Modifier le titre de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Modifie le contenu du résumé d’un sujet.",
+ "apihelp-flow+edit-topic-summary-summary": "Modifie le contenu du résumé d'un article.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID de la révision du résumé de sujet courant, s’il existe, pour vérifier les conflits de modification.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Contenu du résumé.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format du résumé (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Modifier le résumé de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Verrouiller ou déverrouiller un sujet Flow.",
+ "apihelp-flow+lock-topic-summary": "Bloquer ou débloquer un sujet Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "État dans lequel mettre le sujet, soit <kbd>lock</kbd> (verrouillé), soit <kbd>unlock</kbd> (déverrouillé).",
+ "apihelp-flow+lock-topic-param-reason": "Motif pour verrouiller ou déverrouiller le sujet. Note : le client Flow de l’interface graphique utilise « Marqué comme résolu » ici, et met des informations complémentaires facultatives dans le résumé.",
+ "apihelp-flow+lock-topic-example-1": "Verrouiller [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modère un message Flow",
+ "apihelp-flow+moderate-post-summary": "Surveille un billet Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "À quel niveau modérer.",
+ "apihelp-flow+moderate-post-param-reason": "Motif de modération.",
+ "apihelp-flow+moderate-post-param-postId": "ID du message à modérer.",
+ "apihelp-flow+moderate-post-example-1": "Supprimer un message du sujet [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modère un sujet Flow",
+ "apihelp-flow+moderate-topic-summary": "Surveille un article Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "À quel niveau modérer.",
+ "apihelp-flow+moderate-topic-param-reason": "Raison de la modération.",
+ "apihelp-flow+moderate-topic-example-1": "Supprimer le sujet [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Crée un nouveau sujet Flow sur un flux de travail.",
+ "apihelp-flow+new-topic-summary": "Crée un nouveau sujet de Flow sur le flux de travail donné.",
+ "apihelp-flow+new-topic-param-topic": "Texte du titre du nouveau sujet.",
+ "apihelp-flow+new-topic-param-content": "Contenu pour la réponse initiale du sujet.",
+ "apihelp-flow+new-topic-param-format": "Format de la nouvelle réponse initiale au sujet (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Créer un nouveau sujet sur [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Répond à un message.",
+ "apihelp-flow+reply-summary": "Répond à un billet.",
+ "apihelp-flow+reply-param-replyTo": "ID du message auquel répondre.",
+ "apihelp-flow+reply-param-content": "Contenu pour le nouveau message.",
+ "apihelp-flow+reply-param-format": "Format du nouveau message (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Répondre à un message sur [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-header-description": "Afficher la description d'un flux de discussion.",
+ "apihelp-flow+view-header-summary": "Afficher la description d'un flux de discussion.",
+ "apihelp-flow+view-header-param-revId": "Charger cette révision, au lieu de la plus récente.",
+ "apihelp-flow+view-header-example-1": "Récupérer la description de [[Talk:Sandbox]] en wikitexte",
+ "apihelp-flow+view-post-description": "Afficher un message.",
+ "apihelp-flow+view-post-summary": "Afficher un billet.",
+ "apihelp-flow+view-post-param-postId": "ID du message à voir.",
+ "apihelp-flow+view-post-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-post-example-1": "Récupérer le contenu du message sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
+ "apihelp-flow+view-post-history-description": "Afficher l’historique des révisions d’une note.",
+ "apihelp-flow+view-post-history-summary": "Afficher l’historique des révisions d’une note.",
+ "apihelp-flow+view-post-history-param-postId": "ID du message pour lequel afficher l’historique de révisions.",
+ "apihelp-flow+view-post-history-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-post-history-example-1": "Récupérer les révisions d’une note sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
+ "apihelp-flow+view-topic-description": "Afficher un sujet.",
+ "apihelp-flow+view-topic-summary": "Afficher un sujet.",
+ "apihelp-flow+view-topic-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-topic-example-1": "Afficher [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Afficher l’historique des révisions d’un sujet.",
+ "apihelp-flow+view-topic-history-summary": "Afficher l’historique des révisions d’un sujet.",
+ "apihelp-flow+view-topic-history-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-topic-history-example-1": "Afficher les révisions des notes sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
+ "apihelp-flow+view-topic-summary-description": "Afficher un résumé du sujet.",
+ "apihelp-flow+view-topic-summary-summary": "Afficher un résumé d'article.",
+ "apihelp-flow+view-topic-summary-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-topic-summary-param-revId": "Charger cette révision, plutôt que la plus récente.",
+ "apihelp-flow+view-topic-summary-example-1": "Afficher le résumé pour [[Topic:S2tycnas4hcucw8w]] en wikitexte",
+ "apihelp-flow+view-topiclist-description": "Afficher une liste de sujets.",
+ "apihelp-flow+view-topiclist-summary": "Afficher une liste de sujets.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Direction de tri des sujets.",
+ "apihelp-flow+view-topiclist-param-sortby": "Option de tri des sujets, soit <kbd>updated</kbd> (rangés selon la date de mise à jour du sujet), ou <kbd>newest</kbd> (ordonnés selon la date de création du sujet).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Enregistrer l’option de tri dans les préférences utilisateur, si elle est définie.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Valeur de décalage (au format UUID) auquel démarrer la récupération des sujets ; utilisé seulement avec le tri <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Valeur du décalage (un horodatage de la mise à jour du sujet, au format <code>TS_MW</code>(<code>AAAAMMJJHHMMSS</code>)), auquel démarrer la récupération des sujets ; utilisé seulement avec le tri <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Inclut également l’élément correspondant au paramètre offset dans les résultats.",
+ "apihelp-flow+view-topiclist-param-limit": "Nombre de sujets à récupérer.",
+ "apihelp-flow+view-topiclist-param-toconly": "Indique s’il ne faut renvoyer que les informations nécessaires pour afficher le sommaire.",
+ "apihelp-flow+view-topiclist-param-format": "Format dans lequel renvoyer le contenu.",
+ "apihelp-flow+view-topiclist-example-1": "Lister les sujets sur [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Convertir le texte entre wikitexte et HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Conversion de texte entre du source wiki et du HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format du contenu à convertir.",
+ "apihelp-flow-parsoid-utils-param-to": "Format dans lequel convertir le contenu.",
+ "apihelp-flow-parsoid-utils-param-content": "Contenu à convertir.",
+ "apihelp-flow-parsoid-utils-param-title": "Titre de la page. Impossible à utiliser avec $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID de la page. Impossible à utiliser avec $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Convertir le wikicode <nowiki>'''lorem''' ''blah''</nowiki> en HTML",
+ "apihelp-query+flowinfo-description": "Obtenir les informations Flow de base sur une page.",
+ "apihelp-query+flowinfo-summary": "Obtenir les informations Flow de base sur une page.",
+ "apihelp-query+flowinfo-example-1": "Récupérer les informations Flow sur [[Talk:Sandbox]], [[Main Page]], et [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Récupérer les informations nécessaires pour annuler les modifications de la description.",
+ "apihelp-flow+undo-edit-header-summary": "Récupérer les informations nécessaires pour annuler les modifications de la description.",
+ "apihelp-flow+undo-edit-header-param-startId": "Id de révision à partir duquel démarrer l’annulation.",
+ "apihelp-flow+undo-edit-header-param-endId": "Id de révision auquel arrêter l’annulation.",
+ "apihelp-flow+undo-edit-header-example-1": "Récupérer l’information sur l’annulation d’une modification de description sur [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Récupérer l’information nécessaire pour annuler la modification du message.",
+ "apihelp-flow+undo-edit-post-summary": "Récupérer les informations nécessaires à l'annulation de la modification d'un billet.",
+ "apihelp-flow+undo-edit-post-param-postId": "Id du message à annuler.",
+ "apihelp-flow+undo-edit-post-param-startId": "Id de révision à partir duquel commencer l’annulation.",
+ "apihelp-flow+undo-edit-post-param-endId": "Id de révision auquel arrêter l’annulation.",
+ "apihelp-flow+undo-edit-post-example-1": "Récupérer l’information sur l’annulation d’une modification de message dans un sujet spécifique.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Récupérer l’information nécessaire pour annuler les modifications de résumé de sujet.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Récupérer l’information nécessaire pour annuler les modifications de résumé de sujet.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Id de révision auquel commencer l’annulation.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Id de révision auquel arrêter l’annulation.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Récupérer les informations sur l’annulation de la modification d’un résumé de sujet dans un sujet spécifique",
+ "apierror-flow-safeallowcreationfailed": "La page fournie n’a pas Flow activé, et safeAllowCreation a échoué avec : $1",
+ "apierror-flow-notenabled": "La page fournie n'a pas activé Flow."
+}
diff --git a/Flow/i18n/api/gl.json b/Flow/i18n/api/gl.json
new file mode 100644
index 00000000..4bd4b408
--- /dev/null
+++ b/Flow/i18n/api/gl.json
@@ -0,0 +1,140 @@
+{
+ "@metadata": {
+ "authors": [
+ "Elisardojm",
+ "Quiddity",
+ "Toliño"
+ ]
+ },
+ "apihelp-flow-description": "Permitir accións a ser realizadas nas páxinas de Flow.",
+ "apihelp-flow-summary": "Permitir accións a ser realizadas nas páxinas de Flow.",
+ "apihelp-flow-param-submodule": "Submódulo do Flow a invocar.",
+ "apihelp-flow-param-page": "Páxina sobre a que se realizará a acción.",
+ "apihelp-flow-param-token": "Un identificador recuperado por [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Editar a descrición de \"[[Talk:Sandbox]]\".",
+ "apihelp-flow+close-open-topic-description": "Obsoleto en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Obsoleto en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Estado no que deixar o tema, \"bloqueado\" ou \"desbloqueado\".",
+ "apihelp-flow+close-open-topic-param-reason": "Motivo para bloquear ou desbloquear o tema.",
+ "apihelp-flow+edit-header-description": "Editar a descrición dun taboleiro de conversa.",
+ "apihelp-flow+edit-header-summary": "Editar a descrición dun taboleiro de conversa.",
+ "apihelp-flow+edit-header-param-prev_revision": "Identificador da revisión actual da descrición, para comprobar conflitos de edición.",
+ "apihelp-flow+edit-header-param-content": "Contido da descrición.",
+ "apihelp-flow+edit-header-param-format": "Formato da descrición (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Editar a descrición de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Cambiar o contido dunha mensaxe.",
+ "apihelp-flow+edit-post-summary": "Cambiar o contido dunha mensaxe.",
+ "apihelp-flow+edit-post-param-postId": "Identificador da mensaxe.",
+ "apihelp-flow+edit-post-param-prev_revision": "Identificador da revisión actual da mensaxe, para comprobar conflitos de edición.",
+ "apihelp-flow+edit-post-param-content": "Contido para a mensaxe.",
+ "apihelp-flow+edit-post-param-format": "Formato do contido da mensaxe (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Editar unha mensaxe en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edita o título dun tema.",
+ "apihelp-flow+edit-title-summary": "Edita o título dun tema.",
+ "apihelp-flow+edit-title-param-prev_revision": "Identificador da revisión actual do título, para comprobar conflitos de edición.",
+ "apihelp-flow+edit-title-param-content": "Contido para o título, no mesmo formato permitido para editar resumos (tema-título-wikitexto).",
+ "apihelp-flow+edit-title-example-1": "Editar o título de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Editar o contido do resumo dun tema.",
+ "apihelp-flow+edit-topic-summary-summary": "Editar o contido do resumo dun tema.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Identificador da revisión actual do resumo do tema, se hai, para comprobar conflitos de edición.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Contido para o resumo.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formato do resumo (wikitexto|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Editar o resumo de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Bloquear ou desbloquear un tema do Flow.",
+ "apihelp-flow+lock-topic-summary": "Bloquear ou desbloquear un tema do Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Estado no que deixar o tema, <kbd>bloqueado</kbd>ou <kbd>desbloqueado</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Motivo para bloquear ou desbloquear o tema. Teña en conta que o cliente Flow da wiki usa aquí \"Marcado como resolto\" e, opcionalmente, engade información adicional no resumo.",
+ "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Moderar unha mensaxe Flow.",
+ "apihelp-flow+moderate-post-summary": "Moderar unha mensaxe Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A que nivel moderar.",
+ "apihelp-flow+moderate-post-param-reason": "Motivo da moderación.",
+ "apihelp-flow+moderate-post-param-postId": "Identificador da mensaxe a moderar.",
+ "apihelp-flow+moderate-post-example-1": "Borrar unha mensaxe no tema [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderar un tema Flow.",
+ "apihelp-flow+moderate-topic-summary": "Moderar un tema Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A que nivel moderar.",
+ "apihelp-flow+moderate-topic-param-reason": "Motivo da moderación.",
+ "apihelp-flow+moderate-topic-example-1": "Borrar o tema [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Crear un novo tema de Flow no fluxo de traballo indicado.",
+ "apihelp-flow+new-topic-summary": "Crear un novo tema de Flow no fluxo de traballo indicado.",
+ "apihelp-flow+new-topic-param-topic": "Texto para o novo título de tema.",
+ "apihelp-flow+new-topic-param-content": "Contido para a resposta inicial do tema.",
+ "apihelp-flow+new-topic-param-format": "Formato da resposta inicial do novo tema (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Crear un novo tema en [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Responder a unha mensaxe.",
+ "apihelp-flow+reply-summary": "Responder a unha mensaxe.",
+ "apihelp-flow+reply-param-replyTo": "Identificador da mensaxe á que responder.",
+ "apihelp-flow+reply-param-content": "Contido para a nova mensaxe.",
+ "apihelp-flow+reply-param-format": "Formato da nova mensaxe (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Responder a unha mensaxe en [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-header-description": "Ver a descrición dun taboleiro de conversas.",
+ "apihelp-flow+view-header-summary": "Ver a descrición dun taboleiro de conversas.",
+ "apihelp-flow+view-header-param-revId": "Cargar esta revisión, no canto da máis recente.",
+ "apihelp-flow+view-header-example-1": "Buscar a descrición de [[Talk:Sandbox]] como wikitexto",
+ "apihelp-flow+view-post-description": "Ver unha mensaxe.",
+ "apihelp-flow+view-post-summary": "Ver unha mensaxe.",
+ "apihelp-flow+view-post-param-postId": "Identificador da mensaxe a visualizar.",
+ "apihelp-flow+view-post-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-post-example-1": "Obter o contido dunha mensaxe en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-post-history-description": "Ollar o historial de revisións dunha publicación.",
+ "apihelp-flow+view-post-history-summary": "Ollar o historial de revisións dunha publicación.",
+ "apihelp-flow+view-post-history-param-postId": "Identificador da publicación da que ver o historial de revisións.",
+ "apihelp-flow+view-post-history-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-post-history-example-1": "Obter as revisións dunha publicación en [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-topic-description": "Ver un tema.",
+ "apihelp-flow+view-topic-summary": "Ver un tema.",
+ "apihelp-flow+view-topic-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Ollar o historial de revisións dun tema.",
+ "apihelp-flow+view-topic-history-summary": "Ollar o historial de revisións dun tema.",
+ "apihelp-flow+view-topic-history-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-topic-history-example-1": "Obter as revisións das publicacións en [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-topic-summary-description": "Ver o resumo dun tema.",
+ "apihelp-flow+view-topic-summary-summary": "Ver o resumo dun tema.",
+ "apihelp-flow+view-topic-summary-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-topic-summary-param-revId": "Cargar esta revisión, no canto da máis recente.",
+ "apihelp-flow+view-topic-summary-example-1": "Visualizar o resumo de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
+ "apihelp-flow+view-topiclist-description": "Ver a lista de temas.",
+ "apihelp-flow+view-topiclist-summary": "Ver a lista de temas.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Dirección na que ordenar os temas.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opción de ordenación dos temas, <kbd>actualización</kbd> (ordenados por hora de actualización do tema), ou <kbd>máis novo</kbd> (ordenados por hora de creación do tema).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Gardar a opción de ordenación nas preferencias do usuario, se está definida.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Valor inicial (en formato UUID) para a obtención de temas, só usado con ordenación <kbd>máis novo</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Valor inicial (selo de tempo do tema, en formato <code>TS_MW</code> (<code>AAAAMMDDHHMMSS</code>)) para a obtención de temas, só usado coa ordenación <kbd>actualización</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Inclúe o desprazamento do elemento dentro dos resultados.",
+ "apihelp-flow+view-topiclist-param-limit": "Número de temas a obter.",
+ "apihelp-flow+view-topiclist-param-toconly": "Se responder só coa información necesaria para crear o sumario.",
+ "apihelp-flow+view-topiclist-param-format": "Formato no que devolver o contido.",
+ "apihelp-flow+view-topiclist-example-1": "Lista de temas en [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Converter texto entre wikitexto e HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Converter texto entre wikitexto e HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formato do contido a converter.",
+ "apihelp-flow-parsoid-utils-param-to": "Formato ó que converter o contido.",
+ "apihelp-flow-parsoid-utils-param-content": "Contido a converter.",
+ "apihelp-flow-parsoid-utils-param-title": "Título da páxina Non pode usarse xunto con $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Identificador da páxina. Non pode usarse xunto con $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Converter wikitexto <nowiki>'''lorem''' ''blá''</nowiki> a HTML",
+ "apihelp-query+flowinfo-description": "Obter información básica de Flow sobre unha páxina.",
+ "apihelp-query+flowinfo-summary": "Obter información básica de Flow sobre unha páxina.",
+ "apihelp-query+flowinfo-example-1": "Obter información de Flow sobre [[Talk:Sandbox]], [[Main Page]], e [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Obter a información necesaria para desfacer edicións de descricións.",
+ "apihelp-flow+undo-edit-header-summary": "Obter a información necesaria para desfacer edicións de descricións.",
+ "apihelp-flow+undo-edit-header-param-startId": "Identificador de revisión no que comezar a desfacer.",
+ "apihelp-flow+undo-edit-header-param-endId": "Identificador de revisión no que rematar de desfacer.",
+ "apihelp-flow+undo-edit-header-example-1": "Recuperar información sobre desfacer unha modificación da descrición en [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Obter a información necesaria para desfacer a edición dunha mensaxe.",
+ "apihelp-flow+undo-edit-post-summary": "Obter a información necesaria para desfacer a edición dunha mensaxe.",
+ "apihelp-flow+undo-edit-post-param-postId": "Identificador de mensaxe a desfacer.",
+ "apihelp-flow+undo-edit-post-param-startId": "Identificador de revisión no que comezar a desfacer.",
+ "apihelp-flow+undo-edit-post-param-endId": "Identificador de revisión no que rematar de desfacer.",
+ "apihelp-flow+undo-edit-post-example-1": "Obter información sobre como desfacer unha edición nunha mensaxe nun tema específico.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Obter a información necesaria para desfacer a edición dun resumo de tema.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Obter a información necesaria para desfacer a edición dun resumo de tema.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Identificador de revisión no que comezar a desfacer.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Identificador de revisión no que rematar de desfacer.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Obter información sobre como desfacer unha edición nun resumo de tema nun tema específico.",
+ "apierror-flow-safeallowcreationfailed": "A páxina proporcionada non ten activado o Flow e safeAllowCreation deu o erro: $1",
+ "apierror-flow-notenabled": "A páxina proporcionada non ten activo Flow."
+}
diff --git a/Flow/i18n/api/gom-latn.json b/Flow/i18n/api/gom-latn.json
new file mode 100644
index 00000000..6c133f66
--- /dev/null
+++ b/Flow/i18n/api/gom-latn.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "The Discoverer"
+ ]
+ },
+ "apihelp-flow-example-1": "\"[[Talk:Sandbox]]\" acho vornon bodol",
+ "apihelp-flow+edit-header-description": "Folleachem vornon bodol.",
+ "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]] achem vornon bodol",
+ "apihelp-flow+edit-post-example-1": "[[Topic:S2tycnas4hcucw8w]] hantun ek prokasnni bodol",
+ "apihelp-flow+edit-title-description": "Vixoiachem nanv bodol.",
+ "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]] hachem nanv bodol",
+ "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] hacho sar bodol",
+ "apihelp-flow+moderate-post-example-1": "[[Topic:S2tycnas4hcucw8w]] hea vixoiant ek prokasnni kadun udoi",
+ "apihelp-flow+moderate-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] ho vixoi kadun udoi",
+ "apihelp-flow+new-topic-param-topic": "Novea vixoiachem nanv.",
+ "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]]-acher novem vixoi roch",
+ "apihelp-flow+reply-description": "Prokasnniek zobab dita.",
+ "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]] hea vixoiant eke prokasnniek zobab di",
+ "apihelp-flow+view-header-description": "Folleachem vornon polloi.",
+ "apihelp-flow+view-post-description": "Prokasnni polloi.",
+ "apihelp-flow+view-post-history-description": "Eke prokasnniechi uzollniechi itihas polloi.",
+ "apihelp-flow+view-topic-description": "Vixoi polloi.",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] polloi",
+ "apihelp-flow+view-topic-history-description": "Vixoiache uzollniecho itihas polloi.",
+ "apihelp-flow+view-topic-history-example-1": "[[Topic:S2tycnas4hcucw8w]] hacher aslele prokasnnieche uzollnio wikimozkur rupant polloi",
+ "apihelp-flow+view-topic-summary-description": "Eke vixoiachem sar polloi.",
+ "apihelp-flow+view-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] hachem sar wikimozkur rupan polloi",
+ "apihelp-flow+view-topiclist-description": "Vixoianchi suchi polloi."
+}
diff --git a/Flow/i18n/api/he.json b/Flow/i18n/api/he.json
new file mode 100644
index 00000000..09689263
--- /dev/null
+++ b/Flow/i18n/api/he.json
@@ -0,0 +1,124 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Danny-w",
+ "המקיסט"
+ ]
+ },
+ "apihelp-flow-description": "מאפשר ביצוע פעולות על דפים זרימה.",
+ "apihelp-flow-param-submodule": "איזה תת-מודול של זרימה להפעיל.",
+ "apihelp-flow-param-page": "באיזה דף ברצונך לפעול.",
+ "apihelp-flow-param-token": "אוחזר אסימון מ־[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "עריכת התיאור של \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "הוכרז המיושן לטובת [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "באיזה מצב לשים את הנושא, \"lock\" או \"unlock\".",
+ "apihelp-flow+close-open-topic-param-reason": "סיבה לנעילה או פתיחת נעילה של נושא.",
+ "apihelp-flow+edit-header-description": "עריכת תיאור לוח.",
+ "apihelp-flow+edit-header-summary": "עורך תיאור לוח",
+ "apihelp-flow+edit-header-param-prev_revision": "מזהה הגרסה של גרסת התיאור הנוכחית, כדי לבדוק אם יש התנגשויות עריכה.",
+ "apihelp-flow+edit-header-param-content": "תוכן לתיאור",
+ "apihelp-flow+edit-header-param-format": "תסדיר התיאור (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "עריכת התיאור של [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "עריכת תוכן של רשומה.",
+ "apihelp-flow+edit-post-param-postId": "מזהה רשומה.",
+ "apihelp-flow+edit-post-param-prev_revision": "מזהה הגרסה של גרסת הרשומה הנוכחית, כדי לבדוק אם יש התנגשויות עריכה.",
+ "apihelp-flow+edit-post-param-content": "תוכן לרשומה.",
+ "apihelp-flow+edit-post-param-format": "תסדיר תוכן הרשומה (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "עריכת רשומה ב־[[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "עריכת כותרת של נושא",
+ "apihelp-flow+edit-title-param-prev_revision": "מזהה גרסה של גרסת הכותרת הנוכחית, כדי לבדוק התנגשויות עריכה.",
+ "apihelp-flow+edit-title-param-content": "תוכן לכותרת, באותו התסדיר שמותר עבור תקצירי עריכה.",
+ "apihelp-flow+edit-title-example-1": "עריכת הכותרת של [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "עריכת תוכן סיכום נושא",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "מזהה גרסה של הגרסה הנוכחית של סיכום הנושא, אם יש כזה, כדי לבדוק התנגשויות עריכה.",
+ "apihelp-flow+edit-topic-summary-param-summary": "תוכן הסיכום.",
+ "apihelp-flow+edit-topic-summary-param-format": "תסדיר הסיכום (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "עריכת הסיכום של [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "נעילה או פתיחת נעילה של נושא בזרימה.",
+ "apihelp-flow+lock-topic-param-moderationState": "באיזה מצב לשים את הנושא, <kbd>lock</kbd> או לא <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "סיבה לנעילה או פתיחת נעילה של נושא. שימו לב שלקוח זרימה קורא לזה \"סימון בתור פתור\" ומוסיף מידע לסיכום.",
+ "apihelp-flow+lock-topic-example-1": "נעילת [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "פיקוח על רשומת זרימה.",
+ "apihelp-flow+moderate-post-param-moderationState": "באיזו רמה לפקח.",
+ "apihelp-flow+moderate-post-param-reason": "סיבה לפיקוח.",
+ "apihelp-flow+moderate-post-param-postId": "מזהה הרשומה שצריך לפקח עליה.",
+ "apihelp-flow+moderate-post-example-1": "מחיקת רשומה בנושא [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "פיקוח על נושא בזרימה.",
+ "apihelp-flow+moderate-topic-param-moderationState": "באיזו רמה לפקח.",
+ "apihelp-flow+moderate-topic-param-reason": "סיבה לפיקוח.",
+ "apihelp-flow+moderate-topic-example-1": "מחיקת הנושה [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "יצירת נושא זרימה חדש בזרם עבודה נתון.",
+ "apihelp-flow+new-topic-param-topic": "טקסט לכותרת הנושא החדש.",
+ "apihelp-flow+new-topic-param-content": "תוכן לתגובה ההתחלתית בנושא.",
+ "apihelp-flow+new-topic-param-format": "תסדיר לתגובה ההתחלתית בנושא החדש (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "יצירת נושא חדש ב־[[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "תגובות לרשומה.",
+ "apihelp-flow+reply-summary": "הגב להודעה",
+ "apihelp-flow+reply-param-replyTo": "המזהה של הרשומה שצריך להשיב עליה.",
+ "apihelp-flow+reply-param-content": "תוכן לרשומה החדשה.",
+ "apihelp-flow+reply-param-format": "תסדיר לרשומה החדשה (wikitext|html)",
+ "apihelp-flow+reply-example-1": "תגובה לרשומה ב־[[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-header-description": "הצגת תיאור הלוח.",
+ "apihelp-flow+view-header-summary": "הצג תיאור לוח",
+ "apihelp-flow+view-header-param-revId": "טעינת הגרסה הזאת, ולא האחרונה.",
+ "apihelp-flow+view-header-example-1": "אחזור התיאור של [[Talk:Sandbox]] בתור קוד ויקי",
+ "apihelp-flow+view-post-description": "הצגת רשומה.",
+ "apihelp-flow+view-post-summary": "הצג פוסט",
+ "apihelp-flow+view-post-param-postId": "מזהה הרשומה שרצים להציג.",
+ "apihelp-flow+view-post-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-post-example-1": "אחזור תוכן הרשומה ב־[[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
+ "apihelp-flow+view-post-history-description": "הצגת היסטוריית הגרסאות של הרשומה.",
+ "apihelp-flow+view-post-history-param-postId": "מזהה הרשומה שעבורה ברצונך לראות את היסטוריית הגרסאות.",
+ "apihelp-flow+view-post-history-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-post-history-example-1": "אחזור גרסאות של רשומה בנושא [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
+ "apihelp-flow+view-topic-description": "תצוגת נושא.",
+ "apihelp-flow+view-topic-summary": "הצג נושא",
+ "apihelp-flow+view-topic-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-topic-example-1": "תצוגת [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "הצגת היסטוריית הגרסאות של נושא.",
+ "apihelp-flow+view-topic-history-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-topic-history-example-1": "הצגת גרסאות של רשומות בנושא [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
+ "apihelp-flow+view-topic-summary-description": "הצגת סיכום נושא.",
+ "apihelp-flow+view-topic-summary-summary": "הצג את סיכום הנושא",
+ "apihelp-flow+view-topic-summary-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-topic-summary-param-revId": "טעינת הגרסה הזאת, ולא האחרונה.",
+ "apihelp-flow+view-topic-summary-example-1": "הצגת הסיכום של [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
+ "apihelp-flow+view-topiclist-description": "הצגת רשימת נושאים.",
+ "apihelp-flow+view-topiclist-summary": "הצג רשימת נושאים",
+ "apihelp-flow+view-topiclist-param-offset-dir": "באיזה סדר למיין את הנושאים.",
+ "apihelp-flow+view-topiclist-param-sortby": "אפשרות המיון של הנושאים, לפי <kbd>updated</kbd> (מיון לפי זמן העדכון הנושא), או <kbd>newest</kbd> (לפי זמן יצירת הנושא).",
+ "apihelp-flow+view-topiclist-param-savesortby": "שמירת האפשרות \"sortby\" להעדפות, אם היא מוגדרת.",
+ "apihelp-flow+view-topiclist-param-offset-id": "ערך ההיסט (בתסדיר UUID) שבו יתחיל אחזור הנושאים; משמש רק עם מיון <kbd>newest</kbd>.",
+ "apihelp-flow+view-topiclist-param-offset": "ערך ההיסט (בתסדיר חותם זמן <code>TS_MW</code> (כלומר <code>YYYYMMDDHHMMSS</code>)), שבו יתחיל אחזור הנושאים; משמש רק עם מיון <kbd>updated</kbd>.",
+ "apihelp-flow+view-topiclist-param-include-offset": "כולל פריט ההיסט גם בתוצאות.",
+ "apihelp-flow+view-topiclist-param-limit": "כמה נושאים לאחזר.",
+ "apihelp-flow+view-topiclist-param-toconly": "האם להשיב רק עם המידע הדרוש עבור תוכן העניינים.",
+ "apihelp-flow+view-topiclist-param-format": "באיזה תסדיר להחזיר את התוכן.",
+ "apihelp-flow+view-topiclist-example-1": "לקבל רשימת נושאים ב־[[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "להמיר טקסט בין קוד ויקי לבין HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "מאיזה תסדיר להמיר את התוכן.",
+ "apihelp-flow-parsoid-utils-param-to": "לאיזה תסדיר להמיר את התוכן.",
+ "apihelp-flow-parsoid-utils-param-content": "איזה תוכן להמיר.",
+ "apihelp-flow-parsoid-utils-param-title": "כותרת הדף. לא ניתן לשימוש יחד עם $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "מזהה הדף. לא יכול לשמש יחד עם $1pageid.",
+ "apihelp-flow-parsoid-utils-example-1": "המרת קוד הוויקי <nowiki>'''lorem''' ''blah''</nowiki> ל־HTML",
+ "apihelp-query+flowinfo-description": "קבלת מידע זרימה בסיסי על דף.",
+ "apihelp-query+flowinfo-example-1": "אחזור מידע זרימה על [[Talk:Sandbox]]‏, [[Main Page]], ו־[[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "אחזור המידע הנחוץ לביטול עריכות של התיאור.",
+ "apihelp-flow+undo-edit-header-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
+ "apihelp-flow+undo-edit-header-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
+ "apihelp-flow+undo-edit-header-example-1": "אחזור מידע על ביטול עריכת תיאור ב־[[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "אחזור המידע הנחוץ לביטול עריכת רשומה.",
+ "apihelp-flow+undo-edit-post-param-postId": "מזהה של הרשומה שצריך לבטל.",
+ "apihelp-flow+undo-edit-post-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
+ "apihelp-flow+undo-edit-post-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
+ "apihelp-flow+undo-edit-post-example-1": "אחזור מידע על ביטול עריכת רשומה בנושא מסוים.",
+ "apihelp-flow+undo-edit-topic-summary-description": "אחזור מידע נחוץ לביטול עריכות הסיכום.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "אחזור מידע על ביטול עריכת סיכום נושא בנושא מסוים",
+ "apierror-flow-safeallowcreationfailed": "זרימה אינה מופעלת בדף שסופק ופעולת safeAllowCreation נכשלה עם: $1",
+ "apierror-flow-notenabled": "זרימה אינה מופעלת בדף שסופק."
+}
diff --git a/Flow/i18n/api/it.json b/Flow/i18n/api/it.json
new file mode 100644
index 00000000..5fa81a0c
--- /dev/null
+++ b/Flow/i18n/api/it.json
@@ -0,0 +1,136 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Erasmo Barresi",
+ "F. Cosoleto",
+ "Giuseppe Forte",
+ "Ricordisamoa"
+ ]
+ },
+ "apihelp-flow-description": "Permette di eseguire azioni nella pagine Flow.",
+ "apihelp-flow-summary": "Permette di eseguire azioni nella pagine Flow.",
+ "apihelp-flow-param-submodule": "Il sotto-modulo Flow da invocare.",
+ "apihelp-flow-param-page": "La pagina su cui eseguire l'azione.",
+ "apihelp-flow-param-token": "Un token recuperato da [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Modifica la descrizione di \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Deprecato in favore di [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Deprecato in favore di [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Stato in cui mettere l'argomento, \"lock\" o \"unlock\".",
+ "apihelp-flow+close-open-topic-param-reason": "Motivo per bloccare o sbloccare l'argomento.",
+ "apihelp-flow+edit-header-description": "Modifica la descrizione di una bacheca.",
+ "apihelp-flow+edit-header-summary": "Modifica la descrizione di una bacheca.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID versione dell'attuale descrizione, per controllare eventuali conflitti di edizione.",
+ "apihelp-flow+edit-header-param-content": "Contenuto per la descrizione.",
+ "apihelp-flow+edit-header-param-format": "Formato della descrizione (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Modifica la descrizione di [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Modifica il contenuto di un messaggio.",
+ "apihelp-flow+edit-post-summary": "Modifica il contenuto di un messaggio.",
+ "apihelp-flow+edit-post-param-postId": "ID messaggio.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID versione dell'attuale messaggio, per controllare eventuali conflitti di edizione.",
+ "apihelp-flow+edit-post-param-content": "Contenuto per il messaggio.",
+ "apihelp-flow+edit-post-param-format": "Formato del contenuto del messaggio (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Modifica un argomento in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Modifica il titolo di un argomento.",
+ "apihelp-flow+edit-title-summary": "Modifica il titolo di un argomento.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID versione dell'attuale titolo, per controllare eventuali conflitti di edizione.",
+ "apihelp-flow+edit-title-param-content": "Contenuto per il titolo, nello stesso formato consentito per l'oggetto della modifica (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Modifica il titolo di [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Modifica il contenuto del riassunto di un argomento.",
+ "apihelp-flow+edit-topic-summary-summary": "Modifica il contenuto del riassunto di un argomento.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID versione dell'attuale riassunto dell'argomento, per controllare eventuali conflitti di edizione.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Contenuto per il riassunto.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formato del riassunto (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Modifica il riassunto di [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Blocca o sblocca un argomento Flow.",
+ "apihelp-flow+lock-topic-summary": "Blocca o sblocca un argomento Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Stato in cui mettere l'argomento, <kbd>lock</kbd> o <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Motivo per bloccare o sbloccare l'argomento. Nota, il client Flow nel wiki usa \"Contrassegna come risolto\" qui, e inserisce le informazioni aggiuntive facoltative nel riassunto.",
+ "apihelp-flow+lock-topic-example-1": "Blocca [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modera un messaggio Flow.",
+ "apihelp-flow+moderate-post-summary": "Modera un messaggio Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A quale livello moderare.",
+ "apihelp-flow+moderate-post-param-reason": "Motivo della moderazione.",
+ "apihelp-flow+moderate-post-param-postId": "ID del messaggio da moderare.",
+ "apihelp-flow+moderate-post-example-1": "Cancella un messaggio nell'argomento [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modera un argomento Flow.",
+ "apihelp-flow+moderate-topic-summary": "Modera un argomento Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A quale livello moderare.",
+ "apihelp-flow+moderate-topic-param-reason": "Motivo della moderazione.",
+ "apihelp-flow+moderate-topic-example-1": "Cancella l'argomento [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Crea un nuovo argomento Flow nel flusso di lavoro indicato.",
+ "apihelp-flow+new-topic-summary": "Crea un nuovo argomento Flow nel flusso di lavoro indicato.",
+ "apihelp-flow+new-topic-param-topic": "Testo per il nuovo titolo dell'argomento.",
+ "apihelp-flow+new-topic-param-content": "Contenuto della risposta iniziale all'argomento.",
+ "apihelp-flow+new-topic-param-format": "Formato della risposta iniziale al nuovo argomento (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Crea un nuovo argomento su [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Risposte a un messaggio.",
+ "apihelp-flow+reply-summary": "Risposte a un messaggio.",
+ "apihelp-flow+reply-param-replyTo": "ID messaggio a cui rispondere.",
+ "apihelp-flow+reply-param-content": "Contenuto per il nuovo messaggio.",
+ "apihelp-flow+reply-param-format": "Formato del nuovo messaggio (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Rispondi a un messaggio in [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-header-description": "Visualizza la descrizione di una bacheca.",
+ "apihelp-flow+view-header-summary": "Visualizza la descrizione di una bacheca.",
+ "apihelp-flow+view-header-param-revId": "Carica questa versione, anziché la più recente.",
+ "apihelp-flow+view-header-example-1": "Recupera la descrizione di [[Talk:Sandbox]] come wikitesto",
+ "apihelp-flow+view-post-description": "Vedi un messaggio.",
+ "apihelp-flow+view-post-summary": "Vedi un messaggio.",
+ "apihelp-flow+view-post-param-postId": "ID messaggio da visualizzare.",
+ "apihelp-flow+view-post-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-post-example-1": "Recupera il contenuto di un messaggio in [[Topic:S2tycnas4hcucw8w]] come wikitesto",
+ "apihelp-flow+view-post-history-description": "Vedi la cronologia di un messaggio.",
+ "apihelp-flow+view-post-history-summary": "Vedi la cronologia di un messaggio.",
+ "apihelp-flow+view-post-history-param-postId": "ID messaggio di cui vedere la cronologia.",
+ "apihelp-flow+view-post-history-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-post-history-example-1": "Recupera le versioni di un messaggio in [[Topic:S2tycnas4hcucw8w]] come wikitesto",
+ "apihelp-flow+view-topic-description": "Vedi un argomento.",
+ "apihelp-flow+view-topic-summary": "Vedi un argomento.",
+ "apihelp-flow+view-topic-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-topic-example-1": "Vedi [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Vedi la cronologia di un argomento.",
+ "apihelp-flow+view-topic-history-summary": "Vedi la cronologia di un argomento.",
+ "apihelp-flow+view-topic-history-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-topic-history-example-1": "Vedi le versioni dei messaggi su [[Topic:S2tycnas4hcucw8w]] come wikitesto",
+ "apihelp-flow+view-topic-summary-description": "Vedi il riassunto di un argomento.",
+ "apihelp-flow+view-topic-summary-summary": "Vedi il riassunto di un argomento.",
+ "apihelp-flow+view-topic-summary-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-topic-summary-param-revId": "Carica questa versione, anziché la più recente.",
+ "apihelp-flow+view-topic-summary-example-1": "Vedi il riassunto per [[Topic:S2tycnas4hcucw8w]] come wikitesto",
+ "apihelp-flow+view-topiclist-description": "Vedi un'elenco di argomenti.",
+ "apihelp-flow+view-topiclist-summary": "Vedi un'elenco di argomenti.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Direzione per l'ordinamento degli argomenti.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opzione di ordinamento degli argomenti, <kbd>updated</kbd> (ordinati per data di aggiornamento dell'argomento) o <kbd>newest</kbd> (ordinati per data di creazione dell'argomento).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Salva l'opzione di ordinamento nelle preferenze dell'utente, se impostato.",
+ "apihelp-flow+view-topiclist-param-limit": "Numero di argomenti da recuperare.",
+ "apihelp-flow+view-topiclist-param-format": "Formato in cui restituire il contenuto.",
+ "apihelp-flow+view-topiclist-example-1": "Elenco argomenti su [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Converti testo tra wikitesto e HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Converti testo tra wikitesto e HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formato da cui convertire il contenuto.",
+ "apihelp-flow-parsoid-utils-param-to": "Formato in cui convertire il contenuto.",
+ "apihelp-flow-parsoid-utils-param-content": "Contenuto da convertire.",
+ "apihelp-flow-parsoid-utils-param-title": "Titolo della pagina. Non può essere usato insieme con $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID della pagina. Non può essere usato insieme con $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Converti wikitesto <nowiki>'''lorem''' ''blah''</nowiki> in HTML",
+ "apihelp-query+flowinfo-description": "Ottieni informazioni Flow di base su una pagina.",
+ "apihelp-query+flowinfo-summary": "Ottieni informazioni Flow di base su una pagina.",
+ "apihelp-query+flowinfo-example-1": "Recupera informazioni Flow su [[Talk:Sandbox]], [[Main Page]], e [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Recupera le informazioni necessarie per annullare le modifiche della descrizione.",
+ "apihelp-flow+undo-edit-header-summary": "Recupera le informazioni necessarie per annullare le modifiche della descrizione.",
+ "apihelp-flow+undo-edit-header-param-startId": "ID versione da cui iniziare l'annullamento.",
+ "apihelp-flow+undo-edit-header-param-endId": "ID versione a cui terminare l'annullamento.",
+ "apihelp-flow+undo-edit-header-example-1": "Recupera le informazioni sull'annullamento di una modifica alla descrizione di [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Recupera le informazioni necessarie per annullare le modifiche al messaggio.",
+ "apihelp-flow+undo-edit-post-summary": "Recupera le informazioni necessarie per annullare le modifiche al messaggio.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID messaggio da annullare.",
+ "apihelp-flow+undo-edit-post-param-startId": "ID versione da cui iniziare l'annullamento.",
+ "apihelp-flow+undo-edit-post-param-endId": "ID versione a cui terminare l'annullamento.",
+ "apihelp-flow+undo-edit-post-example-1": "Recupera le informazioni sull'annullamento di una modifica al messaggio in un argomento specifico.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Recupera le informazioni necessarie per annullare le modifiche al riassunto dell'argomento.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Recupera le informazioni necessarie per annullare le modifiche al riassunto dell'argomento.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "ID versione da cui iniziare l'annullamento.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "ID versione a cui terminare l'annullamento.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Recupera le informazioni sull'annullamento di una modifica al riassunto dell'argomento in un argomento specifico"
+}
diff --git a/Flow/i18n/api/ja.json b/Flow/i18n/api/ja.json
new file mode 100644
index 00000000..f983ade1
--- /dev/null
+++ b/Flow/i18n/api/ja.json
@@ -0,0 +1,79 @@
+{
+ "@metadata": {
+ "authors": [
+ "2nd-player",
+ "Otokoume",
+ "Shirayuki",
+ "SkyDaisy9",
+ "Sujiniku"
+ ]
+ },
+ "apihelp-flow-description": "Flow ページに対して操作を行います。",
+ "apihelp-flow-param-submodule": "実行する Flow サブモジュールです。",
+ "apihelp-flow-param-page": "操作を行うページです。",
+ "apihelp-flow-example-1": "\"[[Talk:Sandbox]]\" の説明を編集",
+ "apihelp-flow+close-open-topic-param-moderationState": "変更後の話題の状態であり、\"lock\" または \"unlock\" です。",
+ "apihelp-flow+close-open-topic-param-reason": "話題をロックまたはロック解除する理由です。",
+ "apihelp-flow+edit-header-description": "ボードの説明を編集します。",
+ "apihelp-flow+edit-header-param-prev_revision": "現在の説明の版 ID であり、編集競合を確認するためのものです。",
+ "apihelp-flow+edit-header-param-content": "説明の内容です。",
+ "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]] の説明を編集",
+ "apihelp-flow+edit-post-description": "投稿の本文を編集します。",
+ "apihelp-flow+edit-post-param-postId": "投稿 ID です。",
+ "apihelp-flow+edit-post-param-prev_revision": "現在の投稿の版 ID であり、編集競合を確認するためのものです。",
+ "apihelp-flow+edit-post-param-content": "投稿の本文です。",
+ "apihelp-flow+edit-post-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿を編集します。",
+ "apihelp-flow+edit-title-description": "話題の題名を編集します。",
+ "apihelp-flow+edit-title-param-prev_revision": "編集競合を確認するための、現在のページの版ID。",
+ "apihelp-flow+edit-title-param-content": "題名の内容です。",
+ "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]] の題名を編集",
+ "apihelp-flow+edit-topic-summary-description": "話題の要約の内容を編集します。",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "現在の話題の要約の版 ID がある場合は指定します。編集競合を確認するためのものです。",
+ "apihelp-flow+edit-topic-summary-param-summary": "要約の内容です。",
+ "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] の要約を編集",
+ "apihelp-flow+lock-topic-description": "Flow の話題をロックまたはロック解除します。",
+ "apihelp-flow+lock-topic-param-moderationState": "変更後の話題の状態であり、<kbd>lock</kbd> または <kbd>unlock</kbd> です。",
+ "apihelp-flow+lock-topic-param-reason": "話題をロックまたはロック解除する理由です。Note, the on-wiki Flow client uses \"Marked as resolved\" here, and puts optional additional information in the summary.",
+ "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] をロック",
+ "apihelp-flow+moderate-post-example-1": "話題 [[Topic:S2tycnas4hcucw8w]] の投稿を削除",
+ "apihelp-flow+moderate-topic-example-1": "話題 [[Topic:S2tycnas4hcucw8w]] を削除",
+ "apihelp-flow+new-topic-description": "指定したワークフローに Flow の話題を新規作成します。",
+ "apihelp-flow+new-topic-param-topic": "新しい話題の題名です。",
+ "apihelp-flow+new-topic-param-content": "初めのリプライの話題の本文です。",
+ "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]] に話題を新規作成",
+ "apihelp-flow+reply-description": "投稿に返信します。",
+ "apihelp-flow+reply-param-replyTo": "返信先の投稿の ID です。",
+ "apihelp-flow+reply-param-content": "新しい投稿の本文です。",
+ "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿に返信",
+ "apihelp-flow+view-header-param-format": "返す本文の形式です。",
+ "apihelp-flow+view-header-description": "掲示板の説明を閲覧します。",
+ "apihelp-flow+view-header-param-revId": "最新版の代わりに、この版を読み込みます。",
+ "apihelp-flow+view-header-example-1": "[[Talk:Sandbox]] の説明をウィキテキスト形式で取得",
+ "apihelp-flow+view-post-description": "投稿を閲覧します。",
+ "apihelp-flow+view-post-param-postId": "閲覧する投稿の ID です。",
+ "apihelp-flow+view-post-param-format": "返す本文の形式です。",
+ "apihelp-flow+view-post-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿の本文をウィキテキスト形式で取得",
+ "apihelp-flow+view-topic-description": "話題を閲覧します。",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] を閲覧",
+ "apihelp-flow+view-topic-summary-description": "話題の要約を閲覧します。",
+ "apihelp-flow+view-topic-summary-param-format": "返す本文の形式です。",
+ "apihelp-flow+view-topic-summary-param-revId": "最新版の代わりに、この版を読み込みます。",
+ "apihelp-flow+view-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] の要約をウィキテキスト形式で閲覧",
+ "apihelp-flow+view-topiclist-description": "話題の一覧を閲覧します。",
+ "apihelp-flow+view-topiclist-param-offset-dir": "話題の並び順指定です。",
+ "apihelp-flow+view-topiclist-param-sortby": "話題の並べ替えのオプションです。either <kbd>updated</kbd> (ordered by topic update time), or <kbd>newest</kbd> (ordered by topic creation time).",
+ "apihelp-flow+view-topiclist-param-savesortby": "設定すると、ユーザー好みに並べ替えのオプションを保存します。",
+ "apihelp-flow+view-topiclist-param-offset-id": "話題の取得を開始するオフセット値 (UUID 形式) です; <kbd>最新の</kbd> オーダリングとだけで使われます。",
+ "apihelp-flow+view-topiclist-param-offset": "話題の取得を開始するオフセット値(話題の更新のタイムスタンプ、 <code>TS_MW</code> 形式 (<code>YYYYMMDDHHMMSS</code>))です。; used only with <kbd>updated</kbd> ordering",
+ "apihelp-flow+view-topiclist-param-limit": "取得する話題の件数です。",
+ "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]] の話題を列挙",
+ "apihelp-flow-parsoid-utils-description": "テキストをウィキテキスト形式と HTML 形式の間で相互変換します。",
+ "apihelp-flow-parsoid-utils-param-from": "変換元の形式です。",
+ "apihelp-flow-parsoid-utils-param-to": "変換先の形式です。",
+ "apihelp-flow-parsoid-utils-param-content": "変換する内容です。",
+ "apihelp-flow-parsoid-utils-param-title": "ページ名です。$1pageid とは同時に使用できません。",
+ "apihelp-flow-parsoid-utils-param-pageid": "ページの ID です。$1title とは同時に使用できません。",
+ "apihelp-flow-parsoid-utils-example-1": "ウィキテキスト <nowiki>'''lorem''' ''blah''</nowiki> を HTML 形式に変換",
+ "apihelp-query+flowinfo-description": "ページの Flow の基礎的な情報を取得します。",
+ "apihelp-query+flowinfo-example-1": "[[Talk:Sandbox]]、[[Main Page]]、[[Talk:Flow]] の Flow の情報を取得"
+}
diff --git a/Flow/i18n/api/ka.json b/Flow/i18n/api/ka.json
new file mode 100644
index 00000000..78c69589
--- /dev/null
+++ b/Flow/i18n/api/ka.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "David1010"
+ ]
+ },
+ "apihelp-flow+edit-header-param-content": "აღწერის შინაარსი.",
+ "apihelp-flow+edit-header-param-format": "აღწერის ფორმატი (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]]-ის აღწერის რედაქტირება",
+ "apihelp-flow+edit-post-description": "შეტყობინების შინაარსის რედაქტირებები.",
+ "apihelp-flow+edit-post-param-postId": "შეტყობინების ID.",
+ "apihelp-flow+edit-post-param-content": "შეტყობინების შინაარსი.",
+ "apihelp-flow+edit-post-param-format": "შეტყობინების შინაარსის ფორმატი (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "შეტყობინების რედაქტირება [[Topic:S2tycnas4hcucw8w]]-ში",
+ "apihelp-flow+edit-title-description": "თემის სათაურის რედაქტირება.",
+ "apihelp-flow+edit-title-param-content": "სათაურის შინაარსი.",
+ "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის სათაურის რედაქტირება",
+ "apihelp-flow+edit-topic-summary-description": "თემის რეზიუმეს შინაარსის რედაქტირება.",
+ "apihelp-flow+edit-topic-summary-param-summary": "რეზიუმეს შინაარსი.",
+ "apihelp-flow+edit-topic-summary-param-format": "რეზიუმეს ფორმატი (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის რეზიუმეს რედაქტირება",
+ "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის დახურვა",
+ "apihelp-flow+view-post-description": "შეტყობინების ხილვა.",
+ "apihelp-flow+view-post-param-postId": "სანახავი შეტყობინების ID.",
+ "apihelp-flow+view-topic-description": "თემის ხილვა.",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის ხილვა",
+ "apihelp-flow+view-topic-summary-description": "თემის რეზიუმეს ხილვა."
+}
diff --git a/Flow/i18n/api/kk-cyrl.json b/Flow/i18n/api/kk-cyrl.json
new file mode 100644
index 00000000..2600eefc
--- /dev/null
+++ b/Flow/i18n/api/kk-cyrl.json
@@ -0,0 +1,109 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "apihelp-flow-description": "Flow беттеріндегі көрінетін әрекеттерге рұқсат ету",
+ "apihelp-flow-param-submodule": "Шақыруға Flow қарасты модулы",
+ "apihelp-flow-param-page": "Әрекетке жол беретін бет.",
+ "apihelp-flow-example-1": "«[[Talk:Sandbox]]» сипаттамасын өңдеу",
+ "apihelp-flow+close-open-topic-description": "Пайдалануға ескірген [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "\"Ашық\" не \"жабық\" жағдайы бойынша анықталған тақырып.",
+ "apihelp-flow+close-open-topic-param-reason": "Тақырыпты жабу немесе жабуды болдырмау себебі.",
+ "apihelp-flow+edit-header-description": "Тақта сипаттамасын өңдеу.",
+ "apihelp-flow+edit-header-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа сипаттамасының нұсқа сәйкестендіргіші.",
+ "apihelp-flow+edit-header-param-content": "Сипаттама үшін контент.",
+ "apihelp-flow+edit-header-param-format": "Сипаттамысының форматы (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]] сипаттамасын өңдеу",
+ "apihelp-flow+edit-post-description": "Хабарлама контентін өңдеу.",
+ "apihelp-flow+edit-post-param-postId": "Хабарлама сәйкестендіргіші (ID).",
+ "apihelp-flow+edit-post-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа хабарламасының нұсқа сәйкестендіргіші.",
+ "apihelp-flow+edit-post-param-content": "Хабарлама үшін контент.",
+ "apihelp-flow+edit-post-param-format": "Хабарлама контентінің форматы (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Хабарламаны [[Topic:S2tycnas4hcucw8w]] тақырып бетінде өңдеу.",
+ "apihelp-flow+edit-title-description": "Тақырыптың атауын өңдеу.",
+ "apihelp-flow+edit-title-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа атауының нұсқа сәйкестендіргіші.",
+ "apihelp-flow+edit-title-param-content": "Атау үшін контент, өңдеу түйіндемелері үшін бірдей формат рұқсат етілген (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]] тақырыбының атауын өңдеу",
+ "apihelp-flow+edit-topic-summary-description": "Тақырыптың түйіндеме контентін өңдеу.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Егер бар болса өңдеу қақтығыстарын тексеру үшін қазіргі тақырып нұсқасының нұсқа сәйкестендіргіші (ID).",
+ "apihelp-flow+edit-topic-summary-param-summary": "Түйіндемеге контент.",
+ "apihelp-flow+edit-topic-summary-param-format": "Түйіндемесінің форматы (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] тақырыбының түйіндемесін өңдеу",
+ "apihelp-flow+lock-topic-description": "Flow тақырыбын жабу немесе жабуды болдырмау.",
+ "apihelp-flow+lock-topic-param-moderationState": "<kbd>Құлыпталған</kbd> не <kbd>құлыпталмаған</kbd> жағдайы бойынша анықталған тақырып.",
+ "apihelp-flow+lock-topic-param-reason": "Тақырыпты жабу немесе жабуды болдырмау себебі. Есіңізде болсын: мұнда уики Flow клиенті \"Шешілді деп белгіледі\" дегенді қолданады және түйіндемесіне міндетті емес қосымша мәлімет қояды.",
+ "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] дегенді жабу.",
+ "apihelp-flow+moderate-post-description": "Flow хабарламысын модерациялау.",
+ "apihelp-flow+moderate-post-param-moderationState": "Модерацияның қандай денгейі?",
+ "apihelp-flow+moderate-post-param-reason": "Модерациялау себебі.",
+ "apihelp-flow+moderate-post-param-postId": "Хабарламаны модерациялау сәйкестендіргіші.",
+ "apihelp-flow+moderate-post-example-1": "[[Topic:S2tycnas4hcucw8w]] тақырыбындағы хабарламаны жою.",
+ "apihelp-flow+moderate-topic-description": "Flow тақырыбын модерациялайды.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Модерацияның қандай денгейі?",
+ "apihelp-flow+moderate-topic-param-reason": "Модерациялау себебі.",
+ "apihelp-flow+moderate-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]тақырыбын жою.",
+ "apihelp-flow+new-topic-description": "Берілген жұмыс легінен жаңа Flow тақырып бастайды.",
+ "apihelp-flow+new-topic-param-topic": "Жаңа тақырып атауына мәтін.",
+ "apihelp-flow+new-topic-param-content": "Тақырыптың бастапқы жауабына контент.",
+ "apihelp-flow+new-topic-param-format": "Жаңа тақырыптың алғашқы жауабының форматы (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]] бетіне жаңа тақырып бастау.",
+ "apihelp-flow+reply-description": "Хабарламаға жауаптар.",
+ "apihelp-flow+reply-param-replyTo": "Жауапқа хабарлама сәйкестендіргіші.",
+ "apihelp-flow+reply-param-content": "Жаңа хабарламаға котент.",
+ "apihelp-flow+reply-param-format": "Жаңа хабарламасының форматы (wikitext|html)",
+ "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]] деген тақырыптағы хабарламаға жауап беру",
+ "apihelp-flow+view-header-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-header-description": "Тақта сипаттамасын көру.",
+ "apihelp-flow+view-header-param-revId": "Ең жуықтағының орнына мына нұсқаны жүктеңіз.",
+ "apihelp-flow+view-header-example-1": "Уикимәтін секілді [[Talk:Sandbox]] сипаттамасын ығыстыру.",
+ "apihelp-flow+view-post-description": "Хабарламаны қарау.",
+ "apihelp-flow+view-post-param-postId": "Қарау үшін хабарламаның сәйкестендіргіші.",
+ "apihelp-flow+view-post-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-post-example-1": "Уикимәтін ретінде [[Topic:S2tycnas4hcucw8w]] тақырыбындағы хабарлама контентін ығыстыру.",
+ "apihelp-flow+view-post-history-description": "Бұл хабарламаның түзетілу тарихын қарау",
+ "apihelp-flow+view-post-history-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-post-history-example-1": "Уикимәтін ретінде [[Topic:S2tycnas4hcucw8w]] тақырыбындағы хабарлама контентін ығыстыру.",
+ "apihelp-flow+view-topic-description": "Тақырыпты қарау.",
+ "apihelp-flow+view-topic-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] тақырыбын қарау.",
+ "apihelp-flow+view-topic-history-description": "Бұл тақырыптың түзетілу тарихын қарау",
+ "apihelp-flow+view-topic-history-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-topic-history-example-1": "Уикимәтін ретінде [[Topic:S2tycnas4hcucw8w]] тақырыбындағы хабарлама нұсқаларын қарау.",
+ "apihelp-flow+view-topic-summary-description": "Тақырып түйіндемесін қарау.",
+ "apihelp-flow+view-topic-summary-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-topic-summary-param-revId": "Ең соңғының орнына мына нұсқаны жүктеңіз.",
+ "apihelp-flow+view-topic-summary-example-1": "Уикимәтін секілді [[Topic:S2tycnas4hcucw8w]] түйіндемесін қарау.",
+ "apihelp-flow+view-topiclist-description": "Тақырыптардың тізімін қарау.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Тақырыпты реттеу бағыты.",
+ "apihelp-flow+view-topiclist-param-sortby": "Тақырыптарды сұрыпттау параметрі, <kbd>жаңартылған</kbd> (тақырып жаңарту уақыты бойынша реттеледі), не <kbd>ең жаңасы</kbd> (тақырып бастау уақыты бойынша реттеледі) екеуінің біреуі",
+ "apihelp-flow+view-topiclist-param-savesortby": "Егер орнатылған болса, қатысушы баптауларында сұрыптау опциясын сақтау.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Алу тақырыбын бастау үшін орын ауыстыру мәні (UUID форматында); тек <kbd>ең жаңасы</kbd> реттеуі қолданылады",
+ "apihelp-flow+view-topiclist-param-offset": "Ығысу тақырыбын бастау үшін орын ауыстыру мәні.",
+ "apihelp-flow+view-topiclist-param-limit": "Ығыстыратын тақырып саны.",
+ "apihelp-flow+view-topiclist-param-format": "Контентті қайтаратын формат.",
+ "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]] бетіндегі тақырыптар саны",
+ "apihelp-flow-parsoid-utils-description": "HTML және уикимәтін арасында мәтінді түрлендіру",
+ "apihelp-flow-parsoid-utils-param-from": "Контент түрленетін форматтан.",
+ "apihelp-flow-parsoid-utils-param-to": "Контент түрленетін форматқа.",
+ "apihelp-flow-parsoid-utils-param-content": "Түрлендірілетін контент.",
+ "apihelp-flow-parsoid-utils-param-title": "Беттің атауы. $1pageaid дегенмен бірге қолданылмайды.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Бет сәйкестендіргіші. $1title дегенмен бірге қолданылмайды.",
+ "apihelp-flow-parsoid-utils-example-1": "<nowiki>'''lorem''' ''blah''</nowiki> уики мәтінін HTML-ге түрлендіру.",
+ "apihelp-query+flowinfo-description": "Бет туралы негізгі Flow мәліметтер алу.",
+ "apihelp-query+flowinfo-example-1": "[[Talk:Sandbox]], [[Main Page]] және [[Talk:Flow]] туралы мәліметтерді ығыстыру.",
+ "apihelp-flow+undo-edit-header-description": "Сипаттама өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
+ "apihelp-flow+undo-edit-header-param-startId": "Болдырмауды бастауға нұсқа сәйкестендіргіші",
+ "apihelp-flow+undo-edit-header-param-endId": "Болдырмауды аяқтауға нұсқа сәйкестендіргіші.",
+ "apihelp-flow+undo-edit-header-example-1": "[[Talk:Sandbox]] бетіндегі сипаттаманы болдырмау туралы мәліметті ығыстыру.",
+ "apihelp-flow+undo-edit-post-description": "Хабарлама өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
+ "apihelp-flow+undo-edit-post-param-postId": "Жоққа шығару үшін хабарлама сәйкестендіргіші.",
+ "apihelp-flow+undo-edit-post-param-startId": "Болдырмауды бастауға нұсқа сәйкестендіргіші.",
+ "apihelp-flow+undo-edit-post-param-endId": "Болдырмауды аяқтауға нұсқа сәйкестендіргіші.",
+ "apihelp-flow+undo-edit-post-example-1": "Көрсетілген тақырыптағы хабарлама өңдемесін жоққа шығару туралы мәліметті ығыстыру.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Тақырып түйіндеме өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Болдырмауды бастауға нұсқа сәйкестендіргіші",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Болдырмауды аяқтауға нұсқа сәйкестендіргіші.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Көрсетілген тақырыптағы тақырып түйіндемесін өңдемесін жоққа шығару туралы мәліметті ығыстыру."
+}
diff --git a/Flow/i18n/api/ko.json b/Flow/i18n/api/ko.json
new file mode 100644
index 00000000..a9b3cefc
--- /dev/null
+++ b/Flow/i18n/api/ko.json
@@ -0,0 +1,46 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hwangjy9",
+ "Priviet",
+ "SeoJeongHo",
+ "Yearning",
+ "Ykhwong"
+ ]
+ },
+ "apihelp-flow-param-token": "토큰은 [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]에서 가져옵니다",
+ "apihelp-flow-example-1": "\"[[Talk:Sandbox]]\"의 설명을 편집하기",
+ "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]]의 설명을 편집하기",
+ "apihelp-flow+edit-post-summary": "게시물의 내용을 편집합니다.",
+ "apihelp-flow+edit-post-example-1": "[[Topic:S2tycnas4hcucw8w]]에서 게시물을 편집합니다",
+ "apihelp-flow+edit-title-description": "주제의 제목을 편집합니다.",
+ "apihelp-flow+edit-title-summary": "주제의 제목을 편집합니다.",
+ "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]]의 제목을 편집하기",
+ "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]]의 요약을 편집하기",
+ "apihelp-flow+lock-topic-description": "플로우 주제를 잠그거나 잠금을 해제합니다.",
+ "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] 잠그기",
+ "apihelp-flow+moderate-post-example-1": "[[Topic:S2tycnas4hcucw8w]] 게시물을 삭제하기",
+ "apihelp-flow+moderate-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] 주제를 지우기",
+ "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]]에서 새 주제 만들기",
+ "apihelp-flow+reply-summary": "게시물에 댓글을 답니다.",
+ "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]]의 게시물에 답변하기",
+ "apihelp-flow+view-post-summary": "게시물을 봅니다.",
+ "apihelp-flow+view-post-history-summary": "게시물의 판 역사를 봅니다.",
+ "apihelp-flow+view-topic-description": "주제를 봅니다.",
+ "apihelp-flow+view-topic-summary": "주제를 봅니다.",
+ "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] 보기",
+ "apihelp-flow+view-topic-summary-description": "주제 요약을 봅니다.",
+ "apihelp-flow+view-topic-summary-summary": "주제 요약을 봅니다.",
+ "apihelp-flow+view-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]]의 요약을 위키텍스트로 보기",
+ "apihelp-flow+view-topiclist-description": "주제 목록을 봅니다.",
+ "apihelp-flow+view-topiclist-summary": "주제 목록을 봅니다.",
+ "apihelp-flow+view-topiclist-param-include-offset": "결과에 오프셋 항목을 포함합니다.",
+ "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]]의 항목을 나열하기",
+ "apihelp-flow-parsoid-utils-summary": "위키텍스트와 HTML 간에 텍스트를 변환합니다.",
+ "apihelp-flow+undo-edit-post-description": "게시물 편집을 취소하기 위해 필요한 정보를 검색합니다.",
+ "apihelp-flow+undo-edit-post-summary": "게시물 편집을 취소하기 위해 필요한 정보를 검색합니다.",
+ "apihelp-flow+undo-edit-post-param-postId": "포스트 아이디는 취소할수 있습니다.",
+ "apihelp-flow+undo-edit-post-param-endId": "끝으로 아이디 수정이 취소되었습니다.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "계정 아이디 취소를 시작합니다.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "끝으로 아이디 수정이 취소되었습니다."
+}
diff --git a/Flow/i18n/api/ksh.json b/Flow/i18n/api/ksh.json
new file mode 100644
index 00000000..12cf67ae
--- /dev/null
+++ b/Flow/i18n/api/ksh.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha",
+ "Quiddity"
+ ]
+ },
+ "apihelp-flow-param-page": "De Sigg, fö di jät ze donn es.",
+ "apihelp-flow-example-1": "Donn de Äkliehrong op dä Sigg „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Talk:Sandbox]]</code>“ verändere.",
+ "apihelp-flow+edit-header-param-content": "Der Ennhalld för de Äkliehrong.",
+ "apihelp-flow+edit-header-param-format": "Et Fommaht vun dä Äkliehrong (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Donn de Äkliehrong vum [[Talk:Sandbox|Klaaf övver de Schpellwiß]] ändere.",
+ "apihelp-flow+edit-post-param-format": "Et Fommaht vum Enhalld vum neuje Beijdraach (wikitext|html)",
+ "apihelp-flow+edit-title-param-prev_revision": "De Kännong för de aktoölle Väsjohn vun dä Övverschreff, öm noh dubbelte Beärbeidonge ze söhke.",
+ "apihelp-flow+edit-title-param-content": "Der Ennhalld för de Övverschreff.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Der Inhalt for et Resümeh.",
+ "apihelp-flow+edit-topic-summary-param-format": "Et Fommaht vun dä Zosammefaßong (wikitext|html)",
+ "apihelp-flow+new-topic-param-format": "Et Fommaht vun de eezde Antwoot vum neue Tehma (<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">wikitext</code>|<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">html</code>)",
+ "apihelp-flow+reply-param-content": "Dä Enhald för dä neuje Beidraach.",
+ "apihelp-flow+reply-param-format": "Et Fommaht vum neue Beijdraach (wikitext|html)",
+ "apihelp-flow+view-header-example-1": "Holl de Äkliehrong för „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Talk:Sandbox]]</code>“ em Wikkitäx Fommaht.",
+ "apihelp-flow+view-post-history-param-format": "Dat Fommaht för der Enhalld dren ußzejävve.",
+ "apihelp-flow+view-post-history-example-1": "Holl de Väsohne vun de Beijdrähsch zom <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Topic:S2tycnas4hcucw8w]]</code> als Wikkitäx",
+ "apihelp-flow+view-topic-history-example-1": "Belohr de Väsohne vun de Beijdrähsch zom <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Topic:S2tycnas4hcucw8w]]</code> als Wikkitäx",
+ "apihelp-flow+view-topiclist-param-sortby": "Enschtällonge för et Zottehre vun de topics, dadd es äntwehder „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">updated</kbd>“ för zem Zottehre noh de Zigg, woh dä topic et läz jeändert wohd, udder „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">newest</kbd>“ för et Zottehre noh dä Zigg vum Aanläje.",
+ "apihelp-flow+view-topiclist-param-savesortby": "Donn de Enschtällong för woh noh ze zottehre en de Enschtällonge vum Metmaacher, wann jät ennjejovve es.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Der Wäät för der Bejenn — em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Universally unique identifier\">UUID</i>-Fommaht — vun woh aan Jähjeschtänd jehollt wähde sulle. Weed blohß beim Zottehre noh „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">newest</kbd>“ jebruch.",
+ "apihelp-flow-parsoid-utils-description": "Donn Täx zwesche Wikkitäx un <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i> wandelle.",
+ "apihelp-flow-parsoid-utils-param-content": "Der Enhalld zom Ömwandelle.",
+ "apihelp-flow+undo-edit-header-description": "Holl nühdejje Enfommazjuhne, öm de Änderong aan dä Äkliehrong retuhr ze nämme.",
+ "apihelp-flow+undo-edit-header-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
+ "apihelp-flow+undo-edit-header-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull.",
+ "apihelp-flow+undo-edit-post-description": "Holl nühdejje Enfommazjuhne, öm de Änderong aan em Beijdrahch retuhr ze nämme.",
+ "apihelp-flow+undo-edit-post-param-postId": "De Kännong vum Beijdrahch zom zerök nämme.",
+ "apihelp-flow+undo-edit-post-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
+ "apihelp-flow+undo-edit-post-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull.",
+ "apihelp-flow+undo-edit-post-example-1": "Holl Enfommazjuhne, öm en Änderong aan ene beschtemmte topic retuhr ze nämme.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull."
+}
diff --git a/Flow/i18n/api/lb.json b/Flow/i18n/api/lb.json
new file mode 100644
index 00000000..da4d86c3
--- /dev/null
+++ b/Flow/i18n/api/lb.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robby"
+ ]
+ },
+ "apihelp-flow-example-1": "Ännert d'Beschreiwung vun ''[[Talk:Sandbox]]''",
+ "apihelp-flow+edit-header-param-content": "Inhalt fir d'Beschreiwung.",
+ "apihelp-flow+edit-header-param-format": "Format vun der Beschreiwung (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "D'Beschreiwung vun [[Talk:Sandbox]] änneren",
+ "apihelp-flow+edit-title-param-content": "Inhalt fir den Titel, am selwechte Format erlaabt fir de Resumé vun der Ännerung (topic-title-wikitext)",
+ "apihelp-flow+edit-topic-summary-param-summary": "Inhalt fir de Resumé.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format vum Resumé (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Ännert de Resumé vu(n) [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-param-reason": "Grond fir Moderatioun.",
+ "apihelp-flow+view-topic-description": "En Thema weisen.",
+ "apihelp-flow+view-topic-summary": "En Thema weisen.",
+ "apihelp-flow-parsoid-utils-param-to": "Format an deen den Inhalt ëmgewandelt soll ginn."
+}
diff --git a/Flow/i18n/api/mk.json b/Flow/i18n/api/mk.json
new file mode 100644
index 00000000..5e89838c
--- /dev/null
+++ b/Flow/i18n/api/mk.json
@@ -0,0 +1,139 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06",
+ "Quiddity"
+ ]
+ },
+ "apihelp-flow-description": "Овозможува вршење дејства брз страници со Тек.",
+ "apihelp-flow-summary": "Овозможува вршење дејства брз страници со Тек.",
+ "apihelp-flow-param-submodule": "Подмодулот на Тек што треба да се повика.",
+ "apihelp-flow-param-page": "Врз која страница да се изврши дејството.",
+ "apihelp-flow-param-token": "Шифра добиена од [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Измени го описот на „[[Talk:Sandbox]]“",
+ "apihelp-flow+close-open-topic-description": "Застарено и заменето со [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Застарено и заменето со [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Која состојба да ѝ се зададе на темата: „заклучена“ или „отклучена“.",
+ "apihelp-flow+close-open-topic-param-reason": "Причина за заклучување или отклучување на темата.",
+ "apihelp-flow+edit-header-description": "Уредува опис на разговорницата.",
+ "apihelp-flow+edit-header-summary": "Уредува опис на разговорницата.",
+ "apihelp-flow+edit-header-param-prev_revision": "Назнака на тековната преработка на описот, за проверка на можни спротиставености во уредувањето.",
+ "apihelp-flow+edit-header-param-content": "Содржина на описот.",
+ "apihelp-flow+edit-header-param-format": "Формат на описот (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Измени го описот на [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Измени ја содржината на објавата.",
+ "apihelp-flow+edit-post-summary": "Измени ја содржината на објавата.",
+ "apihelp-flow+edit-post-param-postId": "Назнака на објавата.",
+ "apihelp-flow+edit-post-param-prev_revision": "Назнака на тековната преработка на објавата, за проверка на можни спротиставености во уредувањето.",
+ "apihelp-flow+edit-post-param-content": "Содржина на објавата.",
+ "apihelp-flow+edit-post-param-format": "Формат на содржината на објавата (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Измени објава во [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Уредува наслов на објава.",
+ "apihelp-flow+edit-title-summary": "Уредува наслов на објава.",
+ "apihelp-flow+edit-title-param-prev_revision": "Назнака на тековната преработка на насловот, за проверка на можни спротиставености во уредувањето.",
+ "apihelp-flow+edit-title-param-content": "Содржина на насловот, во истиот формат допуштен за описи на уредувања (тема-наслов-викитекст).",
+ "apihelp-flow+edit-title-example-1": "Измени го насловот на [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Измени ја содржината на краткиот преглед на темата.",
+ "apihelp-flow+edit-topic-summary-summary": "Измени ја содржината на краткиот преглед на темата.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Назнака на тековната преработка на краткиот преглед на темата, за проверка на можни спротиставености во уредувањето.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Содржина на краткиот преглед.",
+ "apihelp-flow+edit-topic-summary-param-format": "Формат на описот (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Измени го краткиот преглед на [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Заклучи или отклучи тема со Тек.",
+ "apihelp-flow+lock-topic-summary": "Заклучи или отклучи тема со Тек.",
+ "apihelp-flow+lock-topic-param-moderationState": "Која состојба да ѝ се зададе на темата: <kbd>lock</kbd> или <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Причина за заклучување или отклучување на темата. Имајте на ум дека клиентот на „Тек“ на викито тука користи „Означено како решено“, и става незадолжителни дополнителни информации во описот.",
+ "apihelp-flow+lock-topic-example-1": "Заклучи ја [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Модерирај објава со Тек.",
+ "apihelp-flow+moderate-post-summary": "Модерирај објава со Тек.",
+ "apihelp-flow+moderate-post-param-moderationState": "На кое ниво да се модерира.",
+ "apihelp-flow+moderate-post-param-reason": "Причина за модерирањето.",
+ "apihelp-flow+moderate-post-param-postId": "Назнака на објавата што ќе се модерира.",
+ "apihelp-flow+moderate-post-example-1": "Избриши објава на темата [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Модерира тема со Тек.",
+ "apihelp-flow+moderate-topic-summary": "Модерира тема со Тек.",
+ "apihelp-flow+moderate-topic-param-moderationState": "На кое ниво да се модерира.",
+ "apihelp-flow+moderate-topic-param-reason": "Причина за модерирањето.",
+ "apihelp-flow+moderate-topic-example-1": "Избриши ја темата [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Создава нова тема со Тек за дадениот работен тек.",
+ "apihelp-flow+new-topic-summary": "Создава нова тема со Тек за дадениот работен тек.",
+ "apihelp-flow+new-topic-param-topic": "Текст на насловот на новата тема.",
+ "apihelp-flow+new-topic-param-content": "Содржина на првичниот одговор на темата.",
+ "apihelp-flow+new-topic-param-format": "Формат на првичниот одговор на темата (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Создај нова тема на [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Одговара на објава.",
+ "apihelp-flow+reply-summary": "Одговара на објава.",
+ "apihelp-flow+reply-param-replyTo": "Назнака на објавата на која се одговара.",
+ "apihelp-flow+reply-param-content": "Содржина на новата објава.",
+ "apihelp-flow+reply-param-format": "Формат на новата објава (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Одговори на објава на [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-header-description": "Погл. описот на разговорницата.",
+ "apihelp-flow+view-header-summary": "Погл. описот на разговорницата.",
+ "apihelp-flow+view-header-param-revId": "Вчитај ја оваа преработка наместо најновата.",
+ "apihelp-flow+view-header-example-1": "Дај го описот на [[Talk:Sandbox]] како викитекст",
+ "apihelp-flow+view-post-description": "Погл. објава.",
+ "apihelp-flow+view-post-summary": "Погл. објава.",
+ "apihelp-flow+view-post-param-postId": "Назнака на објавата што треба да се погледа.",
+ "apihelp-flow+view-post-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-post-example-1": "Дај ја содржината на објава на [[Topic:S2tycnas4hcucw8w]] како викитекст",
+ "apihelp-flow+view-post-history-description": "Погледајте ја историјата на преработки на објавата.",
+ "apihelp-flow+view-post-history-summary": "Погледајте ја историјата на преработки на објавата.",
+ "apihelp-flow+view-post-history-param-postId": "Назнака на објавата за која ја барате историјата на преработки.",
+ "apihelp-flow+view-post-history-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-post-history-example-1": "Добијте ги преработките на една објава на [[Topic:S2tycnas4hcucw8w]] како викитекст",
+ "apihelp-flow+view-topic-description": "Погл. тема.",
+ "apihelp-flow+view-topic-summary": "Погл. тема.",
+ "apihelp-flow+view-topic-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-topic-example-1": "Погл. [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Преглед на историјата на преработките на една тема.",
+ "apihelp-flow+view-topic-history-summary": "Преглед на историјата на преработките на една тема.",
+ "apihelp-flow+view-topic-history-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-topic-history-example-1": "Добијте ги преработките на објавите на [[Topic:S2tycnas4hcucw8w]] како викитекст",
+ "apihelp-flow+view-topic-summary-description": "Погл. опис на темата.",
+ "apihelp-flow+view-topic-summary-summary": "Погл. опис на темата.",
+ "apihelp-flow+view-topic-summary-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-topic-summary-param-revId": "Вчитај ја оваа преработка наместо најновата.",
+ "apihelp-flow+view-topic-summary-example-1": "Погл. описот на [[Topic:S2tycnas4hcucw8w]] како викитекст",
+ "apihelp-flow+view-topiclist-description": "Погл. список на теми.",
+ "apihelp-flow+view-topiclist-summary": "Погл. список на теми.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Насока на подредување на темите.",
+ "apihelp-flow+view-topiclist-param-sortby": "Можност за подредување на темите, или <kbd>updated</kbd> (подредени по ден/време на поднова) или <kbd>newest</kbd> (подредување по ден/време на создавање).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Зачувај ја подреденоста во корисничките нагодувања, ако е зададена.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Вредност на отстапката (во форматот UUID) од каде ќе се почне со давање на темите. Се користи само со подреденоста <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Вредност на отстапката (како ден и време на поднова на темата, во формат <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), од која ќе се почне со давање на темите. Се користи само со подреденоста <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Во исходот вклучува и почетна ставка.",
+ "apihelp-flow+view-topiclist-param-limit": "Колку теми да се дадат.",
+ "apihelp-flow+view-topiclist-param-toconly": "Дали да се одговори само со информациите потребни за преглед на содржини.",
+ "apihelp-flow+view-topiclist-param-format": "Во кој формат да се даде содржината.",
+ "apihelp-flow+view-topiclist-example-1": "Испиши ги темите во [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Претвори го текстот од викитекст во HMTL и обратно.",
+ "apihelp-flow-parsoid-utils-summary": "Претвори го текстот од викитекст во HMTL и обратно.",
+ "apihelp-flow-parsoid-utils-param-from": "Од кој формат да се претвори содржината.",
+ "apihelp-flow-parsoid-utils-param-to": "Во кој формат да се претвори содржината.",
+ "apihelp-flow-parsoid-utils-param-content": "Содржина за претворање.",
+ "apihelp-flow-parsoid-utils-param-title": "Наслов на страницата. Не може да се користи заедно со $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Назнака на страницата. Не може да се користи заедно со $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Претвори го викитекстот <nowiki>'''пример''' ''бла''</nowiki> во HTML",
+ "apihelp-query+flowinfo-description": "Дај основни информации за текот на една страница.",
+ "apihelp-query+flowinfo-summary": "Дај основни информации за текот на една страница.",
+ "apihelp-query+flowinfo-example-1": "Дај информации за текот на [[Talk:Sandbox]], [[Main Page|Главната страница]] и [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Испис на информации неопходни за отповикување на уредување на опис.",
+ "apihelp-flow+undo-edit-header-summary": "Испис на информации неопходни за отповикување на уредување на опис.",
+ "apihelp-flow+undo-edit-header-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
+ "apihelp-flow+undo-edit-header-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
+ "apihelp-flow+undo-edit-header-example-1": "Испиши информации за отповикување на уредување на описот во [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Испис на информации неопходни за отповикување на уредување на објава.",
+ "apihelp-flow+undo-edit-post-summary": "Испис на информации неопходни за отповикување на уредување на објава.",
+ "apihelp-flow+undo-edit-post-param-postId": "Назнака на објавата што треба да се отповика.",
+ "apihelp-flow+undo-edit-post-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
+ "apihelp-flow+undo-edit-post-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
+ "apihelp-flow+undo-edit-post-example-1": "Испиши информации за отповикување на уредување на објава на дадена тема",
+ "apihelp-flow+undo-edit-topic-summary-description": "Испис на информации неопходни за отповикување на уредување во опис на тема.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Испис на информации неопходни за отповикување на уредување во опис на тема.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Испиши информации за отповикување на уредување на опис на дадена тема",
+ "apierror-flow-safeallowcreationfailed": "Укажаната страница го нема овозможено Тек, а safeAllowCreation не успеа со: $1",
+ "apierror-flow-notenabled": "Укажаната страница го нема овозможено Тек."
+}
diff --git a/Flow/i18n/api/nb.json b/Flow/i18n/api/nb.json
new file mode 100644
index 00000000..c75eb1cc
--- /dev/null
+++ b/Flow/i18n/api/nb.json
@@ -0,0 +1,118 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Jeblad",
+ "Kingu",
+ "Jon Harald Søby"
+ ]
+ },
+ "apihelp-flow-description": "Tillat at aksjoner kan bli tatt på Flow-sider.",
+ "apihelp-flow-param-submodule": "Flow-undermodulene som skal kalles opp.",
+ "apihelp-flow-param-page": "Siden hvor en aksjon skal tas.",
+ "apihelp-flow-param-token": "Et token hentet fra [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Rediger beskrivelsen av «[[Talk:Sandbox]]»",
+ "apihelp-flow+close-open-topic-description": "Avskrevet til fordel for [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Tilstand for saken, enten «lock» eller «unlock».",
+ "apihelp-flow+close-open-topic-param-reason": "Årsaken til at emnet et låst eller åpnet.",
+ "apihelp-flow+edit-header-description": "Rediger beskrivelse av en tavle.",
+ "apihelp-flow+edit-header-param-prev_revision": "Revisjons-ID av den gjeldende beskrivelsens revisjon, for å sjekke for redigeringskollisjoner.",
+ "apihelp-flow+edit-header-param-content": "Innhold for beskrivelsen.",
+ "apihelp-flow+edit-header-param-format": "Format for beskrivelsen (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Rediger beskrivelsen av [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Rediger et innleggs innhold.",
+ "apihelp-flow+edit-post-param-postId": "Innleggs-ID.",
+ "apihelp-flow+edit-post-param-prev_revision": "Revisjons-ID av det gjeldende innleggets revisjon, for å sjekke for redigeringskollisjoner.",
+ "apihelp-flow+edit-post-param-content": "Innhold for innlegget.",
+ "apihelp-flow+edit-post-param-format": "Format for postens innhold (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Rediger en post i [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Rediger en saksoverskrift.",
+ "apihelp-flow+edit-title-param-prev_revision": "Revisjons-ID for den gjeldende tittelens revisjon, for å sjekke for redigeringskollisjoner.",
+ "apihelp-flow+edit-title-param-content": "Innhold for tittelen, i samme format som er tillatt for redigering av sammendrag (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Rediger tittelen til [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Rediger sakssammendragets innhold.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Revisjons-ID for gjeldende revisjon av sakssammendrag, hvis det finnes, for å sjekke for redigeringskonflikter.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Innhold for sammendraget.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format for sammendraget (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Rediger sammendraget til [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Låser eller åpner en Flow-sak.",
+ "apihelp-flow+lock-topic-param-moderationState": "Tilstand for saken, enten <kbd>lock</kbd> eller <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Grunn for å låse eller åpne en sak. Merk, Flow-klienten som er on-wiki bruker «Merket som løst», og legger valgfri ekstra informasjon i samendraget.",
+ "apihelp-flow+lock-topic-example-1": "Lås [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Moderer en Flow post.",
+ "apihelp-flow+moderate-post-param-moderationState": "Hvilket nivå på moderasjonen.",
+ "apihelp-flow+moderate-post-param-reason": "Grunnlag for moderering.",
+ "apihelp-flow+moderate-post-param-postId": "ID på innlegget som skal modereres.",
+ "apihelp-flow+moderate-post-example-1": "Slett et innlegg i saken [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderer en Flow-sak.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Hvilket nivå på moderasjonen.",
+ "apihelp-flow+moderate-topic-param-reason": "Grunnlag for moderering.",
+ "apihelp-flow+moderate-topic-example-1": "Slett saken [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Lager en ny Flow-sak på angitt arbeidsbord.",
+ "apihelp-flow+new-topic-param-topic": "Tekst for en ny saksoverskrift.",
+ "apihelp-flow+new-topic-param-content": "Innhold i sakens første svar.",
+ "apihelp-flow+new-topic-param-format": "Formatet på den nye sakens første svar (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Lag en ny sak på «[[Talk:Sandbox]]»",
+ "apihelp-flow+reply-description": "Svar på et innlegg.",
+ "apihelp-flow+reply-param-replyTo": "Innlegg-ID som det svares på.",
+ "apihelp-flow+reply-param-content": "Innhold for nytt innlegg.",
+ "apihelp-flow+reply-param-format": "Format for det nye innlegget (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Svar på et innlegg i [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-header-description": "Vis beskrivelse av en tavle.",
+ "apihelp-flow+view-header-param-revId": "Last inn denne revisjonen, istedenfor den nyeste.",
+ "apihelp-flow+view-header-example-1": "Hent beskrivelsen av [[Talk:Sandbox]] som wikitekst",
+ "apihelp-flow+view-post-description": "Vis innlegg",
+ "apihelp-flow+view-post-param-postId": "ID for innlegget som skal vises.",
+ "apihelp-flow+view-post-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-post-example-1": "Hent innholdet av et innlegg i [[Topic:S2tycnas4hcucw8w]] som wikitekst",
+ "apihelp-flow+view-post-history-description": "Vis revisjonshistorikken til et innlegg.",
+ "apihelp-flow+view-post-history-param-postId": "ID for innlegget hvor revisjonshistorikken skal vises.",
+ "apihelp-flow+view-post-history-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-post-history-example-1": "Hent revisjonene til et innlegg i [[Topic:S2tycnas4hcucw8w]] som wikitekst.",
+ "apihelp-flow+view-topic-description": "Vis en sak.",
+ "apihelp-flow+view-topic-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-topic-example-1": "Vis [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Vis revisjonshistorikken til en sak.",
+ "apihelp-flow+view-topic-history-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-topic-history-example-1": "Vis revisjonene til innlegg i [[Topic:S2tycnas4hcucw8w]] som wikitekst",
+ "apihelp-flow+view-topic-summary-description": "Vis et sakssammendrag.",
+ "apihelp-flow+view-topic-summary-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-topic-summary-param-revId": "Last inn denne revisjonen istedenfor den nyeste.",
+ "apihelp-flow+view-topic-summary-example-1": "Vis sammendraget til [[Topic:S2tycnas4hcucw8w]] som wikitekst",
+ "apihelp-flow+view-topiclist-description": "Vis en liste av saker.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Retningen for organisering av sakene.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opsjon for sortering av saker, enten <kbd>updated</kbd> (ordnet etter sakens tidspunkt for oppdatering), or <kbd>newest</kbd> (ordnet etter sakens tidspunkt for opprettelse).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Lagre sortby opsjonentil brukerinnstillinger, hvis den er satt.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Startverdi (i UUID format) for første sak; brukes bare med <kbd>newest</kbd> ordning",
+ "apihelp-flow+view-topiclist-param-offset": "Startverdi (som en saks tidsstempel for oppdatering, i <code>TS_MW</code> format (<code>YYYYMMDDHHMMSS</code>)), for start på henting av saker; brukes bare med <kbd>updated</kbd> ordning",
+ "apihelp-flow+view-topiclist-param-include-offset": "Inkluder oppføringen på startverdien i resultatet i tillegg",
+ "apihelp-flow+view-topiclist-param-limit": "Antall emner som hentes.",
+ "apihelp-flow+view-topiclist-param-toconly": "Om det skal svares kun med nødvendig informasjon for TOC.",
+ "apihelp-flow+view-topiclist-param-format": "Formatet som innholdet skal bruke.",
+ "apihelp-flow+view-topiclist-example-1": "List saker på [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Konverter tekst mellom wikitekst og HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format for å konvertere innhold fra.",
+ "apihelp-flow-parsoid-utils-param-to": "Format for å konvertere innhold til.",
+ "apihelp-flow-parsoid-utils-param-content": "Innhold som skal konverteres.",
+ "apihelp-flow-parsoid-utils-param-title": "Tittelen for siden. Kan ikke brukes sammen med <var>$1pageid</var>.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID for siden. Kan ikke brukes sammen med <var>$1title</var>.",
+ "apihelp-flow-parsoid-utils-example-1": "Konverter wikitekst <nowiki>'''lorem''' ''blah''</nowiki> til HTML",
+ "apihelp-query+flowinfo-description": "Hent grunnleggende Flow-informasjon om en side.",
+ "apihelp-query+flowinfo-example-1": "Hent Flow-informasjon om [[Talk:Sandbox]], [[Main Page]], og [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Hent nødvendig informasjon for å angre redigering av beskrivelsen.",
+ "apihelp-flow+undo-edit-header-param-startId": "Revisjons-ID for start av angring.",
+ "apihelp-flow+undo-edit-header-param-endId": "Revisjons-ID for slutt av angring.",
+ "apihelp-flow+undo-edit-header-example-1": "Hent informasjon om å angre en redigering av beskrivelsen på [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Hent nødvendig informasjon for å angre redigering av innlegget.",
+ "apihelp-flow+undo-edit-post-param-postId": "Innleggets-ID som skal angres.",
+ "apihelp-flow+undo-edit-post-param-startId": "Revisjons-ID for start av angring.",
+ "apihelp-flow+undo-edit-post-param-endId": "Revisjons-ID for slutt av angring.",
+ "apihelp-flow+undo-edit-post-example-1": "Hent informasjon om angringing av redigering på innlegg i en bestemt sak.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Hent informasjonen som er nødvendig for å angre redigering av sakens sammendrag.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Revisjons-ID for start av angring.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Revisjons-ID for slutt av angring.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Hent informasjon om angring av et redigert sakssammendrag i en spesifikk sak",
+ "apierror-flow-safeallowcreationfailed": "Den angitte siden har ikke Flow slått på, og safeAllowCreation mislyktes med: $1",
+ "apierror-flow-notenabled": "Den angitte siden har ikke Flow slått på."
+}
diff --git a/Flow/i18n/api/oc.json b/Flow/i18n/api/oc.json
new file mode 100644
index 00000000..b59a20e8
--- /dev/null
+++ b/Flow/i18n/api/oc.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31"
+ ]
+ },
+ "apihelp-flow+edit-post-param-postId": "ID del messatge.",
+ "apihelp-flow+edit-post-param-content": "Contengut pel messatge.",
+ "apihelp-flow+new-topic-example-1": "Crear un novèl subjècte sus [[Talk:Sandbox]]",
+ "apihelp-flow+view-post-description": "Afichar un messatge."
+}
diff --git a/Flow/i18n/api/pl.json b/Flow/i18n/api/pl.json
new file mode 100644
index 00000000..7359b931
--- /dev/null
+++ b/Flow/i18n/api/pl.json
@@ -0,0 +1,119 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chrumps",
+ "Quiddity",
+ "Tar Lócesilion",
+ "The Polish",
+ "Woytecr"
+ ]
+ },
+ "apihelp-flow-description": "Umożliwia dokonywanie akcji na stronach Flow.",
+ "apihelp-flow-param-submodule": "Podmoduł Flow do wywołania.",
+ "apihelp-flow-param-page": "Strona, na której dokonać akcji.",
+ "apihelp-flow-param-token": "Token pobrany z [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Edycja opisu \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Zdeprecjonowane na rzecz [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Stan w jaki wprowadzić wątek, \"lock\" lub \"unlock\".",
+ "apihelp-flow+close-open-topic-param-reason": "Powód zamknięcia lub otwarcia wątku.",
+ "apihelp-flow+edit-header-description": "Edycja opisu strony dyskusji.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID bieżącej wersji opisu, aby wykryć konflikt edycji.",
+ "apihelp-flow+edit-header-param-content": "Zawartość opisu.",
+ "apihelp-flow+edit-header-param-format": "Format opisu (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Zmień opis dyskusji [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Edycja treści wiadomości.",
+ "apihelp-flow+edit-post-param-postId": "ID wiadomości.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID bieżącej wersji wiadomości, aby wykryć konflikt edycji.",
+ "apihelp-flow+edit-post-param-content": "Treść wiadomości.",
+ "apihelp-flow+edit-post-param-format": "Format zawartości wiadomości (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Edytuj wiadomość w wątku [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Zmienia tytuł wątku.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID bieżącej wersji tytułu, aby wykryć konflikt edycji.",
+ "apihelp-flow+edit-title-param-content": "Zawartość tytułu, w takim samym formacie jaki jest dozwolony dla opisów zmian (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Zmień tytuł wątku [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Zmienia zawartość podsumowania wątku.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID bieżącej wersji podsumowania, aby wykryć konflikt edycji, jeżeli podano.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Treść podsumowania.",
+ "apihelp-flow+edit-topic-summary-param-format": "Format podsumowania (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Zmiana podsumowania wątku [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Zabezpiecz albo odbezpiecz wątek.",
+ "apihelp-flow+lock-topic-param-moderationState": "Stan, w jaki wprowadzić wątek, <kbd>lock</kbd> lub <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Powód zabezpieczenia lub odbezpieczenia wątku. Uwaga, istniejący na wiki program Flow używa opcji „Oznaczony jako załatwiony” oraz nadaje opcjonalne informacje jako jego podsumowanie.",
+ "apihelp-flow+lock-topic-example-1": "Zablokuj wątek [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Wykonuje akcję moderacyjną na wiadomości we Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "Rodzaj moderacji",
+ "apihelp-flow+moderate-post-param-reason": "Powód moderacji.",
+ "apihelp-flow+moderate-post-param-postId": "ID wiadomości do moderacji.",
+ "apihelp-flow+moderate-post-example-1": "Usuń wiadomość w wątku [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Wykonuje akcję moderacyjną na wątku we Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Rodzaj moderacji.",
+ "apihelp-flow+moderate-topic-param-reason": "Powód moderacji.",
+ "apihelp-flow+moderate-topic-example-1": "Usuń wątek [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Tworzy nowy wątek Flow w danym cyklu pracy.",
+ "apihelp-flow+new-topic-param-topic": "Tekst tytułu nowego wątku.",
+ "apihelp-flow+new-topic-param-content": "Treść pierwszej wiadomości w wątku.",
+ "apihelp-flow+new-topic-param-format": "Format pierwszej wiadomości wątku (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Załóż nowy wątek na [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Odpowiedzi na post.",
+ "apihelp-flow+reply-param-replyTo": "ID wiadomości, na którą odpowiedzieć.",
+ "apihelp-flow+reply-param-content": "Treść nowej wiadomości.",
+ "apihelp-flow+reply-param-format": "Format nowej wiadomości (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Umieść odpowiedź na wiadomość w wątku [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-header-description": "Zobacz opis strony dyskusji.",
+ "apihelp-flow+view-header-param-revId": "Pobierz tę wersję zamiast najnowszej.",
+ "apihelp-flow+view-header-example-1": "Pobierz opis [[Talk:Sandbox]] jako wikitext",
+ "apihelp-flow+view-post-description": "Pokaż post",
+ "apihelp-flow+view-post-param-postId": "ID wiadomości do wyświetlenia.",
+ "apihelp-flow+view-post-param-format": "Format, w jakim zwrócić zawartość.",
+ "apihelp-flow+view-post-example-1": "Pobierz treść wiadomości w wątku [[Topic:S2tycnas4hcucw8w]] jako wikitext",
+ "apihelp-flow+view-post-history-description": "Zobacz historię zmian tej wiadomości.",
+ "apihelp-flow+view-post-history-param-postId": "ID wiadomości, której zobaczyć historię.",
+ "apihelp-flow+view-post-history-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-post-history-example-1": "Pobierz wersje wiadomości w wątku [[Topic:S2tycnas4hcucw8w]] jako wikitext",
+ "apihelp-flow+view-topic-description": "Pokaż wątek",
+ "apihelp-flow+view-topic-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-topic-example-1": "Zobacz [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Zobacz historię zmian w wątku.",
+ "apihelp-flow+view-topic-history-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-topic-history-example-1": "Pobierz wersje wiadomości w wątku [[Topic:S2tycnas4hcucw8w]] jako wikitext",
+ "apihelp-flow+view-topic-summary-description": "Zobacz podsumowanie wątku.",
+ "apihelp-flow+view-topic-summary-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-topic-summary-param-revId": "Pobierz tę wersję zamiast najnowszej.",
+ "apihelp-flow+view-topic-summary-example-1": "Zobacz podsumowanie wątku [[Topic:S2tycnas4hcucw8w]] jako wikitext",
+ "apihelp-flow+view-topiclist-description": "Wyświetl listę wątków",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Kierunek sortowania wątków.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opcja sortowania wątków, <kbd>updated</kbd> (według czasu ostatniej zmiany w wątku) lub <kbd>newest</kbd> (według czasu utworzenia wątku).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Zapisz ustawienie opcji sortby w preferencjach, jeżeli ustawiona.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Wartość od jakiej zaczynać pobieranie wątków (w formacie UUID); działa tylko z sortowaniem <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Wartość od jakiej zaczynać pobieranie wątków (jako czas ostatniej zmiany w wątku, w formacie <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)); działa tylko z sortowaniem <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Czy dołączyć element offset do wyników.",
+ "apihelp-flow+view-topiclist-param-limit": "Liczba wątków do pobrania.",
+ "apihelp-flow+view-topiclist-param-toconly": "Czy wysłać w odpowiedzi tylko informacje wymagane do utworzenia spisu treści.",
+ "apihelp-flow+view-topiclist-param-format": "Format zwracanej zawartości.",
+ "apihelp-flow+view-topiclist-example-1": "Lista wątków na [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Konwersja między wikikodem a HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format z jakiego skonwertować treść.",
+ "apihelp-flow-parsoid-utils-param-to": "Format na jaki skonwertować treść.",
+ "apihelp-flow-parsoid-utils-param-content": "Treść do skonwertowania.",
+ "apihelp-flow-parsoid-utils-param-title": "Tytuł strony. Tego parametru nie można używać jednocześnie z $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID strony. Tego parametru nie można używać jednocześnie z $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Skonwertuj wikikod <nowiki>'''lorem''' ''blah''</nowiki> na HTML",
+ "apihelp-query+flowinfo-description": "Pobierz ogólne informacje o stronie związane z Flow.",
+ "apihelp-query+flowinfo-example-1": "Pobierz informacje Flow o [[Talk:Sandbox]], [[Main Page]] oraz [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Pobiera informacje niezbędne do wycofania edycji opisu.",
+ "apihelp-flow+undo-edit-header-param-startId": "ID wersji, od której wycofać.",
+ "apihelp-flow+undo-edit-header-param-endId": "ID wersji, do której wycofać.",
+ "apihelp-flow+undo-edit-header-example-1": "Pobierz informacje potrzebne do wycofania edycji opisu [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Pobiera informacje niezbędne do wycofania edycji wiadomości.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID wiadomości, w której wycofać zmiany.",
+ "apihelp-flow+undo-edit-post-param-startId": "ID wersji, od której wycofać.",
+ "apihelp-flow+undo-edit-post-param-endId": "ID wersji, do której wycofać.",
+ "apihelp-flow+undo-edit-post-example-1": "Pobierz informacje potrzebne do wycofania edycji wiadomości w konkretnym wątku.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Pobierz informacje potrzebne do wycofania edycji podsumowania wątku.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "ID wersji, od której wycofać.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "ID wersji, do której wycofać.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Pobierz informacje potrzebne do wycofania edycji podsumowania konkretnego wątku.",
+ "apierror-flow-safeallowcreationfailed": "Podana strona nie ma włączonego Flow, a procedura safeAllowCreation nie powiodła się: $1",
+ "apierror-flow-notenabled": "Podana strona nie ma włączonego Flow."
+}
diff --git a/Flow/i18n/api/pt-br.json b/Flow/i18n/api/pt-br.json
new file mode 100644
index 00000000..b5d9a35e
--- /dev/null
+++ b/Flow/i18n/api/pt-br.json
@@ -0,0 +1,141 @@
+{
+ "@metadata": {
+ "authors": [
+ "Araceletorres",
+ "Dianakc",
+ "Quiddity",
+ "Felipe L. Ewald"
+ ]
+ },
+ "apihelp-flow-description": "Permite que ações sejam realizadas nas páginas Flow.",
+ "apihelp-flow-summary": "Permite que ações sejam realizadas nas páginas Flow.",
+ "apihelp-flow-param-submodule": "O submódulo do Flow a ser invocado.",
+ "apihelp-flow-param-page": "A página na qual será realizada a ação.",
+ "apihelp-flow-param-token": "Um token recuperado de [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Editar a descrição de \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Depreciado em favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Depreciado em favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Estado em que o tópico será colocado, \"bloqueado\" ou \"desbloqueado\".",
+ "apihelp-flow+close-open-topic-param-reason": "Motivo para bloquear ou desbloquear o tópico.",
+ "apihelp-flow+edit-header-description": "Editar a descrição de um espaço de discussão.",
+ "apihelp-flow+edit-header-summary": "Editar a descrição de um espaço de discussão.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID da revisão atual da revisão da descrição, para verificar conflitos de edição.",
+ "apihelp-flow+edit-header-param-content": "Conteúdo para a descrição.",
+ "apihelp-flow+edit-header-param-format": "Formato da descrição (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Editar a descrição de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Edita o conteúdo da publicação.",
+ "apihelp-flow+edit-post-summary": "Edita o conteúdo da publicação.",
+ "apihelp-flow+edit-post-param-postId": "ID da publicação.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID da revisão atual da revisão da publicação, para verificar conflitos de edição.",
+ "apihelp-flow+edit-post-param-content": "Conteúdo para a publicação.",
+ "apihelp-flow+edit-post-param-format": "Formato do conteúdo da publicação (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Editar uma publicação em [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edita o título de um tópico.",
+ "apihelp-flow+edit-title-summary": "Edita o título de um tópico.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID da revisão atual da revisão do título, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-title-param-content": "Conteúdo para o título, no mesmo formato permitido para os resumos de edição (tópico-título-texto wiki).",
+ "apihelp-flow+edit-title-example-1": "Editar o título de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Edita o conteúdo do resumo de uma publicação.",
+ "apihelp-flow+edit-topic-summary-summary": "Edita o conteúdo do resumo de uma publicação.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID da revisão atual da revisão do resumo do tópico, se houver, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Conteúdo para o resumo.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formato do sumário (texto wiki|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Editar o resumo de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Bloqueia ou desbloqueia um tópico do Flow.",
+ "apihelp-flow+lock-topic-summary": "Bloqueia ou desbloqueia um tópico do Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Estado em que o tópico será colocado, ou <kbd>lock</kbd> ou <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Motivo para bloquear ou desbloquear o tópico. Observe que o cliente on-wiki do Flow usa \"Marcado como resolvido\" aqui e coloca informações adicionais opcionais no resumo.",
+ "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modera uma publicação do Flow.",
+ "apihelp-flow+moderate-post-summary": "Modera uma publicação do Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A qual nível moderar.",
+ "apihelp-flow+moderate-post-param-reason": "Motivo para moderação.",
+ "apihelp-flow+moderate-post-param-postId": "ID da publicação para moderar.",
+ "apihelp-flow+moderate-post-example-1": "Excluir uma publicação no tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modera um tópico do Flow.",
+ "apihelp-flow+moderate-topic-summary": "Modera um tópico do Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A qual nível moderar.",
+ "apihelp-flow+moderate-topic-param-reason": "Motivo para moderação.",
+ "apihelp-flow+moderate-topic-example-1": "Excluir o tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Criar um novo tópico do Flow no fluxo de trabalho dado.",
+ "apihelp-flow+new-topic-summary": "Criar um novo tópico do Flow no fluxo de trabalho dado.",
+ "apihelp-flow+new-topic-param-topic": "Texto para novo título de tópico.",
+ "apihelp-flow+new-topic-param-content": "Conteúdo para a resposta inicial do tópico.",
+ "apihelp-flow+new-topic-param-format": "Formato da resposta inicial do novo tópico (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Criar um novo tópico em [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Responde a uma publicação.",
+ "apihelp-flow+reply-summary": "Responde a uma publicação.",
+ "apihelp-flow+reply-param-replyTo": "ID da publicação para responder.",
+ "apihelp-flow+reply-param-content": "Conteúdo para nova publicação.",
+ "apihelp-flow+reply-param-format": "Formato da nova publicação (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Responder a uma publicação no [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-header-description": "Ver descrição de um espaço de discussão.",
+ "apihelp-flow+view-header-summary": "Ver descrição de um espaço de discussão.",
+ "apihelp-flow+view-header-param-revId": "Carregar esta revisão, em vez da mais recente.",
+ "apihelp-flow+view-header-example-1": "Obtém a descrição de [[Talk:Sandbox]] como texto wiki",
+ "apihelp-flow+view-post-description": "Ver uma publicação.",
+ "apihelp-flow+view-post-summary": "Ver uma publicação.",
+ "apihelp-flow+view-post-param-postId": "Id da publicação para ver.",
+ "apihelp-flow+view-post-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-post-example-1": "Obter o conteúdo de uma publicação em [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-post-history-description": "Ver o histórico de revisão de uma publicação.",
+ "apihelp-flow+view-post-history-summary": "Ver o histórico de revisão de uma publicação.",
+ "apihelp-flow+view-post-history-param-postId": "ID da publicação para a qual deseja visualizar o histórico de revisões.",
+ "apihelp-flow+view-post-history-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-post-history-example-1": "Obter a revisão de uma publicação em [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-topic-description": "Ver um tópico.",
+ "apihelp-flow+view-topic-summary": "Ver um tópico.",
+ "apihelp-flow+view-topic-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Ver o histórico de revisão de um tópico.",
+ "apihelp-flow+view-topic-history-summary": "Ver o histórico de revisão de um tópico.",
+ "apihelp-flow+view-topic-history-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-topic-history-example-1": "Ver as revisões das publicações em [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-topic-summary-description": "Ver o resumo de um tópico.",
+ "apihelp-flow+view-topic-summary-summary": "Ver o resumo de um tópico.",
+ "apihelp-flow+view-topic-summary-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-topic-summary-param-revId": "Carregar esta revisão, em vez da mais recente.",
+ "apihelp-flow+view-topic-summary-example-1": "Ver o resumo de [[Topic:S2tycnas4hcucw8w]] como texto wiki",
+ "apihelp-flow+view-topiclist-description": "Ver uma lista de tópicos.",
+ "apihelp-flow+view-topiclist-summary": "Ver uma lista de tópicos.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Direção para ordenar os tópicos.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opção de classificação dos tópicos, ou <kbd>updated</kbd> (ordenados por tempo de atualização do tópico) ou <kbd>newest</kbd> (ordenados por tempo de criação do tópico).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Se definido, salva a opção de ordenação nas preferências do usuário.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Valor inicial (no formato UUID) para a obtenção de tópicos; usado somente com a ordenação <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Valor inicial (como um tópico para atualizar data/hora, no formato <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), para a obtenção de tópicos; usado somente com a ordenação <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Inclui também o item offset nos resultados.",
+ "apihelp-flow+view-topiclist-param-limit": "Número de tópicos para obter.",
+ "apihelp-flow+view-topiclist-param-toconly": "Se deve responder apenas as informações necessárias para o TOC.",
+ "apihelp-flow+view-topiclist-param-format": "Formato no qual o conteúdo deverá ser retornado.",
+ "apihelp-flow+view-topiclist-example-1": "Listar os tópicos em [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Converter texto entre texto wiki e HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Converter texto entre texto wiki e HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formato do qual o conteúdo deverá ser convertido.",
+ "apihelp-flow-parsoid-utils-param-to": "Formato no qual o conteúdo deverá ser convertido.",
+ "apihelp-flow-parsoid-utils-param-content": "Conteúdo a ser convertido.",
+ "apihelp-flow-parsoid-utils-param-title": "Título da página. Não pode ser usado juntamente com $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID da página. Não pode ser usado juntamente com $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Converte texto wiki <nowiki>'''lorem''' ''blah''</nowiki> para HTML",
+ "apihelp-query+flowinfo-description": "Obter informações básicas do Flow sobre uma página.",
+ "apihelp-query+flowinfo-summary": "Obter informações básicas do Flow sobre uma página.",
+ "apihelp-query+flowinfo-example-1": "Obter informações do Flow sobre [[Talk:Sandbox]], [[Main Page]] e [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Recuperar informações necessárias para desfazer edições de descrições.",
+ "apihelp-flow+undo-edit-header-summary": "Recuperar informações necessárias para desfazer edições de descrições.",
+ "apihelp-flow+undo-edit-header-param-startId": "ID de revisão para começar a desfazer.",
+ "apihelp-flow+undo-edit-header-param-endId": "ID de revisão para terminar de desfazer.",
+ "apihelp-flow+undo-edit-header-example-1": "Obter informação sobre desfazer uma edição de descrição em [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Recuperar informações necessárias para desfazer edições de uma publicação.",
+ "apihelp-flow+undo-edit-post-summary": "Recuperar informações necessárias para desfazer edições de uma publicação.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID da publicação a ser desfeita.",
+ "apihelp-flow+undo-edit-post-param-startId": "ID de revisão para começar a desfazer.",
+ "apihelp-flow+undo-edit-post-param-endId": "ID de revisão para terminar de desfazer.",
+ "apihelp-flow+undo-edit-post-example-1": "Obter informação sobre como desfazer uma edição de uma publicação num tópico específico.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Recuperar informações necessárias para desfazer edições do resumo de tópico.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Recuperar informações necessárias para desfazer edições do resumo de tópico.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "ID de revisão para começar a desfazer.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "ID de revisão para terminar de desfazer.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Obter informação sobre como desfazer uma edição de um resumo de tópico num tópico específico",
+ "apierror-flow-safeallowcreationfailed": "A página fornecida não tem o Flow ativado e safeAllowCreation falhou com: $1",
+ "apierror-flow-notenabled": "A página fornecida não tem o Flow ativado."
+}
diff --git a/Flow/i18n/api/pt.json b/Flow/i18n/api/pt.json
new file mode 100644
index 00000000..51a44785
--- /dev/null
+++ b/Flow/i18n/api/pt.json
@@ -0,0 +1,144 @@
+{
+ "@metadata": {
+ "authors": [
+ "Diego Queiroz",
+ "Fúlvio",
+ "He7d3r",
+ "Imperadeiro90",
+ "Lijealso",
+ "Vitorvicentevalente",
+ "Hamilton Abreu"
+ ]
+ },
+ "apihelp-flow-description": "Permite que sejam realizadas ações nas páginas que utilizam o Flow.",
+ "apihelp-flow-summary": "Permite que sejam realizadas ações nas páginas que utilizam o Flow.",
+ "apihelp-flow-param-submodule": "Submódulo do Flow a ser invocado.",
+ "apihelp-flow-param-page": "A página sobre a qual será realizada uma ação.",
+ "apihelp-flow-param-token": "Uma chave obtida de [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Editar a descrição de \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Descontinuado e substituído por [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Descontinuado e substituído por [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Estado em que o tópico será colocado; \"lock\" (trancado) ou \"unlock\" (destrancado).",
+ "apihelp-flow+close-open-topic-param-reason": "Motivo para trancar ou destrancar o tópico.",
+ "apihelp-flow+edit-header-description": "Edita a descrição de um espaço de discussão.",
+ "apihelp-flow+edit-header-summary": "Edita a descrição de um espaço de discussão.",
+ "apihelp-flow+edit-header-param-prev_revision": "Identificador da revisão atual da descrição, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-header-param-content": "Conteúdo para a descrição.",
+ "apihelp-flow+edit-header-param-format": "Formato da descrição (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Editar a descrição de [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Edita o conteúdo de uma mensagem.",
+ "apihelp-flow+edit-post-summary": "Edita o conteúdo de uma mensagem.",
+ "apihelp-flow+edit-post-param-postId": "Identificador da mensagem.",
+ "apihelp-flow+edit-post-param-prev_revision": "Identificador da revisão atual da mensagem, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-post-param-content": "Conteúdo para a mensagem.",
+ "apihelp-flow+edit-post-param-format": "Formato do conteúdo da mensagem (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Editar uma mensagem do tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Edita o título de um tópico.",
+ "apihelp-flow+edit-title-summary": "Edita o título de um tópico.",
+ "apihelp-flow+edit-title-param-prev_revision": "Identificador da revisão atual do título, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-title-param-content": "Conteúdo para o título, no mesmo formato permitido para resumos de edição (tópico-título-texto wiki).",
+ "apihelp-flow+edit-title-example-1": "Editar o título de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Edita o conteúdo do resumo de um tópico.",
+ "apihelp-flow+edit-topic-summary-summary": "Edita o conteúdo do resumo de um tópico.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Identificador da revisão atual do resumo do tópico, se existir, para verificar conflitos entre edições.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Conteúdo para o resumo.",
+ "apihelp-flow+edit-topic-summary-param-format": "Formato do resumo (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Editar o resumo de [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Trancar ou destrancar um tópico do Flow.",
+ "apihelp-flow+lock-topic-summary": "Trancar ou destrancar um tópico do Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Estado em que o tópico será colocado; <kbd>lock</kbd> (trancado) ou <kbd>unlock</kbd> (destrancado).",
+ "apihelp-flow+lock-topic-param-reason": "Motivo para trancar ou destrancar o tópico. Note que o cliente Flow da wiki utiliza aqui \"Marcado como resolvido\", e, se desejado, coloca informação adicional no resumo.",
+ "apihelp-flow+lock-topic-example-1": "Trancar [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modera uma mensagem Flow.",
+ "apihelp-flow+moderate-post-summary": "Modera uma mensagem Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "A que nível moderar.",
+ "apihelp-flow+moderate-post-param-reason": "Razão para moderação.",
+ "apihelp-flow+moderate-post-param-postId": "Identificador da mensagem a ser moderada.",
+ "apihelp-flow+moderate-post-example-1": "Eliminar uma mensagem do tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Modera um tópico do Flow.",
+ "apihelp-flow+moderate-topic-summary": "Modera um tópico do Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "A que nível moderar.",
+ "apihelp-flow+moderate-topic-param-reason": "Razão para moderação.",
+ "apihelp-flow+moderate-topic-example-1": "Eliminar o tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Cria um novo tópico do Flow no fluxo de trabalho dado.",
+ "apihelp-flow+new-topic-summary": "Cria um novo tópico do Flow no fluxo de trabalho dado.",
+ "apihelp-flow+new-topic-param-topic": "Texto para título do novo tópico.",
+ "apihelp-flow+new-topic-param-content": "Conteúdo para a resposta inicial do tópico.",
+ "apihelp-flow+new-topic-param-format": "Formato da resposta inicial do tópico novo (wikitext|html).",
+ "apihelp-flow+new-topic-example-1": "Criar um novo tópico em [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Respostas a uma mensagem.",
+ "apihelp-flow+reply-summary": "Respostas a uma mensagem.",
+ "apihelp-flow+reply-param-replyTo": "Identificador da mensagem que será respondida.",
+ "apihelp-flow+reply-param-content": "Conteúdo para nova mensagem.",
+ "apihelp-flow+reply-param-format": "Formato da mensagem nova (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Resposta a uma mensagem no tópico [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-header-description": "Ver uma descrição do espaço de discussão.",
+ "apihelp-flow+view-header-summary": "Ver uma descrição do espaço de discussão.",
+ "apihelp-flow+view-header-param-revId": "Carregar esta revisão, em vez da mais recente.",
+ "apihelp-flow+view-header-example-1": "Obter a descrição de [[Talk:Sandbox]] em texto wiki",
+ "apihelp-flow+view-post-description": "Ver uma mensagem.",
+ "apihelp-flow+view-post-summary": "Ver uma mensagem.",
+ "apihelp-flow+view-post-param-postId": "Identificador da mensagem a ser vista.",
+ "apihelp-flow+view-post-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-post-example-1": "Obter o conteúdo de uma mensagem do tópico [[Topic:S2tycnas4hcucw8w]] em texto wiki",
+ "apihelp-flow+view-post-history-description": "Ver o histórico de revisões de uma mensagem.",
+ "apihelp-flow+view-post-history-summary": "Ver o histórico de revisões de uma mensagem.",
+ "apihelp-flow+view-post-history-param-postId": "Identificador da mensagem para a qual será visto o histórico de revisões.",
+ "apihelp-flow+view-post-history-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-post-history-example-1": "Obter as revisões de uma mensagem de [[Topic:S2tycnas4hcucw8w]] em texto wiki",
+ "apihelp-flow+view-topic-description": "Ver um tópico.",
+ "apihelp-flow+view-topic-summary": "Ver um tópico.",
+ "apihelp-flow+view-topic-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Ver o histórico de revisões de um tópico.",
+ "apihelp-flow+view-topic-history-summary": "Ver o histórico de revisões de um tópico.",
+ "apihelp-flow+view-topic-history-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-topic-history-example-1": "Obter as revisões das mensagens de [[Topic:S2tycnas4hcucw8w]] em texto wiki",
+ "apihelp-flow+view-topic-summary-description": "Ver um resumo do tópico.",
+ "apihelp-flow+view-topic-summary-summary": "Ver um resumo do tópico.",
+ "apihelp-flow+view-topic-summary-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-topic-summary-param-revId": "Carregar esta revisão, em vez da mais recente.",
+ "apihelp-flow+view-topic-summary-example-1": "Ver o resumo de [[Topic:S2tycnas4hcucw8w]] em texto wiki",
+ "apihelp-flow+view-topiclist-description": "Ver uma lista de tópicos.",
+ "apihelp-flow+view-topiclist-summary": "Ver uma lista de tópicos.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Direção de ordenação dos tópicos.",
+ "apihelp-flow+view-topiclist-param-sortby": "Opções de ordenação dos tópicos; <kbd>updated</kbd> (ordenados pela hora de atualização do tópico) ou <kbd>newest</kbd> (ordenados pela hora de criação do tópico).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Gravar a opção de ordenação nas preferências do utilizador, se estiver definida.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Posição inicial (no formato UUID) a partir da qual iniciar a obtenção de tópicos; utilizada somente com a ordenação <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Posição inicial (na forma de data e hora de um tópico, em <code>TS_MW</code> formato (<code>AAAAMMDDHHMMSS</code>)), a partir da qual iniciar a obtenção de tópicos; usada somente com a ordenação <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Também inclui nos resultados o elemento da posição inicial.",
+ "apihelp-flow+view-topiclist-param-limit": "Número de tópicos a obter.",
+ "apihelp-flow+view-topiclist-param-toconly": "Responder, ou não, só com a informação necessária para o índice.",
+ "apihelp-flow+view-topiclist-param-format": "Formato em que o conteúdo deverá ser devolvido.",
+ "apihelp-flow+view-topiclist-example-1": "Listar os tópicos em [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Converter texto entre texto wiki e HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Converter texto entre texto wiki e HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Formato a partir do qual o conteúdo deverá ser convertido.",
+ "apihelp-flow-parsoid-utils-param-to": "O formato para o qual o conteúdo deverá ser convertido.",
+ "apihelp-flow-parsoid-utils-param-content": "Conteúdo a ser convertido.",
+ "apihelp-flow-parsoid-utils-param-title": "Título da página. Não pode ser usado em conjunto com $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Identificador da página. Não pode ser utilizado em conjunto com $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Converter o texto wiki <nowiki>'''lorem''' ''blá''</nowiki> para HTML",
+ "apihelp-query+flowinfo-description": "Obter informações básicas do Flow sobre uma página.",
+ "apihelp-query+flowinfo-summary": "Obter informações básicas do Flow sobre uma página.",
+ "apihelp-query+flowinfo-example-1": "Obter informações do Flow sobre [[Talk:Sandbox]], [[Main Page]] e [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Obter a informação necessária para desfazer edições de descrições.",
+ "apihelp-flow+undo-edit-header-summary": "Obter a informação necessária para desfazer edições de descrições.",
+ "apihelp-flow+undo-edit-header-param-startId": "Identificador da revisão a partir da qual começar a desfazer.",
+ "apihelp-flow+undo-edit-header-param-endId": "Identificador da revisão na qual parar de desfazer.",
+ "apihelp-flow+undo-edit-header-example-1": "Obter informação sobre desfazer uma edição de descrição em [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Obter a informação necessária para desfazer a edição de uma mensagem.",
+ "apihelp-flow+undo-edit-post-summary": "Obter a informação necessária para desfazer a edição de uma mensagem.",
+ "apihelp-flow+undo-edit-post-param-postId": "Identificador da mensagem a ser desfeita.",
+ "apihelp-flow+undo-edit-post-param-startId": "Identificador da revisão a partir da qual começar a desfazer.",
+ "apihelp-flow+undo-edit-post-param-endId": "Identificador da revisão na qual parar de desfazer.",
+ "apihelp-flow+undo-edit-post-example-1": "Obter informação sobre desfazer a edição de uma mensagem num tópico específico",
+ "apihelp-flow+undo-edit-topic-summary-description": "Obter a informação necessária para desfazer edições de resumos de tópicos.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Obter a informação necessária para desfazer edições de resumos de tópicos.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Identificador da revisão a partir da qual começar a desfazer.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Identificador da revisão na qual parar de desfazer.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Obter a informação necessária para desfazer a edição do resumo de um tópico específico.",
+ "apierror-flow-safeallowcreationfailed": "A página fornecida não tem o Flow ativado e safeAllowCreation falhou com: $1",
+ "apierror-flow-notenabled": "A página fornecida não tem o Flow ativado."
+}
diff --git a/Flow/i18n/api/qqq.json b/Flow/i18n/api/qqq.json
new file mode 100644
index 00000000..171ff71e
--- /dev/null
+++ b/Flow/i18n/api/qqq.json
@@ -0,0 +1,147 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Brad Jorsch",
+ "Matthias Mullie",
+ "Nemo bis",
+ "Quiddity",
+ "IoannisKydonis",
+ "Purodha",
+ "Alexander Jones",
+ "Erik Bernhardson",
+ "Liuxinyu970226"
+ ]
+ },
+ "apihelp-flow-description": "{{doc-apihelp-description|flow}}",
+ "apihelp-flow-summary": "{{doc-apihelp-summary|flow}}",
+ "apihelp-flow-param-submodule": "{{doc-apihelp-param|flow|submodule}}",
+ "apihelp-flow-param-page": "{{doc-apihelp-param|flow|page}}",
+ "apihelp-flow-param-token": "{{doc-apihelp-param|flow|token}}",
+ "apihelp-flow-example-1": "{{doc-apihelp-example|flow}} (don't translate the [[Talk:Sandbox]] part, that's the name of the page for the API example)",
+ "apihelp-flow+close-open-topic-description": "{{doc-apihelp-description|flow+close-open-topic}}",
+ "apihelp-flow+close-open-topic-summary": "{{doc-apihelp-summary|flow+close-open-topic}}",
+ "apihelp-flow+close-open-topic-param-moderationState": "{{doc-apihelp-param|flow+close-open-topic|moderationState}}",
+ "apihelp-flow+close-open-topic-param-reason": "{{doc-apihelp-param|flow+close-open-topic|reason}}",
+ "apihelp-flow+edit-header-description": "{{doc-apihelp-description|flow+edit-header}}",
+ "apihelp-flow+edit-header-summary": "{{doc-apihelp-summary|flow+edit-header}}",
+ "apihelp-flow+edit-header-param-prev_revision": "{{doc-apihelp-param|flow+edit-header|prev_revision}}",
+ "apihelp-flow+edit-header-param-content": "{{doc-apihelp-param|flow+edit-header|content}}",
+ "apihelp-flow+edit-header-param-format": "{{doc-important|Do not alter the string \"<code><nowiki>(wikitext|html)</nowiki></code>\" in your translation.}}\n----\n{{doc-apihelp-param|flow+edit-header|format}}",
+ "apihelp-flow+edit-header-example-1": "{{doc-apihelp-example|flow+edit-header}}",
+ "apihelp-flow+edit-post-description": "{{doc-apihelp-description|flow+edit-post}}",
+ "apihelp-flow+edit-post-summary": "{{doc-apihelp-summary|flow+edit-post}}",
+ "apihelp-flow+edit-post-param-postId": "{{doc-apihelp-param|flow+edit-post|postId}}",
+ "apihelp-flow+edit-post-param-prev_revision": "{{doc-apihelp-param|flow+edit-post|prev_revision}}",
+ "apihelp-flow+edit-post-param-content": "{{doc-apihelp-param|flow+edit-post|content}}",
+ "apihelp-flow+edit-post-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+edit-post|format}}",
+ "apihelp-flow+edit-post-example-1": "{{doc-apihelp-example|flow+edit-post}}",
+ "apihelp-flow+edit-title-description": "{{doc-apihelp-description|flow+edit-title}}",
+ "apihelp-flow+edit-title-summary": "{{doc-apihelp-summary|flow+edit-title}}",
+ "apihelp-flow+edit-title-param-prev_revision": "{{doc-apihelp-param|flow+edit-title|prev_revision}}",
+ "apihelp-flow+edit-title-param-content": "{{doc-apihelp-param|flow+edit-title|content}}\n'topic-title-wikitext' is the allowed format and should not be translated.",
+ "apihelp-flow+edit-title-example-1": "{{doc-apihelp-example|flow+edit-title}}",
+ "apihelp-flow+edit-topic-summary-description": "{{doc-apihelp-description|flow+edit-topic-summary}}",
+ "apihelp-flow+edit-topic-summary-summary": "{{doc-apihelp-summary|flow+edit-topic-summary}}",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "{{doc-apihelp-param|flow+edit-topic-summary|prev_revision}}",
+ "apihelp-flow+edit-topic-summary-param-summary": "{{doc-apihelp-param|flow+edit-topic-summary|summary}}",
+ "apihelp-flow+edit-topic-summary-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+edit-topic-summary|format}}",
+ "apihelp-flow+edit-topic-summary-example-1": "{{doc-apihelp-example|flow+edit-topic-summary}}",
+ "apihelp-flow+lock-topic-description": "{{doc-apihelp-description|flow+lock-topic}}",
+ "apihelp-flow+lock-topic-summary": "{{doc-apihelp-summary|flow+lock-topic}}",
+ "apihelp-flow+lock-topic-param-moderationState": "{{doc-apihelp-param|flow+lock-topic|moderationState}}",
+ "apihelp-flow+lock-topic-param-reason": "{{doc-apihelp-param|flow+lock-topic|reason}}",
+ "apihelp-flow+lock-topic-example-1": "{{doc-apihelp-example|flow+lock-topic}}",
+ "apihelp-flow+moderate-post-description": "{{doc-apihelp-description|flow+moderate-post}}",
+ "apihelp-flow+moderate-post-summary": "{{doc-apihelp-summary|flow+moderate-post}}",
+ "apihelp-flow+moderate-post-param-moderationState": "{{doc-apihelp-param|flow+moderate-post|moderationState}}",
+ "apihelp-flow+moderate-post-param-reason": "{{doc-apihelp-param|flow+moderate-post|reason}}",
+ "apihelp-flow+moderate-post-param-postId": "{{doc-apihelp-param|flow+moderate-post|postId}}",
+ "apihelp-flow+moderate-post-example-1": "{{doc-apihelp-example|flow+moderate-post}}",
+ "apihelp-flow+moderate-topic-description": "{{doc-apihelp-description|flow+moderate-topic}}",
+ "apihelp-flow+moderate-topic-summary": "{{doc-apihelp-summary|flow+moderate-topic}}",
+ "apihelp-flow+moderate-topic-param-moderationState": "{{doc-apihelp-param|flow+moderate-topic|moderationState}}",
+ "apihelp-flow+moderate-topic-param-reason": "{{doc-apihelp-param|flow+moderate-topic|reason}}",
+ "apihelp-flow+moderate-topic-example-1": "{{doc-apihelp-example|flow+moderate-topic}}",
+ "apihelp-flow+new-topic-description": "{{doc-apihelp-description|flow+new-topic}}",
+ "apihelp-flow+new-topic-summary": "{{doc-apihelp-summary|flow+new-topic}}",
+ "apihelp-flow+new-topic-param-topic": "{{doc-apihelp-param|flow+new-topic|topic}}",
+ "apihelp-flow+new-topic-param-content": "{{doc-apihelp-param|flow+new-topic|content}}",
+ "apihelp-flow+new-topic-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+new-topic|format}}\n----\nA \"new topic\" is a flow item. It is similar to a new Thread in LiquidThreads, or a new Section in standard wikitext talkpages.",
+ "apihelp-flow+new-topic-example-1": "{{doc-apihelp-example|flow+new-topic}}",
+ "apihelp-flow+reply-description": "{{doc-apihelp-description|flow+reply}}",
+ "apihelp-flow+reply-summary": "{{doc-apihelp-summary|flow+reply}}",
+ "apihelp-flow+reply-param-replyTo": "{{doc-apihelp-param|flow+reply|replyTo}}",
+ "apihelp-flow+reply-param-content": "{{doc-apihelp-param|flow+reply|content}}",
+ "apihelp-flow+reply-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+reply|format}}",
+ "apihelp-flow+reply-example-1": "{{doc-apihelp-example|flow+reply}}",
+ "apihelp-flow+view-header-param-format": "{{doc-apihelp-param|flow+view-header|format}}",
+ "apihelp-flow+view-header-description": "{{doc-apihelp-description|flow+view-header}}",
+ "apihelp-flow+view-header-summary": "{{doc-apihelp-summary|flow+view-header}}",
+ "apihelp-flow+view-header-param-revId": "{{doc-apihelp-param|flow+view-header|revId}}",
+ "apihelp-flow+view-header-example-1": "{{doc-apihelp-example|flow+view-header}}",
+ "apihelp-flow+view-post-description": "{{doc-apihelp-description|flow+view-post}}",
+ "apihelp-flow+view-post-summary": "{{doc-apihelp-summary|flow+view-post}}",
+ "apihelp-flow+view-post-param-postId": "{{doc-apihelp-param|flow+view-post|postId}}",
+ "apihelp-flow+view-post-param-format": "{{doc-apihelp-param|flow+view-post|format}}",
+ "apihelp-flow+view-post-example-1": "{{doc-apihelp-example|flow+view-post}}",
+ "apihelp-flow+view-post-history-description": "{{doc-apihelp-description|flow+view-post-history}}",
+ "apihelp-flow+view-post-history-summary": "{{doc-apihelp-summary|flow+view-post-history}}",
+ "apihelp-flow+view-post-history-param-postId": "{{doc-apihelp-param|flow+view-post-history|postId}}",
+ "apihelp-flow+view-post-history-param-format": "{{doc-apihelp-param|flow+view-post-history|format}}",
+ "apihelp-flow+view-post-history-example-1": "{{doc-apihelp-example|flow+view-post-history}}",
+ "apihelp-flow+view-topic-description": "{{doc-apihelp-description|flow+view-topic}}",
+ "apihelp-flow+view-topic-summary": "{{doc-apihelp-summary|flow+view-topic}}",
+ "apihelp-flow+view-topic-param-format": "{{doc-apihelp-param|flow+view-topic|format}}",
+ "apihelp-flow+view-topic-example-1": "{{doc-apihelp-example|flow+view-topic}}",
+ "apihelp-flow+view-topic-history-description": "{{doc-apihelp-description|flow+view-topic-history}}",
+ "apihelp-flow+view-topic-history-summary": "{{doc-apihelp-summary|flow+view-topic-history}}",
+ "apihelp-flow+view-topic-history-param-format": "{{doc-apihelp-param|flow+view-topic-history|format}}",
+ "apihelp-flow+view-topic-history-example-1": "{{doc-apihelp-example|flow+view-topic-history}}",
+ "apihelp-flow+view-topic-summary-description": "{{doc-apihelp-description|flow+view-topic-summary}}",
+ "apihelp-flow+view-topic-summary-summary": "{{doc-apihelp-summary|flow+view-topic-summary}}",
+ "apihelp-flow+view-topic-summary-param-format": "{{doc-apihelp-param|flow+view-topic-summary|format}}",
+ "apihelp-flow+view-topic-summary-param-revId": "{{doc-apihelp-param|flow+view-topic-summary|revId}}",
+ "apihelp-flow+view-topic-summary-example-1": "{{doc-apihelp-example|flow+view-topic-summary}}",
+ "apihelp-flow+view-topiclist-description": "{{doc-apihelp-description|flow+view-topiclist}}",
+ "apihelp-flow+view-topiclist-summary": "{{doc-apihelp-summary|flow+view-topiclist}}",
+ "apihelp-flow+view-topiclist-param-offset-dir": "{{doc-apihelp-param|flow+view-topiclist|offset-dir}}",
+ "apihelp-flow+view-topiclist-param-sortby": "{{doc-apihelp-param|flow+view-topiclist|sortby}}",
+ "apihelp-flow+view-topiclist-param-savesortby": "{{doc-apihelp-param|flow+view-topiclist|savesortby}}",
+ "apihelp-flow+view-topiclist-param-offset-id": "{{doc-apihelp-param|flow+view-topiclist|offset-id}}",
+ "apihelp-flow+view-topiclist-param-offset": "{{doc-apihelp-param|flow+view-topiclist|offset}}",
+ "apihelp-flow+view-topiclist-param-include-offset": "{{doc-apihelp-param|flow+view-topiclist|include-offset}}",
+ "apihelp-flow+view-topiclist-param-limit": "{{doc-apihelp-param|flow+view-topiclist|limit}}",
+ "apihelp-flow+view-topiclist-param-toconly": "{{doc-apihelp-param|flow+view-topiclist|toconly}}",
+ "apihelp-flow+view-topiclist-param-format": "{{doc-apihelp-param|flow+view-topiclist|format}}",
+ "apihelp-flow+view-topiclist-example-1": "{{doc-apihelp-example|flow+view-topiclist}}",
+ "apihelp-flow-parsoid-utils-description": "{{doc-apihelp-description|flow-parsoid-utils}}",
+ "apihelp-flow-parsoid-utils-summary": "{{doc-apihelp-summary|flow-parsoid-utils}}",
+ "apihelp-flow-parsoid-utils-param-from": "{{doc-apihelp-param|flow-parsoid-utils|from}}",
+ "apihelp-flow-parsoid-utils-param-to": "{{doc-apihelp-param|flow-parsoid-utils|to}}",
+ "apihelp-flow-parsoid-utils-param-content": "{{doc-apihelp-param|flow-parsoid-utils|content}}",
+ "apihelp-flow-parsoid-utils-param-title": "{{doc-apihelp-param|flow-parsoid-utils|title}}",
+ "apihelp-flow-parsoid-utils-param-pageid": "{{doc-apihelp-param|flow-parsoid-utils|pageid}}",
+ "apihelp-flow-parsoid-utils-example-1": "{{doc-apihelp-example|flow-parsoid-utils}}",
+ "apihelp-query+flowinfo-description": "{{doc-apihelp-description|query+flowinfo}}",
+ "apihelp-query+flowinfo-summary": "{{doc-apihelp-summary|query+flowinfo}}",
+ "apihelp-query+flowinfo-example-1": "{{doc-apihelp-example|query+flowinfo}}",
+ "apihelp-flow+undo-edit-header-description": "{{doc-apihelp-description|flow+undo-edit-header}}",
+ "apihelp-flow+undo-edit-header-summary": "{{doc-apihelp-summary|flow+undo-edit-header}}",
+ "apihelp-flow+undo-edit-header-param-startId": "{{doc-apihelp-param|flow+undo-edit-header|startId}}",
+ "apihelp-flow+undo-edit-header-param-endId": "{{doc-apihelp-param|flow+undo-edit-header|endId}}",
+ "apihelp-flow+undo-edit-header-example-1": "{{doc-apihelp-example|flow+undo-edit-header}}",
+ "apihelp-flow+undo-edit-post-description": "{{doc-apihelp-description|flow+undo-edit-post}}",
+ "apihelp-flow+undo-edit-post-summary": "{{doc-apihelp-summary|flow+undo-edit-post}}",
+ "apihelp-flow+undo-edit-post-param-postId": "{{doc-apihelp-param|flow+undo-edit-post|postId}}",
+ "apihelp-flow+undo-edit-post-param-startId": "{{doc-apihelp-param|flow+undo-edit-post|startId}}",
+ "apihelp-flow+undo-edit-post-param-endId": "{{doc-apihelp-param|flow+undo-edit-post|endId}}",
+ "apihelp-flow+undo-edit-post-example-1": "{{doc-apihelp-example|flow+undo-edit-post}}",
+ "apihelp-flow+undo-edit-topic-summary-description": "{{doc-apihelp-description|flow+undo-edit-topic-summary}}",
+ "apihelp-flow+undo-edit-topic-summary-summary": "{{doc-apihelp-summary|flow+undo-edit-topic-summary}}",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "{{doc-apihelp-param|flow+undo-edit-topic-summary|startId}}",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "{{doc-apihelp-param|flow+undo-edit-topic-summary|endId}}",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "{{doc-apihelp-example|flow+undo-edit-topic-summary}}",
+ "apierror-flow-safeallowcreationfailed": "{{doc-apierror}}\n\nParameters:\n* $1 - Localized message.",
+ "apierror-flow-notenabled": "{{doc-apierror}}"
+}
diff --git a/Flow/i18n/api/ru.json b/Flow/i18n/api/ru.json
new file mode 100644
index 00000000..f7cfd9bd
--- /dev/null
+++ b/Flow/i18n/api/ru.json
@@ -0,0 +1,119 @@
+{
+ "@metadata": {
+ "authors": [
+ "Okras",
+ "Sunpriat",
+ "Kaganer",
+ "Mailman",
+ "Facenapalm"
+ ]
+ },
+ "apihelp-flow-description": "Позволяет применять действия к страницам Flow.",
+ "apihelp-flow-param-submodule": "Вызываемый подмодуль Flow.",
+ "apihelp-flow-param-page": "Страница, к которой применяются действия.",
+ "apihelp-flow-param-token": "Токен, полученный из [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Править описание у «[[Talk:Sandbox]]»",
+ "apihelp-flow+close-open-topic-description": "Не поддерживается в пользу [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Состояние, задаваемое теме: «закрыта» или «открыта».",
+ "apihelp-flow+close-open-topic-param-reason": "Основание закрытия или отмены закрытия темы.",
+ "apihelp-flow+edit-header-description": "Редактирование описания стены.",
+ "apihelp-flow+edit-header-param-prev_revision": "Идентификатор текущей версии описания, для проверки на конфликты редактирования.",
+ "apihelp-flow+edit-header-param-content": "Содержимое описания.",
+ "apihelp-flow+edit-header-param-format": "Формат описания (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Править описание у [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Правка содержимого сообщения.",
+ "apihelp-flow+edit-post-param-postId": "Идентификатор сообщения.",
+ "apihelp-flow+edit-post-param-prev_revision": "Идентификатор текущей версии сообщения, для проверки на конфликты редактирования.",
+ "apihelp-flow+edit-post-param-content": "Содержимое сообщения.",
+ "apihelp-flow+edit-post-param-format": "Формат содержимого сообщения (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Править сообщение в [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Правка заголовка темы.",
+ "apihelp-flow+edit-title-param-prev_revision": "Идентификатор текущей версии заголовка, для проверки на конфликты редактирования.",
+ "apihelp-flow+edit-title-param-content": "Содержимое заголовка, в том же формате, что разрешён для описания правок (тема-заголовок-викитекст).",
+ "apihelp-flow+edit-title-example-1": "Править заголовок у [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Правка содержимого краткого содержания темы.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Идентификатор текущей версии краткого содержания темы, для проверки на конфликты редактирования.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Содержимое краткого содержания.",
+ "apihelp-flow+edit-topic-summary-param-format": "Формат краткого содержания (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Править краткое содержание в [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Закрытие или отмена закрытия темы Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Состояние, задаваемое теме: <kbd>lock</kbd> или <kbd>unlock</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Причина для закрытия или открытия темы. Обратите внимание, что клиент Flow использует «Отмечено, как решенное» и добавляет необязательные дополнительные сведения в кратком виде.",
+ "apihelp-flow+lock-topic-example-1": "Закрыть [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Модерирование сообщения Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "Задаваемый уровень модерации.",
+ "apihelp-flow+moderate-post-param-reason": "Причина модерации.",
+ "apihelp-flow+moderate-post-param-postId": "Идентификатор модерируемого сообщения.",
+ "apihelp-flow+moderate-post-example-1": "Удалить сообщение в теме [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Модерирование темы Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Задаваемый уровень модерации.",
+ "apihelp-flow+moderate-topic-param-reason": "Причина модерации.",
+ "apihelp-flow+moderate-topic-example-1": "Удалить тему [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Создание новой темы Flow в заданном потоке.",
+ "apihelp-flow+new-topic-param-topic": "Текст нового заголовка темы.",
+ "apihelp-flow+new-topic-param-content": "Содержимое первого ответа в теме.",
+ "apihelp-flow+new-topic-param-format": "Формат первого ответа в новой теме (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Создать новую тему в [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Ответ на сообщение.",
+ "apihelp-flow+reply-param-replyTo": "Идентификатор сообщения для ответа.",
+ "apihelp-flow+reply-param-content": "Содержимое нового сообщения.",
+ "apihelp-flow+reply-param-format": "Формат нового сообщения (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Ответить на сообщение в [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-header-description": "Просмотр описания стены.",
+ "apihelp-flow+view-header-param-revId": "Загрузить эту версию вместо текущей.",
+ "apihelp-flow+view-header-example-1": "Извлечь описание у [[Talk:Sandbox]] как вики-текст",
+ "apihelp-flow+view-post-description": "Просмотр сообщения.",
+ "apihelp-flow+view-post-param-postId": "Идентификатор сообщения для просмотра.",
+ "apihelp-flow+view-post-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-post-example-1": "Извлечь содержимое сообщения в [[Topic:S2tycnas4hcucw8w]] как вики-текст",
+ "apihelp-flow+view-post-history-description": "Просмотр истории версий сообщения.",
+ "apihelp-flow+view-post-history-param-postId": "Идентификатор сообщения для просмотра истории версий.",
+ "apihelp-flow+view-post-history-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-post-history-example-1": "Запросить версии сообщения [[Topic:S2tycnas4hcucw8w]] как вики-текст",
+ "apihelp-flow+view-topic-description": "Просмотр темы.",
+ "apihelp-flow+view-topic-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-topic-example-1": "Просмотреть [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Просмотр истории версий темы.",
+ "apihelp-flow+view-topic-history-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-topic-history-example-1": "Запросить версии сообщений из [[Topic:S2tycnas4hcucw8w]] как вики-текст",
+ "apihelp-flow+view-topic-summary-description": "Просмотр краткого содержания темы.",
+ "apihelp-flow+view-topic-summary-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-topic-summary-param-revId": "Загрузить эту версию вместо текущей.",
+ "apihelp-flow+view-topic-summary-example-1": "Посмотреть краткое содержание у [[Topic:S2tycnas4hcucw8w]] как вики-текст",
+ "apihelp-flow+view-topiclist-description": "Просмотр списока тем.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Порядок перечисления тем.",
+ "apihelp-flow+view-topiclist-param-sortby": "Вариант сортировки тем: либо <kbd>updated</kbd> (сортировать по времени обновления), либо <kbd>newest</kbd> (сортировать по времени создания).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Сохранить способ сортировки в настройках пользователя (если установлен).",
+ "apihelp-flow+view-topiclist-param-offset-id": "Значение смещения (в формате UUID) начала выборки тем. Используется только при сортировке <kbd>newest</kbd>.",
+ "apihelp-flow+view-topiclist-param-offset": "Значение смещения (временная метка обновления темы, в формате <code>TS_MW</code> (<code>ГГГГММДДЧЧММСС</code>)) начала выборки тем; используется только при сортировке <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Включает смещение элемента также и в результат.",
+ "apihelp-flow+view-topiclist-param-limit": "Количество извлекаемых тем.",
+ "apihelp-flow+view-topiclist-param-toconly": "Следует ли запросить только информацию, необходимую для таблицы содержания.",
+ "apihelp-flow+view-topiclist-param-format": "Формат возвращаемого содержимого.",
+ "apihelp-flow+view-topiclist-example-1": "Список тем в [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Конвертация текста между вики-текстом и HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Формат из которого преобразуется содержимое.",
+ "apihelp-flow-parsoid-utils-param-to": "Формат в который преобразуется содержимое.",
+ "apihelp-flow-parsoid-utils-param-content": "Конвертируемое содержимое.",
+ "apihelp-flow-parsoid-utils-param-title": "Заголовок страницы. Не может использоваться вместе с $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Идентификатор страницы. Не может использоваться вместе с $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Преобразование вики-текста <nowiki>'''lorem''' ''blah''</nowiki> в HTML",
+ "apihelp-query+flowinfo-description": "Получение основной информации Flow о странице.",
+ "apihelp-query+flowinfo-example-1": "Извлечь информацию Flow о [[Talk:Sandbox]], [[Main Page]] и [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Получить информацию, необходимую для отмены правок описания.",
+ "apihelp-flow+undo-edit-header-param-startId": "Идентификатор первой отменяемой версии.",
+ "apihelp-flow+undo-edit-header-param-endId": "Идентификатор последней отменяемой версии.",
+ "apihelp-flow+undo-edit-header-example-1": "Извлечь информацию об отмене правки описания у [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Получение информации, необходимой для отмены правки сообщения.",
+ "apihelp-flow+undo-edit-post-param-postId": "Идентификатор отменяемого сообщения.",
+ "apihelp-flow+undo-edit-post-param-startId": "Идентификатор первой отменяемой версии.",
+ "apihelp-flow+undo-edit-post-param-endId": "Идентификатор последней отменяемой версии.",
+ "apihelp-flow+undo-edit-post-example-1": "Извлечь информацию об отмене правок сообщений в указанной теме.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Получение информации, необходимой для отмены правок краткого содержания темы.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Идентификатор первой отменяемой версии.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Идентификатор последней отменяемой версии.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Извлечь сведения об отмене правок краткого содержания темы в указанной теме",
+ "apierror-flow-safeallowcreationfailed": "У указанной страницы не включен Flow, и safeAllowCreation упало с: $1",
+ "apierror-flow-notenabled": "У указанной страницы не включен Flow."
+}
diff --git a/Flow/i18n/api/sv.json b/Flow/i18n/api/sv.json
new file mode 100644
index 00000000..3c3bd669
--- /dev/null
+++ b/Flow/i18n/api/sv.json
@@ -0,0 +1,142 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Bittin",
+ "Lokal Profil",
+ "WikiPhoenix",
+ "Josve05a"
+ ]
+ },
+ "apihelp-flow-description": "GÖr det möjligt att utföra åtgärder på Flow-sidor.",
+ "apihelp-flow-summary": "Gör det möjligt att utföra åtgärder på Flow-sidor.",
+ "apihelp-flow-param-submodule": "Den Flow-undermodul som ska anropas.",
+ "apihelp-flow-param-page": "Sidan som åtgärden ska utföras på.",
+ "apihelp-flow-param-token": "En nyckel hämtades från [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Redigera beskrivningen för \"[[Talk:Sandbox]]\"",
+ "apihelp-flow+close-open-topic-description": "Utfasad i förmån för [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Utfasad i förmån för [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Tillstånd att försätta ämnet i, antingen \"lås\" eller \"lås upp\".",
+ "apihelp-flow+close-open-topic-param-reason": "Skäl för att låsa eller låsa upp ämnet.",
+ "apihelp-flow+edit-header-description": "Redigera beskrivningen för ett forum.",
+ "apihelp-flow+edit-header-summary": "Redigerar beskrivningen för ett forum.",
+ "apihelp-flow+edit-header-param-prev_revision": "Versions-ID för den aktuella beskrivningsversionen, för att hantera redigeringskonflikter.",
+ "apihelp-flow+edit-header-param-content": "Innehåll för beskrivningen.",
+ "apihelp-flow+edit-header-param-format": "Beskrivningens format (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Redigera beskrivningen för [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Redigerar ett inläggs innehåll.",
+ "apihelp-flow+edit-post-summary": "Redigerar ett inläggs innehåll.",
+ "apihelp-flow+edit-post-param-postId": "Inläggs-ID.",
+ "apihelp-flow+edit-post-param-prev_revision": "Versions-ID för den aktuella inläggsversionen, för att hantera redigeringskonflikter.",
+ "apihelp-flow+edit-post-param-content": "Innehåll för inlägg.",
+ "apihelp-flow+edit-post-param-format": "Formatet för inläggets innehåll (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Redigera ett inlägg i [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Redigeringar en ämnesrubrik.",
+ "apihelp-flow+edit-title-summary": "Redigerar en ämnesrubrik.",
+ "apihelp-flow+edit-title-param-prev_revision": "Versions-ID för den aktuella titelversionen, för att hantera redigeringskonflikter.",
+ "apihelp-flow+edit-title-param-content": "Innehåll för rubrik, i samma format som tillåts för redigeringssammanfattningar (topic-title-wikitext).",
+ "apihelp-flow+edit-title-example-1": "Redigera rubriken på [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Redigera innehållet för en ämnessammanfattning.",
+ "apihelp-flow+edit-topic-summary-summary": "Redigerar innehållet för en ämnessammanfattning.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Versions-ID för den aktuella ämnessammanfattningsversionen, för att hantera redigeringskonflikter.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Innehåll för sammanfattningen.",
+ "apihelp-flow+edit-topic-summary-param-format": "Sammanfattningens format (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Redigera sammanfattningen av [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Lås eller lås upp ett Flow-ämne.",
+ "apihelp-flow+lock-topic-summary": "Lås eller lås upp ett Flow-ämne.",
+ "apihelp-flow+lock-topic-param-moderationState": "Tillstånd att försätta ämnet i, antingen <kbd>lås</kbd> eller <kbd>lås upp</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Skäl för att låsa eller låsa upp ämnet. Notera att Flow-klienten på wikin använder \"Markerad som löst\" här vilket lägger till ytterligare information i sammanfattningen.",
+ "apihelp-flow+lock-topic-example-1": "Lås [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Modererar ett Flow-inlägg.",
+ "apihelp-flow+moderate-post-summary": "Modererar ett Flow-inlägg.",
+ "apihelp-flow+moderate-post-param-moderationState": "Vilken nivå att moderera på.",
+ "apihelp-flow+moderate-post-param-reason": "Skäl för moderering.",
+ "apihelp-flow+moderate-post-param-postId": "ID för inlägget som ska modereras.",
+ "apihelp-flow+moderate-post-example-1": "Radera ett inlägg i ämnet [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Moderera ett Flow-ämne.",
+ "apihelp-flow+moderate-topic-summary": "Modererar ett Flow-ämne.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Vilken nivå att moderera på.",
+ "apihelp-flow+moderate-topic-param-reason": "Skäl för moderering.",
+ "apihelp-flow+moderate-topic-example-1": "Radera ämnet [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Skapa ett nytt Flow-ämne på det angivna arbetsflödet.",
+ "apihelp-flow+new-topic-summary": "Skapar ett nytt Flow-ämne på det angivna arbetsflödet.",
+ "apihelp-flow+new-topic-param-topic": "Text för ny ämnestitel.",
+ "apihelp-flow+new-topic-param-content": "Innehåll för ämnets första svar.",
+ "apihelp-flow+new-topic-param-format": "Format på det nya ämnets första svar (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Skapa ett nytt ämne på [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Svar på ett inlägg.",
+ "apihelp-flow+reply-summary": "Svar på ett inlägg.",
+ "apihelp-flow+reply-param-replyTo": "Inläggs-ID att svara på.",
+ "apihelp-flow+reply-param-content": "Innehåll för nytt inlägg.",
+ "apihelp-flow+reply-param-format": "Formatet för det nya inlägget (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Svara på ett inlägg i [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-header-description": "Visa beskrivning för ett forum.",
+ "apihelp-flow+view-header-summary": "Visa beskrivning för ett forum.",
+ "apihelp-flow+view-header-param-revId": "Ladda denna version, istället för den senaste.",
+ "apihelp-flow+view-header-example-1": "Hämta beskrivningen för [[Talk:Sandbox]] som wikitext",
+ "apihelp-flow+view-post-description": "Visa ett inlägg",
+ "apihelp-flow+view-post-summary": "Visa ett inlägg.",
+ "apihelp-flow+view-post-param-postId": "ID för inlägget som ska visas.",
+ "apihelp-flow+view-post-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-post-example-1": "Hämta innehållet för ett inlägg i [[Topic:S2tycnas4hcucw8w]] som wikitext",
+ "apihelp-flow+view-post-history-description": "Se ändringshistorik för ett inlägg.",
+ "apihelp-flow+view-post-history-summary": "Se redigeringshistoriken för ett inlägg.",
+ "apihelp-flow+view-post-history-param-postId": "ID för inlägget att visa historik för.",
+ "apihelp-flow+view-post-history-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-post-history-example-1": "Hämta sidversionen för ett inlägg i [[Topic:S2tycnas4hcucw8w]] as wikitext",
+ "apihelp-flow+view-topic-description": "Visa ett ämne.",
+ "apihelp-flow+view-topic-summary": "Visa ett ämne.",
+ "apihelp-flow+view-topic-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-topic-example-1": "Visa [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Se ändringshistorik för ett ämne.",
+ "apihelp-flow+view-topic-history-summary": "Se redigeringshistoriken för ett ämne.",
+ "apihelp-flow+view-topic-history-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-topic-history-example-1": "Visa sidversionen för inlägget på [[Topic:S2tycnas4hcucw8w]] som wikitext",
+ "apihelp-flow+view-topic-summary-description": "Visa en ämnessammanfattning.",
+ "apihelp-flow+view-topic-summary-summary": "Visa en ämnessammanfattning.",
+ "apihelp-flow+view-topic-summary-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-topic-summary-param-revId": "Ladda denna version, istället för den senaste.",
+ "apihelp-flow+view-topic-summary-example-1": "Visa sammanfattningen för [[Topic:S2tycnas4hcucw8w]] som wikitext",
+ "apihelp-flow+view-topiclist-description": "Visa en lista av ämnen.",
+ "apihelp-flow+view-topiclist-summary": "Visa en lista över ämnen.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Riktning för sortering av ämnen.",
+ "apihelp-flow+view-topiclist-param-sortby": "Sorteringsalternativ för ämnena, anringen <kbd>uppdaterad</kbd> (sorterat på ämnets uppdateringstid), eller <kbd>nyast</kbd> (sorterat på ämnets tid för skapande).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Spara sorteringsalternativ i användarintällningarna, om angivet.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Förskjutningsvärde (i UUID-format) från vilket ämnen ska börja hämtas; används bara i sorteringen <kbd>nyaste</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Förskjutningsvärde (som ämnets tidsstämpel, i <code>TS_MW</code> formatet (<code>ÅÅÅÅMMDDTTMMSS</code>)), från vilket ämnen ska börja hämtas; används bara vid sorteringen <kbd>uppdaterad</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Inkluderar även offsetobjektet i resultaten.",
+ "apihelp-flow+view-topiclist-param-limit": "Antal ämnen att hämta.",
+ "apihelp-flow+view-topiclist-param-toconly": "Om den ska svara med den enda informationen som krävs för innehållsförteckningen.",
+ "apihelp-flow+view-topiclist-param-format": "Format att returnera innehållet i.",
+ "apihelp-flow+view-topiclist-example-1": "Lista ämnen på [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Konvertera text mellan wikitext och HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Konvertera text mellan wikitext och HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Format att konvertera innehållet från.",
+ "apihelp-flow-parsoid-utils-param-to": "Format att konvertera innehållet till.",
+ "apihelp-flow-parsoid-utils-param-content": "Innehåll att konvertera.",
+ "apihelp-flow-parsoid-utils-param-title": "Titel för sidan. Kan inte användas tillsammans med $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID för sidan. Kan inte användas tillsammans med $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Konvertera wikitext <nowiki>'''lorem''' ''blah''</nowiki> till HTML",
+ "apihelp-query+flowinfo-description": "Hämta grundläggande Flow-information för en sida.",
+ "apihelp-query+flowinfo-summary": "Hämta grundläggande Flow-information för en sida.",
+ "apihelp-query+flowinfo-example-1": "Hämta Flow-information om [[Talk:Sandbox]], [[Main Page]], och [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Hämta information som är nödvändig för att göra beskrivningsredigeringar ogjorda.",
+ "apihelp-flow+undo-edit-header-summary": "Hämta information som är nödvändig för att göra beskrivningsredigeringar ogjorda.",
+ "apihelp-flow+undo-edit-header-param-startId": "Sidversionens ID att börja ångra från.",
+ "apihelp-flow+undo-edit-header-param-endId": "Sidversionens ID att sluta ångra på.",
+ "apihelp-flow+undo-edit-header-example-1": "Hämta information om att ångra en beskrivningsredigering på [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Hämta information som är nödvändig för att göra inläggsredigering ogjord.",
+ "apihelp-flow+undo-edit-post-summary": "Hämta information som är nödvändig för att göra inläggsredigeringar ogjord.",
+ "apihelp-flow+undo-edit-post-param-postId": "Inläggs-ID att ångra.",
+ "apihelp-flow+undo-edit-post-param-startId": "Sidversionens ID att börja ångra från.",
+ "apihelp-flow+undo-edit-post-param-endId": "Sidversionens ID att sluta ångra på.",
+ "apihelp-flow+undo-edit-post-example-1": "Hämta information om att ångra en inläggsredigering inom ett specifikt ämne.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Hämta information som är nödvändig för att göra ämnessammanfattningsredigeringar ogjorda.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Hämta information som är nödvändig för att göra ämnessammanfattningsredigeringar ogjorda.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Sidversionens ID att börja ångra från.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Sidversionens ID att sluta ångra på.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Hämta information om att göra en ämnessammanfattningsredigering ogjord i ett specifikt ämne.",
+ "apierror-flow-safeallowcreationfailed": "Den angivna sidan har inte aktiverat Flow och safeAllowCreation misslyckades med: $1",
+ "apierror-flow-notenabled": "Den angivna sidan har inte aktiverat Flow."
+}
diff --git a/Flow/i18n/api/uk.json b/Flow/i18n/api/uk.json
new file mode 100644
index 00000000..ac616034
--- /dev/null
+++ b/Flow/i18n/api/uk.json
@@ -0,0 +1,142 @@
+{
+ "@metadata": {
+ "authors": [
+ "Base",
+ "Dars",
+ "Piramidion",
+ "Quiddity",
+ "Ата"
+ ]
+ },
+ "apihelp-flow-description": "Дозволяє застосовувати дії до сторінок Flow.",
+ "apihelp-flow-summary": "Дозволяє застосовувати дії до сторінок Flow.",
+ "apihelp-flow-param-submodule": "Підмодуль Flow, що викликається.",
+ "apihelp-flow-param-page": "Сторінка, до якої застосовуються дії.",
+ "apihelp-flow-param-token": "Токен, отриманий зі [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+ "apihelp-flow-example-1": "Додати опис «[[Talk:Sandbox]]»",
+ "apihelp-flow+close-open-topic-description": "Застаріло на користь [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-summary": "Застаріло на користь [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Статус, що надається темі, «закрити» або «відкрити».",
+ "apihelp-flow+close-open-topic-param-reason": "Причина закриття чи відкриття теми.",
+ "apihelp-flow+edit-header-description": "Редагує опис стіни.",
+ "apihelp-flow+edit-header-summary": "Редагує опис стіни.",
+ "apihelp-flow+edit-header-param-prev_revision": "ID версії поточної версії опису, який перевіряється на конфлікти редагувань.",
+ "apihelp-flow+edit-header-param-content": "Вміст для опису.",
+ "apihelp-flow+edit-header-param-format": "Формат опису (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Редагувати опис «[[Talk:Sandbox]]»",
+ "apihelp-flow+edit-post-description": "Редагує вміст допису.",
+ "apihelp-flow+edit-post-summary": "Редагує вміст допису.",
+ "apihelp-flow+edit-post-param-postId": "ID допису.",
+ "apihelp-flow+edit-post-param-prev_revision": "ID поточної версії допису, яка перевіряється на конфлікти редагувань.",
+ "apihelp-flow+edit-post-param-content": "Вміст для допису.",
+ "apihelp-flow+edit-post-param-format": "Формат вмісту допису (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Редагувати допис у [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Редагування назви теми.",
+ "apihelp-flow+edit-title-summary": "Редагування назви теми.",
+ "apihelp-flow+edit-title-param-prev_revision": "ID поточної версії назви, яка перевіряється на конфлікти редагувань.",
+ "apihelp-flow+edit-title-param-content": "Вміст для заголовка, в тому ж форматі, який дозволяється і для описів редагувань (тема-заголовок-вікітекст).",
+ "apihelp-flow+edit-title-example-1": "Редагувати назву у [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Редагує вміст підсумку теми.",
+ "apihelp-flow+edit-topic-summary-summary": "Редагує вміст підсумку теми.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "ID поточної версії підсумку теми, яка перевіряється на конфлікти редагувань.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Вміст для підсумку.",
+ "apihelp-flow+edit-topic-summary-param-format": "Формат підсумку (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Редагувати підсумок у [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Закрити чи відкрити тему Flow.",
+ "apihelp-flow+lock-topic-summary": "Закрити чи відкрити тему Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Статус, що надається темі, <kbd>закрити</kbd> або <kbd>відкрити</kbd>.",
+ "apihelp-flow+lock-topic-param-reason": "Причина закриття чи відкриття теми. Зауважте, що клієнт Flow у вікі використовує позначку «Позначено як вирішене» і додає необов'язкову додаткову інформацію в описі.",
+ "apihelp-flow+lock-topic-example-1": "Закрити [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Модерує допис Flow.",
+ "apihelp-flow+moderate-post-summary": "Модерує допис Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "Який рівень модерації.",
+ "apihelp-flow+moderate-post-param-reason": "Причина для модерації.",
+ "apihelp-flow+moderate-post-param-postId": "ID допису для модерації.",
+ "apihelp-flow+moderate-post-example-1": "Вилучити допис у темі [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Модерує тему Flow.",
+ "apihelp-flow+moderate-topic-summary": "Модерує тему Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Який рівень модерації.",
+ "apihelp-flow+moderate-topic-param-reason": "Причина для модерації.",
+ "apihelp-flow+moderate-topic-example-1": "Вилучити тему [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Створює нову тему Flow у даному робочому полі.",
+ "apihelp-flow+new-topic-summary": "Створює нову тему Flow у даному робочому полі.",
+ "apihelp-flow+new-topic-param-topic": "Текст для нової назви теми.",
+ "apihelp-flow+new-topic-param-content": "Вміст для початкової відповіді в темі.",
+ "apihelp-flow+new-topic-param-format": "Формат початкової відповіді в темі (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Створити нову тему у [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Відповіді на допис.",
+ "apihelp-flow+reply-summary": "Відповіді на допис.",
+ "apihelp-flow+reply-param-replyTo": "ID допису для відповіді.",
+ "apihelp-flow+reply-param-content": "Вміст для нового допису.",
+ "apihelp-flow+reply-param-format": "Формат нового допису (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Відповідь на допис у [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Формат виведення вмісту.",
+ "apihelp-flow+view-header-description": "Переглянути опис стіни.",
+ "apihelp-flow+view-header-summary": "Переглянути опис стіни.",
+ "apihelp-flow+view-header-param-revId": "Завантажити цю версію замість останньої.",
+ "apihelp-flow+view-header-example-1": "Вибірка опису [[Talk:Sandbox]] у вигляді вікітексту",
+ "apihelp-flow+view-post-description": "Переглянути допис.",
+ "apihelp-flow+view-post-summary": "Переглянути допис.",
+ "apihelp-flow+view-post-param-postId": "ID допису для перегляду.",
+ "apihelp-flow+view-post-param-format": "Формат виведення вмісту.",
+ "apihelp-flow+view-post-example-1": "Вибірка вмісту допису у [[Topic:S2tycnas4hcucw8w]] у вигляді вікітексту",
+ "apihelp-flow+view-post-history-description": "Переглянути історію змін цього допису.",
+ "apihelp-flow+view-post-history-summary": "Переглянути історію змін цього допису.",
+ "apihelp-flow+view-post-history-param-postId": "ID запису, для якого необхідно переглянути історію змін.",
+ "apihelp-flow+view-post-history-param-format": "Формат, у якому повернути вміст.",
+ "apihelp-flow+view-post-history-example-1": "Отримати версії допису у [[Topic:S2tycnas4hcucw8w]] як вікітекст",
+ "apihelp-flow+view-topic-description": "Переглянути тему.",
+ "apihelp-flow+view-topic-summary": "Переглянути тему.",
+ "apihelp-flow+view-topic-param-format": "Формат, в якому треба вивести вміст.",
+ "apihelp-flow+view-topic-example-1": "Переглянути [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Переглянути історію змін цієї теми.",
+ "apihelp-flow+view-topic-history-summary": "Переглянути історію змін цієї теми.",
+ "apihelp-flow+view-topic-history-param-format": "Формат, у якому повернути вміст.",
+ "apihelp-flow+view-topic-history-example-1": "Переглянути версії допису в [[Topic:S2tycnas4hcucw8w]] як вікітекст",
+ "apihelp-flow+view-topic-summary-description": "Переглянути підсумок теми.",
+ "apihelp-flow+view-topic-summary-summary": "Переглянути підсумок теми.",
+ "apihelp-flow+view-topic-summary-param-format": "Формат виведення вмісту.",
+ "apihelp-flow+view-topic-summary-param-revId": "Завантажити цю версію замість останньої.",
+ "apihelp-flow+view-topic-summary-example-1": "Переглянути підсумок для [[Topic:S2tycnas4hcucw8w]] як вікітекст",
+ "apihelp-flow+view-topiclist-description": "Переглянути список тем.",
+ "apihelp-flow+view-topiclist-summary": "Переглянути список тем.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Порядок сортування тем.",
+ "apihelp-flow+view-topiclist-param-sortby": "Варіант сортування тем: або <kbd>updated</kbd> (сортування за часом оновлення теми), або <kbd>newest</kbd> (сортування за часом створення теми).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Зберегти опцію сортування у налаштуваннях користувача, якщо вказана.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Значення зміщення (у форматі UUID) для початку вибірки тем; використовується лише для сортування <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Значення зміщення (у вигляді часової мітки оновлення теми, у форматі <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), з якого почати вибірку тем; використовується лише з сортуванням <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-include-offset": "Включає в результати також елемент зміщення.",
+ "apihelp-flow+view-topiclist-param-limit": "Кількість тем для вибірки.",
+ "apihelp-flow+view-topiclist-param-toconly": "Чи відповідати лише з інформацією, необхідною для TOC.",
+ "apihelp-flow+view-topiclist-param-format": "Формат, у якому треба повернути вміст.",
+ "apihelp-flow+view-topiclist-example-1": "Список тем у [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Конвертувати текст між вікітекстом і HTML.",
+ "apihelp-flow-parsoid-utils-summary": "Конвертувати текст між вікітекстом і HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Формат, з якого конвертувати вміст.",
+ "apihelp-flow-parsoid-utils-param-to": "Формат, у який конвертувати вміст.",
+ "apihelp-flow-parsoid-utils-param-content": "Вміст для конвертування.",
+ "apihelp-flow-parsoid-utils-param-title": "Заголовок сторінки. Не може використовуватися разом із $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "ID сторінки. Не може використовуватися разом з $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Конвертувати вікітекст <nowiki>'''lorem''' ''blah''</nowiki> у HTML",
+ "apihelp-query+flowinfo-description": "Отримати базову Flow-інформацію про сторінку.",
+ "apihelp-query+flowinfo-summary": "Отримати базову Flow-інформацію про сторінку.",
+ "apihelp-query+flowinfo-example-1": "Вибрати Flow-інформацію про [[Talk:Sandbox]], [[Main Page]], та [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Отримати інформацію, необхідну для скасування редагувань опису.",
+ "apihelp-flow+undo-edit-header-summary": "Отримати інформацію, необхідну для скасування редагувань опису.",
+ "apihelp-flow+undo-edit-header-param-startId": "Ідентифікатор версії для початку скасування.",
+ "apihelp-flow+undo-edit-header-param-endId": "Ідентифікатор версії для закінчення скасування.",
+ "apihelp-flow+undo-edit-header-example-1": "Вибрати інформацію про скасування редагування опису на [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Отримати інформацію, необхідну для скасування редагування допису.",
+ "apihelp-flow+undo-edit-post-summary": "Отримати інформацію, необхідну для скасування редагування допису.",
+ "apihelp-flow+undo-edit-post-param-postId": "ID допису, який буде скасовано.",
+ "apihelp-flow+undo-edit-post-param-startId": "Ідентифікатор версії для початку скасування.",
+ "apihelp-flow+undo-edit-post-param-endId": "Ідентифікатор версії для закінчення скасування.",
+ "apihelp-flow+undo-edit-post-example-1": "Вибрати інформацію про скасування редагування допису у певній темі.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Отримати інформацію, необхідну для скасування редагувань підсумку теми.",
+ "apihelp-flow+undo-edit-topic-summary-summary": "Отримати інформацію, необхідну для скасування редагувань підсумку теми.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Ідентифікатор версії для початку скасування.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Ідентифікатор версії для закінчення скасування.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Вибрати інформацію про скасування редагування підсумку теми у певній темі",
+ "apierror-flow-safeallowcreationfailed": "На вказаній сторінці не увімкнено Flow, і safeAllowCreation завершилося невдачею: $1",
+ "apierror-flow-notenabled": "На вказаній сторінці не увімкнено Flow."
+}
diff --git a/Flow/i18n/api/vi.json b/Flow/i18n/api/vi.json
new file mode 100644
index 00000000..7d80d73d
--- /dev/null
+++ b/Flow/i18n/api/vi.json
@@ -0,0 +1,109 @@
+{
+ "@metadata": {
+ "authors": [
+ "Minh Nguyen"
+ ]
+ },
+ "apihelp-flow-description": "Cho phép thực hiện các tác vụ trên các trang Flow.",
+ "apihelp-flow-param-submodule": "Bộ phận con Flow để gọi.",
+ "apihelp-flow-param-page": "Trang để thực hiện tác vụ.",
+ "apihelp-flow-example-1": "Sửa đổi lời miêu tả của “[[Talk:Sandbox]]”",
+ "apihelp-flow+close-open-topic-description": "Bị phản đối; hãy sử dụng [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
+ "apihelp-flow+close-open-topic-param-moderationState": "Trạng thái mới của đề tài, hoặc “lock” (khóa) hoặc “unlock” (mở khóa).",
+ "apihelp-flow+close-open-topic-param-reason": "Lý do khóa hoặc mở khóa đề tài.",
+ "apihelp-flow+edit-header-description": "Sửa đổi lời miêu tả bảng tin.",
+ "apihelp-flow+edit-header-param-prev_revision": "Số phiên bản của tóm lược hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
+ "apihelp-flow+edit-header-param-content": "Nội dung miêu tả.",
+ "apihelp-flow+edit-header-param-format": "Định dạng của miêu tả (wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "Sửa đổi lời miêu tả của [[Talk:Sandbox]]",
+ "apihelp-flow+edit-post-description": "Sửa đổi nội dung của một bài đăng.",
+ "apihelp-flow+edit-post-param-postId": "Mã số bài đăng.",
+ "apihelp-flow+edit-post-param-prev_revision": "Số phiên bản bài đăng hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
+ "apihelp-flow+edit-post-param-content": "Nội dung bài đăng.",
+ "apihelp-flow+edit-post-param-format": "Định dạng của nội dung bài đăng (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "Sửa đổi một bài đăng trong [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-title-description": "Sửa đổi tiêu đề của đề tài.",
+ "apihelp-flow+edit-title-param-prev_revision": "Số phiên bản tiêu đề hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
+ "apihelp-flow+edit-title-param-content": "Nội dung tiêu đề theo cùng định dạng được cho phép cho tóm lược sửa đổi (đề tài–tiêu đề–mã wiki).",
+ "apihelp-flow+edit-title-example-1": "Sửa đổi tiêu đề của [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+edit-topic-summary-description": "Sửa đổi nội dung của tóm lược đề tài.",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "Số phiên bản tóm lược đề tài hiện tại, nếu có, để kiểm tra có mâu thuẫn sửa đổi hay không.",
+ "apihelp-flow+edit-topic-summary-param-summary": "Nội dung tóm lược.",
+ "apihelp-flow+edit-topic-summary-param-format": "Định dạng của tóm lược (wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "Sửa đổi tóm lược của [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+lock-topic-description": "Khóa hoặc mở khóa một đề tài Flow.",
+ "apihelp-flow+lock-topic-param-moderationState": "Trạng thái mới của đề tài, hoặc <kbd>lock</kbd> (khóa) hoặc <kbd>unlock</kbd> (mở khóa).",
+ "apihelp-flow+lock-topic-param-reason": "Lý do khóa hoặc mở khóa đề tài. Lưu ý rằng trình khác Flow trên wiki sẽ đề “Đã giải quyết” tại đây và đưa thêm thông tin vào tóm lược.",
+ "apihelp-flow+lock-topic-example-1": "Khóa [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "Giữ lại một bài đăng Flow.",
+ "apihelp-flow+moderate-post-param-moderationState": "Mức để giữ lại.",
+ "apihelp-flow+moderate-post-param-reason": "Lý do giữ lại.",
+ "apihelp-flow+moderate-post-param-postId": "Mã số bài đăng để giữ lại.",
+ "apihelp-flow+moderate-post-example-1": "Xóa một bài đăng trong đề tài [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-topic-description": "Giữ lại một đề tài Flow.",
+ "apihelp-flow+moderate-topic-param-moderationState": "Mức để giữ lại.",
+ "apihelp-flow+moderate-topic-param-reason": "Lý do giữ lại.",
+ "apihelp-flow+moderate-topic-example-1": "Xóa đề tài [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "Tạo một đề tài Flow mới theo luồng làm việc được đề tài.",
+ "apihelp-flow+new-topic-param-topic": "Văn bản tiêu đề mới của đề tài.",
+ "apihelp-flow+new-topic-param-content": "Nội dung của lời trả lời đầu tiên trong đề tài.",
+ "apihelp-flow+new-topic-param-format": "Định dạng của lời trả lời đầu tiên của đề tài mới (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "Tạo đề tài mới trên [[Talk:Sandbox]]",
+ "apihelp-flow+reply-description": "Trả lời một bài đăng.",
+ "apihelp-flow+reply-param-replyTo": "Mã số bài đăng để trả lời.",
+ "apihelp-flow+reply-param-content": "Nội dung bài đăng mới.",
+ "apihelp-flow+reply-param-format": "Định dạng của bài đăng mới (wikitext|html)",
+ "apihelp-flow+reply-example-1": "Trả lời một bài đăng trong [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-header-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-header-description": "Xem miêu tả bảng tin.",
+ "apihelp-flow+view-header-param-revId": "Tải phiên bản này thay vì phiên bản mới nhất.",
+ "apihelp-flow+view-header-example-1": "Lấy miêu tả của [[Talk:Sandbox]] dưới dạng mã wiki",
+ "apihelp-flow+view-post-description": "Xem một bài đăng.",
+ "apihelp-flow+view-post-param-postId": "Mã số bài đăng để xem.",
+ "apihelp-flow+view-post-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-post-example-1": "Lấy nội dung của một bài đăng trong [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
+ "apihelp-flow+view-post-history-description": "Xem lịch sử thay đổi của một bài đăng.",
+ "apihelp-flow+view-post-history-param-postId": "ID của bài đăng để xem lịch sử thay đổi.",
+ "apihelp-flow+view-post-history-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-post-history-example-1": "Lấy các phiên bản của một bài đăng trong [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
+ "apihelp-flow+view-topic-description": "Xem một đề tài.",
+ "apihelp-flow+view-topic-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-topic-example-1": "Xem [[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "Xem lịch sử thay đổi của một đề tài.",
+ "apihelp-flow+view-topic-history-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-topic-history-example-1": "Lấy các phiên bản của các bài đăng trên [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
+ "apihelp-flow+view-topic-summary-description": "Xem một tóm lược đề tài.",
+ "apihelp-flow+view-topic-summary-param-format": "Định dạng để trả về nội dung.",
+ "apihelp-flow+view-topic-summary-param-revId": "Tải phiên bản này thay vì phiên bản mới nhất.",
+ "apihelp-flow+view-topic-summary-example-1": "Xem tóm lược của [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
+ "apihelp-flow+view-topiclist-description": "Xem danh sách đề tài.",
+ "apihelp-flow+view-topiclist-param-offset-dir": "Hướng để sắp xếp các đề tài.",
+ "apihelp-flow+view-topiclist-param-sortby": "Thứ tự để sắp xếp các đề tài, hoặc <kbd>updated</kbd> (theo lúc cập nhật đề tài) hoặc <kbd>newest</kbd> (theo lúc tạo ra đề tài).",
+ "apihelp-flow+view-topiclist-param-savesortby": "Lưu tùy chọn sắp xếp, nếu được đặt.",
+ "apihelp-flow+view-topiclist-param-offset-id": "Giá trị chệch (dưới dạng UUID) để bắt đầu lấy đề tài; chỉ sử dụng khi sắp xếp theo thứ tự <kbd>newest</kbd>",
+ "apihelp-flow+view-topiclist-param-offset": "Giá trị chệch (dưới dạng dấu thời gian cập nhật đề tài, dạng <code>TS_MW</code>, tức <code>YYYYMMDDHHMMSS</code>), để bắt đầu lấy đề tài; chỉ sử dụng khi sắp xếp theo thứ tự <kbd>updated</kbd>",
+ "apihelp-flow+view-topiclist-param-limit": "Số đề tài để lấy.",
+ "apihelp-flow+view-topiclist-example-1": "Liệt kê các đề tài trên [[Talk:Sandbox]]",
+ "apihelp-flow-parsoid-utils-description": "Chuyển đổi văn bản giữa mã wiki và HTML.",
+ "apihelp-flow-parsoid-utils-param-from": "Định dạng gốc để chuyển đổi nội dung.",
+ "apihelp-flow-parsoid-utils-param-to": "Định dạng đích để chuyển đổi nội dung.",
+ "apihelp-flow-parsoid-utils-param-content": "Nội dung để chuyển đổi.",
+ "apihelp-flow-parsoid-utils-param-title": "Tên trang. Không thể sử dụng với $1pageid.",
+ "apihelp-flow-parsoid-utils-param-pageid": "Mã số của trang. Không thể sử dụng với $1title.",
+ "apihelp-flow-parsoid-utils-example-1": "Chuyển đổi mã wiki <nowiki>'''ví''' ''dụ''</nowiki> sang HTML",
+ "apihelp-query+flowinfo-description": "Lấy thông tin cơ bản Flow về một trang.",
+ "apihelp-query+flowinfo-example-1": "Lấy thông tin Flow về [[Talk:Sandbox]], [[Main Page]], và [[Talk:Flow]]",
+ "apihelp-flow+undo-edit-header-description": "Lấy thông tin cần thiết để lùi lại sửa đổi miêu tả.",
+ "apihelp-flow+undo-edit-header-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
+ "apihelp-flow+undo-edit-header-param-endId": "Số phiên bản để ngừng lùi sửa.",
+ "apihelp-flow+undo-edit-header-example-1": "Lấy thông tin về việc lùi lại một sửa đổi miêu tả tại [[Talk:Sandbox]]",
+ "apihelp-flow+undo-edit-post-description": "Lấy thông tin cần thiết để lùi lại sửa đổi bài đăng.",
+ "apihelp-flow+undo-edit-post-param-postId": "Mã số bài đăng để lùi lại.",
+ "apihelp-flow+undo-edit-post-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
+ "apihelp-flow+undo-edit-post-param-endId": "Số phiên bản để ngừng lùi sửa.",
+ "apihelp-flow+undo-edit-post-example-1": "Lấy thông tin về việc lùi lại một sửa đổi bài đăng trong một đề tài cụ thể.",
+ "apihelp-flow+undo-edit-topic-summary-description": "Lấy lại thông tin cần thiết để lùi lại sửa đổi tóm lược đề tài.",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "Số phiên bản để ngừng lùi sửa.",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "Lấy thông tin về việc lùi lại một sửa đổi tóm lược của một đề tài cụ thể."
+}
diff --git a/Flow/i18n/api/zh-hans.json b/Flow/i18n/api/zh-hans.json
new file mode 100644
index 00000000..355401c8
--- /dev/null
+++ b/Flow/i18n/api/zh-hans.json
@@ -0,0 +1,143 @@
+{
+ "@metadata": {
+ "authors": [
+ "Liuxinyu970226",
+ "Quiddity",
+ "Shizhao",
+ "御坂美琴",
+ "飞舞回堂前",
+ "Chiefwei"
+ ]
+ },
+ "apihelp-flow-description": "允许对Flow页面的操作。",
+ "apihelp-flow-summary": "允许对Flow页面的操作。",
+ "apihelp-flow-param-submodule": "要调用的Flow子模块。",
+ "apihelp-flow-param-page": "要进行操作的页面。",
+ "apihelp-flow-param-token": "从[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]取回的令牌",
+ "apihelp-flow-example-1": "编辑“[[Talk:Sandbox]]”的描述",
+ "apihelp-flow+close-open-topic-description": "由于[[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]而弃用。",
+ "apihelp-flow+close-open-topic-summary": "由于[[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]而弃用。",
+ "apihelp-flow+close-open-topic-param-moderationState": "提交话题的情形,要么“lock”要么“unlock”。",
+ "apihelp-flow+close-open-topic-param-reason": "锁定或解锁话题的原因。",
+ "apihelp-flow+edit-header-description": "编辑板块的描述。",
+ "apihelp-flow+edit-header-summary": "编辑板块的描述。",
+ "apihelp-flow+edit-header-param-prev_revision": "当前描述修订的版本ID,以检查编辑冲突。",
+ "apihelp-flow+edit-header-param-content": "用于描述的内容。",
+ "apihelp-flow+edit-header-param-format": "描述的格式(wikitext|html)",
+ "apihelp-flow+edit-header-example-1": "编辑[[Talk:Sandbox]]的描述",
+ "apihelp-flow+edit-post-description": "编辑帖子的内容。",
+ "apihelp-flow+edit-post-summary": "编辑帖子的内容。",
+ "apihelp-flow+edit-post-param-postId": "帖子ID。",
+ "apihelp-flow+edit-post-param-prev_revision": "当前帖子修订的版本ID,以检查编辑冲突。",
+ "apihelp-flow+edit-post-param-content": "帖子的内容。",
+ "apihelp-flow+edit-post-param-format": "帖子内容的格式(wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的帖子",
+ "apihelp-flow+edit-title-description": "编辑话题的标题。",
+ "apihelp-flow+edit-title-summary": "编辑话题的标题。",
+ "apihelp-flow+edit-title-param-prev_revision": "当前标题修订的版本ID,以检查编辑冲突。",
+ "apihelp-flow+edit-title-param-content": "标题的内容,与允许用于编辑摘要的格式相同(话题-标题-wiki文本)。",
+ "apihelp-flow+edit-title-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的标题",
+ "apihelp-flow+edit-topic-summary-description": "编辑一个话题的摘要内容。",
+ "apihelp-flow+edit-topic-summary-summary": "编辑一个话题的摘要内容。",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "当前话题摘要修订的版本ID(如果有),以检查编辑冲突。",
+ "apihelp-flow+edit-topic-summary-param-summary": "编辑摘要的内容。",
+ "apihelp-flow+edit-topic-summary-param-format": "摘要格式(wikitext|html)",
+ "apihelp-flow+edit-topic-summary-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的摘要",
+ "apihelp-flow+lock-topic-description": "锁定或解锁一个Flow话题。",
+ "apihelp-flow+lock-topic-summary": "锁定或解锁一个Flow话题。",
+ "apihelp-flow+lock-topic-param-moderationState": "提交话题的情形,要么<kbd>lock</kbd>要么<kbd>unlock</kbd>。",
+ "apihelp-flow+lock-topic-param-reason": "锁定或解锁此话题的原因。注意wiki上的Flow客户端在此使用“Marked as resolved”,并将可选的额外信息放置在摘要中。",
+ "apihelp-flow+lock-topic-example-1": "锁定[[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+moderate-post-description": "限制一个Flow帖子。",
+ "apihelp-flow+moderate-post-summary": "限制一个Flow帖子。",
+ "apihelp-flow+moderate-post-param-moderationState": "限制等级。",
+ "apihelp-flow+moderate-post-param-reason": "限制的原因。",
+ "apihelp-flow+moderate-post-param-postId": "要限制的帖子ID。",
+ "apihelp-flow+moderate-post-example-1": "删除话题[[Topic:S2tycnas4hcucw8w]]中的帖子",
+ "apihelp-flow+moderate-topic-description": "限制一个Flow帖子。",
+ "apihelp-flow+moderate-topic-summary": "限制一个Flow帖子。",
+ "apihelp-flow+moderate-topic-param-moderationState": "限制等级。",
+ "apihelp-flow+moderate-topic-param-reason": "限制的原因。",
+ "apihelp-flow+moderate-topic-example-1": "删除话题[[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+new-topic-description": "在指定的工作流中创建一个新的Flow话题。",
+ "apihelp-flow+new-topic-summary": "在指定的工作流中创建一个新的Flow话题。",
+ "apihelp-flow+new-topic-param-topic": "用于新话题标题的文字。",
+ "apihelp-flow+new-topic-param-content": "用于话题的最初回复的内容。",
+ "apihelp-flow+new-topic-param-format": "新话题首次回复的格式 (wikitext|html)",
+ "apihelp-flow+new-topic-example-1": "在[[Talk:Sandbox]]创建一个新话题",
+ "apihelp-flow+reply-description": "回复一个帖子。",
+ "apihelp-flow+reply-summary": "回复一个帖子。",
+ "apihelp-flow+reply-param-replyTo": "要回复的ID。",
+ "apihelp-flow+reply-param-content": "新帖子的内容。",
+ "apihelp-flow+reply-param-format": "新帖子的格式(wikitext|html)",
+ "apihelp-flow+reply-example-1": "回复[[Topic:S2tycnas4hcucw8w]]中的帖子",
+ "apihelp-flow+view-header-param-format": "返回内容的格式。",
+ "apihelp-flow+view-header-description": "查看板块描述。",
+ "apihelp-flow+view-header-summary": "查看板块描述。",
+ "apihelp-flow+view-header-param-revId": "加载此修订版本,而不是最新的。",
+ "apihelp-flow+view-header-example-1": "获取[[Talk:Sandbox]]的描述作为wiki文本",
+ "apihelp-flow+view-post-description": "查看帖子。",
+ "apihelp-flow+view-post-summary": "查看帖子。",
+ "apihelp-flow+view-post-param-postId": "要查看的帖子ID。",
+ "apihelp-flow+view-post-param-format": "返回内容的格式。",
+ "apihelp-flow+view-post-example-1": "获取[[Topic:S2tycnas4hcucw8w]]中帖子的内容作为wiki文本",
+ "apihelp-flow+view-post-history-description": "浏览一个帖子的修订历史。",
+ "apihelp-flow+view-post-history-summary": "浏览一个帖子的修订历史。",
+ "apihelp-flow+view-post-history-param-postId": "要查看修订历史的帖子ID。",
+ "apihelp-flow+view-post-history-param-format": "返回内容的格式。",
+ "apihelp-flow+view-post-history-example-1": "检索在[[Topic:S2tycnas4hcucw8w]]中的帖子修订作为wiki文本",
+ "apihelp-flow+view-topic-description": "查看话题。",
+ "apihelp-flow+view-topic-summary": "查看话题。",
+ "apihelp-flow+view-topic-param-format": "返回内容的格式。",
+ "apihelp-flow+view-topic-example-1": "查看[[Topic:S2tycnas4hcucw8w]]",
+ "apihelp-flow+view-topic-history-description": "浏览一个话题的修订历史。",
+ "apihelp-flow+view-topic-history-summary": "浏览一个话题的修订历史。",
+ "apihelp-flow+view-topic-history-param-format": "返回内容的格式。",
+ "apihelp-flow+view-topic-history-example-1": "查看在[[Topic:S2tycnas4hcucw8w]]的帖子修订作为wiki文本",
+ "apihelp-flow+view-topic-summary-description": "查看话题摘要。",
+ "apihelp-flow+view-topic-summary-summary": "查看话题摘要。",
+ "apihelp-flow+view-topic-summary-param-format": "返回内容的格式。",
+ "apihelp-flow+view-topic-summary-param-revId": "加载此修订版本,而不是最新的。",
+ "apihelp-flow+view-topic-summary-example-1": "查看[[Topic:S2tycnas4hcucw8w]]的摘要作为wiki文本",
+ "apihelp-flow+view-topiclist-description": "查看话题列表。",
+ "apihelp-flow+view-topiclist-summary": "查看话题列表。",
+ "apihelp-flow+view-topiclist-param-offset-dir": "排序话题的方向。",
+ "apihelp-flow+view-topiclist-param-sortby": "话题的排序选项,既可以是<kbd>updated</kbd>(按话题更新时间排序),又可以是<kbd>newest</kbd>(按话题创建时间排序)。",
+ "apihelp-flow+view-topiclist-param-savesortby": "保存排序方式选项至用户设置,如果设置。",
+ "apihelp-flow+view-topiclist-param-offset-id": "开始抓取话题的偏移值(UUID格式),只与<kbd>newest</kbd>一起用于排序",
+ "apihelp-flow+view-topiclist-param-offset": "偏移值(作为一个<code>TS_MW</code>格式的话题更新时间戳(<code>YYYYMMDDHHMMSS</code>)),以开始取得话题;只与<kbd>updated</kbd>一起排序",
+ "apihelp-flow+view-topiclist-param-include-offset": "在结果中也包括抵消项目。",
+ "apihelp-flow+view-topiclist-param-limit": "要取得的话题数量。",
+ "apihelp-flow+view-topiclist-param-toconly": "是否只响应TOC需要的信息。",
+ "apihelp-flow+view-topiclist-param-format": "返回内容的格式。",
+ "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]]的话题列表",
+ "apihelp-flow-parsoid-utils-description": "在wiki文本和HTML之间互相转换文本。",
+ "apihelp-flow-parsoid-utils-summary": "在wiki文本和HTML之间互相转换文本。",
+ "apihelp-flow-parsoid-utils-param-from": "要转换内容的来源格式。",
+ "apihelp-flow-parsoid-utils-param-to": "要转换内容的目标格式。",
+ "apihelp-flow-parsoid-utils-param-content": "要转换的内容。",
+ "apihelp-flow-parsoid-utils-param-title": "页面标题。不能与$1pageid一起使用。",
+ "apihelp-flow-parsoid-utils-param-pageid": "页面ID。不能与$1title一起使用。",
+ "apihelp-flow-parsoid-utils-example-1": "将wiki文本<nowiki>'''lorem''' ''blah''</nowiki>转换为HTML",
+ "apihelp-query+flowinfo-description": "获取有关页面的基本Flow信息。",
+ "apihelp-query+flowinfo-summary": "获取有关页面的基本Flow信息。",
+ "apihelp-query+flowinfo-example-1": "获取有关[[Talk:Sandbox]]、[[Main Page]]和[[Talk:Flow]]的Flow信息",
+ "apihelp-flow+undo-edit-header-description": "检索撤销描述编辑所必需的信息。",
+ "apihelp-flow+undo-edit-header-summary": "检索撤销描述编辑所必需的信息。",
+ "apihelp-flow+undo-edit-header-param-startId": "要开始撤销的修订ID。",
+ "apihelp-flow+undo-edit-header-param-endId": "要结束撤销的修订ID。",
+ "apihelp-flow+undo-edit-header-example-1": "检索有关在[[Talk:Sandbox]]撤销一次描述编辑的信息",
+ "apihelp-flow+undo-edit-post-description": "检索撤销帖子编辑所必需的信息。",
+ "apihelp-flow+undo-edit-post-summary": "检索撤销帖子编辑所必需的信息。",
+ "apihelp-flow+undo-edit-post-param-postId": "要回退的帖子ID。",
+ "apihelp-flow+undo-edit-post-param-startId": "要开始撤销的修订ID。",
+ "apihelp-flow+undo-edit-post-param-endId": "要结束撤销的修订ID。",
+ "apihelp-flow+undo-edit-post-example-1": "取得有关在一次话题中撤销一次帖子编辑的信息。",
+ "apihelp-flow+undo-edit-topic-summary-description": "检索撤销话题摘要编辑所必需的信息。",
+ "apihelp-flow+undo-edit-topic-summary-summary": "检索撤销话题摘要编辑所必需的信息。",
+ "apihelp-flow+undo-edit-topic-summary-param-startId": "要开始撤销的修订ID。",
+ "apihelp-flow+undo-edit-topic-summary-param-endId": "要结束撤销的修订ID。",
+ "apihelp-flow+undo-edit-topic-summary-example-1": "取得有关撤销在特定话题中一次话题摘要的编辑的信息",
+ "apierror-flow-safeallowcreationfailed": "提供的页面并未启用Flow,并且safeAllowCreation失败:$1",
+ "apierror-flow-notenabled": "提供的页面并未启用Flow。"
+}
diff --git a/Flow/i18n/api/zh-hant.json b/Flow/i18n/api/zh-hant.json
new file mode 100644
index 00000000..b63f1788
--- /dev/null
+++ b/Flow/i18n/api/zh-hant.json
@@ -0,0 +1,50 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bowleerin",
+ "Cwlin0416",
+ "EagerLin"
+ ]
+ },
+ "apihelp-flow-description": "允許對 Flow 頁面執行操作。",
+ "apihelp-flow-param-submodule": "要使用的 Flow 子模組。",
+ "apihelp-flow-param-page": "要執行操作的頁面。",
+ "apihelp-flow-example-1": "編輯 \"[[Talk:Sandbox]]\" 的描述",
+ "apihelp-flow+close-open-topic-description": "已不建議使用 [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]] 用法。",
+ "apihelp-flow+close-open-topic-param-moderationState": "話題要設定的狀態,可為 \"lock\" 或 \"unlock\"。",
+ "apihelp-flow+close-open-topic-param-reason": "鎖定或解除鎖定話題的原因。",
+ "apihelp-flow+edit-header-description": "編輯討論板的描述。",
+ "apihelp-flow+edit-header-param-prev_revision": "目前描述修訂的修訂 ID,以用來檢查編輯衝突。",
+ "apihelp-flow+edit-header-param-content": "內容描述。",
+ "apihelp-flow+edit-header-param-format": "描述格式 (wikitext|html)。",
+ "apihelp-flow+edit-header-example-1": "編輯 [[Talk:Sandbox]] 的描述",
+ "apihelp-flow+edit-post-description": "編輯一篇貼文的內容。",
+ "apihelp-flow+edit-post-param-postId": "貼文 ID。",
+ "apihelp-flow+edit-post-param-prev_revision": "目前貼文修訂的修訂 ID,以用來檢查編輯衝突。",
+ "apihelp-flow+edit-post-param-content": "貼文的內容。",
+ "apihelp-flow+edit-post-param-format": "貼文內容格式 (wikitext|html)",
+ "apihelp-flow+edit-post-example-1": "編輯於 [[Topic:S2tycnas4hcucw8w]] 的貼文",
+ "apihelp-flow+edit-title-description": "編輯話題的標題。",
+ "apihelp-flow+edit-title-param-prev_revision": "目前標題修訂的版本ID,以檢查編輯衝突。",
+ "apihelp-flow+edit-title-param-content": "標題內容",
+ "apihelp-flow+edit-title-example-1": "編輯於[[Topic:S2tycnas4hcucw8w]]的標題",
+ "apihelp-flow+edit-topic-summary-description": "編輯話題的摘要內容。",
+ "apihelp-flow+edit-topic-summary-param-prev_revision": "目前標題修訂的版本ID(如果有),以檢查編輯衝突。",
+ "apihelp-flow+edit-topic-summary-param-summary": "編輯摘要內容。",
+ "apihelp-flow+edit-topic-summary-param-format": "描述格式 (wikitext|html)。",
+ "apihelp-flow+edit-topic-summary-example-1": "編輯於[[Topic:S2tycnas4hcucw8w]]的描述",
+ "apihelp-flow+lock-topic-description": "鎖定或解鎖一則Flow話題。",
+ "apihelp-flow+lock-topic-param-moderationState": "提交話題的情形,要<kbd>lock</kbd>還是要<kbd>unlock</kbd>。",
+ "apihelp-flow+moderate-post-description": "限制Flow的貼文。",
+ "apihelp-flow+moderate-post-param-moderationState": "限制等級。",
+ "apihelp-flow+moderate-post-param-reason": "限制的原因。",
+ "apihelp-flow+moderate-post-param-postId": "要限制的貼文ID。",
+ "apihelp-flow+moderate-post-example-1": "刪除於[[Topic:S2tycnas4hcucw8w]]的話題",
+ "apihelp-flow+moderate-topic-description": "限制一則 Flow 的話題。",
+ "apihelp-flow+moderate-topic-param-reason": "限制的原因。",
+ "apihelp-flow+reply-description": "回覆一篇貼文。",
+ "apihelp-flow+reply-param-content": "新貼文的內容。",
+ "apihelp-flow+reply-example-1": "於 [[Topic:S2tycnas4hcucw8w]] 回覆一篇貼文",
+ "apihelp-flow+view-header-description": "檢視討論板的描述。",
+ "apihelp-flow+view-post-description": "檢視一篇貼文。"
+}
diff --git a/Flow/i18n/ar.json b/Flow/i18n/ar.json
index 681609dd..ad6b0445 100644
--- a/Flow/i18n/ar.json
+++ b/Flow/i18n/ar.json
@@ -7,34 +7,121 @@
"محمد أحمد عبد الفتاح",
"Meno25",
"Hiba Alshawi",
- "Macofe"
+ "Macofe",
+ "Shbib Al-Subaie",
+ "Sonic N800",
+ "علاء",
+ "بدارين",
+ "زكريا",
+ "Youssef",
+ "ديفيد",
+ "Mido"
]
},
+ "enablestructureddiscussions": "فعّل النقاشات الهيكلية",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|توقف|توقفي}} عن مراقبة النشاط الجديد على \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|أنت}} لم تعد تراقب الصفحة \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "هذا لن يؤثر على الموضوعات الفردية التي {{GENDER:$3|تراقبها|تراقبينها}} . يمكنك مراقبة [$2 هذه الصفحة] في أي وقت.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|توقف|توقفي}} عن مراقبة هذا الموضوع",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|أنت}} لم تعد تراقب \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|أنت}} يمكنك مراقبة [$2 هذا الموضوع] في أي وقت.",
+ "flow-desc": "نظام النقاش",
+ "flow-talk-taken-over-comment": "/* هذه الصفحة تم تحويلها إلى منصة النقاشات الهيكلية */",
+ "log-name-flow": "سجل نشاط النقاشات الهيكلية",
+ "logentry-delete-flow-delete-post": "{{GENDER:$2|حذف|حذفت}} $1 [$4 منشورًا] في \"[[$3|$5]]\" على [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|حذف}} تعليق على موضوع على [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|استعاد}} [$4 تعليق] على \"[[$3|$5]]\" على [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|استعاد}} تعليقا على موضوع على [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|أزال}} [$4 منشورًا] على \"[[$3|$5]]\" على [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|إزال}} رداً على موضوع على [[$3]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|حذف|حذفت}} [$4 منشوراً] على \"[[$3|$5]]\" على [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "{{GENDER:$2|حذف|حذفت}} $1 منشورًا على موضوع في [[$3]]",
+ "logentry-delete-flow-delete-topic": "{{GENDER:$2|حذف|حذفت}} $1 موضوع \"[[$3|$5]]\" على [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "{{GENDER:$2|حذف|حذفت}} $1 موضوعًا على [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|استعاد|استعادت}} موضوعاً \"[[$3|$5]]\" على [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|استعاد|استعادت}} موضوعاً على [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ألغى|ألغت}} موضوعاً \"[[$3|$5]]\" على [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|ألغى|ألغت}} موضوعاً على [[$3]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|حذف|حذفت}} موضوع \"[[$3|$5]]\" على [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|حذف|حذفت}} موضوعاً على [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|علّم|علّمت}} موضوعاً \"[[$3|$5]]\" كمحلول على [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|علّم|علّمت}} موضوعاً كمحلول على [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|أعاد فتح|أعادت فتح}} موضوع \"[[$3|$5]]\" على [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|أعاد فتح|أعادت فتح}} موضوعاً على [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] على [[$3]] تم استيرادها من LiquidThreads إلى النقاشات الهيكلية",
+ "abusefilter-edit-builder-vars-board-articleid": "رقم الصفحة للوحة النقاشات الهيكلية",
+ "abusefilter-edit-builder-vars-board-namespace": "نطاق لوحة النقاشات الهيكلية",
+ "abusefilter-edit-builder-vars-board-text": "عنوان لوحة النقاشات الهيكلية",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "العنوان الكامل للوحة النقاشات الهيكلية",
+ "flow-user-moderated": "مستخدم مقيد",
"flow-board-header-browse-topics-link": "تصفح المواضيع",
- "flow-board-header": "عن هذا النقاش",
+ "flow-board-header": "حول هذه الصفحة",
+ "flow-board-description-can-not-edit": "غير قابلة للتعديل",
"flow-board-collapse-description": "أخف الوصف",
"flow-board-expand-description": "أظهر الوصف",
+ "flow-topic-collapse-siderail": "اقرأ بالعرض الكامل",
+ "flow-topic-expand-siderail": "اقرأ بعرض محدد",
"flow-edit-header-link": "عدل الوصف",
+ "flow-post-moderated-toggle-hide-show": "اعرض تعديلاً {{GENDER:$1|أخفاه|أخفته}} $2",
+ "flow-post-moderated-toggle-delete-show": "اعرض تعديلًا {{GENDER:$1|حذفه|حذفته}} $2",
+ "flow-post-moderated-toggle-suppress-show": "إظهار تعليق {{GENDER:$1|أُلغي}} بواسطة $2",
+ "flow-post-moderated-toggle-hide-hide": "اخفاء تعليق {{GENDER:$1|أُخفي}} بواسطة $2",
+ "flow-post-moderated-toggle-delete-hide": "اخفاء تعليق {{GENDER:$1|حذف}} بواسطة $2",
+ "flow-post-moderated-toggle-suppress-hide": "اخفاء تعليق {{GENDER:$1|ألغي}} بواسطة $2",
"flow-topic-moderated-reason-prefix": "السبب:",
+ "flow-hide-post-content": "هذا التعليق تم {{GENDER:$1|اخفاءه}} بواسطة $1 ([$2 تاريخ])",
+ "flow-hide-title-content": "هذا الموضوع {{GENDER:$1|أخفاه|أخفته}} $1",
+ "flow-hide-header-content": "{{GENDER:$1|أخفي}} بواسطة $2",
+ "flow-delete-post-content": "{{GENDER:$1|قام|قامت}} $1 بحذف هذا التعليق ([$2 تاريخ])",
+ "flow-delete-title-content": "هذا الموضوع {{GENDER:$1|حذف}} بواسطة $1",
+ "flow-delete-header-content": "{{GENDER:$1|حذف}} بواسطة $2",
+ "flow-suppress-post-content": "هذا التعليق {{GENDER:$1|أُزيل}} بواسطة $1 ([$2 تاريخ])",
+ "flow-suppress-title-content": "هذا الموضوع تم {{GENDER:$1|طمسه}} بواسطة $1",
+ "flow-suppress-header-content": "{{GENDER:$1|طمس}} بواسطة $2",
+ "flow-suppress-usertext": "<em>اسم مستخدم تم طمسه</em>",
"flow-post-actions": "الإجراءات",
"flow-topic-actions": "الإجراءات",
"flow-cancel": "ألغ",
+ "flow-skip-summary": "تجاوز",
+ "flow-edit-summary-placeholder": "وصف موجز لنتائج هذه المناقشة",
+ "flow-summary-authored": "{{GENDER:$1|لخّص|لخّصت}} $1 هذا الموضوع",
+ "flow-summary-edited": "ملخص أخير {{GENDER:$1|حرر}} بواسطة $1",
"flow-show-change": "اعرض التغييرات",
+ "flow-last-modified-by": "آخر {{GENDER:$1|تعديل}} بواسطة $1",
+ "flow-stub-post-content": "<em> بسبب خطأ تقني، فهذا المحتوى لا يمكن استرجاعه.</em>",
"flow-newtopic-title-placeholder": "موضوع جديد",
+ "flow-newtopic-content-placeholder": "أضف رسالة جديدة إلى \"$1\"",
+ "flow-newtopic-header": "أضف موضوعاً جديداً",
+ "flow-newtopic-save": "أضف موضوعاً",
+ "flow-newtopic-save-anonymously": "إضافة موضوع كمجهول",
+ "flow-newtopic-start-placeholder": "أضف موضوعاً جديداً",
+ "flow-newtopic-first-heading": "ابدأ موضوعًا جديدًا في $1",
+ "flow-summarize-topic-placeholder": "برجاء تلخيص النقاش",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|علّق|علّقت}} على \"$2\"",
"flow-reply-topic-title-placeholder": "رد على \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|رد}}",
+ "flow-reply-link-anonymously": "الرد بصفة مجهول",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|شكر}}}}",
+ "flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|أشكر}}}} الناشر بشكل علني",
+ "flow-history-action-suppress-post": "طمس/حذف",
"flow-history-action-delete-post": "احذف",
"flow-history-action-hide-post": "أخف",
+ "flow-history-action-unsuppress-post": "تراجع عن الحذف/الطمس",
"flow-history-action-undelete-post": "ألغ الحذف",
"flow-history-action-unhide-post": "أظهر",
"flow-history-action-restore-post": "استعد",
"flow-history-action-lock-topic": "حل",
"flow-history-action-unlock-topic": "إعادة فتح",
+ "flow-post-edited": "{{GENDER:$1|عدل|عدلت}} $1 التعليق $2",
"flow-post-action-view": "وصلة دائمة",
"flow-post-action-post-history": "تاريخ",
+ "flow-post-action-suppress-post": "طمس/حذف",
"flow-post-action-delete-post": "احذف",
"flow-post-action-hide-post": "أخف",
"flow-post-action-edit-post": "عدل",
"flow-post-action-edit-post-submit": "احفظ التغييرات",
+ "flow-post-action-edit-post-submit-anonymously": "احفظ التغييرات بصفة مجهول",
+ "flow-post-action-unsuppress-post": "استعادة الطمس/الحذف",
"flow-post-action-undelete-post": "ألغ الحذف",
"flow-post-action-unhide-post": "أظهر",
"flow-post-action-restore-post": "استرجع",
@@ -44,65 +131,406 @@
"flow-topic-action-edit-title": "عدل العنوان",
"flow-topic-action-history": "تاريخ",
"flow-topic-action-hide-topic": "أخف الموضوع",
+ "flow-topic-action-delete-topic": "حذف الموضوع",
+ "flow-topic-action-lock-topic": "علّم كمحلول",
+ "flow-topic-action-unlock-topic": "أعد فتح الموضوع",
"flow-topic-action-summarize-topic": "لخص",
"flow-topic-action-resummarize-topic": "عدل ملخص الموضوع",
"flow-topic-action-update-topic-summary": "حدث الملخص",
+ "flow-topic-action-suppress-topic": "طمس/حذف موضوع",
+ "flow-topic-action-unhide-topic": "أظهر الموضوع",
+ "flow-topic-action-undelete-topic": "استرجع الموضوع",
+ "flow-topic-action-unsuppress-topic": "إزالة طمس الموضوع",
+ "flow-topic-action-restore-topic": "استعادة الموضوع",
"flow-topic-action-undo-moderation": "رجوع",
+ "flow-topic-notification-subscribe-title": "تمت إضافة هذا الموضوع إلى قائمة المراقبة {{GENDER:$1|الخاصة بك}}.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|ستتلقى|ستتلقين}} إشعاراتٍ بجميع الأنشطة في هذا الموضوع.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|أنت}} متابع لنقاش هذه الصفحة!",
+ "flow-board-notification-subscribe-description": "سوف {{GENDER:$1|يصلك}} إشعار في حال إضافة موضوع جديد في هذه الصفحة.",
+ "flow-topic-action-watchlist-add": "تابع هذا الموضوع",
+ "flow-topic-action-watchlist-remove": "ألغِ الاشتراك",
+ "flow-error-allowcreation-no-usedb": "لتمكين النقاشات الهيكلية على صفحة معينة يجب أن تكون قيمة <var>$wgContentHandlerUseDB</var> تساوي <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "الصفحة موجودة فعلا عند الهدف، لذا فلا يمكن نقل لوحة نقاشات هيكلية هناك.",
+ "flow-error-allowcreation-flow-create-board": "المستخدم لا يمتلك صلاحية \"{{int:right-flow-create-board|إنشاء تدفق للصفحة}}\"",
+ "flow-error-can-not-edit-logged-out": "لا يمكنك المشاركة حالياً، جرب أن تسجل الدخول.",
+ "flow-error-can-not-edit-logged-in": "لا يمكنك المشاركة حالياً، نظرا لعدم امتلاكك الصلاحيات المطلوبة.",
"flow-error-http": "حدث خطأ أثناء الاتصال بالخادم.",
- "flow-error-other": "حدث خطأ غير متوقع.",
- "flow-error-external": "حدث خطأ.<br />رسالة الخطأ المتلقاة هي: $1",
+ "flow-error-external": "حدث خطأ. رسالة الخطأ المتلقاة هي: $1",
+ "flow-error-topic-is-locked": "لا يمكن المشاركة في هذا الموضوع؛ لأنهُ مُعلم كمحلول.",
+ "flow-error-lock-moderated-post": "لا يمكنك تعليم منشور مقيد كمحلول.",
+ "flow-error-missing-content": "المنشور فارغ، يجب وضع محتوى ليتم حفظه.",
"flow-error-missing-summary": "يجب أن ترسل ملخص.",
+ "flow-error-missing-title": "هذا الموضوع لا يملك عنوان. تحتاج لكتابة عنوان ليتم حفظه.",
+ "flow-error-parsoid-failure": "لا يمكن نقل المحتوى؛ بسب فشل الاتصال بالخادم للتحويل بين نص ويكي وإتش تي إم إل، لذلك رجاءا قم بتفحص اتصال الانترنت الخاص بك أو حاول مرة أخرى لاحقا، وفي حال تلقيك الخطأ مرة أخرى، قم بإرسال تقرير بالخطأ.",
+ "flow-error-protected-autoconfirmed-logged-in": "هذه الصفحة محمية، فقط المستخدمين المؤكدين تلقائيا يمكنهم المساهمة فيها.\nالسبب: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "هذه الصفحة محمية، فقط المستخدمين المسجلين الحاصلين على صلاحية مؤكد تلقائي يمكنهم المساهمة. السبب: $1",
+ "flow-error-protected-sysop-logged-in": "هذه الصفحة محمية، فقط الإداريين يمكنهم المساهمة. السبب: $1",
+ "flow-error-protected-sysop-logged-out": "هذه الصفحة محمية، فقط المستخدمين المسجلين والحاصلين على صلاحية الإدارة يمكنهم المساهمة. السبب: $1",
+ "flow-error-protected-unknown-reason": "مجهول",
+ "flow-error-missing-replyto": "لم يتم تزويد أي مُعلمة \"replyTo\". وجود المُعلمة ضروري لِـ \"reply\"",
+ "flow-error-missing-postId": "لم يتم تزويد أي مُعلمة \"postId\". وجود المُعلمة ضروري للتعامل مع المنشور.",
+ "flow-error-invalid-postId": "مُعلمة \"postId\" غير صحيحة، لذلك لا يمكن العثور على المنشور ($1) المحدد.",
+ "flow-error-invalid-moderation-state": "قيمة غير صحيحة للمعامل ('moderationState') تم إرسالها إلى API النقاشات الهيكلية.",
+ "flow-error-invalid-moderation-reason": "يرجى تقديم سبب للإشراف.",
+ "flow-error-not-allowed": "أذونات غير كافية لتنفيذ هذا الإجراء.",
+ "flow-error-not-allowed-hide": "تم إخفاء هذا الموضوع.",
+ "flow-error-not-allowed-reply-to-hide-topic": "لا يمكنك الرد لأن هذا الموضوع تم إخفاؤه.",
+ "flow-error-not-allowed-delete": "تم حذف هذا الموضوع.",
+ "flow-error-not-allowed-reply-to-delete-topic": "لا تستطيع الرد لأن الموضوع تم حذفه.",
+ "flow-error-not-allowed-suppress": "تم حذف هذا الموضوع.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "لا تستطيع الرد لأن هذا الموضوع تم حذفه.",
+ "flow-error-not-allowed-hide-extract": "تم إخفاء هذا الموضوع. يتم توفير سجل الإخفاء للموضوع في الأسفل للرجوع اليها.",
+ "flow-error-not-allowed-delete-extract": "تم حذف هذا الموضوع. يتم توفير سجل الحذف للموضوع في الأسفل للرجوع اليه.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "لا تستطيع الرد لأن الموضوع تم حذفه. يتم توفير سجل الحذف للموضوع في الأسفل للرجوع اليه.",
+ "flow-error-not-allowed-suppress-extract": "تم حذف هذا الموضوع. يتم توفير سجل الحذف للموضوع في الأسفل للرجوع اليه.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "لا يمكنك الرد لأن هذا الموضوع قد تم إزالته. يتم توفير سجل الإزالة للموضوع في الأسفل للرجوع اليه.",
+ "flow-error-title-too-long": "عناوين الموضوعات تقتصر على $1 {{PLURAL:$1|بايت|بايتات}}.",
+ "flow-error-no-existing-workflow": "سير عمل التدفق هذا غير موجود حتى الآن.",
+ "flow-error-not-a-post": "لا يمكن حفظ عنوان الموضوع كمنشور.",
"flow-error-missing-header-content": "يجب أن ترسل وصفا.",
+ "flow-error-missing-prev-revision-identifier": "معرف المراجعة السابقة غير موجود.",
+ "flow-error-prev-revision-mismatch": "لقد قام مستخدم آخر بتعديل هذا المنشور قبل عدة ثواني، هل {{GENDER:$3|أنت}} متأكد من أنك تريد الكتابة فوق التعديلات الأخيرة؟",
+ "flow-error-prev-revision-does-not-exist": "لا يمكن العثور على المراجعة السابقة.",
+ "flow-error-core-topic-deletion": "لحذف موضوع، استخدم ... القائمة في لوحة النقاشات الهيكلية أو [$1 صفحة الموضوع]. لا تقم بزيارة action=delete للموضوع مباشرة.",
"flow-error-default": "حدث خطأ.",
- "flow-error-invalid-topic-uuid-title": "عنوان سيء",
+ "flow-error-invalid-input": "الدالة المدخلة غير صالحة لتحميل محتوى النقاشات الهيكلية.",
+ "flow-error-invalid-title": "عنوان خاطئ للصفحة.",
+ "flow-error-invalid-parameter": "معامل مفقود أو غير صحيح لاستدعاء الدالة",
+ "flow-error-fail-load-history": "فشل تحميل محتوى التاريخ.",
+ "flow-error-missing-revision": "لم يتم إيجاد مراجعة لتحميل محتوى النقاشات الهيكلية.",
+ "flow-error-fail-commit": "تعذر حفظ محتوى النقاشات الهيكلية.",
+ "flow-error-insufficient-permission": "صلاحيات غير كافية للوصول إلى المحتوى.",
+ "flow-error-revision-comparison": "عرض الفرق يمكن إجراؤه فقط لمراجعتين تنتميان لنفس المنشور.",
+ "flow-error-missing-topic-title": "تعذر العثور على عنوان الموضوع الخاص بسير عمل التدفق الحالي.",
+ "flow-error-missing-metadata": "لم يتم إيجاد ويكي داتا المطلوبة لهذه المراجعة.",
+ "flow-error-different-page": "workflow النقاشات الهيكلية غير مرتبط بهذه الصفحة.",
+ "flow-error-fail-load-data": "فشل في تحميل البيانات المطلوبة.",
+ "flow-error-invalid-workflow": "تعذر العثور على سير عمل التدفق المطلوب.",
+ "flow-error-process-data": "حصل خطأ أثناء معالجة البيانات في طلبك.",
+ "flow-error-process-wikitext": "لقد حدث خطأ أثناء عملية التحويل بين نص ويكي وإتش تي إم إل.",
+ "flow-error-no-index": "تعذر العثور على مؤشر لإتمام عملية البحث عن البيانات.",
+ "flow-error-no-render": "لم يتم التعرف على الإجراء المحدد.",
+ "flow-error-no-commit": "لا يمكن حفظ الإجراء المحدد.",
+ "flow-error-content-too-long": "المحتوى كبير جدا. فبعد توسيع المحتوى أصبح محدود ب $1 {{PLURAL:$1|بايت|بايتات}}.",
+ "flow-error-move-topic": "من غير الممكن نقل عنوان الصفحة في الوقت الحالي.",
+ "flow-error-invalid-topic-uuid-title": "عنوان سيئ",
+ "flow-error-invalid-topic-uuid": "عنوان الصفحة المطلوب كان غير صحيح. الصفحات في النطاق Topic يتم إنشاؤها تلقائيا بواسطة النقاشات الهيكلية.",
"flow-error-unknown-workflow-id-title": "موضوع غير معروف",
"flow-error-unknown-workflow-id": "الموضوع المطلوب غير موجود.",
+ "flow-error-search": "لا يمكننا إكمال البحث بسبب خلل مؤقت. رجاءا حاول فيما بعد.",
+ "flow-error-invalid-undelete": "لا يمكن استرجاع هذه الصفحة نظرا لوجود مكان نقاش في الصفحة.",
+ "flow-edit-header-placeholder": "ضع وصفا لنقاش هذه الصفحة.",
+ "flow-edit-header-submit": "احفظ الوصف",
+ "flow-edit-header-submit-anonymously": "احفظ الوصف بصفة مجهولة",
"flow-edit-title-submit": "تغيير العنوان",
+ "flow-edit-title-submit-anonymously": "تغيير العنوان كمجهول",
"flow-edit-post-submit": "أرسل التغييرات",
- "flow-edit-post-submit-anonymously": "إرسال التغييرات مجهول",
+ "flow-edit-post-submit-anonymously": "إرسال التغييرات كمجهول",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|عدل|عدلت}} [$3 تعليقاً] على \"$4\"",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|عدل|عدلت}} المنشور",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|علّق|علّقت}}] على \"$4\" (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|تعليق|تعليقات}}</strong> {{PLURAL:$1|قد}} أُضيفت",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|أنشأ|أنشأت}} الموضوع \"[$3 $4]\"",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|أنشأ|أنشأت}} موضوعاً جديداً",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|عدّل|عدّلت}} عنوان الموضوع من \"$5\" إلى \"[$3 $4]\"",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|أنشأ|أنشأت}} الوصف",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|حرر}} الوصف",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|أنشأ|أنشأت}} ملخص موضوع في $3",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|عدّل|عدّلت}} ملخص موضوع على $3",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|أخفى|أخفت}} [$4 تعليقاً] على \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "{{GENDER:$2|حذف|حذفت}} $1 [$4 تعليقًا] على \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|ألغى|ألغت}} [$4 تعليقاً] على \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|استعاد|استعادت}} [$4 تعليقاً] على \"$6\" (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|أخفى}} [$4 الموضوع] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|حذف|حذفت}} [$4 الموضوع] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|طمس|طمست}} [$4 الموضوع] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|علّم|علّمت}} [$4 الموضوع] \"$6\" كمحلول(<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "عُلم كمبتوت فيه",
+ "flow-rev-message-restore-topic-reason": "إعادة فتح",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|استعاد|استعادت}} [$4 الموضوع] \"$6\" (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 على $2",
"flow-board-history": "تاريخ \"$1\"",
+ "flow-board-history-empty": "لا يوجد تاريخ لهذه الصفحة.",
"flow-topic-history": "تاريخ موضوع \"$1\"",
+ "flow-post-history": "\"تم التعليق بواسطة {{GENDER:$2|$2}}\" التاريخ السابق",
"flow-history-last4": "آخر 4 ساعات",
"flow-history-day": "اليوم",
"flow-history-week": "الأسبوع الماضي",
+ "flow-history-pages-topic": "يظهر في [$1 \"$2\" الصفحة]",
+ "flow-history-pages-post": "يظهر في [$1 $2]",
+ "flow-topic-comments": "{{PLURAL:$1|تعليق واحد|تعليقان|$1 تعليقات|0={{GENDER:$2|كن أول|كوني أول}} من يعلق!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|اعرض التعليق|اعرض التعليقات}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|أخف التعليق|أخف التعليقات}}",
"flow-comment-restored": "استرجاع التعليق",
"flow-comment-deleted": "حذف تعليق",
"flow-comment-hidden": "إخفاء التعليق",
+ "flow-comment-moderated": "تعليق مقيد",
+ "flow-last-modified": "آخر تعديل تم في حوالي $1",
+ "flow-workflow": "سير عمل التدفق",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|أجاب|أجابت}} على <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 و{{PLURAL:$5|واحد آخر|$5 آخرون|100=99+ آخرون}} {{GENDER:$1|رد}} على <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 لقد قام {{GENDER:$1|بتعديل}} <span class=\"plainlinks\">[$5 منشورك]</span> على [[$3|$4]].",
+ "flow-notification-edit-bundle": "$1 و{{PLURAL:$5|واحد آخر|$5 آخرون|100=99+ آخرون}} {{GENDER:$1|عدّل}} <span class=\"plainlinks\">[$4 منشور]</span> في\"$2\" على\"$3\".",
+ "notification-header-flow-new-topic-v2": "أنشئ موضوع جديد في <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|موضوع واحد جديد|$1 مواضيع جديدة|100=99+ مواضيع جديدة}} على <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "أنشئ موضوع جديد في <strong>صفحة نقاشك</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|رسالة جديدة|رسالتان جديدتان|$1 رسائل جديدة|$1 رسالة جديدة}} في '''صفحة نقاشك'''.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|رد|ردت}} في \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|رد واحد جديد|$1 ردود جديدة|100=99+ ردود جديدة}} in \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|نشر|نشرت}} رداً على <strong>صفحة نقاشك</strong> في \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|رد واحد جديد|$1 ردود جديدة|100=99+ ردود جديدة}} على <strong>صفحة نقاشك</strong> في \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|منشورك}} على \"<strong>$1</strong>\" تم تعديله.",
+ "notification-bundle-header-flow-post-edited-v2": "لقد تم تعديل {{GENDER:$2|منشورك}} في \"<strong>$1</strong>\" عدة مرات.",
+ "notification-header-flow-post-edited-user-talk": "منشور في \"<strong>$1</strong>\" تم تعديله على صفحة <strong>{{GENDER:$2|نقاشك}}</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "تم تعديل هذا المنشور \"<strong>$1</strong>\" في <strong>صفحة {{GENDER:$2|نقاشك}}</strong> عدة مرات.",
+ "notification-header-flow-topic-renamed-v2": "تمت إعادة تسمية الموضوع \"<strong>$1</strong>\" إلى \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "الموضوع \"<strong>$1</strong>\" أعيد تسميته إلى \"<strong>$2</strong>\" على <strong>{{GENDER:$3|صفحة نقاشك}} </strong>.",
+ "notification-header-flow-summary-edited": "حُدث ملخص \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-first": "الموضوع \"<strong>$1</strong>\" تم تلخيصه.",
+ "notification-bundle-header-flow-summary-edited": "حُدث ملخص \"'''$1'''\" عدة مرات.",
+ "notification-header-flow-summary-edited-user-talk": "الملخص ل\"<strong>$1</strong>\" تم تحديثه على <strong>{{GENDER:$2|صفحة نقاشك}}</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "الموضوع \"<strong>$1</strong>\" تم تلخيصه على <strong>{{GENDER:$2|صفحة نقاشك}}</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "الملخص ل\"<strong>$1</strong>\" تم تحديثه عدة مرات على <strong>{{GENDER:$2|صفحة نقاشك}}</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|حدّث|حدّثت}} الملخص على $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|حدّث|حدّثت}} الملخص على $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 و{{PLURAL:$3|آخر|$3 آخرون|100=99+ آخرون}} {{GENDER:$1|حدث|حدّثت}} الملخص على $2",
+ "notification-header-flow-mention-post": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$4|إليك}} في \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|أشار|أشارت}} {{GENDER:$4|لك}} في الوصف ل<strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "{{GENDER:$2|أشار|أشارت}} $1 {{GENDER:$4|إليك}} في \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "تم تمكين نظام مناقشة جديد على <strong>{{GENDER:$2|صفحة نقاشك}} كمستخدم</strong>.",
+ "notification-header-flow-description-edited": "عُدل وصف <strong>$1</strong>.",
+ "notification-header-flow-description-edited-user-talk": "الوصف تم تعديله على <strong>{{GENDER:$2|صفحة نقاشك}}</strong>.",
+ "notification-bundle-header-flow-description-edited": "وصف </strong>$1</strong> عُدل عدة مرات.",
+ "notification-bundle-header-flow-description-edited-user-talk": "تم تحرير الوصف عدة مرات على <strong>{{GENDER:$2|صفحة نقاشك}} </strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|اعرض}} الصفحة",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|عدل|عدلت}} الوصف في $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|عدل|عدلت}} الوصف في $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 و{{PLURAL:$3|آخر|$3 آخرون|100=99+ آخرون}} {{GENDER:$1|عدل|عدلت}} الوصف على $2",
+ "notification-header-flow-topic-resolved": "الموضوع \"<strong>$1</strong>\" تم البت فيه.",
+ "notification-header-flow-topic-reopened": "موضوع \"<strong>$1</strong>\" أعيد فتحه.",
+ "notification-header-flow-topic-resolved-user-talk": "الموضوع \"<strong>$1</strong>\" تم البت فيه على <strong>صفحة نقاشك</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "الموضوع \"<strong>$1</strong>\" أعيد فتحه على <strong>صفحة نقاشك </strong>.",
+ "notification-email-subject-flow-topic-resolved": "الموضوع \"<strong>$2</strong>\" تم البت فيه.",
+ "notification-email-batch-body-flow-topic-resolved": "الموضوع \"<strong>$2</strong>\" تم البت فيه.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|أنشأ|أنشأت}} موضوعا جديدا في <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|موضوع واحد جديد|$1 مواضيع جديدة|100=99+ مواضيع جديدة}} on <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-rename": "$1 {{GENDER:$1|غير|غيرت}} العنوان class=\"plainlinks\">[$2 $3]</span> إلى \"$4\" في [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|المشار إليه}} {{GENDER:$5|هو أنت}} في {{GENDER:$1}} <span class=\"plainlinks\">[$2 رسالة]</span> في\"$3\" في \"$4\".",
"flow-notification-link-text-view-post": "اعرض المنشور",
"flow-notification-link-text-view-topic": "اعرض الموضوع",
+ "flow-notification-link-text-view-topics": "اعرض المواضيع",
"flow-notification-reply-email-subject": "$2 في $3",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|المشار إليه}} {{GENDER:$4|هو أنت}} في {{GENDER:$1}}\nرسالته في \"$2\" في \"$3\"",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|أجاب|أجابت}} على \"$2\" في $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 و {{PLURAL:$4|واحد آخر|$4 أخرون|100=99+ آخرون}} {{GENDER:$1|رد}} على \"$2\" في $3",
+ "flow-notification-mention-email-subject": "قام $1 {{GENDER:$1|بالإشارة}} {{GENDER:$3|إليك}} في $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|أشار|أشارت}} {{GENDER:$4|إليك}} في {{GENDER:$1|منشوره|منشورها|منشورهم}} في \"$2\" في \"$3\"",
+ "flow-notification-edit-email-subject": "{{GENDER:$1|عدل|عدلت}} $1 منشورًا",
+ "flow-notification-edit-email-batch-body": "{{GENDER:$1|عدل|عدلت}} $1 منشورًا على \"$2\" على $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 و {{PLURAL:$4|آخر|$4 آخرون|100=99+ آخرون}} {{GENDER:$1|عدّل|عدّلت}} منشور في \"$2\" على $3",
+ "flow-notification-rename-email-subject": "قام $1 {{GENDER:$1|بإعادة تسمية}} موضوعك",
+ "flow-notification-rename-email-batch-body": "قام $1 {{GENDER:$1|بإعادة تسمية}} موضوعك من $2 إلى $3 في $4",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|أنشأ|أنشأت}} موضوعا جديدا في $2",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|أنشأ|أنشأت}} موضوعاً جديداً بعنوان \"$2\" على $3",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|موضوع واحد جديد|$1 مواضيع جديدة|100=99+ مواضيع جديدة}} على $2",
+ "echo-category-title-flow-discussion": "نقاش هيكلي",
+ "echo-pref-tooltip-flow-discussion": "أخطرني حول النشاط في المواضيع أو الصفحات التي أتابعها.",
+ "flow-link-post": "نشر",
+ "flow-link-topic": "موضوع",
"flow-link-history": "تاريخ",
+ "flow-link-post-revision": "المراجعة السابقة.",
+ "flow-link-topic-revision": "مراجعة الموضوع.",
+ "flow-link-header-revision": "مراجعة الوصف",
+ "flow-link-summary-revision": "مراجعة الملخص",
+ "flow-moderation-title-suppress-post": "طمس المنشور؟",
+ "flow-moderation-title-delete-post": "حذف المنشور؟",
+ "flow-moderation-title-hide-post": "إخفاء المنشور؟",
+ "flow-moderation-title-unsuppress-post": "إزالة طمس المنشور؟",
+ "flow-moderation-title-undelete-post": "إزالة حذف المنشور؟",
+ "flow-moderation-title-unhide-post": "إزالة إخفاء المنشور؟",
+ "flow-moderation-placeholder-suppress-post": "رجاء {{GENDER:$3|وضح}} لماذا تريد طمس هذا المنشور.",
+ "flow-moderation-placeholder-delete-post": "يرجى {{GENDER:$3|توضيح}} سبب حذفك للمنشور.",
+ "flow-moderation-placeholder-hide-post": "يرجى {{GENDER:$3|توضيح}} سبب إخفائك للمنشور.",
+ "flow-moderation-placeholder-unsuppress-post": "رجاء {{GENDER:$3|وضح}} لماذا تريد إلغاء طمس هذا المنشور.",
+ "flow-moderation-placeholder-undelete-post": "يرجى {{GENDER:$3|توضيح}} سبب إلغاء حذف هذا المنشور.",
+ "flow-moderation-placeholder-unhide-post": "يرجى {{GENDER:$3|توضيح}} سبب إظهار هذا المنشور.",
+ "flow-moderation-confirm-suppress-post": "طمس",
+ "flow-moderation-confirm-delete-post": "احذف",
"flow-moderation-confirm-hide-post": "أخف",
+ "flow-moderation-confirm-unsuppress-post": "إلغاء الطمس",
+ "flow-moderation-confirm-undelete-post": "ألغ الحذف",
+ "flow-moderation-confirm-unhide-post": "أظهر",
+ "flow-moderation-confirm-suppress-topic": "طمس",
+ "flow-moderation-confirm-delete-topic": "حذف",
"flow-moderation-confirm-hide-topic": "أخف",
+ "flow-moderation-confirm-unsuppress-topic": "استعادة الطمس/الحذف",
+ "flow-moderation-confirm-undelete-topic": "ألغ الحذف",
+ "flow-moderation-confirm-unhide-topic": "أظهر",
+ "flow-moderation-confirmation-suppress-post": "قد تم طمس المنشور.\n{{GENDER:$2|يمكنك}} منح $1 تعليق خاص بالمنشور.",
+ "flow-moderation-confirmation-delete-post": "قد تم حذف المنشور.\n{{GENDER:$2|يمكنك}} منح $1 تعليق خاص بالمنشور.",
+ "flow-moderation-confirmation-hide-post": "قد تم إخفاء المنشور.\n{{GENDER:$2|يمكنك}} منح $1 تعليق خاص بالمنشور.",
+ "flow-moderation-confirmation-unsuppress-post": "لقد قمت بإزالة طمس المنشور بالأعلى.",
+ "flow-moderation-confirmation-undelete-post": "لقد قمت باسترجاع المنشور بالأعلى.",
+ "flow-moderation-confirmation-unhide-post": "لقد قمت بإظهار المنشور بالأعلى.",
+ "flow-moderation-confirmation-suppress-topic": "هذا الموضوع تم طمسه",
+ "flow-moderation-confirmation-delete-topic": "هذا الموضوع تم حذفه",
+ "flow-moderation-confirmation-hide-topic": "تم اخفاء هذا الموضوع",
+ "flow-moderation-confirmation-unsuppress-topic": "لقد ألغيت طمس هذا الموضوع.",
+ "flow-moderation-confirmation-undelete-topic": "لقد ألغيت حذف هذا الموضوع.",
+ "flow-moderation-confirmation-unhide-topic": "لقد ألغيت إخفاء هذا الموضوع.",
+ "flow-moderation-title-suppress-topic": "طمس/حذف موضوع",
+ "flow-moderation-title-delete-topic": "حذف الموضوع ؟",
+ "flow-moderation-title-hide-topic": "اخفاء موضوع؟",
+ "flow-moderation-title-unsuppress-topic": "إلغاء طمس موضوع؟",
+ "flow-moderation-title-undelete-topic": "إلغاء حذف موضوع؟",
+ "flow-moderation-title-unhide-topic": "إظهار الموضوع؟",
+ "flow-moderation-placeholder-suppress-topic": "رجاء {{GENDER:$3|وضح}} لماذا تريد طمس هذا الموضوع.",
+ "flow-moderation-placeholder-delete-topic": "رجاء {{GENDER:$3|تفسير}} لماذا تحذف هذا الموضوع.",
+ "flow-moderation-placeholder-hide-topic": "رجاء {{GENDER:$3|توضيح}} سبب إخفاء الموضوع.",
+ "flow-moderation-placeholder-unsuppress-topic": "يرجى {{GENDER:$3|تفسير}} سبب إزالة الطمس عن هذا الموضوع.",
+ "flow-moderation-placeholder-undelete-topic": "يرجى {{GENDER:$3|تفسير}} سبب استرجاع هذا الموضوع.",
+ "flow-moderation-placeholder-unhide-topic": "يرجى {{GENDER:$3|تفسير}} سبب إظهار هذا الموضوع.",
"flow-topic-permalink-warning": "بدأ هذا الموضوع في [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "هذا الموضوع قد بدأ في [$2 صفحة {{GENDER:$1|$1}}].",
+ "flow-revision-permalink-warning-post": "هذه وصلة دائمة لنسخة وحيدة من المنشور، وهي من $1.\nيمكنك الإطلاع على [$5 الفرق بينها وبين النسخة السابقة] أو الإطلاع على النسخ الأخرى في [$4 صفحة التاريخ السابق].",
+ "flow-revision-permalink-warning-post-first": "هذه وصلة دائمة للنسخة الأولى من المنشور.\nيمكنك الإطلاع على النسخ الأحدث من خلال صفحة [$4 تاريخ الصفحة السابق].",
+ "flow-revision-permalink-warning-postsummary": "هذه وصلة دائمة لنسخة وحيدة من ملخص المنشور، وهي من $1.\nيمكنك الإطلاع على [$5 الفرق بينها وبين النسخة السابقة] أو الإطلاع على النسخ الأخرى في [$4 صفحة التاريخ السابق].",
+ "flow-revision-permalink-warning-postsummary-first": "هذه وصلة دائمة للنسخة الأولى من ملخص المنشور.\nيمكنك الإطلاع على النسخ الأحدث من خلال صفحة [$4 تاريخ الصفحة السابق].",
+ "flow-revision-permalink-warning-header": "هذه وصلة دائمة لنسخة وحيدة من الوصف، وهي من $1.\nيمكنك الإطلاع على [$3 الفرق بينها وبين النسخة السابقة] أو الإطلاع على النسخ الأخرى في [$2 صفحة التاريخ].",
+ "flow-revision-permalink-warning-header-first": "هذه وصلة دائمة للنسخة الأولى من وصف المنشور.\nيمكنك الإطلاع على النسخ الأحدث من خلال صفحة [$2 تاريخ الصفحة].",
+ "flow-compare-revisions-revision-header": "النسخة الحالية من $1، ولقد تمت بواسطة {{GENDER:$2|$2}}.",
+ "flow-compare-revisions-header-post": "هذه الصفحة تعرض {{GENDER:$3|التغييرات}} بين نسختين على مشاركة بواسطة $3 في موضوع \"[$5 $2]\" على [$4 $1].\nيمكنك الاطلاع على النسخ الأخرى من هذا الرد في [$6 تاريخ الصفحة].",
+ "flow-compare-revisions-header-postsummary": "هذه الصفحة تعرض التغييرات بين نسختين لملخص الموضوع \"[$4 $2]\" على [$3 $1].\nيمكنك الإطلاع على نسخ أخرى من ملخص هذا الموضوع في [$5 تاريخ الصفحة].",
+ "flow-compare-revisions-header-header": "هذه الصفحة تعرض {{GENDER:$2|التغييرات}} بين نسختين من الوصف على [$3 $1].\nتستطيع ان ترى نسخ أخرى من الوصف في [$4 تاريخ الصفحة].",
+ "action-flow-create-board": "أنشئ لوحة نقاش هيكلي في أي مكان",
+ "right-flow-create-board": "أنشئ لوحات النقاشات الهيكلية في أي مكان",
+ "right-flow-hide": "إخفاء مواضيع ورسائل النقاشات الهيكلية",
+ "right-flow-lock": "وسم موضوعات النقاشات الهيكلية كمحلولة",
+ "right-flow-delete": "حذف مواضيع ورسائل النقاشات الهيكلية",
+ "right-flow-edit-post": "تعديل رسائل النقاشات الهيكلية بواسطة المستخدمين الآخرين",
+ "right-flow-suppress": "إخفاء مراجعات النقاشات الهيكلية",
+ "flow-terms-of-use-new-topic": "بالضغط على \"{{int:flow-newtopic-save}}\"، فأنت توافق على شروط الاستخدام لهذا الويكي.",
+ "flow-terms-of-use-reply": "عند النقر \"{{int:flow-reply-link}}\"، فإنك توافق على شروط الاستخدام الخاصة بهذه الويكي.",
+ "flow-terms-of-use-edit": "عند حفظك لهذه التغييرات، فإنك توافق على شروط استخدام هذه الويكي.",
+ "flow-anon-warning": "لم تقم بتسجيل الدخول. وحتى تنسب المساهمة لك بدلا من عنوان IP الخاص بك، يمكنك [$1 تسجيل الدخول] أو [$2 إنشاء حساب].",
+ "flow-cancel-warning": "لقد قمت بإدخال نص في هذا النموذج، هل أنت متأكد من أنك تريد تجاهل ذلك؟",
+ "flow-topic-first-heading": "موضوع في $1",
+ "flow-topic-html-title": "$1 على $2",
+ "flow-topic-count": "مواضيع ($1)",
"flow-load-more": "حمل المزيد",
"flow-no-more-fwd": "لا توجد مواضيع أقدم",
"flow-newest-topics": "المواضيع الأجدد",
- "flow": "سريان",
- "apihelp-flow+edit-post-param-postId": "معرف المنشور.",
+ "flow-recent-topics": "المواضيع النشطة مؤخرا",
+ "flow-sorting-tooltip-newest": "{{GENDER:|أنت}} تقرأ حالياُ أحدث المواضيع . انقر للحصول على المزيد من خيارات الفرز.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|أنت}} تقرأ حاليا أكثر المواضيع النشطة مؤخرا في البداية. انقر للحصول على المزيد من خيارات الفرز.",
+ "flow-toggle-small-topics": "التبديل إلى طريقة عرض المواضيع الصغيرة",
+ "flow-toggle-topics": "التبديل إلى طريقة عرض المواضيع فقط",
+ "flow-toggle-topics-posts": "التبديل إلى طريقة عرض المواضيع والمنشورات",
+ "flow-terms-of-use-summarize": "بالضغط على \"{{int:Flow-topic-action-update-topic-summary}}\"، فإنك توافق على شروط استخدام هذه الويكي.",
+ "flow-terms-of-use-lock-topic": "بالضغط على \"{{int:flow-topic-action-lock-topic}}\"، فإنك توافق على شروط استخدام هذه الويكي.",
+ "flow-terms-of-use-unlock-topic": "بالضغط على \"{{int:flow-topic-action-unlock-topic}}\"، فإنك توافق على شروط استخدام هذه الويكي.",
+ "flow-whatlinkshere-post": "من [$1 منشور]",
+ "flow-whatlinkshere-header": "من [$1 الوصف]",
+ "flow-whatlinkshere-post-summary": "من [ملخص $1]",
+ "structureddiscussions": "نقاشات هيكلية",
+ "flow-special-desc": "هذه الصفحة تحول إلى workflow للنقاشات الهيكليةأو post للنقاشات الهيكلية مع إعطاء UUID.",
+ "flow-special-type": "نوع",
+ "flow-special-type-post": "نشر",
+ "flow-special-type-workflow": "سير عمل التدفق",
+ "flow-special-uuid": "المعرف الفريد العالمي",
+ "flow-special-invalid-uuid": "تعذر العثور على محتوى يطابق النوع والمعرف الفريد العالمي.",
+ "flow-special-enableflow-legend": "تمكين ميزة النقاشات الهيكلية على صفحة جديدة",
+ "flow-special-enableflow-page": "الصفحة لتفعيل النقاشات الهيكلية عليها",
+ "flow-special-enableflow-header": "الوصف الأولي لصفحة النقاشات الهيكلية (نص ويكي).",
+ "flow-special-enableflow-board-already-exists": "هناك بالفعل لوحة نقاشات هيكلية في [[$1]].",
+ "flow-special-enableflow-invalid-title": "عنوان خاطئ للصفحة.",
+ "flow-special-enableflow-board-creation-not-allowed": "أنت من غير المسموح لك إنشاء لوحة نقاشات هيكلية في [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "هناك صفحة LiquidThreads في [[:$1]].",
+ "flow-special-enableflow-confirmation": "أنت أنشأت لوحة نقاشات هيكلية في [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Archive %d\n%s/Archive%d\n%s/archive %d\n%s/archive%d\n%s/أرشيف %d\n%s/أرشيف%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/أرشيف النقاشات الهيكلية %d\n%s/أرشيف النقاشات الهيكلية %d",
+ "flow-spam-confirmedit-form": "يرجى إثبات أنك لست روبوت من خلال حل كلمة التحقق بالأسفل:\n$1",
+ "flow-spam-confirmedit-using-failure": "هناك خلل تقني في كلمة التحقق. إن كنت غير قادر على حفظ تعديلاتك، قم بنسخها ثم إعادة تحميل الصفحة والمحاولة مرة أخرى لحفظها.",
+ "flow-embedding-unsupported": "لا يمكن تضمين النقاشات في الوقت الحالي.",
+ "mw-ui-unsubmitted-confirm": "هناك تغييرات غير محفوظة في هذه الصفحة. هل أنت متأكد من أنك تريد المغادرة وفقدان التغييرات؟",
+ "flow-post-undo-hide": "تراجع عن الإخفاء",
+ "flow-post-undo-delete": "تراجع عن الحذف",
+ "flow-post-undo-suppress": "تراجع عن الحذف/الطمس",
+ "flow-topic-undo-hide": "تراجع عن الإخفاء",
+ "flow-topic-undo-delete": "تراجع عن الحذف",
+ "flow-topic-undo-suppress": "تراجع عن الحذف/الطمس",
+ "flow-importer-lqt-moved-thread-template": "الخيوط السائلة نقل بذرة الخيط المحول إلى النقاشات الهيكلية",
+ "flow-importer-lqt-moved-thread-template-content": "هذا المنشور قد تم نقله بواسطة {{{author}}} في {{{date}}}، ويمكنك إيجاده هنا [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "صفحة LQT تم تحويلها إلى النقاشات الهيكلية",
+ "flow-importer-lqt-converted-template-content": "صفحة التاريخ السابق قد تم أرشفتها لأغراض النسخ الاحتياطي في <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> في {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-lqt-converted-archive-template": "أرشفة لصفحة LQT محولة",
+ "flow-importer-lqt-converted-archive-template-content": "هذه الصفحة هي عبارة عن أرشيف لصفحة LiquidThreads . لذلك <strong>لا تقم بتعديل محتوى هذه الصفحة</strong>، ويرجى إضافة أي تعليق جديد في [[{{{from}}}|صفحة النقاش الحالية]].",
+ "flow-importer-wt-converted-template": "صفحة نقاش نص الويكي تم تحويلها إلى النقاشات الهيكلية",
+ "flow-importer-wt-converted-template-content": "النقاش السابق تمت أرشفته في <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> بتاريخ {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "أرشيف صفحة نقاش نص ويكي المحول",
+ "flow-importer-wt-converted-archive-template-content": "هذه الصفحة هي عبارة عن أرشيف. لذلك <strong>لا تقم بتعديل محتوى هذه الصفحة</strong>، ويرجى إضافة أي تعليق جديد في [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|صفحة النقاش الحالية]].",
+ "flow-importer-lqt-suppressed-user-template": "نقاش LQT مستورد مع مستخدم مخفي",
+ "flow-importer-lqt-suppressed-user-template-content": "تم استيراد هذه المراجعة من LiquidThreads بواسطة مستخدم مقيد، لذلك تم إعادة إسنادها للمستخدم الحالي.",
+ "flow-importer-lqt-different-author-signature-template": "نقاش LQT مستورد مع توقيع مستخدم مختلف",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>هذا المنشور قد تم نشره بواسطة\n [[User:{{{authorUser}}}|{{{authorUser}}}]]، ولكنه وقع كـ [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "عدلت",
+ "flow-edited-by": "حررت بواسطة $1",
+ "flow-edited-by-header": "وصف المجلس تم تعديله بواسطة $1",
+ "flow-edited-by-topic-title": "عنوان الموضوع تم تعديله بواسطة $1",
+ "flow-lqt-redirect-reason": "تحويل نقاش LiquidThreads القديم إلى نقاش النقاشات الهيكلية المحول",
+ "flow-talk-conversion-move-reason": "تحويل نقاش نص الويكي إلى خاصية النقاشات الهيكلية من $1",
+ "flow-talk-conversion-archive-edit-reason": "تحويل نقاش بنص الويكي إلى النقاشات الهيكلية",
"flow-previous-diff": "→ التعديل الأقدم",
"flow-next-diff": "التعديل الأحدث ←",
+ "flow-undo": "تراجع",
"flow-undo-latest-revision": "المراجعة الحالية",
"flow-undo-your-text": "نصك",
"flow-undo-edit-header": "تعديل الوصف",
"flow-undo-edit-topic-summary": "تعديل ملخص الموضوع",
"flow-undo-edit-post": "تعديل منشور",
- "group-flow-bot": "بوتات فلو",
- "grouppage-flow-bot": "Project:بوتات فلو",
+ "flow-undo-edit-content": "التعديل يمكن الرجوع عنه. من فضلك تحقق من المقارنة بالأسل للتأكد من أن هذا هو ما تود عمله، ثم احفظ التغييرات بالأسفل للانتهاء من الرجوع عن التعديل.",
+ "flow-undo-edit-failure": "لا يمكن استرجاع التعديل بسبب تعديلات متعارضة تمت على الصفحة.",
+ "group-flow-bot": "بوتات النقاشات الهيكلية",
+ "group-flow-bot-member": "بوت النقاشات الهيكلية",
+ "grouppage-flow-bot": "Project:بوتات النقاشات الهيكلية",
+ "flow-ve-mention-context-item-label": "إشارة",
+ "flow-ve-mention-inspector-title": "إشارة",
"flow-ve-mention-inspector-remove-label": "أزل",
"flow-ve-mention-placeholder": "اسم المستخدم",
- "flow-wikitext-editor-help-preview-the-result": "اعرض النتيجة",
+ "flow-ve-mention-tool-title": "إشارة لمستخدم",
+ "flow-ve-mention-template-title": "FlowMention",
+ "flow-ve-mention-inspector-invalid-user": "اسم المستخدم \"$1\" غير مسجل.",
+ "flow-wikitext-editor-help": "نص الويكي $1.",
+ "flow-wikitext-editor-help-and-preview": "نص الويكي $1 ويمكنك $2 في أي وقت.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|يستخدم تنسيق]]",
+ "flow-wikitext-editor-help-preview-the-result": "عرض النتيجة",
"flow-wikitext-switch-editor-tooltip": "الانتقال إلى المحرر المرئي",
"flow-ve-switch-editor-tool-title": "الانتقال إلى محرر نص الويكي",
- "flow-notification-enabled-on-talkpage-email-subject-message": "نظام مناقشة جديد على 2$",
+ "flow-mark-revision-patrolled-link-text": "علم هذه الصفحة كمراجعة",
+ "flow-mark-revision-patrolled-link-title": "علم هذه الصفحة كمراجعة",
+ "flow-mark-diff-patrolled-link-text": "علم كمراجعة",
+ "flow-mark-diff-patrolled-link-title": "علم كمراجعة",
+ "flow-talk-page-beta-feature-message": "نقاشات هيكلية على نقاش المستخدم",
+ "flow-talk-page-beta-feature-description": "يفعل نظام نقاش هيكلي جديد على صفحة {{GENDER:|نقاشك}}. النقاشات الهيكلية تبسط نقاشات صفحات النقاش مع أماكن محددة للكتابة والرد، وتسمح بالإخطارات على مستوى الحوار. هذه الخاصية ليست مفعلة تلقائيا؛ المستخدمون سيتعين عليهم تفعيلها بشكل منفصل.<br /><br />نقاشات نص الويكي الموجودة سيتم نقلها لأرشيف. تعطيل هذه الخاصية سينقل لوحة النقاشات الهيكلية إلى صفحة فرعية وسيسترجع أرشفة صفحة النقاش السابقة.\n[[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|معرفة المزيد حول التنشيط]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|شاهد}} صفحة نقاش المستخدم",
+ "flow-notification-enabled-on-talkpage-title": "تم تفعيل نظام النقاش الجديد في صفحة {{GENDER:$1|نقاشك}}، <small>وهو متوافر في [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "نظام مناقشة جديد على $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "النقاشات الهيكلية، نظام النقاش الجديد في صفحة نقاش المستخدم الخاص {{GENDER:$1|بك}} تم تفعيلها في في {{SITENAME}}، ويمكنك الحصول على أي معلومات إضافية، أو تزويدنا بأي تغذية راجعة، أو تعطيل النظام الجديد في أي وقت، وكل هذا من خلال قسم مميزات الإصدار التجريبي في {{GENDER:$1|تفضيلاتك}}.",
"flow-beta-feature-add-archive-template-edit-summary": "إضافة قالب أرشيف",
"flow-beta-feature-remove-archive-template-edit-summary": "إزالة قالب الأرشيف",
- "flow-dialog-cancelconfirm-title": "هل أنت متأكد؟",
- "flow-dialog-cancelconfirm-message": "هل أنت متأكد أنك تريد إلغاء بدون حفظ أولا؟",
- "flow-dialog-cancelconfirm-keep": "مواصلة المراجعة",
+ "flow-dialog-cancelconfirm-title": "هل {{GENDER:|أنت}} متأكد؟",
+ "flow-dialog-cancelconfirm-message": "هل {{GENDER:|أنت}} متأكد أنك تريد الإلغاء بدون الحفظ أولا؟",
+ "flow-dialog-cancelconfirm-keep": "مواصلة التعديل",
"flow-dialog-cancelconfirm-discard": "تجاهل التغييرات",
- "flow-guidedtour-optin-find-old-conversations-description": "تم نقل المحادثات السابقة إلى صفحة الأرشيف."
+ "flow-optin-archive-wikitext": "نقل صفحة نص ويكي لإفساح المجال لإنشاء صفحة النقاش.",
+ "flow-optin-archive-flow-board": "نقل صفحة النقاش لإفساح المجال لإنشاء صفحة نص ويكي.",
+ "flow-optin-restore-wikitext": "استعادة صفحة نص ويكي المؤرشفة.",
+ "flow-optin-restore-flow-board": "استعادة أرشيف نقاش الصفحة.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|أهلاً}} إلى {{GENDER:$1|صفحة نقاشك}} الجديدة",
+ "flow-guidedtour-optin-welcome-description": "صفحة {{GENDER:$1|نقاشك}} هي المكان الذي يسمح للآخرين بمراسلتك والتواصل {{GENDER:$1|معك}}. مع النقاشات الهيكلية، سيصبح من السهل إنشاء مواضيع جديدة ومتابعة المحادثات.",
+ "flow-guidedtour-optin-find-old-conversations": "ابحث عن {{GENDER:$1|محادثاتك}} القديمة.",
+ "flow-guidedtour-optin-find-old-conversations-description": "تم نقل المحادثات السابقة إلى صفحة الأرشيف.",
+ "flow-guidedtour-optin-feedback": "أعطنا {{GENDER:$1|ملاحظاتك}} !",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|يمكنك}} الحصول على أي معلومات إضافية، أو تزويدنا بأي تغذية راجعة، أو تعطيل النظام الجديد في أي وقت، وكل هذا من خلال قسم مميزات الإصدار التجريبي.",
+ "flow-action-not-page": "كائن الصفحة هو نسخة من الكلاس الخاطئة",
+ "flow-action-wrong-title-content-model": "الصفحة يتم التعامل معها بواسطة النقاشات الهيكلية، لكن الكلاس Title تشير إلى أن موديل المحتوى هو '$1'. هذا سوء ضبط أو حالة غير متناسقة. على سبيل المثال، هذا ربما يكون صفحة غير تابعة للنقاشات الهيكلية في نطاق للنقاشات الهيكلية، مع <code>rev_content_model</code> غير مملوء."
}
diff --git a/Flow/i18n/ast.json b/Flow/i18n/ast.json
index fb3371c0..a3b3f98a 100644
--- a/Flow/i18n/ast.json
+++ b/Flow/i18n/ast.json
@@ -1,20 +1,56 @@
{
"@metadata": {
"authors": [
- "Xuacu"
+ "Xuacu",
+ "Nnemo",
+ "Quiddity",
+ "Macofe",
+ "Matiia"
]
},
- "flow-desc": "Sistema de xestión del fluxu de trabayu",
- "log-name-flow": "Rexistru d'actividá de Flow",
+ "enablestructureddiscussions": "Activar Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Dexar}} de siguir l'actividá nueva en «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Yá nun {{GENDER:$3|tas}} siguiendo la páxina «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Esto nun afeutará a temes individuales que {{GENDER:$3|teas}} siguiendo. Puedes siguir [$2 esta páxina] en cualquier momentu.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Dexar}} de siguir esti tema",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Yá nun {{GENDER:$3|tas}} siguiendo «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Puedes}} siguir [$2 esti tema] en cualquier momentu.",
+ "flow-desc": "Sistema d'alderique",
+ "flow-talk-taken-over-comment": "/* Esta páxina convertióse nun tableru d'Alderiques estructuraos */",
+ "log-name-flow": "Rexistru d'actividá d'Alderiques estructuraos",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|desanició}} un [$4 mensaxe] sobro «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|desanició}} un mensaxe d'un asuntu en [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restauró}} un [$4 mensaxe] sobro «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|restauró}} un mensaxe d'un asuntu en [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|suprimió}} un [$4 mensaxe] sobro «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|suprimió}} un mensaxe d'un asuntu en [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|desanició}} un [$4 mensaxe] sobro «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|desanició}} un mensaxe d'un asuntu en [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|desanició}} l'asuntu «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|desanició}} un asuntu en [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restauró}} l'asuntu «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|restauró}} un asuntu en [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suprimió}} l'asuntu «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|suprimió}} un asuntu en [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|desanició}} l'asuntu «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|desanició}} un asuntu en [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marcó}} l'asuntu \"[[$3|$5]]\" como resueltu en [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|marcó}} un asuntu como resueltu en [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reabrió}} l'asuntu \"[[$3|$5]]\" en [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|reabrió}} un asuntu en [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] en [[$3]] importóse de LiquidThreads a Alderiques estructuraos",
+ "abusefilter-edit-builder-vars-board-articleid": "ID de páxina del tableru d'Alderiques estructuraos",
+ "abusefilter-edit-builder-vars-board-namespace": "Espaciu de nomes del tableru d'Alderiques estructuraos",
+ "abusefilter-edit-builder-vars-board-text": "Títulu del tableru d'Alderiques estructuraos",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Títulu completu del tableru d'Alderiques estructuraos",
"flow-user-moderated": "Usuariu moderáu",
+ "flow-board-header-browse-topics-link": "Navegar polos temes",
+ "flow-board-header": "Tocante a esti tableru",
+ "flow-board-description-can-not-edit": "Nun pué editase",
+ "flow-board-collapse-description": "Anubrir la descripción",
+ "flow-board-expand-description": "Amosar la descripción",
+ "flow-topic-collapse-siderail": "Lleer n'anchu completu",
+ "flow-topic-expand-siderail": "Lleer n'anchu fixu",
"flow-edit-header-link": "Editar la descripción",
"flow-post-moderated-toggle-hide-show": "Amosar el comentariu {{GENDER:$1|tapecíu}} por $2",
"flow-post-moderated-toggle-delete-show": "Amosar el comentariu {{GENDER:$1|desaniciáu}} por $2",
@@ -22,6 +58,7 @@
"flow-post-moderated-toggle-hide-hide": "Tapecer el comentariu {{GENDER:$1|tapecíu}} por $2",
"flow-post-moderated-toggle-delete-hide": "Tapecer el comentariu {{GENDER:$1|desaniciáu}} por $2",
"flow-post-moderated-toggle-suppress-hide": "Tapecer el comentariu {{GENDER:$1|suprimíu}} por $2",
+ "flow-topic-moderated-reason-prefix": "Motivu:",
"flow-hide-post-content": "Esti comentariu {{GENDER:$1|tapeciólu}} $1 ([$2 historial])",
"flow-hide-title-content": "Esti asuntu {{GENDER:$1|tapecióse}} por $1",
"flow-hide-header-content": "{{GENDER:$1|Tapecíu}} por $2",
@@ -35,17 +72,25 @@
"flow-post-actions": "Aiciones",
"flow-topic-actions": "Aiciones",
"flow-cancel": "Encaboxar",
+ "flow-skip-summary": "Saltar",
+ "flow-edit-summary-placeholder": "Describa brevemente'l resultáu d'esti alderique",
+ "flow-summary-authored": "Resume de $1",
+ "flow-summary-edited": "Última {{GENDER:$1|edición}} del resume por $1",
"flow-show-change": "Amosar cambeos",
"flow-last-modified-by": "Últimu {{GENDER:$1|cambiu}} por $1",
- "flow-stub-post-content": "''Por un fallu téunicu, esti mensaxe nun pudo recuperase.''",
+ "flow-stub-post-content": "<em>Por un fallu téunicu, esti conteníu nun pudo recuperase.</em>",
"flow-newtopic-title-placeholder": "Nuevu asuntu",
"flow-newtopic-content-placeholder": "Unviar un mensaxe nuevu a «$1»",
"flow-newtopic-header": "Amestar un nuevu asuntu",
"flow-newtopic-save": "Amestar un asuntu",
+ "flow-newtopic-save-anonymously": "Añadir un tema anónimamente",
"flow-newtopic-start-placeholder": "Principiar un nuevu asuntu",
"flow-newtopic-first-heading": "Aniciar un tema nuevu en $1",
+ "flow-summarize-topic-placeholder": "Por favor, resume esti alderique",
"flow-reply-topic-placeholder": "{{GENDER:$1|Comentar}} sobro «$2»",
+ "flow-reply-topic-title-placeholder": "Responder a «$1»",
"flow-reply-link": "{{GENDER:$1|Responder}}",
+ "flow-reply-link-anonymously": "Responder anónimamente",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Agradecer}}}}",
"flow-thank-link-title": "{{GENDER:$1|Dar les gracies}} públicamente {{GENDER:$2|al autor|a la autora}}",
"flow-history-action-suppress-post": "suprimir",
@@ -65,6 +110,7 @@
"flow-post-action-hide-post": "Tapecer",
"flow-post-action-edit-post": "Editar",
"flow-post-action-edit-post-submit": "Guardar los cambios",
+ "flow-post-action-edit-post-submit-anonymously": "Guardar los cambeos anónimamente",
"flow-post-action-unsuppress-post": "De-suprimir",
"flow-post-action-undelete-post": "Restaurar",
"flow-post-action-unhide-post": "Destapecer",
@@ -80,30 +126,54 @@
"flow-topic-action-unlock-topic": "Reabrir l'asuntu",
"flow-topic-action-summarize-topic": "Resumir",
"flow-topic-action-resummarize-topic": "Editar el resume del tema",
+ "flow-topic-action-update-topic-summary": "Actualizar el resume",
"flow-topic-action-suppress-topic": "Suprimir esti asuntu",
"flow-topic-action-unhide-topic": "Destapecer l'asuntu",
"flow-topic-action-undelete-topic": "Restaurar l'asuntu",
"flow-topic-action-unsuppress-topic": "De-suprimir l'asuntu",
"flow-topic-action-restore-topic": "Restaurar esti asuntu",
"flow-topic-action-undo-moderation": "Desfacer",
+ "flow-topic-notification-subscribe-title": "Esti tema amestóse a {{GENDER:$1|la to}} llista de siguimientu.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Vas}} recibir notificaciones de toles actividaes sobro esti tema.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Tas}} soscritu a esti tableru de discutiniu.",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Recibirás}} un avisu cuando se cree un tema nuevu nesti tableru.",
+ "flow-topic-action-watchlist-add": "Suscribise a esti tema",
+ "flow-topic-action-watchlist-remove": "Date de baxa",
+ "flow-error-allowcreation-no-usedb": "Activar Alderiques estructuraos nuna determinada páxina rique que <var>$wgContentHandlerUseDB</var> sía <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "La páxina yá esiste nel destín, de mou que nun pué movese allí un tableru d'Alderiques estructuraos.",
+ "flow-error-allowcreation-flow-create-board": "L'usuariu nun tien el permisu de «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Anguaño nun puedes participar. Tenta aniciar sesión.",
+ "flow-error-can-not-edit-logged-in": "Anguaño nun puedes participar, porque nun tienes los permisos riquíos.",
"flow-error-http": "Hebo un error al comunicase col sirvidor.",
- "flow-error-other": "Hebo un fallu inesperáu.",
- "flow-error-external": "Hebo un error.<br />El mensaxe d'error recibíu ye: $1",
- "flow-error-external-multi": "Alcontráronse errores.<br />$1",
+ "flow-error-external": "Hebo un error. El mensaxe d'error recibíu foi: $1",
+ "flow-error-topic-is-locked": "Esti tema ta resueltu, asina que nun pué haber más actividá.",
+ "flow-error-lock-moderated-post": "Nun puedes marcar una publicación moderada como resuelta.",
"flow-error-missing-content": "El mensaxe nun tien conteníu. El conteníu ye obligatoriu pa guardar un mensaxe.",
"flow-error-missing-summary": "Tienes d'unviar un resume.",
"flow-error-missing-title": "L'asuntu nun tien títulu. El títulu ye obligatoriu pa guardar un asuntu.",
- "flow-error-parsoid-failure": "Nun ye posible analizar el conteníu por un fallu de Parsoid.",
+ "flow-error-parsoid-failure": "Nun ye posible tresferir el conteníu:Error al comunicase col sirvidor pa la conversión ente testu wiki y HTML. Comprueba la conexón a internet o téntalo sero si'l problema sigue. Si sigues teniendo esti error, rexistra un bug",
+ "flow-error-protected-autoconfirmed-logged-in": "Esti tableru ta protexíu. Solo pueden participar los usuarios autoconfirmaos. Motivu: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Esti tableru ta protexíu. Solo pueden participar los usuarios con sesión aniciada que tean autoconfirmaos. Motivu: $1",
+ "flow-error-protected-sysop-logged-in": "Esti tableru ta protexíu. Solo pueden participar los usuarios con permisu d'alministrador. Motivu: $1",
+ "flow-error-protected-sysop-logged-out": "Esti tableru ta protexíu. Solo pueden participar los usuarios con sesión aniciada con permisu d'alministrador. Motivu: $1",
+ "flow-error-protected-unknown-reason": "Desconocíu",
"flow-error-missing-replyto": "Nun se dio nengún parámetru «responder a». Esti parámetru ye obligatoriu pa l'aición \"responder\".",
- "flow-error-invalid-replyto": "El parámetru «responder a» yera inválidu. Nun pudo alcontrase'l mensaxe especificáu.",
- "flow-error-delete-failure": "Falló'l desaniciu d'esti elementu.",
- "flow-error-hide-failure": "Falló'l tapecer esti elementu.",
"flow-error-missing-postId": "Nun se dio nengún parámetru «postId». Esti parámetru ye obligatoriu p'actuar sobro un mensaxe.",
"flow-error-invalid-postId": "El parámetru «postId» yera inválidu. Nun pudo alcontrase'l mensaxe especificáu ($1).",
- "flow-error-restore-failure": "Falló la restauración d'esti elementu.",
- "flow-error-invalid-moderation-state": "Unvióse un valor inválidu pa un parámetru ('moderationState') a la API de Flow.",
+ "flow-error-invalid-moderation-state": "Unvióse un valor inválidu pa un parámetru ('moderationState') a la API d'Alderiques estructuraos.",
"flow-error-invalid-moderation-reason": "Por favor, ufra un motivu pa la moderación.",
"flow-error-not-allowed": "Nun tien permisu bastante pa executar esta aición.",
+ "flow-error-not-allowed-hide": "Esti tema anubrióse.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Nun puedes responder porque esti tema ta anubríu.",
+ "flow-error-not-allowed-delete": "Esti tema desanicióse.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Nun puedes responder porque esti tema ta desaniciáu.",
+ "flow-error-not-allowed-suppress": "Esti tema desanicióse.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Nun puedes responder porque esti tema ta desaniciáu.",
+ "flow-error-not-allowed-hide-extract": "Esti tema anubrióse. De siguío figura'l rexistru d'anubrimientu del tema pa referencia.",
+ "flow-error-not-allowed-delete-extract": "Esti tema desanicióse. De siguío figura'l rexistru de desaniciu del tema pa referencia.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Nun puedes responder porque esti tema desanicióse. De siguío figura'l rexistru de desaniciu del tema pa referencia.",
+ "flow-error-not-allowed-suppress-extract": "Esti tema desanicióse. De siguío figura'l rexistru de desaniciu del tema pa referencia.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Nun puedes responder porque esti tema suprimióse. De siguío figura'l rexistru de supresión del tema pa referencia.",
"flow-error-title-too-long": "Los títulos del asuntu tan llendaos a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-no-existing-workflow": "Esti fluxu de trabayu inda nun esiste.",
"flow-error-not-a-post": "El títulu del asuntu nun pue guardase como mensaxe.",
@@ -111,27 +181,47 @@
"flow-error-missing-prev-revision-identifier": "Falta l'identificador de revisión anterior.",
"flow-error-prev-revision-mismatch": "Otru usuariu acaba d'editar esti mensaxe hai dellos segundos. ¿Tas {{GENDER:$3|seguru|segura}} de que quies sobreescribir el cambiu reciente?",
"flow-error-prev-revision-does-not-exist": "Nun pudo alcontrase la revisión anterior.",
+ "flow-error-core-topic-deletion": "Pa borrar un asuntu, usa'l menú ... del tableru d'Alderiques estructuraos o [$1 la páxina del asuntu]. Nun visites direutamente action=delete del asuntu.",
"flow-error-default": "Hebo un error.",
- "flow-error-invalid-input": "Dióse un valor inválidu pa cargar el conteníu de fluxu.",
+ "flow-error-invalid-input": "Dióse un valor inválidu pa cargar el conteníu d'Alderiques estructuraos.",
"flow-error-invalid-title": "Dióse un títulu de páxina inválidu.",
+ "flow-error-invalid-parameter": "Parámetru ausente o incorreutu na llamada a un métodu",
"flow-error-fail-load-history": "Falló la carga del conteníu del historial.",
- "flow-error-missing-revision": "Nun pudo alcontrase una revisión pa cargar conteníu de fluxu.",
- "flow-error-fail-commit": "Nun pudo guardase'l conteníu del fluxu.",
- "flow-error-insufficient-permission": "Nun tien permisu bastante pa tener accesu al conteníu.",
- "flow-error-revision-comparison": "La operación diff sólo pue facese ente dos revisiones del mesmu mensaxe.",
- "flow-error-missing-topic-title": "Nun pue alcontrase'l títulu del asuntu del fluxu de trabayu actual.",
+ "flow-error-missing-revision": "Nun pudo alcontrase una revisión pa cargar conteníu d'Alderiques estructuraos.",
+ "flow-error-fail-commit": "Nun pudo guardase'l conteníu d'Alderiques estructuraos.",
+ "flow-error-insufficient-permission": "Nun tienes permisu bastante pa tener accesu al conteníu.",
+ "flow-error-revision-comparison": "La operación diff sólo pué facese ente dos revisiones del mesmu mensaxe.",
+ "flow-error-missing-topic-title": "Nun pudo alcontrase'l títulu del asuntu del fluxu de trabayu actual.",
+ "flow-error-missing-metadata": "Nun pudieron alcontrase los metadatos necesarios pa esta revisión.",
+ "flow-error-different-page": "El procesu d'Alderiques estructuraos nun ta asociáu con esta páxina.",
"flow-error-fail-load-data": "Nun pudieron cargase los datos solicitaos.",
"flow-error-invalid-workflow": "Nun pudo alcontrase'l fluxu de trabayu solicitáu.",
"flow-error-process-data": "Hebo un error al procesar los datos de la solicitú.",
"flow-error-process-wikitext": "Hebo un error al procesar la conversión HTML/testu wiki.",
"flow-error-no-index": "Nun s'alcontró un índiz pa facer la gueta de datos.",
+ "flow-error-no-render": "Nun se reconoció l'aición especificada.",
+ "flow-error-no-commit": "Non pudo guardase l'aición especificada.",
+ "flow-error-content-too-long": "El conteníu ye grande enforma. El conteníu dempués de la espansión ta llindáu a $1 {{PLURAL:$1|byte|bytes}}.",
+ "flow-error-move-topic": "Inda nun hai encontu pa treslladar una páxina d'asuntu.",
+ "flow-error-invalid-topic-uuid-title": "Títulu incorreutu",
+ "flow-error-invalid-topic-uuid": "El títulu de páxina solicitáu ye inválidu. Alderiques estructuraos crea automáticamente les páxines del espaciu de nomes Asuntu.",
+ "flow-error-unknown-workflow-id-title": "Asuntu desconocíu",
+ "flow-error-unknown-workflow-id": "L'asuntu solicitáu nun esiste.",
+ "flow-error-search": "Nun pudimos completar la gueta por un problema temporal. Vuelve a intentalo más sero.",
+ "flow-error-invalid-undelete": "La páxina nun pudo restaurase porque anguaño tien puestu un tableru d'alderique.",
+ "flow-edit-header-placeholder": "Describir esti panel de discutiniu",
"flow-edit-header-submit": "Guardar la descripción",
+ "flow-edit-header-submit-anonymously": "Guardar la descripción anónimamente",
"flow-edit-title-submit": "Camudar el títulu",
+ "flow-edit-title-submit-anonymously": "Camudar el títulu anónimamente",
"flow-edit-post-submit": "Unviar los cambios",
+ "flow-edit-post-submit-anonymously": "Unviar los cambios anónimamente",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|editó}} un [$3 comentariu] sobro «$4».",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Editó}} una publicación",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|comentó}}] sobro «$4» (<em>$5</em>).",
"flow-rev-message-reply-bundle": "{{PLURAL:$1|Amestóse|Amestáronse}} <strong>$1 {{PLURAL:$1|comentariu|comentarios}}</strong>.",
"flow-rev-message-new-post": "$1 {{GENDER:$2|creó}} l'asuntu «[$3 $4]».",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Creó}} un asuntu nuevu",
"flow-rev-message-edit-title": "$1 {{GENDER:$2|camudó}}'l títulu del asuntu de «$5» a «[$3 $4]».",
"flow-rev-message-create-header": "$1 {{GENDER:$2|creó}} la descripción",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|editó}} la descripción.",
@@ -144,7 +234,11 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|tapeció}} l'[$4 asuntu] «$6» (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|desanició}} l'[$4 asuntu] «$6» (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suprimió}} l'[$4 asuntu] «$6» (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcó}} l'[$4 asuntu] \"$6\" como resueltu (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "marcáu como resueltu",
+ "flow-rev-message-restore-topic-reason": "reabiertu",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restauró}} l'[$4 asuntu] «$6» (<em>$5</em>).",
+ "flow-rc-topic-of-board": "$1 en $2",
"flow-board-history": "Historial de «$1»",
"flow-board-history-empty": "Esti tableru actualmente nun tien historial.",
"flow-topic-history": "Historial del asuntu «$1»",
@@ -155,34 +249,81 @@
"flow-history-pages-topic": "Apaez nel [$1 tableru «$2»]",
"flow-history-pages-post": "Apaez en [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 comentariu|$1 comentarios|0=¡Comenta tú {{GENDER:$2|el primeru|la primera}}!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Ver comentariu|Ver comentarios}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Anubrir comentariu|Anubrir comentarios}}",
"flow-comment-restored": "Comentariu restauráu",
"flow-comment-deleted": "Comentariu desaniciáu",
"flow-comment-hidden": "Comentariu tapecíu",
"flow-comment-moderated": "Comentariu moderáu",
"flow-last-modified": "Últimu cambiu hai como $1",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|contestó}} en '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 y {{PLURAL:$6|otru|otros $5}} más {{GENDER:$1|contestaron}} en '''$3'''.",
+ "flow-workflow": "fluxu de trabayu",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|contestó}} en <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 y {{PLURAL:$5|otru|otros $5|100=99+ otros}} más {{GENDER:$1|contestaron}} en <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|editó}}'l to <span class=\"plainlinks\">[$5 comentariu]</span> en [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 y {{PLURAL:$6|otru|otros $5}} {{GENDER:$1|editaron}} un <span class=\"plainlinks\">[$4 comentariu]</span> sobro \"$2\" en \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|creó}} un asuntu nuevu en '''$3'''.",
+ "flow-notification-edit-bundle": "$1 y {{PLURAL:$5|otru|otros $5|100=99+ otros}} {{GENDER:$1|editaron}} un <span class=\"plainlinks\">[$4 comentariu]</span> sobro \"$2\" en \"$3\".",
+ "notification-header-flow-new-topic-v2": "Asuntu nuevu creáu en <strong>$3</strong>: <bdi>«<strong>$4</strong>»</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Un tema nuevu|$1 temes nuevos|100=99+ temes nuevos}} en <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Creóse un asuntu nuevu na to páxina d'alderique: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "Hai {{PLURAL:$1|un asuntu nuevu|$1 asuntos nuevos|100=99+ asuntos nuevos}} na to páxina d'alderique.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|respondió}} en «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-v2": "Hai {{PLURAL:$1|una respuesta nueva|$1 respuestes nueves|100=99+ respuestes nueves}} en «<strong>$3</strong>».",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|publicó}} una respuesta na <strong>to páxina d'alderique</strong> na sección «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Una respuesta nueva|$1 respuestes nueves|100=99+ respuestes nueves}} na <strong>to páxina d'alderique</strong> na sección «<strong>$3</strong>».",
+ "notification-header-flow-post-edited-v2": "Editóse la {{GENDER:$2|to}} publicación en «<strong>$1</strong>».",
+ "notification-bundle-header-flow-post-edited-v2": "La {{GENDER:$2|to}} publicación en «<strong>$1</strong>» editóse delles veces.",
+ "notification-header-flow-post-edited-user-talk": "Editóse un mensaxe en «<strong>$1</strong>» na <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Editóse delles veces un mensaxe en «<strong>$1</strong>» na <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Cambióse'l nome del asuntu «<strong>$1</strong>» a «<strong>$2</strong>».",
+ "notification-header-flow-topic-renamed-user-talk": "Camudóse'l nome del asuntu «<strong>$1</strong>» a «<strong>$2</strong>» na <strong>{{GENDER:$3|to}} páxina d'alderique</strong>.",
+ "notification-header-flow-summary-edited": "Actualizóse'l resume de «<strong>$1</strong>».",
+ "notification-header-flow-summary-edited-first": "Resumióse l'asuntu «<strong>$1</strong>».",
+ "notification-bundle-header-flow-summary-edited": "Actualizóse munches vegaes el resume de «<strong>$1</strong>».",
+ "notification-header-flow-summary-edited-user-talk": "Actualizóse'l resume de «<strong>$1</strong>» na <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Resumióse l'asuntu «<strong>$1</strong>» na <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Actualizóse delles vegaes el resume de «<strong>$1</strong>» na <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|actualizó}}'l resume de $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|actualizó}}'l resume de $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 y {{PLURAL:$3|otra persona|otres $3 persones|100=otros 99+}} {{GENDER:$1|actualizaron}} el resume en $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|te}} {{GENDER:$2|mentó}} en <strong>$5</strong>.",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$4|te}} {{GENDER:$2|mentó}} na descripción de <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:{{GENDER:$4|}}|te}} {{GENDER:$2|mentó}} en «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Nuevu sistema d'alderique activáu pa la <strong>{{GENDER:$2|to}} páxina d'alderique d'usuariu</strong>.",
+ "notification-header-flow-description-edited": "Editóse la descripción de <strong>$1</strong>.",
+ "notification-header-flow-description-edited-user-talk": "Editóse la descripción de la <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-bundle-header-flow-description-edited": "La descripción de <strong>$1</strong> editóse delles vegaes.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Editóse delles veces la descripción en la <strong>{{GENDER:$2|to}} páxina d'alderique</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Ver}} la páxina",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|editó}} la descripción en $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|editó}} la descripción en $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 y {{PLURAL:$3|otra persona|otres $3 persones|100=otros 99+}} {{GENDER:$1|editaron}} la descripción en $2",
+ "notification-header-flow-topic-resolved": "Resolvióse l'asuntu «<strong>$1</strong>».",
+ "notification-header-flow-topic-reopened": "Reabrióse l'asuntu «<strong>$1</strong>».",
+ "notification-header-flow-topic-resolved-user-talk": "Resolvióse l'asuntu «<strong>$1</strong>» na <strong>to páxina d'alderique</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Reabrióse l'asuntu «<strong>$1</strong>» na <strong>to páxina d'alderique</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Resolvióse l'asuntu «<strong>$2</strong>».",
+ "notification-email-batch-body-flow-topic-resolved": "Resolvióse l'asuntu «<strong>$2</strong>».",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|creó}} un asuntu nuevu en <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un asuntu nuevu|$1 asuntos nuevos|100=99+ asuntos nuevos}} en <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|cambió}}'l títulu de <span class=\"plainlinks\">[$2 $3]</span> a «$4» en [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$5|te}}{{GENDER:$1|mencionó}} nel {{GENDER:$1|so}} <span class=\"plainlinks\">[$2 mensaxe]</span> sobro «$3» en «$4».",
"flow-notification-link-text-view-post": "Ver el mensaxe",
"flow-notification-link-text-view-topic": "Ver el filu",
+ "flow-notification-link-text-view-topics": "Ver asuntos",
"flow-notification-reply-email-subject": "$2 en $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondió}} a «$2» en $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 y {{PLURAL:$5|otra persona|otres $4 persones}} {{GENDER:$1|respondieron}} a «$2» en $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 y {{PLURAL:$4|otra persona|otres $4 persones|100=99+ otros}} {{GENDER:$1|respondieron}} a «$2» en $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$3|te}} {{GENDER:$1|mencionó}} en $2.",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|te}} {{GENDER:$1|mencionó}} nel {{GENDER:$1|so}} mensaxe sobro «$2» en $3.",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|editó}} un mensaxe",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|editó}} un mensaxe sobro «$2» en $3.",
- "flow-notification-edit-email-batch-bundle-body": "$1 y $4 {{PLURAL:$5|más}}{{GENDER:$1|editaron}} un mensaxe sobro «$2» en $3.",
+ "flow-notification-edit-email-batch-bundle-body": "$1 y {{PLURAL:$4|otru|otros $4|100=99+}} más {{GENDER:$1|editaron}} un mensaxe sobro «$2» en $3.",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|renomó'l}} so asuntu",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|cambió'l nome}} del to asuntu «$2» a «$3» en $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|creó}} un asuntu nuevu en $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|creó}} un asuntu nuevu col títulu «$2» en $3",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Avisame cuando heba aiciones rellacionaes conmigo en Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|un asuntu nuevu|$1 asuntos nuevos|100=99+ asuntos nuevos}} en $2",
+ "echo-category-title-flow-discussion": "Alderique estructuráu",
+ "echo-pref-tooltip-flow-discussion": "Avisame de l'actividá nos asuntos o páxines que sigo.",
"flow-link-post": "mensaxe",
"flow-link-topic": "asuntu",
"flow-link-history": "historial",
@@ -214,10 +355,172 @@
"flow-moderation-confirm-unsuppress-topic": "De-suprimir",
"flow-moderation-confirm-undelete-topic": "Restaurar",
"flow-moderation-confirm-unhide-topic": "Revelar",
- "flow-moderation-confirmation-suppress-post": "El mensaxe suprimióse correutamente.\n{{GENDER:$2|Considere}} aldericar con $1 tocante a esti mensaxe.",
- "flow-moderation-confirmation-delete-post": "El mensaxe desanicióse correutamente.\n{{GENDER:$2|Considere}} aldericar con $1 tocante a esti mensaxe.",
- "flow-moderation-confirmation-hide-post": "El mensaxe tapecióse correutamente.\n{{GENDER:$2|Considere}} aldericar con $1 tocante a esti mensaxe.",
- "flow-terms-of-use-new-topic": "Al calcar \"{{int:flow-newtopic-save}}\", aceuta les condiciones d'usu d'esta wiki.",
- "flow-terms-of-use-reply": "Al calcar \"{{int:flow-reply-link}}\", aceuta les condiciones d'usu d'esta wiki.",
- "flow-terms-of-use-edit": "Al guardar los cambios, aceuta les condiciones d'usu d'esta wiki."
+ "flow-moderation-confirmation-suppress-post": "El mensaxe suprimióse.\n{{GENDER:$2|Considera}} aldericar con $1 tocante a esti mensaxe.",
+ "flow-moderation-confirmation-delete-post": "El mensaxe desanicióse.\n{{GENDER:$2|Considera}} aldericar con $1 tocante a esti mensaxe.",
+ "flow-moderation-confirmation-hide-post": "El mensaxe tapecióse.\n{{GENDER:$2|Considera}} aldericar con $1 tocante a esti mensaxe.",
+ "flow-moderation-confirmation-unsuppress-post": "Desfixisti la supresión de la publicación anterior.",
+ "flow-moderation-confirmation-undelete-post": "Restaurasti la publicación anterior.",
+ "flow-moderation-confirmation-unhide-post": "Amosasti la publicación anterior.",
+ "flow-moderation-confirmation-suppress-topic": "Esti asuntu suprimióse.",
+ "flow-moderation-confirmation-delete-topic": "Esti asuntu desanicióse.",
+ "flow-moderation-confirmation-hide-topic": "Esti asuntu anubrióse.",
+ "flow-moderation-confirmation-unsuppress-topic": "Desfixisti la supresión del filu anterior.",
+ "flow-moderation-confirmation-undelete-topic": "Restaurasti esti filu.",
+ "flow-moderation-confirmation-unhide-topic": "Amosasti esti filu.",
+ "flow-moderation-title-suppress-topic": "¿Suprimir l'asuntu?",
+ "flow-moderation-title-delete-topic": "¿Desaniciar l'asuntu?",
+ "flow-moderation-title-hide-topic": "¿Tapecer l'asuntu?",
+ "flow-moderation-title-unsuppress-topic": "¿Desfaer la supresión d'esti asuntu?",
+ "flow-moderation-title-undelete-topic": "¿Restaurar l'asuntu?",
+ "flow-moderation-title-unhide-topic": "¿Revelar l'asuntu?",
+ "flow-moderation-placeholder-suppress-topic": "{{GENDER:$3|Esplica}} por qué vas suprimir esti asuntu.",
+ "flow-moderation-placeholder-delete-topic": "{{GENDER:$3|Esplica}} por qué vas desaniciar esti asuntu.",
+ "flow-moderation-placeholder-hide-topic": "{{GENDER:$3|Esplica}} por qué vas despintar esti asuntu.",
+ "flow-moderation-placeholder-unsuppress-topic": "{{GENDER:$3|Esplica}} por qué vas desfacer la supresión d'esti asuntu.",
+ "flow-moderation-placeholder-undelete-topic": "{{GENDER:$3|Esplica}} por qué vas desfacer el desaniciu d'esti asuntu.",
+ "flow-moderation-placeholder-unhide-topic": "{{GENDER:$3|Esplica}} por qué vas amosar esti asuntu.",
+ "flow-topic-permalink-warning": "Esta asuntu empecipióse'n [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Esti asuntu empecipió nel [$2 tableru de {{GENDER:$1|$1}}]",
+ "flow-revision-permalink-warning-post": "Esti ye un enllaz permanente a una única versión d'esta publicación.\nEsta versión ye de $1.\nPuedes ver les [$5 diferencies cola versión anterior] o ver otres versiones na [$4 páxina del historial de publicaciones].",
+ "flow-revision-permalink-warning-post-first": "Esti ye un enllaz permanente a la primera versión d'esta publicación.\nPuedes ver versiones posteriores na [$4 páxina del historial de publicaciones].",
+ "flow-revision-permalink-warning-postsummary": "Esti ye un enllaz permanente a una única versión del resume d'esta publicación. Esta versión ye de $1.\nPuedes ver les [$5 diferencies ente versiones] o ver otres versiones na [$4 páxina del historial de publicaciones].",
+ "flow-revision-permalink-warning-postsummary-first": "Esti ye un enllaz permanente a la primera versión del resume d'esta publicación.\nPuedes ver versiones posteriores na [$4 páxina del historial de la publicación].",
+ "flow-revision-permalink-warning-header": "Esto ye un enllaz permanente a una única versión de la descripción.\nEsta versión ye de $1. Puedes ver les [$3 diferencies dende la versión anterior] o ver otres versiones na [$2 páxina del historial del tableru].",
+ "flow-revision-permalink-warning-header-first": "Esti ye un enllaz permanente a la primera versión de la descripción.\nPuedes ver versiones posteriores na [$2 páxina del historial del tableru].",
+ "flow-compare-revisions-revision-header": "Versión de {{GENDER:$2|$2}} del $1",
+ "flow-compare-revisions-header-post": "Esta páxina amuesa los {{GENDER:$3|cambeos}} ente dos versiones d'una publicación de $3 nel asuntu «[$5 $2]» en [$4 $1].\nPuedes ver otres versiones d'esta publicación na so [$6 páxina d'historial].",
+ "flow-compare-revisions-header-postsummary": "Esta páxina amuesa los cambeos ente dos versiones del resume de la publicación «[$4 $2]» en [$3 $1].\nPuedes ver otres versiones del resume de publicación na [$5 páxina d'historial] del asuntu.",
+ "flow-compare-revisions-header-header": "Esta páxina amuesa los {{GENDER:$2|cambeos}} ente dos versiones de la descripción en [$3 $1].\nPuedes ver otres versiones de la descripción na so [$4 páxina d'historial].",
+ "action-flow-create-board": "crear tableros d'Alderiques estructuraos en cualquier llugar",
+ "right-flow-create-board": "Crear tableros d'Alderiques estructuraos en cualquier llugar",
+ "right-flow-hide": "Tapecer asuntos y publicaciones d'Alderiques estructuraos",
+ "right-flow-lock": "Marcar asuntos d'Alderiques estructuraos como resueltos",
+ "right-flow-delete": "Desaniciar temes y publicaciones d'Alderiques estructuraos",
+ "right-flow-edit-post": "Editar publicaciones d'Alderiques estructuraos d'otros usuarios",
+ "right-flow-suppress": "Suprimir revisiones d'Alderiques estructuraos",
+ "flow-terms-of-use-new-topic": "Al calcar «{{int:flow-newtopic-save}}», aceutes les condiciones d'usu d'esta wiki.",
+ "flow-terms-of-use-reply": "Al calcar «{{int:flow-reply-link}}», aceutes les condiciones d'usu d'esta wiki.",
+ "flow-terms-of-use-edit": "Al guardar los cambios, aceuta les condiciones d'usu d'esta wiki.",
+ "flow-anon-warning": "Nun aniciasti sesión. Pa recibir atribución col to nome'n llugar de la direición IP, puedes [$1 aniciar sesión] o [$2 crear una cuenta].",
+ "flow-cancel-warning": "Escribisti testu nesti formulariu. ¿Tas seguru de que quies descartalu?",
+ "flow-topic-first-heading": "Tema en $1",
+ "flow-topic-html-title": "$1 en $2",
+ "flow-topic-count": "Temes ($1)",
+ "flow-load-more": "Cargar más",
+ "flow-no-more-fwd": "Nun hai temes más antigües",
+ "flow-newest-topics": "Temes nueves",
+ "flow-recent-topics": "Temes con actividá más recién",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Tas}} lleyendo les temes creaes más apocayá primero. Fai clic pa ver más opciones d'ordenación.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Tas}} lleyendo les temes que tuvieron actividá más apocayá primeru. Fai clic pa ver más opciones d'ordenación.",
+ "flow-toggle-small-topics": "Camudar a la vista de temes amenorgada",
+ "flow-toggle-topics": "Camudar a la vista de sólo temes",
+ "flow-toggle-topics-posts": "Camudar a la vista de temes y publicaciones",
+ "flow-terms-of-use-summarize": "Al calcar «{{int:flow-topic-action-update-topic-summary}}», aceutes les condiciones d'usu d'esta wiki.",
+ "flow-terms-of-use-lock-topic": "Al facer click en «{{int:flow-topic-action-lock-topic}}» aceutes los términos d'usu d'esta wiki.",
+ "flow-terms-of-use-unlock-topic": "Al calcar «{{int:flow-topic-action-unlock-topic}}», aceutes les condiciones d'usu d'esta wiki.",
+ "flow-whatlinkshere-post": "d'una [$1 publicación]",
+ "flow-whatlinkshere-header": "de la [$1 descripción]",
+ "flow-whatlinkshere-post-summary": "del [$1 resume]",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Indicando un UUID, esta páxina especial redirixe a un fluxu de trabayu o publicación d'Alderiques estructuraos.",
+ "flow-special-type": "Triba",
+ "flow-special-type-post": "Publicación",
+ "flow-special-type-workflow": "Fluxu de trabayu",
+ "flow-special-uuid": "UUID",
+ "flow-special-invalid-uuid": "Nun s'atopó conteníu que coincida col tipu y el UUID indicaos.",
+ "flow-special-enableflow-legend": "Activar Alderiques estructuraos nuna páxina nueva",
+ "flow-special-enableflow-page": "Páxina onde va activase Alderiques estructuraos",
+ "flow-special-enableflow-header": "Descripción inicial del tableru d'Alderiques estructuraos (testu wiki)",
+ "flow-special-enableflow-board-already-exists": "Yá esiste un tableru d'Alderiques estructuraos en [[$1]].",
+ "flow-special-enableflow-invalid-title": "Dióse un títulu de páxina inválidu.",
+ "flow-special-enableflow-board-creation-not-allowed": "Nun tienes permisu pa crear un tableru d'Alderiques estructuraos en [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Hai una páxina con LiquidThreads en [[:$1]].",
+ "flow-special-enableflow-confirmation": "Creasti un tableru d'Alderiques estructuraos en [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Archivu %d\n%s/Archivu%d\n%s/archivu %d\n%s/archivu%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Archivu d'Alderiques estructuraos %d\n%s/ArchivuAlderiquesEstructuraos%d",
+ "flow-spam-confirmedit-form": "Confirma que yes un humanu resolviendo'l siguiente CAPTCHA: $1",
+ "flow-spam-confirmedit-using-failure": "Hebo un fallu téunicu col CAPTCHA. Si nun puedes unviar el cambiu, copia'l testu, recarga la páxina y tenta otra vuelta.",
+ "flow-embedding-unsupported": "Los alderiques inda nun pueden encuallase.",
+ "mw-ui-unsubmitted-confirm": "Tienes cambeos ensin unviar nesta páxina. ¿Tas seguru que quies dir a otru llugar y perder el to trabayu?",
+ "flow-post-undo-hide": "desfaer despintar",
+ "flow-post-undo-delete": "desfaer desaniciar",
+ "flow-post-undo-suppress": "desfaer suprimir",
+ "flow-topic-undo-hide": "desfaer despintar",
+ "flow-topic-undo-delete": "desfaer desaniciar",
+ "flow-topic-undo-suppress": "desfaer suprimir",
+ "flow-importer-lqt-moved-thread-template": "Entamu de filu LQT treslladáu convertíu a Alderiques estructuraos",
+ "flow-importer-lqt-moved-thread-template-content": "Esta publicación de {{{author}}} treslladóse'l {{{date}}}. Puedes atopala'n [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "Páxina LQT convertida a Alderiques estructuraos",
+ "flow-importer-lqt-converted-template-content": "L'historial anterior de la páxina archivóse como copia de saguridá en [[{{{archive}}}]] el {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-lqt-converted-archive-template": "Archivu de la páxina LQT convertida",
+ "flow-importer-lqt-converted-archive-template-content": "Esta ye una páxina archivada de LiquidThreads. <strong>Nun edites el conteníu d'esta páxina</strong>. Dirixe cualquier otru comentariu a la [[{{{from}}}|páxina d'alderique actual]].",
+ "flow-importer-wt-converted-template": "Páxina d'alderique de testu wiki convertida a Alderiques estructuraos",
+ "flow-importer-wt-converted-template-content": "L'alderique anterior archivóse'n [[{{{archive}}}]] el {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Archivu pa la páxina d'alderique'n testu wiki convertida",
+ "flow-importer-wt-converted-archive-template-content": "Esta páxina ye un archivu. <strong>Nun edites el conteníu d'esta páxina</strong>. Dirixe cualquier otru comentariu a la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|páxina d'alderique actual]].",
+ "flow-importer-lqt-suppressed-user-template": "Publicación de LQT importada con un usuariu suprimíu",
+ "flow-importer-lqt-suppressed-user-template-content": "Esta revisión importóse dende LiquidThreads con un usuariu suprimíu. Reasinóse al usuariu actual.",
+ "flow-importer-lqt-different-author-signature-template": "Publicación de LQT importada con un usuariu firmante distintu",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Esta publicación fízola [[User:{{{authorUser}}}|{{{authorUser}}}]], pero robló como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
+ "flow-edited": "Editáu",
+ "flow-edited-by": "Editáu por $1",
+ "flow-edited-by-header": "Descripción del tableru editada por $1",
+ "flow-edited-by-topic-title": "Títulu del asuntu editáu por $1",
+ "flow-lqt-redirect-reason": "Redirixendo la publicación de LiquidThreads retirada a la so publicación convertida d'Alderiques estructuraos.",
+ "flow-talk-conversion-move-reason": "Conversión d'alderique de testu wiki a Alderiques estructuraos dende $1",
+ "flow-talk-conversion-archive-edit-reason": "Conversión d'alderique de testu wiki a Alderiques estructuraos",
+ "flow-previous-diff": "← Edición más antigua",
+ "flow-next-diff": "Edición más nueva →",
+ "flow-undo": "desfacer",
+ "flow-undo-latest-revision": "Última revisión",
+ "flow-undo-your-text": "El to testu",
+ "flow-undo-edit-header": "Editando la descripción",
+ "flow-undo-edit-topic-summary": "Editando'l resume del asuntu",
+ "flow-undo-edit-post": "Editando una publicación",
+ "flow-undo-edit-content": "La edición se pue esfacer.\nPor favor comprueba la comparanza d'abaxo pa confirmar que ye eso lo que quies facer, y depués guarda los cambios d'abaxo p'acabar d'esfacer la edición.",
+ "flow-undo-edit-failure": "Nun se pudo desfaer la edición por ediciones conflictives entemedies.",
+ "group-flow-bot": "Bots d'Alderiques estructuraos",
+ "group-flow-bot-member": "Bot d'Alderiques estructuraos",
+ "grouppage-flow-bot": "Project:Bots d'Alderiques estructuraos",
+ "flow-ve-mention-context-item-label": "Mentar",
+ "flow-ve-mention-inspector-title": "Mención",
+ "flow-ve-mention-inspector-remove-label": "Desaniciar",
+ "flow-ve-mention-placeholder": "Nome d'usuariu",
+ "flow-ve-mention-tool-title": "Mentar a un usuariu",
+ "flow-ve-mention-template-title": "MenciónFlow",
+ "flow-ve-mention-inspector-invalid-user": "L'usuariu «$1» nun ta rexistráu.",
+ "flow-wikitext-editor-help": "Testu wiki $1.",
+ "flow-wikitext-editor-help-and-preview": "Testu wiki $1 y en cualquier momentu puedes $2.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|usa un llinguaxe de marques]]",
+ "flow-wikitext-editor-help-preview-the-result": "entever el resultáu",
+ "flow-wikitext-switch-editor-tooltip": "Cambiar al editor visual",
+ "flow-ve-switch-editor-tool-title": "Cambiar al editor de testu wiki",
+ "flow-mark-revision-patrolled-link-text": "Marcar esta páxina como supervisada",
+ "flow-mark-revision-patrolled-link-title": "Marcar esta páxina como supervisada",
+ "flow-mark-diff-patrolled-link-text": "Marcar como supervisada",
+ "flow-mark-diff-patrolled-link-title": "Marcar como supervisada",
+ "flow-talk-page-beta-feature-message": "Alderiques estructuraos n'alderique d'usuariu",
+ "flow-talk-page-beta-feature-description": "Activa un nuevu sistema d'alderique estructuráu {{GENDER:|na to}} páxina d'alderique d'usuariu. Alderiques estructuraos simplifica los alderiques nes páxines d'usuariu con sitios claros pa escribir y responder, y permite avisos nel nivel de conversación. Esta carauterística nun s'activa automáticamente; los usuarios tendrán qu'activala por separáu.<br /><br />Los discutinios en testu wiki que yá esistan van movese a un archivu. Si se desactiva esta carauterística, el tableru d'Alderiques estructuraos va treslladaráse a una subpáxina y se desarchivará la páxina d'alderique anterior.[[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Más información tocante a la activación]].",
+ "flow-notification-link-text-enabled-on-talkpage": "Ver la páxina d'alderique {{GENDER:|del usuariu|de la usuaria}}",
+ "flow-notification-enabled-on-talkpage-title": "Activáu el sistema de discutiniu nuevu na to páxina d'alderique d'{{GENDER:$1|usuariu|usuaria}}<br /><small>Disponible'n [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nuevu sistema d'alderique'n $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Alderiques estructuraos, el nuevu sistema d'alderique de la wiki, activóse {{GENDER:$1|na to}} páxina d'alderique d'usuariu de {{SITENAME}}. Puedes llograr más información, facer comentarios o desactivar el nuevu sistema en cualquier momentu dende la sección de carauterístiques Beta de {{GENDER:$1|les tos}} preferencies.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Amestando la plantía d'archivu",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Desaniciando la plantía d'archivu",
+ "flow-dialog-cancelconfirm-title": "¿Tas {{GENDER:|seguru|segura}}?",
+ "flow-dialog-cancelconfirm-message": "¿Tas {{GENDER:|seguru|segura}} de que quies encaboxar ensin guardar primero?",
+ "flow-dialog-cancelconfirm-keep": "Siguir editando",
+ "flow-dialog-cancelconfirm-discard": "Descartar los cambios",
+ "flow-optin-archive-wikitext": "Treslládase la páxina en testu wiki pa dexar sitiu pa un tableru d'alderique.",
+ "flow-optin-archive-flow-board": "Treslládase la páxina de tableru d'alderique pa dexar sitiu a una páxina en testu wiki.",
+ "flow-optin-restore-wikitext": "Restáurase la páxina de testu wiki archivada.",
+ "flow-optin-restore-flow-board": "Restáurase'l tableru d'alderique archiváu.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Bienveníu|Bienvenida}} a la to nueva páxina d'alderique d'{{GENDER:$1|usuariu|usuaria}}",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|La to}} páxina d'alderique ye'l llugar onde otros editores pueden comunicase {{GENDER:$1|contigo}}. Con Alderiques estructuraos, ye más fácil empezar temes nueves y facer un siguimientu de les conversaciones.",
+ "flow-guidedtour-optin-find-old-conversations": "Alcontrar {{GENDER:$1|les tos}} conversaciones antigües",
+ "flow-guidedtour-optin-find-old-conversations-description": "Les conversaciones anteriores treslladáronse a una páxina d'archivu.",
+ "flow-guidedtour-optin-feedback": "Unvianos {{GENDER:$1|los tos}} comentarios.",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Puedes}} llograr más información, facer comentarios o desactivar el nuevu sistema en cualquier momentu dende la sección de carauterístiques beta.",
+ "flow-action-not-page": "L'oxetu de la páxina ye una instancia d'una clase incorreuta",
+ "flow-action-wrong-title-content-model": "La páxina ta xestionándose con Alderiques estructuraos, pero la clase Títulu indica que'l modelu de conteníu ye '$1'. Esti ye un fallu de configuración o un estáu inconsistente. Por casu, esto podría ser en realidá una páxina que nun ye d'Alderiques estructuraos nun espaciu de nomes d'Alderiques estructuraos, con <code>rev_content_model</code> sin rellenar."
}
diff --git a/Flow/i18n/atj.json b/Flow/i18n/atj.json
new file mode 100644
index 00000000..ab894cbf
--- /dev/null
+++ b/Flow/i18n/atj.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dereckson",
+ "Benoit Rochon"
+ ]
+ },
+ "flow-cancel": "Ponipita",
+ "flow-newtopic-save": "Acotcicta",
+ "flow-history-action-delete-post": "wepina",
+ "flow-history-action-hide-post": "kata",
+ "flow-history-action-undelete-post": "wepina",
+ "flow-post-action-post-history": "Isparik",
+ "flow-post-action-delete-post": "Wepina",
+ "flow-post-action-hide-post": "Kata",
+ "flow-post-action-edit-post": "Meckotcita",
+ "flow-post-action-edit-post-submit": "Kanawapata ka meckotcipitcikateki",
+ "flow-topic-action-watchlist": "Ka masinateki",
+ "flow-topic-action-history": "Isparik",
+ "flow-topic-action-undo-moderation": "Nama ntwatc",
+ "flow-error-invalid-topic-uuid-title": "Nama mia icinikatew",
+ "flow-board-history": "\"$1\" isparik",
+ "flow-history-day": "Ke kicikak",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Tapwatcike}} masinhikan",
+ "flow-link-history": "isparik",
+ "flow-moderation-confirm-delete-post": "Wepina",
+ "flow-moderation-confirm-hide-post": "Kata",
+ "flow-moderation-confirm-delete-topic": "Wepina",
+ "flow-moderation-confirm-hide-topic": "Kata",
+ "flow-ve-mention-inspector-remove-label": "Manina"
+}
diff --git a/Flow/i18n/az.json b/Flow/i18n/az.json
index 7e547b6a..76562fb8 100644
--- a/Flow/i18n/az.json
+++ b/Flow/i18n/az.json
@@ -1,12 +1,14 @@
{
"@metadata": {
"authors": [
- "Wertuose"
+ "Wertuose",
+ "Serkanland"
]
},
"flow-post-action-undelete-post": "Bərpa et",
"flow-error-missing-summary": "Siz mütləq şərh əlavə etməlisiniz.",
"flow-error-missing-header-content": "Siz mütləq izah əlavə etməlisiniz.",
+ "flow-notification-mention-email-subject": "$1 $2 səhifəsində sizdən {{GENDER:$1|bəhs etdi}}.",
"flow-moderation-confirm-undelete-post": "Bərpa et",
"flow-moderation-confirm-undelete-topic": "Bərpa et"
}
diff --git a/Flow/i18n/azb.json b/Flow/i18n/azb.json
new file mode 100644
index 00000000..0945efeb
--- /dev/null
+++ b/Flow/i18n/azb.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alp Er Tunqa",
+ "Ilğım"
+ ]
+ },
+ "flow-summary-edited": "دییشدیرمه قیساسینی سوْن دفعه $1 {{GENDER:$1|دییشدیرمیشدیر}}",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|سیزه}} «'''$5'''»-ده {{GENDER:$2|ایشاره ائتدی}}.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$4|سیزه}} «'''$5'''»-ده {{GENDER:$2|ایشاره ائتدی}}.",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$3|سیزه}} «$2»-ده {{GENDER:$1|ایشاره ائتدی}}.",
+ "group-flow-bot": "جریان روباتلاری",
+ "grouppage-flow-bot": "Project:جریان روباتلاری"
+}
diff --git a/Flow/i18n/ba.json b/Flow/i18n/ba.json
new file mode 100644
index 00000000..4c963ec4
--- /dev/null
+++ b/Flow/i18n/ba.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Янмурза Баки",
+ "Айсар",
+ "Азат Хәлилов",
+ "Ilmira",
+ "Ләйсән"
+ ]
+ },
+ "flow-error-protected-unknown-reason": "Билдәһеҙ",
+ "flow-topic-comments": "{{PLURAL:$1|$1 аңлатма|0={{GENDER:$2|Беренсе булып}} аңлатма ҡалдыр!}}",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|яуап бирҙе|яуап бирҙе}} на <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и {{PLURAL:$5|$5 башҡа берәү яуап бирҙе{{GENDER:$1||а}}|$5 башҡа кеше яуап бирҙе|100=99+ икенсе кеше яуап бирҙе}} битте '''$3'''.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|$1 яңы тема}} бында <strong>$3</strong>",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|replied}} in \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Яңы тема}} бында \"<strong>$3</strong>\".",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|mentioned}} {{GENDER:$4|you}} in \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mentioned}} {{GENDER:$4|you}} in \"<strong>$5</strong>\".",
+ "flow-moderation-confirmation-undelete-post": "Өҫтә күрһәтелгән хәбәрҙе юйыуҙы юҡҡа сығарҙығыҙ.",
+ "flow-action-not-page": "Был нөсхәлә объект битенең класы дөрөҫ түгел"
+}
diff --git a/Flow/i18n/bcl.json b/Flow/i18n/bcl.json
index 8d0816f4..df7cd813 100644
--- a/Flow/i18n/bcl.json
+++ b/Flow/i18n/bcl.json
@@ -4,7 +4,6 @@
"Geopoet"
]
},
- "flow-talk-username": "Tagamaneho kan taguytoy sa pahina nin orolay",
"flow-board-header": "Mapanungod kaining diskusyon",
"flow-board-collapse-description": "Tagoon an deskripsyon",
"flow-board-expand-description": "Ipahiling an deskripsyon",
diff --git a/Flow/i18n/be-tarask.json b/Flow/i18n/be-tarask.json
index e8d7af1b..532ce340 100644
--- a/Flow/i18n/be-tarask.json
+++ b/Flow/i18n/be-tarask.json
@@ -1,12 +1,16 @@
{
"@metadata": {
"authors": [
- "Red Winged Duck"
+ "Red Winged Duck",
+ "Renessaince"
]
},
- "right-flow-hide": "хаваць тэмы і паведамленьні Flow",
- "right-flow-lock": "пазначэньне тэмаў Flow як вырашаных",
- "right-flow-delete": "выдаленьне тэмаў і запісаў Flow",
+ "echo-category-title-flow-discussion": "Структураваная дыскусія",
+ "echo-pref-tooltip-flow-discussion": "Паведамляць мне пра актыўнасьць у тэмах і на старонках, за якімі я сачу.",
+ "right-flow-hide": "Хаваць тэмы і паведамленьні структураваных дыскусіяў",
+ "right-flow-lock": "Пазначэньне тэмаў структураваных дыскусіяў як вырашаных",
+ "right-flow-delete": "Выдаленьне тэмаў і запісаў структураваных дыскусіяў",
"right-flow-edit-post": "рэдагаваньне запісаў іншых удзельнікаў у Flow",
- "right-flow-suppress": "падаўленьне вэрсіяў Flow"
+ "right-flow-suppress": "падаўленьне вэрсіяў Flow",
+ "flow-special-type": "Тып"
}
diff --git a/Flow/i18n/be.json b/Flow/i18n/be.json
index 86f36c4d..9f8b970c 100644
--- a/Flow/i18n/be.json
+++ b/Flow/i18n/be.json
@@ -4,5 +4,7 @@
"Дзяніс Тутэйшы"
]
},
- "flow-post-action-hide-post": "Схаваць"
+ "flow-post-action-hide-post": "Схаваць",
+ "flow-notification-mention": "$1 {{GENDER:$1|упамянуў|упамянула}} {{GENDER:$5|вас}} у {{GENDER:$1|сваім}} <span class=\"plainlinks\">[$2 паведамленні]</span> у \"$3\" на \"$4\".",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|упамянуў|упамянула}} {{GENDER:$3|Вас}} на $2"
}
diff --git a/Flow/i18n/bg.json b/Flow/i18n/bg.json
index c323896f..84e36017 100644
--- a/Flow/i18n/bg.json
+++ b/Flow/i18n/bg.json
@@ -3,18 +3,40 @@
"authors": [
"DCLXVI",
"Mitzev",
- "Borislav"
+ "Borislav",
+ "V111P",
+ "StanProg"
]
},
+ "flow-board-header-browse-topics-link": "Преглед на темите",
+ "flow-board-header": "За таблото",
+ "flow-edit-header-link": "Редактиране на описанието",
"flow-cancel": "Отказване",
"flow-newtopic-header": "Добавяне на нова тема",
"flow-newtopic-save": "Добавяне на тема",
"flow-newtopic-start-placeholder": "Започване на нова тема",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Коментар}} в „$2“",
+ "flow-reply-topic-title-placeholder": "Отговор до „$1“",
+ "flow-reply-link": "{{GENDER:$1|Отговор}}",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Благодарност}}}}",
+ "flow-thank-link-title": "Публична {{GENDER:$1|{{GENDER:$2|благодарност}}}} до автора на съобщението",
"flow-topic-action-watchlist": "Списък за наблюдение",
- "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|коментира}}] в $4 (<em>$5</em>).",
- "echo-pref-tooltip-flow-discussion": "Известяване при засягащи ме действия във Flow (новата дискусионна система).",
+ "flow-topic-action-lock-topic": "Отбелязване като разрешено",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Вие се}} абонирахте за това дискусионно табло!",
+ "flow-topic-action-watchlist-add": "Абониране за темата",
+ "flow-error-invalid-undelete": "Страницата не може да бъде възстановена тъй като на нея има дискусионно табло.",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|коментира}}] в „$4“ (<em>$5</em>).",
+ "notification-header-flow-new-topic-v2": "Създадена е нова тема на <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$3|Ви}} {{GENDER:$1|спомена}} на „$2“",
+ "echo-category-title-flow-discussion": "Дискусия чрез Flow",
+ "echo-pref-tooltip-flow-discussion": "Известяване за действия в теми или страници, които следя.",
"flow-link-history": "история",
- "flow-revision-permalink-warning-header": "Това е постоянна препратка към единична версия на заглавката.\nТази версия е от $1. Можете да видите [$3 разликите с предишната версия] или да видите други версии от [$2 историята на страницата].",
- "flow-revision-permalink-warning-header-first": "Това е постоянна препратка към първата версия на заглавката.\nМожете да видите по-нови версии от [$2 историята на страницата].",
- "flow-compare-revisions-header-header": "Тази страница показва {{GENDER:$2|промените}} между две версии на заглавката на [$3 $1].\nМожете да видите други версии на [$4 историята на страницата]."
+ "flow-revision-permalink-warning-header": "Това е постоянна препратка към единична версия на описанието.\nТази версия е от $1. Можете да видите [$3 разликите с предишната версия] или да видите други версии от [$2 историята на страницата].",
+ "flow-revision-permalink-warning-header-first": "Това е постоянна препратка към първата версия на описанието.\nМожете да видите по-нови версии от [$2 историята на страницата].",
+ "flow-compare-revisions-header-header": "Тази страница показва {{GENDER:$2|промените}} между две версии на описанието на [$3 $1].\nМожете да видите други версии на [$4 историята на страницата].",
+ "flow-recent-topics": "Наскоро активни теми",
+ "flow-importer-wt-converted-template-content": "Предишната дискусия е архивирана в <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-ve-mention-placeholder": "Потребителско име",
+ "flow-optin-archive-wikitext": "Преместване на страницата с уики текст за да се освободи място за дискусионно табло.",
+ "flow-optin-restore-flow-board": "Възстановяване на архивирано дискусионно табло."
}
diff --git a/Flow/i18n/bgn.json b/Flow/i18n/bgn.json
new file mode 100644
index 00000000..5aca405e
--- /dev/null
+++ b/Flow/i18n/bgn.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibrahim khashrowdi"
+ ]
+ },
+ "echo-category-title-flow-discussion": "تچي‌تین",
+ "flow-ve-mention-placeholder": "کار زورؤکین نام"
+}
diff --git a/Flow/i18n/bho.json b/Flow/i18n/bho.json
new file mode 100644
index 00000000..6904ba0a
--- /dev/null
+++ b/Flow/i18n/bho.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "SatyamMishra"
+ ]
+ },
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|द्वारा बनावल गइल}}, टॉपिक \"[$3 $4]\"",
+ "flow-rev-message-new-post-recentchanges-summary": "नया टॉपिक {{GENDER:$2|द्वारा बनावल गइल}}",
+ "flow-rev-message-edit-title": "टॉपिक टाइटिल \"$5\" से \"[$3 $4]\" में $1 {{GENDER:$2|द्वारा बदलल गइल}}",
+ "flow-rev-message-create-header": "बिबरण $1 {{GENDER:$2|द्वारा बनावल गइल}}",
+ "flow-rev-message-edit-header": "बिबरण $1 {{GENDER:$2|द्वारा संपादित कइल गइल}}"
+}
diff --git a/Flow/i18n/bn.json b/Flow/i18n/bn.json
index 089d7e84..5cb4f584 100644
--- a/Flow/i18n/bn.json
+++ b/Flow/i18n/bn.json
@@ -5,12 +5,20 @@
"Aftab1995",
"Aftabuzzaman",
"Jim Carter",
- "Sayma Jahan"
+ "Sayma Jahan",
+ "Kayser Ahmad",
+ "Elias Ahmmad",
+ "Bodhisattwa"
]
},
- "enableflow": "ফ্লো সক্রিয় করুন",
- "flow-desc": "কর্মপ্রবাহ ব্যবস্থাপনা পদ্ধতি",
- "log-name-flow": "ফ্লো কার্যকলাপ লগ",
+ "enablestructureddiscussions": "কাঠামোবদ্ধ আলোচনা সক্রিয় করুন",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|আপনি}} আর \"$1\" পাতাটির নজর রাখছেন না",
+ "notification-dynamic-actions-flow-topic-unwatch": "নজরতালিকা থেকে এই প্রসঙ্গ দেখা {{GENDER:$3|বাদ দিন}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|আপনি}} আর \"$1\"-এর নজর রাখছেন না",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|আপনি}} যেকোন সময় [$2 এই প্রসঙ্গ] নজরে রাখতে পারেন।",
+ "flow-desc": "আলোচনার পদ্ধতি",
+ "flow-talk-taken-over-comment": "/* এ পৃষ্ঠাটি একটি কাঠামোবদ্ধ আলোচনা বোর্ডে রূপান্তরিত করা হয়েছে */",
+ "log-name-flow": "কাঠামোবদ্ধ আলোচনা কার্যকলাপ লগ",
"logentry-delete-flow-delete-post": "$1 [[$6]] পাতায় \"[[$3|$5]]\"-এ একটি [$4 প্রকাশনা] {{GENDER:$2|অপসারণ করেছেন}}",
"logentry-delete-flow-restore-post": "$1 [[$6]] পাতায় \"[[$3|$5]]\"-এ একটি [$4 প্রকাশনা] {{GENDER:$2|পুনরুদ্ধার করেছেন}}",
"logentry-suppress-flow-suppress-post": "$1 [[$6]] পাতায় \"[[$3|$5]]\"-এ একটি [$4 প্রকাশনা] {{GENDER:$2|গোপন করেছেন}}",
@@ -21,6 +29,7 @@
"logentry-suppress-flow-restore-topic": "$1 [[$6]]-এ প্রসঙ্গ \"[[$3|$5]]\" {{GENDER:$2|অপসারণ করেছেন}}",
"flow-board-header-browse-topics-link": "প্রসঙ্গ ব্রাউজ করুন",
"flow-board-header": "এই বোর্ড সম্পর্কে",
+ "flow-board-description-can-not-edit": "সম্পাদনাযোগ্য নয়",
"flow-board-collapse-description": "বিবরণ লুকাও",
"flow-board-expand-description": "বিবরণ দেখাও",
"flow-edit-header-link": "বিবরণ সম্পাদনা করুন",
@@ -43,9 +52,14 @@
"flow-post-actions": "কার্যসমূহ",
"flow-topic-actions": "কার্যসমূহ",
"flow-cancel": "বাতিল",
+ "flow-skip-summary": "এড়ান",
+ "flow-summary-authored": "$1 দ্বারা সারাংশ",
+ "flow-summary-edited": "সারাংশ সর্বশেষ $1 দ্বারা {{GENDER:$1|সম্পাদিত হয়েছে}}",
"flow-show-change": "পরিবর্তনসমূহ দেখাও",
"flow-last-modified-by": "$1 দ্বারা সর্বশেষ {{GENDER:$1|সম্পাদিত}}",
+ "flow-stub-post-content": "<em>একটি কারিগরি ত্রুটির কারণে, এই সামগ্রীটি পুনরুদ্ধার করা যায়নি।</em>",
"flow-newtopic-title-placeholder": "নতুন প্রসঙ্গ",
+ "flow-newtopic-content-placeholder": "\"$1\"-এ একটি নতুন বার্তা লিখুন",
"flow-newtopic-header": "একটি নতুন প্রসঙ্গ যোগ করুন",
"flow-newtopic-save": "প্রসঙ্গ যোগ করুন",
"flow-newtopic-start-placeholder": "একটি নতুন প্রসঙ্গ শুরু করুন",
@@ -59,12 +73,15 @@
"flow-history-action-restore-post": "পুনরুদ্ধার",
"flow-history-action-lock-topic": "মিমাংসিত",
"flow-history-action-unlock-topic": "পুনরায় খুলুন",
- "flow-post-action-view": "পার্মালিঙ্ক",
+ "flow-post-action-view": "স্থায়ী সংযোগ",
"flow-post-action-post-history": "ইতিহাস",
"flow-post-action-delete-post": "অপসারণ",
"flow-post-action-hide-post": "আড়াল করো",
"flow-post-action-edit-post": "সম্পাদনা",
"flow-post-action-edit-post-submit": "পরিবর্তন সংরক্ষণ",
+ "flow-post-action-restore-post": "পুনরুদ্ধার",
+ "flow-post-action-undo-moderation": "পূর্বাবস্থা",
+ "flow-topic-action-view": "স্থায়ী সংযোগ",
"flow-topic-action-watchlist": "নজরতালিকা",
"flow-topic-action-edit-title": "শিরোনাম সম্পাদনা করুন",
"flow-topic-action-history": "ইতিহাস",
@@ -75,13 +92,16 @@
"flow-topic-action-summarize-topic": "সংক্ষেপন",
"flow-topic-action-resummarize-topic": "প্রসঙ্গের সারাংশ সম্পাদনা করুন",
"flow-topic-action-update-topic-summary": "হালনাগাদের সারসংক্ষেপ",
+ "flow-topic-action-undo-moderation": "পূর্বাবস্থায় ফেরাও",
"flow-board-notification-subscribe-title": "{{GENDER:$1|আপনি}} এই আলোচনা বোর্ডে সদস্যতা নিয়েছেন!",
"flow-topic-action-watchlist-add": "এই প্রসঙ্গে সদস্যতা নিন",
"flow-topic-action-watchlist-remove": "সদস্যতা ত্যাগ",
"flow-error-topic-is-locked": "এই প্রসঙ্গটি মিমাংসিত হয়েছে, তাই অতিরিক্ত কার্যকলাপ সম্ভব নয়।",
"flow-error-lock-moderated-post": "আপনি একটি মডারেটকৃত প্রকাশনা মিমাংসিত হিসাবে চিহ্নিত করতে পারবেন না।",
"flow-error-missing-summary": "আপনাকে অবশ্যই সারাংশ লিখতে হবে।",
+ "flow-error-protected-unknown-reason": "অজানা",
"flow-error-missing-header-content": "আপনাকে অবশ্যই একটি বিবরণ দিতে হবে।",
+ "flow-error-default": "একটি ত্রুটি দেখা দিয়েছে।",
"flow-error-invalid-topic-uuid-title": "খারাপ শিরোনাম",
"flow-error-unknown-workflow-id-title": "অজানা প্রসঙ্গ",
"flow-error-unknown-workflow-id": "অনুরোধকৃত প্রসঙ্গ বিদ্যমান নেই।",
@@ -89,41 +109,87 @@
"flow-edit-header-submit": "বিবরণ সংরক্ষণ",
"flow-edit-title-submit": "শিরোনাম সংরক্ষণ",
"flow-edit-post-submit": "পরিবর্তন জমা দিন",
+ "flow-rev-message-edit-post": "$1 \"$4\"-এ একটি [$3 মন্তব্য] {{GENDER:$2|সম্পাদনা করেছেন}}",
+ "flow-rev-message-reply": "$1 \"$4\"-এ [$3 {{GENDER:$2|মন্তব্য করেছেন}}] (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1টি {{PLURAL:$1|মন্তব্য}}</strong> যোগ করা {{PLURAL:$1|হয়েছিল}}",
+ "flow-rev-message-new-post": "$1 প্রসঙ্গটি {{GENDER:$2|তৈরি করেছেন}} \"[$3 $4]\"",
"flow-rev-message-new-post-recentchanges-summary": "নতুন প্রসঙ্গ {{GENDER:$2|তৈরি হয়েছে}}",
+ "flow-rev-message-lock-topic-reason": "মিমাংসিত হিসেবে চিহ্নিত করুন",
"flow-rev-message-restore-topic-reason": "পুনঃখোলা হয়েছে",
"flow-rc-topic-of-board": "$2-এ $1",
"flow-board-history": "\"$1\" ইতিহাস",
"flow-topic-history": "\"$1\" প্রসঙ্গের ইতিহাস",
+ "flow-history-last4": "শেষ ৪ ঘণ্টায়",
"flow-history-day": "আজ",
"flow-history-week": "গত সপ্তাহ",
"flow-topic-comments": "{{PLURAL:$1|$1টি মন্তব্য|0={{GENDER:$2|সবার প্রথমে}} মন্তব্য করুন!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|মন্তব্য দেখুন|মন্তব্যগুলি দেখুন}}",
"flow-hide-comments-title": "{{PLURAL:$1|মন্তব্য লুকান}}",
"flow-comment-deleted": "মন্তব্য অপসারিত হয়েছে",
+ "flow-last-modified": "সর্বশেষ সম্পাদিত $1",
+ "notification-header-flow-new-topic-v2": "<strong>$3</strong>-এ নতুন প্রসঙ্গ তৈরি করা হয়েছে: <bdi>\"<strong>$4</strong>\"</bdi>।",
+ "notification-header-flow-post-reply": "$1 \"<strong>$4</strong>\"-এ {{GENDER:$2|উত্তর দিয়েছেন}}।",
+ "notification-bundle-header-flow-post-reply-v2": "\"<strong>$3</strong>\"-এ {{PLURAL:$1|একটি নতুন উত্তর|$1টি নতুন উত্তর|100=৯৯টি+ নতুন উত্তর}} রয়েছে।",
+ "notification-email-batch-body-flow-summary-edited": "$1 $2-এ সারাংশ {{GENDER:$1|হালনাগাদ করেছেন}}।",
+ "notification-header-flow-mention-post-summary": "$1 \"<strong>$5</strong>\"-এ {{GENDER:$$2|আপনাকে}} {{GENDER:$4|উল্লেখ করেছেন}}।",
+ "notification-links-flow-description-edited-view-page": "পাতা {{GENDER:$1|দেখুন}}",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 <strong>$3</strong>-এ একটি নতুন প্রসঙ্গ {{GENDER:$1|তৈরি করেছেন}}।",
"flow-notification-link-text-view-post": "প্রকাশনা দেখুন",
"flow-notification-link-text-view-topic": "প্রসঙ্গ দেখুন",
+ "flow-notification-link-text-view-topics": "প্রসঙ্গ দেখুন",
"flow-notification-reply-email-subject": "$3-এ $2",
- "echo-category-title-flow-discussion": "ফ্লো",
- "echo-pref-tooltip-flow-discussion": "ফ্লোতে যখন আমার সম্পর্কিত কর্ম সঞ্চালন হবে তখন আমাকে বিজ্ঞপ্তি দাও",
+ "flow-notification-newtopic-email-subject": "$1 $2-এ একটি নতুন প্রসঙ্গ {{GENDER:$1|তৈরি করেছেন}}",
+ "flow-notification-newtopic-email-batch-bundle-body": "$2-এ {{PLURAL:$1|একটি নতুন প্রসঙ্গ|$1টি নতুন প্রসঙ্গ|100=৯৯টি+ নতুন প্রসঙ্গ}}",
+ "echo-category-title-flow-discussion": "কাঠামোবদ্ধ আলোচনা",
+ "echo-pref-tooltip-flow-discussion": "আমার অনুসারিত প্রসঙ্গ বা পাতার কর্মকান্ড সম্পর্কে আমাকে বিজ্ঞপ্তি দাও।",
"flow-link-post": "প্রকাশনা",
"flow-link-topic": "প্রসঙ্গ",
"flow-link-history": "ইতিহাস",
"flow-moderation-confirm-delete-post": "অপসারণ",
"flow-moderation-confirm-hide-post": "আড়াল করো",
- "flow-moderation-confirmation-suppress-post": "প্রকাশনাটি সফলভাবে গোপন করা হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া {{GENDER:$2|জানাতে}} বিবেচনা করুন।",
- "flow-moderation-confirmation-delete-post": "প্রকাশনাটি সফলভাবে অপসারণ করা হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া {{GENDER:$2|জানাতে}} বিবেচনা করুন।",
- "flow-moderation-confirmation-hide-post": "প্রকাশনাটি সফলভাবে লুকানো হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া জানাতে {{GENDER:$2|বিবেচনা করুন}}।",
+ "flow-moderation-confirm-delete-topic": "অপসারণ",
+ "flow-moderation-confirm-hide-topic": "আড়াল করো",
+ "flow-moderation-confirmation-suppress-post": "প্রকাশনাটি গোপন করা হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া {{GENDER:$2|জানাতে}} বিবেচনা করুন।",
+ "flow-moderation-confirmation-delete-post": "প্রকাশনাটি অপসারণ করা হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া {{GENDER:$2|জানাতে}} বিবেচনা করুন।",
+ "flow-moderation-confirmation-hide-post": "প্রকাশনাটি লুকানো হয়েছে। \nএই প্রকাশনায় $1 কে প্রতিক্রিয়া জানাতে {{GENDER:$2|বিবেচনা করুন}}।",
"flow-moderation-confirmation-suppress-topic": "প্রসঙ্গটি গোপন করা হয়েছে।",
"flow-moderation-confirmation-delete-topic": "প্রসঙ্গটি অপসারণ করা হয়েছে।",
"flow-moderation-confirmation-hide-topic": "প্রসঙ্গটি লুকানো হয়েছে।",
- "action-flow-create-board": "যে কোনো স্থানে ফ্লো বোর্ড তৈরি করুন",
+ "action-flow-create-board": "যে কোনো স্থানে কাঠামোবদ্ধ আলোচনা বোর্ড তৈরি করুন",
+ "flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\" ক্লিক করার দ্বারা, আপনি এই উইকি ব্যবহারের শর্তাবলীর সাথে সম্মত হন।",
+ "flow-topic-html-title": "$2-এ $1",
+ "flow-topic-count": "প্রসঙ্গ ($1টি)",
+ "flow-load-more": "আরও লোড করুন",
+ "flow-newest-topics": "নতুন প্রসঙ্গ",
"flow-terms-of-use-summarize": "\"{{int:flow-topic-action-update-topic-summary}}\" ক্লিক করার দ্বারা, আপনি এই উইকি ব্যবহারের শর্তাবলীর সাথে সম্মত হন।",
- "flow": "ফ্লো",
- "flow-special-enableflow-legend": "একটি নতুন পাতায় ফ্লো সক্রিয় করুন",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] দেখুন",
+ "flow-terms-of-use-lock-topic": "\"{{int:flow-topic-action-lock-topic}}\" ক্লিক করার দ্বারা, আপনি এই উইকি ব্যবহারের শর্তাবলীর সাথে সম্মত হন।",
+ "flow-terms-of-use-unlock-topic": "\"{{int:flow-topic-action-unlock-topic}}\" ক্লিক করার দ্বারা, আপনি এই উইকি ব্যবহারের শর্তাবলীর সাথে সম্মত হন।",
+ "structureddiscussions": "কাঠামোবদ্ধ আলোচনা",
+ "flow-special-enableflow-legend": "একটি নতুন পাতায় কাঠামোবদ্ধ আলোচনা সক্রিয় করুন",
+ "flow-importer-lqt-converted-template": "LQT পাতা কাঠামোবদ্ধ আলোচনায় রূপান্তরিত হয়েছে",
"flow-edited": "সম্পাদিত",
"flow-edited-by": "$1 দ্বারা সম্পাদিত",
- "group-flow-bot": "ফ্লো বট",
- "grouppage-flow-bot": "Project:ফ্লো বট",
- "flow-ve-mention-template-title": "প্রবাহউল্লেখ"
+ "flow-previous-diff": "← পুরনো সম্পাদনা",
+ "flow-next-diff": "নতুনতর সম্পাদনা →",
+ "flow-undo": "পূর্বাবস্থায় আনো",
+ "flow-undo-latest-revision": "সর্বশেষ সংস্করণ",
+ "flow-undo-your-text": "আপনার লেখা",
+ "flow-undo-edit-header": "বিবরণ সম্পাদনা করছেন",
+ "flow-undo-edit-topic-summary": "প্রসঙ্গের সারাংশ সম্পাদনা করছেন",
+ "group-flow-bot": "কাঠামোবদ্ধ আলোচনা বট",
+ "group-flow-bot-member": "কাঠামোবদ্ধ আলোচনা বট",
+ "grouppage-flow-bot": "Project:কাঠামোবদ্ধ আলোচনা বট",
+ "flow-ve-mention-context-item-label": "উল্লেখ",
+ "flow-ve-mention-inspector-title": "উল্লেখ করুন",
+ "flow-ve-mention-inspector-remove-label": "সরান",
+ "flow-ve-mention-placeholder": "ব্যবহারকারী নাম",
+ "flow-ve-mention-tool-title": "একজন ব্যবহারকারীকে উল্লেখ করুন",
+ "flow-ve-mention-template-title": "প্রবাহউল্লেখ",
+ "flow-ve-mention-inspector-invalid-user": "ব্যবহারকারী নাম \"$1\" নিবন্ধিত নয়।",
+ "flow-wikitext-editor-help": "উইকিলেখা $1।",
+ "flow-talk-page-beta-feature-message": "ব্যবহারকারীর আলাপে কাঠামোবদ্ধ আলোচনা",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|আপনি}} কি নিশ্চিত?",
+ "flow-dialog-cancelconfirm-keep": "সম্পাদনা অব্যাহত রাখুন",
+ "flow-dialog-cancelconfirm-discard": "পরিবর্তন বাতিল করুন",
+ "flow-guidedtour-optin-feedback": "আমাদের {{GENDER:$1|আপনার}} প্রতিক্রিয়া জানান!"
}
diff --git a/Flow/i18n/br.json b/Flow/i18n/br.json
index 0468931d..c143e4b2 100644
--- a/Flow/i18n/br.json
+++ b/Flow/i18n/br.json
@@ -2,10 +2,15 @@
"@metadata": {
"authors": [
"Fohanno",
- "Y-M D"
+ "Y-M D",
+ "Nnemo",
+ "Fulup"
]
},
+ "enablestructureddiscussions": "Gweredekaat Flow",
"flow-user-moderated": "Implijer habaskaet",
+ "flow-board-collapse-description": "Kuzhat an deskrivadur",
+ "flow-board-expand-description": "Diskouez an deskrivadur",
"flow-edit-header-link": "Aozañ an talbenn",
"flow-post-moderated-toggle-hide-show": "Diskouez an evezhiadenn {{GENDER:$1|kuzhet}} gant $2",
"flow-post-moderated-toggle-delete-show": "Diskouez an evezhiadenn {{GENDER:$1|dilamet}} gant $2",
@@ -24,7 +29,6 @@
"flow-post-actions": "Oberoù",
"flow-topic-actions": "Oberoù",
"flow-cancel": "Nullañ",
- "flow-preview": "Rakwelet",
"flow-show-change": "Diskouez ar c'hemmoù",
"flow-last-modified-by": "{{GENDER:$1|kemmet}} da ziwezhañ gant $1",
"flow-newtopic-title-placeholder": "Kaoz nevez",
@@ -34,10 +38,10 @@
"flow-newtopic-start-placeholder": "Kregiñ gant ur gaoz nevez",
"flow-summarize-topic-placeholder": "Diverrit an diviz-mañ, mar plij",
"flow-reply-topic-title-placeholder": "Respont da \"$1\"",
- "flow-reply-submit": "{{GENDER:$1|Respont}}",
"flow-reply-link": "{{GENDER:$1|Respont}}",
"flow-thank-link": "{{GENDER:$1|Trugarez}}",
- "flow-post-edited": "Kemennadenn {{GENDER:$1|aozet}} gant $1 $2",
+ "flow-history-action-hide-post": "kuzhat",
+ "flow-post-edited": "Kemennadenn {{GENDER:$1|kemmet}} gant $1 $2",
"flow-post-action-view": "Peurliamm",
"flow-post-action-post-history": "Istor",
"flow-post-action-suppress-post": "Lemel",
@@ -47,6 +51,7 @@
"flow-post-action-edit-post-submit": "Enrollañ ar c'hemmoù",
"flow-post-action-unhide-post": "Diguzhat",
"flow-post-action-restore-post": "Assevel",
+ "flow-post-action-undo-moderation": "Dizober",
"flow-topic-action-view": "Peurliamm",
"flow-topic-action-watchlist": "Roll evezhiañ",
"flow-topic-action-edit-title": "Kemmañ an titl",
@@ -57,16 +62,10 @@
"flow-topic-action-suppress-topic": "Dilemel ar gaoz",
"flow-topic-action-restore-topic": "Assevel ar gaoz",
"flow-topic-action-undo-moderation": "Dizober",
- "flow-error-other": "Ur fazi dic'hortoz zo bet.",
- "flow-error-external": "Ur fazi zo bet.<br />Ar gemennadenn fazi resevet a oa : $1",
- "flow-error-edit-restricted": "N'oc'h ket aotreet da aozañ ar gemennadenn-mañ.",
- "flow-error-external-multi": "Fazioù zo bet.<br />$1",
- "flow-error-delete-failure": "C'hwitet eo bet diverkadenn an elfenn-mañ",
- "flow-error-hide-failure": "N'eus ket bet gallet kuzhat an elfenn-mañ.",
+ "flow-error-external": "Ur fazi zo bet. <br />Ar gemennadenn fazi resevet a oa : $1",
"flow-error-default": "C'hoarvezet ez eus ur fazi.",
"flow-error-invalid-topic-uuid-title": "Titl fall",
"flow-edit-header-submit": "Enrollañ an talbenn",
- "flow-summarize-topic-submit": "Diverrañ",
"flow-edit-title-submit": "Cheñch an titl",
"flow-edit-post-submit": "Kas ar c'hemmoù",
"flow-rev-message-create-header": "$1 {{GENDER:$2|en deus|he deus}} krouet an talbenn.",
@@ -82,8 +81,8 @@
"flow-comment-moderated": "Evezhiadenn habaskaet",
"flow-last-modified": "Kemm diwezhañ war-dro $1",
"flow-notification-link-text-view-post": "Gwelet ar gemennadenn",
- "flow-notification-reply-email-subject": "$1 {{GENDER:$1|en deus|he deus}} respontet d'ho kemennadenn",
- "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|en deus|he deus}} respontet d'ho kemennadenn e-barzh $2 war \"$3\"",
+ "flow-notification-reply-email-subject": "$2 war $3",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|en deus|he deus}} respontet da \"$2\" war $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|en deus|he deus}} meneget ac'hanoc'h war $2",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|en deus|he deus}} aozet ur gemennadenn",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|en deus|he deus}} aozet ur gemennadenn e-barzh $2 war \"$3\"",
@@ -103,13 +102,9 @@
"flow-moderation-confirm-delete-topic": "Diverkañ",
"flow-moderation-confirm-hide-topic": "Kuzhat",
"flow-moderation-confirm-unhide-topic": "Diguzhat",
- "flow-topic-collapsed-one-line": "Gwel bihan",
- "flow-topic-complete": "Gwel klok",
"flow-load-more": "Kargañ muioc'h",
"flow-special-type": "Seurt",
"flow-special-type-post": "Postañ",
"flow-special-uuid": "UUID",
- "flow-preview-return-edit-post": "Kenderc'hel da aozañ",
- "flow-anonymous": "Dizanv",
"flow-embedding-unsupported": "An divizoù ne c'hallont ket bezañ enframmet c'hoazh."
}
diff --git a/Flow/i18n/bs.json b/Flow/i18n/bs.json
index 7029e6a8..b820dc94 100644
--- a/Flow/i18n/bs.json
+++ b/Flow/i18n/bs.json
@@ -4,24 +4,48 @@
"DzWiki",
"Semso98",
"Srdjan m",
- "Milicevic01"
+ "Milicevic01",
+ "Nnemo",
+ "Matiia",
+ "Macofe",
+ "KWiki"
]
},
- "enableflow": "Uključi Flow",
- "flow-desc": "Sistem za upravljanje radnog toka",
- "log-name-flow": "Flow zapisnik",
+ "enablestructureddiscussions": "Uključi Strukturirane rasprave",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Prestani}} pratiti novu aktivnost na \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Više {{GENDER:$3|ne pratite}} stranicu \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Ovo neće utjecati na pojedinačne teme koje {{GENDER:$3|pratite}}. Možete pratiti [$2 ovu stranicu] u bilo kom trenutku.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Prestani}} pratiti ovu temu",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Više {{GENDER:$3|ne pratite}} \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Možete}} pratiti [$2 ovu temu] u bilo kom trenutku.",
+ "flow-desc": "Sistem za raspravu",
+ "flow-talk-taken-over-comment": "/* Ova stranica je pretvorena u Flow raspravu */",
+ "log-name-flow": "Zapisnik Strukturiranih rasprava",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|obrisao|obrisala}} je [$4 objavu] o \"[[$3|$5]]\" na [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|obrisao|obrisala}} je objavu na temi na [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|vratio|vratila}} je [$4 objavu] o \"[[$3|$5]]\" na [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|vratio|vratila}} je objavu na temi na [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|sakrio|sakrila}} je [$4 objavu] o \"[[$3|$5]]\" na [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|sakrio|sakrila}} je objavu na temi na [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|obrisao|obrisala}} je [$4 objavu] o \"[[$3|$5]]\" na [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|obrisao|obrisala}} je objavu na temi na [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|obrisao|obrisala}} je temu \"[[$3|$5]]\" na [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|obrisao|obrisala}} je temu na [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|vratio|vratila}} je temu \"[[$3|$5]]\" na [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|vratio|vratila}} je temu na [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|sakrio|sakrila}} je temu \"[[$3|$5]]\" na [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|sakrio|sakrila}} je temu na [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|obrisao|obrisala}} je temu \"[[$3|$5]]\" na [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|obrisao|obrisala}} je temu na [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|označio|označila}} je temu \"[[$3|$5]]\" kao riješenu na [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|označio|označila}} je temu kao riješenu na [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|ponovo je otvorio|ponovo je otvorila}} temu \"[[$3|$5]]\" na [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 ponovo je {{GENDER:$2|otvorio|otvorila}} temu na [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] o [[$3]] je uvezena sa LiquidThreads na Flow",
"flow-user-moderated": "Moderirani korisnik",
"flow-board-header-browse-topics-link": "Pregledaj teme",
"flow-board-header": "O ovoj stranici",
+ "flow-board-description-can-not-edit": "Ne može se mijenjati",
"flow-board-collapse-description": "Sakrij opis",
"flow-board-expand-description": "Prikaži opis",
"flow-topic-collapse-siderail": "Čitaj u punoj širini",
@@ -47,23 +71,25 @@
"flow-post-actions": "Radnje",
"flow-topic-actions": "Radnje",
"flow-cancel": "Otkaži",
- "flow-skip-summary": "Preskoči sažetak",
+ "flow-skip-summary": "Preskoči",
"flow-edit-summary-placeholder": "Kratko opišite ishod rasprave",
"flow-summary-authored": "Opis {{GENDER:$1|napisao|napisala}} $1",
"flow-summary-edited": "Posljednju izmjenu opisu {{GENDER:$1|učinio|učinila}} $1",
"flow-show-change": "Prikaži izmjene",
"flow-last-modified-by": "Posljednju izmjenu {{GENDER:$1|učinio|učinila}} $1",
- "flow-stub-post-content": "\"Nije moguće preuzeti ovu objavu zbog tehničke greške.\"",
+ "flow-stub-post-content": "<em>Nije moguće preuzeti ovu objavu zbog tehničke greške.</em>",
"flow-newtopic-title-placeholder": "Nova tema",
"flow-newtopic-content-placeholder": "Dodaj novu poruku na stranici \"$1\"",
"flow-newtopic-header": "Dodaj novu temu",
"flow-newtopic-save": "Dodaj temu",
+ "flow-newtopic-save-anonymously": "Anonimno dodaj temu",
"flow-newtopic-start-placeholder": "Započni novu temu",
"flow-newtopic-first-heading": "Dodaj novu temu na stranici $1",
- "flow-summarize-topic-placeholder": "Molimo da rezimirajte ovu raspravu",
+ "flow-summarize-topic-placeholder": "Molimo da rezimirate ovu raspravu",
"flow-reply-topic-placeholder": "{{GENDER:$1|Komentiraj}} na \"$2\"",
"flow-reply-topic-title-placeholder": "Odgovori na \"$1\"",
"flow-reply-link": "{{GENDER:$1|Odgovori}}",
+ "flow-reply-link-anonymously": "Odgovori anonimno",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Zahvali se}}}}",
"flow-thank-link-title": "Javno {{GENDER:$1|{{GENDER:$2|se zahvali}}}} autoru objave",
"flow-history-action-suppress-post": "sakrij",
@@ -75,6 +101,7 @@
"flow-history-action-restore-post": "vrati",
"flow-history-action-lock-topic": "riješeno",
"flow-history-action-unlock-topic": "ponovo otvori",
+ "flow-post-interaction-separator": "&#32;•&#32;",
"flow-post-edited": "Objavu {{GENDER:$1|uredio|uredila}} $1 $2",
"flow-post-action-view": "Trajni link",
"flow-post-action-post-history": "Historija",
@@ -83,6 +110,7 @@
"flow-post-action-hide-post": "Sakrij",
"flow-post-action-edit-post": "Uredi",
"flow-post-action-edit-post-submit": "Sačuvaj izmjene",
+ "flow-post-action-edit-post-submit-anonymously": "Anonimno sačuvaj izmjene",
"flow-post-action-unsuppress-post": "Otkrij",
"flow-post-action-undelete-post": "Vrati",
"flow-post-action-unhide-post": "Prikaži",
@@ -109,28 +137,25 @@
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Primat}} ćete objavještenja o svim aktivnostima oko ove teme.",
"flow-board-notification-subscribe-title": "{{GENDER:$1|Pretplaćeni}} ste na ovu stranicu za raspravu!",
"flow-board-notification-subscribe-description": "{{GENDER:$1|Primat}} ćete objavještenje kad se nova tema doda na ovu stranicu za raspravu.",
- "flow-topic-action-watchlist-add": "Pretplati se na ovu temu",
- "flow-topic-action-watchlist-remove": "Otkaži pretplatu",
- "flow-error-allowcreation-no-usedb": "allowCreation zahtjeva da <var>$wgContentHandlerUseDB</var> bude vrijednosti <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Stranica već postoji, a zahtjeva se da ne postoji",
+ "flow-topic-action-watchlist-add": "Prati ovu temu",
+ "flow-topic-action-watchlist-remove": "Prestani pratiti",
+ "flow-error-allowcreation-no-usedb": "Uključivanje Flowa na specifičnoj stranici zahtijeva da <var>$wgContentHandlerUseDB</var> bude vrijednosti <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Stranica već postoji na odredištu, tako da nije moguće premjestiti Flow na to mjesto.",
"flow-error-allowcreation-flow-create-board": "Korisnik nema \"{{int:right-flow-create-board}}\" dozvolu",
+ "flow-error-can-not-edit-logged-out": "Trenutno ne možete učestvovati. Prijavite se.",
+ "flow-error-can-not-edit-logged-in": "Trenutno ne možete učestvovati zato što nemate potrebna prava.",
"flow-error-http": "Došlo je do greške pri kontaktiranju servera.",
- "flow-error-other": "Došlo je do neočekivane greške.",
- "flow-error-external": "Došlo je do greške.<br />Primljenja je sljedeća dijagnostička poruka: $1",
+ "flow-error-external": "Došlo je do greške. Primljenja je sljedeća dijagnostička poruka: $1",
"flow-error-topic-is-locked": "Ova tema je riješena, tako da daljnja aktivnost nije moguća.",
"flow-error-lock-moderated-post": "Moderiranu objavu ne možete označiti kao riješenu.",
- "flow-error-external-multi": "Došlo je do grešaka.<br />$1",
"flow-error-missing-content": "Objava nema sadržaja. Sadržaj je potreban da bi se objava sačuvala.",
- "flow-error-missing-summary": "Rezime nema sadržaja. Sadržaj je potreban da bi se rezime sačuvao.",
+ "flow-error-missing-summary": "Morate postaviti rezime.",
"flow-error-missing-title": "Tema nema naslov. Naslov je potreban da bi se tema sačuvala.",
- "flow-error-parsoid-failure": "Sadržaj se ne može raščlaniti zbog greške u Parsoidu.",
+ "flow-error-parsoid-failure": "Sadržaj se ne može prebaciti: Greška u uspostavljanju veze prema serveru za pretvaranje wikiteksta u HTML i obrnuto. Provjerite svoju internetsku vezu ili pokušajte ponovo kasnije ako se problem nastavi. Ako i dalje vidite ovu grešku, molimo Vas da je prijavite.",
+ "flow-error-protected-unknown-reason": "Nepoznato",
"flow-error-missing-replyto": "Nije naveden parametar \"replyTo\". Ovaj parametar se zahtjeva za odgovor.",
- "flow-error-invalid-replyto": "Nevedeni \"replyTo\" parametar je nevažeći. Nevedena objava se ne može pronaći.",
- "flow-error-delete-failure": "Brisanje ove stavke nije uspjelo.",
- "flow-error-hide-failure": "Skrivanje ove stavke nije uspjelo.",
"flow-error-missing-postId": "Nije pronađen parametar \"postId\". Ovaj parametar se zahtjeva za rad sa objavom.",
"flow-error-invalid-postId": "Nevedeni \"postId\" parametar je nevažeći. Nevedena objava ($1) se ne može pronaći.",
- "flow-error-restore-failure": "Vraćanje ove stavke nije uspjelo.",
"flow-error-invalid-moderation-state": "Flow API je primio nevažeću vrijednost za parametar ('moderationState').",
"flow-error-invalid-moderation-reason": "Navedite razlog za moderaciju.",
"flow-error-not-allowed": "Nedovoljna ovlaštenja za izvršenje ove radnje.",
@@ -148,7 +173,7 @@
"flow-error-title-too-long": "Naslovi tema su ograničeni na $1 {{PLURAL:$1|bajt|bajta|bajtova}}.",
"flow-error-no-existing-workflow": "Ovaj radni tok još ne postoji.",
"flow-error-not-a-post": "Naslov teme se ne može sačuvati kao objava.",
- "flow-error-missing-header-content": "Opis nema sadržaj. Morate navesti neki sadržaj da biste sačuvali opis.",
+ "flow-error-missing-header-content": "Morate postaviti opis.",
"flow-error-missing-prev-revision-identifier": "Nedostaje prethodni identifikator verzije.",
"flow-error-prev-revision-mismatch": "Neko je uredio ovu objavu prije nekoliko sekundi. {{GENDER:$3|Jeste}} li sigurni da želite pisati preko najnovije izmjene?",
"flow-error-prev-revision-does-not-exist": "Prethodna verzija se ne može naći.",
@@ -159,14 +184,31 @@
"flow-error-fail-load-history": "Neuspjelo učitavanje historijskog sadržaja.",
"flow-error-missing-revision": "Nije moguće pronaći verziju za učitavanje Flow sadržaja.",
"flow-error-fail-commit": "Neuspješno čuvanje Flow sadržaja.",
+ "flow-error-insufficient-permission": "Nemate dovoljna ovlaštenja da biste pristupili ovom sadržaju.",
+ "flow-error-revision-comparison": "Prikaz razlika se može prikazati jedino za dvije izmjene koje pripadaju istoj objavi.",
+ "flow-error-missing-topic-title": "Ne mogu pronaći naslov na trenutnoj raspravi.",
+ "flow-error-missing-metadata": "Ne mogu pronaći potrebne metapodatke za ovu izmjenu.",
+ "flow-error-fail-load-data": "Ne mogu učitati zatražene podatke.",
+ "flow-error-invalid-workflow": "Ne mogu učitati zatraženu raspravu.",
+ "flow-error-process-data": "Došlo je do greške prilikom obrađivanja vašeg zahtjeva.",
+ "flow-error-process-wikitext": "Došlo je do greške prilikom pretvaranja HTML-a i wikiteksta.",
+ "flow-error-no-index": "Ne mogu pronaći indeks za obavljanje pretrage podataka.",
+ "flow-error-no-render": "Navedena radnja nije prepoznata.",
"flow-error-no-commit": "Navedenu radnju nije moguće sačuvati.",
+ "flow-error-content-too-long": "Sadržaj je prevelik. Sadržaj nakon proširenja ograničen je na $1 {{PLURAL:$1|bajt|bajta|bajtova}}.",
+ "flow-error-move-topic": "Premještanje stranice s temom trenutno nije moguće.",
"flow-error-invalid-topic-uuid-title": "Loš naslov",
+ "flow-error-invalid-topic-uuid": "Navedeni naslov stranice nije ispravan. Flow automatski pravi stranice u imenskom prostoru Tema.",
"flow-error-unknown-workflow-id-title": "Nepoznata tema",
"flow-error-unknown-workflow-id": "Zahtjevana tema ne postoji.",
+ "flow-error-search": "Ne mogu izvršiti Vašu pretragu zbog privremenog problema. Pokušajte ponovo.",
"flow-edit-header-placeholder": "Opišite ovu stranicu za raspravu",
"flow-edit-header-submit": "Sačuvaj opis",
+ "flow-edit-header-submit-anonymously": "Anonimno sačuvaj opis",
"flow-edit-title-submit": "Promijeni naslov",
+ "flow-edit-title-submit-anonymously": "Anonimno promijeni naslov",
"flow-edit-post-submit": "Sačuvaj izmjene",
+ "flow-edit-post-submit-anonymously": "Anonimno sačuvaj izmjene",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|uredio|uredila}} je [$3 komentar] na \"$4\"",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Uredio|Uredila}} je objavu",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|komentirao|komentirala}}] je na \"$4\" (<em>$5</em>)",
@@ -185,9 +227,10 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|sakrio|sakrila}} je [$4 temu] na \"$6\" (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|obrisao|obrisala}} je [$4 temu] na \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|sakrio|sakrila}} je [$4 temu] na \"$6\" (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|označio|označila}} je [$4 temu] $6 kao riješenu (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|označio|označila}} je [$4 temu] \"$6\" kao riješenu (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "označeno kao riješeno",
"flow-rev-message-restore-topic-reason": "ponovo otvoreno",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|vratio|vratila}} je [$4 temu] \"$6\" (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 na $2",
"flow-board-history": "\"$1\" historija",
"flow-board-history-empty": "Ova stranica trenutno nema historiju.",
@@ -199,16 +242,81 @@
"flow-history-pages-topic": "Nalazi se na [$1 \"$2\" stranici]",
"flow-history-pages-post": "Nalazi se na [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 komentar|$1 komentara|0={{GENDER:$2|Prvi|Prva}} prokomentariši!}}",
+ "flow-show-comments-title": "Pogledaj {{PLURAL:$1|komentar|komentare}}",
+ "flow-hide-comments-title": "Sakrij {{PLURAL:$1|komentar|komentare}}",
"flow-comment-restored": "Vraćeni komentar",
"flow-comment-deleted": "Obrisani komentar",
"flow-comment-hidden": "Skriveni komentar",
"flow-comment-moderated": "Moderirani komentar",
"flow-last-modified": "Posljednji put uređeno prije $1",
"flow-workflow": "radni tok",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|odgovorio|odgovorila}} je na <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i još {{PLURAL:$5|1=jedan korisnik|$5 korisnika|100=više od 99 drugih korisnika}} {{GENDER:$1|odgovorili}} su na <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|uredio|uredila}} je vašu <span class=\"plainlinks\">[$5 objavu]</span> na [[$3|$4]].",
+ "flow-notification-edit-bundle": "$1 i još {{PLURAL:$5|1=jedan korisnik|$5 korisnika|100=više od 99 korisnika}} {{GENDER:$1|uredili}} su <span class=\"plainlinks\">[$4 objavu]</span> u \"$2\" na \"$3\".",
+ "notification-header-flow-new-topic-v2": "Stvorena nova tema na <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Jedan novi odgovor|$1 nova odgovora|$1 novih odgovora|100=Preko 99 novih odgovora}} na <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Stvorena je nova tema na <strong>Vašoj stranici za razgovor</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Jedna nova tema|$1 nove teme|$1 novih tema|100=Preko 99 novih tema}} na <strong>Vašoj stranici za razgovor</strong>.",
+ "notification-header-flow-post-reply": "$1 je {{GENDER:$2|odgovorio|odgovorila}} na temu \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Jedan novi odgovor|$1 nova odgovora|$1 novih odgovora|100=Preko 99 novih odgovora}} na temu \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 je {{GENDER:$2|odgovorio|odgovorila}} na <strong>Vašoj stranici za razgovor</strong> u \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Jedan novi odgovor|$1 nova odgovora|$1 novih odgovora|100=Preko 99 novih odgovora}} na <strong>Vašoj stranici za razgovor</strong> u \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Vaša}} poruka u \"<strong>$1</strong>\" izmijenjena je.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Vaša}} poruka u \"<strong>$1</strong>\" izmijenjena je nekoliko puta.",
+ "notification-header-flow-post-edited-user-talk": "Promijenjena je poruka u \"<strong>$1</strong>\" na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Poruka u \"<strong>$1</strong>\" promijenjena je nekoliko puta na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Tema \"<strong>$1</strong>\" preimenovana je u \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "Tema \"<strong>$1</strong>\" preimenovana je u \"<strong>$2</strong>\" na <strong>{{GENDER:$3|Vašoj}} stranici za razgovor</strong>.",
+ "notification-header-flow-summary-edited": "Ažuriran je rezime teme \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-first": "Tema \"<strong>$1</strong>\" rezimirana je.",
+ "notification-bundle-header-flow-summary-edited": "Rezime teme \"<strong>$1</strong>\" ažuriran je nekoliko puta.",
+ "notification-header-flow-summary-edited-user-talk": "Rezime teme \"<strong>$1</strong>\" ažuriran je na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Napravljen je rezime teme \"<strong>$1</strong>\" na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Rezime teme \"<strong>$1</strong>\" ažuriran je nekoliko puta na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 je {{GENDER:$1|ažurirao|ažurirala}} je rezime teme $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 je {{GENDER:$1|ažurirao|ažurirala}} je rezime teme $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 i još {{PLURAL:$3|1=jedan korisnik|$3 korisnika|100=više od 99 drugih korisnika}} {{GENDER:$1|ažurirao je|ažurirali su}} rezime teme $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|Vas}} je {{GENDER:$2|spomenuo|spomenula}} u \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$4|Vas}} je {{GENDER:$2|spomenuo|spomenula}} u opisu stranice <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$4|Vas}} je {{GENDER:$2|spomenuo|spomenula}} u \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Uključen je novi sistem za razgovor na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-header-flow-description-edited": "Promijenjen je opis stranice <strong>$1</strong>.",
+ "notification-header-flow-description-edited-user-talk": "Promijenjen je opis na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-bundle-header-flow-description-edited": "Opis stranice <strong>$1</strong> promijenjen je nekoliko puta.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Opis stranice promijenjen je nekoliko puta na <strong>{{GENDER:$2|Vašoj}} stranici za razgovor</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Pogledaj}} stranicu",
+ "notification-email-subject-flow-description-edited": "$1 je {{GENDER:$1|uredio|uredila}} opis stranice $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 je {{GENDER:$1|uredio|uredila}} opis na $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 i još {{PLURAL:$3|1=jedan korisnik|$3 korisnika|100=više od 99 drugih korisnika}} {{GENDER:$1|uredio je|uredili su}} opis na $2",
+ "notification-header-flow-topic-resolved": "Tema \"<strong>$1</strong>\" riješena je.",
+ "notification-header-flow-topic-reopened": "Tema \"<strong>$1</strong>\" ponovo je otvorena.",
+ "notification-header-flow-topic-resolved-user-talk": "Tema \"<strong>$1</strong>\" riješena je na <strong>Vašoj stranici za razgovor</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Tema \"<strong>$1</strong>\" ponovo je otvorena na <strong>Vašoj stranici za razgovor</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Tema \"<strong>$2</strong>\" riješena je.",
+ "notification-email-batch-body-flow-topic-resolved": "Tema \"<strong>$2</strong>\" riješena je.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|napravio|napravila}} je novu temu na <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Jedna nova tema|$1 novih tema|100=Više od 99 novih tema}} na <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-rename": "$1 {{GENDER:$1|promijenio|promijenila}} je naslov <span class=\"plainlinks\">[$2 $3]</span> na \"$4\" na [[$5|$6]].",
+ "flow-notification-mention": "$1 {{GENDER:$5|Vas}} je {{GENDER:$1|spomenuo|spomenula}} u svojoj <span class=\"plainlinks\">[$2 objavi]</span> na \"$3\" na \"$4\".",
"flow-notification-link-text-view-post": "Vidi objavu",
"flow-notification-link-text-view-topic": "Vidi temu",
+ "flow-notification-link-text-view-topics": "Pogledaj teme",
"flow-notification-reply-email-subject": "$2 na $3",
- "echo-category-title-flow-discussion": "Flow",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|odgovorio|odgovorila}} je na \"$2\" na $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 i još {{PLURAL:$4|1=jedan korisnik|$4 korisnika|100=više od 99 drugih korisnika}} {{GENDER:$1|odgovorili su}} na \"$2\" na $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|spomenuo|spomenula}} {{GENDER:$3|vas}} je na $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|Vas}} je {{GENDER:$1|spomenuo|spomenula}} u svojoj objavi pod naslovom \"$2\" na stranici $3",
+ "flow-notification-edit-email-subject": "$1 {{GENDER:$1|uredio|uredila}} je objavu",
+ "flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|uredio|uredila}} je objavu na \"$2\" na $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 i još {{PLURAL:$4|1=jedan korisnik|$4 korisnika|100=više od 99 drugih korisnika}} {{GENDER:$1|uredili su}} objavu na \"$2\" na $3",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|preimenovao|preimenovala}} je vašu temu",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|preimenovao|preimenovala}} je vašu temu sa \"$2\" na \"$3\" na $4",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|napravio|napravila}} je novu temu na $2",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|napravio|napravila}} je novu temu naslova \"$2\" na $3",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Jedna nova tema|$1 novih tema|100=preko 99 novih tema}} na $2",
+ "echo-category-title-flow-discussion": "Strukturirana rasprava",
+ "echo-pref-tooltip-flow-discussion": "Obavijesti me o aktivnostima u temama ili stranicama koje pratim.",
"flow-link-post": "objava",
"flow-link-topic": "tema",
"flow-link-history": "historija",
@@ -222,6 +330,12 @@
"flow-moderation-title-unsuppress-post": "Otkrij objavu?",
"flow-moderation-title-undelete-post": "Vrati objavu?",
"flow-moderation-title-unhide-post": "Otkrij objavu?",
+ "flow-moderation-placeholder-suppress-post": "Molimo {{GENDER:$3|objasnite}} zašto skrivate ovu objavu.",
+ "flow-moderation-placeholder-delete-post": "Molimo {{GENDER:$3|objasnite}} zašto brišete ovu objavu.",
+ "flow-moderation-placeholder-hide-post": "Molimo {{GENDER:$3|objasnite}} zašto skrivate ovu objavu.",
+ "flow-moderation-placeholder-unsuppress-post": "Molimo {{GENDER:$3|objasnite}} zašto otkrivate ovu objavu.",
+ "flow-moderation-placeholder-undelete-post": "Molimo {{GENDER:$3|objasnite}} zašto vraćate ovu objavu.",
+ "flow-moderation-placeholder-unhide-post": "Molimo {{GENDER:$3|objasnite}} zašto otkrivate ovu objavu.",
"flow-moderation-confirm-suppress-post": "Sakrij",
"flow-moderation-confirm-delete-post": "Obriši",
"flow-moderation-confirm-hide-post": "Sakrij",
@@ -234,15 +348,129 @@
"flow-moderation-confirm-unsuppress-topic": "Otkrij",
"flow-moderation-confirm-undelete-topic": "Vrati",
"flow-moderation-confirm-unhide-topic": "Otkrij",
+ "flow-moderation-confirmation-suppress-post": "Objava je skrivena.\n{{GENDER:$2|Razmislite o}} pružanju povratnih informacija {{GENDER:$1|korisniku|korisnici}} $1 povodom ove objave.",
+ "flow-moderation-confirmation-delete-post": "Objava je obrisana.\n{{GENDER:$2|Razmislite o}} pružanju povratnih informacija {{GENDER:$1|korisniku|korisnici}} $1 povodom ove objave.",
+ "flow-moderation-confirmation-hide-post": "Objava je skrivena.\n{{GENDER:$2|Razmislite o}} pružanju povratnih informacija {{GENDER:$1|korisniku|korisnici}} $1 povodom ove objave.",
+ "flow-moderation-confirmation-unsuppress-post": "Otkrili se gornju objavu.",
+ "flow-moderation-confirmation-undelete-post": "Vratili ste gornju objavu.",
+ "flow-moderation-confirmation-unhide-post": "Otkrili se gornju objavu.",
+ "flow-moderation-confirmation-suppress-topic": "Ova tema je skrivena.",
+ "flow-moderation-confirmation-delete-topic": "Ova tema je obrisana.",
+ "flow-moderation-confirmation-hide-topic": "Ova tema je skrivena.",
+ "flow-moderation-confirmation-unsuppress-topic": "Otkrili ste ovu temu.",
+ "flow-moderation-confirmation-undelete-topic": "Vratili ste ovu temu.",
+ "flow-moderation-confirmation-unhide-topic": "Otkrili ste ovu temu.",
+ "flow-moderation-title-suppress-topic": "Sakrij temu?",
+ "flow-moderation-title-delete-topic": "Obriši temu?",
+ "flow-moderation-title-hide-topic": "Sakrij temu?",
+ "flow-moderation-title-unsuppress-topic": "Otkrij temu?",
+ "flow-moderation-title-undelete-topic": "Vrati temu?",
+ "flow-moderation-title-unhide-topic": "Otkrij temu?",
+ "flow-moderation-placeholder-suppress-topic": "Molimo {{GENDER:$3|objasnite}} zašto skrivate ovu temu.",
+ "flow-moderation-placeholder-delete-topic": "Molimo {{GENDER:$3|objasnite}} zašto brišete ovu temu.",
+ "flow-moderation-placeholder-hide-topic": "Molimo {{GENDER:$3|objasnite}} zašto skrivate ovu temu.",
+ "flow-moderation-placeholder-unsuppress-topic": "Molimo {{GENDER:$3|objasnite}} zašto otkrivate ovu temu.",
+ "flow-moderation-placeholder-undelete-topic": "Molimo {{GENDER:$3|objasnite}} zašto vraćate ovu temu.",
+ "flow-moderation-placeholder-unhide-topic": "Molimo {{GENDER:$3|objasnite}} zašto otkrivate ovu temu.",
+ "flow-topic-permalink-warning": "Tema je započeta na [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Tema je započeta na [$2 raspravi {{GENDER:$1|korisnika|korisnice}} $1]",
+ "flow-revision-permalink-warning-post": "Ovo je trajni link ka jednoj verziji ove objave.\nOva verzija je objavljena $1.\nMožete vidjeti [$5 po čemu se razlikuje od prethodne verzije] ili možete vidjeti ostale verzije na [$4 historiji objave].",
+ "flow-revision-permalink-warning-post-first": "Ovo je trajni link ka prvoj verziji ove objave.\nNovije verzije možete vidjeti na [$4 historiji objave].",
+ "flow-revision-permalink-warning-postsummary": "Ovo je trajni link ka jednoj verziji sažetka ove objave.\nOva verzija je objavljena $1.\nMožete vidjeti [$5 po čemu se razlikuje od prethodne verzije] ili možete vidjeti ostale verzije na [$4 historiji objave].",
+ "flow-revision-permalink-warning-postsummary-first": "Ovo je trajni link ka prvoj verziji sažetka ove objave.\nNovije verzije možete vidjeti na [$4 historiji objave].",
+ "flow-revision-permalink-warning-header": "Ovo je trajni link ka jednoj verziji opisa ove objave.\nOva verzija je objavljena $1.\nMožete vidjeti [$3 po čemu se razlikuje od prethodne verzije] ili možete vidjeti ostale verzije na [$2 historiji rasprave].",
+ "flow-revision-permalink-warning-header-first": "Ovo je trajni link ka prvoj verziji opisa ove objave.\nNovije verzije možete vidjeti na [$2 historiji rasprave].",
+ "flow-compare-revisions-revision-header": "Verziju {{GENDER:$2|načinio korisnik|načinila korisnica}} $2 $1",
+ "flow-compare-revisions-header-post": "Ova stranica prikazuje izmjene između dvije verzije objave {{GENDER:$3|korisnika|korisnice}} $3 na temi \"[$5 $2]\" na [$4 $1].\nOstale verzije možete vidjeti na [$6 historiji stranice].",
+ "flow-compare-revisions-header-postsummary": "Ova stranica prikazuje izmjene između dvije verzije sažetka teme \"[$4 $2]\" na [$3 $1].\nOstale verzije možete vidjeti na [$5 historiji teme].",
+ "flow-compare-revisions-header-header": "Ova stranica prikazuje {{GENDER:$2|izmjene}} između dvije verzije opisa objave [$3 $1].\nOstale verzije možete vidjeti na [$4 historiji stranice].",
+ "action-flow-create-board": "bilo gdje pravite Flow rasprave",
+ "right-flow-create-board": "Pravljenje Flow rasprava bilo gdje",
+ "right-flow-hide": "Skrivanje tema i objava u Flowu",
+ "right-flow-lock": "Označavanje tema riješenim u Flowu",
+ "right-flow-delete": "Brisanje tema i objava u Flowu",
+ "right-flow-edit-post": "Uređivanje tuđih objava u Flowu",
+ "right-flow-suppress": "Sakrivanje izmjena u Flowu",
"flow-terms-of-use-new-topic": "Klikom na \"{{int:flow-newtopic-save}}\", prihvaćate uslove korištenja na ovom wikiju.",
"flow-terms-of-use-reply": "Klikom na \"{{int:flow-reply-link}}\", prihvaćate uslove korištenja na ovom wikiju.",
+ "flow-terms-of-use-edit": "Čuvanjem izmjena prihvatate uvjete korištenja ovog wikija.",
+ "flow-anon-warning": "Niste prijavljeni. Kako bi se izmjene čuvale pod vaše ime, a ne pod vašu IP adresu, možete se [$1 prijaviti] ili [$2 napraviti korisnički račun].",
+ "flow-cancel-warning": "Upisali ste tekst u ovaj okvir. Jeste li sigurni da ga želite odbaciti?",
+ "flow-topic-first-heading": "Tema na $1",
+ "flow-topic-html-title": "$1 na $2",
+ "flow-topic-count": "Temâ ($1)",
"flow-load-more": "Učitaj više",
+ "flow-no-more-fwd": "Nema starijih tema",
"flow-newest-topics": "Najnovije teme",
"flow-recent-topics": "Nedavno aktivne teme",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Trenutno}} čitate najnovije teme. Kliknite za više opcija sortiranja.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Trenutno}} čitate najaktivnije teme. Kliknite za više opcija sortiranja.",
+ "flow-toggle-small-topics": "Prebaci na umanjeni pregled tema",
+ "flow-toggle-topics": "Prebaci na sâm pregled tema",
+ "flow-toggle-topics-posts": "Prebaci na pregled tema i objava",
"flow-terms-of-use-summarize": "Klikom na \"{{int:flow-topic-action-update-topic-summary}}\", prihvaćate uslove korištenja na ovom wikiju.",
- "apihelp-flow+edit-header-param-content": "Sadržaj opisa.",
- "apihelp-flow+edit-header-example-1": "Uredi opis [[Talk:Sandbox]]",
+ "flow-terms-of-use-lock-topic": "Klikom na \"{{int:flow-topic-action-lock-topic}}\", prihvatate uvjete korištenja ovog wikija.",
+ "flow-terms-of-use-unlock-topic": "Klikom na \"{{int:flow-topic-action-unlock-topic}}\", prihvatate uvjete korištenja ovog wikija.",
+ "flow-whatlinkshere-post": "sa sljedeće [$1 objave]",
+ "flow-whatlinkshere-header": "sa sljedećeg [$1 opisa]",
+ "flow-whatlinkshere-post-summary": "sa sljedećeg [$1 sažetka]",
+ "structureddiscussions": "Strukturirane rasprave",
+ "flow-special-desc": "Ova posebna stranica preusmjerava na Flow raspravu ili na objavu na Flowu ako posjeduje odgovarajući UUID.",
+ "flow-special-type": "Vrsta",
+ "flow-special-type-post": "Objava",
+ "flow-special-type-workflow": "Rasprava",
+ "flow-special-uuid": "UUID",
+ "flow-special-invalid-uuid": "Ne mogu pronaći sadržaj kojem odgovara ova vrsta i UUID.",
+ "flow-special-enableflow-legend": "Uključi Flow na novoj stranici",
+ "flow-special-enableflow-page": "Stranice na koje se uključuje Flow",
+ "flow-special-enableflow-header": "Prvobitni opis Flow rasprave (wikitekst)",
+ "flow-special-enableflow-board-already-exists": "Flow rasprava već postoji na [[$1]].",
+ "flow-special-enableflow-invalid-title": "Naveden je nevažeći naslov stranice",
+ "flow-special-enableflow-board-creation-not-allowed": "Nije vam dozvoljeno da napravite Flow raspravu na [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Postoji LiquidThreads stranica na [[:$1]].",
+ "flow-special-enableflow-confirmation": "Napravili ste Flow raspravu na [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Arhiva %d\n%s/Arhiva%d\n%s/arhiva %d\n%s/arhiva%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Flow Arhiva %d\n%s/FlowArhiva%d",
+ "flow-spam-confirmedit-form": "Molimo da potvrdite da ste čovjek riješavanjem donje sigurnosne provjere: $1",
+ "flow-embedding-unsupported": "Rasprave se još uvijek ne mogu ugraditi.",
+ "mw-ui-unsubmitted-confirm": "Imate izmjena koje niste objavili. Jeste li sigurni da želite napustiti ovu stranicu i izgubiti svoj rad?",
+ "flow-post-undo-hide": "poništeno skrivanje",
+ "flow-post-undo-delete": "poništeno brisanje",
+ "flow-post-undo-suppress": "poništeno skrivanje",
+ "flow-topic-undo-hide": "poništeno skrivanje",
+ "flow-topic-undo-delete": "poništeno brisanje",
+ "flow-topic-undo-suppress": "poništeno skrivanje",
+ "flow-importer-lqt-moved-thread-template": "LQT Moved thread stub pretvoren u Flow",
+ "flow-importer-lqt-moved-thread-template-content": "Objava koju je načinio/-la {{{author}}} premještena je na datum {{{date}}}. Možete je pronaći na [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "LQT stranica pretvorena u Flow",
+ "flow-importer-lqt-converted-template-content": "Prethodna historija stranica arhivirana je na <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> u {{#time: Y-m-d|{{{date}}}}} u svrhu pričuvne kopije.",
+ "flow-importer-lqt-converted-archive-template": "Arhiva pretvorene LQT stranice",
+ "flow-importer-lqt-converted-archive-template-content": "Ova stranica je arhiva LiquidThreadsa. <strong>Ne mijenjajte joj sadržaj</strong>. Bilo kakve komentare možete ostaviti na [[{{{from}}}|trenutnoj stranici za razgovor]].",
+ "flow-importer-wt-converted-template": "Stranica za razgovor u wikitekstu pretvorena u Flow",
+ "flow-importer-wt-converted-template-content": "Prethodna rasprava arhivirana je na <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> na {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Arhiva za pretvorenu stranicu u wikitekst formatu",
+ "flow-importer-wt-converted-archive-template-content": "Ova stranica je arhiva. <strong>Ne mijenjajte joj sadržaj</strong>. Naknadne komentare možete ostaviti na [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|trenutnoj stranici za razgovor]].",
+ "flow-importer-lqt-suppressed-user-template": "Uvezena LQT objava skrivenog korisnika",
+ "flow-importer-lqt-suppressed-user-template-content": "Ova izmjena skrivenog korisnika uvezena je s LiquidThreadsa. Dodjeljena je trenutnom korisniku.",
+ "flow-importer-lqt-different-author-signature-template": "Uvezena LQT objava s drugim potpisom korisnika",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Ovo je objavio/-la korisnik/-ica [[User:{{{authorUser}}}|{{{authorUser}}}]], ali je objavu potpisao/-la [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
+ "flow-edited": "Izmijenjeno",
+ "flow-edited-by": "{{GENDER:$1|Izmijenio|Izmijenila}} $1",
+ "flow-edited-by-header": "Opis stranice za raspravu izmijenio/-la je $1",
+ "flow-edited-by-topic-title": "Naslov teme izmijenio/-la je $1",
+ "flow-lqt-redirect-reason": "Preusmjeravanje zastarjelih objava LiquidThreadsa na pretvorenu Flow objavu",
+ "flow-talk-conversion-move-reason": "Pretvaranje stranice za razgovor u wikitekstu na Flow sa stranice $1",
+ "flow-talk-conversion-archive-edit-reason": "Pretvaranje stranice za razgovor u wikitekstu u Flow",
+ "flow-previous-diff": "← Starija izmjena",
+ "flow-next-diff": "Novija izmjena →",
"flow-undo": "poništi",
+ "flow-undo-latest-revision": "Trenutna verzija",
+ "flow-undo-your-text": "Vaš tekst",
+ "flow-undo-edit-header": "Uređujete opis",
+ "flow-undo-edit-topic-summary": "Uređujete sažetak teme",
+ "flow-undo-edit-post": "Uređujete objavu",
+ "flow-undo-edit-content": "Izmjenu je moguće poništiti. Molimo da ispod uporedite razlike u verzijama kako biste bili sigurni da ovo zaista želite uraditi, te sačuvajte stranicu i izmjene će biti poništene.",
+ "flow-undo-edit-failure": "Ova izmjena se ne može poništiti jer se međuverzije sukobe.",
"group-flow-bot": "Flow botovi",
"group-flow-bot-member": "Flow bot",
"grouppage-flow-bot": "Project:Flow botovi",
@@ -255,12 +483,34 @@
"flow-ve-mention-inspector-invalid-user": "Korisničko ime \"$1\" nije registrirano.",
"flow-wikitext-editor-help": "Wikitekst $1.",
"flow-wikitext-editor-help-and-preview": "Wikitekst $1, te u bilo kojem trenutku možete $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|koristi označavanje]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|koristi označavanje]]",
"flow-wikitext-editor-help-preview-the-result": "vidjeti kako će izgledati",
- "flow-wikitext-switch-editor-tooltip": "Prebaci me na VisualEditor",
+ "flow-wikitext-switch-editor-tooltip": "Prebaci me na vizualno uređivanje",
"flow-ve-switch-editor-tool-title": "Prebaci me na uređivač wikiteksta",
"flow-mark-revision-patrolled-link-text": "Označi ovu stranicu kao patroliranu",
"flow-mark-revision-patrolled-link-title": "Označi ovu stranicu kao patroliranu",
"flow-mark-diff-patrolled-link-text": "Označi kao patrolirano",
- "flow-mark-diff-patrolled-link-title": "Označi kao patrolirano"
+ "flow-mark-diff-patrolled-link-title": "Označi kao patrolirano",
+ "flow-talk-page-beta-feature-message": "Flow na stranici za razgovor",
+ "flow-talk-page-beta-feature-description": "Uključuje novi strukturalni sistem za raspravu na {{GENDER:|Vašoj}} stranicu za razgovor. Flow pojednostavljuje rasprave na stranici za razgovor s jasnim mjestima za unos novih tema i odgovora, te pruža obavještenja o odgovoru na nivou pojedine teme. Postojeće rasprave u wikitekst formatu bit će premještene u arhivu. Ova mogućnost se ne uključuje automatski, već je korisnici moraju sami uključiti. Isključivanjem ove mogućnosti, Flow rasprava će se premjestiti na podstranicu, a prethodna stranica za razgovor će biti vraćena iz arhive.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Vidi}} korisničku stranicu za razgovor",
+ "flow-notification-enabled-on-talkpage-title": "Novi sistem za rasprave uključen je na {{GENDER:$1|vašoj}} stranici za razgovor<br /><small>Flow je sad dostupan na [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Novi sistem za raspravu na stranici $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Novi sistem za raspravu pod imenom Flow, aktiviran je na {{GENDER:$1|Vašoj}} korisničkoj stranici na {{GRAMMAR:dativ|{{SITENAME}}}}. Možete dobiti dodatne informacije, pružiti povratne informacije ili isključiti novi sistem u bilo kojem trenutku tako što ćete otiću u odjeljak za Beta mogućnosti u {{GENDER:$1|svojim}} postavkama.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Dodavanje šablona za arhive",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Uklanjanje šablona za arhive",
+ "flow-dialog-cancelconfirm-title": "Jeste li sigurni?",
+ "flow-dialog-cancelconfirm-message": "Jeste li sigurni da želite odustati prije nego što sačuvate izmjene?",
+ "flow-dialog-cancelconfirm-keep": "Nastavi s uređivanjem",
+ "flow-dialog-cancelconfirm-discard": "Odbaci izmjene",
+ "flow-optin-archive-wikitext": "Premještanje stranice na wikitekstu kako bi se napravilo mjesta za Flow.",
+ "flow-optin-archive-flow-board": "Premještanje Flow stranice kako bi se napravilo mjesta za stranicu na wikitekstu.",
+ "flow-optin-restore-wikitext": "Vraćanje arhivirane stranice u wikitekstu.",
+ "flow-optin-restore-flow-board": "Vraćanje arhivirane Flow stranice.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Dobro došli}} na {{GENDER:$1|svoju}} novu stranicu za razgovor",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Vaša}} stranica za razgovor je mjesto gdje {{GENDER:$1|vas}} drugi urednici mogu kontaktirati. Koristeći Flow jednostavnije je započeti nove teme i pratiti razgovore.",
+ "flow-guidedtour-optin-find-old-conversations": "Pronađi {{GENDER:$1|svoje}} ranije razgovore",
+ "flow-guidedtour-optin-find-old-conversations-description": "Raniji razgovori premješteni su u arhivu.",
+ "flow-guidedtour-optin-feedback": "{{GENDER:$1|Dajte}} nam povratne informacije!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Možete}} dobiti više informacija, pružiti povratne informacije ili isključiti novi sistem u bilo kojem trenutku koristeći odjeljak za Beta mogućnosti u postavkama."
}
diff --git a/Flow/i18n/bxr.json b/Flow/i18n/bxr.json
index 1bdd9c4d..51821ad9 100644
--- a/Flow/i18n/bxr.json
+++ b/Flow/i18n/bxr.json
@@ -3,25 +3,5 @@
"authors": [
"Elvonudinium"
]
- },
- "flow-started-ago-day": "$1 {{PLURAL:$1|үдэр}} урда эхилһэн",
- "flow-started-ago-hour": "$1 {{PLURAL:$1|саг}} урда эхилһэн",
- "flow-started-ago-minute": "$1 {{PLURAL:$1|минута}} урда эхилһэн",
- "flow-started-ago-second": "$1 {{PLURAL:$1|секунда}} урда эхилһэн",
- "flow-started-ago-week": "$1 {{PLURAL:$1|долоо хоног}} урда эхилһэн",
- "flow-edited-ago-day": "$1 {{PLURAL:$1|үдэр}} урда заһабарилагдаһан",
- "flow-edited-ago-hour": "$1 {{PLURAL:$1|саг}} урда заһабарилагдаһан",
- "flow-edited-ago-minute": "$1 {{PLURAL:$1|минута}} урда заһабарилагдаһан",
- "flow-edited-ago-second": "$1 {{PLURAL:$1|секунда}} урда заһабарилагдаһан",
- "flow-edited-ago-week": "$1 {{PLURAL:$1|долоо хоног}} урда заһабарилагдаһан",
- "flow-active-ago-day": "$1 {{PLURAL:$1|үдэр}} урда эдэбхитэй байгаа",
- "flow-active-ago-hour": "$1 {{PLURAL:$1|саг}} урда эдэбхитэй байгаа",
- "flow-active-ago-minute": "$1 {{PLURAL:$1|минута}} урда эдэбхитэй байгаа",
- "flow-active-ago-second": "$1 {{PLURAL:$1|секунда}} урда эдэбхитэй байгаа",
- "flow-active-ago-week": "$1 {{PLURAL:$1|долоо хоног}} урда эдэбхитэй байгаа",
- "flow-time-ago-day": "$1 {{PLURAL:$1|үдэр}} урда",
- "flow-time-ago-hour": "$1 {{PLURAL:$1|саг}} урда",
- "flow-time-ago-minute": "$1 {{PLURAL:$1|минута}} урда",
- "flow-time-ago-second": "$1 {{PLURAL:$1|секунда}} урда",
- "flow-time-ago-week": "$1 {{PLURAL:$1|долоо хоног}} урда"
+ }
}
diff --git a/Flow/i18n/ca.json b/Flow/i18n/ca.json
index 4cedf9a8..53ebdada 100644
--- a/Flow/i18n/ca.json
+++ b/Flow/i18n/ca.json
@@ -12,32 +12,45 @@
"Macofe",
"Annamerida",
"Paucabot",
- "Eduardo Martinez"
+ "Eduardo Martinez",
+ "Nnemo",
+ "Matiia",
+ "Syum90"
]
},
- "enableflow": "Habilita el Flow",
+ "enablestructureddiscussions": "Habilita el Flow",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Deixeu}} de seguir el tema",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Ja}} no seguiu «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Podeu}} seguir [$2 aquest tema] en qualsevol moment.",
"flow-desc": "Sistema de gestió del flux de treball",
+ "flow-talk-taken-over-comment": "/* Aquesta pàgina ha estat convertida a un tauler de discussió Flow */",
"log-name-flow": "Registre d'activitat del Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|ha esborrat}} un [$4 missatge] sobre «[[$3|$5]]» a [[$6]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|ha restaurat}} un [$4 missatge] sobre «[[$3|$5]]» a [[$6]]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|ha suprimit}} un [$4 missatge] sobre «[[$3|$5]]» a [[$6]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|ha eliminat}} un [$4 apunt] sobre «[[$3|$5]]» a [[$6]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|ha esborrat}} un [$4 missatge] sobre «[[$3|$5]]» a [[$6]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|ha esborrat}} un el tema «[[$3|$5]]» de [[$6]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|ha restaurat}} el tema «[[$3|$5]]» de [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ha suprimit}} el tema «[[$3|$5]]» de [[$6]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ha eliminat}} el tema «[[$3|$5]]» de [[$6]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|ha esborrat}} el tema «[[$3|$5]]» de [[$6]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|ha marcat}} el tema «[[$3|$5]]» com a resolt a [[$6]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|ha reobert}} el tema «[[$3|$5]]» a [[$6]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] de [[$3]] ha estat importat de LiquidThreads a Flow",
"flow-user-moderated": "Usuari moderat",
"flow-board-header-browse-topics-link": "Navega els temes",
"flow-board-header": "Sobre aquest tauler",
+ "flow-board-description-can-not-edit": "No modificable",
"flow-board-collapse-description": "Amaga la descripció",
"flow-board-expand-description": "Mostra la descripció",
+ "flow-topic-collapse-siderail": "Mostra a tota l'amplada",
+ "flow-topic-expand-siderail": "Mostra a amplada fixa",
"flow-edit-header-link": "Modifica la descripció",
"flow-post-moderated-toggle-hide-show": "Mostra el comentari {{GENDER:$1|amagat}} per $2",
"flow-post-moderated-toggle-delete-show": "Mostra el comentari {{GENDER:$1|esborrat}} per $2",
- "flow-post-moderated-toggle-suppress-show": "Mostra el comentari {{GENDER:$1|suprimit}} per $2",
+ "flow-post-moderated-toggle-suppress-show": "Mostra el comentari {{GENDER:$1|eliminat}} per $2",
"flow-post-moderated-toggle-hide-hide": "Amaga el comentari {{GENDER:$1|amagat}} per $2",
"flow-post-moderated-toggle-delete-hide": "Amaga el comentari {{GENDER:$1|esborrat}} per $2",
- "flow-post-moderated-toggle-suppress-hide": "Amaga el comentari {{GENDER:$1|suprimit}} per $2",
+ "flow-post-moderated-toggle-suppress-hide": "Amaga el comentari {{GENDER:$1|eliminat}} per $2",
"flow-topic-moderated-reason-prefix": "Motiu:",
"flow-hide-post-content": "Aquest comentari va ser {{GENDER:$1|amagat}} per $1 ([$2 historial])",
"flow-hide-title-content": "Aquest tema de discussió ha estat {{GENDER:$1|amagat}} per $1",
@@ -45,34 +58,36 @@
"flow-delete-post-content": "Aquest comentari va ser {{GENDER:$1|esborrat}} per $1 ([$2 historial])",
"flow-delete-title-content": "Aquest tema de discussió ha estat {{GENDER:$1|esborrat}} per $1",
"flow-delete-header-content": "{{GENDER:$1|Esborrat}} per $2",
- "flow-suppress-post-content": "Aquest comentari va ser {{GENDER:$1|suprimit}} per $1 ([$2 historial])",
+ "flow-suppress-post-content": "Aquest comentari va ser {{GENDER:$1|eliminat}} per $1 ([$2 historial])",
"flow-suppress-title-content": "Aquest tema de discussió ha estat {{GENDER:$1|suprimit}} per $1",
- "flow-suppress-header-content": "{{GENDER:$1|Suprimit}} per $2",
+ "flow-suppress-header-content": "{{GENDER:$1|Eliminat}} per $2",
"flow-suppress-usertext": "<em>Nom d'usuari suprimit</em>",
"flow-post-actions": "Accions",
"flow-topic-actions": "Accions",
"flow-cancel": "Cancel·la",
- "flow-skip-summary": "Salta't el resum",
+ "flow-skip-summary": "Salta",
"flow-edit-summary-placeholder": "Descriviu breument el resultat d'aquesta discussió",
"flow-summary-authored": "Resum per $1",
"flow-summary-edited": "Darrera {{GENDER:$1|edició}} del resum per $1",
"flow-show-change": "Mostra els canvis",
"flow-last-modified-by": "Darrera {{GENDER:$1|modificació}} per $1",
- "flow-stub-post-content": "\"A causa d'un error tècnic, aquesta publicació no s'ha pogut recuperar.\"",
+ "flow-stub-post-content": "<em>A causa d'un error tècnic, aquest apunt no s'ha pogut recuperar.</em>",
"flow-newtopic-title-placeholder": "Nou tema",
"flow-newtopic-content-placeholder": "Envia un missatge nou a «$1»",
"flow-newtopic-header": "Afegir un nou tema",
"flow-newtopic-save": "Afegeix el tema",
+ "flow-newtopic-save-anonymously": "Afegeix el tema de forma anònima",
"flow-newtopic-start-placeholder": "Comenceu un nou tema",
"flow-newtopic-first-heading": "Comença un nou tema sobre $1",
"flow-summarize-topic-placeholder": "Si us plau, resumiu aquesta discussió",
"flow-reply-topic-placeholder": "{{GENDER:$1|Comentari}} a \"$2\"",
"flow-reply-topic-title-placeholder": "Resposta a «$1»",
"flow-reply-link": "{{GENDER:$1|Respon}}",
+ "flow-reply-link-anonymously": "Respon anònimament",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Agraeix}}}}",
"flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Agraïu}}}} l'autor públicament",
- "flow-history-action-suppress-post": "suprimeix",
- "flow-history-action-delete-post": "eliminar",
+ "flow-history-action-suppress-post": "elimina",
+ "flow-history-action-delete-post": "esborrar",
"flow-history-action-hide-post": "amaga",
"flow-history-action-unsuppress-post": "restaura",
"flow-history-action-undelete-post": "restaura",
@@ -83,11 +98,12 @@
"flow-post-edited": "Missatge {{GENDER:$1|modificat}} per $1 $2",
"flow-post-action-view": "Enllaç permanent",
"flow-post-action-post-history": "Historial",
- "flow-post-action-suppress-post": "suprimeix",
- "flow-post-action-delete-post": "Elimina",
+ "flow-post-action-suppress-post": "Elimina",
+ "flow-post-action-delete-post": "Esborra",
"flow-post-action-hide-post": "Amaga",
"flow-post-action-edit-post": "Modifica",
"flow-post-action-edit-post-submit": "Desa els canvis",
+ "flow-post-action-edit-post-submit-anonymously": "Desa els canvis de forma anònima",
"flow-post-action-unsuppress-post": "Restaura",
"flow-post-action-undelete-post": "Restaura",
"flow-post-action-unhide-post": "Mostrar",
@@ -104,7 +120,7 @@
"flow-topic-action-summarize-topic": "Resum",
"flow-topic-action-resummarize-topic": "Modifica el resum del tema",
"flow-topic-action-update-topic-summary": "Actualitza el resum",
- "flow-topic-action-suppress-topic": "Suprimeix el tema",
+ "flow-topic-action-suppress-topic": "Elimina el tema",
"flow-topic-action-unhide-topic": "Mostrar el tema",
"flow-topic-action-undelete-topic": "Restaura el tema",
"flow-topic-action-unsuppress-topic": "Restaura el tema",
@@ -114,21 +130,24 @@
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Rebreu}} notificacions de tota activitat sobre aquest tema.",
"flow-board-notification-subscribe-title": "{{GENDER:$1|Esteu}} subscrit a aquest tauler de discussió!",
"flow-board-notification-subscribe-description": "{{GENDER:$1|Rebreu}} una notificació quan es creï un nou tema en aquest tauler.",
- "flow-error-allowcreation-no-usedb": "allowCreation necessita que <var>$wgContentHandlerUseDB</var> sigui <code>true</code>.",
- "flow-error-allowcreation-already-exists": "La pàgina ja existeix i es necessitava que no ho fos",
+ "flow-topic-action-watchlist-add": "Subscripció a aquest tema",
+ "flow-topic-action-watchlist-remove": "Cancel·la la subscripció",
+ "flow-error-allowcreation-no-usedb": "Per activar Flow en una pàgina determinada es necessita que <var>$wgContentHandlerUseDB</var> sigui <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "La pàgina destinació ja existeix, per tant no s'hi pot moure un tauler Flow.",
"flow-error-allowcreation-flow-create-board": "L'usuari no té el permís «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Ara no podeu participar-hi. Proveu d'iniciar una sessió.",
"flow-error-http": "S'ha produït un error mentre es contactava amb el servidor.",
- "flow-error-other": "S'ha produït un error inesperat.",
- "flow-error-external": "S'ha produït un error.<br />El missatge d'error rebre és: $1",
+ "flow-error-external": "S'ha produït un error. El missatge d'error rebut és: $1",
"flow-error-topic-is-locked": "Aquest tema està resolt, per tant no és possible cap més activitat.",
"flow-error-lock-moderated-post": "No podeu marcar un apunt moderat com a resolt.",
- "flow-error-external-multi": "S'han trobat errors.<br />$1",
"flow-error-missing-content": "La publicació no té contingut. El contingut és necessari per desar una publicació.",
- "flow-error-missing-summary": "El resum no té cap contingut. El contingut és necessari per desar un resum.",
+ "flow-error-missing-summary": "Heu d'introduir un resum.",
"flow-error-missing-title": "El tema no té cap títol. És necessari un títol per desar un tema.",
- "flow-error-delete-failure": "La supressió d'aquest element ha fallat.",
- "flow-error-hide-failure": "Ha fallat amagar aquest fitxer.",
- "flow-error-restore-failure": "La recuperació d'aquest element ha fallat.",
+ "flow-error-parsoid-failure": "No s'ha pogut transferir el contingut: Error en contactar el servidor per a la conversió entre text wiki i HTML. Comproveu la vostra connexió a Internet o intenteu-ho de nou més tard si el problema persisteix. Si encara rebeu aquest error llavors informeu del bug.",
+ "flow-error-protected-unknown-reason": "Desconegut",
+ "flow-error-missing-replyto": "No s'ha proporcionat cap paràmetre «replyTo». Aquest paràmetre és necessari per la acció «reply».",
+ "flow-error-missing-postId": "No s'ha proporcionat cap paràmetre «postId». Aquest paràmetre és necessari per manipular un apunt.",
+ "flow-error-invalid-postId": "El paràmetre «postId» no és vàlid. L'apunt especificat ($1) no s'ha pogut trobar.",
"flow-error-invalid-moderation-reason": "Proporcioneu un motiu per la moderació",
"flow-error-not-allowed": "No teniu permisos suficients per executar l'acció.",
"flow-error-not-allowed-hide": "Aquest tema ha estat amagat.",
@@ -137,29 +156,43 @@
"flow-error-not-allowed-reply-to-delete-topic": "No podeu respondre perquè aquest tema ha estat esborrat",
"flow-error-not-allowed-suppress": "Aquest tema ha estat esborrat.",
"flow-error-not-allowed-reply-to-suppress-topic": "No podeu respondre perquè aquest tema ha estat esborrat.",
+ "flow-error-not-allowed-hide-extract": "Aquest tema ha estat amagat. A continuació es proporciona el registre per a referència.",
+ "flow-error-not-allowed-delete-extract": "Aquest tema ha estat esborrat. A continuació es proporciona el registre d'esborrament del tema per a referència.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "No podeu respondre perquè aquest tema ha estat esborrat. A continuació es proporciona el registre d'esborrament del tema per a referència.",
"flow-error-not-allowed-suppress-extract": "Aquest tema ha estat suprimit. El registre de supressions d'aquest tema es mostra a continuació.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "No podeu respondre perquè el tema ha estat eliminat. A continuació es proporciona el registre d'eliminació per a referència.",
"flow-error-title-too-long": "Els títols dels temes estan limitats a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-not-a-post": "El títol del tema no es pot desar com un apunt.",
- "flow-error-missing-header-content": "La descripció està buida. Per desar una descripció cal afegir algun contingut.",
+ "flow-error-missing-header-content": "Heu d'introduir una descripció.",
+ "flow-error-missing-prev-revision-identifier": "Falta l'identificador de revisió anterior.",
"flow-error-prev-revision-mismatch": "Un altre usuari acaba de modificar aquest apunt fa un moment. {{GENDER:$3|Segur}} que voleu sobreescriure el canvi recent?",
"flow-error-prev-revision-does-not-exist": "No s'ha pogut trobar la revisió anterior.",
+ "flow-error-core-topic-deletion": "Per esborrar un tema, utilitzeu el menú ... del tauler Flow o de la [$1 pàgina del tema]. No accediu directament al tema amb action=delete.",
"flow-error-default": "S'ha produït un error.",
+ "flow-error-invalid-input": "S'ha proporcionat un valor no vàlid per carregar el contingut Flow.",
"flow-error-invalid-title": "S'ha proporcionat un títol de pàgina no vàlid.",
"flow-error-fail-load-history": "Error en carregar l'historial de continguts.",
+ "flow-error-missing-revision": "No s'ha pogut trobar una revisió per carregar el contingut Flow.",
"flow-error-fail-commit": "No s'ha pogut desar el contingut de Flow.",
"flow-error-insufficient-permission": "Permisos insuficients per accedir a aquest contingut.",
"flow-error-revision-comparison": "La visualització de diferències només es pot fer per dos versions del mateix apunt.",
"flow-error-fail-load-data": "Error en carregar les dades sol·licitades.",
+ "flow-error-process-data": "S'ha produït un error en processar les dades de la vostra sol·licitud.",
+ "flow-error-process-wikitext": "S'ha produït un error en processar la conversió HTLM/text wiki.",
"flow-error-no-render": "L’acció especificada no s'ha pogut reconèixer.",
"flow-error-no-commit": "No s'ha pogut desar l'acció especificada.",
"flow-error-content-too-long": "El contingut és massa gran. El contingut després de l'expansió està limitat a $1 {{PLURAL:$1|byte|octets}}.",
+ "flow-error-move-topic": "No és possible actualment reanomenar una pàgina de tema.",
"flow-error-invalid-topic-uuid-title": "El títol no és correcte",
"flow-error-unknown-workflow-id-title": "Tema desconegut.",
"flow-error-unknown-workflow-id": "El tema sol·licitat no existeix.",
"flow-edit-header-placeholder": "Descriviu aquest tauler de discussió",
"flow-edit-header-submit": "Desa la descripció",
+ "flow-edit-header-submit-anonymously": "Desa la descripció de forma anònima",
"flow-edit-title-submit": "Canvia el títol",
+ "flow-edit-title-submit-anonymously": "Canviar el títol de forma anònima",
"flow-edit-post-submit": "Publica els canvis",
+ "flow-edit-post-submit-anonymously": "Envia el canvis de forma anònima",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|ha modificat}} un [$3 comentari] a «$4»",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Ha modificat}} un apunt",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|ha afegit}}] un comentari a «$4» (<em>$5</em>)",
@@ -171,9 +204,14 @@
"flow-rev-message-edit-header": "$1 {{GENDER:$2|ha modificat}} la descripció",
"flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|ha creat}} un resum del tema a $3",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|ha modificat}} el resum del tema $3",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|ha amagat}} un [$4 comentari] a «$6» (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|ha esborrat}} un [$4 comentari] a «$6» (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|ha eliminat}} un [$4 comentari] a «$6» (<em>$5</em>)",
"flow-rev-message-restored-post": "$1 {{GENDER:$2|ha restaurat}} un [$4 comentari] a «$6» (<em>$5</em>)",
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ha amagat}} el [$4 tema] \"$6\" (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|ha marcat}} el [$4 tema] $6 com a resolt (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|ha esborrat}} el [$4 tema] «$6» (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|ha eliminat}} el [$4 tema] «$6» (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|ha marcat}} el [$4 tema] «$6» com a resolt (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "marcat com a resolt",
"flow-rev-message-restore-topic-reason": "reobert",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|ha restaurat}} el [$4 tema] «$6» (<em>$5</em>)",
@@ -181,10 +219,12 @@
"flow-board-history": "Historial de «$1»",
"flow-board-history-empty": "Aquest tauler no té actualment cap historial.",
"flow-topic-history": "Historial del tema «$1»",
+ "flow-post-history": "Historial de l'apunt «comentari de {{GENDER:$2|$2}}»",
"flow-history-last4": "Darreres 4 hores",
"flow-history-day": "Avui",
"flow-history-week": "Darrera setmana",
"flow-history-pages-topic": "Apareix en el [$1 tauler «$2»]",
+ "flow-history-pages-post": "Apareix a [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 comentari|$1 comentaris|0=Sigueu {{GENDER:$2|el primer|la primera}} en comentar!}}",
"flow-show-comments-title": "{{PLURAL:$1|Mostra el comentari|Mostra els comentaris}}",
"flow-hide-comments-title": "{{PLURAL:$1|Amaga el comentari|Amaga els comentaris}}",
@@ -194,29 +234,71 @@
"flow-comment-moderated": "Comentari revisat.",
"flow-last-modified": "Darrera modificació $1",
"flow-workflow": "flux de treball",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|ha contestat}} a '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i $5 {{PLURAL:$6|més}} han {{GENDER:$1|contestat}} a '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|ha contestat}} a <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i {{PLURAL:$5|un altre|$5 més|100=més d'un centenar}} han {{GENDER:$1|contestat}} a <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 ha {{GENDER:$1|modificat}} el vostre <span class=\"plainlinks\">[$5 apunt]</span> a [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 i $5 {{PLURAL:$6|més}} han {{GENDER:$1|modificat}} un <span class=\"plainlinks\">[$4 apunt]</span> de «$2» a «$3».",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|ha creat}} un nou tema a '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nou tema|$1 temes nous|250=+250 temes nous}} a '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 i {{PLURAL:$5|un altre|$5 més|100=més d'un centenar}} han {{GENDER:$1|modificat}} un <span class=\"plainlinks\">[$4 apunt]</span> sobre «$2» a «$3».",
+ "notification-header-flow-new-topic-v2": "Nou tema creat a <strong>$3</strong>: <bdi>«<strong>$4</strong>»</bdi>.",
+ "notification-bundle-header-flow-new-topic": "$1 {{PLURAL:$1|tema nou|temes nous}} a <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Nou tema creat a la <strong>vostra pàgina de discussió</strong>: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "$1 {{PLURAL:$1|nou tema|nous temes}} a la <strong>vostra pàgina de discussió</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|ha respost}} a «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-v2": "$1 {{PLURAL:$1|nova resposta|noves respostes}} a «<strong>$3</strong>».",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|ha publicat}} una resposta en <strong>la vostra pàgina de discussió</strong> sobre «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-user-talk": "$1 {{PLURAL:$1|nova resposta|noves respostes}} a la <strong>vostra pàgina de discussió</strong> sobre «<strong>$3</strong>».",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|El vostre}} apunt sobre «<strong>$1</strong>» ha estat modificat.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|El vostre}} apunt sobre «<strong>$1</strong>» ha estat modificat diverses vegades.",
+ "notification-header-flow-post-edited-user-talk": "Un apunt sobre «<strong>$1<strong>» ha estat modificat en la <strong>{{GENDER:$2|vostra}} pàgina de discussió<strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Un apunt sobre «<strong>$1</strong>» ha estat modificat diverses vegades a la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-header-flow-topic-renamed-v2": "El tema «<strong>$1</strong>» ha estat reanomenat a «<strong>$2</strong>».",
+ "notification-header-flow-topic-renamed-user-talk": "El tema «<strong>$1</strong>» ha estat reanomenat a «<strong>$2</strong>» en la <strong>vostra pàgina de discussió</strong>.",
+ "notification-header-flow-summary-edited": "El resum de «<strong>$1</strong>» ha estat actualitzat.",
+ "notification-header-flow-summary-edited-first": "El tema «<strong>$1</strong>» ha estat resumit.",
+ "notification-bundle-header-flow-summary-edited": "El resum de «<strong>$1</strong>» ha estat actualitzat diverses vegades.",
+ "notification-header-flow-summary-edited-user-talk": "El resum de «<strong>$1</strong>» ha estat actualitzat en la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "El tema «<strong>$1</strong>» ha estat resumit en la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "El resum de «<strong>$1</strong>» ha estat actualitzat diverses vegades en la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|ha actualitzat}} el resum de $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|ha actualitzat}} el resum de $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 i {{PLURAL:$3|un altre|$3 més|100=més d'un centenar}} {{GENDER:$1|han actualitzat}} el resum de $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|us}} ha {{GENDER:$2|mencionat}} a «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$4|us}} ha {{GENDER:$2|mencionat}} en la descripció de <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|us}} ha {{GENDER:$4|mencionat}} en «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Nou sistema de discussió habilitat per la <strong>{{GENDER:$2|vostra}} pàgina de discussió d'usuari</strong>.",
+ "notification-header-flow-description-edited": "La descripció de <strong>$1</strong> ha estat modificada.",
+ "notification-header-flow-description-edited-user-talk": "La descripció ha estat modificada en la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-bundle-header-flow-description-edited": "La descripció de <strong>$1</strong> ha estat modificada diverses vegades.",
+ "notification-bundle-header-flow-description-edited-user-talk": "La descripció ha estat modificada diverses vegades en la <strong>{{GENDER:$2|vostra}} pàgina de discussió</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Mostra}} la pàgina",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|ha modificat}} la descripció de $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|ha modificat}} la descripció de $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 i {{PLURAL:$3|un altre|$3 més|100=més d'un centenar}} {{GENDER:$1|han modificat}} la descripció de $2",
+ "notification-header-flow-topic-resolved": "El tema «<strong>$1</strong>» ha estat resolt.",
+ "notification-header-flow-topic-reopened": "El tema «<strong>$1</strong>» ha estat reobert.",
+ "notification-header-flow-topic-resolved-user-talk": "El tema «<strong>$1</strong>» ha estat resolt en la <strong>vostra pàgina de discussió</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "El tema «<strong>$1</strong>» ha estat reobert en la <strong>vostra pàgina de discussió</strong>.",
+ "notification-email-subject-flow-topic-resolved": "El tema «<strong>$2</strong>» ha estat resolt.",
+ "notification-email-batch-body-flow-topic-resolved": "El tema «<strong>$2</strong>» ha estat resolt.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|ha creat}} un nou tema a <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un nou tema|$1 temes nous|100=Més d'un centenar de temes nous}} a <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|ha modificat}} el títol de <span class=\"plainlinks\">[$2 $3]</span> a «$4», a [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$5|us}} {{GENDER:$1|ha mencionat}} en {{GENDER:$1|el seu}} <span class=\"plainlinks\">[$2 apunt]</span> de \"$3\" a \"$4\".",
"flow-notification-link-text-view-post": "Mostra l'apunt",
"flow-notification-link-text-view-topic": "Mostra el tema",
+ "flow-notification-link-text-view-topics": "Mostra els temes",
"flow-notification-reply-email-subject": "$2 a $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|ha respost}} a «$2» de $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 i $4 {{PLURAL:$5|més}} {{GENDER:$1|han respost}} sobre «$2» a $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 i {{PLURAL:$4|un altre|$4 més|100=més d'un centenar}} {{GENDER:$1|han respost}} a «$2» de $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$3|us}} {{GENDER:$1|ha mencionat}} a $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|us}} {{GENDER:$1|ha mencionat}} en {{GENDER:$1|el seu}} apunt de «$2» a $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|ha modificat}} un apunt",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|ha modificat}} un apunt de «$2» a $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 i $4 {{PLURAL:$5|més}} {{GENDER:$1|han modificat}} un apunt de «$2» a $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 i {{PLURAL:$4|un altre|$4 més|100=més d'un centenar}} {{GENDER:$1|han modificat}} un apunt de «$2» a $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|ha reanomenat}} el vostre tema",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|ha reanomenat}} el tema «$2» a «$3», a $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|ha creat}} un nou tema a $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|ha creat}} un nou tema amb el títol «$2» a $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nou tema|$1 temes nous|250=+250 temes nous}} a $2",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Un nou tema|$1 temes nous|100=Més d'un centenar de temes nous}} a $2",
"echo-category-title-flow-discussion": "Flux de discussió",
"echo-pref-tooltip-flow-discussion": "Notifica'm quan hi hagi accions que em concerneixin en el flux de discussió",
"flow-link-post": "apunt",
@@ -226,30 +308,56 @@
"flow-link-topic-revision": "versió del tema",
"flow-link-header-revision": "versió de la descripció",
"flow-link-summary-revision": "versió del resum",
+ "flow-moderation-title-suppress-post": "Voleu eliminar l'apunt?",
+ "flow-moderation-title-delete-post": "Voleu esborrar l'apunt?",
"flow-moderation-title-hide-post": "Voleu amagar l'apunt?",
+ "flow-moderation-title-unsuppress-post": "Voleu anul·lar l'eliminació de l'apunt?",
+ "flow-moderation-title-undelete-post": "Voleu recuperar l'apunt esborrat?",
+ "flow-moderation-title-unhide-post": "Voleu deixar d'amagar l'apunt?",
"flow-moderation-placeholder-suppress-post": "{{GENDER:$3|Expliqueu}} per què suprimiu aquest apunt.",
"flow-moderation-placeholder-delete-post": "{{GENDER:$3|Expliqueu}} per què esborreu aquest missatge.",
"flow-moderation-placeholder-hide-post": "{{GENDER:$3|Expliqueu}} per què amagueu aquest missatge.",
"flow-moderation-placeholder-unsuppress-post": "{{GENDER:$3|Expliqueu}} per què recupereu aquest missatge.",
"flow-moderation-placeholder-undelete-post": "{{GENDER:$3|Expliqueu}} per què restaureu aquest missatge.",
"flow-moderation-placeholder-unhide-post": "{{GENDER:$3|Expliqueu}} per què mostreu de nou aquest missatge.",
- "flow-moderation-confirm-suppress-post": "Suprimeix",
- "flow-moderation-confirm-delete-post": "Elimina",
+ "flow-moderation-confirm-suppress-post": "Elimina",
+ "flow-moderation-confirm-delete-post": "Esborra",
"flow-moderation-confirm-hide-post": "Amaga",
"flow-moderation-confirm-unsuppress-post": "Restaura",
"flow-moderation-confirm-undelete-post": "Restaura",
"flow-moderation-confirm-unhide-post": "Mostrar",
- "flow-moderation-confirm-suppress-topic": "Suprimir",
- "flow-moderation-confirm-delete-topic": "Elimina",
+ "flow-moderation-confirm-suppress-topic": "Elimina",
+ "flow-moderation-confirm-delete-topic": "Esborra",
"flow-moderation-confirm-hide-topic": "Amaga",
"flow-moderation-confirm-unsuppress-topic": "Restaura",
"flow-moderation-confirm-undelete-topic": "Restaura",
"flow-moderation-confirm-unhide-topic": "Mostra",
+ "flow-moderation-confirmation-suppress-post": "L'apunt ha estat eliminat.\n{{GENDER:$2|Considereu}} comentar amb $1 sobre aquest apunt.",
+ "flow-moderation-confirmation-delete-post": "L'apunt ha estat esborrat.\n{{GENDER:$2|Considereu}} comentar amb $1 sobre aquest apunt.",
+ "flow-moderation-confirmation-hide-post": "L'apunt ha estat amagat.\n{{GENDER:$2|Considereu}} comentar amb $1 sobre aquest apunt.",
+ "flow-moderation-confirmation-unsuppress-post": "Heu anul·lat l'eliminació de l'apunt de més amunt.",
+ "flow-moderation-confirmation-undelete-post": "Heu recuperat l'apunt de més amunt.",
+ "flow-moderation-confirmation-unhide-post": "Heu deixat d'amagar l'apunt de més amunt.",
+ "flow-moderation-confirmation-suppress-topic": "Aquest tema ha estat eliminat.",
"flow-moderation-confirmation-delete-topic": "Aquest tema ha estat esborrat.",
"flow-moderation-confirmation-hide-topic": "Aquest tema ha estat amagat.",
+ "flow-moderation-confirmation-unsuppress-topic": "Heu anul·lat l'eliminació d'aquest apunt.",
+ "flow-moderation-confirmation-undelete-topic": "Heu recuperat aquest apunt.",
+ "flow-moderation-confirmation-unhide-topic": "Heu deixat d'amagar aquest apunt.",
+ "flow-moderation-title-suppress-topic": "Voleu eliminar el tema?",
+ "flow-moderation-title-delete-topic": "Voleu esborrar el tema?",
"flow-moderation-title-hide-topic": "Voleu amagar el tema?",
+ "flow-moderation-title-unsuppress-topic": "Voleu anul·lar l'eliminació del tema?",
+ "flow-moderation-title-undelete-topic": "Voleu recuperar el tema esborrat?",
+ "flow-moderation-title-unhide-topic": "Voleu deixar d'amagar el tema?",
+ "flow-moderation-placeholder-suppress-topic": "{{GENDER:$3|Expliqueu}} per què esteu eliminant aquest tema.",
"flow-moderation-placeholder-delete-topic": "{{GENDER:$3|Expliqueu}} per què esborreu aquest tema.",
"flow-moderation-placeholder-hide-topic": "{{GENDER:$3|Expliqueu}} per què amagueu aquest tema.",
+ "flow-moderation-placeholder-unsuppress-topic": "{{GENDER:$3|Expliqueu}} per què esteu anul·lant l'eliminació d'aquest tema.",
+ "flow-moderation-placeholder-undelete-topic": "{{GENDER:$3|Expliqueu}} per què esteu recuperant aquest tema esborrat.",
+ "flow-moderation-placeholder-unhide-topic": "{{GENDER:$3|Expliqueu}} per què esteu deixant d'amagar aquest tema.",
+ "flow-topic-permalink-warning": "Tema iniciat a [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Tema iniciat en el [$2 tauler de {{GENDER:$1|$1}}]",
"flow-revision-permalink-warning-post": "Aquest és un enllaç permanent a una versió determinada d'aquest apunt.\nAquesta versió és de $1.\nPodeu veure les [$5 diferències amb la versió anterior], o veure altres versions a la [$4 pàgina d'historial de l'apunt].",
"flow-revision-permalink-warning-post-first": "Aquest és un enllaç permanent a la primera versió d'aquest apunt.\nPodeu veure les versions posteriors a la [$4 pàgina d'historial de l'apunt].",
"flow-revision-permalink-warning-postsummary": "Aquest és un enllaç permanent a una versió determinada del resum per a aquest apunt. Aquesta és la versió de $1.\nPodeu veure les [$5 diferències amb la versió anterior], o veure altres versions a la [$4 pàgina d'historial de l'apunt].",
@@ -260,6 +368,13 @@
"flow-compare-revisions-header-post": "Aquesta pàgina mostra els {{GENDER:$3|canvis}} entre dues versions d'un apunt de $3 en el tema «[$5 $2]» de [$4 $1].\nPodeu veure altres versions d'aquest apunt en la seva [$6 pàgina d'historial].",
"flow-compare-revisions-header-postsummary": "Aquesta pàgina mostra els canvis entre dues versions del resum de l'apunt «[$4 $2]» a [$3 $1].\nPodeu veure altres versions d'aquest apunt a la seva [$5 pàgina d'historial].",
"flow-compare-revisions-header-header": "Aquesta pàgina mostra els {{GENDER:$2|canvis}} entre dues versions de la descripció de [$3 $1].\nPodeu veure altres versions de la descripció en la [$4 pàgina d'historial].",
+ "action-flow-create-board": "crear taulers Flow en qualsevol lloc",
+ "right-flow-create-board": "Creació de taulers Flow en qualsevol ubicació",
+ "right-flow-hide": "Amagar temes i apunts de Flow",
+ "right-flow-lock": "Marcar temes de Flow com a resolts",
+ "right-flow-delete": "Esborrament de temes i apunts Flow",
+ "right-flow-edit-post": "Modificació d'apunts Flow d'altres usuaris",
+ "right-flow-suppress": "Eliminació de revisions Flow",
"flow-terms-of-use-new-topic": "En clicar «{{int:flow-newtopic-save}}», esteu acceptant les condicions d'ús d'aquest wiki.",
"flow-terms-of-use-reply": "En clicar «{{int:flow-replay-submit}}», esteu acceptant les condicions d'ús d'aquest wiki.",
"flow-terms-of-use-edit": "En desar el canvis, esteu acceptant les condicions d'ús d'aquest wiki.",
@@ -282,7 +397,8 @@
"flow-terms-of-use-unlock-topic": "En clicar «{{int:flow-topic-action-unlock-topic}}», esteu acceptant les condicions d'ús d'aquest wiki.",
"flow-whatlinkshere-post": "de partir d'un [$1 apunt]",
"flow-whatlinkshere-header": "a partir de la [$1 descripció]",
- "flow": "Flow",
+ "flow-whatlinkshere-post-summary": "des del [$1 resum]",
+ "structureddiscussions": "Flow",
"flow-special-type": "Tipus",
"flow-special-type-post": "Apunt",
"flow-special-type-workflow": "Flux de treball",
@@ -291,28 +407,40 @@
"flow-special-enableflow-header": "Descripció inicial del tauler Flow (wikitext)",
"flow-special-enableflow-board-already-exists": "Ja existeix un tauler Flow a [[$1]].",
"flow-special-enableflow-invalid-title": "S'ha proporcionat un títol de pàgina no vàlid.",
- "flow-special-enableflow-confirmation": "Heu creat correctament un tauler Flow a [[$1]].",
+ "flow-special-enableflow-confirmation": "Heu creat un tauler Flow a [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Arxiu %d\n%s/Arxiu%d\n%s/arxiu%d\n%s/arxiu%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Arxiu Flow %d",
"flow-spam-confirmedit-form": "Confirmeu que no és una edició mecànica desxifrant el captcha següent: $1",
+ "flow-embedding-unsupported": "Les discussions no es poden incrustar per ara.",
"mw-ui-unsubmitted-confirm": "Teniu canvis no desats en aquesta pàgina. Segur que voleu sortir i perdre la feina feta?",
+ "flow-post-undo-hide": "deixant d'amagar",
+ "flow-post-undo-delete": "desfés l'esborrament",
+ "flow-post-undo-suppress": "anul·lació d'eliminació",
+ "flow-topic-undo-hide": "deixant d'amagar",
+ "flow-topic-undo-delete": "desfés l'esborrament",
+ "flow-topic-undo-suppress": "anul·lació d'eliminació",
+ "flow-importer-lqt-moved-thread-template-content": "Aquest apunt de {{{author}}} ha estat traslladat el {{{date}}}. El podeu trobar a [[{{{title}}}]].",
"flow-importer-wt-converted-template": "Pàgina de discussió en wikitext convertida a Flow",
+ "flow-importer-wt-converted-template-content": "Les discussions prèvies estan arxivades a <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> amb data {{#time: d-m-Y|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Arxiu de pàgina de discussió en wikitext convertida",
- "apihelp-flow+view-post-history-description": "Veure la revisió de la història d'un post.",
- "apihelp-flow+view-post-history-example-1": "Buscar les revisions d'un missatge a [[Topic:S2tycnas4hcucw8w]] com wikitext",
- "apihelp-flow+view-topic-description": "Mostra un tema.",
- "apihelp-flow+view-topic-history-example-1": "Veure les revisions de les entrades a [[Topic:S2tycnas4hcucw8w]] com wikitext",
- "apihelp-flow+view-topiclist-description": "Mostra una llista de temes.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Direcció d'ordenació dels temes.",
- "apihelp-flow-parsoid-utils-param-content": "Contingut per convertir.",
+ "flow-importer-wt-converted-archive-template-content": "Aquesta pàgina és un arxiu. <strong>No modifiqueu el contingut d'aquesta pàgina</strong>. Podeu fer qualsevol comentari addicional en la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|pàgina de discussió actual]].",
+ "flow-importer-lqt-suppressed-user-template-content": "Aquesta revisió va ser importada de LiquidThreads amb un usuari eliminat. Ha estat reassignada a l'usuari actual.",
"flow-edited": "Modificat",
"flow-edited-by": "Editat per $1",
+ "flow-edited-by-header": "Descripció del tauler editada per $1",
+ "flow-edited-by-topic-title": "Títol del tema editat per $1",
"flow-talk-conversion-move-reason": "Conversió de la discussió en wikitext de $1 a Flow",
"flow-talk-conversion-archive-edit-reason": "Conversió de discussió en wikitext a Flow",
"flow-previous-diff": "← Edició anterior",
"flow-next-diff": "Edició següent →",
"flow-undo": "desfés",
+ "flow-undo-latest-revision": "Darrera revisió",
+ "flow-undo-your-text": "El seu text",
+ "flow-undo-edit-header": "Modificació de la descripció",
+ "flow-undo-edit-topic-summary": "Modificació del resum del tema",
+ "flow-undo-edit-post": "Modificació d'un apunt",
"group-flow-bot": "Bots de Flow",
- "group-flow-bot-member": "bot Flow",
+ "group-flow-bot-member": "bot de Flow",
"grouppage-flow-bot": "Project:Bots de Flow",
"flow-ve-mention-context-item-label": "Menció",
"flow-ve-mention-inspector-title": "Menció",
@@ -322,7 +450,7 @@
"flow-ve-mention-inspector-invalid-user": "L'usuari «$1» no està registrat.",
"flow-wikitext-editor-help": "El text wiki $1.",
"flow-wikitext-editor-help-and-preview": "El text wiki $1 i podeu $2 en qualsevol moment.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|utilitza marcatge]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|utilitza marcatge]]",
"flow-wikitext-editor-help-preview-the-result": "previsualitzar el resultat",
"flow-wikitext-switch-editor-tooltip": "Canvia a l'editor visual",
"flow-ve-switch-editor-tool-title": "Canvia a l'editor de text wiki",
@@ -330,7 +458,26 @@
"flow-mark-revision-patrolled-link-title": "Marca la pàgina com a supervisada",
"flow-mark-diff-patrolled-link-text": "Marca com a supervisat",
"flow-mark-diff-patrolled-link-title": "Marca com a supervisat",
+ "flow-talk-page-beta-feature-message": "Flow en la discussió d'usuari",
+ "flow-talk-page-beta-feature-description": "Habilita un nou sistema de discussió estructurada en la vostra pàgina de discussió d'{{GENDER:|usuari|usuària}}. Flow simplifica la conversa en pàgines de discussió amb emplaçaments clars per escriure i respondre, i permet notificacions a nivell de tema de discussió. Les discussions existents en text wiki es traslladen a un arxiu. Aquesta funcionalitat no està activada automàticament; els usuaris l'han d'activar per separat. En desactivar-la el tauler Flow es traslladarà a una subpàgina i es recuperarà la pàgina arxivada prèviament.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Vegeu}} la pàgina de discussió d'usuari",
+ "flow-notification-enabled-on-talkpage-title": "El nou sistema de discussió està activat per la vostra pàgina de discussió d'{{GENDER:$1|usuari|usuària}}<br /><small>Disponible a [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nou sistema de discussió a $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, el nou sistema de discussió wiki, ha estat activat en la {{GENDER:$1|vostra}} pàgina de discussió del projecte {{SITENAME}}. Podeu obtenir més informació, fer comentaris o desactivar-lo en qualsevol moment en la secció de funcionalitats beta de les {{GENDER:$1|vostres}} preferències.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Afegint la plantilla d'arxiu",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Traient la plantilla d'arxiu",
"flow-dialog-cancelconfirm-title": "N'esteu segur?",
+ "flow-dialog-cancelconfirm-message": "Esteu segurs que voleu cancel·lar sense desar abans?",
"flow-dialog-cancelconfirm-keep": "Continua editant",
- "flow-dialog-cancelconfirm-discard": "Descarta els canvis"
+ "flow-dialog-cancelconfirm-discard": "Descarta els canvis",
+ "flow-optin-archive-wikitext": "Es trasllada la pàgina de text wiki per fer lloc a un tauler de discussió.",
+ "flow-optin-archive-flow-board": "Es trasllada tauler de discussió per fer lloc a una pàgina de text wiki.",
+ "flow-optin-restore-wikitext": "Es restaura pàgina de text wiki arxivada.",
+ "flow-optin-restore-flow-board": "Es restaura tauler de discussió arxivat.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Benvinguts}} a la vostra nova pàgina de discussió d'{{GENDER:$1|usuari|usuària}}",
+ "flow-guidedtour-optin-welcome-description": "La {{GENDER:$1|vostra}} pàgina de discussió és el lloc on altres editors {{GENDER:$1|us}} poden contactar. Amb Flow, és més fàcil iniciar nous temes i fer un seguiment de les converses.",
+ "flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|Vegeu}} les vostres converses anteriors",
+ "flow-guidedtour-optin-find-old-conversations-description": "Les converses prèvies han estat traslladades a una pàgina d'arxiu.",
+ "flow-guidedtour-optin-feedback": "Doneu-nos el {{GENDER:$1|vostre}} parer!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Podeu}} obtenir més informació, fer comentaris o desactivar el nou sistema en qualsevol moment en la secció de funcionalitats beta."
}
diff --git a/Flow/i18n/cdo.json b/Flow/i18n/cdo.json
new file mode 100644
index 00000000..c7b2ca86
--- /dev/null
+++ b/Flow/i18n/cdo.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "唐吉訶德的侍從"
+ ]
+ },
+ "flow-post-action-edit-post-submit": "Bō̤-còng siŭ-gāi"
+}
diff --git a/Flow/i18n/ce.json b/Flow/i18n/ce.json
index 9e958ac3..00759dae 100644
--- a/Flow/i18n/ce.json
+++ b/Flow/i18n/ce.json
@@ -1,78 +1,180 @@
{
"@metadata": {
"authors": [
- "Умар"
+ "Умар",
+ "Macofe",
+ "Исмаил Садуев",
+ "Matiia"
]
},
- "flow-hide-post-content": "ХӀара къамел хьулдина {{GENDER:$1|декъашхочо}} $1",
+ "enablestructureddiscussions": "Латаде структурйина дийцаре",
+ "flow-desc": "Эхаран белхан урхаллин система",
+ "flow-talk-taken-over-comment": "ХӀокху агӀонах эхаран дийцарийн у дина */",
+ "log-name-flow": "Эхаран жигараллин тептар",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|дӀабаьккхина}} [$4 хаам] «[[$3|$5]]» чохь [[$6]] тӀера",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|меттахӀоттина}} [$4 хаам] «[[$3|$5]]» чохь [[$6]] тӀера",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|бохийна}} [$4 хаам] «[[$3|$5]]» чохь [[$6]] тӀера",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|дӀабаьккхина}} [$4 хаам] «[[$3|$5]]» чохь [[$6]] тӀера",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|дӀадаьккхина}} «[[$3|$5]]» хьедар [[$6]] тӀера",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|меттахӀоттина}} «[[$3|$5]]» хьедар [[$6]] тӀера",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|дохийна}} «[[$3|$5]]» хьедар [[$6]] тӀера",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|дӀадаьккхина}} «[[$3|$5]]» хьедар [[$6]] тӀера",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] [[$3]] чу импорт йина LiquidThreads чура Эхаран чу",
+ "flow-user-moderated": "Декъашхочун модераци йина",
+ "flow-board-header-browse-topics-link": "Хьедаршка хьажар",
+ "flow-board-header": "ХӀокху унах лаьцна",
+ "flow-board-collapse-description": "Къайлабаккха хаам",
+ "flow-board-expand-description": "Гайта хаам",
+ "flow-edit-header-link": "Нисбе хаам",
+ "flow-post-moderated-toggle-hide-show": "{{GENDER:$1|Декъашхочо}} $2 къайлаяьккхина коммент гайта",
+ "flow-post-moderated-toggle-delete-show": "{{GENDER:$1|ДӀаяьккхина}} $2 коммент гайта",
+ "flow-post-moderated-toggle-suppress-show": "{{GENDER:$1|Декъашхочо}} $2 йохийна коммент гайта",
+ "flow-post-moderated-toggle-hide-hide": "Къайлаяккха, {{GENDER:$1|къайлаяьккхина}} $2 коммент",
+ "flow-post-moderated-toggle-delete-hide": "{{GENDER:$1|Декъашхочо}} $2 дӀаяьккхина коммент къайлаяккха",
+ "flow-post-moderated-toggle-suppress-hide": "{{GENDER:$1|Декъашхочо}} $2 йохийна коммент къайлаяккха",
+ "flow-topic-moderated-reason-prefix": "Бахьана:",
+ "flow-hide-post-content": "ХӀара коммент хьулдина {{GENDER:$1|декъашхочо}} $1",
"flow-hide-title-content": "ХӀара къамел хьулдина {{GENDER:$1|декъашхочо}} $1",
+ "flow-hide-header-content": "{{GENDER:$1|Декъашхочо}} $2 къайладаьккхина",
"flow-delete-post-content": "ХӀара къамел дӀадаьккхина {{GENDER:$1|декъашхочо}} $1",
"flow-post-actions": "дийраш",
"flow-topic-actions": "Дийраш",
"flow-cancel": "Цаоьшу",
+ "flow-skip-summary": "Дехьа гӀо",
"flow-show-change": "Гайта хийцам",
"flow-last-modified-by": "ТӀаьххьара бина {{GENDER:$1|хийцам}} цу $1",
"flow-newtopic-title-placeholder": "Керла тема",
"flow-newtopic-content-placeholder": "ДӀбазбе керла хаам «$1» чохь",
+ "flow-newtopic-save": "Тема тӀетоха",
+ "flow-newtopic-start-placeholder": "Доладе керла хьедар",
+ "flow-reply-topic-title-placeholder": "«$1» жоп далар",
"flow-reply-link": "{{GENDER:$1|Жоп}}",
"flow-thank-link": "{{GENDER:$1|Баркалла аьлла}}",
+ "flow-thank-link-title": "Массарна гуш {{GENDER:$1|{{GENDER:$2|баркалла ала}}}} хӀара хаам битанчуна",
+ "flow-history-action-suppress-post": "йохо",
"flow-history-action-delete-post": "дӀаяккха",
"flow-history-action-hide-post": "къайлаяккха",
+ "flow-history-action-unsuppress-post": "юхадаккха йохор",
+ "flow-history-action-undelete-post": "юхадаккха дӀаяккхар",
+ "flow-history-action-unhide-post": "юхадаккха хьулдар",
+ "flow-history-action-restore-post": "меттахӀоттае",
+ "flow-history-action-lock-topic": "сацам бан",
+ "flow-history-action-unlock-topic": "юху схьаелла",
"flow-post-edited": "Хаам табина {{GENDER:$1|декъашхочо}} $1 $2",
"flow-post-action-view": "Гуттура йолу хьажорг",
"flow-post-action-post-history": "Истори",
+ "flow-post-action-suppress-post": "Йохо",
"flow-post-action-delete-post": "ДӀаяккха",
"flow-post-action-hide-post": "Къайлаяккха",
"flow-post-action-edit-post": "Тае",
+ "flow-post-action-edit-post-submit": "Ӏалашбе хийцамаш",
+ "flow-post-action-edit-post-submit-anonymously": "Ӏалашбе хийцамаш цӀе хьулйина",
+ "flow-post-action-unsuppress-post": "Юхадаккха йохор",
"flow-post-action-undelete-post": "МеттахӀоттае",
"flow-post-action-unhide-post": "Гайта",
"flow-post-action-restore-post": "МеттахӀоттае",
+ "flow-post-action-undo-moderation": "Юхадаккха",
"flow-topic-action-view": "Гуттура йолу хьажорг",
"flow-topic-action-watchlist": "Тергаме могӀам",
"flow-topic-action-edit-title": "Табе корта",
"flow-topic-action-history": "Истори",
"flow-topic-action-hide-topic": "Хьулле тема",
"flow-topic-action-delete-topic": "ДӀаяккха тема",
+ "flow-topic-action-undo-moderation": "Цаоьшу",
+ "flow-topic-action-watchlist-remove": "ДӀадаккхар",
+ "flow-error-missing-topic-title": "Карара белхийн хьедар каро йиш ца хилира.",
+ "flow-error-missing-metadata": "ХӀокху версина оьшуш болу метахаамаш каро йиш ца хилира.",
+ "flow-error-fail-load-data": "Магийна боцу хаамаш чубаха йиш ца хилира.",
+ "flow-error-invalid-workflow": "Магийна боцу белхаш каро йиш ца хилира.",
+ "flow-error-process-data": "Хьан дехарехь хаамаш кечбечу хенахь гӀалат даьлла.",
"flow-error-no-commit": "Нисдинарг Ӏалашдан йиш яц.",
"flow-error-invalid-topic-uuid-title": "Цамегаш йолу цӀе",
+ "flow-error-unknown-workflow-id-title": "Девзаш доцу хьедар",
+ "flow-error-unknown-workflow-id": "Магийна доцу хьедар дац.",
"flow-edit-header-submit": "Ӏалашбе хаам",
- "flow-rev-message-edit-post": "$1 {{GENDER:$2|тадина}} [$3 къамел] темехь $4.",
- "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|къамел диттина}}] темехь $4.",
+ "flow-edit-title-submit": "Хийца корта",
+ "flow-edit-title-submit-anonymously": "Хийца корта цӀе хьулйина",
+ "flow-edit-post-submit": "Бакъбе хийцамаш",
+ "flow-edit-post-submit-anonymously": "Ӏалашбе хийцамаш цӀе хьулйина",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|тадина}} [$3 къамел] $4 чохь.",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Хийцам бина}} хаамна",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|коммент йитина}}] «$4» (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|коммент}}</strong> {{PLURAL:$1|тӀетоьхна}} {{PLURAL:$1|дара}}",
"flow-rev-message-new-post": "$1 {{GENDER:$2|кхоьллина}} къамел ''[$3 $4]''.",
- "flow-rev-message-create-header": "$1 {{GENDER:$2|кхоьллина}} корта.",
- "flow-rev-message-edit-header": "$1 {{GENDER:$2|табина}} корта.",
- "flow-rev-message-deleted-post": "$1 {{GENDER:$2||дӀадяьккхина}} [$4 къамел] темехь $6(<em>$5</em>).",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Кхоьллина}} керла хьедар",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|хийцина}} хьедаран цӀе «$5» → «[$3 $4]»",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|кхоьллина}} цунах лаьцна.",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|табина}} хаам.",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|кхоьллина}} доца хьедарах «$3» лаьцна",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|табина}} «$3» хьедаран боца чулацам",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|къайлаяьккхина}} [$4 коммент] «$6» (<em>$5</em>) чохь",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2||дӀадяьккхина}} [$4 къамел] $6(<em>$5</em>) хьедар чохь.",
"flow-rev-message-suppressed-post": "$1 {{GENDER:$2||дӀаяьккхина}} [$4 къамел] $6(<em>$5</em>) чохь.",
- "flow-rev-message-deleted-topic": "$1 {{GENDER:$2||дӀаяьккхина}} [$4 тема] $6(<em>$5</em>).",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|дӀаяьккхина}} тема [$4 topic] $6 (<em>$5</em>).",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|меттахӀоттина}} [$4 коммент] «$6» (<em>$5</em>) чохь",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|къайладаьккхина}} [$4 хьедар] «$6» (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2||дӀаяьккхина}} [$4 хьедар] $6(<em>$5</em>).",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|дӀаяьккхина}} хьедар [$4 topic] $6 (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|билгалдина}} [$4 хьедар] \"$6\" магийна сана (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|меттахӀотина}} [$4 хьедар] «$6» (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 оцу $2",
"flow-board-history": "\"$1\" истори",
+ "flow-history-day": "Тахана",
+ "flow-history-week": "Даханчу кӀирнахь",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|жоп делла}} \"<strong>$4</strong>\" чохь.",
"flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|кхоьллина}} '''$3''' агӀонгахь керла хьедар.",
"flow-notification-mention": "$1 {{GENDER:$1|хьахийна}} {{GENDER:$5|хьо}} {{GENDER:$1|шен}} <span class=\"plainlinks\">[$2 хаамехь]</span> темехь «$3» агӀонгахь «$4».",
"flow-notification-link-text-view-post": "Хьажа хааме",
+ "flow-notification-link-text-view-topic": "Хьажа хьедаре",
+ "flow-notification-link-text-view-topics": "Хьажа хьедаршка",
"flow-notification-reply-email-subject": "$2 $3 тӀе",
"flow-notification-reply-email-batch-body": "$1 хан хааан {{GENDER:$1||жоп делла}} темехь «$2» «$3» чохь",
"flow-notification-mention-email-subject": "$1 хьо {{GENDER:$1|хьахийна}} «$2» чохь",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|хьахийна}} {{GENDER:$4|хьо}} {{GENDER:$1|шен}} хаамехь «$2» агӀонгахь «$3»",
+ "flow-notification-edit-email-subject": "$1 {{GENDER:$1|хийцам бина}} хаамна",
+ "flow-notification-edit-email-batch-body": "$1 {{GENDER:$2|хийцам бина}} «$2» хаамна → $3",
+ "echo-category-title-flow-discussion": "Эхар",
"flow-link-post": "хаам",
+ "flow-link-topic": "хьедар",
"flow-link-history": "истори",
+ "flow-link-post-revision": "Хааман верси",
+ "flow-link-topic-revision": "Хьедаран верси",
+ "flow-link-header-revision": "Хааман верси",
+ "flow-link-summary-revision": "боца чулацаман верси",
+ "flow-moderation-title-suppress-post": "ДӀабаккха хаам?",
"flow-moderation-title-delete-post": "ДӀабаккха хаам",
"flow-moderation-title-hide-post": "Къайлабаккха хаам?",
+ "flow-moderation-title-unsuppress-post": "Хаам тӀетохар юхадаккха?",
+ "flow-moderation-title-undelete-post": "Хаам дӀабаккхар юхадаккха?",
+ "flow-moderation-title-unhide-post": "Къайла хаамаш юхабаха?",
+ "flow-moderation-confirm-suppress-post": "Йохо",
"flow-moderation-confirm-delete-post": "ДӀаяккха",
"flow-moderation-confirm-hide-post": "Къайлаяккха",
+ "flow-moderation-confirm-unsuppress-post": "Юхадаккха йохор",
"flow-moderation-confirm-undelete-post": "ДӀаяккха",
"flow-moderation-confirm-unhide-post": "Гайта",
+ "flow-moderation-confirm-suppress-topic": "Йохо",
"flow-moderation-confirm-delete-topic": "ДӀаяккха",
"flow-moderation-confirm-hide-topic": "Къайлаяккха",
+ "flow-moderation-confirm-unsuppress-topic": "Юхадаккха йохор",
"flow-moderation-confirm-undelete-topic": "МеттахӀоттае",
"flow-moderation-confirm-unhide-topic": "Гайта",
"flow-topic-first-heading": "$1 чура хьедар",
"flow-topic-html-title": "$1 $2 тӀе",
+ "flow-topic-count": "Хьедарш ($1)",
+ "flow-load-more": "Чуяха кхин",
+ "flow-no-more-fwd": "Шира хьедарш дац",
+ "flow-newest-topics": "Керла хьедарш",
"flow-recent-topics": "Дукху хан йоцуш жигара хьедарш",
"flow-whatlinkshere-header": "[$1 хьехар] чура",
- "flow-spam-confirmedit-form": "Хьой адам делахь сурт тӀера йоза язде: $1",
+ "structureddiscussions": "Структурйина дийцаре",
+ "flow-special-desc": "ХӀокху леррина агӀоно workflow тӀе хьажо Эхар я хаамаш тӀе UUID тӀехула.",
+ "flow-special-type": "Тайпа",
+ "flow-special-type-post": "Хаам",
+ "flow-special-type-workflow": "Белхан эхар",
+ "flow-special-uuid": "UUID",
+ "flow-spam-confirmedit-form": "Сурт тӀера йоза лаха яздехьа, нагахь хьо робот вацахь: $1",
"flow-post-undo-delete": "юхадаккха дӀадаккхар",
- "apihelp-flow-example-1": "«[[Talk:Sandbox]]» лаьцна хаам нисъбе",
+ "flow-edited-by": "Хийцина $1",
"flow-previous-diff": "← Хьалха доьда нисдинарг",
"flow-next-diff": "ТӀаьхьа догӀа нисдинарг →",
"flow-undo": "йохо",
@@ -80,5 +182,13 @@
"group-flow-bot": "Flow-боташ",
"group-flow-bot-member": "Flow-бот",
"grouppage-flow-bot": "Project:Flow bots",
- "flow-ve-mention-placeholder": "Декъашхочун цӀе"
+ "flow-ve-mention-context-item-label": "Хьахор",
+ "flow-ve-mention-inspector-title": "Хьахор",
+ "flow-ve-mention-inspector-remove-label": "ДӀаяккха",
+ "flow-ve-mention-placeholder": "Декъашхочун цӀе",
+ "flow-ve-mention-tool-title": "Декъашхо хьахо",
+ "flow-ve-mention-inspector-invalid-user": "Декъашхочун «$1» дӀаяздар дац.",
+ "flow-wikitext-editor-help": "Вики-йоза $1.",
+ "flow-wikitext-switch-editor-tooltip": "Тае бӀаьран тадар чохь",
+ "flow-ve-switch-editor-tool-title": "Тае вики-йозан тадар чохь"
}
diff --git a/Flow/i18n/ckb.json b/Flow/i18n/ckb.json
index df8c21d4..9c8d162f 100644
--- a/Flow/i18n/ckb.json
+++ b/Flow/i18n/ckb.json
@@ -1,8 +1,15 @@
{
"@metadata": {
"authors": [
- "Pirehelokan"
+ "Pirehelokan",
+ "Sarchia"
]
},
- "flow-summary-authored": "پوختە بە $1"
+ "flow-cancel": "ھەڵوەشاندنەوە",
+ "flow-summary-authored": "پوختە بە $1",
+ "flow-history-action-delete-post": "سڕینەوە",
+ "flow-post-action-delete-post": "سڕینەوە",
+ "flow-comment-hidden": "بۆچوونی شاردراوە",
+ "flow-moderation-confirm-delete-post": "سڕینەوە",
+ "flow-moderation-confirm-delete-topic": "سڕینەوە"
}
diff --git a/Flow/i18n/cs.json b/Flow/i18n/cs.json
index f8c33657..6c01230a 100644
--- a/Flow/i18n/cs.json
+++ b/Flow/i18n/cs.json
@@ -5,26 +5,91 @@
"Mormegil",
"Paxt",
"Cvanca",
- "Vks"
+ "Vks",
+ "Matěj Suchánek",
+ "Urbanecm",
+ "Dvorapa",
+ "Martin Urbanec"
]
},
+ "enablestructureddiscussions": "Aktivovat Flow",
+ "flow-desc": "Diskusní systém",
+ "flow-talk-taken-over-comment": "/* Tato stránka byla převedena na nástěnku Flow */",
+ "log-name-flow": "Kniha aktivity Flow",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|smazal|smazala}} [$4 příspěvek] k tématu „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|smazal|smazala|smazal(a)}} příspěvek k tématu na stránce [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|obnovil|obnovila}} [$4 příspěvek] k tématu „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|obnovil|obnovila|obnovil(a)}} příspěvek k tématu na stránce [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|utajil|utajila}} [$4 příspěvek] k tématu „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|skryl|skryla|skryl(a)}} příspěvek k tématu na stránce [[$3]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|smazal|smazala}} [$4 příspěvek] k tématu „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|smazal|smazala|smazal(a)}} příspěvek k tématu na stránce [[$3]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|smazal|smazala}} téma „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|smazal|smazala|smazal(a)}} téma na stránce [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|obnovil|obnovila}} téma „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|obnovil|obnovila|obnovil(a)}} téma na stránce [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|utajil|utajila}} téma „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|skryl|skryla|skryl(a)}} téma na stránce [[$3]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|smazal|smazala}} téma „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|smazal|smazala|smazal(a)}} téma na stránce [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|označil|označila}} téma „[[$3|$5]]“ v [[$6]] jako vyřešené",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|označil|označila|označil(a)}} téma za vyřešené na stránce [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|obnovil|obnovila}} téma „[[$3|$5]]“ na stránce [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 znovu {{GENDER:$2|otevřel|otevřela|otevřel(a)}} téma na stránce [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "Téma [[$1|$2]] na nástěnce [[$3]] bylo naimportováno z LiquidThreads do Flow",
+ "flow-user-moderated": "Moderovaný uživatel",
"flow-board-header-browse-topics-link": "Procházet témata",
+ "flow-board-header": "O této stránce",
+ "flow-board-collapse-description": "Skrýt popis",
+ "flow-board-expand-description": "Zobrazit popis",
"flow-edit-header-link": "Editovat popis",
- "flow-post-moderated-toggle-hide-show": "Ukázat komentář {{GENDER:$1|skrytý}} od $2",
- "flow-post-moderated-toggle-delete-show": "Ukázat komentář {{GENDER:$1|odstraněný}} od $2",
- "flow-post-moderated-toggle-suppress-show": "Ukázat komentář {{GENDER:$1|odstraněný}} od $2",
- "flow-post-moderated-toggle-hide-hide": "Skrýt komentář {{GENDER:$1|skrytý}} od $2",
- "flow-post-moderated-toggle-delete-hide": "Skrýt komentář {{GENDER:$1|odstraněný}} od $2",
- "flow-post-moderated-toggle-suppress-hide": "Skrýt komentář {{GENDER:$1|potlačený}} od $2",
+ "flow-post-moderated-toggle-hide-show": "Ukázat komentář skrytý {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-post-moderated-toggle-delete-show": "Ukázat komentář smazaný {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-post-moderated-toggle-suppress-show": "Ukázat komentář utajený {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-post-moderated-toggle-hide-hide": "Skrýt komentář skrytý {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-post-moderated-toggle-delete-hide": "Skrýt komentář smazaný {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-post-moderated-toggle-suppress-hide": "Skrýt komentář utajený {{GENDER:$1|uživatelem|uživatelkou}} $2",
"flow-topic-moderated-reason-prefix": "Důvod:",
+ "flow-hide-post-content": "Tento komentář byl skryt {{GENDER:$1|uživatelem|uživatelkou}} $1 ([$2 historie])",
+ "flow-hide-title-content": "Toto téma bylo skryto {{GENDER:$1|uživatelem|uživatelkou}} $1",
+ "flow-hide-header-content": "Skryto {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-delete-post-content": "Tento komentář byl smazán {{GENDER:$1|uživatelem|uživatelkou}} $1 ([$2 historie])",
+ "flow-delete-title-content": "Toto téma bylo smazáno {{GENDER:$1|uživatelem|uživatelkou}} $1",
+ "flow-delete-header-content": "Smazáno {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-suppress-post-content": "Tento komentář byl utajen {{GENDER:$1|uživatelem|uživatelkou}} $1 ([$2 historie])",
+ "flow-suppress-title-content": "Toto téma bylo utajeno {{GENDER:$1|uživatelem|uživatelkou}} $1",
+ "flow-suppress-header-content": "Utajeno {{GENDER:$1|uživatelem|uživatelkou}} $2",
+ "flow-suppress-usertext": "<em>Uživatelské jméno utajeno</em>",
"flow-post-actions": "Akce",
"flow-topic-actions": "Akce",
"flow-cancel": "Storno",
+ "flow-skip-summary": "Přeskočit",
+ "flow-edit-summary-placeholder": "Stručně popište výsledek této diskuse",
+ "flow-summary-authored": "Shrnutí od {{GENDER:$1|uživatele|uživatelky}} $1",
+ "flow-summary-edited": "Shrnutí naposledy {{GENDER:$1|upravil|upravila}} $1",
"flow-show-change": "Ukázat změny",
+ "flow-last-modified-by": "Naposledy {{GENDER:$1|upravil|upravila}} $1",
+ "flow-stub-post-content": "<em>Kvůli technické chybě se tento příspěvek nepodařilo načíst.</em>",
"flow-newtopic-title-placeholder": "Nové téma",
+ "flow-newtopic-content-placeholder": "Založit nové téma v „$1“",
"flow-newtopic-header": "Přidat nové téma",
"flow-newtopic-save": "Přidat téma",
+ "flow-newtopic-save-anonymously": "Přidat sekci anonymně.",
"flow-newtopic-start-placeholder": "Založit nové téma",
+ "flow-summarize-topic-placeholder": "Shrňte tuto diskusi",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Okomentovat}} „$2“",
+ "flow-reply-link": "{{GENDER:$1|Odpovědět}}",
+ "flow-reply-link-anonymously": "Anonymně odpovědět",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Poděkovat}}}}",
+ "flow-thank-link-title": "Veřejně {{GENDER:$1|poděkovat}} {{GENDER:$2|uživateli|uživatelce}}",
+ "flow-history-action-suppress-post": "utajit",
+ "flow-history-action-delete-post": "smazat",
+ "flow-history-action-hide-post": "skrýt",
+ "flow-history-action-unsuppress-post": "odtajit",
+ "flow-history-action-undelete-post": "obnovit",
+ "flow-history-action-unhide-post": "odkrýt",
+ "flow-history-action-restore-post": "obnovit",
+ "flow-post-edited": "Příspěvek {{GENDER:$1|upravil|upravila}} $1 $2",
"flow-post-action-view": "Trvalý odkaz",
"flow-post-action-post-history": "Historie",
"flow-post-action-suppress-post": "Utajit",
@@ -43,20 +108,123 @@
"flow-topic-action-history": "Historie",
"flow-topic-action-hide-topic": "Skrýt téma",
"flow-topic-action-delete-topic": "Smazat téma",
- "flow-topic-action-lock-topic": "Zamknout téma",
- "flow-topic-action-unlock-topic": "Odemknout téma",
+ "flow-topic-action-lock-topic": "Označit jako vyřešené",
+ "flow-topic-action-unlock-topic": "Znovuotevřít téma",
"flow-topic-action-summarize-topic": "Shrnout",
"flow-topic-action-resummarize-topic": "Upravit shrnutí tématu",
+ "flow-topic-action-update-topic-summary": "Aktualizovat shrnutí",
+ "flow-topic-action-suppress-topic": "Utajit téma",
+ "flow-topic-action-unhide-topic": "Odkrýt téma",
+ "flow-topic-action-undelete-topic": "Obnovit téma",
+ "flow-topic-action-unsuppress-topic": "Odtajit téma",
"flow-topic-action-undo-moderation": "Zpět",
+ "flow-topic-notification-subscribe-title": "Téma bylo přidáno na {{GENDER:$1|váš}} seznam sledovaných stránek.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Budete}} dostávat upozornění na veškerou činnost v tomto tématu",
+ "flow-topic-action-watchlist-add": "Odebírat toto téma",
+ "flow-topic-action-watchlist-remove": "Zrušit odběr",
+ "flow-error-http": "Během kontaktování serveru došlo k chybě.",
+ "flow-error-external": "Došlo k chybě. Přijaté chybové hlášení je: $1",
+ "flow-error-missing-content": "Příspěvek nemůže být prázdný.",
+ "flow-error-missing-summary": "Musíte vložit shrnutí.",
+ "flow-error-missing-title": "Název sekce nemůže být prázdný.",
+ "flow-error-parsoid-failure": "Kvůli chybě softwaru Parsoid se nepodařilo analyzovat obsah.",
+ "flow-error-invalid-moderation-reason": "Uveďte, prosím, důvod pro moderování.",
+ "flow-error-not-allowed": "Nedostatečná oprávnění k provedení této akce.",
+ "flow-error-not-allowed-hide": "Toto téma bylo skryto.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Na tento příspěvek nemůžete odpovědět, protože sekce byla skryta.",
+ "flow-error-not-allowed-delete": "Tato sekce byla smazána.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Na tento příspěvek nemůžete odpovědět, protože sekce byla smazána.",
+ "flow-error-not-allowed-suppress": "Tato sekce byla smazána.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Na tento příspěvek nemůžete odpovědět, protože sekce byla smazána.",
+ "flow-error-not-allowed-hide-extract": "Tato sekce byla skryta. Níže je pro přehled zobrazen poslední protokolovací záznam.",
+ "flow-error-not-allowed-delete-extract": "Tato sekce byla skryta. Níže je pro přehled zobrazen poslední protokolovací záznam.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Na tento příspěvek není možné odpovědět, protože sekce byla smazána. Níže je pro přehled zobrazen poslední protokolovací záznam.",
+ "flow-error-not-allowed-suppress-extract": "Tato sekce byla smazána. Níže je pro přehled zobrazen poslední protokolovací záznam.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Na tento příspěvek není možné odpovědět, protože sekce byla utajena. Níže je pro přehled zobrazen poslední protokolovací záznam.",
+ "flow-error-missing-header-content": "Musite zadat popis",
+ "flow-error-prev-revision-mismatch": "Tento příspěvek před chvíli editoval jiný uživatel. Jste si {{GENDER:$3|jistý|jistá|jisti}}, že chcete přepsat nejnovější změnu?",
"flow-error-default": "Došlo k chybě.",
+ "flow-error-fail-load-history": "Nepodařilo se načíst obsah historie.",
+ "flow-error-fail-commit": "Nepodařilo se uložit obsah příspěvku.",
+ "flow-error-insufficient-permission": "Nedostatečná oprávnění pro přístup k obsahu.",
+ "flow-error-fail-load-data": "Nepodařilo se načíst požadovaná data.",
+ "flow-error-process-data": "Při zpracování vašeho požadavku došlo k chybě.",
+ "flow-error-process-wikitext": "Při zpracování HTML nebo wikitextu došlo k chybě.",
+ "flow-error-content-too-long": "Tento příspěvek je příliš dlouhý. Velikost příspěvku po jeho expanzi je omezena na $1 {{PLURAL:$1|bajt|bajty|bajtů}}.",
+ "flow-error-move-topic": "Přesunutí stránky sekce v současné době není podporováno.",
"flow-error-invalid-topic-uuid-title": "Neplatný název",
+ "flow-error-search": "Kvůli dočasnému problému jsme nemohli provést požadované vyhledávání. Zkuste to prosím znovu později.",
"flow-edit-header-submit": "Uložit popis",
- "flow-edit-header-submit-overwrite": "Přepsat popis",
+ "flow-edit-header-submit-anonymously": "Anonymně uložit popis",
+ "flow-edit-title-submit": "Změnit název stránky",
+ "flow-edit-title-submit-anonymously": "Anonymně změnit název stránky",
+ "flow-edit-post-submit": "Odeslat změny",
+ "flow-edit-post-submit-anonymously": "Anonymně odeslat změny",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|upravil|upravila}} [$3 komentář] k tématu „$4“",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Upraven}} příspěvek",
+ "flow-rev-message-reply-bundle": "{{PLURAL:$1|byl přidán <strong>jeden komentář</strong>|byly přidány <strong>$1 komentáře</strong>|bylo přidáno <strong>$1 komentářů</strong>}}",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|vytvořil|vytvořila}} téma „[$3 $4]“",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Vytvořeno}} nové téma",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|změnil|změnila}} název tématu z „$5“ na „[$3 $4]“",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|vytvořil|vytvořila}} popis",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|upravil|upravila}} popis",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|skryl|skryla}} [$4 komentář] k tématu „$6“ (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|smazal|smazala}} [$4 komentář] k tématu „$6“ (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|utajil|utajila}} [$4 komentář] na stránce „$6“ (<em>$5</em>).",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|obnovil|obnovila}} [$4 komentář] na stránce „$6“ (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|skryl|skryla}} [$4 sekci] „$6“ (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|smazal|smazala}} [$4 téma] „$6“ (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|utajil|utajila}} [$4 sekci] „$6“ (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|označil|označila}} [$4 téma] „$6“ jako vyřešené (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|obnovil|obnovila}} [$4 téma] „$6“ (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 na $2",
+ "flow-board-history-empty": "Tato Flow stránka v současnosti nemá žádnou historii.",
"flow-history-day": "Dnes",
"flow-history-week": "Poslední týden",
+ "flow-topic-comments": "{{PLURAL:$1|$1 komentář|$1 komentáře|$1 komentářů|0={{GENDER:$2|Napište komentář jako první}}!}}",
+ "flow-show-comments-title": "Zobrazit {{PLURAL:$1|komentář|komentáře}}",
+ "flow-hide-comments-title": "Skrýt {{PLURAL:$1|komentář|komentáře}}",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|odpověděl|odpověděla}} na stránce <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 a {{PLURAL:$5|$5 další|$5 další|$5 dalších|100=více než 99 dalších}} {{GENDER:$1|odpověděli}} na stránce <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|upravil|upravila}} váš <span class=\"plainlinks\">[$5 příspěvek]</span> v sekci [[$3|$4]].",
+ "flow-notification-edit-bundle": "$1 a {{PLURAL:$5|$5 další|$5 další|$5 dalších|100=více než 99 dalších}} upravili <span class=\"plainlinks\">[$4 příspěvek]</span> v sekci „$2“ na stránce „$3“.",
+ "notification-header-flow-new-topic-v2": "Na stránce <strong>$3</strong> bylo vytvořeno nové téma: <bdi>„<strong>$4</strong>“</bdi>.",
+ "notification-compact-header-flow-new-topic": "„<strong>$1</strong>“",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Jedno nové téma|$1 nová témata|$1 nových témat|100=Více než 99 nových témat}} na stránce <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Na <strong>vaší diskusní stránce</strong> bylo vytvořeno nové téma: „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Jedno nové téma|$1 nová témata|$1 nových témat|100=Více než 99 nových témat}} na <strong>vaší diskusní stránce</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|odpověděl|odpověděla}} u „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Jedna nová odpověď|$1 nové odpovědi|$1 nových odpovědí|100=Více než 99 nových odpovědí}} u „<strong>$3</strong>“.",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|odpověděl|odpověděla}} na <strong>vaší diskusní stránce</strong> u „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Jedna nová odpověď|$1 nové odpovědi|$1 nových odpovědí|100=Více než 99 nových odpovědí}} na <strong>vaší diskusní stránce</strong> u „<strong>$3</strong>“.",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Váš}} příspěvek u „<strong>$1</strong>“ byl upraven.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Váš}} příspěvek u „<strong>$1</strong>“ byl několikrát upraven.",
+ "notification-header-flow-post-edited-user-talk": "Na <strong>{{GENDER:$2|vaší}} diskusní stránce</strong> byl upraven příspěvek u „<strong>$1</strong>“.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Na <strong>{{GENDER:$2|vaší}} diskusní stránce</strong> byl několikrát upraven příspěvek u „<strong>$1</strong>“.",
+ "notification-header-flow-topic-renamed-v2": "Téma „<strong>$1</strong>“ bylo přejmenováno na „<strong>$2</strong>“.",
+ "notification-header-flow-topic-renamed-user-talk": "Téma „<strong>$1</strong>“ na <strong>{{GENDER:$3|vaší}} diskusní stránce</strong> bylo přejmenováno na „<strong>$2</strong>“.",
+ "notification-header-flow-summary-edited": "Shrnutí tématu „<strong>$1</strong>“ bylo aktualizováno.",
+ "notification-header-flow-summary-edited-first": "Tématu „<strong>$1</strong>“ bylo vytvořeno shrnutí.",
+ "notification-bundle-header-flow-summary-edited": "Shrnutí tématu „<strong>$1</strong>“ bylo několikrát aktualizováno.",
+ "notification-header-flow-summary-edited-user-talk": "Shrnutí tématu „<strong>$1</strong>“ na <strong>{{GENDER:$2|vaší}} diskusní stránce</strong> bylo aktualizováno.",
+ "notification-header-flow-summary-edited-first-user-talk": "Tématu „<strong>$1</strong>“ na <strong>{{GENDER:$2|vaší}} diskusní stránce</strong> bylo vytvořeno shrnutí.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Shrnutí tématu „<strong>$1</strong>“ na <strong>{{GENDER:$2|vaší}} diskusní stránce</strong> bylo několikrát aktualizováno.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Jedno nové téma|$1 nová témata|$1 nových témat|100=Více než 99 nových témat}} na stránce <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-mention": "$1 {{GENDER:$5|vás}} {{GENDER:$1|zmínil|zmínila}} ve svém <span class=\"plainlinks\">[$2 příspěvku]</span> v sekci „$3“ na stránce „$4“.",
"flow-notification-link-text-view-post": "Zobrazit příspěvek",
"flow-notification-link-text-view-topic": "Zobrazit téma",
"flow-notification-reply-email-subject": "$2 na $3",
+ "echo-category-title-flow-discussion": "diskusi ve Flow",
+ "echo-pref-tooltip-flow-discussion": "Upozorněte mě na činnosti ve vláknech nebo na diskusních stránkách, které sleduji.",
+ "flow-link-post": "příspěvek",
+ "flow-link-topic": "téma",
+ "flow-link-history": "historie",
+ "flow-moderation-placeholder-suppress-post": "Prosím {{GENDER:$3|popište}}, proč utajujete tento příspěvek.",
+ "flow-moderation-placeholder-delete-post": "Prosím {{GENDER:$3|popište}}, proč mažete tento příspěvek.",
+ "flow-moderation-placeholder-hide-post": "Prosím {{GENDER:$3|popište}}, proč skrýváte tento příspěvek.",
+ "flow-moderation-placeholder-unsuppress-post": "Prosím {{GENDER:$3|popište}}, proč odtajujete tento příspěvek.",
+ "flow-moderation-placeholder-undelete-post": "Prosím {{GENDER:$3|popište}}, proč obnovujete tento příspěvek.",
"flow-moderation-confirm-suppress-post": "Utajit",
"flow-moderation-confirm-delete-post": "Smazat",
"flow-moderation-confirm-hide-post": "Skrýt",
@@ -66,29 +234,46 @@
"flow-moderation-confirm-suppress-topic": "Utajit",
"flow-moderation-confirm-delete-topic": "Smazat",
"flow-moderation-confirm-hide-topic": "Skrýt",
- "flow-moderation-confirm-lock-topic": "Uzamknout",
"flow-moderation-confirm-unsuppress-topic": "Zrušit utajení",
"flow-moderation-confirm-undelete-topic": "Obnovit",
"flow-moderation-confirm-unhide-topic": "Odkrýt",
- "flow-moderation-confirm-unlock-topic": "Odemknout",
+ "flow-moderation-placeholder-suppress-topic": "Prosím {{GENDER:$3|popište}}, proč utajujete tuto sekci.",
+ "flow-moderation-placeholder-hide-topic": "Prosím {{GENDER:$3|popište}}, proč skrýváte tuto sekci.",
+ "flow-moderation-placeholder-unsuppress-topic": "Prosím {{GENDER:$3|popište}}, proč odtajujete toto téma.",
+ "flow-moderation-placeholder-undelete-topic": "Prosím {{GENDER:$3|popište}}, proč obnovujete tuto sekci.",
+ "flow-moderation-placeholder-unhide-topic": "Prosím {{GENDER:$3|popište}}, proč odkrýváte tuto sekci.",
+ "action-flow-create-board": "vytvářet nástěnky Flow na libovolném místě",
+ "right-flow-create-board": "Vytváření nástěnek Flow na libovolném místě",
+ "right-flow-hide": "Skrýt Flow témata a příspěvky",
+ "right-flow-lock": "Označování Flow témat jako vyřešená",
+ "right-flow-delete": "Mazání Flow témat a příspěvků",
+ "right-flow-edit-post": "Editovat Flow příspěvky od ostatních uživatelů",
+ "right-flow-suppress": "Utajit Flow editace",
"flow-topic-html-title": "$1 na $2",
"flow-topic-count": "Témata ($1)",
"flow-load-more": "Načíst další",
"flow-no-more-fwd": "Neexistují žádná starší témata",
"flow-newest-topics": "Nejnovější témata",
"flow-recent-topics": "Nedávno aktivní témata",
+ "flow-whatlinkshere-post": "v [$1 příspěvku]",
"flow-special-type": "Typ",
"flow-special-type-post": "Příspěvek",
"flow-special-type-workflow": "Workflow",
"flow-special-uuid": "UUID",
"flow-edited": "Upraveno",
"flow-edited-by": "{{GENDER:$1|Upravil|Upravila|Upravil(a)}} $1",
+ "flow-undo": "zrušit editaci",
+ "group-flow-bot": "Roboti pro Flow",
"flow-ve-mention-context-item-label": "Zmínit",
"flow-ve-mention-inspector-title": "Zmínka",
"flow-ve-mention-inspector-remove-label": "Odstranit",
"flow-ve-mention-placeholder": "Uživatelské jméno",
"flow-ve-mention-tool-title": "Zmínit uživatele",
- "flow-ve-mention-template": "Odpověď",
"flow-ve-mention-inspector-invalid-user": "Uživatelské jméno „$1“ není zaregistrováno.",
- "flow-ve-switch-editor-tool-title": "Přepnout do Wikitext editoru"
+ "flow-wikitext-switch-editor-tooltip": "Přepnout do vizuálního editoru",
+ "flow-ve-switch-editor-tool-title": "Přepnout do editoru wikitextu",
+ "flow-talk-page-beta-feature-message": "Flow v uživatelské diskusi",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Zobrazit}} uživatelskou diskusní stránku",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Vítejte}} na své nové uživatelské diskusní stránce",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Vaše}} diskusní stránka je místo, kde vás mohou kontaktovat ostatní editoři. Pomocí Flow se snáze začínají nová témata a sledují diskuse."
}
diff --git a/Flow/i18n/cu.json b/Flow/i18n/cu.json
new file mode 100644
index 00000000..ac1b5520
--- /dev/null
+++ b/Flow/i18n/cu.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "ОйЛ"
+ ]
+ },
+ "flow-undo": "отъмѣтаниѥ"
+}
diff --git a/Flow/i18n/da.json b/Flow/i18n/da.json
new file mode 100644
index 00000000..d28535db
--- /dev/null
+++ b/Flow/i18n/da.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jens Jensen",
+ "Sarrus"
+ ]
+ },
+ "flow-board-expand-description": "Vis beskrivelse",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|nævnte}} {{GENDER:$4|dig}} i \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|nævnte}} {{GENDER:$4|dig}} i \"<strong>$5</strong>\".",
+ "flow-notification-link-text-view-topics": "Se emner",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|nævnte}} {{GENDER:$3|dig}} på $2"
+}
diff --git a/Flow/i18n/de.json b/Flow/i18n/de.json
index 60d1f08e..dc229eb4 100644
--- a/Flow/i18n/de.json
+++ b/Flow/i18n/de.json
@@ -8,25 +8,54 @@
"Tiin",
"Macofe",
"MarcoFalke",
- "J. 'mach' wust"
+ "J. 'mach' wust",
+ "Nnemo",
+ "Predatorix",
+ "Quiddity",
+ "TMg",
+ "ThePiscin",
+ "Umherirrender"
]
},
- "enableflow": "Flow aktivieren",
- "flow-desc": "Ermöglicht ein Verwaltungssystem zu Benutzerdiskussionen",
- "flow-talk-taken-over-comment": "/* Diese Seite wurde in ein Flow-Diskussionsboard konvertiert */",
- "log-name-flow": "Flow-Aktivitätslogbuch",
+ "enablestructureddiscussions": "Strukturierte Diskussionen aktivieren",
+ "notification-dynamic-actions-flow-board-unwatch": "Mit dem Beobachten neuer Aktivitäten zu „$1“ {{GENDER:$3|aufhören}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Du}} beobachtest nicht mehr die Seite „$1“",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Dies betrifft nicht einzelne Themen, die {{GENDER:$3|du}} beobachtest. Du kannst jederzeit [$2 diese Seite] beobachten.",
+ "notification-dynamic-actions-flow-topic-unwatch": "Mit dem Beobachten dieses Themas {{GENDER:$3|aufhören}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Du}} beobachtest nicht mehr „$1“",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Du}} kannst jederzeit [$2 dieses Thema] beobachten.",
+ "flow-desc": "Diskussionssystem",
+ "flow-talk-taken-over-comment": "/* Diese Seite wurde in ein Strukturierte-Diskussionen-Board konvertiert */",
+ "log-name-flow": "Strukturierte-Diskussionen-Aktivitätslogbuch",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|löschte}} einen [$4 Beitrag] auf „[[$3|$5]]“ auf [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|löschte}} einen Beitrag auf einem Thema auf [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|stellte}} einen [$4 Beitrag] auf „[[$3|$5]]“ auf [[$6]] wieder her",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|stellte}} einen Beitrag auf einem Thema auf [[$3]] wieder her",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|unterdrückte}} einen [$4 Beitrag] auf „[[$3|$5]]“ auf [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|unterdrückte}} einen Beitrag auf einem Thema auf [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|löschte}} einen [$4 Beitrag] auf „[[$3|$5]]“ auf [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|löschte}} einen Beitrag auf einem Thema auf [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|löschte}} das Thema „[[$3|$5]]“ auf [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|löschte}} ein Thema auf [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|stellte}} das Thema „[[$3|$5]]“ auf [[$6]] wieder her",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|stellte}} ein Thema auf [[$3]] wieder her",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|unterdrückte}} das Thema „[[$3|$5]]“ auf [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|unterdrückte}} ein Thema auf [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|löschte}} das Thema „[[$3|$5]]“ auf [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] auf [[$3]] wurde von LiquidThreads zu Flow importiert",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|löschte}} ein Thema auf [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|markierte}} das Thema „[[$3|$5]]“ auf [[$6]] als erledigt",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|markierte}} ein Thema auf [[$3]] als erledigt",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|eröffnete}} wieder das Thema „[[$3|$5]]“ auf [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|hat}} ein Thema auf [[$3]] wieder eröffnet",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] auf [[$3]] wurde von LiquidThreads zu Strukturierte Diskussionen importiert",
+ "abusefilter-edit-builder-vars-board-articleid": "Seitenkennung des Strukturierte-Diskussionen-Boards",
+ "abusefilter-edit-builder-vars-board-namespace": "Namensraum des Strukturierte-Diskussionen-Boards",
+ "abusefilter-edit-builder-vars-board-text": "Titel des Strukturierte-Diskussionen-Boards",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Vollständiger Titel des Strukturierte-Diskussionen-Boards",
"flow-user-moderated": "Moderierter Benutzer",
"flow-board-header-browse-topics-link": "Themen durchsuchen",
"flow-board-header": "Über dieses Board",
+ "flow-board-description-can-not-edit": "Nicht bearbeitbar",
"flow-board-collapse-description": "Beschreibung ausblenden",
"flow-board-expand-description": "Beschreibung anzeigen",
"flow-topic-collapse-siderail": "Mit voller Breite lesen",
@@ -52,13 +81,13 @@
"flow-post-actions": "Aktionen",
"flow-topic-actions": "Aktionen",
"flow-cancel": "Abbrechen",
- "flow-skip-summary": "Zusammenfassung überspringen",
+ "flow-skip-summary": "Überspringen",
"flow-edit-summary-placeholder": "Beschreibe kurz den Ausgang dieser Diskussion",
"flow-summary-authored": "Zusammenfassung von $1",
"flow-summary-edited": "Zusammenfassung zuletzt {{GENDER:$1|bearbeitet}} von $1",
"flow-show-change": "Änderungen anzeigen",
"flow-last-modified-by": "Zuletzt {{GENDER:$1|geändert}} von $1",
- "flow-stub-post-content": "''Aufgrund eines technischen Fehlers konnte dieser Beitrag nicht abgerufen werden.''",
+ "flow-stub-post-content": "<em>Aufgrund eines technischen Fehlers konnte dieser Inhalt nicht abgerufen werden.</em>",
"flow-newtopic-title-placeholder": "Neues Thema",
"flow-newtopic-content-placeholder": "Eine neue Nachricht zu „$1“ posten",
"flow-newtopic-header": "Ein neues Thema hinzufügen",
@@ -119,27 +148,28 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Du}} erhältst eine Benachrichtigung, wenn ein neues Thema auf diesem Board erstellt wird.",
"flow-topic-action-watchlist-add": "Dieses Thema abonnieren",
"flow-topic-action-watchlist-remove": "Nicht mehr abonnieren",
- "flow-error-allowcreation-no-usedb": "allowCreation erfordert, dass <var>$wgContentHandlerUseDB</var> auf <code>true</code> gesetzt wird",
- "flow-error-allowcreation-already-exists": "Die Seite ist bereits vorhanden, aber es ist erforderlich, dass sie es nicht ist.",
+ "flow-error-allowcreation-no-usedb": "Das Aktivieren von strukturierten Diskussionen auf einer speziellen Seite erfordert, dass <var>$wgContentHandlerUseDB</var> auf <code>true</code> gesetzt wird.",
+ "flow-error-allowcreation-already-exists": "Es ist bereits eine Seite am Ziel vorhanden, sodass ein Strukturierte-Diskussionen-Board nicht dorthin verschoben werden kann.",
"flow-error-allowcreation-flow-create-board": "Der Benutzer hat nicht das Recht „{{int:right-flow-create-board}}“",
+ "flow-error-can-not-edit-logged-out": "Du kannst derzeit nicht an der Diskussion teilnehmen. Du kannst versuchen, dich anzumelden.",
+ "flow-error-can-not-edit-logged-in": "Du kannst derzeit nicht an der Diskussion teilnehmen, da du nicht die erforderlichen Rechte hast.",
"flow-error-http": "Beim Kontaktieren des Servers ist ein Fehler aufgetreten.",
- "flow-error-other": "Ein unerwarteter Fehler ist aufgetreten.",
- "flow-error-external": "Es ist ein Fehler aufgetreten.<br />Die empfangene Fehlermeldung lautete: $1",
+ "flow-error-external": "Es ist ein Fehler aufgetreten. Die empfangene Fehlermeldung lautete: $1",
"flow-error-topic-is-locked": "Dieses Thema ist erledigt. Weitere Aktivitäten sind nicht möglich.",
"flow-error-lock-moderated-post": "Du kannst keinen moderierten Beitrag als erledigt markieren.",
- "flow-error-external-multi": "Es sind Fehler aufgetreten.<br />$1",
"flow-error-missing-content": "Der Beitrag hat keinen Inhalt. Dieser ist erforderlich, um einen Beitrag zu speichern.",
"flow-error-missing-summary": "Du musst eine Zusammenfassung angeben.",
"flow-error-missing-title": "Das Thema hat keinen Titel. Dieser ist erforderlich, um ein Thema zu speichern.",
- "flow-error-parsoid-failure": "Aufgrund eines Parsoid-Fehlers konnte der Inhalt nicht geparst werden.",
+ "flow-error-parsoid-failure": "Inhalt konnte nicht transferiert werden: Fehler beim Kontaktieren des Servers zur Konvertierung zwischen Wikitext und HTML. Bitte Internetverbindung überprüfen. Falls das Problem weiterhin bestehen bleibt, später erneut versuchen oder einen Fehlerbericht einreichen.",
+ "flow-error-protected-autoconfirmed-logged-in": "Dieses Board ist geschützt. Nur automatisch bestätigte Benutzer können an der Diskussion teilnehmen. Grund: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Dieses Board ist geschützt. Nur angemeldete Benutzer, die automatisch bestätigt sind, können an der Diskussion teilnehmen. Grund: $1",
+ "flow-error-protected-sysop-logged-in": "Dieses Board ist geschützt. Nur Benutzer mit Administratorrechten können an der Diskussion teilnehmen. Grund: $1",
+ "flow-error-protected-sysop-logged-out": "Dieses Board ist geschützt. Nur angemeldete Benutzer mit Administratorrechten können an der Diskussion teilnehmen. Grund: $1",
+ "flow-error-protected-unknown-reason": "Unbekannt",
"flow-error-missing-replyto": "Es wurde kein Parameter „Antworten an“ angegeben. Dieser Parameter ist für die „Antworten“-Aktion erforderlich.",
- "flow-error-invalid-replyto": "Der Parameter „Antworten an“ war ungültig. Der angegebene Beitrag konnte nicht gefunden werden.",
- "flow-error-delete-failure": "Das Löschen dieses Objektes ist fehlgeschlagen.",
- "flow-error-hide-failure": "Das Verstecken dieses Objektes ist fehlgeschlagen.",
"flow-error-missing-postId": "Es wurde kein Parameter „postId“ angegeben. Dieser Parameter ist zum Löschen/Wiederherstellen eines Beitrags erforderlich.",
"flow-error-invalid-postId": "Der Parameter „postId“ war ungültig. Der angegebene Beitrag ($1) konnte nicht gefunden werden.",
- "flow-error-restore-failure": "Das Wiederherstellen dieses Objektes ist fehlgeschlagen.",
- "flow-error-invalid-moderation-state": "An die Flow-API wurde ein ungültiger Wert für einen Parameter („moderationState“) übermittelt.",
+ "flow-error-invalid-moderation-state": "An die Strukturierte-Diskussionen-API wurde ein ungültiger Wert für einen Parameter („moderationState“) übermittelt.",
"flow-error-invalid-moderation-reason": "Bitte gib einen Grund für die Moderation an",
"flow-error-not-allowed": "Keine ausreichenden Berechtigungen zum Ausführen dieser Aktion",
"flow-error-not-allowed-hide": "Dieses Thema wurde versteckt.",
@@ -160,17 +190,19 @@
"flow-error-missing-prev-revision-identifier": "Eine Kennung der vorherigen Version fehlt.",
"flow-error-prev-revision-mismatch": "Ein anderer Benutzer hat diesen Beitrag soeben vor einigen Sekunden bearbeitet. Bist {{GENDER:$3|du}} sicher, dass du die letzte Änderung überschreiben möchtest?",
"flow-error-prev-revision-does-not-exist": "Die vorherige Version konnte nicht gefunden werden.",
- "flow-error-core-topic-deletion": "Um ein Thema zu löschen, verwende das Menü „…“ auf dem Flow-Board oder der [$1 Themenseite]. Besuche nicht direkt action=delete für das Thema.",
+ "flow-error-core-topic-deletion": "Um ein Thema zu löschen, verwende das Menü „…“ auf dem Strukturierte-Diskussionen-Board oder der [$1 Themenseite]. Besuche nicht direkt action=delete für das Thema.",
"flow-error-default": "Es ist ein Fehler aufgetreten.",
- "flow-error-invalid-input": "Für das Laden des Flow-Inhalts wurde ein ungültiger Wert angegeben.",
+ "flow-error-invalid-input": "Für das Laden des Strukturierte-Diskussionen-Inhalts wurde ein ungültiger Wert angegeben.",
"flow-error-invalid-title": "Es wurde ein ungültiger Seitentitel angegeben.",
+ "flow-error-invalid-parameter": "Fehlender oder ungültiger Parameter an den Methodenaufruf",
"flow-error-fail-load-history": "Der Inhalt des Verlaufs konnte nicht geladen werden.",
- "flow-error-missing-revision": "Zum Laden des Flow-Inhalts konnte keine Version gefunden werden.",
- "flow-error-fail-commit": "Der Flow-Inhalt konnte nicht gespeichert werden.",
+ "flow-error-missing-revision": "Zum Laden des Strukturierte-Diskussionen-Inhalts konnte keine Version gefunden werden.",
+ "flow-error-fail-commit": "Der Strukturierte-Diskussionen-Inhalt konnte nicht gespeichert werden.",
"flow-error-insufficient-permission": "Keine ausreichenden Berechtigungen, um auf den Inhalt zugreifen zu können.",
"flow-error-revision-comparison": "Der Unterschiedsvorgang kann nur für zwei Versionen des gleichen Beitrags ausgeführt werden.",
"flow-error-missing-topic-title": "Der Thementitel für das aktuelle Workflow konnte nicht gefunden werden.",
"flow-error-missing-metadata": "Die erforderlichen Metadaten für diese Version konnten nicht gefunden werden.",
+ "flow-error-different-page": "Das Strukturierte-Diskussionen-Workflow ist nicht mit dieser Seite verknüpft.",
"flow-error-fail-load-data": "Die angeforderten Daten konnten nicht geladen werden.",
"flow-error-invalid-workflow": "Das angeforderte Workflow konnte nicht gefunden werden.",
"flow-error-process-data": "Beim Verarbeiten der Daten in deiner Anfrage ist ein Fehler aufgetreten.",
@@ -180,12 +212,12 @@
"flow-error-no-commit": "Die angegebene Aktion konnte nicht gespeichert werden.",
"flow-error-content-too-long": "Der Inhalt ist zu groß. Der Inhalt nach der Expandierung ist beschränkt auf {{PLURAL:$1|ein Byte|$1 Bytes}}.",
"flow-error-move-topic": "Das Verschieben einer Themenseite wird derzeit nicht unterstützt.",
- "flow-error-move-no-create-permissions": "Die Berechtigung „{{int:right-flow-create-board}}“ ist zum Verschieben eines Flow-Boards erforderlich.",
"flow-error-invalid-topic-uuid-title": "Ungültiger Titel",
- "flow-error-invalid-topic-uuid": "Der angeforderte Seitentitel war ungültig. Seiten im Themennamensraum werden von Flow automatisch erstellt.",
+ "flow-error-invalid-topic-uuid": "Der angeforderte Seitentitel war ungültig. Seiten im Themennamensraum werden von strukturierten Diskussionen automatisch erstellt.",
"flow-error-unknown-workflow-id-title": "Unbekanntes Thema",
"flow-error-unknown-workflow-id": "Das angeforderte Thema ist nicht vorhanden.",
"flow-error-search": "Aufgrund eines vorübergehenden Problems konnten wir deine Suche nicht abschließen. Bitte versuche es später erneut.",
+ "flow-error-invalid-undelete": "Die Seite konnte nicht wiederhergestellt werden, da derzeit ein Diskussionsboard vorhanden ist.",
"flow-edit-header-placeholder": "Dieses Diskussions-Board beschreiben",
"flow-edit-header-submit": "Beschreibung speichern",
"flow-edit-header-submit-anonymously": "Beschreibung anonym speichern",
@@ -211,7 +243,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|versteckte}} das [$4 Thema] „$6“ (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|löschte}} das [$4 Thema] „$6“ (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|unterdrückte}} das [$4 Thema] „$6“ (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|markierte}} das [$4 Thema] $6 als erledigt (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|markierte}} das [$4 Thema] „$6“ als erledigt (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "als erledigt markiert",
"flow-rev-message-restore-topic-reason": "wieder geöffnet",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|stellte}} das [$4 Thema] „$6“ wieder her (<em>$5</em>).",
@@ -234,31 +266,73 @@
"flow-comment-moderated": "Kommentar moderiert",
"flow-last-modified": "Zuletzt geändert $1",
"flow-workflow": "workflow",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|antwortete}} auf '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 und $5 {{PLURAL:$6|ein anderer|andere}} {{GENDER:$1|antworteten}} auf '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|antwortete}} auf <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 und {{PLURAL:$5|ein anderer|$5 andere|100=mehr als 99 andere}} {{GENDER:$1|antworteten}} auf <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 hat deinen <span class=\"plainlinks\">[$5 Beitrag]</span> auf [[$3|$4]] {{GENDER:$1|bearbeitet}}.",
- "flow-notification-edit-bundle": "$1 und {{PLURAL:$6|ein anderer|$5 andere}} {{GENDER:$1|bearbeiteten}} einen <span class=\"plainlinks\">[$4 Beitrag]</span> in „$2“ auf „$3“.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|erstellte}} ein neues Thema auf '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|250=Mehr als 250 neue Themen}} auf '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 und {{PLURAL:$5|ein anderer|$5 andere|100=mehr als 99 andere}} {{GENDER:$1|bearbeiteten}} einen <span class=\"plainlinks\">[$4 Beitrag]</span> in „$2“ auf „$3“.",
+ "notification-header-flow-new-topic-v2": "Neues Thema auf <strong>$3</strong> erstellt: <bdi>„<strong>$4</strong>“</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|100=Über 99 neue Themen}} auf <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Ein neues Thema wurde auf <strong>deiner Diskussionsseite</strong> erstellt: „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|100=Über 99 neue Themen}} auf <strong>deiner Diskussionsseite</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|antwortete}} in „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Eine neue Antwort|$1 neue Antworten|100=Über 99 neue Antworten}} in „<strong>$3</strong>“.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|hinterließ}} eine Antwort auf <strong>deiner Diskussionsseite</strong> in „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Eine neue Antwort|$1 neue Antworten|100=Über 99 neue Antworten}} auf <strong>deiner Diskussionsseite</strong> in „<strong>$3</strong>“.",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Dein}} Beitrag in „<strong>$1</strong>“ wurde bearbeitet.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Dein}} Beitrag in „<strong>$1</strong>“ wurde mehrere Male bearbeitet.",
+ "notification-header-flow-post-edited-user-talk": "Ein Beitrag in „<strong>$1</strong>“ auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> wurde bearbeitet.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Ein Beitrag in „<strong>$1</strong>“ wurde mehrere Male auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> bearbeitet.",
+ "notification-header-flow-topic-renamed-v2": "Das Thema „<strong>$1</strong>“ wurde in „<strong>$2</strong>“ umbenannt.",
+ "notification-header-flow-topic-renamed-user-talk": "Das Thema „<strong>$1</strong>“ wurde auf <strong>{{GENDER:$3|deiner}} Diskussionsseite</strong> in „<strong>$2</strong>“ umbenannt.",
+ "notification-header-flow-summary-edited": "Die Zusammenfassung für „<strong>$1</strong>“ wurde aktualisiert.",
+ "notification-header-flow-summary-edited-first": "Das Thema „<strong>$1</strong>“ wurde zusammengefasst.",
+ "notification-bundle-header-flow-summary-edited": "Die Zusammenfassung für „<strong>$1</strong>“ wurde mehrere Male aktualisiert.",
+ "notification-header-flow-summary-edited-user-talk": "Die Zusammenfassung für „<strong>$1</strong>“ wurde auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> aktualisiert.",
+ "notification-header-flow-summary-edited-first-user-talk": "Das Thema „<strong>$1</strong>“ wurde auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> zusammengefasst.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Die Zusammenfassung für „<strong>$1</strong>“ wurde mehrere Male auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> aktualisiert.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|aktualisierte}} die Zusammenfassung zu $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|aktualisierte}} die Zusammenfassung zu $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 und {{PLURAL:$3|ein anderer|$3 andere|100=mehr als 99 andere}} {{GENDER:$1|aktualisierten}} die Zusammenfassung zu $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$4|dich}} in „<strong>$5</strong>“.",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$4|dich}} in der Beschreibung von <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|erwähnte}} {{GENDER:$4|dich}} in „<strong>$5</strong>“.",
+ "notification-header-flow-enabled-on-talkpage": "Neues Diskussionssystem für <strong>{{GENDER:$2|deine}} Benutzerdiskussionsseite</strong> aktiviert.",
+ "notification-header-flow-description-edited": "Die Beschreibung von <strong>$1</strong> wurde bearbeitet.",
+ "notification-header-flow-description-edited-user-talk": "Die Beschreibung wurde auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> bearbeitet.",
+ "notification-bundle-header-flow-description-edited": "Die Beschreibung von <strong>$1</strong> wurde mehrere Male bearbeitet.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Die Beschreibung wurde mehrere Male auf <strong>{{GENDER:$2|deiner}} Diskussionsseite</strong> bearbeitet.",
+ "notification-links-flow-description-edited-view-page": "Seite {{GENDER:$1|ansehen}}",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|bearbeitete}} die Beschreibung auf $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|bearbeitete}} die Beschreibung auf $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 und {{PLURAL:$3|ein anderer|$3 andere|100=mehr als 99 andere}} {{GENDER:$1|bearbeiteten}} die Beschreibung auf $2",
+ "notification-header-flow-topic-resolved": "Das Thema „<strong>$1</strong>“ wurde erledigt.",
+ "notification-header-flow-topic-reopened": "Das Thema „<strong>$1</strong>“ wurde wieder eröffnet.",
+ "notification-header-flow-topic-resolved-user-talk": "Das Thema „<strong>$1</strong>“ wurde auf <strong>deiner Diskussionsseite</strong> erledigt.",
+ "notification-header-flow-topic-reopened-user-talk": "Das Thema „<strong>$1</strong>“ wurde auf <strong>deiner Diskussionsseite</strong> wieder eröffnet.",
+ "notification-email-subject-flow-topic-resolved": "Das Thema „<strong>$2</strong>“ wurde erledigt.",
+ "notification-email-batch-body-flow-topic-resolved": "Das Thema „<strong>$2</strong>“ wurde erledigt.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|erstellte}} ein neues Thema auf <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|100=Mehr als 99 neue Themen}} auf <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|änderte}} den Titel von <span class=\"plainlinks\">[$2 $3]</span> nach „$4“ auf [[$5|$6]].",
- "flow-notification-mention": "$1 hat {{GENDER:$5|dich}} in {{GENDER:$1|seinem|ihrem|dem}} <span class=\"plainlinks\">[$2 Beitrag]</span> in „$3“ auf Seite „$4“ erwähnt.",
+ "flow-notification-mention": "$1 hat {{GENDER:$5|dich}} in {{GENDER:$1|seinem|ihrem}} <span class=\"plainlinks\">[$2 Beitrag]</span> in „$3“ auf Seite „$4“ erwähnt.",
"flow-notification-link-text-view-post": "Beitrag ansehen",
"flow-notification-link-text-view-topic": "Thema ansehen",
+ "flow-notification-link-text-view-topics": "Themen ansehen",
"flow-notification-reply-email-subject": "$2 auf $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|antwortete}} auf „$2“ auf $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 und {{PLURAL:$5|ein anderer|$4 andere}} {{GENDER:$1|antworteten}} auf „$2“ auf $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 und {{PLURAL:$4|ein anderer|$4 andere|100=mehr als 99 andere}} {{GENDER:$1|antworteten}} auf „$2“ auf $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|erwähnte}} {{GENDER:$3|dich}} auf $2",
- "flow-notification-mention-email-batch-body": "$1 hat {{GENDER:$4|dich}} in {{GENDER:$1|seinem|ihrem|dem}} Beitrag in „$2“ auf der Seite $3 erwähnt",
+ "flow-notification-mention-email-batch-body": "$1 hat {{GENDER:$4|dich}} in {{GENDER:$1|seinem|ihrem}} Beitrag in „$2“ auf der Seite $3 erwähnt",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|bearbeitete}} einen Beitrag",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|bearbeitete}} einen Beitrag in „$2“ auf der Seite $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 und {{PLURAL:$5|ein anderer|$4 andere}} {{GENDER:$1|bearbeiteten}} einen Beitrag in „$2“ auf der Seite $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 und {{PLURAL:$4|ein anderer|$4 andere|100=mehr als 99 andere}} {{GENDER:$1|bearbeiteten}} einen Beitrag in „$2“ auf der Seite $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|benannte}} dein Thema um",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|benannte}} dein Thema „$2“ in „$3“ auf der Seite $4 um",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|erstellte}} ein neues Thema auf $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|erstellte}} ein neues Thema mit dem Titel „$2“ auf $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|250=Mehr als 250 neue Themen}} auf $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Benachrichtige mich, wenn mich betreffende Aktionen in Flow stattfinden.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Ein neues Thema|$1 neue Themen|100=Mehr als 99 neue Themen}} auf $2",
+ "echo-category-title-flow-discussion": "Strukturierte Diskussion",
+ "echo-pref-tooltip-flow-discussion": "Benachrichtige mich über Aktivitäten in Themen oder zu Seiten, denen ich folge.",
"flow-link-post": "Beitrag",
"flow-link-topic": "Thema",
"flow-link-history": "Verlauf",
@@ -314,7 +388,7 @@
"flow-moderation-placeholder-unsuppress-topic": "Bitte {{GENDER:$3|erkläre}}, warum du dieses Thema nicht mehr unterdrückst.",
"flow-moderation-placeholder-undelete-topic": "Bitte {{GENDER:$3|erkläre}}, warum du dieses Thema wiederherstellst.",
"flow-moderation-placeholder-unhide-topic": "Bitte {{GENDER:$3|erkläre}}, warum du dieses Thema einblendest.",
- "flow-topic-permalink-warning": "Dieses Thema wurde gestartet auf [$2 $1]",
+ "flow-topic-permalink-warning": "Dieses Thema wurde gestartet auf [$2 $1]",
"flow-topic-permalink-warning-user-board": "Dieses Thema wurde gestartet auf dem [$2 Board von {{GENDER:$1|$1}}]",
"flow-revision-permalink-warning-post": "Dies ist ein Permanentlink zu einer einzelnen Version dieses Beitrags.\nDiese Version ist vom $1.\nDu kannst die [$5 Unterschiede von der vorherigen Version] oder andere Versionen im [$4 Verlauf] ansehen.",
"flow-revision-permalink-warning-post-first": "Dies ist ein Permanentlink zur ersten Version dieses Beitrags.\nDu kannst spätere Versionen im [$4 Verlauf] ansehen.",
@@ -324,15 +398,15 @@
"flow-revision-permalink-warning-header-first": "Dies ist ein Permanentlink zur ersten Version der Beschreibung.\nDu kannst neuere Versionen im [$2 Verlauf des Boards] ansehen.",
"flow-compare-revisions-revision-header": "Version von {{GENDER:$2|$2}} vom $1",
"flow-compare-revisions-header-post": "Diese Seite zeigt die {{GENDER:$3|Änderungen}} zwischen zwei Versionen eines Beitrags von $3 im Thema „[$5 $2]“ auf [$4 $1] an.\nDu kannst andere Versionen dieses Beitrags im [$6 Verlauf] ansehen.",
- "flow-compare-revisions-header-postsummary": "Diese Seite zeigt die Änderungen zwischen zwei Versionen einer Beitragszusammenfassung im Beitrag „[$4 $2]“ auf [$3 $1].\nDu kannst andere Versionen dieses Beitrags in seiner [$5 Verlaufsseite] ansehen.",
+ "flow-compare-revisions-header-postsummary": "Diese Seite zeigt die Änderungen zwischen zwei Versionen der Zusammenfassung des Themas „[$4 $2]“ auf [$3 $1].\nDu kannst andere Versionen dieser Themenzusammenfassung in der [$5 Verlaufsseite] ansehen.",
"flow-compare-revisions-header-header": "Diese Seite zeigt die {{GENDER:$2|Änderungen}} zwischen zwei Versionen der Beschreibung von [$3 $1] an.\nDu kannst andere Versionen der Beschreibung in ihrem [$4 Verlauf] einsehen.",
- "action-flow-create-board": "Flow-Boards an beliebigen Orten zu erstellen",
- "right-flow-create-board": "Flow-Boards an jedem Ort erstellen",
- "right-flow-hide": "Flow-Themen und -Beiträge verstecken",
- "right-flow-lock": "Flow-Themen als erledigt markieren",
- "right-flow-delete": "Flow-Themen und -Beiträge löschen",
- "right-flow-edit-post": "Flow-Beiträge von anderen Benutzern bearbeiten",
- "right-flow-suppress": "Flow-Versionen unterdrücken",
+ "action-flow-create-board": "Strukturierte-Diskussionen-Boards an beliebigen Orten zu erstellen",
+ "right-flow-create-board": "Strukturierte-Diskussionen-Boards an jedem Ort erstellen",
+ "right-flow-hide": "Strukturierte-Diskussionen-Themen und -Beiträge verstecken",
+ "right-flow-lock": "Strukturierte-Diskussionen-Themen als erledigt markieren",
+ "right-flow-delete": "Strukturierte-Diskussionen-Themen und -Beiträge löschen",
+ "right-flow-edit-post": "Strukturierte-Diskussionen-Beiträge von anderen Benutzern bearbeiten",
+ "right-flow-suppress": "Strukturierte-Diskussionen-Versionen unterdrücken",
"flow-terms-of-use-new-topic": "Mit dem Klicken auf „{{int:flow-newtopic-save}}“ stimmst du unseren Nutzungsbedingungen für dieses Wiki zu.",
"flow-terms-of-use-reply": "Mit dem Klicken auf „{{int:flow-reply-link}}“ stimmst du unseren Nutzungsbedingungen für dieses Wiki zu.",
"flow-terms-of-use-edit": "Mit dem Speichern deiner Änderungen stimmst du unseren Nutzungsbedingungen für dieses Wiki zu.",
@@ -356,24 +430,25 @@
"flow-whatlinkshere-post": "von einem [$1 Beitrag]",
"flow-whatlinkshere-header": "von der [$1 Beschreibung]",
"flow-whatlinkshere-post-summary": "aus der [$1 Zusammenfassung]",
- "flow": "Flow",
- "flow-special-desc": "Diese Spezialseite leitet mithilfe einer UUID auf ein Flow-Workflow oder einen Flow-Beitrag weiter.",
+ "structureddiscussions": "Strukturierte Diskussionen",
+ "flow-special-desc": "Diese Spezialseite leitet mithilfe einer UUID auf ein Strukturierte-Diskussionen-Workflow oder einen Strukturierte-Diskussionen-Beitrag weiter.",
"flow-special-type": "Typ",
"flow-special-type-post": "Beitrag",
"flow-special-type-workflow": "Workflow",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Es konnte kein Inhalt mit dem Typ und der UUID gefunden werden.",
- "flow-special-enableflow-legend": "Flow auf einer neuen Seite aktivieren",
- "flow-special-enableflow-page": "Seite, auf der Flow aktiviert werden soll",
- "flow-special-enableflow-header": "Erste Beschreibung des Flow-Boards (Wikitext)",
- "flow-special-enableflow-board-already-exists": "Es gibt bereits ein Flow-Board unter [[$1]].",
+ "flow-special-enableflow-legend": "Strukturierte Diskussionen auf einer neuen Seite aktivieren",
+ "flow-special-enableflow-page": "Seite, auf der strukturierte Diskussionen aktiviert werden sollen",
+ "flow-special-enableflow-header": "Erste Beschreibung des Strukturierte-Diskussionen-Boards (Wikitext)",
+ "flow-special-enableflow-board-already-exists": "Es gibt bereits ein Strukturierte-Diskussionen-Board unter [[$1]].",
"flow-special-enableflow-invalid-title": "Es wurde ein ungültiger Seitentitel angegeben",
- "flow-special-enableflow-board-creation-not-allowed": "Du bist nicht berechtigt, ein Flow-Board unter [[:$1]] zu erstellen.",
+ "flow-special-enableflow-board-creation-not-allowed": "Du bist nicht berechtigt, ein Strukturierte-Diskussionen-Board unter [[:$1]] zu erstellen.",
"flow-special-enableflow-page-is-liquidthreads": "Es gibt eine LiquidThreads-Seite unter [[:$1]].",
- "flow-special-enableflow-confirmation": "Du hast erfolgreich ein Flow-Board unter [[$1]] erstellt.",
+ "flow-special-enableflow-confirmation": "Du hast erfolgreich ein Strukturierte-Diskussionen-Board unter [[$1]] erstellt.",
"flow-conversion-archive-page-name-format": "%s/Archiv %d\n%s/Archiv%d\n%s/archiv %d\n%s/archiv%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Flow-Archiv %d\n%s/FlowArchiv%d",
- "flow-spam-confirmedit-form": "Bitte bestätige, dass du ein Mensch bist, indem du das unten stehende Captcha löst: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Strukturierte-Diskussionen-Archiv %d\n%s/StrukturierteDiskussionenArchiv%d",
+ "flow-spam-confirmedit-form": "Bitte bestätige, dass du ein Mensch bist, indem du das unten stehende CAPTCHA löst: $1",
+ "flow-spam-confirmedit-using-failure": "Es gab einen technischen Fehler mit dem CAPTCHA. Falls du deine Änderung nicht speichern kannst, kopiere bitte deinen Text, lade die Seite erneut und versuche es noch einmal.",
"flow-embedding-unsupported": "Diskussionen können noch nicht eingebettet werden.",
"mw-ui-unsubmitted-confirm": "Du hast auf dieser Seite ungespeicherte Änderungen. Bist du sicher, dass du diese Seite verlassen möchtest und die Arbeit verloren gehen soll?",
"flow-post-undo-hide": "Verstecken rückgängig gemacht",
@@ -382,112 +457,27 @@
"flow-topic-undo-hide": "Verstecken rückgängig gemacht",
"flow-topic-undo-delete": "Löschen rückgängig gemacht",
"flow-topic-undo-suppress": "Unterdrücken rückgängig gemacht",
- "flow-importer-lqt-moved-thread-template": "Durch LQT verschobenen Thread-Stub zu Flow konvertiert",
+ "flow-importer-lqt-moved-thread-template": "Durch LQT verschobenen Thread-Stub zu Strukturierte Diskussionen konvertiert",
"flow-importer-lqt-moved-thread-template-content": "Dieser Beitrag von {{{author}}} wurde am {{{date}}} verschoben. Du kannst ihn finden unter [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "LiquidThreads-Seite nach Flow konvertiert",
+ "flow-importer-lqt-converted-template": "LiquidThreads-Seite nach Strukturierte Diskussionen konvertiert",
"flow-importer-lqt-converted-template-content": "Die frühere Versionsgeschichte wurde für Wiederherstellungszwecke am {{#time: Y-m-d|{{{date}}} }} unter <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> archiviert.",
"flow-importer-lqt-converted-archive-template": "Archiv für konvertierte LiquidThreads-Seite",
- "flow-importer-lqt-converted-archive-template-content": "Diese Seite ist eine archivierte LiquidThreads-Seite. '''Die Inhalte dieser Seite nicht bearbeiten.''' Richte bitte zusätzliche Kommentare an die [[{{{from}}}|aktuelle Diskussionsseite]].",
- "flow-importer-wt-converted-template": "Wikitext-Diskussionsseite zu Flow konvertiert",
+ "flow-importer-lqt-converted-archive-template-content": "Diese Seite ist eine archivierte LiquidThreads-Seite. <strong>Die Inhalte dieser Seite nicht bearbeiten.</strong> Richte bitte zusätzliche Kommentare an die [[{{{from}}}|aktuelle Diskussionsseite]].",
+ "flow-importer-wt-converted-template": "Wikitext-Diskussionsseite zu Strukturierte Diskussionen konvertiert",
"flow-importer-wt-converted-template-content": "Die frühere Diskussion wurde am {{#time: Y-m-d|{{{date}}} }} unter <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> archiviert.",
"flow-importer-wt-converted-archive-template": "Archiv für konvertierte Wikitext-Diskussionsseite",
- "flow-importer-wt-converted-archive-template-content": "Diese Seite ist ein Archiv. '''Die Inhalte dieser Seite nicht bearbeiten.''' Richte bitte zusätzliche Kommentare an die [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|aktuelle Diskussionsseite]].",
+ "flow-importer-wt-converted-archive-template-content": "Diese Seite ist ein Archiv. <strong>Die Inhalte dieser Seite nicht bearbeiten.</strong> Richte bitte zusätzliche Kommentare an die [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|aktuelle Diskussionsseite]].",
"flow-importer-lqt-suppressed-user-template": "LQT-Beitrag wurde mit einem unterdrückten Benutzer importiert",
"flow-importer-lqt-suppressed-user-template-content": "Diese Version wurde von LiquidThreads mit einem unterdrückten Benutzer importiert. Er wurde dem aktuellen Benutzer neu zugeordnet.",
"flow-importer-lqt-different-author-signature-template": "LQT-Beitrag mit einem anderen Signaturbenutzer importiert",
- "flow-importer-lqt-different-author-signature-template-content": "''Dieser Beitrag wurde abgespeichert von [[User:{{{authorUser}}}|{{{authorUser}}}]], aber signiert als [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-param-submodule": "Das aufzurufende Flow-Submodul.",
- "apihelp-flow-param-page": "Die Seite, auf die die Aktion angewandt werden soll.",
- "apihelp-flow-example-1": "Die Beschreibung von „[[Talk:Sandbox]]“ bearbeiten",
- "apihelp-flow+close-open-topic-param-reason": "Grund für das Sperren oder Freigeben des Themas.",
- "apihelp-flow+edit-header-description": "Bearbeitet die Beschreibung eines Boards.",
- "apihelp-flow+edit-header-param-prev_revision": "Kennung der aktuellen Beschreibungsversion, die auf Bearbeitungskonflikte überprüft werden soll.",
- "apihelp-flow+edit-header-param-content": "Inhalt für die Beschreibung.",
- "apihelp-flow+edit-header-param-format": "Format der Beschreibung (wikitext oder html)",
- "apihelp-flow+edit-header-example-1": "Bearbeitet die Beschreibung von [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Bearbeitet den Inhalt eines Beitrags.",
- "apihelp-flow+edit-post-param-postId": "Beitragskennung.",
- "apihelp-flow+edit-post-param-content": "Inhalt für den Beitrag.",
- "apihelp-flow+edit-post-param-format": "Format des Beitrags (wikitext oder html)",
- "apihelp-flow+edit-post-example-1": "Bearbeitet einen Beitrag in [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Bearbeitet den Titel eines Themas.",
- "apihelp-flow+edit-title-param-prev_revision": "Versionskennung der aktuellen Titelversion zum Erkennen von Bearbeitungskonflikten.",
- "apihelp-flow+edit-title-param-content": "Inhalt für den Titel.",
- "apihelp-flow+edit-title-example-1": "Bearbeitet den Titel von [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Bearbeitet den Inhalt einer Themenzusammenfassung.",
- "apihelp-flow+edit-topic-summary-param-summary": "Inhalt für die Zusammenfassung.",
- "apihelp-flow+edit-topic-summary-param-format": "Format der Zusammenfassung (wikitext oder html)",
- "apihelp-flow+edit-topic-summary-example-1": "Bearbeitet die Zusammenfassung von [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Sperrt ein Flow-Thema oder gibt es wieder frei.",
- "apihelp-flow+lock-topic-param-reason": "Grund für das Sperren oder Freigeben des Themas. Beachte bitte, dass der Wiki-Flow-Client hier „Als erledigt markiert“ verwendet und optionale zusätzliche Informationen in die Zusammenfassung platziert.",
- "apihelp-flow+lock-topic-example-1": "Sperrt [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Moderiert einen Flow-Beitrag.",
- "apihelp-flow+moderate-post-param-reason": "Grund für die Moderation.",
- "apihelp-flow+moderate-post-param-postId": "Kennung des zu moderierenden Beitrags.",
- "apihelp-flow+moderate-post-example-1": "Löscht einen Beitrag im Thema [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Moderiert ein Flow-Thema.",
- "apihelp-flow+moderate-topic-param-reason": "Grund für die Moderation.",
- "apihelp-flow+moderate-topic-example-1": "Löscht das Thema [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-param-topic": "Text für den Titel des neuen Themas.",
- "apihelp-flow+new-topic-param-content": "Inhalt für die erste Antwort des Themas.",
- "apihelp-flow+new-topic-param-format": "Format des Ausgangsbeitrags des neuen Themas (wikitext oder html)",
- "apihelp-flow+new-topic-example-1": "Erstellt ein neues Thema auf [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Antwortet auf einen Beitrag.",
- "apihelp-flow+reply-param-replyTo": "Kennung des Beitrags, auf den geantwortet werden soll.",
- "apihelp-flow+reply-param-content": "Inhalt für den neuen Beitrag.",
- "apihelp-flow+reply-param-format": "Format des neuen Beitrags (wikitext oder html)",
- "apihelp-flow+reply-example-1": "Antwortet auf einen Beitrag auf [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
- "apihelp-flow+view-header-description": "Board-Beschreibung ansehen.",
- "apihelp-flow+view-header-param-revId": "Lädt diese anstelle der aktuellsten Version.",
- "apihelp-flow+view-header-example-1": "Ruft die Beschreibung von [[Talk:Sandbox]] als Wikitext ab",
- "apihelp-flow+view-post-description": "Betrachtet einen Beitrag.",
- "apihelp-flow+view-post-param-postId": "Kennung des anzuzeigenden Beitrags.",
- "apihelp-flow+view-post-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
- "apihelp-flow+view-post-example-1": "Ruft den Inhalt von [[Topic:S2tycnas4hcucw8w]] als Wikitext ab",
- "apihelp-flow+view-post-history-description": "Zeigt die Versionsgeschichte eines Beitrags an.",
- "apihelp-flow+view-post-history-param-postId": "Kennung des Beitrags, für den die Versionsgeschichte angezeigt werden soll.",
- "apihelp-flow+view-post-history-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
- "apihelp-flow+view-topic-description": "Betrachtet ein Thema.",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] ansehen",
- "apihelp-flow+view-topic-history-description": "Zeigt die Versionsgeschichte eines Themas an.",
- "apihelp-flow+view-topic-history-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
- "apihelp-flow+view-topic-summary-description": "Betrachtet eine Themenzusammenfassung.",
- "apihelp-flow+view-topic-summary-param-format": "Format, in dem der Inhalt zurückgegeben werden soll.",
- "apihelp-flow+view-topic-summary-param-revId": "Lädt diese anstelle der aktuellsten Version.",
- "apihelp-flow+view-topic-summary-example-1": "Zeigt die Zusammenfassung für [[Topic:S2tycnas4hcucw8w]] als Wikitext an",
- "apihelp-flow+view-topiclist-description": "Betrachtet eine Liste der Themen.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Sortierrichtung der Themen.",
- "apihelp-flow+view-topiclist-param-sortby": "Sortieroption der Themen, entweder <kbd>updated</kbd> (sortiert nach der Zeit der Aktualisierung des Themas) oder <kbd>newest</kbd> (sortiert nach der Zeit der Erstellung des Themas).",
- "apihelp-flow+view-topiclist-param-savesortby": "Speichert die Sortieroption in den Benutzereinstellungen, falls festgelegt.",
- "apihelp-flow+view-topiclist-param-limit": "Anzahl der abzurufenden Themen.",
- "apihelp-flow+view-topiclist-example-1": "Themen zu [[Talk:Sandbox]] auflisten",
- "apihelp-flow-parsoid-utils-description": "Konvertiert Text zwischen Wikitext und HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Format, aus dem Inhalte konvertiert werden.",
- "apihelp-flow-parsoid-utils-param-to": "Format, zu dem Inhalte konvertiert werden.",
- "apihelp-flow-parsoid-utils-param-content": "Zu konvertierender Inhalt.",
- "apihelp-flow-parsoid-utils-param-title": "Titel der Seite. Kann nicht zusammen mit $1pageid verwendet werden.",
- "apihelp-flow-parsoid-utils-param-pageid": "Kennung der Seite. Kann nicht zusammen mit $1title verwendet werden.",
- "apihelp-flow-parsoid-utils-example-1": "Wandelt den Wikitext <nowiki>'''lorem''' ''blah''</nowiki> in HTML um",
- "apihelp-query+flowinfo-description": "Ruft Basis-Flow-Informationen über eine Seite ab.",
- "apihelp-flow+undo-edit-header-description": "Informationen beziehen, die zum Rückgängigmachen der Bearbeitung der Beschreibung nötig sind.",
- "apihelp-flow+undo-edit-header-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
- "apihelp-flow+undo-edit-header-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
- "apihelp-flow+undo-edit-header-example-1": "Bezieht Informationen zum Rückgängigmachen einer Bearbeitung in der Beschreibung von [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Bezieht die zum Rückgängigmachen einer Beitragsbearbeitung nötigen Informationen.",
- "apihelp-flow+undo-edit-post-param-postId": "Kennung des Beitrages, dessen Bearbeitung rückgängig gemacht werden soll.",
- "apihelp-flow+undo-edit-post-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
- "apihelp-flow+undo-edit-post-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
- "apihelp-flow+undo-edit-post-example-1": "Bezieht Informationen zum Rückgängigmachen einer Beitragsbearbeitung in einem bestimmten Thema.",
- "apihelp-flow+undo-edit-topic-summary-description": "Bezieht die zum Rückgängigmachen einer Bearbeitung der Themenzusammenfassung nötigen Informationen.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Versionskennung, bei der mit dem Rückgängigmachen begonnen werden soll.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Versionskennung, auf die zurückgesetzt werden soll.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Bezieht Informationen zum Rückgängigmachen einer Bearbeitung der Themenzusammenfassung eines bestimmten Themas",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Dieser Beitrag wurde abgespeichert von [[User:{{{authorUser}}}|{{{authorUser}}}]], aber signiert als [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Bearbeitet",
"flow-edited-by": "Bearbeitet von $1",
- "flow-lqt-redirect-reason": "Eingeschlafenen LiquidThreads-Beitrag zum konvertierten Flow-Beitrag umgeleitet",
- "flow-talk-conversion-move-reason": "Konvertierung der Wikitext-Diskussion zu Flow von $1",
- "flow-talk-conversion-archive-edit-reason": "Wikitext-Diskussion-zu-Flow-Konvertierung",
+ "flow-edited-by-header": "Boardbeschreibung bearbeitet von $1",
+ "flow-edited-by-topic-title": "Thementitel bearbeitet von $1",
+ "flow-lqt-redirect-reason": "Eingeschlafenen LiquidThreads-Beitrag zum konvertierten Strukturierte-Diskussionen-Beitrag umgeleitet",
+ "flow-talk-conversion-move-reason": "Konvertierung der Wikitext-Diskussion zu Strukturierte Diskussionen von $1",
+ "flow-talk-conversion-archive-edit-reason": "Wikitext-Diskussion-zu-Strukturierte-Diskussionen-Konvertierung",
"flow-previous-diff": "← Ältere Bearbeitung",
"flow-next-diff": "Neuere Bearbeitung →",
"flow-undo": "rückgängig machen",
@@ -498,9 +488,9 @@
"flow-undo-edit-post": "Beitrag bearbeiten",
"flow-undo-edit-content": "Die Bearbeitung kann rückgängig gemacht werden. Bitte überprüfe den unten stehenden Vergleich, um zu verifizieren, dass das ist, was du tun möchtest, und speichere die Änderungen unten, um die Rückgängigmachung der Bearbeitung abzuschließen.",
"flow-undo-edit-failure": "Die Bearbeitung konnte aufgrund kollidierender dazwischenliegender Bearbeitungen nicht rückgängig gemacht werden.",
- "group-flow-bot": "Flow-Bots",
- "group-flow-bot-member": "Flow-Bot",
- "grouppage-flow-bot": "Project:Flow-Bots",
+ "group-flow-bot": "Strukturierte-Diskussionen-Bots",
+ "group-flow-bot-member": "Strukturierte-Diskussionen-Bot",
+ "grouppage-flow-bot": "Project:Strukturierte-Diskussionen-Bots",
"flow-ve-mention-context-item-label": "Erwähnung",
"flow-ve-mention-inspector-title": "Erwähnung",
"flow-ve-mention-inspector-remove-label": "Entfernen",
@@ -510,30 +500,36 @@
"flow-ve-mention-inspector-invalid-user": "Der Benutzername „$1“ ist nicht registriert.",
"flow-wikitext-editor-help": "Wikitext $1.",
"flow-wikitext-editor-help-and-preview": "Wikitext $1 und du kannst jederzeit $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|verwendet Markup]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|verwendet Markup]]",
"flow-wikitext-editor-help-preview-the-result": "eine Vorschau des Ergebnisses anzeigen",
- "flow-wikitext-switch-editor-tooltip": "Zum VisualEditor wechseln",
+ "flow-wikitext-switch-editor-tooltip": "Zum visuellen Editor wechseln",
"flow-ve-switch-editor-tool-title": "Zum Wikitext-Editor wechseln",
"flow-mark-revision-patrolled-link-text": "Diese Seite als kontrolliert markieren",
"flow-mark-revision-patrolled-link-title": "Diese Seite als kontrolliert markieren",
"flow-mark-diff-patrolled-link-text": "Als kontrolliert markieren",
"flow-mark-diff-patrolled-link-title": "Als kontrolliert markieren",
- "flow-talk-page-beta-feature-message": "Flow auf der Benutzerdiskussionsseite",
- "flow-talk-page-beta-feature-description": "Aktiviert auf {{GENDER:|deiner}} Benutzerdiskussionsseite ein neu strukturiertes Diskussionssystem. Flow vereinfacht Diskussionsseiten mit klaren Orten zum Schreiben und Antworten und erlaubt Benachrichtigungen auf Diskussionsebene. Vorhandene Wikitext-Diskussionen werden in ein Archiv verschoben. Diese Funktion ist nicht automatisch aktiviert. Benutzer müssen es getrennt aktivieren. Das Deaktivieren dieser Funktion verschiebt das Flow-Board in eine Unterseite und stellt die vorherige Diskussionsseite wieder her.",
- "flow-notification-link-text-enabled-on-talkpage": "Benutzerdiskussionsseite ansehen",
+ "flow-talk-page-beta-feature-message": "Strukturierte Diskussionen auf der Benutzerdiskussionsseite",
+ "flow-talk-page-beta-feature-description": "Aktiviert auf {{GENDER:|deiner}} Benutzerdiskussionsseite ein neu strukturiertes Diskussionssystem. Strukturierte Diskussionen vereinfachen Diskussionsseiten mit klaren Orten zum Schreiben und Antworten und erlaubt Benachrichtigungen auf Diskussionsebene. Diese Funktion ist nicht automatisch aktiviert. Benutzer müssen sie ausdrücklich aktivieren.<br /><br />Vorhandene Wikitext-Diskussionen werden in ein Archiv verschoben. Das Deaktivieren dieser Funktion verschiebt das Strukturierte-Diskussionen-Board auf eine Unterseite und stellt die vorherige Diskussionsseite wieder her. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Mehr über die Aktivierung erfahren]].",
+ "flow-notification-link-text-enabled-on-talkpage": "Benutzerdiskussionsseite {{GENDER:|ansehen}}",
"flow-notification-enabled-on-talkpage-title": "Neues Diskussionssystem für {{GENDER:$1|deine}} Benutzerdiskussionsseite aktiviert<br /><small>Verfügbar unter [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Neues Diskussionssystem auf $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, das neue Wikidiskussionssystem, wurde auf {{GENDER:$1|deiner}} {{SITENAME}}-Benutzerdiskussionsseite aktiviert. Du erhältst weitere Informationen im Betafunktionen-Abschnitt in {{GENDER:$1|deinen}} Einstellungen. Dort kannst du auch Rückmeldungen geben oder das neue System jederzeit wieder deaktivieren.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Strukturierte Diskussionen, das neue Wikidiskussionssystem, wurde auf {{GENDER:$1|deiner}} {{SITENAME}}-Benutzerdiskussionsseite aktiviert. Du erhältst weitere Informationen im Betafunktionen-Abschnitt in {{GENDER:$1|deinen}} Einstellungen. Dort kannst du auch Rückmeldungen geben oder das neue System jederzeit wieder deaktivieren.",
"flow-beta-feature-add-archive-template-edit-summary": "Archivvorlage hinzugefügt",
"flow-beta-feature-remove-archive-template-edit-summary": "Archivvorlage entfernt",
- "flow-dialog-cancelconfirm-title": "Bist du dir sicher?",
- "flow-dialog-cancelconfirm-message": "Bist du dir sicher, dass du ohne zuerst zu speichern abbrechen möchtest?",
+ "flow-dialog-cancelconfirm-title": "Bist {{GENDER:|du}} dir sicher?",
+ "flow-dialog-cancelconfirm-message": "Bist {{GENDER:|du}} dir sicher, dass du ohne zuerst zu speichern abbrechen möchtest?",
"flow-dialog-cancelconfirm-keep": "Mit dem Bearbeiten fortfahren",
"flow-dialog-cancelconfirm-discard": "Änderungen verwerfen",
+ "flow-optin-archive-wikitext": "Wikitextseite verschoben, um Platz für ein Diskussionsboard zu schaffen.",
+ "flow-optin-archive-flow-board": "Diskussionsboardseite verschoben, um Platz für eine Wikitextseite zu schaffen.",
+ "flow-optin-restore-wikitext": "Archivierte Wikitextseite wiederhergestellt.",
+ "flow-optin-restore-flow-board": "Archiviertes Diskussionsboard wiederhergestellt.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Willkommen}} auf {{GENDER:$1|deiner}} neuen Benutzerdiskussionsseite",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Deine}} Diskussionsseite ist der Ort, wo andere Autoren {{GENDER:$1|dich}} kontaktieren können. Mit Flow ist es leichter, neue Themen zu erstellen und Diskussionen zu verfolgen.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Deine}} Diskussionsseite ist der Ort, wo andere Autoren {{GENDER:$1|dich}} kontaktieren können. Mit strukturierten Diskussionen ist es leichter, neue Themen zu erstellen und Diskussionen zu verfolgen.",
"flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|Deine}} alten Diskussionen finden",
"flow-guidedtour-optin-find-old-conversations-description": "Frühere Diskussionen wurden auf eine Archivseite verschoben.",
"flow-guidedtour-optin-feedback": "Gib uns {{GENDER:$1|deine}} Rückmeldung!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kannst weitere Informationen im Betafunktionen-Abschnitt erhalten. Dort kannst du auch Rückmeldungen geben oder das neue System jederzeit deaktivieren."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kannst weitere Informationen im Betafunktionen-Abschnitt erhalten. Dort kannst du auch Rückmeldungen geben oder das neue System jederzeit deaktivieren.",
+ "flow-action-not-page": "Das Seitenobjekt ist eine Instanz der falschen Klasse",
+ "flow-action-wrong-title-content-model": "Die Seite wird von Strukturierte Diskussionen verwaltet, aber die Titelklasse zeigt an, dass das Inhaltsmodell „$1“ ist. Dies ist eine Falschkonfiguration oder widersprüchlicher Status. Zum Beispiel könnte dies tatsächlich eine Nicht-Strukturierte-Diskussionen-Seite in einem Strukturierte-Diskussionen-Namensraum sein und <code>rev_content_model</code> ist nicht eingetragen."
}
diff --git a/Flow/i18n/diq.json b/Flow/i18n/diq.json
new file mode 100644
index 00000000..96f77330
--- /dev/null
+++ b/Flow/i18n/diq.json
@@ -0,0 +1,64 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kumkumuk",
+ "Mirzali",
+ "Asmen",
+ "1917 Ekim Devrimi"
+ ]
+ },
+ "enablestructureddiscussions": "Rodiyayışi feal ke",
+ "flow-user-moderated": "Moderator Karber",
+ "flow-board-header-browse-topics-link": "Bıweni mewzuyan",
+ "flow-edit-header-link": "Akerden bıvurne",
+ "flow-topic-moderated-reason-prefix": "Sebeb:",
+ "flow-hide-header-content": "$2 ra {{GENDER:$1|nımıt}}",
+ "flow-delete-header-content": "$2 ra {{GENDER:$1|esteriya}}",
+ "flow-post-actions": "Kerdışi",
+ "flow-topic-actions": "Kerdışi",
+ "flow-cancel": "Bıtexelne",
+ "flow-skip-summary": "Xulasa bıvurne",
+ "flow-summary-authored": "Xulasaya $1",
+ "flow-show-change": "Vurriyayışan bımotne",
+ "flow-newtopic-title-placeholder": "Mewzuyo newe",
+ "flow-newtopic-header": "Mewzuyo newe cı ke",
+ "flow-newtopic-save": "Mewzu vıraze",
+ "flow-newtopic-start-placeholder": "Mewzuyo newe vıraze",
+ "flow-reply-topic-placeholder": "\"$2\" sero {{GENDER:$1|vatış}}",
+ "flow-reply-topic-title-placeholder": "Cewabê $1",
+ "flow-reply-link": "{{GENDER:$1|Cewab}}",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Teşekur}}}}",
+ "flow-history-action-delete-post": "bestere",
+ "flow-history-action-hide-post": "bınımne",
+ "flow-history-action-undelete-post": "Mebesterne",
+ "flow-history-action-unhide-post": "Menımne",
+ "flow-history-action-restore-post": "Timar bike",
+ "flow-history-action-unlock-topic": "Fına Ake",
+ "flow-post-action-view": "Greyo Daimi",
+ "flow-post-action-post-history": "Tarix",
+ "flow-post-action-delete-post": "Bestere",
+ "flow-post-action-hide-post": "Bınımne",
+ "flow-post-action-edit-post": "Bıvurne",
+ "flow-post-action-edit-post-submit": "Vıryayışan qeyd kı",
+ "flow-post-action-edit-post-submit-anonymously": "Vurnayışanê anonima qeyd ke",
+ "flow-post-action-undelete-post": "Mebesterne",
+ "flow-post-action-unhide-post": "Menımne",
+ "flow-post-action-restore-post": "Timar bike",
+ "flow-post-action-undo-moderation": "Peyser biya",
+ "flow-topic-action-view": "Greyo Daimi",
+ "flow-topic-action-watchlist": "Lista seyrkerdışi",
+ "flow-topic-action-edit-title": "Sernamey bıvurnê",
+ "flow-topic-action-history": "Tarix",
+ "flow-topic-action-hide-topic": "Mewzuy bınımne",
+ "flow-topic-action-delete-topic": "Mewzuy Bestere",
+ "flow-topic-action-undo-moderation": "Peyser biya",
+ "flow-error-protected-unknown-reason": "Nêzanaye",
+ "flow-error-unknown-workflow-id-title": "Mewzuyo nêzanaye",
+ "flow-rc-topic-of-board": "$2 de $1",
+ "flow-history-day": "Ewro",
+ "echo-category-title-flow-discussion": "Rodiyayış",
+ "flow-moderation-confirmation-delete-topic": "Ena mewzu esteriya ya.",
+ "group-flow-bot": "Botê rodayışi",
+ "group-flow-bot-member": "Botê rodayışi",
+ "grouppage-flow-bot": "Project:Botê rodayışi"
+}
diff --git a/Flow/i18n/dty.json b/Flow/i18n/dty.json
index 91c1701f..7b286fc1 100644
--- a/Flow/i18n/dty.json
+++ b/Flow/i18n/dty.json
@@ -1,8 +1,13 @@
{
"@metadata": {
"authors": [
- "राम प्रसाद जोशी"
+ "राम प्रसाद जोशी",
+ "Nirajan pant"
]
},
+ "notification-dynamic-actions-flow-board-unwatch": "\"$1\"मी नौला कृयाकलाप तक्द {{GENDER:$3|बन्द}} अरऽ",
+ "notification-dynamic-actions-flow-topic-unwatch": "यो विषय हेद्द {{GENDER:$3|बन्द }} अरऽ",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|तम}} आब \"$1\" नाइहेद्दार्‍याऽ",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|तम}} [$2 this topic] जज्ज्याईँलै तक्द सकन्छऽ",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|धन्यवाद देओ}}}}"
}
diff --git a/Flow/i18n/ee.json b/Flow/i18n/ee.json
index f2d50c50..18c477eb 100644
--- a/Flow/i18n/ee.json
+++ b/Flow/i18n/ee.json
@@ -6,7 +6,7 @@
},
"flow-topic-action-resummarize-topic": "Trɔ asi le nyatia ŋu",
"flow-wikitext-editor-help": "Wikinuŋɔŋlɔ $1.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Nuŋɔŋlɔɖoɖo|zãa atsiãfianu]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|zãa atsiãfianu]]",
"flow-wikitext-editor-help-preview-the-result": "kpɔ ŋuɖoɖoa ƒe kpɔɖeŋu",
"flow-wikitext-switch-editor-tooltip": "Trɔe Yi VisualEditor",
"flow-ve-switch-editor-tool-title": "Trɔe Yi Wikinuŋɔnu"
diff --git a/Flow/i18n/el.json b/Flow/i18n/el.json
index 9b46f330..8eb91009 100644
--- a/Flow/i18n/el.json
+++ b/Flow/i18n/el.json
@@ -4,22 +4,284 @@
"Astralnet",
"Evropi",
"Geraki",
- "Nikosguard"
+ "Nikosguard",
+ "Glavkos"
]
},
+ "enablestructureddiscussions": "Ενεργοποίηση Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Σταματήστε}} την παρακολούθηση νέας δραστηριότητας στο «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Δεν}} παρακολουθείτε πλέον τη σελίδα «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Αυτό δεν θα επηρεάσει επιμέρους θέματα {{GENDER:$3|που}} παρακολουθείτε. Μπορείτε να παρακολουθήσετε [$2 αυτή τη σελίδα] ανά πάσα στιγμή.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Σταματήστε}} να παρακολουθείτε αυτό το νήμα",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Δεν}} παρακολουθείτε πια το «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Μπορείτε}} να παρακολουθήσετε [$2 αυτό το νήμα] οποιαδήποτε στιγμή.",
+ "flow-desc": "Σύστημα συζήτησης",
+ "flow-talk-taken-over-comment": "/* Αυτή η σελίδα έχει μετατραπεί σε πίνακα συζήτησης Flow */",
+ "log-name-flow": "Καταγραφή δραστηριοτήτων Flow",
+ "logentry-delete-flow-delete-post": "{{GENDER:$2|Ο|Η}} $1 διέγραψε μια [$4 δημοσίευση] στο \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 διέγραψε μια ανάρτηση σε ένα θέμα στο [[$3]]",
+ "logentry-delete-flow-restore-post": "{{GENDER:$2|Ο|Η}} $1 αποκατέστησε μια [$4 δημοσίευση] στο \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 επανέφερε μια ανάρτηση σε ένα θέμα στο [[$3]]",
+ "logentry-suppress-flow-suppress-post": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε μια [$4 δημοσίευση] στο \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε μια ανάρτηση σε ένα θέμα στο [[$3]]",
+ "logentry-suppress-flow-restore-post": "{{GENDER:$2|Ο|Η}} $1 διέγραψε μια [$4 δημοσίευση] στο \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 διέγραψε μια ανάρτηση σε ένα θέμα στο [[$3]]",
+ "logentry-delete-flow-delete-topic": "{{GENDER:$2|Ο|Η}} $1 διέγραψε το θέμα \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 διέγραψε ένα θέμα στο [[$3]]",
+ "logentry-delete-flow-restore-topic": "{{GENDER:$2|Ο|Η}} $1 αποκατέστησε το θέμα \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 επανέφερε ένα θέμα στο [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε το θέμα \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε ένα θέμα στο [[$3]]",
+ "logentry-suppress-flow-restore-topic": "{{GENDER:$2|Ο|Η}} $1 διέγραψε το θέμα \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 διέγραψε ένα θέμα στο [[$3]]",
+ "logentry-lock-flow-lock-topic": "{{GENDER:$2|Ο|Η}} $1 επισήμανε το θέμα \"[[$3|$5]]\" ως επιλυμένο στην [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 επισήμανε ένα θέμα ως επιλυμένο στο [[$3]]",
+ "logentry-lock-flow-restore-topic": "{{GENDER:$2|Ο|Η}} $1 ξανάνοιξε το θέμα \"[[$3|$5]]\" στην [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Ο|Η}} $1 ξανάνοιξε ένα θέμα στο [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] στην [[$3]] εισήχθει από το LiquidThreads στο Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "ID σελίδας του πίνακα Flow",
+ "abusefilter-edit-builder-vars-board-namespace": "Namespace του πίνακα Flow",
+ "abusefilter-edit-builder-vars-board-text": "Τίτλος του πίνακα Flow",
+ "flow-user-moderated": "Χρήστης υπό επιτήρηση",
+ "flow-board-header-browse-topics-link": "Περιήγηση στα θέματα",
+ "flow-board-header": "Σχετικά με αυτό τον πίνακα",
+ "flow-board-description-can-not-edit": "Μη επεξεργάσιμο",
+ "flow-board-collapse-description": "Απόκρυψη περιγραφής",
+ "flow-board-expand-description": "Εμφάνιση περιγραφής",
+ "flow-topic-collapse-siderail": "Ανάγνωση σε πλήρες πλάτος",
+ "flow-topic-expand-siderail": "Ανάγνωση σε σταθερό πλάτος",
+ "flow-edit-header-link": "Επεξεργασία περιγραφής",
+ "flow-post-moderated-toggle-hide-show": "Εμφάνιση σχολίου που αποκρύφθηκε από {{GENDER:$1|τον|την}} $2",
"flow-post-moderated-toggle-delete-show": "Εμφάνιση σχολίου {{GENDER:$1|διαγραφή}} $2",
+ "flow-post-moderated-toggle-suppress-show": "Εμφάνιση σχολίου που καταστάλθηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-post-moderated-toggle-hide-hide": "Εμφάνιση σχολίου που αποκρύφθηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-post-moderated-toggle-delete-hide": "Απόκρυψη σχολίου που διαγράφτηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-post-moderated-toggle-suppress-hide": "Απόκρυψη σχολίου που καταστάλθηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-topic-moderated-reason-prefix": "Αιτία:",
+ "flow-hide-post-content": "Αυτό το σχόλιο αποκρύφθηκε από {{GENDER:$1|τον|την}} $1 ([$2 ιστορικό])",
+ "flow-hide-title-content": "Αυτό το θέμα αποκρύφθηκε από {{GENDER:$1|τον|την}} $1",
+ "flow-hide-header-content": "Αποκρύφθηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-delete-post-content": "Αυτό το σχόλιο διαγράφτηκε από {{GENDER:$1|τον|την}} $1 ([$2 ιστορικό])",
+ "flow-delete-title-content": "Αυτό το θέμα διαγράφτηκε από {{GENDER:$1|τον|την}} $1",
+ "flow-delete-header-content": "Διαγράφτηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-suppress-post-content": "Αυτό το θέμα καταστάλθηκε από {{GENDER:$1|τον|την}} $1 ([$2 history])",
+ "flow-suppress-title-content": "Αυτό το θέμα καταστάλθηκε από {{GENDER:$1|τον|την}} $1",
+ "flow-suppress-header-content": "Καταστάλθηκε από {{GENDER:$1|τον|την}} $2",
+ "flow-suppress-usertext": "<em>Το όνομα χρήστη καταστάλθηκε</em>",
+ "flow-post-actions": "Ενέργειες",
"flow-topic-actions": "Ενέργειες",
- "flow-preview": "Προεπισκόπηση",
+ "flow-cancel": "Ακύρωση",
+ "flow-skip-summary": "Παράβλεψη",
+ "flow-edit-summary-placeholder": "Περιγράψτε εν συντομία τα αποτελέσματα αυτής της συζήτησης",
+ "flow-summary-authored": "Σύνοψη από $1",
+ "flow-summary-edited": "Σύνοψη με τελευταία επεξεργασία από {{GENDER:$1|τον|την}} $1",
+ "flow-show-change": "Εμφάνιση αλλαγών",
+ "flow-last-modified-by": "Τελευταία τροποποίηση από {{GENDER:$1|τον|την}} $1",
+ "flow-stub-post-content": "<em>Λόγω ενός τεχνικού σφάλματος, δεν ήταν δυνατό να ανακτηθεί αυτή η δημοσίευση.</em>",
+ "flow-newtopic-title-placeholder": "Νέο θέμα",
"flow-newtopic-content-placeholder": "Δημοσιεύστε ένα νέο μήνυμα στην \"$1\"",
+ "flow-newtopic-header": "Προσθήκη νέου θέματος",
+ "flow-newtopic-save": "Προσθήκη θέματος",
+ "flow-newtopic-save-anonymously": "Προσθήκη θέματος ανώνυμα",
+ "flow-newtopic-start-placeholder": "Εκκίνηση νέου θέματος",
"flow-newtopic-first-heading": "Ξεκινήσετε ένα νέο θέμα στην $1",
+ "flow-summarize-topic-placeholder": "Παρακαλούμε συνοψίστε αυτή τη συζήτηση",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Σχολιάστε}} στο \"$2\"",
+ "flow-reply-topic-title-placeholder": "Απαντήστε στο \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|Απάντηση}}",
+ "flow-reply-link-anonymously": "Απάντηση ανώνυμα",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Ευχαριστήστε}}}}",
+ "flow-thank-link-title": "{{GENDER:$1|Ευχαριστήστε}} δημόσια {{GENDER:$2|τον συμμετέχοντα|την συμμετέχουσα}}",
+ "flow-history-action-suppress-post": "καταστείλτε",
+ "flow-history-action-delete-post": "διαγράψτε",
+ "flow-history-action-hide-post": "αποκρύψτε",
+ "flow-history-action-unsuppress-post": "αντικαταστολή",
+ "flow-history-action-undelete-post": "επαναφορά",
+ "flow-history-action-unhide-post": "επανεμφανίστε",
+ "flow-history-action-restore-post": "επαναφέρετε",
+ "flow-history-action-lock-topic": "επιλύστε",
+ "flow-history-action-unlock-topic": "ξανανοίξτε",
+ "flow-post-edited": "Η δημοσίεστη επεξεργάστηκε από {{GENDER:$1|τον|την}} $1 $2",
+ "flow-post-action-view": "Σταθερός σύνδεσμος",
"flow-post-action-post-history": "Ιστορικό",
+ "flow-post-action-suppress-post": "Καταστολή",
+ "flow-post-action-delete-post": "Διαγραφή",
+ "flow-post-action-hide-post": "Απόκρυψη",
"flow-post-action-edit-post": "Επεξεργασία",
+ "flow-post-action-edit-post-submit": "Αποθήκευση αλλαγών",
+ "flow-post-action-edit-post-submit-anonymously": "Αποθήκευση αλλαγών ανώνυμα",
+ "flow-post-action-unsuppress-post": "Αντικαταστολή",
+ "flow-post-action-undelete-post": "Αποδιαγραφή",
+ "flow-post-action-unhide-post": "Επανεμφάνιση",
+ "flow-post-action-restore-post": "Επαναφορά",
+ "flow-post-action-undo-moderation": "Αναίρεση",
+ "flow-topic-action-view": "Σταθερός σύνδεσμος",
+ "flow-topic-action-watchlist": "Λίστα παρακολούθησης",
+ "flow-topic-action-edit-title": "Επεξεργασία τίτλου",
+ "flow-topic-action-history": "Ιστορικό",
+ "flow-topic-action-hide-topic": "Απόκρυψη θέματος",
+ "flow-topic-action-delete-topic": "Διαγραφή θέματος",
+ "flow-topic-action-lock-topic": "Επισήμανση ως επιλυμένο",
+ "flow-topic-action-unlock-topic": "Ξανάνοιγμα θέματος",
+ "flow-topic-action-summarize-topic": "Συνόψιση",
+ "flow-topic-action-resummarize-topic": "Επεξεργασία σύνοψης θέματος",
+ "flow-topic-action-update-topic-summary": "Ενημέρωση σύνοψης",
+ "flow-topic-action-suppress-topic": "Καταστολή θέματος",
+ "flow-topic-action-unhide-topic": "Επανεμφάνιση θέματος",
+ "flow-topic-action-undelete-topic": "Αποδιαγραφή θέματος",
+ "flow-topic-action-unsuppress-topic": "Αντικαταστολή θέματος",
+ "flow-topic-action-restore-topic": "Επαναφορά θέματος",
+ "flow-topic-action-undo-moderation": "Αναίρεση",
"flow-topic-notification-subscribe-title": "Αυτό το θέμα έχει προστεθεί στη λίστα παρακολούθησής {{GENDER:$1|σας}}.",
"flow-topic-notification-subscribe-description": "Θα {{GENDER:$1|λαμβάνετε}} ειδοποιήσεις για όλες τις δραστηριότητες σχετικά με αυτό το θέμα.",
"flow-board-notification-subscribe-title": "Είστε {{GENDER:$1|εγγεγραμμένος|εγγεγραμμένη}} σε αυτό τον πίνακα συζητήσεων!",
"flow-board-notification-subscribe-description": "{{GENDER:$1|Θα}} λάβετε μια ειδοποίηση όταν υπάρχει ένα νέο θέμα που έχει δημιουργηθεί σε αυτόν τον πίνακα.",
+ "flow-topic-action-watchlist-add": "Εγγραφή σε αυτό το θέμα",
+ "flow-topic-action-watchlist-remove": "Κατάργηση εγγραφής",
+ "flow-error-allowcreation-no-usedb": "Ενεργοποίηση του Flow σε μια συγκεκριμένη σελίδα απαιτεί το <var>$wgContentHandlerUseDB</var> να είναι <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Υπάρχει ήδη σελίδα στον προορισμό, οπότε ένας πίνακας Flow δεν μπορεί να μεταφερθεί εκεί.",
+ "flow-error-allowcreation-flow-create-board": "Ο χρήστης δεν έχει την άδεια «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Επί του παρόντος δεν είστε σε θέση να συμμετάσχετε. Μπορείτε να δοκιμάστε να συνδεθείτε.",
+ "flow-error-can-not-edit-logged-in": "Επί του παρόντος δεν είστε σε θέση να συμμετέχετε, επειδή δεν έχετε τα απαιτούμενα δικαιώματα.",
+ "flow-error-http": "Παρουσιάστηκε ένα σφάλμα κατά την επικοινωνία με το διακομιστή.",
+ "flow-error-external": "Παρουσιάστηκε ένα σφάλμα. Το μήνυμα λάθους που ελήφθη ήταν: $1",
+ "flow-error-topic-is-locked": "Αυτό το θέμα έχει επιλυθεί, οπότε περαιτέρω δραστηριότητα δεν είναι δυνατή.",
+ "flow-error-lock-moderated-post": "Δεν μπορείτε να επισημάνετε μια περιορισμένη ανάρτηση ως επιλυθείσα.",
+ "flow-error-missing-content": "Η ανάρτηση δεν έχει περιεχόμενο. Απαιτείται περιεχόμενο για να αποθηκευτεί μια ανάρτηση.",
+ "flow-error-missing-summary": "Θα πρέπει να υποβάλετε μια σύνοψη.",
+ "flow-error-missing-title": "Το θέμα δεν έχει τίτλο. Απαιτείται τίτλος για να αποθηκεύσετε ένα θέμα.",
+ "flow-error-protected-autoconfirmed-logged-in": "Αυτός ο πίνακας είναι προστατευμένος. Μόνο αυτοεπιβεβαιωμένοι χρήστες μπορούν να συμμετάσχουν. Αιτία: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Αυτός ο πίνακας είναι προστατευμένος. Μόνο συνδεδεμένοι χρήστες που είναι αυτοεπιβεβαιωμένοι μπορούν να συμμετάσχουν. Αιτία: $1",
+ "flow-error-protected-sysop-logged-in": "Αυτός ο πίνακας είναι προστατευμένος. Μόνο χρήστες με διαχειριστικά δικαιώματα μπορούν να συμμετάσχουν. Αιτία: $1",
+ "flow-error-protected-sysop-logged-out": "Αυτός ο πίνακας είναι προστατευμένος. Μόνο συνδεδεμένοι χρήστες με διαχειριστικά δικαιώματα μπορούν να συμμετάσχουν. Αιτία: $1",
+ "flow-error-protected-unknown-reason": "Άγνωστο",
+ "flow-error-missing-replyto": "Δεν καταχωρήθηκε παράμετρος \"απάντηση σε\". Αυτή η παράμετρος είναι απαραίτητη για την ενέργεια \"απάντηση\".",
+ "flow-error-invalid-moderation-reason": "Παρακαλούμε δώστε αιτία για τη μετρίαση.",
+ "flow-error-not-allowed": "Μη επαρκή δικαιώματα για εκτέλεση αυτής της ενέργειας.",
+ "flow-error-not-allowed-hide": "Αυτό το θέμα έχει αποκρυφτεί.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Δεν μπορείτε να απαντήσετε επειδή αυτό το θέμα έχει αποκρυφτεί.",
+ "flow-error-not-allowed-delete": "Το θέμα έχει διαγραφεί.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Δεν μπορείτε να απαντήσετε επειδή αυτό το θέμα έχει διαγραφεί.",
+ "flow-error-not-allowed-suppress": "Αυτό το θέμα έχει διαγραφεί.",
+ "flow-error-missing-header-content": "Πρέπει να καταχωρήσετε μια περιγραφή.",
+ "flow-error-unknown-workflow-id-title": "Άγνωστο θέμα",
+ "flow-error-unknown-workflow-id": "Το θέμα που ζητήθηκε δεν υπάρχει.",
+ "flow-error-search": "Δεν μπορούμε να ολοκληρώσουμε την αναζήτησή σας λόγου προσωρινού προβλήματος. Παρακαλώ προσπαθήστε ξανά αργότερα.",
+ "flow-edit-header-placeholder": "Περιγράψτε αυτό τον πίνακα συζητήσεων",
+ "flow-edit-header-submit": "Αποθήκευση περιγραφής",
+ "flow-edit-header-submit-anonymously": "Αποθήκευση περιγραφής ανώνυμα",
+ "flow-edit-title-submit": "Αλλαγή τίτλου",
+ "flow-edit-title-submit-anonymously": "Αλλάξτε τον τίτλο ανώνυμα",
+ "flow-edit-post-submit": "Υποβολή αλλαγών",
+ "flow-edit-post-submit-anonymously": "Αποθήκευση αλλαγών ανώνυμα",
+ "flow-rev-message-edit-post": "{{GENDER:$2|Ο|Η}} $1 επεξεργάστηκε ένα [$3 σχόλιο] στο «$4»",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Επεξεργάστηκε}} μια ανάρτηση",
+ "flow-rev-message-reply": "{{GENDER:$2|Ο|Η}} $1 [$3 σχολίασε] στο \"$4\" (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|σχόλιο|σχόλια}}</strong> {{PLURAL:$1|έχει|έχουν}} πρόστεθεί",
+ "flow-rev-message-new-post": "{{GENDER:$2|Ο|Η}} $1 δημιούργησε το θέμα «[$3 $4]»",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Δημιούργησε}} νέο θέμα",
+ "flow-rev-message-edit-title": "{{GENDER:$2|Ο|Η}} $1 άλλαξε τον τίτλο θέματος από \"$5\" σε \"[$3 $4]\"",
+ "flow-rev-message-create-header": "{{GENDER:$2|Ο|Η}} $1 άλλαξε την περιγραφή",
+ "flow-rev-message-edit-header": "{{GENDER:$2|Ο|Η}} $1 επεξεργάστηκε την περιγραφή",
+ "flow-rev-message-create-topic-summary": "{{GENDER:$2|Ο|Η}} $1 δημιούργησε σύνοψη θέματος στο $3",
+ "flow-rev-message-edit-topic-summary": "{{GENDER:$2|Ο|Η}} $1 επεξεργάστηκε τη σύνοψη θέματος στο $3",
+ "flow-rev-message-hid-post": "{{GENDER:$2|Ο|Η}} $1 απέκρυψε ένα [$4 σχόλιο] στο \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "{{GENDER:$2|Ο|Η}} $1 διέγραψε ένα [$4 σχόλιο] στο \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε ένα [$4 σχόλιο] στο \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "{{GENDER:$2|Ο|Η}} $1 αποκατέστησε ένα [$4 σχόλιο] στο \"$6\" (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "{{GENDER:$2|Ο|Η}} $1 απέκρυψε το [$4 θέμα] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "{{GENDER:$2|Ο|Η}} $1 διέγραψε το [$4 θέμα] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "{{GENDER:$2|Ο|Η}} $1 κατέστειλε το [$4 θέμα] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "{{GENDER:$2|Ο|Η}} $1 σήμανε το [$4 θέμα] \"$6\" ως επιλυμένο (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "επισημασμένο ως επιλυμένο",
+ "flow-rev-message-restore-topic-reason": "ξανανοιγμένο",
+ "flow-rev-message-restored-topic": "{{GENDER:$2|Ο|Η}} $1 επανέφερε το [$4 θέμα] \"$6\" (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 στη $2",
+ "flow-board-history": "Ιστορικό «$1»",
+ "flow-board-history-empty": "Ο πίνακας επί του παρόντος δεν έχει ιστορικό.",
+ "flow-topic-history": "Ιστορικό θέματος «$1»",
+ "flow-post-history": "Ιστορικό ανάρτησης «σχολίου από {{GENDER:$2|τον|την}} $2»",
"flow-history-last4": "Τελευταίες 4 ώρες",
"flow-history-day": "Σήμερα",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />{{GENDER:$1|Ο|Η}} $1 απάντησε στην '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />{{GENDER:$1|Ο|Η}} $1 και $5 {{PLURAL:$6|άλλος|άλλοι}} απάντησαν στην '''$3'''."
+ "flow-history-week": "Τελευταία εβδομάδα",
+ "flow-history-pages-topic": "Εμφανίζεται στον [$1 πίνακα «$2»]",
+ "flow-history-pages-post": "Εμφανίζεται στο [$1 $2]",
+ "flow-topic-comments": "{{PLURAL:$1|Ένα σχόλιο|$1 σχόλια|0=Γίνετε {{GENDER:$2|ο πρώτος|η πρώτη}} που θα σχολιάσει!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Εμφάνιση σχολίου|Εμφάνιση σχολίων}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Απόκρυψη σχολίου|Απόκρυψη σχολίων}}",
+ "flow-last-modified": "Τελευταία επεξεργασία $1",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />{{GENDER:$1|Ο|Η}} $1 απάντησε στην <strong>$4</strong>",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />{{GENDER:$1|Ο|Η}} $1 και {{PLURAL:$5|άλλος ένας|άλλοι $5|100=99+ ακόμη}} απάντησαν στην <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Ένα νέο θέμα δημιουργήθηκε στη <strong>σελίδα συζήτησής σας</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Ένα νέο θέμα|$1 νέα θέματα|100=99+ νέα θέματα}} στη <strong>σελίδα συζήτησής σας</strong>.",
+ "notification-header-flow-post-reply": "{{GENDER:$2|Ο|Η}} $1 απάντησε στο \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Μια νέα απάντηση|$1 νέες απαντήσεις|100=99+ νέες απαντήσεις}} στη «<strong>$3</strong>».",
+ "notification-header-flow-post-reply-user-talk": "{{GENDER:$2|Ο|Η}} $1 ανάρτησε μια απάντηση στη <strong>σελίδα συζήτησής σας</strong> στο «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Μια νέα απάντηση|$1 νέες απαντήσεις|100=99+ νέες απαντήσεις}} στη <strong>σελίδα συζήτησής σας</strong> στο «<strong>$3</strong>».",
+ "notification-header-flow-mention-post": "{{GENDER:$2|Ο|Η}} $1 {{GENDER:$4|σας}} ανάφερε στο «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "{{GENDER:$2|Ο|Η}} $1 {{GENDER:$4|σας}} ανάφερε στην περιγραφή του <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "{{GENDER:$2|Ο|Η}} $1 {{GENDER:$4|σας}} ανάφερε στο «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Νέο σύστημα συζητήσεων ενεργοποιήθηκε για την <strong>σελίδα συζήτησης χρήστη {{GENDER:$2|σας}}</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Προβολή}} σελίδας",
+ "notification-email-subject-flow-description-edited": "{{GENDER:$2|Ο|Η}} $1 επεξεργάστηκε την περιγραφή στο $2.",
+ "notification-email-batch-body-flow-description-edited": "{{GENDER:$1|Ο|Η}} $1 επεξεργάστηκε την περιγραφή στο $2.",
+ "flow-notification-link-text-view-post": "Εμφάνιση ανάρτησης",
+ "flow-notification-link-text-view-topic": "Εμφάνιση θέματος",
+ "flow-notification-link-text-view-topics": "Εμφάνιση θεμάτων",
+ "flow-notification-reply-email-subject": "$2 στη $3",
+ "flow-notification-reply-email-batch-body": "{{GENDER:$1|Ο|Η}} $1 απάντησε στο «$2» στη $3",
+ "flow-notification-reply-email-batch-bundle-body": "Οι $1 και {{PLURAL:$4|άλλος ένας|$4 άλλοι|100=99+ άλλοι}} {{GENDER:$1|απάντησαν}} στο «$2» στη $3",
+ "flow-notification-mention-email-subject": "{{GENDER:$1|Ο|Η}} $1 {{GENDER:$3|σας}} ανέφερε στο $2",
+ "flow-notification-mention-email-batch-body": "{{GENDER:$1|Ο|Η}} $1 {{GENDER:$4|σας}} ανάφερε στην ανάρτησή {{GENDER:$1|του|της}} στο «$2» στη $3",
+ "flow-notification-edit-email-subject": "{{GENDER:$1|Ο|Η}} $1 επεξεργάστηκε μια ανάρτηση",
+ "flow-notification-edit-email-batch-body": "{{GENDER:$1|Ο|Η}} $1 επεξεργάστηκε μια ανάρτηση στο «$2» στη $3",
+ "echo-category-title-flow-discussion": "Συζήτηση Flow",
+ "echo-pref-tooltip-flow-discussion": "Ειδοποίηση σχετικά με τη δραστηριότητα στα θέματα ή στις σελίδες ακολουθώ.",
+ "flow-link-post": "ανάρτηση",
+ "flow-link-topic": "θέμα",
+ "flow-link-history": "ιστορικό",
+ "flow-link-post-revision": "εκδοχή ανάρτησης",
+ "flow-link-topic-revision": "εκδοχή θέματος",
+ "flow-link-header-revision": "εκδοχή περιγραφής",
+ "flow-link-summary-revision": "εκδοχή σύνοψης",
+ "flow-moderation-title-suppress-post": "Καταστολή ανάρτησης;",
+ "flow-moderation-title-delete-post": "Διαγραφή ανάρτησης;",
+ "flow-moderation-title-hide-post": "Απόκρυψη ανάρτησης;",
+ "flow-moderation-title-unsuppress-post": "Αντικαταστολή ανάρτησης;",
+ "flow-moderation-title-undelete-post": "Αποδιαγραφή ανάρτησης;",
+ "flow-moderation-title-unhide-post": "Επανεμφάνιση ανάρτησης;",
+ "flow-moderation-placeholder-suppress-post": "Καταστολή",
+ "flow-moderation-confirm-suppress-post": "Καταστολή",
+ "flow-moderation-confirm-delete-post": "Διαγραφή",
+ "flow-moderation-confirm-hide-post": "Απόκρυψη",
+ "flow-moderation-confirm-unsuppress-post": "Αντικαταστολή",
+ "flow-moderation-confirm-undelete-post": "Επαναφορά",
+ "flow-moderation-confirm-unhide-post": "Επανεμφάνιση",
+ "flow-moderation-confirm-suppress-topic": "Καταστολή",
+ "flow-moderation-confirm-delete-topic": "Διαγραφή",
+ "flow-moderation-confirm-hide-topic": "Απόκρυψη",
+ "flow-moderation-confirm-unsuppress-topic": "Αντικαταστολή",
+ "flow-moderation-confirm-undelete-topic": "Επαναφορά",
+ "flow-moderation-confirm-unhide-topic": "Επανεμφάνιση",
+ "flow-revision-permalink-warning-header-first": "Αυτός είναι ένας μόνιμος σύνδεσμος στην πρώτη έκδοση της περιγραφής.\nΜπορείτε να δείτε νεότερες εκδόσεις στη [$2 σελίδα ιστορικού του πίνακα].",
+ "flow-anon-warning": "Δεν έχετε συνδεθεί. Για να λάβετε απόδοση πατρότητας με το όνομά σας αντί για τη διεύθυνση IP, μπορείτε να [$1 συνδεθείτε] ή να [$2 δημιουργήσετε έναν λογαριασμό].",
+ "flow-topic-first-heading": "Θέμα στο $1",
+ "flow-no-more-fwd": "Δεν υπάρχουν παλαιότερα θέματα",
+ "flow-newest-topics": "Νεότερα θέματα",
+ "flow-recent-topics": "Πρόσφατα ενεργά θέματα",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Διαβάζετε}} τα νεότερα θέματα πρώτα. Πατήστε για περισσότερες επιλογές ταξινόμησης.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Διαβάζετε}} τα πιο πρόσφατα ενεργά θέματα πρώτα. Πατήστε για περισσότερες επιλογές ταξινόμησης.",
+ "flow-conversion-archive-page-name-format": "%s/Αρχείο %d\n%s/Αρχείο%d\n%s/αρχείο %d\n%s/αρχείο%d",
+ "flow-importer-wt-converted-template": "Wikitext σελίδας συζήτησης που μετατράπηκε σε Flow",
+ "flow-importer-wt-converted-template-content": "Προηγούμενη συζήτηση αρχειοθετήθηκε στην <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> στις {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-edited-by": "Υπέστη επεξεργασία από $1",
+ "flow-wikitext-editor-help-and-preview": "Το κείμενο wiki $1 και μπορείτε να $2 οποτεδήποτε.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|χρησιμοποιεί κώδικα]]",
+ "flow-wikitext-editor-help-preview-the-result": "κάνετε προεπισκόπηση του αποτελέσματος",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Καλώς ήρθατε}} στη νέα σελίδα συζήτησης χρήστη {{GENDER:$1|σας}}",
+ "flow-guidedtour-optin-welcome-description": "Η σελίδα συζήτησής {{GENDER:$1|σας}} είναι ο χώρος όπου άλλοι συντάκτες μπορούν να έρθουν σε επαφή μαζί {{GENDER:$1|σας}}. Με το Flow, είναι πιο εύκολο να ξεκινήσετε νέα θέματα και να παρακολουθείτε τις συνομιλίες.",
+ "flow-guidedtour-optin-find-old-conversations": "Βρείτε παλιές συζητήσεις {{GENDER:$1|σας}}",
+ "flow-guidedtour-optin-find-old-conversations-description": "Προηγούμενες συζητήσεις έχουν μετακινηθεί σε μια σελίδα αρχείου.",
+ "flow-guidedtour-optin-feedback": "Δώστε μας τα σχόλιά {{GENDER:$1|σας}}!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Μπορείτε}} να πάρετε περισσότερες πληροφορίες, να παρέχετε ανατροφοδότηση, ή να απενεργοποιήσετε το νέο σύστημα οποιαδήποτε στιγμή από την ενότητα λειτουργιών Beta."
}
diff --git a/Flow/i18n/en-gb.json b/Flow/i18n/en-gb.json
index 30c17e16..87c5f31a 100644
--- a/Flow/i18n/en-gb.json
+++ b/Flow/i18n/en-gb.json
@@ -3,14 +3,16 @@
"authors": [
"Shirayuki",
"Mdann52",
- "Caliburn"
+ "Caliburn",
+ "Aursani",
+ "Andibing",
+ "Anomie"
]
},
"flow-summarize-topic-placeholder": "Please summarise this discussion",
"flow-topic-action-summarize-topic": "Summarise",
"flow-error-no-render": "The specified action was not recognised.",
- "flow-summarize-topic-submit": "Summarise",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mentioned}} {{GENDER:$4|you}} in {{GENDER:$1|his|her|their}} post in \"$2\" on \"$3\"",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mentioned}} {{GENDER:$4|you}} in {{GENDER:$1|his|her|their}} post in \"$2\" on $3",
"flow-previous-diff": "← Older edit",
"flow-next-diff": "Newer edit →"
}
diff --git a/Flow/i18n/en.json b/Flow/i18n/en.json
index 80903650..d50ab875 100644
--- a/Flow/i18n/en.json
+++ b/Flow/i18n/en.json
@@ -13,22 +13,45 @@
"Amir E. Aharoni"
]
},
- "enableflow": "Enable Flow",
- "flow-desc": "Workflow management system",
- "flow-talk-taken-over-comment": "/* This page has been converted into a Flow discussion board */",
- "log-name-flow": "Flow activity log",
+ "enablestructureddiscussions": "Enable Structured Discussions",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Stop}} watching new activity on \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|You}} are no longer watching the page \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "This will not affect individual topics {{GENDER:$3|you}} are watching. You can watch [$2 this page] anytime.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Stop}} watching this topic",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|You}} are no longer watching \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|You}} can watch [$2 this topic] anytime.",
+ "flow-desc": "Discussion system",
+ "flow-talk-taken-over-comment": "/* This page has been converted into a Structured Discussions board */",
+ "log-name-flow": "Structured Discussions activity log",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|deleted}} a [$4 post] on \"[[$3|$5]]\" on [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|deleted}} a post on a topic on [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restored}} a [$4 post] on \"[[$3|$5]]\" on [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|restored}} a post on a topic on [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|suppressed}} a [$4 post] on \"[[$3|$5]]\" on [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|suppressed}} a post on a topic on [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|deleted}} a [$4 post] on \"[[$3|$5]]\" on [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|deleted}} a post on a topic on [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|deleted}} topic \"[[$3|$5]]\" on [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|deleted}} a topic on [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restored}} topic \"[[$3|$5]]\" on [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|restored}} a topic on [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suppressed}} topic \"[[$3|$5]]\" on [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|suppressed}} a topic on [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|deleted}} topic \"[[$3|$5]]\" on [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] on [[$3]] was imported from LiquidThreads to Flow",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|deleted}} a topic on [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marked}} topic \"[[$3|$5]]\" as resolved on [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|marked}} a topic as resolved on [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reopened}} topic \"[[$3|$5]]\" on [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|reopened}} a topic on [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] on [[$3]] was imported from LiquidThreads to Structured Discussions",
+ "abusefilter-edit-builder-vars-board-articleid": "Page ID of Structured Discussions board",
+ "abusefilter-edit-builder-vars-board-namespace": "Namespace of Structured Discussions board",
+ "abusefilter-edit-builder-vars-board-text": "Title of Structured Discussions board",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Full title of Structured Discussions board",
"flow-user-moderated": "Moderated user",
"flow-board-header-browse-topics-link": "Browse topics",
"flow-board-header": "About this board",
+ "flow-board-description-can-not-edit": "Not editable",
"flow-board-collapse-description": "Hide description",
"flow-board-expand-description": "Show description",
"flow-topic-collapse-siderail": "Read at full width",
@@ -56,14 +79,14 @@
"flow-post-actions": "Actions",
"flow-topic-actions": "Actions",
"flow-cancel": "Cancel",
- "flow-skip-summary": "Skip summary",
+ "flow-skip-summary": "Skip",
"flow-edit-summary-placeholder": "Describe briefly the outcome of this discussion",
"flow-summary-authored": "Summary by $1",
"flow-summary-edited": "Summary last {{GENDER:$1|edited}} by $1",
"flow-show-change": "Show changes",
"flow-last-modified-by": "Last {{GENDER:$1|modified}} by $1",
"flow-system-usertext": "{{SITENAME}}",
- "flow-stub-post-content": "''Due to a technical error, this post could not be retrieved.''",
+ "flow-stub-post-content": "<em>Due to a technical error, this content could not be retrieved.</em>",
"flow-newtopic-title-placeholder": "New topic",
"flow-newtopic-content-placeholder": "Post a new message to \"$1\"",
"flow-newtopic-header": "Add a new topic",
@@ -125,27 +148,28 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|You}} will get a notification when a new topic is created on this board.",
"flow-topic-action-watchlist-add": "Subscribe to this topic",
"flow-topic-action-watchlist-remove": "Unsubscribe",
- "flow-error-allowcreation-no-usedb": "allowCreation requires <var>$wgContentHandlerUseDB</var> to be <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Page already exists, but was required not to",
+ "flow-error-allowcreation-no-usedb": "Enabling Structured Discussions on a specific page requires <var>$wgContentHandlerUseDB</var> to be <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Page already exists at destination, so a Structured Discussions board can not be moved there.",
"flow-error-allowcreation-flow-create-board": "User does not have the \"{{int:right-flow-create-board}}\" permission",
+ "flow-error-can-not-edit-logged-out": "You currently are not able to participate. You can try logging in.",
+ "flow-error-can-not-edit-logged-in": "You currently are not able to participate, because you do not have the required rights.",
"flow-error-http": "An error occurred while contacting the server.",
- "flow-error-other": "An unexpected error occurred.",
- "flow-error-external": "An error occurred.<br />The error message received was: $1",
+ "flow-error-external": "An error occurred. The error message received was: $1",
"flow-error-topic-is-locked": "This topic is resolved, so further activity is not possible.",
"flow-error-lock-moderated-post": "You cannot mark a moderated post as resolved.",
- "flow-error-external-multi": "Errors were encountered.<br />$1",
"flow-error-missing-content": "Post has no content. Content is required to save a post.",
"flow-error-missing-summary": "You must submit a summary.",
"flow-error-missing-title": "Topic has no title. Title is required to save a topic.",
- "flow-error-parsoid-failure": "Unable to parse content due to a Parsoid failure.",
+ "flow-error-parsoid-failure": "Unable to transfer content: Error contacting the server for conversion between wikitext and HTML. Please check your Internet connection or try again later if the problem persists. If you still get this error please file a bug",
+ "flow-error-protected-autoconfirmed-logged-in": "This board is protected. Only autoconfirmed users can participate. Reason: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "This board is protected. Only logged in users who are autoconfirmed can participate. Reason: $1",
+ "flow-error-protected-sysop-logged-in": "This board is protected. Only users with administrator privileges can participate. Reason: $1",
+ "flow-error-protected-sysop-logged-out": "This board is protected. Only logged in users with administrator privileges can participate. Reason: $1",
+ "flow-error-protected-unknown-reason": "Unknown",
"flow-error-missing-replyto": "No \"replyTo\" parameter was supplied. This parameter is required for the \"reply\" action.",
- "flow-error-invalid-replyto": "\"replyTo\" parameter was invalid. The specified post could not be found.",
- "flow-error-delete-failure": "Deletion of this item failed.",
- "flow-error-hide-failure": "Hiding this item failed.",
"flow-error-missing-postId": "No \"postId\" parameter was supplied. This parameter is required to manipulate a post.",
"flow-error-invalid-postId": "\"postId\" parameter was invalid. The specified post ($1) could not be found.",
- "flow-error-restore-failure": "Restoration of this item failed.",
- "flow-error-invalid-moderation-state": "An invalid value for a parameter ('moderationState') was submitted to the Flow API.",
+ "flow-error-invalid-moderation-state": "An invalid value for a parameter ('moderationState') was submitted to the Structured Discussions API.",
"flow-error-invalid-moderation-reason": "Please provide a reason for the moderation.",
"flow-error-not-allowed": "Insufficient permissions to execute this action.",
"flow-error-not-allowed-hide": "This topic has been hidden.",
@@ -166,18 +190,20 @@
"flow-error-missing-prev-revision-identifier": "Previous revision identifier is missing.",
"flow-error-prev-revision-mismatch": "Another user just edited this post a few seconds ago. Are {{GENDER:$3|you}} sure you want to overwrite the recent change?",
"flow-error-prev-revision-does-not-exist": "Could not find the previous revision.",
- "flow-error-core-topic-deletion": "To delete a topic, use the ... menu on the Flow board or [$1 topic page]. Do not visit action=delete for the topic directly.",
+ "flow-error-core-topic-deletion": "To delete a topic, use the ... menu on the Structured Discussions board or [$1 topic page]. Do not visit action=delete for the topic directly.",
"flow-error-default": "An error has occurred.",
- "flow-error-invalid-input": "Invalid value was provided for loading Flow content.",
+ "flow-error-invalid-input": "Invalid value was provided for loading Structured Discussions content.",
"flow-error-invalid-title": "Invalid page title was provided.",
"flow-error-invalid-action": "{{int:nosuchactiontext}}",
+ "flow-error-invalid-parameter": "Missing or invalid parameter to method call",
"flow-error-fail-load-history": "Failed to load history content.",
- "flow-error-missing-revision": "Could not find a revision to load Flow content.",
- "flow-error-fail-commit": "Failed to save the Flow content.",
+ "flow-error-missing-revision": "Could not find a revision to load Structured Discussions content.",
+ "flow-error-fail-commit": "Failed to save the Structured Discussions content.",
"flow-error-insufficient-permission": "Insufficient permission to access the content.",
"flow-error-revision-comparison": "Diff operation can only be done for two revisions belonging to the same post.",
"flow-error-missing-topic-title": "Could not find the topic title for current workflow.",
"flow-error-missing-metadata": "Could not find required metadata for this revision.",
+ "flow-error-different-page": "The Structured Discussions workflow is not associated with this page.",
"flow-error-fail-load-data": "Failed to load the requested data.",
"flow-error-invalid-workflow": "Could not find the requested workflow.",
"flow-error-process-data": "An error has occurred while processing the data in your request.",
@@ -187,12 +213,12 @@
"flow-error-no-commit": "The specified action could not be saved.",
"flow-error-content-too-long": "The content is too large. Content after expansion is limited to $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-move-topic": "Moving a topic page is currently not supported.",
- "flow-error-move-no-create-permissions": "The \"{{int:right-flow-create-board}}\" permission is required to move a Flow board.",
"flow-error-invalid-topic-uuid-title": "Bad title",
- "flow-error-invalid-topic-uuid": "The requested page title was invalid. Pages in the Topic namespace are automatically created by Flow.",
+ "flow-error-invalid-topic-uuid": "The requested page title was invalid. Pages in the Topic namespace are automatically created by Structured Discussions.",
"flow-error-unknown-workflow-id-title": "Unknown topic",
"flow-error-unknown-workflow-id": "The requested topic does not exist.",
"flow-error-search": "We could not complete your search due to a temporary problem. Please try again later.",
+ "flow-error-invalid-undelete": "The page couldn't be restored because there is currently a discussion board in place.",
"flow-edit-header-placeholder": "Describe this discussion board",
"flow-edit-header-submit": "Save description",
"flow-edit-header-submit-anonymously": "Save description anonymously",
@@ -239,8 +265,8 @@
"flow-rev-message-deleted-topic-irc": "$2 {{GENDER:$2|deleted}} the topic \"$6\" ($5)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suppressed}} the [$4 topic] \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-topic-irc": "$2 {{GENDER:$2|suppressed}} the topic \"$6\" ($5)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marked}} the [$4 topic] $6 as resolved (<em>$5</em>)",
- "flow-rev-message-locked-topic-irc": "$2 {{GENDER:$2|resolved}} the topic $6 ($5)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marked}} the [$4 topic] \"$6\" as resolved (<em>$5</em>)",
+ "flow-rev-message-locked-topic-irc": "$2 {{GENDER:$2|resolved}} the topic \"$6\" ($5)",
"flow-rev-message-lock-topic-reason": "marked as resolved",
"flow-rev-message-restore-topic-reason": "reopened",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restored}} the [$4 topic] \"$6\" (<em>$5</em>)",
@@ -255,7 +281,7 @@
"flow-history-week": "Last week",
"flow-history-pages-topic": "Appears on [$1 \"$2\" board]",
"flow-history-pages-post": "Appears on [$1 $2]",
- "flow-topic-comments": "{{PLURAL:$1|$1 comment|$1 comments|0={{GENDER:$2|Be the first}} to comment!}}",
+ "flow-topic-comments": "{{PLURAL:$1|One comment|$1 comments|0={{GENDER:$2|Be the first}} to comment!}}",
"flow-show-comments-title": "{{PLURAL:$1|View comment|View comments}}",
"flow-hide-comments-title": "{{PLURAL:$1|Hide comment|Hide comments}}",
"flow-comment-restored": "Restored comment",
@@ -264,31 +290,86 @@
"flow-comment-moderated": "Moderated comment",
"flow-last-modified": "Last modified about $1",
"flow-workflow": "workflow",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|responded}} on '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 and $5 {{PLURAL:$6|other|others}} {{GENDER:$1|responded}} on '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|responded}} on <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 and {{PLURAL:$5|one other|$5 others|100=99+ others}} {{GENDER:$1|responded}} on <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 has {{GENDER:$1|edited}} your <span class=\"plainlinks\">[$5 post]</span> on [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 and $5 {{PLURAL:$6|other|others}} {{GENDER:$1|edited}} a <span class=\"plainlinks\">[$4 post]</span> in \"$2\" on \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|created}} a new topic on '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 new topic|$1 new topics|250=250+ new topics}} on '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 and {{PLURAL:$5|one other|$5 others|100=99+ others}} {{GENDER:$1|edited}} a <span class=\"plainlinks\">[$4 post]</span> in \"$2\" on \"$3\".",
+ "notification-header-flow-new-topic-v2": "New topic created on <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-compact-header-flow-new-topic": "\"<strong>$1</strong>\"",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|One new topic|$1 new topics|100=99+ new topics}} on <strong>$3</strong>.",
+ "notification-body-flow-new-topic-v2": "$1",
+ "notification-header-flow-new-topic-user-talk": "A new topic was created on <strong>your talk page</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|One new topic|$1 new topics|100=99+ new topics}} on <strong>your talk page</strong>.",
+ "notification-body-flow-new-topic-user-talk": "$1",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|replied}} in \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|One new reply|$1 new replies|100=99+ new replies}} in \"<strong>$3</strong>\".",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-body-flow-post-reply-v2": "$1",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|posted}} a reply on <strong>your talk page</strong> in \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|One new reply|$1 new replies|100=99+ new replies}} on <strong>your talk page</strong> in \"<strong>$3</strong>\".",
+ "notification-body-flow-post-reply-user-talk": "$1",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Your}} post in \"<strong>$1</strong>\" was edited.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Your}} post in \"<strong>$1</strong>\" was edited multiple times.",
+ "notification-body-flow-post-edited-v2": "$1",
+ "notification-header-flow-post-edited-user-talk": "A post in \"<strong>$1</strong>\" was edited on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "A post in \"<strong>$1</strong>\" was edited multiple times on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-body-flow-post-edited-user-talk": "$1",
+ "notification-header-flow-topic-renamed-v2": "The topic \"<strong>$1</strong>\" was renamed to \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "The topic \"<strong>$1</strong>\" was renamed to \"<strong>$2</strong>\" on <strong>{{GENDER:$3|your}} talk page</strong>.",
+ "notification-header-flow-summary-edited": "The summary for \"<strong>$1</strong>\" was updated.",
+ "notification-header-flow-summary-edited-first": "The topic \"<strong>$1</strong>\" was summarized.",
+ "notification-bundle-header-flow-summary-edited": "The summary for \"<strong>$1</strong>\" was updated multiple times.",
+ "notification-body-flow-summary-edited": "$1",
+ "notification-header-flow-summary-edited-user-talk": "The summary for \"<strong>$1</strong>\" was updated on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "The topic \"<strong>$1</strong>\" was summarized on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "The summary for \"<strong>$1</strong>\" was updated multiple times on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-body-flow-summary-edited-user-talk": "$1",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|updated}} the summary on $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|updated}} the summary on $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 and {{PLURAL:$3|one other|$3 others|100=99+ others}} {{GENDER:$1|updated}} the summary on $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|mentioned}} {{GENDER:$4|you}} in \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|mentioned}} {{GENDER:$4|you}} in the description of <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mentioned}} {{GENDER:$4|you}} in \"<strong>$5</strong>\".",
+ "notification-body-flow-mention": "$1",
+ "notification-header-flow-enabled-on-talkpage": "New discussion system enabled for <strong>{{GENDER:$2|your}} user talk page</strong>.",
+ "notification-header-flow-description-edited": "The description of <strong>$1</strong> was edited.",
+ "notification-header-flow-description-edited-user-talk": "The description was edited on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-bundle-header-flow-description-edited": "The description of <strong>$1</strong> was edited multiple times.",
+ "notification-bundle-header-flow-description-edited-user-talk": "The description was edited multiple times on <strong>{{GENDER:$2|your}} talk page</strong>.",
+ "notification-body-flow-description-edited": "$1",
+ "notification-body-flow-description-edited-user-talk": "$1",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|View}} page",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|edited}} the description on $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|edited}} the description on $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 and {{PLURAL:$3|one other|$3 others|100=99+ others}} {{GENDER:$1|edited}} the description on $2",
+ "notification-header-flow-topic-resolved": "The topic \"<strong>$1</strong>\" was resolved.",
+ "notification-header-flow-topic-reopened": "The topic \"<strong>$1</strong>\" was reopened.",
+ "notification-header-flow-topic-resolved-user-talk": "The topic \"<strong>$1</strong>\" was resolved on <strong>your talk page</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "The topic \"<strong>$1</strong>\" was reopened on <strong>your talk page</strong>.",
+ "notification-email-subject-flow-topic-resolved": "The topic \"<strong>$2</strong>\" was resolved.",
+ "notification-email-batch-body-flow-topic-resolved": "The topic \"<strong>$2</strong>\" was resolved.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|created}} a new topic on <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|One new topic|$1 new topics|100=99+ new topics}} on <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|changed}} the title of <span class=\"plainlinks\">[$2 $3]</span> to \"$4\" on [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|mentioned}} {{GENDER:$5|you}} in {{GENDER:$1|his|her|their}} <span class=\"plainlinks\">[$2 post]</span> in \"$3\" on \"$4\".",
"flow-notification-link-text-view-post": "View post",
"flow-notification-link-text-view-topic": "View topic",
+ "flow-notification-link-text-view-topics": "View topics",
"flow-notification-reply-email-subject": "$2 on $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|responded}} to \"$2\" on $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 and $4 {{PLURAL:$5|other|others}} {{GENDER:$1|responded}} to \"$2\" on $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 and {{PLURAL:$4|one other|$4 others|100=99+ others}} {{GENDER:$1|responded}} to \"$2\" on $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|mentioned}} {{GENDER:$3|you}} on $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mentioned}} {{GENDER:$4|you}} in {{GENDER:$1|his|her|their}} post in \"$2\" on $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|edited}} a post",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|edited}} a post in \"$2\" on $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 and $4 {{PLURAL:$5|other|others}} {{GENDER:$1|edited}} a post in \"$2\" on $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 and {{PLURAL:$4|one other|$4 others|100=99+ others}} {{GENDER:$1|edited}} a post in \"$2\" on $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|renamed}} your topic",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renamed}} your topic \"$2\" to \"$3\" on $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|created}} a new topic on $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|created}} a new topic with the title \"$2\" on $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 new topic|$1 new topics|250=250+ new topics}} on $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Notify me when actions related to me occur in Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|One new topic|$1 new topics|100=99+ new topics}} on $2",
+ "echo-category-title-flow-discussion": "Structured Discussion",
+ "echo-pref-tooltip-flow-discussion": "Notify me about activity in topics or on pages I'm following.",
"flow-link-post": "post",
"flow-link-topic": "topic",
"flow-link-board": "$1",
@@ -321,18 +402,18 @@
"flow-moderation-confirm-unsuppress-topic": "Unsuppress",
"flow-moderation-confirm-undelete-topic": "Undelete",
"flow-moderation-confirm-unhide-topic": "Unhide",
- "flow-moderation-confirmation-suppress-post": "The post was successfully suppressed.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
- "flow-moderation-confirmation-delete-post": "The post was successfully deleted.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
- "flow-moderation-confirmation-hide-post": "The post was successfully hidden.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
- "flow-moderation-confirmation-unsuppress-post": "You have successfully unsuppressed the above post.",
- "flow-moderation-confirmation-undelete-post": "You have successfully undeleted the above post.",
- "flow-moderation-confirmation-unhide-post": "You have successfully unhidden the above post.",
+ "flow-moderation-confirmation-suppress-post": "The post was suppressed.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
+ "flow-moderation-confirmation-delete-post": "The post was deleted.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
+ "flow-moderation-confirmation-hide-post": "The post was hidden.\n{{GENDER:$2|Consider}} giving $1 feedback on this post.",
+ "flow-moderation-confirmation-unsuppress-post": "You have unsuppressed the above post.",
+ "flow-moderation-confirmation-undelete-post": "You have undeleted the above post.",
+ "flow-moderation-confirmation-unhide-post": "You have unhidden the above post.",
"flow-moderation-confirmation-suppress-topic": "This topic has been suppressed.",
"flow-moderation-confirmation-delete-topic": "This topic has been deleted.",
"flow-moderation-confirmation-hide-topic": "This topic has been hidden.",
- "flow-moderation-confirmation-unsuppress-topic": "You have successfully unsuppressed this topic.",
- "flow-moderation-confirmation-undelete-topic": "You have successfully undeleted this topic.",
- "flow-moderation-confirmation-unhide-topic": "You have successfully unhidden this topic.",
+ "flow-moderation-confirmation-unsuppress-topic": "You have unsuppressed this topic.",
+ "flow-moderation-confirmation-undelete-topic": "You have undeleted this topic.",
+ "flow-moderation-confirmation-unhide-topic": "You have unhidden this topic.",
"flow-moderation-title-suppress-topic": "Suppress topic?",
"flow-moderation-title-delete-topic": "Delete topic?",
"flow-moderation-title-hide-topic": "Hide topic?",
@@ -355,15 +436,15 @@
"flow-revision-permalink-warning-header-first": "This is a permanent link to the first version of the description.\nYou can view later versions on the [$2 board history page].",
"flow-compare-revisions-revision-header": "Version by {{GENDER:$2|$2}} from $1",
"flow-compare-revisions-header-post": "This page shows the {{GENDER:$3|changes}} between two versions of a post by $3 in the topic \"[$5 $2]\" on [$4 $1].\nYou can see other versions of this post at its [$6 history page].",
- "flow-compare-revisions-header-postsummary": "This page shows the changes between two versions of a post summary in the post \"[$4 $2]\" on [$3 $1].\nYou can see other versions of this post at its [$5 history page].",
+ "flow-compare-revisions-header-postsummary": "This page shows the changes between two versions of the summary of the topic \"[$4 $2]\" on [$3 $1].\nYou can see other versions of this topic summary at the topic's [$5 history page].",
"flow-compare-revisions-header-header": "This page shows the {{GENDER:$2|changes}} between two versions of the description on [$3 $1].\nYou can see other versions of the description at its [$4 history page].",
- "action-flow-create-board": "create Flow boards in any location",
- "right-flow-create-board": "Create Flow boards in any location",
- "right-flow-hide": "Hide Flow topics and posts",
- "right-flow-lock": "Mark Flow topics as resolved",
- "right-flow-delete": "Delete Flow topics and posts",
- "right-flow-edit-post": "Edit Flow posts by other users",
- "right-flow-suppress": "Suppress Flow revisions",
+ "action-flow-create-board": "create Structured Discussions boards in any location",
+ "right-flow-create-board": "Create Structured Discussions boards in any location",
+ "right-flow-hide": "Hide Structured Discussions topics and posts",
+ "right-flow-lock": "Mark Structured Discussions topics as resolved",
+ "right-flow-delete": "Delete Structured Discussions topics and posts",
+ "right-flow-edit-post": "Edit Structured Discussions posts by other users",
+ "right-flow-suppress": "Suppress Structured Discussions revisions",
"flow-terms-of-use-new-topic": "By clicking \"{{int:flow-newtopic-save}}\", you agree to the terms of use for this wiki.",
"flow-terms-of-use-reply": "By clicking \"{{int:flow-reply-link}}\", you agree to the terms of use for this wiki.",
"flow-terms-of-use-edit": "By saving your changes, you agree to the terms of use for this wiki.",
@@ -387,24 +468,25 @@
"flow-whatlinkshere-post": "from a [$1 post]",
"flow-whatlinkshere-header": "from the [$1 description]",
"flow-whatlinkshere-post-summary": "from the [$1 summary]",
- "flow": "Flow",
- "flow-special-desc": "This special page redirects to a Flow workflow or a Flow post given a UUID.",
+ "structureddiscussions": "Structured Discussions",
+ "flow-special-desc": "This special page redirects to a Structured Discussions workflow or a Structured Discussions post given a UUID.",
"flow-special-type": "Type",
"flow-special-type-post": "Post",
"flow-special-type-workflow": "Workflow",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Could not find content matching the type and the UUID.",
- "flow-special-enableflow-legend": "Enable Flow on a new page",
- "flow-special-enableflow-page": "Page to enable Flow on",
- "flow-special-enableflow-header": "Initial description of Flow board (wikitext)",
- "flow-special-enableflow-board-already-exists": "There is already a Flow board at [[$1]].",
+ "flow-special-enableflow-legend": "Enable Structured Discussions on a new page",
+ "flow-special-enableflow-page": "Page to enable Structured Discussions on",
+ "flow-special-enableflow-header": "Initial description of Structured Discussions board (wikitext)",
+ "flow-special-enableflow-board-already-exists": "There is already a Structured Discussions board at [[$1]].",
"flow-special-enableflow-invalid-title": "An invalid page title was provided",
- "flow-special-enableflow-board-creation-not-allowed": "You are not allowed to create a Flow board at [[:$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "You are not allowed to create a Structured Discussions board at [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "There is a LiquidThreads page at [[:$1]].",
- "flow-special-enableflow-confirmation": "You have successfully created a Flow board at [[$1]].",
+ "flow-special-enableflow-confirmation": "You have created a Structured Discussions board at [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archive %d\n%s/Archive%d\n%s/archive %d\n%s/archive%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Flow Archive %d\n%s/FlowArchive%d",
- "flow-spam-confirmedit-form": "Please confirm you are a human by solving the below captcha: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Structured Discussions Archive %d\n%s/Structured DiscussionsArchive%d",
+ "flow-spam-confirmedit-form": "Please confirm you are a human by solving the below CAPTCHA: $1",
+ "flow-spam-confirmedit-using-failure": "There was a technical error with the CAPTCHA. If you are unable to submit your change, please copy your text, reload, and try again.",
"flow-embedding-unsupported": "Discussions cannot be embedded yet.",
"mw-ui-unsubmitted-confirm": "You have unsubmitted changes on this page. Are you sure you want to navigate away and lose your work?",
"flow-post-undo-hide": "undo hide",
@@ -413,126 +495,27 @@
"flow-topic-undo-hide": "undo hide",
"flow-topic-undo-delete": "undo delete",
"flow-topic-undo-suppress": "undo suppress",
- "flow-importer-lqt-moved-thread-template": "LQT Moved thread stub converted to Flow",
+ "flow-importer-lqt-moved-thread-template": "LQT Moved thread stub converted to Structured Discussions",
"flow-importer-lqt-moved-thread-template-content": "This post by {{{author}}} was moved on {{{date}}}. You can find it at [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "LQT page converted to Flow",
+ "flow-importer-lqt-converted-template": "LQT page converted to Structured Discussions",
"flow-importer-lqt-converted-template-content": "Previous page history was archived for backup purposes at <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Archive for converted LQT page",
- "flow-importer-lqt-converted-archive-template-content": "This page is an archived LiquidThreads page. '''Do not edit the contents of this page'''. Please direct any additional comments to the [[{{{from}}}|current talk page]].",
- "flow-importer-wt-converted-template": "Wikitext talk page converted to Flow",
+ "flow-importer-lqt-converted-archive-template-content": "This page is an archived LiquidThreads page. <strong>Do not edit the contents of this page</strong>. Please direct any additional comments to the [[{{{from}}}|current talk page]].",
+ "flow-importer-wt-converted-template": "Wikitext talk page converted to Structured Discussions",
"flow-importer-wt-converted-template-content": "Previous discussion was archived at <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Archive for converted wikitext talk page",
- "flow-importer-wt-converted-archive-template-content": "This page is an archive. '''Do not edit the contents of this page'''. Please direct any additional comments to the [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|current talk page]].",
- "flow-importer-lqt-suppressed-user-template": "LQT post imported with supressed user",
+ "flow-importer-wt-converted-archive-template-content": "This page is an archive. <strong>Do not edit the contents of this page</strong>. Please direct any additional comments to the [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|current talk page]].",
+ "flow-importer-lqt-suppressed-user-template": "LQT post imported with suppressed user",
"flow-importer-lqt-suppressed-user-template-content": "This revision was imported from LiquidThreads with a suppressed user. It has been reassigned to the current user.",
"flow-importer-lqt-different-author-signature-template": "LQT post imported with different signature user",
- "flow-importer-lqt-different-author-signature-template-content": "''This post was posted by [[User:{{{authorUser}}}|{{{authorUser}}}]], but signed as [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Allows actions to be taken on Flow pages.",
- "apihelp-flow-param-submodule": "The Flow submodule to invoke.",
- "apihelp-flow-param-page": "The page to take the action on.",
- "apihelp-flow-example-1": "Edit the description of \"[[Talk:Sandbox]]\"",
- "apihelp-flow+close-open-topic-description": "Deprecated in favor of [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "State to put topic in, either \"lock\" or \"unlock\".",
- "apihelp-flow+close-open-topic-param-reason": "Reason for locking or unlocking the topic.",
- "apihelp-flow+edit-header-description": "Edits a board description.",
- "apihelp-flow+edit-header-param-prev_revision": "Revision ID of the current description revision, to check for edit conflicts.",
- "apihelp-flow+edit-header-param-content": "Content for description.",
- "apihelp-flow+edit-header-param-format": "Format of the description (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "Edit the description of [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Edits a post's content.",
- "apihelp-flow+edit-post-param-postId": "Post ID.",
- "apihelp-flow+edit-post-param-prev_revision": "Revision ID of the current post revision, to check for edit conflicts.",
- "apihelp-flow+edit-post-param-content": "Content for post.",
- "apihelp-flow+edit-post-param-format": "Format of the post content (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "Edit a post in [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Edits a topic's title.",
- "apihelp-flow+edit-title-param-prev_revision": "Revision ID of the current title revision, to check for edit conflicts.",
- "apihelp-flow+edit-title-param-content": "Content for title.",
- "apihelp-flow+edit-title-example-1": "Edit the title of [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Edits a topic summary's content.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Revision ID of the current topic summary revision, if any, to check for edit conflicts.",
- "apihelp-flow+edit-topic-summary-param-summary": "Content for the summary.",
- "apihelp-flow+edit-topic-summary-param-format": "Format of the summary (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Edit the summary of [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Lock or unlock a Flow topic.",
- "apihelp-flow+lock-topic-param-moderationState": "State to put topic in, either <kbd>lock</kbd> or <kbd>unlock</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Reason for locking or unlocking the topic. Note, the on-wiki Flow client uses \"Marked as resolved\" here, and puts optional additional information in the summary.",
- "apihelp-flow+lock-topic-example-1": "Lock [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Moderates a Flow post.",
- "apihelp-flow+moderate-post-param-moderationState": "What level to moderate at.",
- "apihelp-flow+moderate-post-param-reason": "Reason for moderation.",
- "apihelp-flow+moderate-post-param-postId": "ID of the post to moderate.",
- "apihelp-flow+moderate-post-example-1": "Delete a post on topic [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Moderates a Flow topic.",
- "apihelp-flow+moderate-topic-param-moderationState": "What level to moderate at.",
- "apihelp-flow+moderate-topic-param-reason": "Reason for moderation.",
- "apihelp-flow+moderate-topic-example-1": "Delete the topic [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Creates a new Flow topic on the given workflow.",
- "apihelp-flow+new-topic-param-topic": "Text for new topic title.",
- "apihelp-flow+new-topic-param-content": "Content for the topic's initial reply.",
- "apihelp-flow+new-topic-param-format": "Format of the new topic's initial reply (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "Create a new topic on [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Replies to a post.",
- "apihelp-flow+reply-param-replyTo": "Post ID to reply to.",
- "apihelp-flow+reply-param-content": "Content for new post.",
- "apihelp-flow+reply-param-format": "Format of the new post (wikitext|html)",
- "apihelp-flow+reply-example-1": "Reply to a post on [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Format to return the content in.",
- "apihelp-flow+view-header-description": "View a board description.",
- "apihelp-flow+view-header-param-revId": "Load this revision, instead of the most recent.",
- "apihelp-flow+view-header-example-1": "Fetch the description of [[Talk:Sandbox]] as wikitext",
- "apihelp-flow+view-post-description": "View a post.",
- "apihelp-flow+view-post-param-postId": "ID of the post to view.",
- "apihelp-flow+view-post-param-format": "Format to return the content in.",
- "apihelp-flow+view-post-example-1": "Fetch the content of a post on [[Topic:S2tycnas4hcucw8w]] as wikitext",
- "apihelp-flow+view-post-history-description": "View the revision history of a post.",
- "apihelp-flow+view-post-history-param-postId": "ID of the post for which to view revision history.",
- "apihelp-flow+view-post-history-param-format": "Format to return the content in.",
- "apihelp-flow+view-post-history-example-1": "Fetch the revisions of a post on [[Topic:S2tycnas4hcucw8w]] as wikitext",
- "apihelp-flow+view-topic-description": "View a topic.",
- "apihelp-flow+view-topic-example-1": "View [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "View the revision history of a topic.",
- "apihelp-flow+view-topic-history-param-format": "Format to return the content in.",
- "apihelp-flow+view-topic-history-example-1": "View the revisions of the posts on [[Topic:S2tycnas4hcucw8w]] as wikitext",
- "apihelp-flow+view-topic-summary-description": "View a topic summary.",
- "apihelp-flow+view-topic-summary-param-format": "Format to return the content in.",
- "apihelp-flow+view-topic-summary-param-revId": "Load this revision, instead of the most recent.",
- "apihelp-flow+view-topic-summary-example-1": "View the summary for [[Topic:S2tycnas4hcucw8w]] as wikitext",
- "apihelp-flow+view-topiclist-description": "View a list of topics.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Direction to order the topics.",
- "apihelp-flow+view-topiclist-param-sortby": "Sorting option of the topics, either <kbd>updated</kbd> (ordered by topic update time), or <kbd>newest</kbd> (ordered by topic creation time).",
- "apihelp-flow+view-topiclist-param-savesortby": "Save sortby option to user preferences, if set.",
- "apihelp-flow+view-topiclist-param-offset-id": "Offset value (in UUID format) to start fetching topics at; used only with <kbd>newest</kbd> ordering",
- "apihelp-flow+view-topiclist-param-offset": "Offset value (as a topic update timestamp, in <code>TS_MW</code> format (<code>YYYYMMDDHHMMSS</code>)), to start fetching topics at; used only with <kbd>updated</kbd> ordering",
- "apihelp-flow+view-topiclist-param-limit": "Number of topics to fetch.",
- "apihelp-flow+view-topiclist-example-1": "List topics on [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Convert text between wikitext and HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Format to convert content from.",
- "apihelp-flow-parsoid-utils-param-to": "Format to convert content to.",
- "apihelp-flow-parsoid-utils-param-content": "Content to be converted.",
- "apihelp-flow-parsoid-utils-param-title": "Title of the page. Cannot be used together with $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID of the page. Cannot be used together with $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Convert wikitext <nowiki>'''lorem''' ''blah''</nowiki> to HTML",
- "apihelp-query+flowinfo-description": "Get basic Flow information about a page.",
- "apihelp-query+flowinfo-example-1": "Fetch Flow information about [[Talk:Sandbox]], [[Main Page]], and [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Retrieve information necessary to undo description edits.",
- "apihelp-flow+undo-edit-header-param-startId": "Revision id to start undo at.",
- "apihelp-flow+undo-edit-header-param-endId": "Revision id to end undo at.",
- "apihelp-flow+undo-edit-header-example-1": "Fetch information about undoing a description edit at [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Retrieve information necesary to undo post edit.",
- "apihelp-flow+undo-edit-post-param-postId": "Post id to be undone.",
- "apihelp-flow+undo-edit-post-param-startId": "Revision id to start undo at.",
- "apihelp-flow+undo-edit-post-param-endId": "Revision id to end undo at.",
- "apihelp-flow+undo-edit-post-example-1": "Fetch information about undoing a post edit in a specific topic.",
- "apihelp-flow+undo-edit-topic-summary-description": "Retrieve information necessary to undo topic summary edits.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Revision id to start undo at.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Revision id to end undo at.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Fetch information about undoing a topic summary edit in a specific topic",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>This post was posted by [[User:{{{authorUser}}}|{{{authorUser}}}]], but signed as [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Edited",
"flow-edited-by": "Edited by $1",
- "flow-lqt-redirect-reason": "Redirecting retired LiquidThreads post to its converted Flow post",
- "flow-talk-conversion-move-reason": "Conversion of wikitext talk to Flow from $1",
- "flow-talk-conversion-archive-edit-reason": "Wikitext talk to Flow conversion",
+ "flow-edited-by-header": "Board description edited by $1",
+ "flow-edited-by-topic-title": "Topic title edited by $1",
+ "flow-lqt-redirect-reason": "Redirecting retired LiquidThreads post to its converted Structured Discussions post",
+ "flow-talk-conversion-move-reason": "Conversion of wikitext talk to Structured Discussions from $1",
+ "flow-talk-conversion-archive-edit-reason": "Wikitext talk to Structured Discussions conversion",
"flow-previous-diff": "← Older edit",
"flow-next-diff": "Newer edit →",
"flow-undo": "undo",
@@ -543,9 +526,9 @@
"flow-undo-edit-post": "Editing a post",
"flow-undo-edit-content": "The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.",
"flow-undo-edit-failure": "The edit could not be undone due to conflicting intermediate edits.",
- "group-flow-bot": "Flow bots",
- "group-flow-bot-member": "Flow bot",
- "grouppage-flow-bot": "Project:Flow bots",
+ "group-flow-bot": "Structured Discussions bots",
+ "group-flow-bot-member": "Structured Discussions bot",
+ "grouppage-flow-bot": "Project:Structured Discussions bots",
"flow-ve-mention-context-item-label": "Mention",
"flow-ve-mention-inspector-title": "Mention",
"flow-ve-mention-inspector-remove-label": "Remove",
@@ -555,30 +538,36 @@
"flow-ve-mention-inspector-invalid-user": "The username \"$1\" is not registered.",
"flow-wikitext-editor-help": "Wikitext $1.",
"flow-wikitext-editor-help-and-preview": "Wikitext $1 and you can $2 anytime.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|uses markup]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|uses markup]]",
"flow-wikitext-editor-help-preview-the-result": "preview the result",
- "flow-wikitext-switch-editor-tooltip": "Switch to VisualEditor",
- "flow-ve-switch-editor-tool-title": "Switch to Wikitext editor",
+ "flow-wikitext-switch-editor-tooltip": "Switch to the visual editor",
+ "flow-ve-switch-editor-tool-title": "Switch to wikitext editor",
"flow-mark-revision-patrolled-link-text": "Mark this page as patrolled",
"flow-mark-revision-patrolled-link-title": "Mark this page as patrolled",
"flow-mark-diff-patrolled-link-text": "Mark as patrolled",
"flow-mark-diff-patrolled-link-title": "Mark as patrolled",
- "flow-talk-page-beta-feature-message": "Flow on user talk",
- "flow-talk-page-beta-feature-description": "Enables a new structured discussion system on {{GENDER:|your}} user talk page. Flow simplifies talk page discussions with clear places to write and reply, and allows conversation-level notifications. Existing wikitext discussions are moved to an archive. This feature is not auto-enabled; users will have to enable it separately. Disabling this feature will move the Flow board to a subpage and un-archive the previous talkpage.",
- "flow-notification-link-text-enabled-on-talkpage": "View user talk page",
+ "flow-talk-page-beta-feature-message": "Structured Discussions on user talk",
+ "flow-talk-page-beta-feature-description": "Enables a new structured discussion system on {{GENDER:|your}} user talk page. Structured Discussions simplifies talk page discussions with clear places to write and reply, and allows conversation-level notifications. This feature is not auto-enabled; users will have to enable it separately.<br /><br />Existing wikitext discussions are moved to an archive. Disabling this feature will move the Structured Discussion board to a subpage and un-archive the previous talkpage. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Learn more about activation]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|View}} user talk page",
"flow-notification-enabled-on-talkpage-title": "New discussion system enabled for {{GENDER:$1|your}} user talk page<br /><small>Available at [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "New discussion system on $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, the new wiki discussion system, has been enabled on {{GENDER:$1|your}} user talk page on {{SITENAME}}. You can get more information, provide feedback or disable the new system any time from the Beta features section in {{GENDER:$1|your}} preferences.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Structured Discussions, the new wiki discussion system, has been enabled on {{GENDER:$1|your}} user talk page on {{SITENAME}}. You can get more information, provide feedback or disable the new system any time from the Beta features section in {{GENDER:$1|your}} preferences.",
"flow-beta-feature-add-archive-template-edit-summary": "Adding archive template",
"flow-beta-feature-remove-archive-template-edit-summary": "Removing archive template",
- "flow-dialog-cancelconfirm-title": "Are you sure?",
- "flow-dialog-cancelconfirm-message": "Are you sure you want to cancel without saving first?",
+ "flow-dialog-cancelconfirm-title": "Are {{GENDER:|you}} sure?",
+ "flow-dialog-cancelconfirm-message": "Are {{GENDER:|you}} sure you want to cancel without saving first?",
"flow-dialog-cancelconfirm-keep": "Continue editing",
"flow-dialog-cancelconfirm-discard": "Discard changes",
+ "flow-optin-archive-wikitext": "Move wikitext page to make room for a discussion board.",
+ "flow-optin-archive-flow-board": "Move discussion board page to make room for a wikitext page.",
+ "flow-optin-restore-wikitext": "Restore archived wikitext page.",
+ "flow-optin-restore-flow-board": "Restore archived discussion board.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Welcome}} to {{GENDER:$1|your}} new user talk page",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Your}} talk page is the place where other editors can contact {{GENDER:$1|you}}. With Flow, it's easier to start new topics and keep track of conversations.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Your}} talk page is the place where other editors can contact {{GENDER:$1|you}}. With Structured Discussions, it's easier to start new topics and keep track of conversations.",
"flow-guidedtour-optin-find-old-conversations": "Find {{GENDER:$1|your}} old conversations",
"flow-guidedtour-optin-find-old-conversations-description": "Previous conversations have been moved to an archive page.",
"flow-guidedtour-optin-feedback": "Give us {{GENDER:$1|your}} feedback!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|You}} can get more information, provide feedback, or disable the new system any time from the Beta features section."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|You}} can get more information, provide feedback, or disable the new system any time from the Beta features section.",
+ "flow-action-not-page": "Page object is an instance of the wrong class",
+ "flow-action-wrong-title-content-model": "The page is being handled by Structured Discussions, but the Title class indicates that the content model is '$1'. This is a misconfiguration or inconsistent state. For example, this may actually be a non-Structured Discussions page in a Structured Discussions namespace, with <code>rev_content_model</code> not populated."
}
diff --git a/Flow/i18n/eo.json b/Flow/i18n/eo.json
index 0800041b..1c49db92 100644
--- a/Flow/i18n/eo.json
+++ b/Flow/i18n/eo.json
@@ -1,26 +1,80 @@
{
"@metadata": {
"authors": [
- "Happy5214"
+ "Happy5214",
+ "Robin van der Vliet",
+ "Lucas",
+ "Gamliel Fishkin",
+ "Psychoslave",
+ "NMaia",
+ "Yekrats"
]
},
+ "enablestructureddiscussions": "Ŝalti Flow",
+ "flow-topic-moderated-reason-prefix": "Kialo:",
"flow-post-actions": "Agoj",
"flow-topic-actions": "Agoj",
"flow-cancel": "Nuligi",
+ "flow-skip-summary": "Preterpasi",
+ "flow-show-change": "Montri ŝanĝojn",
+ "flow-newtopic-title-placeholder": "Nova temo",
+ "flow-newtopic-content-placeholder": "Sendi novan mesaĝon al \"$1\"",
+ "flow-newtopic-header": "Aldoni novan temon",
+ "flow-newtopic-save": "Aldoni temon",
+ "flow-newtopic-save-anonymously": "Aldoni temon anonime",
+ "flow-newtopic-start-placeholder": "Krei novan temon",
+ "flow-newtopic-first-heading": "Krei novan temon ĉe $1",
+ "flow-reply-topic-title-placeholder": "Respondo al \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|Respondi}}",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Danki}}}}",
+ "flow-history-action-suppress-post": "forviŝi",
+ "flow-history-action-delete-post": "forigi",
+ "flow-history-action-hide-post": "kaŝi",
+ "flow-history-action-unsuppress-post": "malforviŝi",
+ "flow-history-action-undelete-post": "malforigi",
+ "flow-history-action-unhide-post": "malkaŝi",
+ "flow-history-action-restore-post": "restarigi",
+ "flow-history-action-lock-topic": "solvi",
+ "flow-history-action-unlock-topic": "remalfermi",
"flow-post-action-view": "Konstanta ligilo",
"flow-post-action-post-history": "Historio",
+ "flow-post-action-suppress-post": "Forviŝi",
"flow-post-action-delete-post": "Forigi",
"flow-post-action-hide-post": "Kaŝi",
"flow-post-action-edit-post": "Redakti",
+ "flow-post-action-edit-post-submit": "Konservi ŝanĝojn",
+ "flow-post-action-unsuppress-post": "Malforviŝi",
"flow-post-action-undelete-post": "Malforigi",
+ "flow-post-action-unhide-post": "Malkaŝi",
+ "flow-post-action-restore-post": "Restarigi",
+ "flow-post-action-undo-moderation": "Malfari",
+ "flow-topic-action-view": "Konstanta ligilo",
"flow-topic-action-watchlist": "Atentaro",
+ "flow-topic-action-edit-title": "Redakti titolon",
"flow-topic-action-history": "Historio",
+ "flow-topic-action-hide-topic": "Kaŝi temon",
+ "flow-topic-action-delete-topic": "Forigi temon",
+ "flow-topic-action-lock-topic": "Marki kiel solvita",
+ "flow-topic-action-unlock-topic": "Remalfermi temon",
+ "flow-topic-action-undo-moderation": "Malfari",
+ "flow-error-protected-unknown-reason": "Nekonata",
+ "flow-error-default": "Eraro okazis.",
+ "flow-error-unknown-workflow-id-title": "Nekonata temo",
+ "flow-edit-header-submit": "Konservi priskribon",
+ "flow-edit-title-submit": "Ŝanĝi titolon",
"flow-board-history": "\"$1\" historio",
"flow-history-day": "Hodiaŭ",
"flow-history-week": "Lasta semajno",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|menciis}} {{GENDER:$4|vin}} en “<strong>$5</strong>”.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Montri}} paĝon",
+ "echo-category-title-flow-discussion": "Diskuto pri fluo",
+ "echo-pref-tooltip-flow-discussion": "Sciigi al mi kiam rilataj al mi agoj okazas en Flua diskuto.",
"flow-link-history": "historio",
"flow-moderation-confirm-delete-post": "Forigi",
"flow-moderation-confirm-hide-post": "Kaŝi",
"flow-moderation-confirm-delete-topic": "Forigi",
- "flow-moderation-confirm-hide-topic": "Kaŝi"
+ "flow-moderation-confirm-hide-topic": "Kaŝi",
+ "flow-ve-mention-placeholder": "Uzantnomo",
+ "flow-dialog-cancelconfirm-title": "Ĉu vi certas?",
+ "flow-action-not-page": "Objekto de paĝo estas ano de malkongrua klaso"
}
diff --git a/Flow/i18n/es.json b/Flow/i18n/es.json
index 8f22ea13..d9f6250e 100644
--- a/Flow/i18n/es.json
+++ b/Flow/i18n/es.json
@@ -21,11 +21,20 @@
"JosouNoAria",
"Mor",
"Effy",
- "Ryo567"
+ "Ryo567",
+ "Nnemo",
+ "Joaquin1001",
+ "Quiddity",
+ "Peter Bowman",
+ "Matiia",
+ "Lemondoge",
+ "Rubentl134",
+ "Dgstranz",
+ "MarcoAurelio"
]
},
- "enableflow": "Activar Flow",
- "flow-desc": "Sistema de gestión de flujo de trabajo",
+ "enablestructureddiscussions": "Activar discusiones estructuradas",
+ "flow-desc": "Sistema de discusión",
"flow-talk-taken-over-comment": "/* Esta página se ha convertido en un tablero de discusión Flow */",
"log-name-flow": "Registro de actividad de Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|borró}} una [$4 publicación] sobre «[[$3|$5]]» en [[$6]]",
@@ -36,14 +45,18 @@
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restauró}} el tema «[[$3|$5]]» en [[$6]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suprimió}} el tema «[[$3|$5]]» en [[$6]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|borró}} el tema \"[[$3|$5]]\" en [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|borró}} un tema en [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marcó}} el tema \"[[$3|$5]]\" como resuelto en [[$6]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reabrió}} el tema \"[[$3|$5]]\" en [[$6]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] en [[$3]] se ha importado a Flow desde LiquidThreads",
"flow-user-moderated": "Usuario moderado",
"flow-board-header-browse-topics-link": "Explorar temas",
"flow-board-header": "Acerca de este panel",
+ "flow-board-description-can-not-edit": "No se puede editar",
"flow-board-collapse-description": "Ocultar descripción",
"flow-board-expand-description": "Mostrar descripción",
- "flow-topic-collapse-siderail": "Leer en ancho completo",
- "flow-topic-expand-siderail": "Leer en ancho fijo",
+ "flow-topic-collapse-siderail": "Leer en anchura completa",
+ "flow-topic-expand-siderail": "Leer en anchura fija",
"flow-edit-header-link": "Editar descripción",
"flow-post-moderated-toggle-hide-show": "Mostrar comentario {{GENDER:$1|ocultado}} por $2",
"flow-post-moderated-toggle-delete-show": "Mostrar comentario {{GENDER:$1|eliminado}} por $2",
@@ -65,7 +78,7 @@
"flow-post-actions": "Acciones",
"flow-topic-actions": "Acciones",
"flow-cancel": "Cancelar",
- "flow-skip-summary": "Saltar resumen",
+ "flow-skip-summary": "Omitir",
"flow-edit-summary-placeholder": "Describir brevemente el resultado de esta discusión",
"flow-summary-authored": "Resumen de $1",
"flow-summary-edited": "Resumen {{GENDER:$1|editado}} por última vez por $1",
@@ -132,26 +145,25 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Recibirás}} una notificación cuando se cree un tema nuevo en este panel.",
"flow-topic-action-watchlist-add": "Suscribirse a este tema",
"flow-topic-action-watchlist-remove": "Desuscribirse",
- "flow-error-allowcreation-no-usedb": "allowCreation requiere que <var>$wgContentHandlerUseDB</var> sea <code>true</code>.",
- "flow-error-allowcreation-already-exists": "La página ya existe, pero se requirió lo contrario",
+ "flow-error-allowcreation-no-usedb": "Habilitar Flow en una página específica requiere que <var>$wgContentHandlerUseDB</var> sea <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "La página ya existía en destino, así que no se pudo mover allí un panel de Flow.",
"flow-error-allowcreation-flow-create-board": "El usuario no tiene el permiso de \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Actualmente no puedes participar. Intenta iniciar sesión.",
+ "flow-error-can-not-edit-logged-in": "Actualmente no puedes participar, por que no tienes los derechos necesarios.",
"flow-error-http": "Ha ocurrido un error mientras se contactaba al servidor.",
- "flow-error-other": "Ha ocurrido un error inesperado.",
- "flow-error-external": "Se ha producido un error.<br />El mensaje de error recibido es: $1",
+ "flow-error-external": "Se ha producido un error. <br />El mensaje de error recibido es: $1",
"flow-error-topic-is-locked": "Este tema está resuelto, así que no se puede continuar modificando.",
"flow-error-lock-moderated-post": "No puedes marcar como resuelta una publicación moderada.",
- "flow-error-external-multi": "Se han encontrado errores.<br />$1",
"flow-error-missing-content": "La entrada no tiene contenido. Para guardarla necesitas añadir contenido.",
"flow-error-missing-summary": "Debes escribir un resumen.",
"flow-error-missing-title": "El tema no tiene título. Para guardarlo necesitas añadirle un título.",
- "flow-error-parsoid-failure": "No se puede analizar el contenido debido a una falla de Parsoid.",
+ "flow-error-parsoid-failure": "No se puede transferir el contenido: Error al intentar contactar al servidor para la conversión entre wikitexto y HTML. Verifica tu conexión a Internet o inténtalo más tarde si el problema persiste. Si sigue apareciendo este error, por favor, envía un informe de error.",
+ "flow-error-protected-autoconfirmed-logged-in": "Este tablero está protegido. Solo usuarios autoconfirmados pueden participar. Razón: $1",
+ "flow-error-protected-sysop-logged-out": "Este tablero está protegido. Solo usuarios registrados con privilegios de administrador pueden participar. Razón: $1",
+ "flow-error-protected-unknown-reason": "Desconocido",
"flow-error-missing-replyto": "Ningún parámetro \"replyTo\" fue suministrado. Este parámetro es requerido para hacer la acción \"responder\".",
- "flow-error-invalid-replyto": "El parámetro \"replyTo\" era inválido. La publicación especificada no su pudo encontrar.",
- "flow-error-delete-failure": "Falló la eliminación de este elemento.",
- "flow-error-hide-failure": "Falló el ocultamiento de este elemento.",
"flow-error-missing-postId": "Ningún parámetro \"postId\" fue suministrado. Es requerido este parámetro para manipular una publicación.",
- "flow-error-invalid-postId": "El parámetro \"postId\" era inválido. La publicación especificada ($1) no pudo ser encontrada.",
- "flow-error-restore-failure": "Falló la restauración de este elemento.",
+ "flow-error-invalid-postId": "El parámetro «postID» no es válido. No se pudo encontrar la publicación especificada ($1).",
"flow-error-invalid-moderation-state": "Se envió un valor de parámetro no válido («moderationState») a la API de Flow.",
"flow-error-invalid-moderation-reason": "Proporciona el motivo de la moderación.",
"flow-error-not-allowed": "Permisos insuficientes para ejecutar esta acción.",
@@ -177,6 +189,7 @@
"flow-error-default": "Se ha producido un error.",
"flow-error-invalid-input": "Se proporcionó un valor de carga de contenido de Flow no válido.",
"flow-error-invalid-title": "Se proporcionó un título de página no válido.",
+ "flow-error-invalid-parameter": "El parámetro de la llamada al método no existe o no es válido",
"flow-error-fail-load-history": "No se pudo cargar el contenido del historial.",
"flow-error-missing-revision": "No se pudo encontrar una revisión para cargar el contenido dinámico.",
"flow-error-fail-commit": "Error al guardar el contenido dinámico.",
@@ -193,12 +206,12 @@
"flow-error-no-commit": "No se pudo guardar la acción especificada.",
"flow-error-content-too-long": "El contenido es demasiado largo. El contenido después de su expansión está limitado a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-move-topic": "No se admite el traslado de los las páginas de hilo.",
- "flow-error-move-no-create-permissions": "Se necesita el permiso «{{int:right-flow-create-board}}» para trasladar un foro de Flow.",
"flow-error-invalid-topic-uuid-title": "Título incorrecto",
"flow-error-invalid-topic-uuid": "El título de la página solicitada no es válido. Flow crea automáticamente las páginas del espacio de nombres Tema.",
"flow-error-unknown-workflow-id-title": "Tema desconocido",
"flow-error-unknown-workflow-id": "El tema solicitado no existe.",
"flow-error-search": "No pudimos completar tu búsqueda debido a un problema temporal. Intenta de nuevo más tarde.",
+ "flow-error-invalid-undelete": "La página no se pudo restaurar debido a que actualmente hay una junta de discusión.",
"flow-edit-header-placeholder": "Describir este panel de discusión",
"flow-edit-header-submit": "Guardar descripción",
"flow-edit-header-submit-anonymously": "Guardar la descripción anónimamente",
@@ -224,7 +237,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ocultó}} el [$4 tema] \"$6\" (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|eliminó}} el [$4 tema] \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suprimió}} el [$4 tema] \"$6\" (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcó}} el [$4 tema] $6 como resuelto (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcó}} el [$4 tema] \"$6\" como resuelto (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "marcado como resuelto",
"flow-rev-message-restore-topic-reason": "reabierto",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restauró}} el [$4 tema] \"$6\" (<em>$5</em>)",
@@ -247,31 +260,73 @@
"flow-comment-moderated": "Comentario moderado",
"flow-last-modified": "Última modificación hace $1",
"flow-workflow": "flujo de trabajo",
- "flow-notification-reply": "$1 {{GENDER:$1|respondió}} a <span class=\"plainlinks\">[$5 $2]</span> en «$4».",
- "flow-notification-reply-bundle": "$1 y $5 {{PLURAL:$6|otro|otros}} {{GENDER:$1|respondieron}} a <span class=\"plainlinks\">[$4 $2]</span> en «$3».",
+ "flow-notification-reply": "$1 {{GENDER:$1|respondió}} a <span class=\"plainlinks\">[$5 $2]</span> en <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 y {{PLURAL:$5|otro|otros $5|100=otros 99+}} {{GENDER:$1|respondieron}} en <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 ha {{GENDER:$1|editado}} tu <span class=\"plainlinks\">[$5 publicación]</span> en [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 y {{PLURAL:$6|$5 más|otros $5}} {{GENDER:$1|editaron}} una <span class=\"plainlinks\">[$4 publicación]</span> en \"$2\" el \"$3\".",
+ "flow-notification-edit-bundle": "$1 y {{PLURAL:$5|otro|otros $5|100=otros 99+}} {{GENDER:$1|editaron}} una <span class=\"plainlinks\">[$4 publicación]</span> en «$2» el \"$3\".",
+ "notification-header-flow-new-topic-v2": "Tema nuevo creado en <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Un tema nuevo|$1 temas nuevos|100=99+ temas nuevos}} en <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Se creó un tema nuevo en <strong>tu página de discusión</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Un tema nuevo|$1 temas nuevos|100=99+ temas nuevos}} en <strong>tu página de discusión</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|respondió}} en \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Una respuesta nueva|$1 respuestas nuevas|100=99+ respuestas nuevas}} en \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|publicó}} una respuesta en <strong>tu página de discusión</strong> en la sección \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Una respuesta nueva|$1 respuestas nuevas|100=99+ respuestas nuevas}} en <strong>tu página de discusión</strong> en la sección \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "Se editó {{GENDER:$2|tu}} publicación sobre \"<strong>$1</strong>\".",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Tu}} publicación en \"'''$1'''\" fue editada varias veces.",
+ "notification-header-flow-post-edited-user-talk": "Un mensaje en «<strong>$1</strong>» se editó en <strong>{{GENDER:$2|tu}} página de discusión</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Un mensaje en «<strong>$1</strong>» se editó muchas veces en <strong>{{GENDER:$2|tu}} página de discusión</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Se renombró el tema \"<strong>$1</strong>\" como \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "El tema \"<strong>$1</strong>\" se renombró a \"<strong>$2</strong>\" en <strong>{{GENDER:$3|tu}} página de discusión</strong>.",
+ "notification-header-flow-summary-edited": "Se actualizó el resumen de \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-first": "Se resumió el tema \"<strong>$1</strong>\".",
+ "notification-bundle-header-flow-summary-edited": "Se actualizó varias veces el resumen de \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-user-talk": "Se actualizó el resumen de \"<strong>$1</strong>\" en <strong>{{GENDER:$2|tu}} página de discusión</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Se resumió el tema \"<strong>$1</strong>\" en '''{{GENDER:$2|tu}} página de discusión'''.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Se actualizó varias veces el resumen de \"<strong>$1</strong>\" en <strong>{{GENDER:$2|tu}} página de discusión</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|actualizó}} el resumen de $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|actualizó}} el resumen de $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 y {{PLURAL:$3|otro|otros $3|100=otros 99+}} {{GENDER:$1|actualizaron}} el resumen en $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|te}} ha {{GENDER:$2|mencionado}} en «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$4|te}} {{GENDER:$2|mencionó}} en la descripción de '''$3'''.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|te}} {{GENDER:$4|mencionó}} en \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Nuevo sistema de discusión activado para <strong>tu página de discusión de {{GENDER:$2|usuario|usuaria}}</strong>.",
+ "notification-header-flow-description-edited": "Se editó la descripción de <strong>$1</strong>.",
+ "notification-header-flow-description-edited-user-talk": "Se editó la descripción en '''{{GENDER:$2|tu}} página de discusión'''.",
+ "notification-bundle-header-flow-description-edited": "La descripción de <strong>$1</strong> se editó varias veces.",
+ "notification-bundle-header-flow-description-edited-user-talk": "La descripción se editó varias veces en '''{{GENDER:$2|tu}} página de discusión'''.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Ver}} la página",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$q|editó}} la descripción en $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|editó}} la descripción en $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 y {{PLURAL:$3|otro|otros $3|100=otros 99+}} {{GENDER:$1|editaron}} la descripción en $2",
+ "notification-header-flow-topic-resolved": "Se resolvió el tema \"<strong>$1</strong>\".",
+ "notification-header-flow-topic-reopened": "Se reabrió el tema \"<strong>$1</strong>\".",
+ "notification-header-flow-topic-resolved-user-talk": "Se resolvió el tema \"<strong>$1</strong>\" en <strong>tu página de discusión</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Se reabrió el tema \"<strong>$1</strong>\"en <strong>tu página de discusión</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Se resolvió el tema \"<strong>$2</strong>\".",
+ "notification-email-batch-body-flow-topic-resolved": "Se resolvió el tema \"<strong>$2</strong>\".",
"flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|creó}} un tema nuevo en '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1 tema nuevo|$1 temas nuevos|250=250+ temas nuevos}} en '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un tema nuevo|$1 temas nuevos|100=99+ temas nuevos}} en <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|cambió}} el título de <span class=\"plainlinks\">[$2 $3]</span> a «$4» en [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$5|te}} {{GENDER:$1|mencionó}} en {{GENDER:$1|su}} <span class=\"plainlinks\">[$2 publicación]</span> en «$3» en «$4».",
"flow-notification-link-text-view-post": "Ver la entrada",
"flow-notification-link-text-view-topic": "Ver el tema",
+ "flow-notification-link-text-view-topics": "Ver temas",
"flow-notification-reply-email-subject": "$2 en $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondió}} a «$2» en $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 y {{PLURAL:$5|otro|otros}} $4 {{GENDER:$1|respondieron}} a «$2» en $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 y {{PLURAL:$4|otro|otros $4|100=otros 99+}} {{GENDER:$1|respondieron}} a «$2» en $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$3|te}} {{GENDER:$1|mencionó}} en $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|te}} {{GENDER:$1|mencionó}} en {{GENDER:$1|su}} publicación en «$2» en $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|editó}} una publicación",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|editó}} una publicación en «$2» en $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 y {{PLURAL:$5|otro|otros}} $4 {{GENDER:$1|editaron}} una publicación en «$2» en $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 y {{PLURAL:$4|otro|otros $4|100=otros 99+}} {{GENDER:$1|editaron}} una publicación en «$2» en $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|renombró}} tu tema",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renombró}} tu tema «$2» a «$3» en $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|creó}} un nuevo tema en $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|creó}} un nuevo tema titulado \"$2\" en $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1 tema nuevo|$1 temas nuevos|250=250+ temas nuevos}} en $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Notificarme cuando se produzcan acciones relacionadas conmigo en Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Un tema nuevo|$1 temas nuevos|100=99+ temas nuevos}} en $2",
+ "echo-category-title-flow-discussion": "Discusión de Flow",
+ "echo-pref-tooltip-flow-discussion": "Notificarme de cambios en temas o páginas que esté siguiendo.",
"flow-link-post": "publicación",
"flow-link-topic": "tema",
"flow-link-history": "historial",
@@ -303,18 +358,18 @@
"flow-moderation-confirm-unsuppress-topic": "Deshacer supresión",
"flow-moderation-confirm-undelete-topic": "Restaurar",
"flow-moderation-confirm-unhide-topic": "Revelar",
- "flow-moderation-confirmation-suppress-post": "La entrada fue suprimida con éxito.\n{{GENDER:$2|Considera}} entregar un comentario $1 sobre esta entrada.",
- "flow-moderation-confirmation-delete-post": "La entrada fue eliminada con éxito.\n{{GENDER:$2|Considera}} entregar un comentario $1 sobre esta entrada.",
- "flow-moderation-confirmation-hide-post": "La entrada fue ocultada con éxito.\n{{GENDER:$2|Considera}} entregar un comentario $1 sobre esta entrada.",
- "flow-moderation-confirmation-unsuppress-post": "Has deshecho la supresión de la publicación anterior con éxito.",
- "flow-moderation-confirmation-undelete-post": "Has restaurado la publicación anterior con éxito.",
- "flow-moderation-confirmation-unhide-post": "Has mostrado la publicación anterior con éxito.",
+ "flow-moderation-confirmation-suppress-post": "Se suprimió la entrada.\n{{GENDER:$2|Considera}} hacerle un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-delete-post": "Se eliminó la entrada .\n{{GENDER:$2|Considera}} hacerle un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-hide-post": "Se ocultó la entrada.\n{{GENDER:$2|Considera}} hacerle un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-unsuppress-post": "Has deshecho la supresión de la publicación anterior.",
+ "flow-moderation-confirmation-undelete-post": "Has restaurado la publicación anterior.",
+ "flow-moderation-confirmation-unhide-post": "Has mostrado la publicación anterior.",
"flow-moderation-confirmation-suppress-topic": "Este tema se eliminó.",
"flow-moderation-confirmation-delete-topic": "Este tema se eliminó.",
"flow-moderation-confirmation-hide-topic": "Este tema se ocultó.",
- "flow-moderation-confirmation-unsuppress-topic": "Has deshecho la supresión del hilo anterior con éxito.",
- "flow-moderation-confirmation-undelete-topic": "Has restaurado el hilo anterior con éxito.",
- "flow-moderation-confirmation-unhide-topic": "Has mostrado el hilo anterior con éxito.",
+ "flow-moderation-confirmation-unsuppress-topic": "Has deshecho la supresión del hilo anterior.",
+ "flow-moderation-confirmation-undelete-topic": "Has restaurado este hilo.",
+ "flow-moderation-confirmation-unhide-topic": "Has mostrado el hilo anterior.",
"flow-moderation-title-suppress-topic": "¿Quieres suprimir el tema?",
"flow-moderation-title-delete-topic": "¿Quieres eliminar el tema?",
"flow-moderation-title-hide-topic": "¿Quieres ocultar el tema?",
@@ -337,7 +392,7 @@
"flow-revision-permalink-warning-header-first": "Esto es un enlace permanente a la primera versión de la descripción.\nPuedes ver versiones posteriores en el [$2 historial de la página].",
"flow-compare-revisions-revision-header": "Versión de {{GENDER:$2|$2}} del $1",
"flow-compare-revisions-header-post": "Esta página muestra los {{GENDER:$3|cambios}} entre dos versiones de de una publicación de $3 en el tema \"[$5 $2]\" en [$4 $1].\nPuedes ver otras versiones de esta publicación en su [$6 historial].",
- "flow-compare-revisions-header-postsummary": "Esta página muestra los cambios entre dos versiones de un resumen en la publicación \"[$4 $2]\" en [$3 $1].\nPuedes ver otras versiones de esta publicación en su [$5 historial].",
+ "flow-compare-revisions-header-postsummary": "Esta página muestra los cambios entre dos versiones del resumen del tema \"[$4 $2]\" en [$3 $1].\nPuedes ver otras versiones de este resumen en el [$5 historial] del tema.",
"flow-compare-revisions-header-header": "Esta página muestra los {{GENDER:$2|cambios}} entre dos versiones de la descripción en [$3 $1].\nPuedes ver otras versiones de la descripción en su [$4 historial].",
"action-flow-create-board": "crear paneles de Flow en cualquier ubicación",
"right-flow-create-board": "Crear paneles de Flow en cualquier ubicación",
@@ -369,7 +424,7 @@
"flow-whatlinkshere-post": "de una [$1 publicación]",
"flow-whatlinkshere-header": "de la [$1 descripción]",
"flow-whatlinkshere-post-summary": "del [$1 resumen]",
- "flow": "Flujo",
+ "structureddiscussions": "Flujo",
"flow-special-desc": "Indicando un UUID, esta página especial redirige a un flujo de trabajo o publicación Flow.",
"flow-special-type": "Tipo",
"flow-special-type-post": "Publicación",
@@ -386,7 +441,7 @@
"flow-special-enableflow-confirmation": "Has creado un nuevo panel de discusión en [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archivo %d\n%s/Archivo%d\n%s/archivo %d\n%s/archivo%d",
"flow-conversion-archive-flow-page-name-format": "%s/Archivo Flow %d\n%s/ArchivoFlow%d",
- "flow-spam-confirmedit-form": "Confirma que eres un humano resolviendo el siguiente captha: $1",
+ "flow-spam-confirmedit-form": "Confirma que eres un humano resolviendo el siguiente CAPTCHA: $1",
"flow-embedding-unsupported": "Las discusiones todavía no pueden ser incrustadas.",
"mw-ui-unsubmitted-confirm": "Tienes cambios no enviados en esta página. ¿Estás seguro que deseas salir y perder tu trabajo?",
"flow-post-undo-hide": "deshacer ocultar",
@@ -398,113 +453,16 @@
"flow-importer-lqt-moved-thread-template-content": "Esta publicación de {{{author}}} se trasladó el {{{date}}}. Puedes encontrarla en [[{{{title}}}]].",
"flow-importer-lqt-converted-template": "Página LQT convertida a Flow",
"flow-importer-lqt-converted-template-content": "El historial de página anterior se archivó como respaldo en <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> el {{#time: Y-m-d|{{{date}}} }}.",
+ "flow-importer-lqt-converted-archive-template": "Archivo para páginas LQT convertidas",
"flow-importer-lqt-converted-archive-template-content": "Esta página es un página LiquidThreads archivada. '''No edites los contenidos de esta página'''. Dirige cualquier comentario adicional a la [[{{{from}}}|página de discusión actual]].",
"flow-importer-wt-converted-template": "Página de discusión de wikitexto convertida a Flow",
"flow-importer-wt-converted-template-content": "La discusión anterior se archivó en <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> el {{#time: Y-m-d|{{{date}}} }}.",
- "flow-importer-wt-converted-archive-template-content": "Esta página es un archivo. '''No edites los contenidos de esta página'''. Dirige cualquier comentario adicional a la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|página de discusión actual]].",
+ "flow-importer-wt-converted-archive-template": "Archivo para páginas de discusión de wikitexto convertidas",
+ "flow-importer-wt-converted-archive-template-content": "Esta página es un archivo. <strong>No edites los contenidos de esta página</strong>. Dirige cualquier comentario adicional a la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|página de discusión actual]].",
+ "flow-importer-lqt-suppressed-user-template": "Entrada LQT importada con un usuario suprimido",
"flow-importer-lqt-suppressed-user-template-content": "Esta revisión se importó desde LiquidThreads con un usuario suprimido. Ha sido reasignada al usuario actual.",
+ "flow-importer-lqt-different-author-signature-template": "Entrada LQT importada con un usuario firmante distinto",
"flow-importer-lqt-different-author-signature-template-content": "''Esta publicación la hizo [[User:{{{authorUser}}}|{{{authorUser}}}]], pero firmó como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Permite realizar acciones en páginas Flows.",
- "apihelp-flow-param-submodule": "El submódulo de Flow que se invocará.",
- "apihelp-flow-param-page": "La página en la que tomar la acción.",
- "apihelp-flow-example-1": "Editar la descripción de «[[Talk:Sandbox]]»",
- "apihelp-flow+close-open-topic-description": "En desuso en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]",
- "apihelp-flow+close-open-topic-param-moderationState": "Estado en el que poner el tema, ya sea \"lock\" (abierto) o \"unlock\" (cerrado).",
- "apihelp-flow+close-open-topic-param-reason": "El motivo por el cual bloquear o desbloquear el tema.",
- "apihelp-flow+edit-header-description": "Edita la descripción de un tablero.",
- "apihelp-flow+edit-header-param-prev_revision": "ID de revisión de la revisión actual de la descripción, para comprobar conflictos de edición.",
- "apihelp-flow+edit-header-param-content": "Contenido para la descripción.",
- "apihelp-flow+edit-header-param-format": "Formato de la descripción (wikitexto|html)",
- "apihelp-flow+edit-header-example-1": "Editar la descripción de [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Editar el contenido de una publicación.",
- "apihelp-flow+edit-post-param-postId": "ID de la publicación.",
- "apihelp-flow+edit-post-param-prev_revision": "ID de revisión de la revisión actual de la publicación, para comprobar conflictos de edición.",
- "apihelp-flow+edit-post-param-content": "Contenido para publicar.",
- "apihelp-flow+edit-post-param-format": "Formato del contenido de la publicación (wikitexto|html)",
- "apihelp-flow+edit-post-example-1": "Editar una publicación en [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Edita el título de un tema.",
- "apihelp-flow+edit-title-param-prev_revision": "ID de revisión de la revisión actual del título, para comprobar conflictos de edición.",
- "apihelp-flow+edit-title-param-content": "Contenido para el título.",
- "apihelp-flow+edit-title-example-1": "Editar el título de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Editar el contenido del resumen de un tema.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "ID de revisión de la revisión de la revisión actual del resumen del tema, si hubiera, para comprobar conflictos de edición.",
- "apihelp-flow+edit-topic-summary-param-summary": "Contenido del resumen.",
- "apihelp-flow+edit-topic-summary-param-format": "Formato del resumen (wikitexto|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Editar el resumen de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Bloquear o desbloquear un tema de Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Estado en el que poner el tema, ya sea <kbd>lock</kbd> (abierto) o <kbd>unlock</kbd> (cerrado).",
- "apihelp-flow+lock-topic-param-reason": "El motivo por el cual bloquear o desbloquear el tema. Ten en cuenta que el cliente Flow de la wiki usa aquí «Marcado como resuelto» y, opcionalmente, añade información adicional en el resumen.",
- "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Modera una publicación de Flow.",
- "apihelp-flow+moderate-post-param-moderationState": "A qué nivel moderar.",
- "apihelp-flow+moderate-post-param-reason": "Motivo de la moderación.",
- "apihelp-flow+moderate-post-param-postId": "ID de la publicación a moderar.",
- "apihelp-flow+moderate-post-example-1": "Eliminar una publicación en [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Modera un tema de Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "A qué nivel moderar.",
- "apihelp-flow+moderate-topic-param-reason": "Motivo de la moderación.",
- "apihelp-flow+moderate-topic-example-1": "Eliminar el tema [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Crea un nuevo tema de Flow en el flujo de trabajo indicado.",
- "apihelp-flow+new-topic-param-topic": "Texto para el nuevo título del tema.",
- "apihelp-flow+new-topic-param-content": "Contenido para la respuesta inicial del tema.",
- "apihelp-flow+new-topic-param-format": "Formato de la respuesta inicial del nuevo tema (wikitexto|html)",
- "apihelp-flow+new-topic-example-1": "Crear un nuevo tema en [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Respuestas a una publicación.",
- "apihelp-flow+reply-param-replyTo": "ID de la publicación a la que responder.",
- "apihelp-flow+reply-param-content": "Contenido para una nueva publicación.",
- "apihelp-flow+reply-param-format": "Formato de la publicación nueva (wikitexto|html)",
- "apihelp-flow+reply-example-1": "Responder a una publicación en [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Formato en que se devolverá el contenido.",
- "apihelp-flow+view-header-description": "Ver la descripción de un tablero.",
- "apihelp-flow+view-header-param-revId": "Cargar esta revisión en vez de la más reciente.",
- "apihelp-flow+view-header-example-1": "Obtener la descripción de [[Talk:Sandbox]] como wikitexto",
- "apihelp-flow+view-post-description": "Ver una publicación.",
- "apihelp-flow+view-post-param-postId": "Identificador de la publicación que se visualizará.",
- "apihelp-flow+view-post-param-format": "Formato en que se devolverá el contenido.",
- "apihelp-flow+view-post-example-1": "Obtener el contenido de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-post-history-description": "Ver el historial de revisión de una publicación.",
- "apihelp-flow+view-post-history-param-postId": "Identificador de la publicación para el cual ver el historial de revisiones.",
- "apihelp-flow+view-post-history-param-format": "Formato en que se devolverá el contenido.",
- "apihelp-flow+view-post-history-example-1": "Obtener las revisiones de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topic-description": "Ver un tema.",
- "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Ver el historial de revisión de un tema.",
- "apihelp-flow+view-topic-history-param-format": "Formato en que se devolverá el contenido.",
- "apihelp-flow+view-topic-history-example-1": "Ver las revisiones de una publicación en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topic-summary-description": "Ver el resumen de un tema.",
- "apihelp-flow+view-topic-summary-param-format": "Formato en que se devolverá el contenido.",
- "apihelp-flow+view-topic-summary-param-revId": "Cargar esta revisión en vez de la más reciente.",
- "apihelp-flow+view-topic-summary-example-1": "Ver el resumen de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topiclist-description": "Ver una lista de temas.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Dirección de ordenamiento de los temas.",
- "apihelp-flow+view-topiclist-param-sortby": "Opción de ordenamiento de los temas. Puede ser <kbd>updated</kbd> (ordenado por tiempo de actualización de tema), o bien <kbd>newest</kbd> (ordenado por tiempo de creación de tema).",
- "apihelp-flow+view-topiclist-param-savesortby": "Guardar la opción de ordenamiento en las preferencias del usuario, si se establece.",
- "apihelp-flow+view-topiclist-param-offset-id": "Valor de compensación (en formato UUID) para iniciar a escoger temas; utilizado solo con los pedidos <kbd>más nuevos</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Valor de compensación (como un tema de actualización de sello de tiempo, en formato <code>TS_MW</code> (<code>AAAAMMDDHHMMSS</code>)), para empezar a buscar temas; usado solo con ordenamiento <kbd>updated</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Número de temas que se obtendrán.",
- "apihelp-flow+view-topiclist-example-1": "Lista de temas en [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Convertir texto entre wikitexto y HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Formato de origen para conversión de contenido.",
- "apihelp-flow-parsoid-utils-param-to": "Formato de destino para conversión de contenido.",
- "apihelp-flow-parsoid-utils-param-content": "El contenido que se convertirá.",
- "apihelp-flow-parsoid-utils-param-title": "Título de la página. No puede usarse en conjunto con $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "Identificador de la página. No puede usarse en conjunto con $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Convertir wikitexto (<nowiki>'''un''' ''ejemplo''</nowiki>) en HTML",
- "apihelp-query+flowinfo-description": "Obtener información básica de Flow acerca de una página.",
- "apihelp-query+flowinfo-example-1": "Obtener información de Flow sobre [[Talk:Sandbox]], [[Main Page]] y [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Obtener la información necesaria para deshacer ediciones de descripciones.",
- "apihelp-flow+undo-edit-header-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
- "apihelp-flow+undo-edit-header-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
- "apihelp-flow+undo-edit-header-example-1": "Obtener información sobre deshacer una edición de descripción en [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Obtener la información necesaria para deshacer ediciones de publicaciones.",
- "apihelp-flow+undo-edit-post-param-postId": "Identificador de publicación para deshacer.",
- "apihelp-flow+undo-edit-post-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
- "apihelp-flow+undo-edit-post-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
- "apihelp-flow+undo-edit-post-example-1": "Obtener información acerca de cómo deshacer una edición de publicación en un tema específico.",
- "apihelp-flow+undo-edit-topic-summary-description": "Recuperar información necesaria para deshacer las ediciones del resumen de este tema.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Identificador de revisión desde el cual empezar a deshacer.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Identificador de revisión hasta el cual terminar de deshacer.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Obtener información acerca de cómo deshacer una edición de resumen en un tema específico.",
"flow-edited": "Editada",
"flow-edited-by": "Editado por $1",
"flow-lqt-redirect-reason": "Redirección de la publicación LiquidThreads a su publicación Flow convertida.",
@@ -521,7 +479,7 @@
"flow-undo-edit-content": "Puedes deshacer la edición. Antes de deshacerla, comprueba la siguiente comparación para verificar que realmente es lo que quieres hacer y entonces guarda los cambios para así efectuar la reversión.",
"flow-undo-edit-failure": "No se ha podido deshacer la edición ya que otro usuario ha realizado ediciones intermedias.",
"group-flow-bot": "Bots de Flow",
- "group-flow-bot-member": "Bot de Flow",
+ "group-flow-bot-member": "bot de Flow",
"grouppage-flow-bot": "Project:Bots de Flow",
"flow-ve-mention-context-item-label": "Mencionar",
"flow-ve-mention-inspector-title": "Mención",
@@ -531,7 +489,7 @@
"flow-ve-mention-inspector-invalid-user": "El nombre de usuario «$1» no está registrado.",
"flow-wikitext-editor-help": "El wikitexto $1.",
"flow-wikitext-editor-help-and-preview": "El wikitexto $1 y en cualquier momento puedes $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|usa un lenguaje de marcado]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|usa un lenguaje de marcado]]",
"flow-wikitext-editor-help-preview-the-result": "previsualizar el resultado",
"flow-wikitext-switch-editor-tooltip": "Cambiar al editor visual",
"flow-ve-switch-editor-tool-title": "Cambiar al editor de wikitexto",
@@ -540,21 +498,27 @@
"flow-mark-diff-patrolled-link-text": "Marcar como verificada",
"flow-mark-diff-patrolled-link-title": "Marcar como verificada",
"flow-talk-page-beta-feature-message": "Flow en la página de discusión",
- "flow-talk-page-beta-feature-description": "Habilita un sistema de discusión estructurado nuevo en tu página de discusión. Flow simplifica las discusiones con sitios claros para escribir y responder, y permite notificaciones por cada tema. Las discusiones existentes en wikitexto se archivarán. Esta característica no está habilitada predeterminadamente; los usuarios la tendrán que habilitar por separado. Si se desactivada esta característica, el tablero de Flow se trasladará a una subpágina y se desarchivará la página de discusión previa.",
- "flow-notification-link-text-enabled-on-talkpage": "Ver la página de discusión del usuario",
+ "flow-talk-page-beta-feature-description": "Habilita un sistema de discusión estructurado nuevo en {{GENDER:|tu}} página de discusión. Flow simplifica las discusiones con sitios claros para escribir y responder, y permite notificaciones por cada tema. Esta característica no está habilitada predeterminadamente; los usuarios la tendrán que habilitar por separado.<br /><br />Las discusiones existentes en wikitexto se archivarán. Si se desactivada esta característica, el tablero de Flow se trasladará a una subpágina y se desarchivará la página de discusión previa.\n[[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Aprende más sobre su activación]].",
+ "flow-notification-link-text-enabled-on-talkpage": "Ver la página de discusión {{GENDER:|del usuario|de la usuaria}}",
"flow-notification-enabled-on-talkpage-title": "Sistema de discusión nuevo activado para {{GENDER:$1|tu}} página de discusión<br /><small>Disponible en [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Nuevo sistema de discusión en $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, el nuevo sistema de discusión del wiki, se ha activado en tu página de discusión de {{SITENAME}}. Puedes obtener más información, realizar comentarios o desactivar el nuevo sistema en cualquier momento desde la sección de características beta en tus preferencias.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, el nuevo sistema de discusión del wiki, se ha activado en {{GENDER:$1|tu}} página de discusión de {{SITENAME}}. Puedes obtener más información, realizar comentarios o desactivar el nuevo sistema en cualquier momento desde la sección de características beta en {{GENDER:$1|tus}} preferencias.",
"flow-beta-feature-add-archive-template-edit-summary": "Adición de la plantilla de archivo",
"flow-beta-feature-remove-archive-template-edit-summary": "Eliminación de la plantilla de archivo",
- "flow-dialog-cancelconfirm-title": "¿Estás seguro?",
- "flow-dialog-cancelconfirm-message": "¿Estás seguro de que quieres cancelar sin guardar primero?",
+ "flow-dialog-cancelconfirm-title": "¿Estás {{GENDER:|seguro|segura}}?",
+ "flow-dialog-cancelconfirm-message": "¿Estás {{GENDER:|seguro|segura}} de que quieres cancelar sin guardar primero?",
"flow-dialog-cancelconfirm-keep": "Continuar editando",
"flow-dialog-cancelconfirm-discard": "Descartar los cambios",
+ "flow-optin-archive-wikitext": "Se traslada página de wikitexto para hacer lugar para un tablero de discusión.",
+ "flow-optin-archive-flow-board": "Se traslada tablero de discusión para hacer lugar para una página de wikitexto.",
+ "flow-optin-restore-wikitext": "Se restaura página de wikitexto archivada.",
+ "flow-optin-restore-flow-board": "Se restaura tablero de discusión archivado.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Bienvenido|Bienvenida}} a tu nueva página de discusión de usuario",
"flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Tu}} página de discusión es el lugar donde otros editores pueden ponerse en contactarte. Con Flow, es más fácil empezar temas nuevos y realizar un seguimiento de las conversaciones.",
"flow-guidedtour-optin-find-old-conversations": "Ver {{GENDER:$1|tus}} conversaciones antiguas",
"flow-guidedtour-optin-find-old-conversations-description": "Las conversaciones previas se han trasladado a una página de archivo.",
"flow-guidedtour-optin-feedback": "Bríndanos {{GENDER:$1|tus}} comentarios.",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Puedes}} obtener más información, realizar comentarios o desactivar el nuevo sistema en cualquier momento desde la sección de características beta en tus preferencias."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Puedes}} obtener más información, realizar comentarios o desactivar el nuevo sistema en cualquier momento desde la sección de características beta en tus preferencias.",
+ "flow-action-not-page": "El objeto de la página es una instancia de una clase equivocada",
+ "flow-action-wrong-title-content-model": "La página está siendo manejado por el Flujo, pero el Título de la clase indica que el modelo de contenido es '$1'. Este es un error de configuración o estado incoherente. Por ejemplo, esto puede ser en realidad un no-Flujo de la página en un Flujo de espacio de nombres, con <code>rev_content_model</code> no se llena."
}
diff --git a/Flow/i18n/et.json b/Flow/i18n/et.json
index 85d7c6f4..a94819b9 100644
--- a/Flow/i18n/et.json
+++ b/Flow/i18n/et.json
@@ -3,16 +3,19 @@
"authors": [
"Pikne",
"Lyrixn",
- "Boxmein"
+ "Boxmein",
+ "Cumbril"
]
},
- "flow-desc": "Töövoo haldamise süsteem",
+ "flow-desc": "Arutelusüsteem",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|kustutas}} leheküljel [[$6]] [$4 postituse] \"[[$3|$5]]\"",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|taastas}} leheküljel [[$6]] [$4 postituse] \"[[$3|$5]]\"",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|varjas}} leheküljel [[$6]] [$4 postituse] \"[[$3|$5]]\"",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|kustutas}} leheküljel [[$6]] teema \"[[$3|$5]]\"",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|taastas}} leheküljel [[$6]] teema \"[[$3|$5]]\"",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|varjas}} leheküljel [[$6]] teema \"[[$3|$5]]\"",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|märkis}} leheküljel \"[[$6]]\" teema \"[[$3|$5]]\" lahendatuks",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|taasavas}} leheküljel \"[[$6]]\" teema \"[[$3|$5]]\"",
"flow-board-header-browse-topics-link": "Sirvi teemasid",
"flow-board-header": "Sellest arutelust",
"flow-board-collapse-description": "Peida kirjeldus",
@@ -31,6 +34,7 @@
"flow-suppress-title-content": "$1 varjas selle teema.",
"flow-suppress-header-content": "{{GENDER:$1|Varjanud}} $2",
"flow-cancel": "Loobu",
+ "flow-edit-summary-placeholder": "Kirjelda lühidalt selle arutelu tulemust",
"flow-summary-authored": "Kokkuvõtte autor: $1",
"flow-newtopic-content-placeholder": "Postita uus sõnum leheküljele \"$1\"",
"flow-newtopic-save": "Lisa teema",
@@ -48,7 +52,7 @@
"flow-history-action-unhide-post": "tühista peitmine",
"flow-history-action-restore-post": "ennista",
"flow-history-action-lock-topic": "lahenda",
- "flow-history-action-unlock-topic": "ava taas",
+ "flow-history-action-unlock-topic": "taasava",
"flow-post-action-view": "Püsilink",
"flow-post-action-suppress-post": "Varja",
"flow-post-action-delete-post": "Kustuta",
@@ -66,7 +70,7 @@
"flow-topic-action-hide-topic": "Peida teema",
"flow-topic-action-delete-topic": "Kustuta teema",
"flow-topic-action-lock-topic": "Märgi lahendatuks",
- "flow-topic-action-unlock-topic": "Ava teema taas",
+ "flow-topic-action-unlock-topic": "Taasava teema",
"flow-topic-action-summarize-topic": "Võta kokku",
"flow-topic-action-resummarize-topic": "Redigeeri teema kokkuvõtet",
"flow-topic-action-update-topic-summary": "Uuenda kokkuvõtet",
@@ -104,35 +108,35 @@
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|varjas}} [$4 teema] \"$6\" (<em>$5</em>)",
"flow-rev-message-locked-topic": "$1 {{GENDER:$2|märkis}} [$4 teema] \"$6\" lahendatuks (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "märgitud lahendatuks",
- "flow-rev-message-restore-topic-reason": "avatud uuesti",
+ "flow-rev-message-restore-topic-reason": "taasavatud",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|ennistas}} [$4 teema] \"$6\" (<em>$5</em>)",
"flow-rc-topic-of-board": "$2 – teema \"$1\"",
"flow-topic-comments": "{{PLURAL:$1|Üks kommentaar|$1 kommentaari|0=Kommentaare {{GENDER:$2|pole}} veel.}}",
"flow-workflow": "töövoog",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 vastas leheküljel \"'''$4'''\".",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ja veel {{PLURAL:$6|üks kasutaja vastas|$5 kasutajat vastasid}} leheküljel \"'''$3'''\".",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 vastas leheküljel \"<strong>$4</strong>\".",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ja veel {{PLURAL:$5|üks kasutaja vastas|$5 kasutajat vastasid|100=rohkem kui 99 kasutajat vastasid}} leheküljel \"<strong>$3</strong>\".",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 redigeeris sinu <span class=\"plainlinks\">[$5 postitust]</span> leheküljel \"[[$3|$4]]\".",
- "flow-notification-edit-bundle": "$1 ja veel {{PLURAL:$6|üks kasutaja redigeeris|$5 kasutajat redigeerisid}} <span class=\"plainlinks\">[$4 postitust]</span> teemas \"$2\" leheküljel \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 alustas leheküljel \"'''$3'''\" uut teemat.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|Üks uus teema|$1 uut teemat|250=Üle 250 uue teema}} leheküljel \"'''<span class=\"plainlinks\">[$3 $2]</span>'''\"",
+ "flow-notification-edit-bundle": "$1 ja veel {{PLURAL:$5|üks kasutaja redigeeris|$5 kasutajat redigeerisid|100=rohkem kui 99 kasutajat redigeerisid}} <span class=\"plainlinks\">[$4 postitust]</span> teemas \"$2\" leheküljel \"$3\".",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 alustas leheküljel \"<strong>$3</strong>\" uut teemat.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Üks uus teema|$1 uut teemat|100=Üle 100 uue teema}} leheküljel \"<strong><span class=\"plainlinks\">[$3 $2]</span></strong>\"",
"flow-notification-rename": "$1 pani leheküljel \"[[$5|$6]]\" teema <span class=\"plainlinks\">\"[$2 $3]\"</span> uueks pealkirjaks \"$4\".",
"flow-notification-mention": "$1 mainis {{GENDER:$5|sind}} leheküljel \"$4\" teema \"$3\" <span class=\"plainlinks\">[$2 postituses]</span>.",
"flow-notification-link-text-view-post": "Vaata postitust",
"flow-notification-link-text-view-topic": "Vaata teemat",
"flow-notification-reply-email-subject": "\"$2\" leheküljel \"$3\"",
"flow-notification-reply-email-batch-body": "$1 vastas teemale \"$2\" leheküljel \"$3\".",
- "flow-notification-reply-email-batch-bundle-body": "$1 ja veel {{PLURAL:$5|üks kasutaja vastas|$4 kasutajat vastasid}} leheküljel \"$3\" teemale \"$2\".",
+ "flow-notification-reply-email-batch-bundle-body": "$1 ja veel {{PLURAL:$4|üks kasutaja vastas|$4 kasutajat vastasid|100=rohkem kui 99 kasutajat vastasid}} leheküljel \"$3\" teemale \"$2\".",
"flow-notification-mention-email-subject": "$1 mainis {{GENDER:$3|sind}} leheküljel \"$2\"",
"flow-notification-mention-email-batch-body": "$1 mainis {{GENDER:$4|sind}} leheküljel \"$3\" teema \"$2\" postituses.",
"flow-notification-edit-email-subject": "$1 redigeeris postitust",
"flow-notification-edit-email-batch-body": "$1 redigeeris postitust teemas \"$2\" leheküljel \"$3\".",
- "flow-notification-edit-email-batch-bundle-body": "$1 ja veel {{PLURAL:$5|üks kasutaja redigeeris|$4 kasutajat redigeerisid}} postitust leheküljel \"$2\" teemas \"$3\".",
+ "flow-notification-edit-email-batch-bundle-body": "$1 ja veel {{PLURAL:$4|üks kasutaja redigeeris|$4 kasutajat redigeerisid|100=rohkem kui 99 kasutajat redigeerisid}} postitust leheküljel \"$2\" teemas \"$3\".",
"flow-notification-rename-email-subject": "$1 pani sinu teemale uue pealkirja",
"flow-notification-rename-email-batch-body": "$1 pani leheküljel \"$4\" sinu teema \"$2\" uueks pealkirjaks \"$3\".",
"flow-notification-newtopic-email-subject": "$1 alustas uut teemat leheküljel \"$2\"",
"flow-notification-newtopic-email-batch-body": "$1 alustas leheküljel \"$3\" uut teemat \"$2\".",
"echo-category-title-flow-discussion": "Voogarutelu",
- "echo-pref-tooltip-flow-discussion": "Teavita mind, kui voogarutelus esineb minusse puutuvaid tegevusi.",
+ "echo-pref-tooltip-flow-discussion": "Teavita mind tegevusest teemas või leheküljel, mida jälgin.",
"flow-link-topic": "teema",
"flow-moderation-placeholder-suppress-post": "Palun {{GENDER:$3|selgita}}, miks selle postituse varjad.",
"flow-moderation-placeholder-delete-post": "Palun {{GENDER:$3|selgita}}, miks selle postituse kustutad.",
@@ -162,8 +166,9 @@
"flow-revision-permalink-warning-postsummary-first": "See püsilink viitab selle postituse kokkuvõtte esimesele versioonile.\nHilisemaid versioone saad vaadata postituse [$4 ajaloo leheküljelt].",
"flow-compare-revisions-revision-header": "Versioon: $2 $1",
"flow-compare-revisions-header-post": "See lehekülg näitab erinevust kasutaja $3 postituse kahe versiooni vahel leheküljel [$4 $1] teemas \"[$5 $2]\".\nPostituse teisi versioone saad vaadata selle [$6 ajalooleheküljel].",
- "flow-compare-revisions-header-postsummary": "See lehekülg näitab erinevust postituse kokkuvõtte kahe versiooni vahel leheküljel [$3 $1] teemas \"[$4 $2]\".\nPostituse teisi versioone saad vaadata selle [$5 ajalooleheküljel].",
+ "flow-compare-revisions-header-postsummary": "See lehekülg näitab erinevust teema \"[$4 $2]\" kokkuvõtte kahe versiooni vahel leheküljel [$3 $1].\nTeema kokkuvõtte teisi versioone saad vaadata teema [$5 ajalooleheküljel].",
"flow-compare-revisions-header-header": "See lehekülg näitab {{GENDER:$2|erinevust}} kirjelduse kahe versiooni vahel leheküljel [$3 $1].\nKirjelduse teisi versioone saad vaadata selle [$4 ajalooleheküljel].",
+ "right-flow-create-board": "Luua kõikjal voogarutelusid",
"right-flow-hide": "Peita voogarutelu teemasid ja postitusi",
"right-flow-lock": "Märkida voogarutelu teemasid lahendatuks",
"right-flow-delete": "Kustutada voogarutelu teemasid ja postitusi",
@@ -187,6 +192,7 @@
"flow-terms-of-use-summarize": "Kui klõpsad \"{{int:flow-topic-action-update-topic-summary}}\", nõustud selle viki kasutustingimustega.",
"flow-terms-of-use-lock-topic": "Kui klõpsad \"{{int:flow-topic-action-lock-topic}}\", nõustud selle viki kasutustingimustega.",
"flow-terms-of-use-unlock-topic": "Kui klõpsad \"{{int:flow-topic-action-unlock-topic}}\", nõustud selle viki kasutustingimustega.",
+ "flow-special-desc": "See erilehekülg suunab ümber antud UUID-ga Flow töövoo või voogarutelu postituse juurde.",
"flow-special-type": "Tüüp",
"flow-special-type-post": "Postitus",
"flow-special-type-workflow": "Töövoog",
@@ -194,12 +200,13 @@
"flow-edited-by": "Redigeerinud $1",
"flow-ve-mention-context-item-label": "Mainimine",
"flow-ve-mention-inspector-title": "Mainimine",
+ "flow-ve-mention-inspector-remove-label": "Eemalda",
"flow-ve-mention-placeholder": "Kasutajanimi",
"flow-ve-mention-tool-title": "Maini kasutajat",
"flow-ve-mention-inspector-invalid-user": "Kasutajanimi \"$1\" pole registreeritud.",
"flow-wikitext-editor-help": "Vikitekst $1.",
"flow-wikitext-editor-help-and-preview": "Vikitekst $1. Saad $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|kasutab märgistuskeelt]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|kasutab märgistuskeelt]]",
"flow-wikitext-editor-help-preview-the-result": "tulemust eelvaadelda",
"flow-wikitext-switch-editor-tooltip": "Vaheta visuaaltoimeti vastu",
"flow-ve-switch-editor-tool-title": "Vaheta vikiteksti redaktori vastu"
diff --git a/Flow/i18n/eu.json b/Flow/i18n/eu.json
index a8dc81d8..0fb5137e 100644
--- a/Flow/i18n/eu.json
+++ b/Flow/i18n/eu.json
@@ -2,35 +2,77 @@
"@metadata": {
"authors": [
"Subi",
- "Sator"
+ "Sator",
+ "An13sa",
+ "Mikel Ibaiba"
]
},
+ "flow-desc": "Eztabaida-sistema",
"flow-board-header-browse-topics-link": "Arakatu gaiak",
+ "flow-board-collapse-description": "Ezkutatu deskribapena",
+ "flow-board-expand-description": "Erakutsi deskribapena",
"flow-topic-moderated-reason-prefix": "Arrazoia:",
"flow-post-actions": "Ekintzak",
"flow-topic-actions": "Ekintzak",
"flow-cancel": "Utzi",
+ "flow-skip-summary": "Jauzi",
"flow-show-change": "Erakutsi aldaketak",
"flow-newtopic-title-placeholder": "Gai berria",
+ "flow-newtopic-header": "Gehitu gai berria",
+ "flow-newtopic-save": "Gehitu gaia",
+ "flow-newtopic-save-anonymously": "Gehitu gaia anonimoki",
"flow-reply-link": "{{GENDER:$1|Erantzun}}",
- "flow-thank-link": "{{GENDER:$1|Eskertu}}",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Eskertu}}}}",
"flow-history-action-delete-post": "ezabatu",
"flow-history-action-hide-post": "ezkutatu",
+ "flow-post-action-view": "Lotura iraunkorra",
"flow-post-action-post-history": "Historia",
"flow-post-action-delete-post": "Ezabatu",
"flow-post-action-hide-post": "Ezkutatu",
"flow-post-action-edit-post": "Aldatu",
"flow-post-action-edit-post-submit": "Aldaketak gorde",
+ "flow-post-action-edit-post-submit-anonymously": "Gorde aldaketak anonimoki",
"flow-post-action-undo-moderation": "Desegin",
+ "flow-topic-action-view": "Lotura iraunkorra",
"flow-topic-action-history": "Historia",
"flow-topic-action-hide-topic": "Ezkutatu gaia",
"flow-topic-action-delete-topic": "Ezabatu gaia",
+ "flow-topic-action-unlock-topic": "Berrireki gaia",
+ "flow-topic-action-summarize-topic": "Laburtu",
+ "flow-topic-action-resummarize-topic": "Editatu gaiaren laburpena",
+ "flow-topic-action-update-topic-summary": "Eguneratu laburpena",
+ "flow-topic-action-suppress-topic": "Ezabatu gaia",
+ "flow-topic-action-unhide-topic": "Erakutsi gaia",
"flow-topic-action-undo-moderation": "Desegin",
"flow-topic-action-watchlist-remove": "Harpidetza kendu",
+ "flow-error-invalid-undelete": "Orrialdea ezin izan da berrezarri orain eztabaida bat dagoelako.",
+ "flow-edit-header-submit": "Gorde deskribapena",
+ "flow-edit-header-submit-anonymously": "Gorde deskribapena anonimoki",
+ "flow-edit-title-submit": "Aldatu izenburua",
+ "flow-edit-title-submit-anonymously": "Aldatu izenburua anonimoki",
+ "flow-edit-post-submit": "Bidali aldaketak",
+ "flow-edit-post-submit-anonymously": "Bidali aldaketak anonimoki",
"flow-history-day": "Gaur",
+ "flow-show-comments-title": "{{PLURAL:$1|Ikusi iruzkina|Ikusi iruzkinak}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Ezkutatu iruzkina|Ezkutatu iruzkinak}}",
+ "flow-comment-deleted": "Ezabatutako iruzkina",
+ "flow-comment-hidden": "Ezkutatutako iruzkina",
+ "flow-notification-link-text-view-topic": "Ikusi gaia",
+ "flow-notification-link-text-view-topics": "Ikusi gaiak",
"flow-moderation-confirm-delete-post": "Ezabatu",
"flow-moderation-confirm-hide-post": "Ezkutatu",
"flow-moderation-confirm-delete-topic": "Ezabatu",
"flow-moderation-confirm-hide-topic": "Ezkutatu",
+ "flow-topic-count": "Gaiak ($1)",
+ "flow-load-more": "Kargatu gehiago",
+ "flow-no-more-fwd": "Ez dago gai zaharragorik",
+ "flow-newest-topics": "Gairik berrienak",
+ "flow-undo": "desegin",
+ "flow-undo-your-text": "Zure testua",
+ "flow-ve-mention-tool-title": "Lankide bat aipatu",
+ "flow-wikitext-editor-help-preview-the-result": "Emaitza aurreikusi",
+ "flow-wikitext-switch-editor-tooltip": "Aldatu editore bisualera",
+ "flow-ve-switch-editor-tool-title": "Aldatu wikitestu-editorera",
+ "flow-mark-diff-patrolled-link-title": "Patruilatutzat markatu",
"flow-dialog-cancelconfirm-title": "Ziur zaude?"
}
diff --git a/Flow/i18n/fa.json b/Flow/i18n/fa.json
index 2342eae5..7425d732 100644
--- a/Flow/i18n/fa.json
+++ b/Flow/i18n/fa.json
@@ -14,93 +14,121 @@
"Leyth",
"Pirehelokan",
"MRG90",
- "Mardetanha"
+ "Mardetanha",
+ "Huji",
+ "Ladsgroup",
+ "Saeidpourbabak",
+ "Quiddity",
+ "Macofe",
+ "Rtemis",
+ "Dalba",
+ "AzorAhai",
+ "Alifakoor"
]
},
- "enableflow": "فعال‌سازی جریان",
+ "enablestructureddiscussions": "فعال‌سازی فلو",
+ "notification-dynamic-actions-flow-board-unwatch": "پی‌گیری فعالیت‌ها در «$1» را {{GENDER:$3|متوقف کن}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "شما دیگر صفحهٔ «$1» را پی‌گیری {{GENDER:$3|نمی‌کنید}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "این روی تک تک مبحث‌هایی که پی‌گیری {{GENDER:$3|می‌کنید}} تأثیر نمی‌گذارد. شما می‌توانید هر زمان خواستید این صفحه را [$2 پی‌گیری کنید].",
+ "notification-dynamic-actions-flow-topic-unwatch": "پی‌گیری این مبحث را {{GENDER:$3|متوقف کن}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "شما دیگر «$1» را پی‌گیری {{GENDER:$3|نمی‌کنید}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "شما می‌توانید هر زمان خواستید [$2 این مبحث] را {{GENDER:$3|‌پی‌گیری کنید}}.",
"flow-desc": "سیستم مدیریت جریان کار",
- "flow-talk-taken-over-comment": "/* این صفحه به صفحه بحث افزونهٔ فلو تبدیل شد */",
- "log-name-flow": "سیاههٔ فعالیت جریان",
- "logentry-delete-flow-delete-post": "$1 یک [$4 پست] را در «[[$3|$5]]» بر [[$6]] {{GENDER:$2|حذف کرد}}",
- "logentry-delete-flow-restore-post": "$1 یک [$4 ارسال] را در «[[$3|$5]]» بر [[$6]] {{GENDER:$2|بازیابی کرد}}",
- "logentry-suppress-flow-suppress-post": "$1 یک [$4 پست] را در «[[$3|$5]]» بر [[$6]] {{GENDER:$2|سرکوب شده}}",
- "logentry-suppress-flow-restore-post": "$1 یک [$4 پست] را در «[[$3|$5]]» بر [[$6]] {{GENDER:$2|حذف کرد}}",
- "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|حذف شده}} موضوع «[[$3|$5]]» بر [[$6]]",
- "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|بازگردانده شده}} موضوع «[[$3|$5]]» بر [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|سرکوب شده}} موضوع «[[$3|$5]]» بر [[$6]]",
- "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|حذف شده}} موضوع «[[$3|$5]]» بر [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] در [[$3]] از LiquidThreads به فلوو درون‌ریزی شد",
- "flow-user-moderated": "کاربر کنترل شده",
+ "flow-talk-taken-over-comment": "/* این صفحه به یک تالار گفتگوی فلو تبدیل شد */",
+ "log-name-flow": "سیاههٔ فعالیت فلو",
+ "logentry-delete-flow-delete-post": "$1 یک [$4 ارسال] را در «[[$3|$5]]» در [[$6]] {{GENDER:$2|حذف کرد}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 ارسال را در مبحث [[$3]] {{GENDER:$2|حذف کرد}}",
+ "logentry-delete-flow-restore-post": "$1 یک [$4 ارسال] را در «[[$3|$5]]» بر [[$6]] {{GENDER:$2|احیا کرد}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 یک ارسال را در مبحث [[$3]] {{GENDER:$2|احیا کرد}}",
+ "logentry-suppress-flow-suppress-post": "$1 یک [$4 ارسال] را در «[[$3|$5]]» در [[$6]] {{GENDER:$2|فرونشانی کرد}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 ارسال را در مبحث [[$3]] {{GENDER:$2|فرونشانی کرد}}",
+ "logentry-suppress-flow-restore-post": "$1 یک [$4 ارسال] را در «[[$3|$5]]» در [[$6]] {{GENDER:$2|حذف کرد}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 ارسال را در مبحث [[$3]] {{GENDER:$2|حذف کرد}}",
+ "logentry-delete-flow-delete-topic": "مبحث «[[$3|$5]]» در [[$6]] را {{GENDER:$2|حذف کرد}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 یک مبحث را در [[$3]] {{GENDER:$2|حذف کرد}}",
+ "logentry-delete-flow-restore-topic": "$1 مبحث «[[$3|$5]]» در [[$6]] را {{GENDER:$2|احیا کرد}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "یک مبحث را در [[$3]] {{GENDER:$2|احیا کرد}}",
+ "logentry-suppress-flow-suppress-topic": "$1 مبحث «[[$3|$5]]» در [[$6]] را {{GENDER:$2|فرونشانی کرد}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 یک مبحث را در [[$3]] {{GENDER:$2|فرونشانی کرد}}",
+ "logentry-suppress-flow-restore-topic": "$1 مبحث «[[$3|$5]]» در [[$6]] را {{GENDER:$2|حذف کرد}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 یک مبحث را در [[$3]] {{GENDER:$2|حذف کرد}}",
+ "logentry-lock-flow-lock-topic": "$1 مبحث «[[$3|$5]]» در [[$6]] را به عنوان حل‌شده {{GENDER:$2|علامت زد}}",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 یک مبحث را در [[$3]] به عنوان حل شده {{GENDER:$2|علامت زد}}",
+ "logentry-lock-flow-restore-topic": "$1 مبحث «[[$3|$5]]» در [[$6]] را {{GENDER:$2|بازگشایی کرد}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 یک مبحث را در [[$3]] {{GENDER:$2|بازگشایی کرد}}",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] در [[$3]] از ال‌کیوتی به فول درون‌ریزی شد",
+ "flow-user-moderated": "کاربر تعدیل‌شده",
"flow-board-header-browse-topics-link": "مرور مبحث‌ها",
- "flow-board-header": "دربارهٔ این صفحه",
+ "flow-board-header": "دربارهٔ این تالار",
+ "flow-board-description-can-not-edit": "غیر قابل ویرایش",
"flow-board-collapse-description": "مخفی کردن توضیحات",
"flow-board-expand-description": "نمایش توضیحات",
- "flow-topic-collapse-siderail": "خواندن با حداکثر عرض",
- "flow-topic-expand-siderail": "خواند در عرض مشخص شده",
+ "flow-topic-collapse-siderail": "خواندن با پهنای کامل صفحه",
+ "flow-topic-expand-siderail": "خواندن با پهنای مشخص شده",
"flow-edit-header-link": "ویرایش توضیحات",
"flow-post-moderated-toggle-hide-show": "نمایش نظر {{GENDER:$1|پنهان شده}} توسط $2",
"flow-post-moderated-toggle-delete-show": "نمایش نظر {{GENDER:$1|حذف شده}} توسط $2",
"flow-post-moderated-toggle-suppress-show": "نمایش نظر {{GENDER:$1|سرکوب شده}} توسط $2",
"flow-post-moderated-toggle-hide-hide": "پنهان کردن نظر {{GENDER:$1|پنهان‌شده}} توسط $2",
"flow-post-moderated-toggle-delete-hide": "پنهان کردن نظر {{GENDER:$1|حذف‌شده}} توسط $2",
- "flow-post-moderated-toggle-suppress-hide": "پنهان کردن نظر {{GENDER:$1|سرکوب شده}} توسط $2",
+ "flow-post-moderated-toggle-suppress-hide": "پنهان کردن نظر {{GENDER:$1|فرونشانی شده}} توسط $2",
"flow-topic-moderated-reason-prefix": "دلیل:",
- "flow-hide-post-content": "این نظر توسط $1 ([$2 تاریخچه])، {{GENDER:$1|hidden}} بود",
- "flow-hide-title-content": "این مبحث توسط $1، {{GENDER:$1|مخفی}} بود",
+ "flow-hide-post-content": "این نظر توسط $1 {{GENDER:$1|پنهان شد}} ([$2 تاریخچه])",
+ "flow-hide-title-content": "این مبحث توسط $1 {{GENDER:$1|پنهان شد}}",
"flow-hide-header-content": "{{GENDER:$1|مخفی شده}} توسط $2",
- "flow-delete-post-content": "این نظر توسط $1 ([$2 تاریخچه])، {{GENDER:$1|deleted}} بود",
- "flow-delete-title-content": "این محبث توسط $1، {{GENDER:$1|حذف}} شده",
+ "flow-delete-post-content": "این نظر توسط $1 {{GENDER:$1|حذف شده‌است}} ([$2 تاریخچه])",
+ "flow-delete-title-content": "این محبث توسط $1 {{GENDER:$1|حذف}} شده‌است",
"flow-delete-header-content": "{{GENDER:$1|حذف شده}} توسط $2",
- "flow-suppress-post-content": "این نظر توسط $1 ([$2 تاریخچه])، {{GENDER:$1|suppressed}} بود",
- "flow-suppress-title-content": "این مبحث توسط $1، {{GENDER:$1|حذف کلی}} شده",
- "flow-suppress-header-content": "{{GENDER:$1|حذف کلی شده}} توسط $2",
- "flow-suppress-usertext": "<em>نام کاربری حذف کلی شد</em>",
+ "flow-suppress-post-content": "این نظر توسط $1 {{GENDER:$1|فرونشانی شده‌است}} ([$2 تاریخچه])",
+ "flow-suppress-title-content": "این مبحث توسط $1 {{GENDER:$1|فرونشانی شده‌است}}",
+ "flow-suppress-header-content": "{{GENDER:$1|فرونشانی شده}} توسط $2",
+ "flow-suppress-usertext": "<em>نام کاربری سرکوب شد</em>",
"flow-post-actions": "عمل‌ها",
"flow-topic-actions": "عمل‌ها",
"flow-cancel": "انصراف",
- "flow-skip-summary": "انصراف از خلاصه ویرایش",
- "flow-edit-summary-placeholder": "توضیح مختصری از خروجی این بحث بدهید",
- "flow-summary-authored": "خلاصه به وسیله $1",
- "flow-summary-edited": "خلاصهٔ آخرین {{GENDER:$1|ویرایش}} توسط $1",
+ "flow-skip-summary": "انصراف از جمع‌بندی",
+ "flow-edit-summary-placeholder": "توضیح مختصری از نتیجهٔ این بحث بدهید",
+ "flow-summary-authored": "جمع‌بندی توسط $1",
+ "flow-summary-edited": "جمع‌بندی آخرین بار توسط $1 {{GENDER:$1|ویرایش شده‌است}}",
"flow-show-change": "نمایش تغییرات",
- "flow-last-modified-by": "آخرین {{GENDER:$1|modified}} توسط $1",
- "flow-stub-post-content": "''به دلیل یک خطای فنی، این پست نتوانست بازیابی شود.''",
+ "flow-last-modified-by": "آخرین {{GENDER:$1|تغییر}} توسط $1",
+ "flow-stub-post-content": "<em>به دلیل یک خطای فنی، این ارسال قابل بازیابی نیست.<em>",
"flow-newtopic-title-placeholder": "مبحث جدید",
"flow-newtopic-content-placeholder": "یک پیام تازه به «$1» ارسال کنید",
"flow-newtopic-header": "اضافه کردن یک مبحث جدید",
"flow-newtopic-save": "افزودن مبحث",
- "flow-newtopic-save-anonymously": "افزودن یک مبحث بی‌نام",
+ "flow-newtopic-save-anonymously": "افزودن یک مبحث به صورت گمنام",
"flow-newtopic-start-placeholder": "آغاز مبحث جدید",
- "flow-newtopic-first-heading": "شروع کردن یک مبحث چدیدی در $1",
- "flow-summarize-topic-placeholder": "لطفاً این بحث را به طور خلاصه بیان کنید",
+ "flow-newtopic-first-heading": "شروع کردن یک مبحث جدید در $1",
+ "flow-summarize-topic-placeholder": "لطفاً این بحث را جمع‌بندی کنید",
"flow-reply-topic-placeholder": "{{GENDER:$1|نظر}} در «$2»",
"flow-reply-topic-title-placeholder": "پاسخ به «$1»",
"flow-reply-link": "{{GENDER:$1|پاسخ}}",
- "flow-reply-link-anonymously": "پاسخ بی‌نام",
+ "flow-reply-link-anonymously": "پاسخ به صورت گمنام",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|تشکر}}}}",
- "flow-thank-link-title": "از ارسال کننده به صورت علنی {{GENDER:$1|{{GENDER:$2|تشکر کرد}}}}",
- "flow-history-action-suppress-post": "از بین‌بردن",
+ "flow-thank-link-title": "از ارسال کننده به صورت علنی {{GENDER:$1|{{GENDER:$2|تشکر کنید}}}}",
+ "flow-history-action-suppress-post": "فرونشانی",
"flow-history-action-delete-post": "حذف",
- "flow-history-action-hide-post": "مخفی‌سازی",
- "flow-history-action-unsuppress-post": "خنثی‌سازیِ از بین‌بردن",
+ "flow-history-action-hide-post": "پنهان کردن",
+ "flow-history-action-unsuppress-post": "بازنشانی",
"flow-history-action-undelete-post": "احیا",
"flow-history-action-unhide-post": "نمایش",
- "flow-history-action-restore-post": "بازگردانی",
+ "flow-history-action-restore-post": "احیا",
"flow-history-action-lock-topic": "برطرف کردن",
- "flow-history-action-unlock-topic": "باز کردن",
- "flow-post-edited": "پست {{GENDER:$1|ویرایش شد}} توسط $1 $2",
+ "flow-history-action-unlock-topic": "بازگشودن",
+ "flow-post-edited": "ارسال توسط $1 $2 {{GENDER:$1|ویرایش شد}}",
"flow-post-action-view": "پیوند پایدار",
"flow-post-action-post-history": "تاریخچه",
- "flow-post-action-suppress-post": "سرکوب",
+ "flow-post-action-suppress-post": "فرونشانی",
"flow-post-action-delete-post": "حذف",
"flow-post-action-hide-post": "نهفتن",
"flow-post-action-edit-post": "ویرایش",
- "flow-post-action-edit-post-submit": "ذخیره‌کردن تغییرات",
- "flow-post-action-edit-post-submit-anonymously": "ذخیره تغییرات به‌صورت ناشناس",
- "flow-post-action-unsuppress-post": "از مخفی‌بودن در آوردن",
- "flow-post-action-undelete-post": "احیاء",
- "flow-post-action-unhide-post": "نمایش",
- "flow-post-action-restore-post": "بازیابی",
+ "flow-post-action-edit-post-submit": "ذخیره کردن تغییرات",
+ "flow-post-action-edit-post-submit-anonymously": "ذخیره تغییرات به‌صورت گمنام",
+ "flow-post-action-unsuppress-post": "بازنشانی",
+ "flow-post-action-undelete-post": "احیا",
+ "flow-post-action-unhide-post": "آشکار کردن",
+ "flow-post-action-restore-post": "احیا",
"flow-post-action-undo-moderation": "خنثی‌سازی",
"flow-topic-action-view": "پیوند پایدار",
"flow-topic-action-watchlist": "فهرست پی‌گیری‌ها",
@@ -108,45 +136,46 @@
"flow-topic-action-history": "تاریخچه",
"flow-topic-action-hide-topic": "پنهان کردن مبحث",
"flow-topic-action-delete-topic": "حذف مبحث",
- "flow-topic-action-lock-topic": "برچسپ به عنوان برطرف شده",
- "flow-topic-action-unlock-topic": "باز کردن دوبارهٔ مبحث",
- "flow-topic-action-summarize-topic": "خلاصه‌سازی",
- "flow-topic-action-resummarize-topic": "ویرایش خلاصه مبحث",
- "flow-topic-action-update-topic-summary": "به‌روزرسانی خلاصه",
- "flow-topic-action-suppress-topic": "حذف کلی مبحث",
- "flow-topic-action-unhide-topic": "آشکارنمودن مبحث",
- "flow-topic-action-undelete-topic": "احیاء مبحث",
- "flow-topic-action-unsuppress-topic": "از مخفی‌بودن در آوردن مبحث",
- "flow-topic-action-restore-topic": "بازیابی مبحث",
- "flow-topic-action-undo-moderation": "واگردانی",
- "flow-topic-notification-subscribe-title": "این مبحث به فهرست {{GENDER:$1|پیگیری‌تان}} افزوده شده است.",
- "flow-topic-notification-subscribe-description": "{{GENDER:$1|شما}} برای همه فعالیت‌ها در این مبحث اطلاعیه دریافت خواهید کرد.",
- "flow-board-notification-subscribe-title": "{{GENDER:$1|شما}} به این بحث اشتراک دارید!",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|شما}} به طور خودکار هنگامی که موضوع جدید در برد ایجاد شود اعلام دریافت خواهید کرد.",
+ "flow-topic-action-lock-topic": "علامت زدن به عنوان برطرف شده",
+ "flow-topic-action-unlock-topic": "بازگشایی مبحث",
+ "flow-topic-action-summarize-topic": "جمع‌بندی",
+ "flow-topic-action-resummarize-topic": "ویرایش جمع‌بندی مبحث",
+ "flow-topic-action-update-topic-summary": "به‌روزرسانی جمع‌بندی",
+ "flow-topic-action-suppress-topic": "فرونشانی مبحث",
+ "flow-topic-action-unhide-topic": "آشکار کردن مبحث",
+ "flow-topic-action-undelete-topic": "احیای مبحث",
+ "flow-topic-action-unsuppress-topic": "بازنشانی مبحث",
+ "flow-topic-action-restore-topic": "احیای مبحث",
+ "flow-topic-action-undo-moderation": "خنثی‌سازی",
+ "flow-topic-notification-subscribe-title": "این مبحث به فهرست {{GENDER:$1|پیگیری‌تان}} افزوده شد.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|شما}} برای همه فعالیت‌ها در این مبحث آگاه‌سازی دریافت خواهید کرد.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|شما}} مشترک تالار گفتگو شدید!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|شما}} به طور خودکار هنگامی که مبحثی جدید در این تالار ایجاد شود آگاه‌سازی دریافت خواهید کرد.",
"flow-topic-action-watchlist-add": "اشتراک در این مبحث",
"flow-topic-action-watchlist-remove": "لغو اشتراک",
- "flow-error-allowcreation-no-usedb": "allowCreation نیاز دارد که <var>$wgContentHandlerUseDB</var> <code>true</code> باشد.",
- "flow-error-allowcreation-already-exists": "صفحه در حال حاضر وجود دارد، ولی نیاز بود که نباشد",
+ "flow-error-allowcreation-no-usedb": "فعال کردن فلو در یک صفحهٔ خاص نیاز دارد که <var>$wgContentHandlerUseDB</var> برابر <code>true</code> باشد.",
+ "flow-error-allowcreation-already-exists": "صفحه در حال حاضر در مقصد وجود دارد، لذا یک صفحهٔ فلو را نمی‌توان به آنجا منتقل کرد.",
"flow-error-allowcreation-flow-create-board": "کاربر دسترسی «{{int:right-flow-create-board}}» ندارد",
+ "flow-error-can-not-edit-logged-out": "امکان مشارکت برای شما وجود ندارد. باید به سامانه وارد شوید.",
+ "flow-error-can-not-edit-logged-in": "امکان مشارکت برای شما وجود ندارد چون شما دسترسی لازم را ندارید.",
"flow-error-http": "یک خطا هنگام تماس با سرور رخ داد.",
- "flow-error-other": "یک خطای غیرمنتظره رخ داد.",
- "flow-error-external": "خطایی رخ داده. <br /> پیغام خطای دریافت شده: $1 بود",
+ "flow-error-external": "خطایی رخ داد. پیغام خطای دریافت شده این بود: $1",
"flow-error-topic-is-locked": "این مبحث برطرف شده است بنابراین فعالیت بیشتر در آن ممکن نیست.",
- "flow-error-lock-moderated-post": "شما نمی‌توانید یک ارسال را به‌عنوان برطرف شده پرچسپ زنید.",
- "flow-error-external-multi": "خطاهایی رخ داده‌اند. <br />$1",
- "flow-error-missing-content": "پست هیچ محتوایی ندارد. محتوا نیازمند به ذخیرهٔ یک پست است.",
+ "flow-error-lock-moderated-post": "شما نمی‌توانید یک ارسال تعدیل شده را به‌عنوان برطرف شده علامت بزنید.",
+ "flow-error-missing-content": "ارسال هیچ محتوایی ندارد. محتوا برای ذخیره کردن یک ارسال ضروری است.",
"flow-error-missing-summary": "باید خلاصه‌ای وارد کنید.",
- "flow-error-missing-title": "مبحث هیچ عنوانی ندارد. عنوان برای ذخیرهٔ یک محبث، لازم است.",
- "flow-error-parsoid-failure": "به علت یک پارسوئید ناموفق، قادر به تجزیهٔ محتوا نیست.",
- "flow-error-missing-replyto": "هیچ \"پاسخی به\" پارامتر عرضه نشد. این پارامتر نیازمند عمل \"پاسخ\" است.",
- "flow-error-invalid-replyto": "«پاسخ» پارامتر نامعتبر بود. پست تعیین‌شده نتوانست پیدا شود.",
- "flow-error-delete-failure": "حذف کردن این مورد ناموفق بود.",
- "flow-error-hide-failure": "پنهان کردن این مورد ناموفق بود.",
- "flow-error-missing-postId": "هیچ «شناسهٔ پستی» پارامتری عرضه نشد. این پارامتر نیازمند به کنترل یک پست است.",
- "flow-error-invalid-postId": "\"شناسهٔ پستی\" پارامتر نامعتبر بود. پست تعیین شدهٔ ($1) نتوانست پیدا شود.",
- "flow-error-restore-failure": "بازگردانی این مورد ناموفق بود.",
- "flow-error-invalid-moderation-state": "یک ارزش نامعتبر برای وضعیت کنترل، ارائه شد.",
- "flow-error-invalid-moderation-reason": "لطفاً یک دلیل برای کنترل ارائه دهید.",
+ "flow-error-missing-title": "مبحث هیچ عنوانی ندارد. عنوان برای ذخیرهٔ یک مبحث ضروری است.",
+ "flow-error-parsoid-failure": "ناتوان از تحلیل محتوا: خطا در اتصال به کارگزار برای تبدیل بین ویکی‌کد و اچ‌تی‌ام‌ال. لطفاً ارتباط اینترنت خود را بررسی کنید یا اگر مشکل ادامه داشت بعداً تلاش کنید. اگر کماکان این خطا را می‌بینید گزارشش کنید",
+ "flow-error-protected-autoconfirmed-logged-in": "این تالار محافظت شده‌است. تنها کاربران تأییدشده می‌توانند مشارکت کنند. دلیل: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "این تالار محافظت شده‌است. تنها کاربرانی تأییدشده‌ای که به سامانه وارد شده‌اند می‌توانند مشارکت کنند. دلیل: $1",
+ "flow-error-protected-sysop-logged-in": "این تالار محافظت شده‌است. تنها کاربران دارای اختیارات مدیریت می‌توانند مشارکت کنند. دلیل: $1",
+ "flow-error-protected-sysop-logged-out": "این تالار محافظت شده‌است. تنها کاربران دارای اختیارات مدیریت که به سامانه وارد شده‌اند می‌توانند مشارکت کنند. دلیل: $1",
+ "flow-error-protected-unknown-reason": "نامشخص",
+ "flow-error-missing-replyto": "هیچ مقداری برای پارامتر «replyTo» عرضه نشد. این پارامتر برای عمل «reply» ضروری است.",
+ "flow-error-missing-postId": "هیچ مقداری برای پارامتر «postId» عرضه نشد. این پارامتر برای دستکاری یک ارسال ضروری است.",
+ "flow-error-invalid-postId": "پارامتر «postId» نامعتبر بود. ارسال تعیین شدهٔ ($1) پیدا نشد.",
+ "flow-error-invalid-moderation-state": "یک مقدار نامعتبر برای یک پارامتر («moderationState») به رابط برنامه‌نویسی کاربردی فلو ارسال شد.",
+ "flow-error-invalid-moderation-reason": "لطفاً برای تعدیل یک دلیل ارائه دهید.",
"flow-error-not-allowed": "مجوزهای ناکافی برای اجرای این عمل.",
"flow-error-not-allowed-hide": "این مبحث پنهان شده است.",
"flow-error-not-allowed-reply-to-hide-topic": "شما نمی‌توانید پاسخ دهید چرا که این مبحث پنهان شده است.",
@@ -154,258 +183,357 @@
"flow-error-not-allowed-reply-to-delete-topic": "شما نمی‌توانید پاسخ دهید چرا که این مبحث حذف شده است.",
"flow-error-not-allowed-suppress": "این مبحث حذف شده‌است.",
"flow-error-not-allowed-reply-to-suppress-topic": "شما نمی‌توانید پاسخ دهید چرا که این مبحث حذف شده است.",
- "flow-error-not-allowed-hide-extract": "این مبحث پنهان شده‌است. سیاههٔ آن در زیر برای ارجاع ارائه شده است.",
- "flow-error-not-allowed-delete-extract": "این مبحث حذف شده‌است. سیاههٔ حذف مبحث در زیر برای ارجاع ارائه شده‌است.",
- "flow-error-not-allowed-reply-to-delete-topic-extract": "شما نمی‌توانید پاسخ دهید چرا که این مبحث حذف شده‌است. سیاههٔ حذف برای مبحث در زیر برای ارجاع ارائه شده است.",
- "flow-error-not-allowed-suppress-extract": "این مبحث حذف شده‌است. سیاههٔ حذف مبحث در زیر برای ارجاع ارائه شده‌است.",
+ "flow-error-not-allowed-hide-extract": "این مبحث پنهان شده‌است. سیاههٔ پنهانسازی این مبحث در زیر برای ارجاع ارائه شده است.",
+ "flow-error-not-allowed-delete-extract": "این مبحث حذف شده‌است. سیاههٔ حذف این مبحث در زیر برای ارجاع ارائه شده‌است.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "شما نمی‌توانید پاسخ دهید چرا که این مبحث حذف شده‌است. سیاههٔ حذف این مبحث در زیر برای ارجاع ارائه شده است.",
+ "flow-error-not-allowed-suppress-extract": "این مبحث حذف شده‌است. سیاههٔ حذف این مبحث در زیر برای ارجاع ارائه شده‌است.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "شما قادر به پاسخ نیستید چراکه این بحث فرونشانی شده‌است. سیاههٔ فرونشانی این مبحث در زیر برای ارجاع ارائه شده است.",
"flow-error-title-too-long": "عناوین مبحث، محدود به $1 {{PLURAL:$1|بایت}} هستند.",
"flow-error-no-existing-workflow": "این جریان کار هنوز وجود ندارد.",
- "flow-error-not-a-post": "عنوان مبحث نمی‌تواند به عنوان یک پست ذخیره شود.",
+ "flow-error-not-a-post": "عنوان مبحث نمی‌تواند به عنوان یک ارسال ذخیره شود.",
"flow-error-missing-header-content": "باید توضیحاتی وارد کنید.",
"flow-error-missing-prev-revision-identifier": "شناساگر نسخهٔ قبلی مفقود شده است.",
- "flow-error-prev-revision-mismatch": "چند ثانیه پیش کاربر دیگری این پست را ویرایش کرده‌است. آیا مطمئن {{GENDER:$3|هستید}} که می‌خواهید تغییر اخیر را بازنویسی کنید؟",
- "flow-error-prev-revision-does-not-exist": "نسخهٔ قبلی یافت نمی‌شود.",
- "flow-error-default": "یک خطا رخ داده است.",
- "flow-error-invalid-input": "ارزش نامعتبر برای بارگذاری جریان محتوا، ارائه شده.",
+ "flow-error-prev-revision-mismatch": "چند ثانیه پیش کاربر دیگری این پست را ویرایش کرده‌است. آیا مطمئن {{GENDER:$3|هستید}} که می‌خواهید تغییر اخیر را رونویسی کنید؟",
+ "flow-error-prev-revision-does-not-exist": "نسخهٔ قبلی یافت نشد.",
+ "flow-error-core-topic-deletion": "برای حذف یک مبحث، از منوی ... در تالار فلو یا [$1 صفحه مبحث] استفاده کنید. از رفتن به action=delete به طور مستقیم برای حذف مبحث خودداری کنید.",
+ "flow-error-default": "یک خطا رخ داده‌است.",
+ "flow-error-invalid-input": "مقدار وارد شده برای بارگذاری محتوای فلو نامعتبر بود.",
"flow-error-invalid-title": "عنوان صفحهٔ نامعتبر ارائه شده.",
+ "flow-error-invalid-parameter": "پارامتر ناموجود یا نامعتبر در فراخوانی متد",
"flow-error-fail-load-history": "عدم موفقیت بارگذاری محتوای سابقه.",
- "flow-error-missing-revision": "بررسی برای بارگذاری محتوای جریان، نتوانست پیدا شود.",
- "flow-error-fail-commit": "عدم موفقیت ذخیرهٔ محتوای جریان.",
+ "flow-error-missing-revision": "ناتوان از پیدا کردن نسخه‌ای برای بارگیری محتوای فلو.",
+ "flow-error-fail-commit": "ذخیره کردن محتوای فلو شکست خورد.",
"flow-error-insufficient-permission": "مجوز ناکافی برای دسترسی به محتوا.",
- "flow-error-revision-comparison": "عملکرد متفاوت برای دو بررسی متعلق به پست مشابه، می‌تواند به تنهایی انجام شده باشد.",
+ "flow-error-revision-comparison": "عملکرد تفاوت را تنها می‌توان روی دو نسخه که به یک ارسال تعلق دارند اجرا کرد.",
"flow-error-missing-topic-title": "عنوان مبحث برای جریان کار کنونی، یافت نشد.",
- "flow-error-missing-metadata": "متادیتای لازم برای این نسخه پیدا نشد.",
+ "flow-error-missing-metadata": "فرادادهٔ لازم برای این نسخه پیدا نشد.",
+ "flow-error-different-page": "جریان کار فلو با این صفحه مرتبط نیست.",
"flow-error-fail-load-data": "عدم موفقیت در بارگذاری اطلاعات درخواست شده.",
- "flow-error-invalid-workflow": "جریان کار درخواست شده نتوانست پیدا شود.",
- "flow-error-process-data": "خطایی هنگام پردازش اطلاعات در درخواست شما رخ داده است.",
- "flow-error-process-wikitext": "خطایی هنگام پردازش تبدیل اچ‌تی‌‌ام‌ال/متن‌ویکی رخ داده است.",
- "flow-error-no-index": "عدم موفقیت در پیدا کردن یک شاخص برای انجام جستجوی اطلاعات.",
+ "flow-error-invalid-workflow": "جریان کار درخواست شده پیدا نشد.",
+ "flow-error-process-data": "خطایی هنگام پردازش اطلاعات در درخواست شما رخ داد.",
+ "flow-error-process-wikitext": "خطایی هنگام پردازش تبدیل اچ‌تی‌‌ام‌ال/ویکی‌متن رخ داد.",
+ "flow-error-no-index": "پیدا کردن یک اندیس برای انجام جستجوی اطلاعات شکست خورد.",
"flow-error-no-render": "عمل مشخص‌شده شناخته نشد.",
"flow-error-no-commit": "عمل مشخص‌شده ذخیره نمی‌شود.",
- "flow-error-move-topic": "انتقال یک صفحه بحث هنوز پشتیبانی نمی‌شود.",
+ "flow-error-content-too-long": "محتوا بیش از اندازه بزرگ است. محتوا بعد از باز شدن به $1 {{PLURAL:$1|بایت|بایت}} محدود شده‌است.",
+ "flow-error-move-topic": "انتقال یک صفحهٔ مبحث در حال حاضر پشتیبانی نمی‌شود.",
"flow-error-invalid-topic-uuid-title": "عنوان بد",
+ "flow-error-invalid-topic-uuid": "عنوان صفحهٔ درخواست شده غیرمجاز است. صفحه‌ها در فضای نام مبحث به طور خودکار توسط فلو ساخته می‌شوند.",
"flow-error-unknown-workflow-id-title": "مبحث نامشخص",
- "flow-error-unknown-workflow-id": "مبحث درخواستی وجود ندارد.",
- "flow-error-search": "ما نمی‌توانیم جستجویتان به دلیل یک مشکل موقت کامل کنیم. لطفاً بعداً دوباره تلاش کنید.",
- "flow-edit-header-placeholder": "این بحث را توصیف کنید",
- "flow-edit-header-submit": "ثبت توضیحات",
- "flow-edit-header-submit-anonymously": "ذخیره توضیحات به‌صورت ناشناس",
+ "flow-error-unknown-workflow-id": "مبحث درخواست‌شده وجود ندارد.",
+ "flow-error-search": "به دلیل یک مشکل موقت نمی‌توانیم جستجوی‌تان را کامل کنیم. لطفاً بعداً دوباره تلاش کنید.",
+ "flow-error-invalid-undelete": "این مقاله قابل احیا نبود زیرا همینک یک تالار گفتگو به جای آن قرار گرفته‌است.",
+ "flow-edit-header-placeholder": "این تالار گفتگو را توصیف کنید",
+ "flow-edit-header-submit": "ذخیره کردن توضیحات",
+ "flow-edit-header-submit-anonymously": "ذخیره کردن توضیحات به‌صورت گمنام",
"flow-edit-title-submit": "تغییر عنوان",
- "flow-edit-title-submit-anonymously": "تغییر عنوان به‌صورت ناشناس",
+ "flow-edit-title-submit-anonymously": "تغییر عنوان به‌صورت گمنام",
"flow-edit-post-submit": "ثبت تغییرات",
- "flow-edit-post-submit-anonymously": "ثبت تغییرات به‌صورت ناشناس",
- "flow-rev-message-edit-post": "$1 {{GENDER:$2|ویرایش شد}} یک [$3 نظر] در $4.",
- "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|نطر داده}}] در $4 (<em>$5</em>).",
- "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|نظر|نظرها}}</strong> {{PLURAL:$1|بود|بودند}} اضافه شد.",
- "flow-rev-message-new-post": "$1 {{GENDER:$2|ایجاد شد}} موضوع [$3 $4].",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|تغییر یافت}} عنوان موضوع از $5 به [$3 $4].",
- "flow-rev-message-create-header": "$1 {{GENDER:$2|ایجاد شده}} سرفصل صفحه.",
- "flow-rev-message-edit-header": "$1 {{GENDER:$2|ویرایش شده}} سرفصل صفحه.",
- "flow-rev-message-hid-post": "$1 {{GENDER:$2|پنهان}} یک [$4 نظر] در «$6» (<em>$5</em>).",
- "flow-rev-message-deleted-post": "$1 {{GENDER:$2|حذف شده}} یک [$4 نظر] در «$6» (<em>$5</em>)",
- "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|سرکوب شده}} یک [$4 نظر] در «$6» (<em>$5</em>)",
- "flow-rev-message-restored-post": "$1 {{GENDER:$2|بازگردانده شده}} یک [$4 نظر] در «$6» (<em>$5</em>)",
- "flow-rev-message-hid-topic": "$1 {{GENDER:$2|پنهان شد}} [$4 موضوع] «$6» (<em>$5</em>)",
- "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|حذف شده}} [$4 موضوع] «$6» (<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|سرکوب شده}} [$4 موضوع] $6 (<em>$5</em>).",
- "flow-rev-message-lock-topic-reason": "علامت‌گذاری به عنوان حل و فصل",
- "flow-rev-message-restore-topic-reason": "باز کرد",
- "flow-rev-message-restored-topic": "$1 {{GENDER:$2|بازگردانده شده}} [$4 موضوع] «$6» (<em>$5</em>)",
+ "flow-edit-post-submit-anonymously": "ثبت تغییرات به‌صورت گمنام",
+ "flow-rev-message-edit-post": "$1 یک [$3 نظر] را در $4 {{GENDER:$2|ویرایش کرد}}",
+ "flow-rev-message-edit-post-recentchanges-summary": "یک نظر را {{GENDER:$2|ویرایش کرد}}",
+ "flow-rev-message-reply": "$1 در «$4» [$3 {{GENDER:$2|نظری داد}}] (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|نظر}}</strong> اضافه {{PLURAL:$1|شد|شدند}}",
+ "flow-rev-message-new-post": "$1 مبحث «[$3 $4]» را {{GENDER:$2|ایجاد کرد}}",
+ "flow-rev-message-new-post-recentchanges-summary": "مبحث جدید {{GENDER:$2|ایجاد کرد}}",
+ "flow-rev-message-edit-title": "$1 عنوان مبحث را از «$5» به «[$3 $4]» {{GENDER:$2|تغییر داد}}",
+ "flow-rev-message-create-header": "$1 توضیحات را {{GENDER:$2|ایجاد کرد}}",
+ "flow-rev-message-edit-header": "$1 توضیحات را {{GENDER:$2|ویرایش کرد}}",
+ "flow-rev-message-create-topic-summary": "$1 یک جمع‌بندی برای مبحث $3 {{GENDER:$2|ایجاد کرد}}",
+ "flow-rev-message-edit-topic-summary": "$1 جمع‌بندی مبحث $3 را {{GENDER:$2|ویرایش کرد}}",
+ "flow-rev-message-hid-post": "$1 یک [$4 نظر] را در «$6» {{GENDER:$2|پنهان کرد}} (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 یک [$4 نظر] را در «$6» {{GENDER:$2|حذف کرد}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 یک [$4 نظر] را در «$6» {{GENDER:$2|فرونشاند}} (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 یک [$4 نظر] را در «$6 {{GENDER:$2|احیا کرد}} (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 [$4 موضوع] «$6» را {{GENDER:$2|پنهان کرد}} (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 [$4 موضوع] «$6» را {{GENDER:$2|حذف کرد}}(<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 [$4 موضوع] «$6» را {{GENDER:$2|پنهان کرد}} (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 [$4 مبحث] «$6» را به عنوان برطرف‌شده {{GENDER:$2|علامت زد}} (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "علامت‌گذاری به عنوان برطرف‌شده",
+ "flow-rev-message-restore-topic-reason": "بازگشایی",
+ "flow-rev-message-restored-topic": "$1 [$4 موضوع] «$6» را {{GENDER:$2|احیا کرد}} (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 در $2",
- "flow-board-history": "تاریخ \"$1\"",
+ "flow-board-history": "تاریخچهٔ «$1»",
+ "flow-board-history-empty": "این تالار همینک هیچ تاریخچه‌ای ندارد.",
"flow-topic-history": " تاریخچهٔ مبحث «$1»",
- "flow-post-history": "تاریخچهٔ پست «نظر توسط {{GENDER:$2|$2}}»",
+ "flow-post-history": "تاریخچهٔ ارسال «نظر توسط {{GENDER:$2|$2}}»",
"flow-history-last4": "۴ ساعت گذشته",
"flow-history-day": "امروز",
"flow-history-week": "هفتهٔ گذشته",
- "flow-history-pages-topic": "بر روی [$1 \"$2\" صفحه] به نظر رسیدن",
- "flow-history-pages-post": "بر روی [$1 $2] به نظر رسیدن",
- "flow-topic-comments": "{{PLURAL:$1|نظر $1 |نظرها $1 |0={{GENDER:$2|اولین}} شخصی باشید که نظر می‌گذارد!}}",
- "flow-comment-restored": "بازگرداندن نظر",
- "flow-comment-deleted": "نظر حذف شده",
+ "flow-history-pages-topic": "بر روی [$1 تالار «$2»] نمایش می‌یابد",
+ "flow-history-pages-post": "بر روی [$1 $2] نمایش می‌یابد",
+ "flow-topic-comments": "{{PLURAL:$1|یک نظر|$1 نظر|0=اولین کسی {{GENDER:$2|باشید}} که نظر می‌گذارد!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|نمایش نظر|نمایش نظرها}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|نهفتن نظر|نهفتن نظرها}}",
+ "flow-comment-restored": "احیای نظر",
+ "flow-comment-deleted": "نظر حذف‌شده",
"flow-comment-hidden": "پنهان کردن نظر",
- "flow-comment-moderated": "کنترل نظر",
- "flow-last-modified": "آخرین تغییریافته دربارهٔ $1",
+ "flow-comment-moderated": "تعدیل نظر",
+ "flow-last-modified": "آخرین تغییر حوالی $1",
"flow-workflow": "جریان کار",
- "flow-notification-reply": "$1 {{GENDER:$1|پاسخ داده شد}} به شما <span class=\"plainlinks\">[$5 post]</span> در \"$2\" در \"$4\".",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 و $5 {{PLURAL:$6|نفر دیگر|نفر دیگر}} روی '''$3''' {{GENDER:$1|پاسخ داده‌اند}}.",
- "flow-notification-edit": "$1 {{GENDER:$1|ویرایش شده}} یک <span class=\"plainlinks\">[$5 post]</span> در \"$2\" در [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 و $5 {{PLURAL:$6|دیگر|دیگران}} {{GENDER:$1|ویرایش شده}} یک <span class=\"plainlinks\">[$4 post]</span> در \"$2\" در \"$3\".",
- "flow-notification-newtopic": "$1 یک مبحث تازه در '''$3''' {{GENDER:$1|ایجاد کرد}}.",
- "flow-notification-rename": "$1 {{GENDER:$1|تغیر یافته}} به عنوان <span class=\"plainlinks\">[$2 $3]</span> به \"$4\" در [[$5|$6]].",
- "flow-notification-mention": "$1 به {{GENDER:$5|شما}} در <span class=\"plainlinks\">[$2 ارسال]</span> {{GENDER:$1|خودش|خودش|خودشان}} در «$3» در «$4» {{GENDER:$1|اشاره کرد}}.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 در <strong>$4</strong> {{GENDER:$1|پاسخ داد}}.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 و {{PLURAL:$5|یک نفر دیگر|$5 نفر دیگر|100=بیش از ۹۹ نفر دیگر}} روی <strong>$3</strong> {{GENDER:$1|پاسخ داده‌اند}}.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 <span class=\"plainlinks\">[$5 ارسال]</span> شما را در [[$3|$4]] {{GENDER:$1|ویرایش کرد}}.",
+ "flow-notification-edit-bundle": "$1 و {{PLURAL:$5|یک نفر دیگر|$5 نفر دیگر|100=بیش از ۹۹ نفر دیگر}} یک <span class=\"plainlinks\">[$4 مبحث]</span> در \"$2\" در \"$3\" را {{GENDER:$1|ویرایش کردند}}.",
+ "notification-header-flow-new-topic-v2": "یک مبحث جدید در <strong>$3</strong> ایجاد شده‌است: <bdi>«<strong>$4</strong>»</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|یک مبحث|$1 مبحث|100=بیش از ۹۹ مبحث}} جدید در <strong>$3</strong> ایجاد شده است.",
+ "notification-header-flow-new-topic-user-talk": "یک مبحث جدید در <strong>صفحهٔ بحث شما</strong> ایجاد شد: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|یک مبحث|$1 مبحث|100=بیش از ۹۹ مبحث}} جدید در <strong>صفحه بحث شما</strong>.",
+ "notification-header-flow-post-reply": "$1 در «<strong>$4</strong>» {{GENDER:$2|پاسخ داد}}.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|یک پاسخ| $1پاسخ|100=بیش از ۹۹ پاسخ}} جدید در «<strong>$3</strong>».",
+ "notification-header-flow-post-reply-user-talk": "$1 یک پاسخ در <strong>صفحه بحث شما</strong> در «<strong>$4</strong>» {{GENDER:$2|ارسال کرد}}.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|یک پاسخ|$1 پاسخ|100=بیش از ۹۹ پاسخ}} جدید در <strong>صفحهٔ بحث شما</strong> در «<strong>$3</strong>».",
+ "notification-header-flow-post-edited-v2": "ارسال {{GENDER:$2|شما}} در «<strong>$1</strong>» ویرایش شد.",
+ "notification-bundle-header-flow-post-edited-v2": "ارسال {{GENDER:$2|شما}} در «<strong>$1</strong>» چندین بار ویرایش شد.",
+ "notification-header-flow-post-edited-user-talk": "یک ارسال در «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> ویرایش شد.",
+ "notification-bundle-header-flow-post-edited-user-talk": "یک ارسال در «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> چندین بار ویرایش شد.",
+ "notification-header-flow-topic-renamed-v2": "مبحث «<strong>$1</strong>» به «<strong>$2</strong>» تغییر نام یافت.",
+ "notification-header-flow-topic-renamed-user-talk": "مبحث «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$3|شما}}</strong> به «<strong>$2</strong>» تغییر نام یافت.",
+ "notification-header-flow-summary-edited": "جمع‌بندی «<strong>$1</strong>» به روز شد.",
+ "notification-header-flow-summary-edited-first": "مبحث «<strong>$1</strong>» جمع‌بندی شد.",
+ "notification-bundle-header-flow-summary-edited": "جمع‌بندی «<strong>$1</strong>» چندین بار به روز شد.",
+ "notification-header-flow-summary-edited-user-talk": "جمع‌بندی «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> به روز شد.",
+ "notification-header-flow-summary-edited-first-user-talk": "مبحث «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> جمع‌بندی شد.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "جمع‌بندی «<strong>$1</strong>» در <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> چندین بار به روز شد.",
+ "notification-email-subject-flow-summary-edited": "$1 جمع‌بندی $2 را {{GENDER:$1|به روز کرد}}.",
+ "notification-email-batch-body-flow-summary-edited": "$1 جمع‌بندی $2 را {{GENDER:$1|به روز کرد}}.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 و {{PLURAL:$3|یک نفر دیگر|$3نفر دیگر|100=بیش از ۹۹ نفر دیگر}} جمع‌بندی $2 را {{GENDER:$1|به روز کردند}}",
+ "notification-header-flow-mention-post": "$1 به {{GENDER:$4|شما}} در «<strong>$5</strong>» {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-flow-mention-header": "$1 به {{GENDER:$4|شما}} در توضیحات <strong>$3</strong> {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-flow-mention-post-summary": "$1 به {{GENDER:$4|شما}} در «<strong>$5</strong>» {{GENDER:$2|اشاره کرد}}.",
+ "notification-header-flow-enabled-on-talkpage": "سامانهٔ جدید بحث برای <strong>صفحه بحث {{GENDER:$2|شما}}</strong> فعال شد.",
+ "notification-header-flow-description-edited": "توضیحات «<strong>$1</strong>» ویرایش شد.",
+ "notification-header-flow-description-edited-user-talk": "توضیحات <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> ویرایش شد.",
+ "notification-bundle-header-flow-description-edited": "توضیحات <strong>$1</strong> چندین بار ویرایش شد.",
+ "notification-bundle-header-flow-description-edited-user-talk": "توضیحات <strong>صفحهٔ بحث {{GENDER:$2|شما}}</strong> چندین بار ویرایش شد.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|نمایش}} صفحه",
+ "notification-email-subject-flow-description-edited": "$1 توضیحات $2 را {{GENDER:$1|ویرایش کرد}}.",
+ "notification-email-batch-body-flow-description-edited": "$1 توضیحات $2 را {{GENDER:$1|ویرایش کرد}}.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 و {{PLURAL:$3|یک نفر دیگر|$3نفر دیگر|100=بیش از ۹۹ نفر دیگر}} توضیحات $2 را {{GENDER:$1|ویرایش کردند}}",
+ "notification-header-flow-topic-resolved": "مبحث «<strong>$1</strong>» برطرف شد.",
+ "notification-header-flow-topic-reopened": "مبحث «<strong>$1</strong>» بازگشایی شد.",
+ "notification-header-flow-topic-resolved-user-talk": "مبحث «<strong>$1</strong>» روی <strong>صفحهٔ بحث شما</strong> برطرف شد.",
+ "notification-header-flow-topic-reopened-user-talk": "مبحث «<strong>$1</strong>» روی <strong>صفحهٔ بحث شما</strong> بازگشایی شد.",
+ "notification-email-subject-flow-topic-resolved": "مبحث «<strong>$2</strong>» برطرف شد.",
+ "notification-email-batch-body-flow-topic-resolved": "مبحث «<strong>$2</strong>» برطرف شد.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 یک مبحث جدید در <strong>$3</strong> {{GENDER:$1|ایجاد کرد}}.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|یک مبحث جدید|$1 مبحث جدید|100=بیش از ۹۹ مبحث جدید}} در <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-rename": "$1 عنوان <span class=\"plainlinks\">[$2 $3]</span> در [[$5|$6]] را به «$4» {{GENDER:$1|تغییر داد}}.",
+ "flow-notification-mention": "$1 به {{GENDER:$5|شما}} در <span class=\"plainlinks\">[$2 ارسال]</span> {{GENDER:$1|خودش}} در «$3» در «$4» {{GENDER:$1|اشاره کرد}}.",
"flow-notification-link-text-view-post": "نمایش ارسال",
- "flow-notification-link-text-view-topic": "مشاهدهٔ تاپیک",
+ "flow-notification-link-text-view-topic": "نمایش مبحث",
+ "flow-notification-link-text-view-topics": "نمایش مباحث",
"flow-notification-reply-email-subject": "$2 در $3",
- "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|پاسخ داده شده}} به پست شما در $2 در \"$3\"",
- "flow-notification-reply-email-batch-bundle-body": "$1 و $4 {{PLURAL:$5|دیگر|دیگران}} {{GENDER:$1|پاسخ داده}} به پست شما در \"$2\" در \"$3\"",
- "flow-notification-mention-email-subject": "$1 به {{GENDER:$3|شما}} در «$2» {{GENDER:$1|اشاره کرد}}",
- "flow-notification-mention-email-batch-body": "$1 به {{GENDER:$4|شما}} در ارسال {{GENDER:$1|ش|ش|‌شان}} در «$2» در «$3» {{GENDER:$1|اشاره کرد}}",
- "flow-notification-edit-email-subject": "$1 {{GENDER:$1|ویرایش شد}} یک پست",
- "flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|ویرایش شده}} یک پست در $2 در \"$3\"",
- "flow-notification-edit-email-batch-bundle-body": "$1 و $4 {{PLURAL:$5|دیگر|دیگران}} {{GENDER:$1|ویرایش شده}} یک پست در $2 در \"$3\"",
+ "flow-notification-reply-email-batch-body": "$1 به $2 در \"$3\" {{GENDER:$1|پاسخ داد}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 و {{PLURAL:$4|یک نفر|$4 نفر|100=بیش از ۹۹ نفر}} دیگر به «$2» در $3 {{GENDER:$1|پاسخ دادند}}",
+ "flow-notification-mention-email-subject": "$1 به {{GENDER:$3|شما}} در $2 {{GENDER:$1|اشاره کرد}}",
+ "flow-notification-mention-email-batch-body": "$1 به {{GENDER:$4|شما}} در {{GENDER:$1|ارسالش}} در «$2» در $3 {{GENDER:$1|اشاره کرد}}",
+ "flow-notification-edit-email-subject": "$1 یک ارسال را {{GENDER:$1|ویرایش کرد}}",
+ "flow-notification-edit-email-batch-body": "$1 یک ارسال در «$2» در $3 را {{GENDER:$1|ویرایش کرد}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 و {{PLURAL:$4|یک نفر دیگر|$4 نفر دیگر|100=بیش از ۹۹ نفر دیگر}} یک ارسال در «$2» در $3 را {{GENDER:$1|ویرایش کردند}}",
"flow-notification-rename-email-subject": "$1 مبحث شما را {{GENDER:$1|تغییر نام داد}}",
- "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|تغییر نام داد}} موضوع شما \"$2\" بر \"$3\" بر \"$4\"",
- "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|ایجاد شده}} یک موضوع تازه در $2",
+ "flow-notification-rename-email-batch-body": "$1 مبحث شما «$2» را به «$3» در $4 {{GENDER:$1|تغییر نام داد}}",
+ "flow-notification-newtopic-email-subject": "$1 یک موضوع تازه در $2 {{GENDER:$1|ایجاد کرد}}",
"flow-notification-newtopic-email-batch-body": "$1 یک مبحث جدید با عنوان «$2» در «$3» {{GENDER:$1|ایجاد کرد}}",
- "echo-category-title-flow-discussion": "جریان",
- "echo-pref-tooltip-flow-discussion": "هنگامی که عملیات مربوط به من رخ می‌دهد، من را در جریان قرار بده.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|یک مبحث جدید|$1 مبحث جدید|100=بیش از ۹۹ مبحث جدید}} در $2",
+ "echo-category-title-flow-discussion": "فلو",
+ "echo-pref-tooltip-flow-discussion": "هنگامی که عملیات مربوط به من در فلو رخ می‌دهد، من را در جریان قرار بده.",
"flow-link-post": "ارسال",
"flow-link-topic": "مبحث",
"flow-link-history": "تاریخچه",
- "flow-link-post-revision": "نسخهٔ پست",
+ "flow-link-post-revision": "نسخهٔ ارسال",
"flow-link-topic-revision": "نسخهٔ مبحث",
"flow-link-header-revision": "نسخهٔ توضیحات",
- "flow-link-summary-revision": "نسخهٔ خلاصه",
- "flow-moderation-title-suppress-post": "سرکوب ارسال؟",
+ "flow-link-summary-revision": "نسخهٔ جمع‌بندی",
+ "flow-moderation-title-suppress-post": "فرونشانی ارسال؟",
"flow-moderation-title-delete-post": "حذف ارسال؟",
- "flow-moderation-title-hide-post": "پنهان‌کردن پست؟",
- "flow-moderation-title-unsuppress-post": "از مخفی‌بودن در آوردن ارسال؟",
- "flow-moderation-title-undelete-post": "احیاء ارسال",
+ "flow-moderation-title-hide-post": "پنهان‌کردن ارسال؟",
+ "flow-moderation-title-unsuppress-post": "بازنشانی ارسال؟",
+ "flow-moderation-title-undelete-post": "احیای ارسال",
"flow-moderation-title-unhide-post": "آشکارنمودن ارسال؟",
- "flow-moderation-placeholder-suppress-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این پست را سرکوب می‌کنید.",
- "flow-moderation-placeholder-delete-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا این پست را حذف می‌کنید.",
- "flow-moderation-placeholder-hide-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این پست را پنهان می‌کنید.",
- "flow-moderation-placeholder-unsuppress-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال از مخفی‌بودن در می‌آورید.",
- "flow-moderation-placeholder-undelete-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را احیاء می‌کنید.",
- "flow-moderation-placeholder-unhide-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را از مخفی‌بودن در می‌آورید.",
- "flow-moderation-confirm-suppress-post": "سرکوب",
+ "flow-moderation-placeholder-suppress-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را فرونشانی می‌کنید.",
+ "flow-moderation-placeholder-delete-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا این ارسال را حذف می‌کنید.",
+ "flow-moderation-placeholder-hide-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را پنهان می‌کنید.",
+ "flow-moderation-placeholder-unsuppress-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را از پنهان‌بودن به در می‌آورید.",
+ "flow-moderation-placeholder-undelete-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را احیا می‌کنید.",
+ "flow-moderation-placeholder-unhide-post": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این ارسال را از پنهان‌بودن به در می‌آورید.",
+ "flow-moderation-confirm-suppress-post": "فرونشانی",
"flow-moderation-confirm-delete-post": "حذف",
"flow-moderation-confirm-hide-post": "نهفتن",
- "flow-moderation-confirm-unsuppress-post": "از مخفی‌بودن در آوردن",
- "flow-moderation-confirm-undelete-post": "احیاء کردن",
+ "flow-moderation-confirm-unsuppress-post": "بازنشانی",
+ "flow-moderation-confirm-undelete-post": "احیا",
"flow-moderation-confirm-unhide-post": "نمایش",
- "flow-moderation-confirm-suppress-topic": "سرکوب",
+ "flow-moderation-confirm-suppress-topic": "فرونشانی",
"flow-moderation-confirm-delete-topic": "حذف",
"flow-moderation-confirm-hide-topic": "نهفتن",
- "flow-moderation-confirm-unsuppress-topic": "از مخفی‌بودن در آوردن",
- "flow-moderation-confirm-undelete-topic": "احیاءکردن",
+ "flow-moderation-confirm-unsuppress-topic": "بازنشانی",
+ "flow-moderation-confirm-undelete-topic": "احیا",
"flow-moderation-confirm-unhide-topic": "نمایش",
- "flow-moderation-confirmation-suppress-post": "پست با موفقیت سرکوب شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این پست.",
- "flow-moderation-confirmation-delete-post": "پست با موفقیت حذف شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این پست.",
- "flow-moderation-confirmation-hide-post": "پست با موفقیت پنهان شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این پست.",
- "flow-moderation-confirmation-unsuppress-post": "شما با موفقیت ارسال بالا را از مخفی‌بودن در آوردید.",
- "flow-moderation-confirmation-undelete-post": "شما با موفقیت ارسال بالا را احیاء کردید.",
- "flow-moderation-confirmation-suppress-topic": "موضوع با موفقیت سرکوب شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این موضوع.",
- "flow-moderation-confirmation-delete-topic": "موضوع با موفقیت حذف شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این موضوع.",
- "flow-moderation-confirmation-hide-topic": "موضوع با موفقیت پنهان شده‌بود.\n{{GENDER:$2|در نظر بگیرید}} واکنش دادن $1 را در این موضوع.",
- "flow-moderation-title-suppress-topic": "مبحث حذف کلی شود؟",
+ "flow-moderation-confirmation-suppress-post": "ارسال با موفقیت فرونشانی شد.\n{{GENDER:$2|در خاطر داشته باشید}} که به $1 راجع به این ارسال بازخورد دهید.",
+ "flow-moderation-confirmation-delete-post": "ارسال با موفقیت حذف شد.\n{{GENDER:$2|در خاطر داشته باشید}} که به $1 راجع به این ارسال بازخورد دهید.",
+ "flow-moderation-confirmation-hide-post": "ارسال با موفقیت پنهان شد.\n{{GENDER:$2|در خاطر داشته باشید}} که به $1 راجع به این ارسال بازخورد دهید.",
+ "flow-moderation-confirmation-unsuppress-post": "شما ارسال بالا را از مخفی‌بودن در آوردید.",
+ "flow-moderation-confirmation-undelete-post": "شما ارسال بالا را احیا کردید.",
+ "flow-moderation-confirmation-unhide-post": "شما ارسال بالا را از مخفی بودن درآوردید.",
+ "flow-moderation-confirmation-suppress-topic": "مبحث فرونشانی شده‌است.",
+ "flow-moderation-confirmation-delete-topic": "بحث حذف شده‌است.",
+ "flow-moderation-confirmation-hide-topic": "بحث پنهان شده‌است.",
+ "flow-moderation-confirmation-unsuppress-topic": "شما این مبحث را بازنشانی کردید.",
+ "flow-moderation-confirmation-undelete-topic": "شما این مبحث را احیا کردید.",
+ "flow-moderation-confirmation-unhide-topic": "شما ارسال بالا را از مخفی بودن در آوردید.",
+ "flow-moderation-title-suppress-topic": "مبحث فرونشانی شود؟",
"flow-moderation-title-delete-topic": "مبحث حذف شود؟",
"flow-moderation-title-hide-topic": "مبحث مخفی شود؟",
- "flow-moderation-title-unsuppress-topic": "مبحث از حذف کلی بازیابی شود؟",
- "flow-moderation-title-undelete-topic": "مبحث احیاء شود؟",
+ "flow-moderation-title-unsuppress-topic": "مبحث بازنشانی شود؟",
+ "flow-moderation-title-undelete-topic": "مبحث احیا شود؟",
"flow-moderation-title-unhide-topic": "مبحث آشکار شود؟",
- "flow-moderation-placeholder-suppress-topic": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این مبحث را حذف کلی می‌کنید.",
+ "flow-moderation-placeholder-suppress-topic": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این مبحث را فرونشانی می‌کنید.",
"flow-moderation-placeholder-delete-topic": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این مبحث را حذف می‌کنید.",
"flow-moderation-placeholder-hide-topic": "لطفاً {{GENDER:$3|توضیح دهید}} که چرا شما این مبحث را پنهان می‌کنید.",
+ "flow-moderation-placeholder-unsuppress-topic": "لطفا {{GENDER:$3|توضیح دهید}} چرا این بحث را از بازنشانی می‌کنید.",
+ "flow-moderation-placeholder-undelete-topic": "لطفا {{GENDER:$3|توضیح دهید}} چرا این بحث را احیا می‌کنید.",
+ "flow-moderation-placeholder-unhide-topic": "لطفا {{GENDER:$3|توضیح دهید}} چرا این بحث را آشکار می‌کنید.",
"flow-topic-permalink-warning": "این مبحث در [$2 $1] شروع شده‌ بود",
- "flow-topic-permalink-warning-user-board": "این مبحث در [$2 تخت {{GENDER:$1|$1}}] شروع شده بود",
- "flow-revision-permalink-warning-post": "این یک پیوند دائم برای یک تک نسخه از این ارسال است.\nاین نسخه از $1 است.\nشما می‌توانید [$5 تفاوت‌ها از نسخهٔ قبلی] را مشاهده کنید، یا نسخه‌های دیگری را در [$4 صفحهٔ تاریخچهٔ پست] مشاهده کنید.",
- "flow-revision-permalink-warning-post-first": "این یک پیوند دائم برای اولین نسخهٔ این پست است.\nشما می‌توانید نسخه‌های بعدی را در [$4 صفحهٔ تاریخچهٔ پست] مشاهده کنید.",
- "flow-revision-permalink-warning-header": "این یک پیوند دائمی برای یک نسخهٔ تک سرفصل است.\nاین نسخه از $1 است. شما می‌توانید [$3 تفاوت‌ها را از نسخهٔ قبلی] مشاهده کنید، یا نسخه‌های دیگر را در [$2 تابلو صفحهٔ تاریخچه] مشاهده کنید.",
- "flow-revision-permalink-warning-header-first": "این یک پیوند دائمی برای یک نسخهٔ تک سرفصل است.\nشما می‌توانید نسخه‌های بعدی را در [$2 تابلو صفحهٔ تاریخچه] مشاهده کنید.",
+ "flow-topic-permalink-warning-user-board": "این مبحث در [$2 تالار {{GENDER:$1|$1}}] شروع شده بود",
+ "flow-revision-permalink-warning-post": "این یک پیوند دائم برای یک نسخهٔ منفرد از این ارسال است.\nاین نسخه مربوط به $1 است.\nشما می‌توانید [$5 تفاوت‌ها از نسخهٔ قبلی] را مشاهده کنید، یا نسخه‌های دیگری را در [$4 صفحهٔ تاریخچهٔ ارسال] مشاهده کنید.",
+ "flow-revision-permalink-warning-post-first": "این یک پیوند دائم برای اولین نسخهٔ این ارسال است.\nشما می‌توانید نسخه‌های بعدی را در [$4 صفحهٔ تاریخچهٔ ارسال] مشاهده کنید.",
+ "flow-revision-permalink-warning-postsummary": "این یک پیوند دائم برای یک نسخهٔ منفرد از این ارسال است.\nاین نسخه مربوط به $1 است.\nشما می‌توانید [$5 تفاوت‌ها از نسخهٔ قبلی] را مشاهده کنید، یا نسخه‌های دیگری را در [$4 صفحهٔ تاریخچهٔ ارسال] مشاهده کنید.",
+ "flow-revision-permalink-warning-postsummary-first": "این یک پیوند دائم برای اولین نسخهٔ این ارسال است.\nشما می‌توانید نسخه‌های بعدی را در [$4 صفحهٔ تاریخچهٔ ارسال] مشاهده کنید.",
+ "flow-revision-permalink-warning-header": "این یک پیوند دائمی برای یک نسخهٔ منفرد از توضیحات است.\nاین نسخه مربوط به $1 است. شما می‌توانید [$3 تفاوت‌ها را از نسخهٔ قبلی] مشاهده کنید، یا نسخه‌های دیگر را در [$2 صفحهٔ تاریخچهٔ تالار] مشاهده کنید.",
+ "flow-revision-permalink-warning-header-first": "این یک پیوند دائمی برای یک نسخهٔ منفرد از توضیحات است.\nشما می‌توانید نسخه‌های بعدی را در [$2 صفحهٔ تاریخچهٔ تالار] مشاهده کنید.",
"flow-compare-revisions-revision-header": "نسخه توسط {{GENDER:$2|$2}} از $1",
- "flow-compare-revisions-header-post": "این صفحه {{GENDER:$3|تغییرات}} را بین دو نسخه از یک پست توسط $3 در موضوع \"[$5 $2]\" بر [$4 $1] نمایش می‌دهد.\nشما می‌توانید نسخه‌های دیگری از این پست را در [$6 صفحهٔ تاریخچه] مشاهده کنید.",
- "flow-compare-revisions-header-header": "این صفحه {{GENDER:$2|تغییرات}} بین دو نسخهٔ سرفصل را در [$3 $1] نشان می‌دهد.\nشما می‌توانید نسخه‌های دیگر سرفصل را در این [$4 صفحهٔ تاریخچه] مشاهده کنید.",
- "action-flow-create-board": "ایجاد صفحه‌های جریان در هر مکانی",
- "right-flow-create-board": "ایجاد صفحه‌های جریان در هر مکانی",
- "right-flow-hide": "مخفی‌کردن مبحث‌ها و پست‌های جریان",
- "right-flow-lock": "علامت‌گذاری مبحث‌های جریان به عنوان حل‌شده",
- "right-flow-delete": "حذف مبحث‌ها و پست‌های جریان",
- "right-flow-edit-post": "ویرایش پست‌های جریات سایر کاربران",
- "right-flow-suppress": "حذف کلی نسخه‌های جریان",
+ "flow-compare-revisions-header-post": "این صفحه {{GENDER:$3|تغییرات}} بین دو نسخه از یک ارسال توسط $3 در موضوع \"[$5 $2]\" بر [$4 $1] را نمایش می‌دهد.\nشما می‌توانید نسخه‌های دیگری از این ارسال را در [$6 صفحهٔ تاریخچه] مشاهده کنید.",
+ "flow-compare-revisions-header-postsummary": "این صفحه تغییرات بین دو نسخه از جمع‌بندی «[$4 $2]» در [$3 $1] را نشان می‌دهد.\nشما می‌توانید نسخه‌های دیگری از این جمع‌بندی را در [$5 صفحهٔ تاریخچه] مشاهده کنید.",
+ "flow-compare-revisions-header-header": "این صفحه {{GENDER:$2|تغییرات}} بین دو نسخهٔ توضیحات در [$3 $1] را نشان می‌دهد.\nشما می‌توانید نسخه‌های دیگر توضیحات را در [$4 صفحهٔ تاریخچه] مشاهده کنید.",
+ "action-flow-create-board": "ایجاد تالارهای فلو در هر جا",
+ "right-flow-create-board": "ایجاد صفحه‌های فلو در هر جا",
+ "right-flow-hide": "مخفی‌کردن مبحث‌ها و ارسال‌های فلو",
+ "right-flow-lock": "علامت‌گذاری مبحث‌های فلو به عنوان برطرف‌شده",
+ "right-flow-delete": "حذف مبحث‌ها و ارسال‌های فلو",
+ "right-flow-edit-post": "ویرایش ارسال‌های سایر کاربران در فلو",
+ "right-flow-suppress": "فرونشانی نسخه‌های فلو",
"flow-terms-of-use-new-topic": "با کلیک کردن \"{{int:flow-newtopic-save}}\"، شما با شرایط استفاده برای این ویکی موافقت می‌کنید.",
"flow-terms-of-use-reply": "با کلیک کردن \"{{int:flow-reply-link}}\"، شما با شرایط استفاده برای این ویکی موافقت می‌کنید.",
- "flow-terms-of-use-edit": "با ذخیرهٔ تغییرات شما، شما با شرایط استفاده برای این ویکی موافقت می‌کنید.",
- "flow-anon-warning": "شما وارد نشده‌ايد.",
+ "flow-terms-of-use-edit": "با ذخیرهٔ تغییرات‌تان، شما با شرایط استفاده برای این ویکی موافقت می‌کنید.",
+ "flow-anon-warning": "شما وارد نشده‌ايد. برای این که این بحث به جای آن که به حساب نشانی آی‌پی شما ثبت شود به حساب خودتان ثبت گردد، می‌توانید [$1 وارد سامانه شوید] یا [$2 یک حساب بسازید].",
+ "flow-cancel-warning": "شما در این فرم متن نوشته‌اید. آیا مطمئن هستید که می‌خواهید آن را دور بریزید؟",
"flow-topic-first-heading": "مبحث $1",
"flow-topic-html-title": "$1 در $2",
"flow-topic-count": "مبحث‌ها ($1)",
"flow-load-more": "بارگیری بیشتر",
+ "flow-no-more-fwd": "مبحث قدیمی‌تر وجود ندارد",
"flow-newest-topics": "مبحث‌های جدیدتر",
- "flow-recent-topics": "مبحث‌هایی که اخیراً فعال بودند",
+ "flow-recent-topics": "مبحث‌های اخیراً فعال",
"flow-sorting-tooltip-newest": "{{GENDER:|شما}} در حال حاضر مبحث جدیدتر را اول می‌خوانید. برای گزینه‌های مرتب‌سازی بیشتر کلیک کنید.",
"flow-sorting-tooltip-recent": "{{GENDER:|شما}} در حال حاضر فعال‌ترین مبحث اخیر را اول می‌خوانید. برای گزینه‌های بیشتر مرتب‌سازی کلیک کنید.",
"flow-toggle-small-topics": "به نمای مبحث‌های کوچک تغییر حالت دهید",
"flow-toggle-topics": "به نمای فقط مبحث‌ها تغییر حالت دهید",
- "flow-toggle-topics-posts": "به نمای مبحث‌ها و پست‌ها تغییر حالت دهید",
+ "flow-toggle-topics-posts": "به نمای مبحث‌ها و ارسال‌ها تغییر حالت دهید",
"flow-terms-of-use-summarize": "شما با کلیک بر روی «{{int:flow-topic-action-update-topic-summary}}»، با شرایط استفاده برای این ویکی، موافقت می‌کنید.",
"flow-terms-of-use-lock-topic": "شما با کلیک بر روی «{{int:flow-topic-action-lock-topic}}»، با شرایط استفاده برای این ویکی، موافقت می‌کنید.",
"flow-terms-of-use-unlock-topic": "شما با کلیک بر روی «{{int:flow-topic-action-unlock-topic}}»، با شرایط استفاده برای این ویکی، موافقت می‌کنید.",
- "flow-whatlinkshere-post": "از یک [$1 پست]",
+ "flow-whatlinkshere-post": "از یک [$1 ارسال]",
"flow-whatlinkshere-header": "از [$1 توضیحات]",
- "flow-whatlinkshere-post-summary": "از [$1 خلاصه]",
- "flow": "جریان",
- "flow-special-desc": "این صفحهٔ ویژه، به جریان کاری یا پست جریانی که UUID (شناسه) آن داده می‌شود، انتقال می‌یابد.",
+ "flow-whatlinkshere-post-summary": "از [$1 جمع‌بندی]",
+ "structureddiscussions": "فلو",
+ "flow-special-desc": "این صفحهٔ ویژه، به جریان کاری فلو یا ارسال فلویی که شناسهٔ UUID آن داده شود تغییر مسیر می‌یابد.",
"flow-special-type": "نوع",
"flow-special-type-post": "ارسال",
"flow-special-type-workflow": "جریان کار",
- "flow-special-uuid": "شناسه UUID",
+ "flow-special-uuid": "شناسهٔ UUID",
"flow-special-invalid-uuid": "نمی‌توان محتوایی با این عنوان و شناسهٔ UUID پیدا کرد.",
- "flow-special-enableflow-legend": "فعال سازی جریان روی این صفحه",
- "flow-special-enableflow-page": "صفحه برای فعال‌سازی جریان روی آن",
- "flow-special-enableflow-header": "توضیحات اولیه از تخت جریان (ویکی‌متن)",
- "flow-special-enableflow-board-already-exists": "در حال حاضر تخت جریاتی در [[$1]] وجود دارد.",
- "flow-special-enableflow-invalid-title": "عنوان نامعتبر داده شده است",
- "flow-special-enableflow-board-creation-not-allowed": "شما مجاز به ایجاد تخت جریان در [[:$1]] نیستید.",
- "flow-special-enableflow-page-is-liquidthreads": "صفحهٔ موضوعات روان (LiquidThreads) در [[:$1]] موجود است.",
- "flow-special-enableflow-confirmation": "شما با موفقیت تخت جریان در [[$1]] ایجاد کردید.",
- "flow-spam-confirmedit-form": "با حل کپچای مقابل خود را انسان نشان دهید: $1",
+ "flow-special-enableflow-legend": "فعال‌سازی فلو روی یک صفحهٔ جدید",
+ "flow-special-enableflow-page": "صفحه برای فعال‌سازی فلو روی آن",
+ "flow-special-enableflow-header": "توضیحات اولیهٔ تالار فلو (ویکی‌متن)",
+ "flow-special-enableflow-board-already-exists": "در حال حاضر یک تالار فلو در [[$1]] وجود دارد.",
+ "flow-special-enableflow-invalid-title": "عنوان صفحهٔ نامعتبر داده شده است",
+ "flow-special-enableflow-board-creation-not-allowed": "شما مجاز به ایجاد تالار فلو در [[:$1]] نیستید.",
+ "flow-special-enableflow-page-is-liquidthreads": "صفحهٔ ال‌کیوتی در [[:$1]] موجود است.",
+ "flow-special-enableflow-confirmation": "شما یک تالار فلو در [[$1]] ایجاد کردید.",
+ "flow-conversion-archive-page-name-format": "%s/بایگانی %d\n%s/بایگانی%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/بایگانی فلو %d\n%s/بایگانی‌فلو%d",
+ "flow-spam-confirmedit-form": "با حل کپچای مقابل تأیید کنید که انسان هستید: $1",
+ "flow-spam-confirmedit-using-failure": "یک خطای فنی با کپچا رخ داد. اگر نمی‌توانید تغییرات خود را ارسال کنید لطفاً متن را کپی کنید، صفحه را از نو بارگیری کنید و دوباره تلاش کنید.",
"flow-embedding-unsupported": "در حال حاضر بحث‌ها نمی‌توانند توکار تعبیه شوند.",
"mw-ui-unsubmitted-confirm": "شما تغییرات ثبت نشده در این صفحه دارید. می‌خواهد بروید و تغییرات را از دست دهید؟",
"flow-post-undo-hide": "خنثی‌سازیِ مخفی‌سازی",
"flow-post-undo-delete": "خنثی‌سازیِ حذف",
- "flow-post-undo-suppress": "خنثی‌سازیِ از بین‌بردن",
+ "flow-post-undo-suppress": "خنثی‌سازیِ فرونشانی",
"flow-topic-undo-hide": "خنثی‌سازیِ مخفی‌سازی",
"flow-topic-undo-delete": "خنثی‌سازیِ حذف",
- "flow-topic-undo-suppress": "خنثی‌سازیِ از بین‌بردن",
- "flow-importer-lqt-converted-template": "صفحهٔ موضوعات روان به جریان تبدیل شد",
- "flow-importer-lqt-converted-archive-template": "بایگانی برای صفحهٔ موضوعات روانی تبدیل شده",
- "flow-importer-wt-converted-template": "ویکی‌متن صفحهٔ بحث تبدیل شده به جریان",
+ "flow-topic-undo-suppress": "خنثی‌سازیِ فرونشانی",
+ "flow-importer-lqt-moved-thread-template": "ریسمان منتقل شدهٔ خرد ال‌کیوتی تبدیل شده به فلو",
+ "flow-importer-lqt-moved-thread-template-content": "این ارسال توسط {{{author}}} در {{{date}}} منتقل شد. شما می‌توانید آن را در [[{{{title}}}]] بیابید.",
+ "flow-importer-lqt-converted-template": "صفحهٔ ال‌کیوتی به فلو تبدیل شد",
+ "flow-importer-lqt-converted-template-content": "تاریخچهٔ قبلی صفحه برای پشتیبانی در {{#time: Y-m-d|{{{date}}}}} در <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> بایگانی شد.",
+ "flow-importer-lqt-converted-archive-template": "بایگانی برای صفحهٔ ال‌کیوتی تبدیل شده",
+ "flow-importer-lqt-converted-archive-template-content": "این صفحه یک بایگانی از صفحه‌ای مبتنی بر ال‌کیوتی است. <strong>محتویات این صفحه را ویرایش نکنید</strong>. لطفاً نظرات اضافی را به [[{{{from}}}|صفحهٔ بحث فعلی]] ببرید.",
+ "flow-importer-wt-converted-template": "ویکی‌متن صفحهٔ بحث تبدیل شده به فلو",
+ "flow-importer-wt-converted-template-content": "بحث‌های قبلی در {{#time: Y-m-d|{{{date}}}}} در <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> بایگانی شد.",
"flow-importer-wt-converted-archive-template": "بایگانی برای ویکی‌متن صفحهٔ بحث تبدیل شده",
- "apihelp-flow+edit-header-param-content": "محتوا برای توضیحات",
- "apihelp-flow+edit-header-param-format": "قالب توضیحات (ویکی‌متن|اچ‌تی‌ام‌ال)",
- "apihelp-flow+edit-post-param-postId": "شناسه پست.",
- "apihelp-flow+edit-post-param-content": "محتوا برای پست.",
- "apihelp-flow+edit-title-param-content": "محتوا برای عنوان",
- "apihelp-flow+new-topic-param-topic": "متن برای عنوان مبحث جدید.",
- "apihelp-flow+view-post-description": "مشاهدهٔ پست.",
- "apihelp-flow+view-post-param-postId": "شناسهٔ پست برای مشاهده.",
- "apihelp-flow+view-topic-description": "مشاهدهٔ مبحث.",
- "apihelp-flow+view-topiclist-description": "مشاهده فهرستی از مبحث‌ها.",
- "apihelp-flow+view-topiclist-param-limit": "تعداد مبحث‌ها برای گرفتن.",
+ "flow-importer-wt-converted-archive-template-content": "این صفحه یک بایگانی است. <strong>محتویات این صفحه را ویرایش نکنید.</strong> لطفاً نظرات اضافی را به [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|صفحهٔ بحث فعلی]] ببرید.",
+ "flow-importer-lqt-suppressed-user-template": "ارسال ال‌کیوتی درون‌ریزی شده با کاربر فرونشانده",
+ "flow-importer-lqt-suppressed-user-template-content": "این نسخه از ال‌کیوتی با یک کاربر فرونشانده درون‌ریزی شد و به کاربر فعلی منصوب شده‌است.",
+ "flow-importer-lqt-different-author-signature-template": "ارسال ال‌کیوتی درون‌ریزی شده با کاربری با امضای متفاوت",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>این ارسال توسط [[User:{{{authorUser}}}|{{{authorUser}}}]] فرستاده شده بود، اما امضای [[User:{{{signatureUser}}}|{{{signatureUser}}}]] را داشت.</em>",
"flow-edited": "ویرایش شده",
"flow-edited-by": "ویرایش شده توسط $1",
- "flow-talk-conversion-archive-edit-reason": "ویکی‌متن بحث به گفتگوی جریان",
+ "flow-edited-by-header": "توضیحات تالار توسط $1 ویرایش شد",
+ "flow-edited-by-topic-title": "عنوان مبحث توسط $1 ویرایش شد",
+ "flow-lqt-redirect-reason": "تغییر مسیر ارسال‌های بازنشستهٔ ال‌کیوتی به ارسال‌های تبدیل‌شدهٔ فلو",
+ "flow-talk-conversion-move-reason": "تبدیل بحث ویکی‌متن به فلو از $1",
+ "flow-talk-conversion-archive-edit-reason": "تبدیل بحث ویکی‌متن به گفتگوی فلو",
"flow-previous-diff": "→ ویرایش کهنه‌تر",
"flow-next-diff": "ویراش تازه‌تر ←",
"flow-undo": "خنثی‌سازی",
"flow-undo-latest-revision": "آخرین نسخه",
"flow-undo-your-text": "متن شما",
"flow-undo-edit-header": "در حال ویرایش توضیحات",
- "flow-undo-edit-topic-summary": "در حال ویرایش خلاصه مبحث",
- "flow-undo-edit-post": "در حال ویرایش پست",
+ "flow-undo-edit-topic-summary": "در حال ویرایش جمع‌بندی مبحث",
+ "flow-undo-edit-post": "در حال ویرایش ارسال",
+ "flow-undo-edit-content": "این ویرایش را می‌توان خنثی کرد. لطفاً تفاوت زیر را بررسی کنید تا تأیید کنید که این چیزی است که می‌خواهید انجام دهید، سپس تغییرات زیر را ذخیره کنید تا خنثی‌سازی ویرایش را به پایان ببرید.",
"flow-undo-edit-failure": "به علت تعارض با ویرایش‌های میانی، این ویرایش را نمی‌توان خنثی کرد.",
- "group-flow-bot": "ربات‌های جریان",
- "group-flow-bot-member": "ربات جریان",
- "grouppage-flow-bot": "Project:ربات‌های جریان",
- "flow-ve-mention-context-item-label": "یاد کردن",
- "flow-ve-mention-inspector-title": "یاد کردن",
+ "group-flow-bot": "ربات‌های فلو",
+ "group-flow-bot-member": "ربات فلو",
+ "grouppage-flow-bot": "Project:ربات‌های فلو",
+ "flow-ve-mention-context-item-label": "اشاره کردن",
+ "flow-ve-mention-inspector-title": "اشاره کردن",
"flow-ve-mention-inspector-remove-label": "حذف",
"flow-ve-mention-placeholder": "نام کاربری",
- "flow-ve-mention-tool-title": "یاد کردن یک کاربر",
- "flow-ve-mention-inspector-invalid-user": "نا کاربری «$1» ثبت نشده است.",
+ "flow-ve-mention-tool-title": "اشاره کردن به یک کاربر",
+ "flow-ve-mention-template-title": "اشارهٔ فلو",
+ "flow-ve-mention-inspector-invalid-user": "نام کاربری «$1» ثبت نشده است.",
"flow-wikitext-editor-help": "ویکی‌متن $1.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|از قالب‌بندی استفاده می‌کند]]",
+ "flow-wikitext-editor-help-and-preview": "ویکی‌متن $1 و می‌توانید هرگاه خواستید $2 را ببینید.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|از نشانه‌گذاری استفاده می‌کند]]",
"flow-wikitext-editor-help-preview-the-result": "پیش‌نمایش نتیجه",
- "flow-wikitext-switch-editor-tooltip": "رفتن به ویرایشگر بصری",
- "flow-ve-switch-editor-tool-title": "رفتن به ویرایشگر متن ویکی",
+ "flow-wikitext-switch-editor-tooltip": "رفتن به ویرایشگر دیداری",
+ "flow-ve-switch-editor-tool-title": "رفتن به ویرایشگر ویکی‌متن",
"flow-mark-revision-patrolled-link-text": "به این صفحه برچسب گشت بزن",
"flow-mark-revision-patrolled-link-title": "به این صفحه برچسب گشت بزن",
"flow-mark-diff-patrolled-link-text": "برچسب گشت بزن",
"flow-mark-diff-patrolled-link-title": "برچسب گشت بزن",
+ "flow-talk-page-beta-feature-message": "فلو در صفحهٔ بحث کاربر",
+ "flow-talk-page-beta-feature-description": "یک سامانهٔ گفتگوی ساختارمند در صفحهٔ بحث {{GENDER:|شما}} فعال می‌کند. فلو گفتگو در صفحه‌های بحث را ساده می‌کند، مکان‌های روشنی برای نوشتن و پاسخ دادن دارد، و امکان آگاه‌سازی در سطح گفتگو را فراهم می‌کند. بحث‌های ویکی‌متنی موجود به یک بایگانی انتقال خواهند یافت. این ویژگی به طور خودکار فعال نمی‌شود؛ کاربران باید آن را به طور مجزا فعال کنند. غیر فعال کردن فلو، تالار گفتگو را به یک زیر صفحه می‌برد و صفحهٔ بحث قدیمی را از بایگانی در می‌آورد.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|نمایش}} صفحهٔ بحث کاربر",
+ "flow-notification-enabled-on-talkpage-title": "سامانهٔ گفتگوی جدید برای صفحهٔ بحث {{GENDER:$1|شما}} فعال شده<br /><small>آن را در [[$2]] بیابید</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "سامانهٔ گفتگوی جدید در $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "فلو، سامانهٔ جدید گفتگو در ویکی، در صفحهٔ بحث {{GENDER:$1|شما}} در {{SITENAME}} فعال شده‌است. برای اطلاعات بیشتر، بازخورد دادن و یا غیر فعال کردن سامانهٔ جدید در هر زمان، به قسمت ویژگی‌های آزمایشی در ترجیحات {{GENDER:$1|خود}} بروید.",
+ "flow-beta-feature-add-archive-template-edit-summary": "افزودن الگوی بایگانی",
+ "flow-beta-feature-remove-archive-template-edit-summary": "حذف الگوی بایگانی",
"flow-dialog-cancelconfirm-title": "اطمینان دارید؟",
- "flow-dialog-cancelconfirm-message": "مطمئنید که می‌خواهید بدون اینکه اول ذخیره کنید فسخ کنید؟",
+ "flow-dialog-cancelconfirm-message": "مطمئنید که می‌خواهید بدون اینکه اول ذخیره کنید، لغو کنید؟",
"flow-dialog-cancelconfirm-keep": "ادامه دادن به ویرایش",
- "flow-dialog-cancelconfirm-discard": "دور ریختن تغییرات"
+ "flow-dialog-cancelconfirm-discard": "دور ریختن تغییرات",
+ "flow-optin-archive-wikitext": "انتقال صفحهٔ ویکی‌متن به منظور جا باز کردن برای تالار گفتگو.",
+ "flow-optin-archive-flow-board": "انتقال تالار گفتگو به منظور جا باز کردن برای صفحهٔ ویکی‌متن.",
+ "flow-optin-restore-wikitext": "احیای صفحهٔ ویکی‌متن بایگانی‌شده.",
+ "flow-optin-restore-flow-board": "احیای تالار گفتگوی بایگانی‌شده.",
+ "flow-guidedtour-optin-welcome": "به صفحهٔ بحث جدیدتان {{GENDER:$1|خوش آمدید}}",
+ "flow-guidedtour-optin-welcome-description": "صفحهٔ بحث {{GENDER:$1|شما}} جایی است که دیگر ویرایشگران با شما تماس می‌گیرند. با فلو، ایجاد مبحث‌های جدید و پی‌گیری گفتگوها آسان‌تر است.",
+ "flow-guidedtour-optin-find-old-conversations": "یافتن بحث‌های قدیمی {{GENDER:$1|شما}}",
+ "flow-guidedtour-optin-find-old-conversations-description": "بحث‌های قدیمی به یک صفحه بایگانی منتقل شدند.",
+ "flow-guidedtour-optin-feedback": "به ما بازخورد {{GENDER:$1|دهید}}!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|شما}} می‌توانید برای اطلاعات بیشتر، ارائهٔ بازخورد، یا غیر فعال کردن سامانه در هر زمان به بخش ویژگی‌های آزمایشی مراجعه کنید.",
+ "flow-action-not-page": "شیء صفحه نمونه‌ای از کلاس اشتباه است"
}
diff --git a/Flow/i18n/fi.json b/Flow/i18n/fi.json
index 18bab674..0875248b 100644
--- a/Flow/i18n/fi.json
+++ b/Flow/i18n/fi.json
@@ -8,19 +8,46 @@
"MrTapsa",
"McSalama",
"Lliehu",
- "Pitke"
+ "Pitke",
+ "Nnemo",
+ "Olimar",
+ "Quiddity",
+ "Macofe",
+ "Mikahama",
+ "01miki10",
+ "Alluk."
]
},
- "enableflow": "Ota Flow käyttöön",
- "flow-desc": "Asianhallintajärjestelmä",
- "flow-talk-taken-over-comment": "/* Tämä sivu on muunnettu käyttämään Flow-keskustelualustaa */",
+ "enablestructureddiscussions": "Ota Flow käyttöön",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Lopeta}} sivun \"$1\" tarkkailu",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Sivu \"$1\" on poistettu tarkkailulistaltasi",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Tämä ei vaikuta yksittäisiin aiheisiin, joita tarkkailet. Voit tarkkailla [$2 tätä sivua] milloin tahansa.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Lopeta}} aiheen tarkkailu",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Aihe \"$1\" on poistettu tarkkailulistaltasi",
+ "flow-desc": "Keskustelujärjestelmä",
+ "flow-talk-taken-over-comment": "/* Tämä sivu on muunnettu käyttämään Flow-palstaa */",
"log-name-flow": "Flow-tapahtumaloki",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|poisti}} [$4 viestin] aiheessa \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{$2|poisti}} viestin sivulla [[$3]] olevasta aiheesta",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|palautti}} [$4 viestin] aiheessa \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|häivytti}} [$4 viestin] aiheessa \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|poisti}} [$4 viestin] aiheessa \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|poisti}} aiheen \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|poisti}} aiheen sivulla [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|palautti}} aiheen \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|häivytti}} aiheen \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|poisti}} aiheen \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|merkitsi}} aiheen \"[[$3|$5]]\" loppuunkäsitellyksi kohteessa [[$6]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|avasi uudelleen}} aiheen \"[[$3|$5]]\" kohteessa [[$6]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] kohteessa [[$3]] tuotiin LiquidThreadsista Flow'hun",
"flow-user-moderated": "Valvonnan alainen käyttäjä",
"flow-board-header-browse-topics-link": "Selaa aiheita",
- "flow-board-header": "Tietoa tästä keskustelusta",
+ "flow-board-header": "Tietoa tästä palstasta",
+ "flow-board-description-can-not-edit": "Ei muokattavissa",
"flow-board-collapse-description": "Piilota kuvaus",
"flow-board-expand-description": "Näytä kuvaus",
"flow-topic-collapse-siderail": "Lue koko leveydessään",
+ "flow-topic-expand-siderail": "Lue määrätyssä leveydessä",
"flow-edit-header-link": "Muokkaa kuvausta",
"flow-post-moderated-toggle-hide-show": "Näytä kommentti, jonka on {{GENDER:$1|piilottanut}} $2",
"flow-post-moderated-toggle-delete-show": "Näytä kommentti, jonka on {{GENDER:$1|poistanut}} $2",
@@ -29,36 +56,38 @@
"flow-post-moderated-toggle-delete-hide": "Piilota kommentti, jonka on {{GENDER:$1|poistanut}} $2",
"flow-post-moderated-toggle-suppress-hide": "Piilota kommentti, jonka on {{GENDER:$1|häivyttänyt}} $2",
"flow-topic-moderated-reason-prefix": "Syy:",
- "flow-hide-post-content": "Tämän kommentin on käyttäjä $1 {{GENDER:$1|piilottanut}} ([$2 historia])",
+ "flow-hide-post-content": "Tämän kommentin on {{GENDER:$1|piilottanut}} käyttäjä $1 ([$2 historia])",
"flow-hide-title-content": "Käyttäjä $1 on {{GENDER:$1|piilottanut}} tämän aiheen",
"flow-hide-header-content": "{{GENDER:$1|Piilottanut}} $2",
"flow-delete-post-content": "Tämän kommentin on käyttäjä $1 {{GENDER:$1|poistanut}} ([$2 historia])",
- "flow-delete-title-content": "Tämän aiheen on käyttäjä $1 {{GENDER:$1|poistanut}}",
+ "flow-delete-title-content": "Käyttäjä $1 on {{GENDER:$1|poistanut}} tämän aiheen",
"flow-delete-header-content": "{{GENDER:$1|Poistanut}} $2",
"flow-suppress-post-content": "Tämän kommentin on käyttäjä $1 {{GENDER:$1|häivyttänyt}} ([$2 historia])",
- "flow-suppress-title-content": "Tämän aiheen on käyttäjä $1 {{GENDER:$1|häivyttänyt}}",
- "flow-suppress-header-content": "{{GENDER:$1|Häivyttänyt}} $2",
+ "flow-suppress-title-content": "Käyttäjä $1 on {{GENDER:$1|häivyttänyt}} tämän aiheen",
+ "flow-suppress-header-content": "$2 {{GENDER:$1|häivytti}} tämän",
"flow-suppress-usertext": "<em>Käyttäjänimi on häivytetty</em>",
"flow-post-actions": "Toiminnot",
"flow-topic-actions": "Toiminnot",
"flow-cancel": "Peruuta",
- "flow-skip-summary": "Ohita yhteenveto",
+ "flow-skip-summary": "Ohita",
"flow-edit-summary-placeholder": "Kuvaile lyhyesti tämän keskustelun lopputulos",
"flow-summary-authored": "Yhteenveto käyttäjältä $1",
"flow-summary-edited": "Yhteenvetoa on viimeksi {{GENDER:$1|muokannut}} käyttäjä $1",
"flow-show-change": "Näytä muutokset",
"flow-last-modified-by": "Viimeksi {{GENDER:$1|muokannut}} käyttäjä $1",
- "flow-stub-post-content": "\"Teknisen virheen takia tämä viesti ei ole saatavissa.\"",
+ "flow-stub-post-content": "<em>Teknisen virheen takia tämä viesti ei ole saatavissa.</em>",
"flow-newtopic-title-placeholder": "Uusi aihe",
"flow-newtopic-content-placeholder": "Kirjoita uusi viesti sivulle \"$1\"",
"flow-newtopic-header": "Lisää uusi aihe",
"flow-newtopic-save": "Lisää aihe",
+ "flow-newtopic-save-anonymously": "Lisää aihe nimettömänä",
"flow-newtopic-start-placeholder": "Aloita uusi aihe",
"flow-newtopic-first-heading": "Aloita uusi aihe sivulla $1",
"flow-summarize-topic-placeholder": "Kirjoita yhteenveto tästä keskustelusta",
"flow-reply-topic-placeholder": "{{GENDER:$1|Kommentoi}} aihetta \"$2\"",
- "flow-reply-topic-title-placeholder": "Vastaa viestiin \"$1\"",
+ "flow-reply-topic-title-placeholder": "Vastaa aiheeseen \"$1\"",
"flow-reply-link": "{{GENDER:$1|Vastaa}}",
+ "flow-reply-link-anonymously": "Vastaa nimettömänä",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Kiitä}}}}",
"flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Kiitä}}}} julkisesti viestin kirjoittajaa",
"flow-history-action-suppress-post": "häivytä",
@@ -68,7 +97,7 @@
"flow-history-action-undelete-post": "palauta takaisin",
"flow-history-action-unhide-post": "tuo näkyviin",
"flow-history-action-restore-post": "palauta ennalleen",
- "flow-history-action-lock-topic": "käsittele",
+ "flow-history-action-lock-topic": "lopeta käsittely",
"flow-history-action-unlock-topic": "avaa uudelleen",
"flow-post-edited": "Viestiä on {{GENDER:$1|muokannut}} $1 $2",
"flow-post-action-view": "Ikilinkki",
@@ -78,6 +107,7 @@
"flow-post-action-hide-post": "Piilota",
"flow-post-action-edit-post": "Muokkaa",
"flow-post-action-edit-post-submit": "Tallenna muutokset",
+ "flow-post-action-edit-post-submit-anonymously": "Tallenna muutokset nimettömänä",
"flow-post-action-unsuppress-post": "Ota häivytys pois",
"flow-post-action-undelete-post": "Palauta takaisin",
"flow-post-action-unhide-post": "Tuo näkyviin",
@@ -106,19 +136,22 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Saat}} ilmoituksen kun uusi aihe lisätään tänne.",
"flow-topic-action-watchlist-add": "Tilaa tämä aihe",
"flow-topic-action-watchlist-remove": "Peruuta tilaus",
+ "flow-error-allowcreation-no-usedb": "Flow'n käyttöönotto tietyllä sivulla edellyttää <var>$wgContentHandlerUseDB</var> olevan <code>true</code>.",
"flow-error-allowcreation-already-exists": "Sivu on jo olemassa, vaikka sen ei tarvinnut olla olemassa",
+ "flow-error-allowcreation-flow-create-board": "Käyttäjällä ei ole lupaa \"{{int:-flow-create-board}}\"",
"flow-error-http": "Virhe muodostettaessa yhteyttä palvelimeen.",
- "flow-error-other": "Tuntematon virhe tapahtui.",
- "flow-error-external": "On tapahtunut virhe.<br />Vastaanotettu virheilmoitus oli: $1",
+ "flow-error-external": "Tapahtui virhe. Vastaanotettu virheilmoitus oli: $1",
"flow-error-topic-is-locked": "Tämä aihe on loppuunkäsitelty, joten siihen ei voi enää koskea.",
- "flow-error-lock-moderated-post": "Et voi merkitä valvottua viestiä loppuun käsitellyksi.",
- "flow-error-external-multi": "Virheitä on tapahtunut.<br />$1",
+ "flow-error-lock-moderated-post": "Et voi merkitä valvottua viestiä loppuunkäsitellyksi.",
"flow-error-missing-content": "Viestissä ei ole sisältöä. Vain tekstiä sisältäviä viestejä voidaan tallentaa.",
"flow-error-missing-summary": "Sinun täytyy antaa yhteenveto.",
"flow-error-missing-title": "Aiheella ei ole otsikkoa. Aiheen otsikko on välttämätön, jotta aihe voidaan tallentaa.",
- "flow-error-delete-failure": "Tämän kohteen poistaminen epäonnistui.",
- "flow-error-hide-failure": "Tämän kohteen piilottaminen epäonnistui.",
- "flow-error-restore-failure": "Tämän kohteen ennalleen palauttaminen epäonnistui.",
+ "flow-error-parsoid-failure": "Ei voi jäsentää sisältöä, koska tapahtui Parsoid-virhe.",
+ "flow-error-protected-unknown-reason": "Tuntematon",
+ "flow-error-missing-replyto": "\"vastaaTälle\"-parametria ei sisällytetty. Parametria vaaditaan \"vastaa\"-toiminnolle.",
+ "flow-error-missing-postId": "\"postId\"-parametriä ei annettu. Parametria tarvitaan viestin poistamiseen tai palauttamiseen.",
+ "flow-error-invalid-postId": "\"postId\"-parametri oli virheellinen. Määriteltyä viestiä ($1) ei löydetty.",
+ "flow-error-invalid-moderation-state": "Parametrille ('moderationState') annettiin virheellinen arvo Flow-API:ssa.",
"flow-error-invalid-moderation-reason": "Anna perusteltu syy viestin valvonnalle.",
"flow-error-not-allowed": "Käyttöoikeutesi eivät riitä tämän toiminnon suorittamiseen.",
"flow-error-not-allowed-hide": "Tämä aihe on piilotettu.",
@@ -129,110 +162,309 @@
"flow-error-not-allowed-reply-to-suppress-topic": "Et voi vastata, koska tämä aihe on poistettu.",
"flow-error-not-allowed-hide-extract": "Tämä aihe on piilotettu. Alla näkyy piilotusloki, jossa on lisätietoja.",
"flow-error-not-allowed-delete-extract": "Tämä aihe on poistettu. Alla näkyy poistoloki, jossa on lisätietoja.",
- "flow-error-title-too-long": "Aiheen otsikon koko ei voi olla suurempi kuin $1 {{PLURAL:$1|tavu|tavua}}.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Et voi vastata, koska tämä aihe on poistettu. Aiheen poistoloki on tarkistettavissa alta.",
+ "flow-error-not-allowed-suppress-extract": "Tämä aihe on poistettu. Alla näkyy poistoloki, jossa on lisätietoja.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Et voi vastata, koska tämä aihe on poistettu häivyttämällä. Häivytysloki koskien tätä aihetta on alla.",
+ "flow-error-title-too-long": "Otsikossa voi olla enintään $1 {{PLURAL:$1|merkki|merkkiä}}.",
"flow-error-no-existing-workflow": "Tätä aihetta ei vielä ole olemassa.",
"flow-error-not-a-post": "Aiheen otsikkoa ei voida tallentaa ikään kuin se olisi viesti.",
- "flow-error-missing-header-content": "Kuvauksessa ei ole sisältöä. Sisältöä pitää olla ennen kuvauksen tallentamista.",
+ "flow-error-missing-header-content": "Sinun on annettava kuvaus.",
"flow-error-missing-prev-revision-identifier": "Aiemman version tunnusnumero puuttuu.",
"flow-error-prev-revision-mismatch": "Toinen käyttäjä muokkasi tätä viestiä muutama sekunti sitten. {{GENDER:$3|Oletko}} varma, että haluat tuhota aiemman tekstin kirjoittamalla oman kommenttisi sen päälle?",
"flow-error-prev-revision-does-not-exist": "Aiempaa versioita ei löydetty.",
+ "flow-error-core-topic-deletion": "Jos haluat poistaa aiheen, käytä ...valikkoa Flow-seinällä tai [$1 aiheen sivulla]. Älä käytä toiminto=poista aiheelle suoraan.",
"flow-error-default": "Tapahtui virhe.",
+ "flow-error-invalid-input": "Flow-sisällön lataamiselle annettiin virheellinen arvo.",
"flow-error-invalid-title": "On annettu virheellinen sivun nimi.",
"flow-error-fail-load-history": "Historian sisältöä ei voitu ladata.",
+ "flow-error-missing-revision": "Flow-sisällön lataamiselle ei kyetty löytämään versiota.",
"flow-error-fail-commit": "Flow-sisällön tallentaminen epäonnistui.",
"flow-error-insufficient-permission": "Sinulla ei ole riittäviä oikeuksia, jotta pääsisit käsiksi tähän sisältöön.",
+ "flow-error-revision-comparison": "Näytä muutokset -toiminnon voi suorittaa vain kahdelle samaan postaukseen kuuluvaan versioon.",
+ "flow-error-missing-topic-title": "Ei löytynyt aiheen otsikkoa tämänhetkiselle workflow'lle.",
+ "flow-error-missing-metadata": "Tälle versiolle ei kyetty löytämään vaadittua metatietoa.",
+ "flow-error-fail-load-data": "Vaaditun tiedon lataaminen epäonnistui.",
+ "flow-error-invalid-workflow": "Tavoiteltua workflow'ta ei löydetty.",
+ "flow-error-process-data": "Tapahtui virhe käsiteltäessäsi pyyntösi tietoja.",
+ "flow-error-process-wikitext": "HTML/wikiteksti-muunnosta käsiteltäessä tapahtui virhe.",
+ "flow-error-no-index": "Ei löydetty hakemistoa tietojen haun suorittamiseksi.",
+ "flow-error-no-render": "Määriteltyä toimintoa ei tunnistettu.",
+ "flow-error-no-commit": "Määriteltyä toimintoa ei voitu tallentaa.",
+ "flow-error-content-too-long": "Sisältö on liian suuri. Laajentamisen jälkeinen sisältö on rajoitettu $1 {{PLURAL:$1|merkkiin}}.",
"flow-error-move-topic": "Aihesivun siirtämistä ei nykyisessä järjestelmässä ole mahdollista tehdä lainkaan.",
"flow-error-invalid-topic-uuid-title": "Sopimaton otsikko",
+ "flow-error-invalid-topic-uuid": "Sivun otsikko oli virheellinen. Flow luo automaattisesti sivut aiheen nimiavaruudessa.",
"flow-error-unknown-workflow-id-title": "Tuntematon aihe",
"flow-error-unknown-workflow-id": "Pyydettyä aihetta ei ole olemassa.",
- "flow-edit-header-placeholder": "Kuvaile tätä keskustelupaikkaa",
+ "flow-error-search": "Hakuasi ei voitu suorittaa tilapäisen virheen takia. Kokeile myöhemmin uudestaan.",
+ "flow-edit-header-placeholder": "Kuvaile tätä keskustelupalstaa",
"flow-edit-header-submit": "Tallenna kuvaus",
+ "flow-edit-header-submit-anonymously": "Tallenna kuvaus nimettömänä",
"flow-edit-title-submit": "Muuta otsikkoa",
+ "flow-edit-title-submit-anonymously": "Muuta otsikko nimettömänä.",
"flow-edit-post-submit": "Lähetä muutokset",
+ "flow-edit-post-submit-anonymously": "Tallenna muutokset nimettömänä",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|muokkasi}} [$3 kommenttia] koskien aihetta \"$4\"",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Muokkasi}} viestiä",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|kommentoi}}] aihetta \"$4\" (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|kommentti|kommenttia}}</strong> {{PLURAL:$1|on}} lisätty",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|on luonut}} aiheen \"[$3 $4]\"",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Luotu}} uusi aihe",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|muutti}} aiheen otsikkoa vanhasta \"$5\" uudeksi \"[$3 $4]\"",
"flow-rev-message-create-header": "$1 {{GENDER:$2|loi}} kuvauksen",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|muokkasi}} kuvausta",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|loi}} yhteenvedon aiheeseen $3",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|muokkasi}} aiheen $3 yhteenvetoa",
- "flow-rev-message-restored-post": "$1 {{GENDER:$2|palautti}} aiheen \"$6\" [$4 kommentin] (<em>$5</em>).",
- "flow-rev-message-lock-topic-reason": "merkitty käsitellyksi",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|piilotti}} aiheeseen \"$6\" käyttäjän [$4 tekemän kommentin] (<em>$5</em>).",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|poisti}} aiheeseen \"$6\" käyttäjän [$4 tekemän kommentin] (<em>$5</em>).",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|häivytti}} [$4 kommentin] aiheessa \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|palautti}} aiheen \"$6\" [$4 kommentin] (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|piilotti näkyvistä}} [$4 aiheen] \"$6\" (<em>$5</em>).",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|poisti}} [$4 aiheen] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|häivytti}} [$4 aiheen] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|merkitsi}} [$4 aiheen] ”$6” loppuunkäsitellyksi (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "merkitty loppuunkäsitellyksi",
"flow-rev-message-restore-topic-reason": "avattu uudelleen",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|palautti käsiteltäväksi}} [$4 aiheen] \"$6\" (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 palstalla $2",
+ "flow-board-history": "Sivun \"$1\" historia",
"flow-board-history-empty": "Tällä palstalla ei ole historiaa.",
"flow-topic-history": "Aiheen \"$1\" historia",
+ "flow-post-history": "\"Käyttäjän {{GENDER:$2|$2}} kommentti\" viestihistoria",
"flow-history-last4": "Viimeiset 4 tuntia",
"flow-history-day": "Tänään",
"flow-history-week": "Viimeinen viikko",
"flow-history-pages-topic": "Näkyy sivulla [$1 \"$2\"]",
+ "flow-history-pages-post": "Näkyy aiheessa [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 kommentti|$1 kommenttia|0={{GENDER:$2|Ole ensimmäinen}} kommentoija!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Näytä kommentti|Näytä kommentit}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Piilota kommentti|Piilota kommentit}}",
"flow-comment-restored": "Palautettu kommentti",
"flow-comment-deleted": "Poistettu kommentti",
"flow-comment-hidden": "Piilotettu kommentti",
"flow-comment-moderated": "Moderoitu kommentti",
+ "flow-last-modified": "Viimeksi muokattu noin $1",
+ "flow-workflow": "työnkulku",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|vastasi}} sivulla <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ja {{PLURAL:$5|yksi muu|$5 muuta|100=yli 99 muuta}} {{GENDER:$1|vastasivat}} sivulla <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 on {{GENDER:$1|muokannut}} aiheen [[$3|$4]] <span class=\"plainlinks\">[$5 viestiäsi]</span>.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|loi}} uuden aiheen sivulla '''$3'''.",
+ "flow-notification-edit-bundle": "$1 ja {{PLURAL:$5|yksi muu|$5 muuta|100=yli 99 muuta}} {{GENDER:$1|muokkasivat}} <span class=\"plainlinks\">[$4 viestiä]</span> aiheessa \"$2\" sivulla \"$3\".",
+ "notification-header-flow-new-topic-v2": "Uusi aihe luotu sivulla <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Yksi uusi aihe|$1 uutta aihetta|100=Yli 99 uutta aihetta}} sivulla <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Uusi aihe luotiin <strong>keskustelusivullesi</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Yksi uusi aihe|$1 uutta aihetta|100=Yli 99 uutta aihetta}} <strong>keskustelusivullasi</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|vastasi}} aiheeseen \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Yksi uusi vastaus|$1 uutta vastausta|100=Yli 99 uutta vastausta}} sivulla \"<strong>$3</strong>\".",
+ "notification-header-flow-description-edited": "Palstan <strong>$1</strong> kuvausta muokattiin.",
+ "notification-header-flow-description-edited-user-talk": "{{GENDER:$2|Keskustelusivusi}} kuvausta muokattiin.",
+ "notification-bundle-header-flow-description-edited": "Palstan <strong>$1</strong> kuvausta muokattiin useita kertoja.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Näytä}} sivu",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|muokkasi}} kuvausta sivulla $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|muokkasi}} kuvausta sivulla $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 ja {{PLURAL:$3|yksi muu|$3 muuta|100=yli 99 muuta}} {{GENDER:$1|muokkasivat}} kuvausta sivulla $2",
+ "notification-header-flow-topic-resolved": "Aihe <strong>$1</strong> merkittiin käsitellyksi.",
+ "notification-header-flow-topic-reopened": "Aihe \"<strong>$1</strong>\" avattiin uudelleen.",
+ "notification-header-flow-topic-resolved-user-talk": "Aihe \"<strong>$1</strong>\" ratkaistiin <strong>keskustelusivullasi</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Aihe \"<strong>$1</strong>\" avattiin uudelleen <strong>keskustelusivullasi</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Aihe \"<strong>$2</strong>\" ratkaistiin.",
+ "notification-email-batch-body-flow-topic-resolved": "Aihe \"<strong>$2</strong>\" ratkaistiin.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|loi}} uuden aiheen sivulla <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Yksi uusi aihe|$1 uutta aihetta|100=Yli 99 uutta aihetta}} sivulla <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-rename": "$1 {{GENDER:$1|muutti}} aiheen <span class=\"plainlinks\">[$2 $3]</span> otsikon muotoon \"$4\" sivulla [[$5|$6]].",
+ "flow-notification-mention": "$1 {{GENDER:$1|mainitsi}} {{GENDER:$5|sinut}} {{GENDER:$1|hänen}} <span class=\"plainlinks\">[$2 viestissään]</span> aiheessa \"$3\" sivulla \"$4\".",
"flow-notification-link-text-view-post": "Näytä viesti",
"flow-notification-link-text-view-topic": "Näytä aihe",
- "flow-notification-reply-email-subject": "$1 {{GENDER:$1|vastasi}} aiheeseen",
- "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mainitsi}} {{GENDER:$3|sinut}} keskustelussa $2",
+ "flow-notification-link-text-view-topics": "Näytä aiheet",
+ "flow-notification-reply-email-subject": "$2 kohteessa $3",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|vastasi}} aiheeseen \"$2\" kohteessa $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 ja {{PLURAL:$4|yksi muu|$4 muuta|100=yli 99 muuta}} {{GENDER:$1|vastasivat}} aiheeseen \"$2\" sivulla $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mainitsi}} {{GENDER:$3|sinut}} kohteessa $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mainitsi}} {{GENDER:$4|sinut}} {{GENDER:$1|viestissään}} aiheessa \"$2\" kohteessa $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|muokkasi}} viestiä",
+ "flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|muokkasi}} viestiä aiheessa \"$2\" kohteessa $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 ja {{PLURAL:$4|yksi muu|$4 muuta|100=yli 99 muuta}} {{GENDER:$1|muokkasivat}} viestiä aiheessa \"$2\" sivulla $3",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|vaihtoi nimen}} aiheeseesi",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|uudelleennimesi}} aiheesi \"$2\" muotoon \"$3\" sivulla $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|loi}} uuden aiheen sivulla $2",
- "echo-pref-tooltip-flow-discussion": "Ilmoita minulle, kun minuun liittyvää toimintaa tapahtuu Flowissa.",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|loi}} loi uuden aiheen otsikolla \"$2\" sivulla $3",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Yksi uusi aihe|$1 uutta aihetta|100=Yli 99 uutta aihetta}} sivulla $2",
+ "echo-category-title-flow-discussion": "Flow-keskustelu",
+ "echo-pref-tooltip-flow-discussion": "Ilmoita minulle tapahtumista seuraamillani palstoilla ja aiheissa.",
"flow-link-post": "viesti",
"flow-link-topic": "aihe",
"flow-link-history": "historia",
- "flow-moderation-title-suppress-post": "Viestin sensurointi",
- "flow-moderation-title-delete-post": "Viestin poisto",
- "flow-moderation-title-hide-post": "Viestin piilotus",
+ "flow-link-post-revision": "viestin versio",
+ "flow-link-topic-revision": "aiheen versio",
+ "flow-link-header-revision": "kuvauksen versio",
+ "flow-link-summary-revision": "yhteenvedon versio",
+ "flow-moderation-title-suppress-post": "Häivytä viesti?",
+ "flow-moderation-title-delete-post": "Poista viesti?",
+ "flow-moderation-title-hide-post": "Piilota viesti?",
+ "flow-moderation-title-unsuppress-post": "Poista häivytys viestistä?",
"flow-moderation-title-undelete-post": "Palautetaanko viesti?",
"flow-moderation-title-unhide-post": "Tuo näkyviin viesti?",
"flow-moderation-placeholder-suppress-post": "{{GENDER:$3|Kerro}} miksi häivytät tämän viestin.",
+ "flow-moderation-placeholder-delete-post": "{{GENDER:$3|Kerro}}, miksi olet poistamassa tätä viestiä.",
"flow-moderation-placeholder-hide-post": "{{GENDER:$3|Kerro}} miksi piilotat tämän viestin.",
+ "flow-moderation-placeholder-unsuppress-post": "{{GENDER:$3|Kerro}}, miksi olet poistamassa häivytyksen tästä viestistä.",
"flow-moderation-placeholder-undelete-post": "{{GENDER:$3|Kerro}} miksi palautat tämän viestin.",
+ "flow-moderation-placeholder-unhide-post": "{{GENDER:$3|Kerro}}, miksi olet palauttamassa tätä viestiä näkyviin.",
"flow-moderation-confirm-suppress-post": "Häivytä",
"flow-moderation-confirm-delete-post": "Poista",
"flow-moderation-confirm-hide-post": "Piilota",
+ "flow-moderation-confirm-unsuppress-post": "Poista häivytys",
"flow-moderation-confirm-undelete-post": "Palauta",
"flow-moderation-confirm-unhide-post": "Tuo näkyviin",
"flow-moderation-confirm-suppress-topic": "Häivytä",
"flow-moderation-confirm-delete-topic": "Poista",
"flow-moderation-confirm-hide-topic": "Piilota",
+ "flow-moderation-confirm-unsuppress-topic": "Poista häivytys",
"flow-moderation-confirm-undelete-topic": "Palauta",
"flow-moderation-confirm-unhide-topic": "Tuo näkyviin",
- "flow-moderation-confirmation-unhide-post": "Olet onnistuneesti tuonut näkyviin edellä olevan viestin.",
+ "flow-moderation-confirmation-suppress-post": "Viesti häivytettiin.\n{{GENDER:$2|Harkitse}} palautteen antamista käyttäjälle $1 viestin sisällöstä.",
+ "flow-moderation-confirmation-delete-post": "Viesti poistettiin.\n{{GENDER:$2|Harkitse}} palautteen antamista käyttäjälle $1 tästä viestistä.",
+ "flow-moderation-confirmation-hide-post": "Viesti piilotettiin.\n{{GENDER:$2|Harkitse}} palautteen antamista käyttäjälle $1 tästä viestistä.",
+ "flow-moderation-confirmation-unsuppress-post": "Olet poistanut häivytyksen yllä olevasta viestistä.",
+ "flow-moderation-confirmation-undelete-post": "Olet palauttanut näkyviin yllä olevan viestin.",
+ "flow-moderation-confirmation-unhide-post": "Olet tuonut näkyviin edellä olevan viestin.",
+ "flow-moderation-confirmation-suppress-topic": "Tämä aihe on häivytetty.",
+ "flow-moderation-confirmation-delete-topic": "Tämä aihe on poistettu.",
"flow-moderation-confirmation-hide-topic": "Tämä aihe on piilotettu.",
- "flow-moderation-confirmation-unhide-topic": "Olet onnistuneesti tuonut näkyviin tämän aiheen.",
+ "flow-moderation-confirmation-unsuppress-topic": "Olet poistanut häivytyksen aiheesta ja palauttanut sen näkyviin.",
+ "flow-moderation-confirmation-undelete-topic": "Olet palauttanut tämän aiheen takaisin.",
+ "flow-moderation-confirmation-unhide-topic": "Olet tuonut näkyviin tämän aiheen.",
"flow-moderation-title-suppress-topic": "Häivytä aihe?",
"flow-moderation-title-delete-topic": "Poista aihe?",
"flow-moderation-title-hide-topic": "Piilota aihe?",
+ "flow-moderation-title-unsuppress-topic": "Poistetaanko aiheen häivytys?",
+ "flow-moderation-title-undelete-topic": "Palautetaanko aihe takaisin?",
"flow-moderation-title-unhide-topic": "Tuo näkyviin aihe?",
- "flow-moderation-placeholder-undelete-topic": "{{GENDER:$3|Kerro}} miksi palautat tämän ketjun takaisin.",
+ "flow-moderation-placeholder-suppress-topic": "{{GENDER:$3|Kerro}}, miksi haluat häivyttää tämän aiheen.",
+ "flow-moderation-placeholder-delete-topic": "{{GENDER:$3|Kerro}}, miksi olet poistamassa tätä aihetta.",
+ "flow-moderation-placeholder-hide-topic": "{{GENDER:$3|Kerro}}, miksi olet piilottamassa tätä aihetta.",
+ "flow-moderation-placeholder-unsuppress-topic": "{{GENDER:$3|Kerro}}, miksi olet poistamassa häivytyksen tästä aiheesta.",
+ "flow-moderation-placeholder-undelete-topic": "{{GENDER:$3|Kerro}} miksi palautat tämän aiheen takaisin.",
+ "flow-moderation-placeholder-unhide-topic": "{{GENDER:$3|Kerro}}, miksi olet palauttamassa tätä aihetta näkyviin.",
"flow-topic-permalink-warning": "Tämä aihe aloitettiin sivulla [$2 $1]",
- "flow-compare-revisions-revision-header": "Versio, jonka tehnyt {{GENDER:$2|$2}} $1",
- "flow-compare-revisions-header-post": "Tämä sivu näyttää {{GENDER:$3|muutokset}} kahden version välillä viestistä käyttäjältä $3 aiheessa \"[$5 $2]\" sivulla [$4 $1].\nVoit nähdä muut versiot tästä aiheesta sen [$6 historiasivulla].",
+ "flow-topic-permalink-warning-user-board": "Tämä aihe aloitettiin [$2 käyttäjän {{GENDER:$1|$1}} palstalla]",
+ "flow-revision-permalink-warning-post": "Tämä on ikilinkki yhteen versioon tästä viestistä.\nTämän version päiväys on $1.\nVoit nähdä [$5 eroavaisuudet edeltävästä versiosta], tai katsoa muita versioita [$4 viestin historiasivulla].",
+ "flow-revision-permalink-warning-post-first": "Tämä on ikilinkki viestin ensimmäiseen versioon.\nVoit katsoa uudempia versioita [$4 viestin historiasivulla].",
+ "flow-revision-permalink-warning-postsummary": "Tämä on ikilinkki yksittäiseen versioon viestin yhteenvedosta. Tämän version päiväys on $1. Voit katsoa [$5 eroavaisuudet edellisestä versiosta] tai katsoa muita versioita [$4 viestin historiasivulla].",
+ "flow-compare-revisions-revision-header": "Versio, jonka on tehnyt {{GENDER:$2|$2}} $1",
+ "flow-compare-revisions-header-post": "Tämä sivu näyttää {{GENDER:$3|muutokset}} kahden version välillä käyttäjän $3 kirjoittamassa viestissä, jonka aihe on \"[$5 $2]\" ja joka on palstalla [$4 $1].\nVoit nähdä tämän viestin muut versiot sen [$6 historiasivulta].",
+ "action-flow-create-board": "luo Flow-palstoja mihin tahansa",
+ "right-flow-create-board": "Luoda Flow-palstoja minne tahansa",
"right-flow-hide": "Piilottaa Flow'n aiheita ja sisältöä",
"right-flow-lock": "Merkitä Flow'n aiheita loppuunkäsitellyiksi",
"right-flow-delete": "Poistaa Flow'n aiheita ja viestejä",
"right-flow-edit-post": "Muokata Flow'n viestejä, jotka on kirjoittanut toinen käyttäjä",
"right-flow-suppress": "Häivyttää Flow'n versioita",
- "flow-terms-of-use-new-topic": "Napsauttamalla \"{{int:flow-newtopic-save}}\", hyväksyt tämän wikin käyttöehdot.",
- "flow-terms-of-use-edit": "Tallentamalla muutoksesi, hyväksyt käyttöehdot tässä wikissä.",
+ "flow-terms-of-use-new-topic": "Napsauttamalla ”{{int:flow-newtopic-save}}”, hyväksyt tämän wikin käyttöehdot.",
+ "flow-terms-of-use-edit": "Tallentamalla muutoksesi hyväksyt käyttöehdot tässä wikissä.",
+ "flow-anon-warning": "Et ole kirjautunut sisään. Saadaksesi muokkauksen omiin nimiisi IP-osoitteen sijaan, [$1 kirjaudu sisään] tai [$2 luo tunnus].",
"flow-cancel-warning": "Olet asettanut tekstiä tähän lomakkeeseen. Oletko varma, että haluat hylätä muutoksesi?",
+ "flow-topic-first-heading": "Aihe sivulla $1",
+ "flow-topic-html-title": "$1 sivulla $2",
+ "flow-topic-count": "Aiheet ($1)",
+ "flow-load-more": "Lataa lisää",
"flow-no-more-fwd": "Ei vanhempia aiheita",
"flow-newest-topics": "Uusimmat aiheet",
- "flow-recent-topics": "Viimeksi aktiiviset aiheet",
+ "flow-recent-topics": "Viimeksi kommentoidut aiheet",
"flow-sorting-tooltip-newest": "{{GENDER:|Näet}} tällä hetkellä uusimmat aiheet ylimpänä. Napsauta saadaksesi lisää lajitteluvaihtoehtoja.",
"flow-sorting-tooltip-recent": "{{GENDER:|Näet}} tällä hetkellä viimeksi aktiiviset aiheet ylimpänä. Napsauta saadaksesi lisää lajitteluvaihtoehtoja.",
+ "flow-toggle-small-topics": "Vaihda näkymään pienet aiheet",
+ "flow-toggle-topics": "Vaihda näkymään vain aiheet",
+ "flow-toggle-topics-posts": "Vaihda näkymään aiheet ja viestit",
+ "flow-terms-of-use-summarize": "Klikkaamalla \"{{int:flow-topic-action-update-topic-summary}}\", hyväksyt tämän wikin käyttöehdot.",
+ "flow-terms-of-use-lock-topic": "Klikkaamalla \"{{int:flow-topic-action-lock-topic}}\", hyväksyt tämän wikin käyttöehdot.",
+ "flow-terms-of-use-unlock-topic": "Klikkaamalla \"{{int:flow-topic-action-unlock-topic}}\", hyväksyt tämän wikin käyttöehdot.",
+ "flow-whatlinkshere-post": "[$1 viestistä]",
+ "flow-whatlinkshere-header": "[$1 kuvauksesta]",
+ "flow-whatlinkshere-post-summary": "[$1 yhteenvedosta]",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Tämä erikoissivu ohjaa Flow-workflow'hun tai Flow-viestiin, jolle on annettu UUID.",
+ "flow-special-type": "Tyyppi",
+ "flow-special-type-post": "Viesti",
+ "flow-special-type-workflow": "Workflow",
+ "flow-special-uuid": "UUID",
+ "flow-special-invalid-uuid": "Ei löydetty tyyppiä tai UUID:tä vastaavaa sisältöä.",
+ "flow-special-enableflow-legend": "Ota käyttöön Flow uudella sivulla",
+ "flow-special-enableflow-page": "Sivu jolla Flow otetaan käyttöön",
+ "flow-special-enableflow-header": "Alkuperäinen kuvaus Flow-palstalle (wikitekstiä)",
+ "flow-special-enableflow-board-already-exists": "On jo olemassa Flow-palsta sivulla [[$1]]",
+ "flow-special-enableflow-invalid-title": "Annoit sivulle virheellisen nimen.",
+ "flow-special-enableflow-board-creation-not-allowed": "Sinulla ei ole oikeutta luoda Flow-palstaa sivulle [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Sivulla [[:$1]] on LiquidThreads-sivu.",
+ "flow-special-enableflow-confirmation": "Olet luonut Flow-palstan sivulle [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Arkisto %d\n%s/arkisto%d\n%s/arkisto %d\n%s/arkisto%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Flow-arkisto %d\n%s/Flow-arkisto%d",
+ "flow-spam-confirmedit-form": "Todista olevasi ihminen ratkomalla allaoleva CAPTCHA: $1",
+ "flow-embedding-unsupported": "Keskusteluja ei voi vielä upottaa.",
+ "mw-ui-unsubmitted-confirm": "Sinulla on tallentamattomia muokkauksia tällä sivulla. Haluatko varmasti siirtyä pois ja menettää muokkauksesi?",
+ "flow-post-undo-hide": "piilottaminen on peruutettu",
+ "flow-post-undo-delete": "peruuta poistaminen",
+ "flow-post-undo-suppress": "peruuta häivyttäminen",
+ "flow-topic-undo-hide": "piilottaminen on peruutettu",
+ "flow-topic-undo-delete": "peruuta poistaminen",
+ "flow-topic-undo-suppress": "peruuta häivyttäminen",
+ "flow-importer-lqt-moved-thread-template": "LQT siirsi ketjutyngän, joka oli muunnettu Flow'hun",
+ "flow-importer-lqt-converted-template": "Flow'hun muunnettu LQT-sivu",
+ "flow-importer-lqt-converted-archive-template": "Muunnetun LQT-sivun arkisto",
+ "flow-importer-wt-converted-template": "Flow'hun muunnettu wikitekstikeskustelusivu",
+ "flow-importer-wt-converted-archive-template": "Muunnetun wikitekstikeskustelusivun arkisto",
+ "flow-importer-wt-converted-archive-template-content": "Tämä sivu on arkisto. <strong>Älä muokkaa tätä sivua</strong>. Kaikki uudet kommentit aiheesta kuuluvat [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|nykyiselle keskustelusivulle]].",
+ "flow-importer-lqt-suppressed-user-template": "LQT-viesti siirrettiin häivytetyn käyttäjän kanssa",
"flow-edited": "Muokattu",
"flow-edited-by": "Muokannut $1",
+ "flow-edited-by-header": "$1 muokkasi palstan kuvausta",
+ "flow-edited-by-topic-title": "$1 muokkasi aiheen otsikkoa",
+ "flow-talk-conversion-archive-edit-reason": "Wikiteksti-keskustelusivu muutettu Flow-palstaksi",
+ "flow-previous-diff": "← Vanhempi muokkaus",
+ "flow-next-diff": "Uudempi muokkaus →",
+ "flow-undo": "kumoa",
+ "flow-undo-latest-revision": "Viimeisin versio",
+ "flow-undo-your-text": "Tekstisi",
+ "flow-undo-edit-header": "Muokataan kuvausta",
+ "flow-undo-edit-topic-summary": "Muokataan aiheen yhteenvetoa",
+ "flow-undo-edit-post": "Muokataan viestiä",
+ "flow-undo-edit-content": "Muokkaus voidaan peruuttaa. Tarkista alla näkyvästä vertailusta että varmasti haluat tehdä näin, ja sen jälkeen tallenna muutokset peruuttaaksesi muokkauksen.",
+ "flow-undo-edit-failure": "Muokkausta ei voitu peruuttaa päällekkäisten muokkausten takia.",
"group-flow-bot": "botit (Flow)",
- "group-flow-bot-member": "Flow'n botti",
+ "group-flow-bot-member": "Flow-botti",
+ "grouppage-flow-bot": "Project:Botit (Flow)",
"flow-ve-mention-context-item-label": "Mainitse",
"flow-ve-mention-inspector-title": "Mainitse",
"flow-ve-mention-inspector-remove-label": "Poista",
"flow-ve-mention-placeholder": "Käyttäjätunnus",
"flow-ve-mention-tool-title": "Mainitse käyttäjä",
+ "flow-ve-mention-template-title": "Flow-maininta",
+ "flow-ve-mention-inspector-invalid-user": "Käyttäjänimeä \"$1\" ei ole rekisteröity.",
+ "flow-wikitext-editor-help": "Wikiteksti $1.",
+ "flow-wikitext-editor-help-and-preview": "Wikiteksti $1 ja voit $2 milloin tahansa.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|käyttää merkintäkieltä]]",
+ "flow-wikitext-editor-help-preview-the-result": "esikatsella tulosta",
"flow-wikitext-switch-editor-tooltip": "Vaihda Visuaaliseen muokkaimeen",
- "flow-ve-switch-editor-tool-title": "Vaihda wikitekstimuokkaimeen"
+ "flow-ve-switch-editor-tool-title": "Vaihda wikitekstimuokkaimeen",
+ "flow-mark-revision-patrolled-link-text": "Merkitse tämä sivu tarkastetuksi",
+ "flow-mark-revision-patrolled-link-title": "Merkitse tämä sivu tarkastetuksi",
+ "flow-mark-diff-patrolled-link-text": "Merkitse tarkastetuksi",
+ "flow-mark-diff-patrolled-link-title": "Merkitse tarkastetuksi",
+ "flow-talk-page-beta-feature-message": "Flow käyttäjän keskustelusivulla",
+ "flow-talk-page-beta-feature-description": "Ota käyttöön uusi rakenteinen keskustelujärjestelmä {{GENDER:|sinun}} keskustelusivullesi. Flow yksinkertaistaa keskusteluja selkeillä kirjoitus- ja vastauskentillä ja mahdollistaa keskustelukohtaiset ilmoitukset. Olemassaolevat wikitekstikeskustelut siirretään arkistoon. Tätä ominaisuutta ei oteta käyttöön automaattisesti; käyttäjien pitää ottaa se käyttöön yksitellen. Ominaisuuden ottaminen pois käytöstä siirtää Flow-palstan alasivulle ja palauttaa aikaisemman keskustelusivun.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Näytä}} käyttäjän keskustelusivu",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Uusi keskustelujärjestelmä sivulla $2",
+ "flow-beta-feature-add-archive-template-edit-summary": "Lisätään arkistomalline.",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Poistetaan arkistomalline",
+ "flow-dialog-cancelconfirm-title": "Oletko varma?",
+ "flow-dialog-cancelconfirm-message": "Oletko varma että haluat peruuttaa ennen kuin olet tallentanut?",
+ "flow-dialog-cancelconfirm-keep": "Jatka muokkaamista",
+ "flow-dialog-cancelconfirm-discard": "Hylkää muutokset",
+ "flow-optin-archive-wikitext": "Siirrä wikitekstisivu tehdäksesi tilaa keskustelupalstalle.",
+ "flow-optin-archive-flow-board": "Siirrä keskustelupalsta tehdäksesi tilaa wikitekstisivulle.",
+ "flow-optin-restore-wikitext": "Palauta arkistoitu wikitekstisivu.",
+ "flow-optin-restore-flow-board": "Palauta arkistoitu keskustelupalsta.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Tervetuloa}} uudelle keskustelusivullesi",
+ "flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|Sinun}} vanhat keskustelusi",
+ "flow-guidedtour-optin-find-old-conversations-description": "Aikaisemmat keskustelut on siirretty arkistosivulle.",
+ "flow-guidedtour-optin-feedback": "Kaipaamme {{GENDER:$1|sinun}} palautettasi!"
}
diff --git a/Flow/i18n/fr.json b/Flow/i18n/fr.json
index bf5d7385..3a0907f2 100644
--- a/Flow/i18n/fr.json
+++ b/Flow/i18n/fr.json
@@ -38,63 +38,92 @@
"TomT0m",
"Thibaut120094",
"J. 'mach' wust",
- "Trizek (WMF)"
+ "Trizek (WMF)",
+ "Nclm",
+ "Nnemo",
+ "PifyZ",
+ "Zebulon84",
+ "Quiddity",
+ "Pols12"
]
},
- "enableflow": "Activer Flow",
- "flow-desc": "Système de gestion du flux de travail",
- "flow-talk-taken-over-comment": "/* Cette page a été convertie en un flux de forum de discussion */",
- "log-name-flow": "Journal d’activité de Flow",
- "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|a supprimé}} une [$4 publication] sur « [[$3|$5]] » sur [[$6]]",
- "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|a rétabli}} une [$4 publication] sur « [[$3|$5]] » sur [[$6]]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|a masqué}} une [$4 publication] sur « [[$3|$5]] » sur [[$6]]",
+ "enablestructureddiscussions": "Activer les discussions structurées",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Arrêter}} de suivre la nouvelle activité sur « $1 »",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Vous}} ne suivez plus la page «&nbsp;$1&nbsp;»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Cela n'affectera pas les différentes rubriques que {{GENDER:$3|vous}} suivez. Vous pouvez suivre [$2 cette page] à tout moment.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Arrêter}} de suivre cette rubrique",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Vous}} ne suivez plus «&nbsp;$1&nbsp;»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Vous}} pouvez suivre [$2 ce sujet] à tout moment.",
+ "flow-desc": "Système de discussion",
+ "flow-talk-taken-over-comment": "/* Cette page a été convertie en discussions structurées */",
+ "log-name-flow": "Journal d’activité des discussions structurées",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|a supprimé}} un [$4 message] sur « [[$3|$5]] » sur [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un message d’un sujet sur [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|a restauré}} un [$4 message] sur « [[$3|$5]] » sur [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|a rétabli}} un message d’un sujet sur [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|a masqué}} un [$4 message] sur « [[$3|$5]] » sur [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un message d’un sujet sur [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|a supprimé}} un [$4 message] sur « [[$3|$5]] » sur [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un message d’un sujet sur [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|a supprimé}} le sujet « [[$3|$5]] » sur [[$6]]",
- "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|a rétabli}} le sujet « [[$3|$5]] » sur [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un sujet sur [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|a restauré}} le sujet « [[$3|$5]] » sur [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|a rétabli}} un sujet sur [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|a masqué}} le sujet « [[$3|$5]] » sur [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un sujet sur [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|a supprimé}} le sujet « [[$3|$5]] » sur [[$6]]",
- "logentry-import-lqt-to-flow-topic": "Le sujet [[$1|$2]] de [[$3]] a été importé depuis LiquidThreads vers Flow.",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|a supprimé}} un sujet sur [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|a marqué}} le sujet « [[$3|$5]] » comme résolu sur [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|a marqué}} un sujet comme résolu sur [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|a rouvert}} le sujet « [[$3|$5]] » sur [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|a réouvert}} un sujet sur [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "Le sujet [[$1|$2]] de [[$3]] a été importé depuis LiquidThreads vers les discussions structurées.",
+ "abusefilter-edit-builder-vars-board-articleid": "ID de la page du tableau des discussions structurées",
+ "abusefilter-edit-builder-vars-board-namespace": "Espace de noms du tableau des discussions structurées",
+ "abusefilter-edit-builder-vars-board-text": "Titre du tableau des discussions structurées",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Titre complet du tableau des discussions structurées",
"flow-user-moderated": "Utilisateur modéré",
- "flow-board-header-browse-topics-link": "Parcourir les discussions",
- "flow-board-header": "À propos de ce tableau",
+ "flow-board-header-browse-topics-link": "Parcourir les sujets",
+ "flow-board-header": "À propos de ce flux de discussion",
+ "flow-board-description-can-not-edit": "Non modifiable",
"flow-board-collapse-description": "Cacher la description",
"flow-board-expand-description": "Afficher la description",
"flow-topic-collapse-siderail": "Lire à pleine largeur",
"flow-topic-expand-siderail": "Lire à largeur fixe",
"flow-edit-header-link": "Modifier la description",
- "flow-post-moderated-toggle-hide-show": "Afficher le commentaire {{GENDER:$1|masqué}} par $2",
+ "flow-post-moderated-toggle-hide-show": "Afficher le commentaire {{GENDER:$1|caché}} par $2",
"flow-post-moderated-toggle-delete-show": "Afficher le commentaire {{GENDER:$1|supprimé}} par $2",
- "flow-post-moderated-toggle-suppress-show": "Afficher le commentaire {{GENDER:$1|supprimé}} par $2",
+ "flow-post-moderated-toggle-suppress-show": "Afficher le commentaire {{GENDER:$1|masqué}} par $2",
"flow-post-moderated-toggle-hide-hide": "Cacher le commentaire {{GENDER:$1|caché}} par $2",
"flow-post-moderated-toggle-delete-hide": "Cacher le commentaire {{GENDER:$1|supprimé}} par $2",
"flow-post-moderated-toggle-suppress-hide": "Cacher le commentaire {{GENDER:$1|masqué}} par $2",
"flow-topic-moderated-reason-prefix": "Motif :",
"flow-hide-post-content": "Ce commentaire a été {{GENDER:$1|caché}} par $1 ([$2 historique])",
- "flow-hide-title-content": "Le sujet a été {{GENDER:$1|caché}} par $1",
+ "flow-hide-title-content": "Ce sujet a été {{GENDER:$1|caché}} par $1",
"flow-hide-header-content": "{{GENDER:$1|Caché}} par $2",
"flow-delete-post-content": "Ce commentaire a été {{GENDER:$1|supprimé}} par $1 ([$2 historique])",
"flow-delete-title-content": "Le sujet a été {{GENDER:$1|supprimé}} par $1",
"flow-delete-header-content": "{{GENDER:$1|Supprimé}} par $2",
- "flow-suppress-post-content": "Ce commentaire a été {{GENDER:$1|supprimé}} par $1 ([$2 historique])",
- "flow-suppress-title-content": "Le sujet a été {{GENDER:$1|supprimé}} par $1",
+ "flow-suppress-post-content": "Ce commentaire a été {{GENDER:$1|masqué}} par $1 ([$2 historique])",
+ "flow-suppress-title-content": "Ce sujet a été {{GENDER:$1|masqué}} par $1",
"flow-suppress-header-content": "{{GENDER:$1|Masqué}} par $2",
- "flow-suppress-usertext": "<em>Nom d’{{GENDER:$1|utilisateur|utilisatrice}} masqué</em>",
+ "flow-suppress-usertext": "<em>Nom d’utilisateur masqué</em>",
"flow-post-actions": "Actions",
"flow-topic-actions": "Actions",
"flow-cancel": "Annuler",
- "flow-skip-summary": "Résumé de modification",
+ "flow-skip-summary": "Passer",
"flow-edit-summary-placeholder": "Décrire brièvement le résultat de cette discussion",
"flow-summary-authored": "Résumé par $1",
"flow-summary-edited": "Résumé modifié en dernier par $1",
"flow-show-change": "Voir les modifications",
"flow-last-modified-by": "{{GENDER:$1|Modifié}} en dernier par $1",
- "flow-stub-post-content": "« En raison d’une erreur technique, ce message n’a pas pu être récupéré. »",
+ "flow-stub-post-content": "<em>En raison d’une erreur technique, ce contenu n’a pas pu être chargé.</em>",
"flow-newtopic-title-placeholder": "Nouveau sujet",
"flow-newtopic-content-placeholder": "Rédigez ici votre message sur « $1 »",
"flow-newtopic-header": "Ajouter un nouveau sujet",
- "flow-newtopic-save": "Ajouter une discussion",
+ "flow-newtopic-save": "Ajouter un sujet",
"flow-newtopic-save-anonymously": "Ajouter un sujet de manière anonyme",
- "flow-newtopic-start-placeholder": "Commencer un nouveau sujet",
+ "flow-newtopic-start-placeholder": "Démarrer un nouveau sujet",
"flow-newtopic-first-heading": "Démarrer un nouveau sujet sur $1",
"flow-summarize-topic-placeholder": "Veuillez résumer le sujet de la discussion",
"flow-reply-topic-placeholder": "{{GENDER:$1|Commenter}} « $2 »",
@@ -107,9 +136,9 @@
"flow-history-action-delete-post": "supprimer",
"flow-history-action-hide-post": "cacher",
"flow-history-action-unsuppress-post": "annuler le masquage",
- "flow-history-action-undelete-post": "rétablir",
- "flow-history-action-unhide-post": "ne plus cacher",
- "flow-history-action-restore-post": "rétablir",
+ "flow-history-action-undelete-post": "restaurer",
+ "flow-history-action-unhide-post": "réafficher",
+ "flow-history-action-restore-post": "restaurer",
"flow-history-action-lock-topic": "résoudre",
"flow-history-action-unlock-topic": "rouvrir",
"flow-post-interaction-separator": "&nbsp;•&#32;",
@@ -122,102 +151,105 @@
"flow-post-action-edit-post": "Modifier",
"flow-post-action-edit-post-submit": "Enregistrer les modifications",
"flow-post-action-edit-post-submit-anonymously": "Enregistrer les modifications de manière anonyme",
- "flow-post-action-unsuppress-post": "Annuler la masquage",
- "flow-post-action-undelete-post": "Rétablir",
- "flow-post-action-unhide-post": "Afficher",
+ "flow-post-action-unsuppress-post": "Annuler le masquage",
+ "flow-post-action-undelete-post": "Restaurer",
+ "flow-post-action-unhide-post": "Réafficher",
"flow-post-action-restore-post": "Restaurer",
"flow-post-action-undo-moderation": "Annuler",
"flow-topic-action-view": "Lien permanent",
"flow-topic-action-watchlist": "Liste de suivi",
"flow-topic-action-edit-title": "Modifier le titre",
"flow-topic-action-history": "Historique",
- "flow-topic-action-hide-topic": "Cacher la discussion",
- "flow-topic-action-delete-topic": "Supprimer la discussion",
- "flow-topic-action-lock-topic": "Marquer comme résolue",
- "flow-topic-action-unlock-topic": "Rouvrir la discussion",
+ "flow-topic-action-hide-topic": "Cacher le sujet",
+ "flow-topic-action-delete-topic": "Supprimer le sujet",
+ "flow-topic-action-lock-topic": "Marquer comme résolu",
+ "flow-topic-action-unlock-topic": "Rouvrir le sujet",
"flow-topic-action-summarize-topic": "Résumer",
"flow-topic-action-resummarize-topic": "Modifier le résumé du sujet",
"flow-topic-action-update-topic-summary": "Mettre à jour le résumé",
"flow-topic-action-suppress-topic": "Masquer le sujet",
- "flow-topic-action-unhide-topic": "Afficher la discussion",
- "flow-topic-action-undelete-topic": "Rétablir la discussion",
- "flow-topic-action-unsuppress-topic": "Annuler le masquage de la discussion",
- "flow-topic-action-restore-topic": "Restaurer la discussion",
+ "flow-topic-action-unhide-topic": "Afficher le sujet",
+ "flow-topic-action-undelete-topic": "Restaurer le sujet",
+ "flow-topic-action-unsuppress-topic": "Annuler le masquage du sujet",
+ "flow-topic-action-restore-topic": "Restaurer le sujet",
"flow-topic-action-undo-moderation": "Annuler",
- "flow-topic-notification-subscribe-title": "Cette discussion a été ajoutée à {{GENDER:$1|votre}} liste de suivi.",
- "flow-topic-notification-subscribe-description": "{{GENDER:$1|Vous}} recevrez des notifications pour toutes les activités sur cette discussion.",
- "flow-board-notification-subscribe-title": "Vous vous êtes {{GENDER:$1|abonné|abonnée}} à ce forum de discussion !",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|Vous}} recevrez une notification quand un nouveau sujet sera créé sur ce forum.",
- "flow-topic-action-watchlist-add": "S'abonner à cette discussion",
+ "flow-topic-notification-subscribe-title": "Ce sujet a été ajouté à {{GENDER:$1|votre}} liste de suivi.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Vous}} recevrez des notifications pour toutes les activités sur ce sujet.",
+ "flow-board-notification-subscribe-title": "Vous vous êtes {{GENDER:$1|abonné|abonnée}} à ce flux de discussion !",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Vous}} recevrez une notification quand un nouveau sujet sera créé sur ce flux de discussion.",
+ "flow-topic-action-watchlist-add": "S’abonner à ce sujet",
"flow-topic-action-watchlist-remove": "Se désabonner",
- "flow-error-allowcreation-no-usedb": "allowCreation nécessite <var>$wgContentHandlerUseDB</var> pour être <code>vrai</code>.",
- "flow-error-allowcreation-already-exists": "La page existe déjà, alors qu'elle ne devrait pas",
- "flow-error-allowcreation-flow-create-board": "L’utilisateur n’a pas l’autorisation « {{int:droit des flux de création de carte}} »",
+ "flow-error-allowcreation-no-usedb": "Activer les discussions structurées sur une page spécifique nécessite que <var>$wgContentHandlerUseDB</var> vaille <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "La page existe déjà sur la cible, donc un tableau de discussions structurées ne peut pas y être déplacé.",
+ "flow-error-allowcreation-flow-create-board": "L’utilisateur n’a pas le droit « {{int:right-flow-create-board}} »",
+ "flow-error-can-not-edit-logged-out": "Vous ne pouvez pas participer actuellement. Vous pouvez essayer en vous connectant.",
+ "flow-error-can-not-edit-logged-in": "Vous ne pouvez pas participer actuellement, parce que vous n’avez pas les droits requis.",
"flow-error-http": "Une erreur s’est produite en communiquant avec le serveur.",
- "flow-error-other": "Une erreur inattendue s’est produite.",
- "flow-error-external": "Une erreur s’est produite.<br />Le message d’erreur reçu était : $1",
- "flow-error-topic-is-locked": "Cette discussion est marquée comme résolue, aucune activité supplémentaire n'est possible.",
- "flow-error-lock-moderated-post": "Vous ne pouvez pas marquer une discussion modérée comme résolue.",
- "flow-error-external-multi": "Des erreurs se sont produites.<br />$1",
+ "flow-error-external": "Une erreur s’est produite. Le message d’erreur reçu était : $1",
+ "flow-error-topic-is-locked": "Ce sujet est marqué comme résolu, aucune activité supplémentaire n’est possible.",
+ "flow-error-lock-moderated-post": "Vous ne pouvez pas marquer un sujet modéré comme résolu.",
"flow-error-missing-content": "Le message n’a aucun contenu. Un contenu est obligatoire pour enregistrer un message.",
"flow-error-missing-summary": "Vous devez saisir un résumé.",
- "flow-error-missing-title": "La discussion n’a pas de titre. Un titre est obligatoire pour enregistrer une discussion.",
- "flow-error-parsoid-failure": "Impossible d'analyser le contenu en raison d'une panne de Parsoid.",
+ "flow-error-missing-title": "Le sujet n’a pas de titre. Un titre est obligatoire pour enregistrer un sujet.",
+ "flow-error-parsoid-failure": "Impossible de transférer le contenu : Erreur en contactant le serveur pour la conversion de wikitexte en HTML. Veuillez vérifier votre connexion Internet ou réessayer ultérieurement si le problème persiste. Si vous obtenez toujours cette erreur, veuillez signaler un bogue.",
+ "flow-error-protected-autoconfirmed-logged-in": "Ce tableau est protégé. Seuls les utilisateurs auto-confirmés peuvent participer. Motif : $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Ce tableau est protégé. Seuls les utilisateurs connectés qui sont auto-confirmés peuvent participer. Motif : $1",
+ "flow-error-protected-sysop-logged-in": "Ce tableau est protégé. Seuls les utilisateurs avec des droits administrateur peuvent participer. Motif : $1",
+ "flow-error-protected-sysop-logged-out": "Ce tableau est protégé. Seuls les utilisateurs connectés avec des droits administrateur peuvent participer. Motif : $1",
+ "flow-error-protected-unknown-reason": "Inconnu",
"flow-error-missing-replyto": "Aucun paramètre « replyTo » n’a été fourni. Ce paramètre est requis pour l’action « répondre ».",
- "flow-error-invalid-replyto": "Le paramètre « replyTo » n’était pas valide. Le message spécifié n’a pas pu être trouvé.",
- "flow-error-delete-failure": "Impossible de supprimer cet élément.",
- "flow-error-hide-failure": "Impossible de cacher cet élément.",
"flow-error-missing-postId": "Aucun paramètre « postId » n’a été fourni. Ce paramètre est obligatoire pour manipuler un message.",
"flow-error-invalid-postId": "Le paramètre « postId » n’était pas valide. Le message spécifié ($1) n’a pas pu être trouvé.",
- "flow-error-restore-failure": "Impossible de restaurer cet élément.",
- "flow-error-invalid-moderation-state": "Une valeur invalide a été fournie pour un paramètre (« moderationState ») de l’API de Flow.",
+ "flow-error-invalid-moderation-state": "Une valeur non valide a été fournie pour un paramètre (« moderationState ») à l’API Discussions Structurées.",
"flow-error-invalid-moderation-reason": "Veuillez indiquer un motif de modération.",
- "flow-error-not-allowed": "Droits insuffisants pour exécuter cette action",
- "flow-error-not-allowed-hide": "Cette discussion a été cachée.",
- "flow-error-not-allowed-reply-to-hide-topic": "Vous ne pouvez pas répondre car cette discussion a été cachée.",
- "flow-error-not-allowed-delete": "Cette discussion a été supprimée.",
- "flow-error-not-allowed-reply-to-delete-topic": "Vous ne pouvez pas répondre car cette discussion a été supprimée.",
- "flow-error-not-allowed-suppress": "Cette discussion a été supprimée.",
- "flow-error-not-allowed-reply-to-suppress-topic": "Vous ne pouvez pas répondre car cette discussion a été supprimée.",
- "flow-error-not-allowed-hide-extract": "Cette discussion a été cachée. Le journal de la discussion est affiché ci-dessous pour référence.",
- "flow-error-not-allowed-delete-extract": "Cette discussion a été supprimée. Le journal de suppression de la discussion est affiché ci-dessous pour référence.",
- "flow-error-not-allowed-reply-to-delete-topic-extract": "Cette discussion a été supprimée. Le journal de suppression est affiché ci-dessous pour référence.",
- "flow-error-not-allowed-suppress-extract": "Cette discussion a été supprimée. Le journal de suppression est affiché ci-dessous :",
- "flow-error-not-allowed-reply-to-suppress-topic-extract": "Vous ne pouvez pas répondre car ce sujet a été supprimé. Le journal de suppression pour ce sujet est fourni ci-dessous à titre de référence.",
- "flow-error-title-too-long": "Les titres des sujets sont limités à $1 {{PLURAL:$1|octet|octets}}.",
- "flow-error-no-existing-workflow": "Cette discussion n’existe pas encore.",
+ "flow-error-not-allowed": "Droits insuffisants pour exécuter cette action.",
+ "flow-error-not-allowed-hide": "Ce sujet a été caché.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Vous ne pouvez pas répondre car ce sujet a été caché.",
+ "flow-error-not-allowed-delete": "Ce sujet a été supprimé.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Vous ne pouvez pas répondre car ce sujet a été supprimé.",
+ "flow-error-not-allowed-suppress": "Ce sujet a été supprimé.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Vous ne pouvez pas répondre car ce sujet a été supprimé.",
+ "flow-error-not-allowed-hide-extract": "Cet sujet a été caché. Le journal du sujet est affiché ci-dessous pour référence.",
+ "flow-error-not-allowed-delete-extract": "Ce sujet a été supprimé. Le journal des suppressions pour le sujet est affiché ci-dessous pour référence.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Ce sujet a été supprimé. Le journal des suppressions pour le sujet est affiché ci-dessous pour référence.",
+ "flow-error-not-allowed-suppress-extract": "Ce sujet a été supprimé. Le journal des suppressions pour le sujet est affiché ci-dessous pour référence.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Vous ne pouvez pas répondre car ce sujet a été masqué. Le journal des masquages pour ce sujet est fourni ci-dessous pour référence.",
+ "flow-error-title-too-long": "Les titres des sujets sont limités à $1 {{PLURAL:$1|octet|octets}}.",
+ "flow-error-no-existing-workflow": "Ce sujet n’existe pas encore.",
"flow-error-not-a-post": "Le titre du sujet ne peut pas être enregistré comme un message.",
"flow-error-missing-header-content": "Vous devez saisir une description.",
"flow-error-missing-prev-revision-identifier": "L’identifiant de révision précédente est absent.",
- "flow-error-prev-revision-mismatch": "Un autre utilisateur vient de modifier cette publication il y a quelques secondes. Êtes-vous {{GENDER:$3|sûr|sûre}} de vouloir écraser cette modification récente ?",
+ "flow-error-prev-revision-mismatch": "Un autre utilisateur vient de modifier ce message il y a quelques secondes. Êtes-vous {{GENDER:$3|sûr|sûre}} de vouloir écraser cette modification récente ?",
"flow-error-prev-revision-does-not-exist": "Impossible de trouver la révision précédente.",
- "flow-error-core-topic-deletion": "Pour supprimer un sujet, utiliser le menu … sur le tableau Flow ou [$1 la page du sujet]. Ne pas visiter directement action=delete pour le sujet.",
+ "flow-error-core-topic-deletion": "Pour supprimer un sujet, utiliser le menu … sur le tableau Discussions Structurées ou [$1 la page du sujet]. Ne pas visiter directement action=delete pour le sujet.",
"flow-error-default": "Une erreur s’est produite.",
- "flow-error-invalid-input": "Une valeur non valide a été fournie lors du chargement du contenu du flux de discussions.",
+ "flow-error-invalid-input": "Une valeur non valide a été fournie lors du chargement du contenu de Discussions Structurées.",
"flow-error-invalid-title": "Un titre de page non valide a été fourni.",
+ "flow-error-invalid-parameter": "Paramètre manquant ou non valide dans l’appel de la méthode",
"flow-error-fail-load-history": "Échec au chargement du contenu de l’historique.",
- "flow-error-missing-revision": "Impossible de trouver une révision pour charger le contenu du flux de discussions.",
- "flow-error-fail-commit": "Échec à l’enregistrement du contenu du flux de discussions.",
+ "flow-error-missing-revision": "Impossible de trouver une révision pour charger le contenu de Discussions Structurées.",
+ "flow-error-fail-commit": "Échec à l’enregistrement du contenu du Discussions Structurées.",
"flow-error-insufficient-permission": "Permission insuffisante pour accéder au contenu.",
- "flow-error-revision-comparison": "Une visualisation des différences ne peut être faite que pour deux révisions appartenant à la même publication.",
+ "flow-error-revision-comparison": "Une visualisation des différences ne peut être faite que pour deux révisions appartenant au même message.",
"flow-error-missing-topic-title": "Impossible de trouver le titre du sujet pour le flux de travail actuel.",
- "flow-error-missing-metadata": "Les métadonnées requises pour cette révision n'ont pas pu être trouvées.",
+ "flow-error-missing-metadata": "Les métadonnées requises pour cette révision n’ont pas pu être trouvées.",
+ "flow-error-different-page": "Le processus de Discussions Structurées n’est pas associé avec cette page.",
"flow-error-fail-load-data": "Échec au chargement des données demandées.",
"flow-error-invalid-workflow": "Impossible de trouver le flux de travail demandé.",
- "flow-error-process-data": "Une erreur s’est produite lors du traitement des données dans votre demande.",
+ "flow-error-process-data": "Une erreur s’est produite lors du traitement des données dans votre requête.",
"flow-error-process-wikitext": "Une erreur s’est produite lors du traitement de la conversion HTML/wikitexte.",
"flow-error-no-index": "Impossible de trouver un index pour effectuer la recherche de données.",
"flow-error-no-render": "L’action spécifiée n’a pas été reconnue.",
"flow-error-no-commit": "L’action spécifiée n’a pas pu être enregistrée.",
- "flow-error-content-too-long": "Le contenu est trop grand. Après expansion, la taille du contenu est limitée à $1 {{PLURAL:$1|octet|octets}}.",
- "flow-error-move-topic": "Déplacer une page de sujet n’est pas supporté pour le moment.",
- "flow-error-move-no-create-permissions": "L’autorisation '{{Int:droit des flux de création de carte}}' est nécessaire pour déplacer un tableau Flow.",
+ "flow-error-content-too-long": "Le contenu est trop grand. Après expansion, la taille du contenu est limitée à $1 {{PLURAL:$1|octet|octets}}.",
+ "flow-error-move-topic": "Renommer une page de sujet n’est pas géré pour le moment.",
"flow-error-invalid-topic-uuid-title": "Mauvais titre",
- "flow-error-invalid-topic-uuid": "Le titre de la page demandée n’est pas valide. Les pages de l’espace Sujet sont créées automatiquement par Flow.",
- "flow-error-unknown-workflow-id-title": "Discussion inconnue",
- "flow-error-unknown-workflow-id": "La discussion demandée n’existe pas.",
+ "flow-error-invalid-topic-uuid": "Le titre de la page demandée n’est pas valide. Les pages de l’espace Sujet sont créées automatiquement par Discussions Structurées.",
+ "flow-error-unknown-workflow-id-title": "Sujet inconnu",
+ "flow-error-unknown-workflow-id": "Le sujet demandé n’existe pas.",
"flow-error-search": "Nous n’avons pas pu terminer votre recherche à cause d’un problème temporaire. Veuillez réessayer plus tard.",
- "flow-edit-header-placeholder": "Décrire l'ensemble de cette discussion",
+ "flow-error-invalid-undelete": "La page n’a pas pu être restaurée car elle contient actuellement un flux de discussion.",
+ "flow-edit-header-placeholder": "Décrire ce flux de discussion",
"flow-edit-header-submit": "Enregistrer la description",
"flow-edit-header-submit-anonymously": "Enregistrer la description de manière anonyme",
"flow-edit-title-submit": "Changer le titre",
@@ -228,33 +260,33 @@
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|A modifié}} un message",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|a ajouté}} un commentaire] sur « $4 » (<em>$5</em>).",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|commentaire|commentaires}}</strong> {{PLURAL:$1|a été ajouté|ont été ajoutés}}.",
- "flow-rev-message-new-post": "$1 {{GENDER:$2|a créé}} la discussion « [$3 $4] ».",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|a créé}} le sujet « [$3 $4] ».",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|A créé}} un nouveau sujet",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|a changé}} le titre de la discussion « $5 » en « [$3 $4] ».",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|a changé}} le titre du sujet « $5 » en « [$3 $4] ».",
"flow-rev-message-create-header": "$1 {{GENDER:$2|a créé}} la description",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|a modifié}} la description",
- "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|a créé}} un résumé de la discussion sur $3.",
- "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|a modifié}} le résumé de la discussion sur $3.",
- "flow-rev-message-hid-post": "$1 {{GENDER:$2|a caché}} un [$4 commentaire] sur « $6 » (<em>$5</em>)..",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|a créé}} un résumé du sujet sur $3.",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|a modifié}} le résumé du sujet sur $3.",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|a caché}} un [$4 commentaire] sur « $6 » (<em>$5</em>)",
"flow-rev-message-deleted-post": "$1 {{GENDER:$2|a supprimé}} un [$4 commentaire] sur « $6 » (<em>$5</em>)..",
"flow-rev-message-suppressed-post": "$1 {{GENDER:$2|a masqué}} un [$4 commentaire] sur « $6 » (<em>$5</em>)..",
"flow-rev-message-restored-post": "$1 {{GENDER:$2|a restauré}} un [$4 commentaire] sur « $6 » (<em>$5</em>)..",
- "flow-rev-message-hid-topic": "$1 {{GENDER:$2|a caché}} la [$4 discussion] « $6 » (<em>$5</em>).",
- "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|a supprimé}} la [$4 discussion] « $6 » (<em>$5</em>).",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|a masqué}} la [$4 discussion] « $6 » (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|a marqué}} la [$4 discussion] $6 comme résolue (<em>$5</em>)",
- "flow-rev-message-lock-topic-reason": "marquée comme résolue",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|a caché}} le [$4 sujet] « $6 » (<em>$5</em>).",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|a supprimé}} le [$4 sujet] « $6 » (<em>$5</em>).",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|a masqué}} le [$4 sujet] « $6 » (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|a marqué}} le [$4 sujet] « $6 » comme résolu (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "marqué comme résolu",
"flow-rev-message-restore-topic-reason": "rouverte",
- "flow-rev-message-restored-topic": "$1 {{GENDER:$2|a restauré}} la [$4 discussion] « $6 » (<em>$5</em>).",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|a restauré}} le [$4 sujet] « $6 » (<em>$5</em>).",
"flow-rc-topic-of-board": "$1 sur $2",
"flow-board-history": "Historique de « $1 »",
- "flow-board-history-empty": "Cet ensemble de discussions n’a actuellement aucun historique.",
- "flow-topic-history": "Historique de la discussion « $1 »",
+ "flow-board-history-empty": "Ce flux de discussion n’a actuellement aucun historique.",
+ "flow-topic-history": "Historique du sujet « $1 »",
"flow-post-history": "Historique du message « Commentaire par {{GENDER:$2|$2}} »",
- "flow-history-last4": "Dernières 4 heures",
+ "flow-history-last4": "4 dernières heures",
"flow-history-day": "Aujourd’hui",
"flow-history-week": "Semaine dernière",
- "flow-history-pages-topic": "Apparaît sur le [$1 forum « $2 »]",
+ "flow-history-pages-topic": "Apparaît sur [$1 le flux de discussion « $2 »]",
"flow-history-pages-post": "Apparaît sur [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 commentaire|$1 commentaires|0={{GENDER:$2|Soyez le premier|Soyez la première}} à laisser un message !}}",
"flow-show-comments-title": "{{PLURAL:$1|Voir le commentaire|Voir les commentaires}}",
@@ -265,274 +297,218 @@
"flow-comment-moderated": "Message soumis à modération",
"flow-last-modified": "Dernière modification : $1",
"flow-workflow": "flux de travail",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|a répondu}} sur '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 et $5 {{PLURAL:$6|autre|autres}} ont {{GENDER:$1|répondu}} sur '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|a répondu}} sur <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 <bdi>$2</bdi>]</span><br /> $1 et {{PLURAL:$5|un autre|$5 autres|100=plus de 100 autres}} ont répondu sur <strong><bdi>$3</bdi></strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 a {{GENDER:$1|modifié}} votre <span class=\"plainlinks\">[$5 message]</span> sur [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 et $5 {{PLURAL:$6|autre|autres}} {{GENDER:$1|ont modifié}} un <span class=\"plainlinks\">[$4 message]</span> sur « $2 », lié à « $3 ».",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|a créé}} une nouvelle discussion sur '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1|250=250+}} {{PLURAL:$1|nouveau sujet|nouveaux sujets}} sur '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 et {{PLURAL:$5|un autre|$5 autres|100=plus de 100 autres}} {{GENDER:$1|ont modifié}} un <span class=\"plainlinks\">[$4 message]</span> sur « $2 », lié à « $3 ».",
+ "notification-header-flow-new-topic-v2": "Nouveau sujet créé sur <strong>$3</strong> : « <strong><bdi>$4</bdi></strong> ».",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Un nouveau sujet|$1 nouveaux sujets|100=Plus de 100 nouveaux sujets}} sur <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Un nouveau sujet a été créé sur <strong>votre page de discussion</strong> : « <strong><bdi>$4</bdi></strong> ».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Un nouveau sujet|$1 nouveaux sujets|100=Plus de 100 nouveaux sujets}} sur <strong>votre page de discussion</strong>.",
+ "notification-header-flow-post-reply": "{{GENDER:$2|$1}} a répondu sur « <strong><bdi>$4</bdi></strong> ».",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Une nouvelle réponse|$1 nouvelles réponses|100=Plus de 100 nouvelles réponses}} sur « <strong><bdi>$3</bdi></strong> ».",
+ "notification-header-flow-post-reply-user-talk": "{{GENDER:$2|$1}} a posté une réponse sur <strong>votre page de discussion</strong> dans « <strong><bdi>$4</bdi></strong> ».",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Une nouvelle réponse|$1 nouvelles réponses|100=Plus de 100 nouvelles réponses}} sur <strong>votre page de discussion</strong> sur « <strong><bdi>$3</bdi></strong> ».",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Votre}} billet sur « <strong><bdi>$1</bdi></strong> » a été modifié.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Votre}} billet sur « <strong><bdi>$1</bdi></strong> » a été modifié à plusieurs reprises.",
+ "notification-header-flow-post-edited-user-talk": "Un billet sur « <strong><bdi>$1</bdi></strong> » a été modifié sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Une note sur « <strong><bdi>$1</bdi></strong> » a été modifiée plusieurs fois sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Le sujet « <strong><bdi>$1</bdi></strong> » a été renommé en « <strong><bdi>$2</bdi></strong> ».",
+ "notification-header-flow-topic-renamed-user-talk": "Le sujet « <strong><bdi>$1</bdi></strong> » a été renommé en « <strong><bdi>$2</bdi></strong> » sur <strong>{{GENDER:$3|votre}} page de discussion</strong>.",
+ "notification-header-flow-summary-edited": "Le résumé pour « <strong><bdi>$1</bdi></strong> » a été mis à jour.",
+ "notification-header-flow-summary-edited-first": "Le sujet « <strong><bdi>$1</bdi></strong> » a été résumé.",
+ "notification-bundle-header-flow-summary-edited": "Le résumé pour « <strong><bdi>$1</bdi></strong> » a été mis à jour plusieurs fois.",
+ "notification-header-flow-summary-edited-user-talk": "Le résumé pour « <strong><bdi>$1</bdi></strong> » a été mis à jour sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Le sujet « <strong><bdi>$1</bdi></strong> » a été résumé sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Le résumé de « <strong><bdi>$1</bdi></strong> » a été mis à jour plusieurs fois sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|a mis à jour}} le résumé sur $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|a mis à jour}} le résumé sur $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 et {{PLURAL:$3|un autre|$3 autres|100=plus de 100 autres}} {{GENDER:$1|ont mis à jour}} le résumé sur $2",
+ "notification-header-flow-mention-post": "{{GENDER:$2|$1}} {{GENDER:$4|vous a mentionné|vous a mentionnée}} dans « <strong><bdi>$5</bdi></strong> ».",
+ "notification-header-flow-mention-header": "{{GENDER:$2|$1}} {{GENDER:$4|vous a mentionné|vous a mentionnée}} dans la description de <strong><bdi>$3</bdi></strong>.",
+ "notification-header-flow-mention-post-summary": "{{GENDER:$2|$1}} {{GENDER:$4|vous a mentionné|vous a mentionnée}} dans « <strong><bdi>$5</bdi></strong> ».",
+ "notification-header-flow-enabled-on-talkpage": "Nouveau système de discussion activé pour <strong>{{GENDER:$2|votre}} page de discussion utilisateur</strong>.",
+ "notification-header-flow-description-edited": "La description de <strong><bdi>$1</bdi></strong> a été modifiée.",
+ "notification-header-flow-description-edited-user-talk": "La description a été modifiée sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-bundle-header-flow-description-edited": "La description de <strong><bdi>$1</bdi></strong> a été modifiée plusieurs fois.",
+ "notification-bundle-header-flow-description-edited-user-talk": "La description a été modifiée plusieurs fois sur <strong>{{GENDER:$2|votre}} page de discussion</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Afficher}} la page",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|a modifié}} la description sur $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|a modifié}} la description sur $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 et {{PLURAL:$3|un autre|$3 autres|100=plus de 100 autres}} {{GENDER:$1|ont modifié}} la description sur $2",
+ "notification-header-flow-topic-resolved": "Le sujet « <strong>$1</strong> » a été résolu.",
+ "notification-header-flow-topic-reopened": "Le sujet « <strong>$1</strong> » a été rouvert.",
+ "notification-header-flow-topic-resolved-user-talk": "Le sujet « <strong>$1</strong> » a été résolu sur <strong>votre page de discussion</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Le sujet « <strong>$1</strong> » a été rouvert sur <strong>votre page de discussion</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Le sujet « <strong>$2</strong> » a été résolu.",
+ "notification-email-batch-body-flow-topic-resolved": "Le sujet « <strong>$2</strong> » a été résolu.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 <bdi>$4</bdi>]</span><br /> {{GENDER:$1|$1}} a créé un nouveau sujet sur <strong><bdi>$3</bdi></strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un nouveau sujet|$1 nouveaux sujets|100=plus de 100 nouveaux sujets}} sur <strong><span class=\"plainlinks\">[$3 <bdi>$2</bdi>]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|a modifié}} le titre de <span class=\"plainlinks\">[$2 $3]</span> en « $4 » sur [[$5|$6]].",
- "flow-notification-mention": "$1 vous a {{GENDER:$5|mentionné|mentionnée|mentionné(e)}} dans {{GENDER:$1|son}} <span class=\"plainlinks\">[$2 message]</span> sur « $3 », lié à « $4 »",
+ "flow-notification-mention": "$1 vous a {{GENDER:$5|mentionné|mentionnée|mentionné(e)}} dans son <span class=\"plainlinks\">[$2 message]</span> sur « $3 », lié à « $4 »",
"flow-notification-link-text-view-post": "Afficher le message",
- "flow-notification-link-text-view-topic": "Afficher la discussion",
+ "flow-notification-link-text-view-topic": "Afficher le sujet",
+ "flow-notification-link-text-view-topics": "Voir les sujets",
"flow-notification-reply-email-subject": "$2 sur $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|a répondu}} à « $2 » sur $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 et $4 {{PLURAL:$5|autre|autres}} {{GENDER:$1|ont répondu}} à votre note concernant « $2 » sur $3",
- "flow-notification-mention-email-subject": "$1 {{GENDER:$3|vous}} {{GENDER:$1|a mentionné|a mentionnée}} sur $2",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|vous}} {{GENDER:$1|a mentionné|a mentionnée}} dans {{GENDER:$1|son}} message sur « $2 », lié à $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 et {{PLURAL:$4|un autre|$4 autres|100=plus de 100 autres}} {{GENDER:$1|ont répondu}} à votre note concernant « $2 » sur $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$3|vous}} {{GENDER:$3|a mentionné|a mentionnée}} sur $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|vous}} a mentionné{{GENDER:$4||e}} dans son message sur « $2 », lié à $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|a modifié}} un message",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|a modifié}} un message sur « $2 », lié à $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 et $4 {{PLURAL:$5|autre|autres}} {{GENDER:$1|ont modifié}} un message sur « $2 », lié à $3",
- "flow-notification-rename-email-subject": "$1 {{GENDER:$1|a renommé}} votre discussion",
- "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|a renommé}} votre discussion « $2 » en « $3 » sur $4",
- "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|a créé}} une nouvelle discussion sur $2",
- "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|a créé}} une nouvelle discussion avec le titre « $2 » sur $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nouveau sujet|$1 nouveaux sujets|250=250+ nouveaux sujets}} sur $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "M’informer quand des actions me concernant ont lieu dans le flux de discussion.",
+ "flow-notification-edit-email-batch-bundle-body": "$1 et {{PLURAL:$4|un autre|$4 autres|100=plus de 100 autres}} {{GENDER:$1|ont modifié}} un message sur « $2 », lié à $3",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|a renommé}} votre sujet",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|a renommé}} votre sujet « $2 » en « $3 » sur $4",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|a créé}} un nouveau sujet sur $2",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|a créé}} un nouveau sujet avec le titre « $2 » sur $3",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1Un nouveau sujet|$1 nouveaux sujets|100=plus de 100 nouveaux sujets}} sur $2",
+ "echo-category-title-flow-discussion": "Discussion structurée",
+ "echo-pref-tooltip-flow-discussion": "M’informer sur l’activité concernant des sujets ou des pages que je suis.",
"flow-link-post": "message",
- "flow-link-topic": "discussion",
+ "flow-link-topic": "sujet",
"flow-link-history": "historique",
"flow-link-post-revision": "version du message",
- "flow-link-topic-revision": "version de la discussion",
+ "flow-link-topic-revision": "version du sujet",
"flow-link-header-revision": "révision de la description",
"flow-link-summary-revision": "résumé de la révision",
"flow-moderation-title-suppress-post": "Masquer le message ?",
"flow-moderation-title-delete-post": "Supprimer le message ?",
"flow-moderation-title-hide-post": "Cacher le message ?",
"flow-moderation-title-unsuppress-post": "Annuler le masquage du message ?",
- "flow-moderation-title-undelete-post": "Rétablir le message ?",
- "flow-moderation-title-unhide-post": "Ne plus cacher le message ?",
+ "flow-moderation-title-undelete-post": "Restaurer le message ?",
+ "flow-moderation-title-unhide-post": "Réafficher le message ?",
"flow-moderation-placeholder-suppress-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous masquez ce message",
"flow-moderation-placeholder-delete-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous supprimez ce message.",
"flow-moderation-placeholder-hide-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous cachez ce message",
"flow-moderation-placeholder-unsuppress-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous annulez le masquage de ce message.",
"flow-moderation-placeholder-undelete-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous annulez la suppression de ce message.",
- "flow-moderation-placeholder-unhide-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous affichez ce message.",
+ "flow-moderation-placeholder-unhide-post": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous réaffichez ce message.",
"flow-moderation-confirm-suppress-post": "Masquer",
"flow-moderation-confirm-delete-post": "Supprimer",
"flow-moderation-confirm-hide-post": "Cacher",
"flow-moderation-confirm-unsuppress-post": "Annuler le masquage",
- "flow-moderation-confirm-undelete-post": "Rétablir",
- "flow-moderation-confirm-unhide-post": "Afficher",
+ "flow-moderation-confirm-undelete-post": "Restaurer",
+ "flow-moderation-confirm-unhide-post": "Réafficher",
"flow-moderation-confirm-suppress-topic": "Supprimer",
"flow-moderation-confirm-delete-topic": "Supprimer",
"flow-moderation-confirm-hide-topic": "Cacher",
"flow-moderation-confirm-unsuppress-topic": "Annuler le masquage",
- "flow-moderation-confirm-undelete-topic": "Rétablir",
- "flow-moderation-confirm-unhide-topic": "Afficher",
- "flow-moderation-confirmation-suppress-post": "Ce message a été supprimé avec succès.\n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons de cette suppression.",
- "flow-moderation-confirmation-delete-post": "Ce message a été supprimé avec succès. \n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons de cette suppression.",
- "flow-moderation-confirmation-hide-post": "Ce message a été caché avec succès. \n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons pour lesquelles il a été caché.",
- "flow-moderation-confirmation-unsuppress-post": "Vous avez bien annulé le masquage du message ci-dessus.",
- "flow-moderation-confirmation-undelete-post": "Vous avez bien rétabli le message ci-dessus.",
- "flow-moderation-confirmation-unhide-post": "Vous avez bien affiché le message ci-dessus.",
- "flow-moderation-confirmation-suppress-topic": "Cette discussion a été masquée.",
- "flow-moderation-confirmation-delete-topic": "Cette discussion a été supprimée.",
- "flow-moderation-confirmation-hide-topic": "Cette discussion a été cachée.",
- "flow-moderation-confirmation-unsuppress-topic": "Vous avez bien annulé le masquage de cette discussion.",
- "flow-moderation-confirmation-undelete-topic": "Vous avez bien rétabli cette discussion.",
- "flow-moderation-confirmation-unhide-topic": "Vous avez bien affiché cette discussion.",
+ "flow-moderation-confirm-undelete-topic": "Restaurer",
+ "flow-moderation-confirm-unhide-topic": "Réafficher",
+ "flow-moderation-confirmation-suppress-post": "Ce message a été masqué. \n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons de ce masquage.",
+ "flow-moderation-confirmation-delete-post": "Ce message a été supprimé. \n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons de cette suppression.",
+ "flow-moderation-confirmation-hide-post": "Ce message a été caché. \n{{GENDER:$2|Pensez}} à expliquer à $1 les raisons pour lesquelles il a été caché.",
+ "flow-moderation-confirmation-unsuppress-post": "Vous avez annulé le masquage du message ci-dessus.",
+ "flow-moderation-confirmation-undelete-post": "Vous avez restauré le message ci-dessus.",
+ "flow-moderation-confirmation-unhide-post": "Vous avez réaffiché le message ci-dessus.",
+ "flow-moderation-confirmation-suppress-topic": "Ce sujet a été masqué.",
+ "flow-moderation-confirmation-delete-topic": "Ce sujet a été supprimé.",
+ "flow-moderation-confirmation-hide-topic": "Ce sujet a été caché.",
+ "flow-moderation-confirmation-unsuppress-topic": "Vous avez annulé le masquage de ce sujet.",
+ "flow-moderation-confirmation-undelete-topic": "Vous avez restauré ce sujet.",
+ "flow-moderation-confirmation-unhide-topic": "Vous avez réaffiché ce sujet.",
"flow-moderation-title-suppress-topic": "Masquer le sujet ?",
- "flow-moderation-title-delete-topic": "Supprimer la discussion ?",
- "flow-moderation-title-hide-topic": "Cacher la discussion ?",
- "flow-moderation-title-unsuppress-topic": "Annuler le masquage de la discussion ?",
- "flow-moderation-title-undelete-topic": "Rétablir la discussion ?",
- "flow-moderation-title-unhide-topic": "Ne plus cacher la discussion ?",
- "flow-moderation-placeholder-suppress-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous masquez cette discussion.",
- "flow-moderation-placeholder-delete-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous supprimez cette discussion.",
- "flow-moderation-placeholder-hide-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous cachez cette discussion.",
- "flow-moderation-placeholder-unsuppress-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous avez annulé le masquage de cette discussion.",
- "flow-moderation-placeholder-undelete-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous avez récupéré cette discussion.",
- "flow-moderation-placeholder-unhide-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous avez affiché cette discussion.",
- "flow-topic-permalink-warning": "Cette discussion a été démarrée sur [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Cette discussion a été démarrée sur la page de discussion de [$2 {{GENDER:$1|$1}}]",
- "flow-revision-permalink-warning-post": "Voici un lien permanent vers une version unique de ce message.\nCette version date de $1.\nVous pouvez voir les [$5 différences depuis la version précédente], ou afficher d’autres versions sur la [$4 page d’historique du message].",
- "flow-revision-permalink-warning-post-first": "Voici un lien permanent vers la première version de ce message.\nVous pouvez afficher des versions ultérieures depuis la [$4 page d’historique du message].",
- "flow-revision-permalink-warning-postsummary": "Voici un lien permanent vers une version unique du résumé de ce message. Cette version date d'$1.\nVous pouvez voir les [$5 différences avec la version précédente], ou afficher d’autres versions sur la [$4 page d’historique du message].",
+ "flow-moderation-title-delete-topic": "Supprimer le sujet ?",
+ "flow-moderation-title-hide-topic": "Cacher le sujet ?",
+ "flow-moderation-title-unsuppress-topic": "Annuler le masquage du sujet ?",
+ "flow-moderation-title-undelete-topic": "Restaurer la discussion ?",
+ "flow-moderation-title-unhide-topic": "Réafficher le sujet ?",
+ "flow-moderation-placeholder-suppress-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous masquez ce sujet.",
+ "flow-moderation-placeholder-delete-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous supprimez ce sujet.",
+ "flow-moderation-placeholder-hide-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous cachez ce sujet.",
+ "flow-moderation-placeholder-unsuppress-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous annulez le masquage de ce sujet.",
+ "flow-moderation-placeholder-undelete-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous restaurez ce sujet.",
+ "flow-moderation-placeholder-unhide-topic": "Veuillez {{GENDER:$3|expliquer}} pourquoi vous réaffichez ce sujet.",
+ "flow-topic-permalink-warning": "Ce sujet a été démarré sur [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Ce sujet a été démarré sur le flux de discussion de [$2 {{GENDER:$1|$1}}]",
+ "flow-revision-permalink-warning-post": "Voici un lien permanent vers une version unique de ce message. \nCette version date de $1. \nVous pouvez voir les [$5 différences depuis la version précédente], ou afficher d’autres versions sur la [$4 page d’historique du message].",
+ "flow-revision-permalink-warning-post-first": "Voici un lien permanent vers la première version de ce message. \nVous pouvez afficher des versions ultérieures depuis la [$4 page d’historique du message].",
+ "flow-revision-permalink-warning-postsummary": "Voici un lien permanent vers une version unique du résumé de ce message. Cette version date d’$1. \nVous pouvez voir les [$5 différences avec la version précédente], ou afficher d’autres versions sur la [$4 page d’historique du message].",
"flow-revision-permalink-warning-postsummary-first": "Voici un lien permanent vers la première version du résumé du message.\nVous pouvez afficher des versions ultérieures sur la [$4 page d’historique du message].",
- "flow-revision-permalink-warning-header": "Voici un lien permanent vers une version unique de la description.\nCette version date de $1. Vous pouvez voir les [$3 différences avec la version précédente], ou afficher les autres versions sur la [$2 page du tableau historique].",
- "flow-revision-permalink-warning-header-first": "Voici un lien permanent vers la première version de la description.\nVous pouvez afficher les versions ultérieures sur la [$2 page du tableau historique].",
- "flow-compare-revisions-revision-header": "Version par {{GENDER:$2|$2}} datée d'$1",
- "flow-compare-revisions-header-post": "Cette page affiche les {{GENDER:$3|modifications}} entre deux versions d’un message par $3 dans la discussion « [$5 $2] » sur [$4 $1].\nVous pouvez voir d’autres versions de ce message sur sa [$6 page d’historique].",
- "flow-compare-revisions-header-postsummary": "Cette page affiche les modifications entre deux versions d’un résumé de message dans le message « [$4 $2] », lié à [$3 $1].\nVous pouvez voir d’autres versions de ce message sur sa [$5 page d’historique].",
- "flow-compare-revisions-header-header": "Cette page affiche les {{GENDER:$2|modifications}} entre deux versions de la description sur [$3 $1].\nVous pouvez afficher les autres versions de la description sur sa [$4 page d’historique].",
- "action-flow-create-board": "créer des tableaux Flow n’importe où",
- "right-flow-create-board": "Créer des tableaux Flow n’importe où",
- "right-flow-hide": "Cacher les sujets et discussions de Flow",
- "right-flow-lock": "Marquer des discussions de Flow comme résolues",
- "right-flow-delete": "Supprimer les discussions et messages de Flow",
- "right-flow-edit-post": "Modifier les messages de Flow par d’autres utilisateurs",
- "right-flow-suppress": "Supprimer les versions de Flow",
+ "flow-revision-permalink-warning-header": "Voici un lien permanent vers une version unique de la description. \nCette version date de $1. Vous pouvez voir les [$3 différences avec la version précédente], ou afficher les autres versions sur [$2 l’historique du flux de discussion].",
+ "flow-revision-permalink-warning-header-first": "Voici un lien permanent vers la première version de la description. \nVous pouvez afficher les versions ultérieures sur [$2 l’historique du flux de discussion].",
+ "flow-compare-revisions-revision-header": "Version par {{GENDER:$2|$2}} datée d’$1",
+ "flow-compare-revisions-header-post": "Cette page affiche les {{GENDER:$3|modifications}} entre deux versions d’un message par $3 dans le sujet « [$5 $2] » sur [$4 $1]. \nVous pouvez voir d’autres versions de ce message sur sa [$6 page d’historique].",
+ "flow-compare-revisions-header-postsummary": "Cette page affiche les modifications entre deux versions du résumé du sujet « [$4 $2] », lié à [$3 $1]. \nVous pouvez voir d’autres versions de ce résumé de sujet sur sa [$5 page d’historique].",
+ "flow-compare-revisions-header-header": "Cette page affiche les {{GENDER:$2|modifications}} entre deux versions de la description sur [$3 $1]. \nVous pouvez afficher les autres versions de la description sur sa [$4 page d’historique].",
+ "action-flow-create-board": "créer des flux de Discussions Structurées n’importe où",
+ "right-flow-create-board": "Créer des flux de Discussions Struturées n’importe où",
+ "right-flow-hide": "Cacher les sujets et messages de Discussions Structurées",
+ "right-flow-lock": "Marquer des sujets de Discussions Structurées comme résolus",
+ "right-flow-delete": "Supprimer les sujets et messages de Discussions Structurées",
+ "right-flow-edit-post": "Modifier les messages de Discussions Structurées publiés par d’autres utilisateurs",
+ "right-flow-suppress": "Masquer les révisions de Discussions Structurées",
"flow-terms-of-use-new-topic": "En cliquant sur « {{int:flow-newtopic-save}} », vous acceptez les conditions d’utilisation de ce wiki.",
"flow-terms-of-use-reply": "En cliquant sur « {{int:flow-reply-link}} », vous acceptez les conditions d’utilisation de ce wiki.",
"flow-terms-of-use-edit": "En enregistrant vos modifications, vous acceptez les conditions d’utilisation de ce wiki.",
- "flow-anon-warning": "Vous n’êtes pas connecté. Pour que vos modifications soient associées à votre nom d'utilisateur plutôt qu'à votre adresse IP, vous pouvez [$1 vous connecter] ou [$2 créer un compte].",
- "flow-cancel-warning": "Vous avez saisi du texte dans ce formulaire. Confirmez-vous l'abandon de la saisie ?",
- "flow-topic-first-heading": "Discussion sur $1",
+ "flow-anon-warning": "Vous n’êtes pas connecté(e). Pour que vos modifications soient associées à votre nom d’utilisateur plutôt qu’à votre adresse IP, vous pouvez [$1 vous connecter] ou [$2 créer un compte].",
+ "flow-cancel-warning": "Vous avez saisi du texte dans ce formulaire. Confirmez-vous l’abandon de la saisie ?",
+ "flow-topic-first-heading": "Sujet sur $1",
"flow-topic-html-title": "$1 sur $2",
- "flow-topic-count": "Discussions ($1)",
+ "flow-topic-count": "Sujets ($1)",
"flow-load-more": "Charger davantage",
- "flow-no-more-fwd": "Il n’y a pas de discussions plus anciennes",
- "flow-newest-topics": "Discussions les plus récentes",
- "flow-recent-topics": "Discussions actives récemment",
- "flow-sorting-tooltip-newest": "{{GENDER:|Vous}} lisez les discussions les plus récentes d’abord. Cliquez pour plus d’options de tri.",
- "flow-sorting-tooltip-recent": "{{GENDER:|Vous}} lisez actuellement les sujets les plus récemment actifs en premier. Cliquez pour avoir plus d’options de tri.",
- "flow-toggle-small-topics": "Basculer vers l'affichage des titres uniquement",
- "flow-toggle-topics": "Basculer vers l'affichage des discussions sans leur détail",
- "flow-toggle-topics-posts": "Basculer vers l'affichage des discussions et de leur détail",
+ "flow-no-more-fwd": "Il n’y a pas de sujets plus anciens",
+ "flow-newest-topics": "Sujets les plus récents",
+ "flow-recent-topics": "Sujets actifs récemment",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Vous}} lisez les sujets les plus récents d’abord. Cliquez pour plus d’options de tri.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Vous}} lisez actuellement les sujets les plus récemment actifs en premier. Cliquez pour plus d’options de tri.",
+ "flow-toggle-small-topics": "Basculer vers l’affichage des titres uniquement",
+ "flow-toggle-topics": "Basculer vers l’affichage des sujets sans leur détail",
+ "flow-toggle-topics-posts": "Basculer vers l’affichage des sujets et des messages",
"flow-terms-of-use-summarize": "En cliquant sur « {{int:flow-topic-action-update-topic-summary}} », vous acceptez les conditions d’utilisation de ce wiki.",
"flow-terms-of-use-lock-topic": "En cliquant sur « {{int:flow-topic-action-lock-topic}} », vous acceptez les conditions d’utilisation de ce wiki.",
- "flow-terms-of-use-unlock-topic": "En cliquant sur « {{int:flow-topic-action-unlock-topic}} », vous acceptez les conditions d’utilisation de ce wiki.",
- "flow-whatlinkshere-post": "à partir d'un [$1 message]",
+ "flow-terms-of-use-unlock-topic": "En cliquant sur « {{int:flow-topic-action-unlock-topic}} », vous acceptez les conditions d’utilisation de ce wiki.",
+ "flow-whatlinkshere-post": "à partir d’un [$1 message]",
"flow-whatlinkshere-header": "à partir de la [$1 description]",
"flow-whatlinkshere-post-summary": "à partir du [$1 sommaire]",
- "flow": "Flow",
- "flow-special-desc": "Cette page spéciale redirige vers un flux de travail Flow ou une note Flow d’après un UUID.",
+ "structureddiscussions": "Discussions structurées",
+ "flow-special-desc": "Cette page spéciale redirige vers un flux de travail de Discussions Structurées ou une note de Discussions Structurées d’après un UUID.",
"flow-special-type": "Type",
"flow-special-type-post": "Message",
"flow-special-type-workflow": "Flux de travail",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Impossible de trouver un contenu correspondant au type et à l’UUID.",
- "flow-special-enableflow-legend": "Activer Flow sur une nouvelle page",
- "flow-special-enableflow-page": "Page sur laquelle activer Flow",
- "flow-special-enableflow-header": "Description initiale du tableau Flow (wikitexte)",
- "flow-special-enableflow-board-already-exists": "Il y a déjà un tableau Flow sur [[$1]].",
+ "flow-special-enableflow-legend": "Activer Discussions Structurées sur une nouvelle page",
+ "flow-special-enableflow-page": "Page sur laquelle activer les discussions structurées",
+ "flow-special-enableflow-header": "Description initiale du flux de Discussions Structurées (wikitexte)",
+ "flow-special-enableflow-board-already-exists": "Il y a déjà un flux de Discussions Structurées sur [[$1]].",
"flow-special-enableflow-invalid-title": "Un titre invalide de page a été fourni.",
- "flow-special-enableflow-board-creation-not-allowed": "Vous n'êtes pas autorisé à créer un tableau Flux à [[:$1]].",
- "flow-special-enableflow-page-is-liquidthreads": "Il existe une page LiquidThreads à [[:$1]].",
- "flow-special-enableflow-confirmation": "Vous avez bien créé un tableau Flow sur [[$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "Vous n’êtes pas {{GENDER:|autorisé|autorisée}} à créer un flux de Discussions Structurées sur [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Il existe une page LiquidThreads sur [[:$1]].",
+ "flow-special-enableflow-confirmation": "Vous avez créé un flux de Discussions Structurées sur [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archive %d\n%s/Archive%d\n%s/archive %d\n%s/archive%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Flow Archive %d\n%s/FlowArchive%d",
- "flow-spam-confirmedit-form": "Veuillez confirmer que vous êtes humain en résolvant le captcha ci-dessous : $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Structured Discussions Archive %d\n%s/Structured DiscussionsArchive%d",
+ "flow-spam-confirmedit-form": "Veuillez confirmer que vous êtes un humain en résolvant le CAPTCHA ci-dessous : $1",
+ "flow-spam-confirmedit-using-failure": "Il y a eu une erreur technique avec le CAPTCHA. Si vous ne pouvez pas soumettre vos modifications, veuillez copier votre texte, recharger, et réessayer.",
"flow-embedding-unsupported": "Les discussions ne peuvent pas encore être incorporées.",
- "mw-ui-unsubmitted-confirm": "Vous avez des modifications non enregistrées sur cette page. Êtes-vous sûr de vouloir la quitter et perdre ainsi votre travail ?",
- "flow-post-undo-hide": "annuler masquage",
- "flow-post-undo-delete": "annuler suppression",
- "flow-post-undo-suppress": "annuler la suppression",
- "flow-topic-undo-hide": "annuler le masquage",
- "flow-topic-undo-delete": "annuler la suppression",
- "flow-topic-undo-suppress": "annuler la suppression",
- "flow-importer-lqt-moved-thread-template": "Ébauche de fil LQT déplacée et convertie pour Flow",
- "flow-importer-lqt-moved-thread-template-content": "Cette note de {{{author}}} a été déplacée le {{{date}}}. Vous pouvez la trouver à [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "Page LQT convertie en Flow",
+ "mw-ui-unsubmitted-confirm": "Vous avez des modifications non enregistrées sur cette page. Êtes-vous sûr(e) de vouloir la quitter et perdre ainsi votre travail ?",
+ "flow-post-undo-hide": "réaffichage",
+ "flow-post-undo-delete": "annulation de la suppression",
+ "flow-post-undo-suppress": "annulation du masquage",
+ "flow-topic-undo-hide": "réaffichage",
+ "flow-topic-undo-delete": "annulation de la suppression",
+ "flow-topic-undo-suppress": "annulation du masquage",
+ "flow-importer-lqt-moved-thread-template": "Ébauche de fil LQT déplacée et convertie pour Discussions Structurées",
+ "flow-importer-lqt-moved-thread-template-content": "Ce message de {{{author}}} a été déplacé le {{{date}}}. Vous pouvez le trouver sur [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "Page LQT convertie en Discussions Structurées",
"flow-importer-lqt-converted-template-content": "L’historique de la page précédente a été archivé pour des raisons de sauvegarde dans <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> le {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-lqt-converted-archive-template": "Archive pour la page LQT convertie",
- "flow-importer-lqt-converted-archive-template-content": "Cette page est une page LiquidThreads archivée. '''Ne pas modifier le contenu de cette page'''. Veuillez mettre tout commentaire supplémentaire dans la [[{{{from}}}|page de discussion actuelle]].",
- "flow-importer-wt-converted-template": "Page de discussion wikitexte convertie en Flow",
+ "flow-importer-lqt-converted-archive-template-content": "Cette page est une page LiquidThreads archivée. <strong>Ne pas modifier le contenu de cette page</strong>. Veuillez mettre tout commentaire supplémentaire dans la [[{{{from}}}|page de discussion actuelle]].",
+ "flow-importer-wt-converted-template": "Page de discussion wikitexte convertie en Discussions Structurées",
"flow-importer-wt-converted-template-content": "La discussion précédente a été archivée dans <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> le {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-wt-converted-archive-template": "Archive pour la page de discussion wikitexte convertie",
- "flow-importer-wt-converted-archive-template-content": "Cette page est une archive. '''Ne pas modifier le contenu de cette page'''. Veuillez mettre tout commentaire supplémentaire sur la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|page de discussion actuelle]].",
- "flow-importer-lqt-suppressed-user-template": "Le poste LQT a été importé avec un utilisateur supprimé.",
- "flow-importer-lqt-suppressed-user-template-content": "Cette révision a été importée depuis LiquidThreads avec un utilisateur supprimé. Elle a été réaffectée à l’utilisateur courant.",
+ "flow-importer-wt-converted-archive-template-content": "Cette page est une archive. <strong>Ne pas modifier le contenu de cette page</strong>. Veuillez mettre tout commentaire supplémentaire sur la [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|page de discussion actuelle]].",
+ "flow-importer-lqt-suppressed-user-template": "Le message LQT a été importé avec un utilisateur masqué",
+ "flow-importer-lqt-suppressed-user-template-content": "Cette révision a été importée depuis LiquidThreads avec un utilisateur masqué. Elle a été réaffectée à l’utilisateur courant.",
"flow-importer-lqt-different-author-signature-template": "Message LQT importé avec une signature utilisateur différente.",
- "flow-importer-lqt-different-author-signature-template-content": "''Cette note a été publiée par [[User:{{{authorUser}}}|{{{authorUser}}}]], mais signée avec [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Permet d’effectuer des actions sur les pages Flow.",
- "apihelp-flow-param-submodule": "Le sous-module Flow à invoquer.",
- "apihelp-flow-param-page": "La page sur laquelle effectuer l’action.",
- "apihelp-flow-example-1": "Modifier la description de « [[Talk:Sandbox]] »",
- "apihelp-flow+close-open-topic-description": "Rendu désuet par [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "État dans lequel mettre le sujet, \"verrouiller\" ou \"déverrouiller\".",
- "apihelp-flow+close-open-topic-param-reason": "Motif pour verrouiller ou déverrouiller ce sujet.",
- "apihelp-flow+edit-header-description": "Modifie la description d’un tableau.",
- "apihelp-flow+edit-header-param-prev_revision": "ID de la révision actuelle de la description, pour vérifier qu'il n'existe aucun conflit de modification.",
- "apihelp-flow+edit-header-param-content": "Le contenu de la description.",
- "apihelp-flow+edit-header-param-format": "Le format de la description (wikitexte|html)",
- "apihelp-flow+edit-header-example-1": "Modifier la description de [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Modifier le contenu d’un message.",
- "apihelp-flow+edit-post-param-postId": "ID du message.",
- "apihelp-flow+edit-post-param-prev_revision": "ID de la révision actuelle du message, pour vérifier les conflits de modification.",
- "apihelp-flow+edit-post-param-content": "Contenu pour le message.",
- "apihelp-flow+edit-post-param-format": "Format du contenu du message (wikitexte|html)",
- "apihelp-flow+edit-post-example-1": "Modifier un message dans [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Modifie un titre de sujet.",
- "apihelp-flow+edit-title-param-prev_revision": "ID de la révision actuelle du titre, pour vérifier les conflits de modification.",
- "apihelp-flow+edit-title-param-content": "Contenu pour le titre.",
- "apihelp-flow+edit-title-example-1": "Modifier le titre de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Modifie le contenu du résumé d’un sujet.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "ID de la révision du résumé de sujet courant, s’il existe, pour vérifier les conflits de modification.",
- "apihelp-flow+edit-topic-summary-param-summary": "Contenu du résumé.",
- "apihelp-flow+edit-topic-summary-param-format": "Format du résumé (wikitexte|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Modifier le résumé de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Verrouiller ou déverrouiller un sujet Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "État dans lequel mettre le sujet, soit <kbd>verrouillé</kbd>, soit <kbd>déverrouillé</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Motif pour verrouiller ou déverrouiller le sujet. Note : le bloc Flow utilise « Marqué comme résolu » ici, et met des informations complémentaires facultatives dans le résumé.",
- "apihelp-flow+lock-topic-example-1": "Verrouiller [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Modère un message Flow",
- "apihelp-flow+moderate-post-param-moderationState": "À quel niveau modérer.",
- "apihelp-flow+moderate-post-param-reason": "Motif de modération.",
- "apihelp-flow+moderate-post-param-postId": "ID du message à modérer.",
- "apihelp-flow+moderate-post-example-1": "Supprimer un message du sujet [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Modère un sujet Flow",
- "apihelp-flow+moderate-topic-param-moderationState": "À quel niveau modérer.",
- "apihelp-flow+moderate-topic-param-reason": "Raison de la modération.",
- "apihelp-flow+moderate-topic-example-1": "Supprimer le sujet [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Crée un nouveau sujet Flow sur un flux de travail.",
- "apihelp-flow+new-topic-param-topic": "Texte du titre du nouveau sujet.",
- "apihelp-flow+new-topic-param-content": "Contenu pour la réponse initiale du sujet.",
- "apihelp-flow+new-topic-param-format": "Format de la nouvelle réponse initiale au sujet (wikitexte|html)",
- "apihelp-flow+new-topic-example-1": "Créer un nouveau sujet sur [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Répond à un message.",
- "apihelp-flow+reply-param-replyTo": "ID du message auquel répondre.",
- "apihelp-flow+reply-param-content": "Contenu pour le nouveau message.",
- "apihelp-flow+reply-param-format": "Format du nouveau message (wikitexte|html)",
- "apihelp-flow+reply-example-1": "Répondre à un message sur [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Format dans lequel renvoyer le contenu.",
- "apihelp-flow+view-header-description": "Afficher la description d'un tableau.",
- "apihelp-flow+view-header-param-revId": "Charger cette révision, au lieu de la plus récente.",
- "apihelp-flow+view-header-example-1": "Récupérer la description de [[Talk:Sandbox]] en wikitexte",
- "apihelp-flow+view-post-description": "Afficher un message",
- "apihelp-flow+view-post-param-postId": "ID du message à voir.",
- "apihelp-flow+view-post-param-format": "Format dans lequel renvoyer le contenu.",
- "apihelp-flow+view-post-example-1": "Récupérer le contenu du message sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
- "apihelp-flow+view-post-history-description": "Afficher l’historique des révisions d’une note.",
- "apihelp-flow+view-post-history-param-postId": "ID de la note pour laquelle afficher l’historique de révision.",
- "apihelp-flow+view-post-history-param-format": "Format dans lequel renvoyer le contenu.",
- "apihelp-flow+view-post-history-example-1": "Récupérer les révisions d’une note sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
- "apihelp-flow+view-topic-description": "Afficher un sujet.",
- "apihelp-flow+view-topic-example-1": "Afficher [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Afficher l’historique des révisions d’un sujet.",
- "apihelp-flow+view-topic-history-param-format": "Format dans lequel renvoyer le contenu.",
- "apihelp-flow+view-topic-history-example-1": "Afficher els révisions des notes sur [[Topic:S2tycnas4hcucw8w]] en wikitexte",
- "apihelp-flow+view-topic-summary-description": "Afficher un résumé du sujet.",
- "apihelp-flow+view-topic-summary-param-format": "Format dans lequel renvoyer le contenu.",
- "apihelp-flow+view-topic-summary-param-revId": "Charger cette révision, plutôt que la plus récente.",
- "apihelp-flow+view-topic-summary-example-1": "Afficher le résumé pour [[Topic:S2tycnas4hcucw8w]] en wikitexte",
- "apihelp-flow+view-topiclist-description": "Afficher une liste de sujets.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Direction de tri des sujets.",
- "apihelp-flow+view-topiclist-param-sortby": "Option de tri des sujets, soit <kbd>mis à jour</kbd> (rangé selon la date de mise à jour du sujet), ou <kbd>plus récent</kbd> (ordonné selon la date de création du sujet)..",
- "apihelp-flow+view-topiclist-param-savesortby": "Sauvegarder l'option de tri, si elle est définie.",
- "apihelp-flow+view-topiclist-param-offset-id": "Valeur de décalage (au format UUID) auquel démarrer la récupération des sujets ; utilisé seulement avec le tri <kbd>plus récent</kbd>.",
- "apihelp-flow+view-topiclist-param-offset": "Valeur du décalage (un timestamp de la mise à jour du sujet, au format <code>TS_MW</code>(<code>AAAAMMJJHHMMSS</code>)) auquel démarrer la récupération des sujets; utilisé seulement avec le tri <kbd>mise à jour</kbd>.",
- "apihelp-flow+view-topiclist-param-limit": "Nombre de sujets à récupérer.",
- "apihelp-flow+view-topiclist-example-1": "Lister les sujets sur [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Convertir le texte entre wikitexte et HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Format du contenu à convertir.",
- "apihelp-flow-parsoid-utils-param-to": "Format dans lequel convertir le contenu.",
- "apihelp-flow-parsoid-utils-param-content": "Contenu à convertir.",
- "apihelp-flow-parsoid-utils-param-title": "Titre de la page. Impossible à utiliser avec $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID de la page. Impossible à utiliser avec $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Convertir le wikicode <nowiki>'''lorem''' ''blah''</nowiki> en HTML",
- "apihelp-query+flowinfo-description": "Obtenir les informations Flow de base sur une page.",
- "apihelp-query+flowinfo-example-1": "Récupérer les informations Flow sur [[Talk:Sandbox]], [[Main Page]], et [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Récupérer les informations nécessaires pour annuler les modifications de la description.",
- "apihelp-flow+undo-edit-header-param-startId": "Id de révision auquel démarrer l’annulation.",
- "apihelp-flow+undo-edit-header-param-endId": "Id de révision auquel arrêter l’annulation.",
- "apihelp-flow+undo-edit-header-example-1": "Récupérer l’information sur l’annulation d’une modification de description sur [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Récupérer l’information nécessaire pour annuler la modification du message.",
- "apihelp-flow+undo-edit-post-param-postId": "Id du message à annuler.",
- "apihelp-flow+undo-edit-post-param-startId": "Id de révision auquel commencer l’annulation.",
- "apihelp-flow+undo-edit-post-param-endId": "Id de révision auquel arrêter l’annulation.",
- "apihelp-flow+undo-edit-post-example-1": "Récupérer l’information sur l’annulation d’une modification de message dans un sujet spécifique.",
- "apihelp-flow+undo-edit-topic-summary-description": "Récupérer l’information nécessaire pour annuler les modifications de résumé de sujet.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Id de révision auquel commencer l’annulation.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Id de révision auquel arrêter l’annulation.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Récupérer les informations sur l’annulation de la modification d’un résumé de sujet dans un sujet spécifique",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Cette note a été publiée par [[User:{{{authorUser}}}|{{{authorUser}}}]], mais signée avec [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Modifié",
"flow-edited-by": "Modifié par $1",
- "flow-lqt-redirect-reason": "Redirection de message LiquidThreads retiré vers son message converti en Flow",
- "flow-talk-conversion-move-reason": "Conversion de la discussion en wikicode de $1 vers Flow",
- "flow-talk-conversion-archive-edit-reason": "Conversion d’une discussion en wikicode vers Flow",
+ "flow-edited-by-header": "Description de la carte éditée par $1",
+ "flow-edited-by-topic-title": "Le titre de la rubrique édité par $1",
+ "flow-lqt-redirect-reason": "Redirection de message LiquidThreads retiré vers son message converti en Discussions Structurées",
+ "flow-talk-conversion-move-reason": "Conversion de la discussion en wikitexte de $1 vers Discussions Structurées",
+ "flow-talk-conversion-archive-edit-reason": "Conversion d’une discussion en wikitexte vers Discussions Structurées",
"flow-previous-diff": "← Modification plus ancienne",
"flow-next-diff": "Modification plus récente →",
"flow-undo": "annuler",
@@ -541,44 +517,50 @@
"flow-undo-edit-header": "Modification de la description",
"flow-undo-edit-topic-summary": "Modification du résumé du sujet",
"flow-undo-edit-post": "Modification d’un message",
- "flow-undo-edit-content": "La modification peut être annulée. Veuillez contrôler la comparaison ci-dessous pour vérifier que c’est ce que vous voulez faire, puis enregistrer les modifications ci-dessous pour terminer l’annulation de cette modification.",
+ "flow-undo-edit-content": "La modification peut être annulée. Veuillez contrôler la comparaison ci-dessous pour vérifier que c’est ce que vous voulez faire, puis enregistrer les modifications ci-dessous pour terminer l’annulation de la modification.",
"flow-undo-edit-failure": "La modification ne peut pas être annulée à cause de modifications intermédiaires en conflit.",
- "group-flow-bot": "Bots pour Flow",
- "group-flow-bot-member": "Robot Flow",
- "grouppage-flow-bot": "Project:Flow bots",
+ "group-flow-bot": "Robots pour Discussions Structurées",
+ "group-flow-bot-member": "Robot des discussions structurées",
+ "grouppage-flow-bot": "Project:Structured Discussions bots",
"flow-ve-mention-context-item-label": "Mentionner",
"flow-ve-mention-inspector-title": "Mentionner",
"flow-ve-mention-inspector-remove-label": "Supprimer",
"flow-ve-mention-placeholder": "Nom d’utilisateur",
"flow-ve-mention-tool-title": "Mentionner un utilisateur",
"flow-ve-mention-template-title": "Mention",
- "flow-ve-mention-inspector-invalid-user": "Le nom d’utilisateur '$1' n’est pas enregistré.",
- "flow-wikitext-editor-help": "$1 wikitexte.",
- "flow-wikitext-editor-help-and-preview": "Votre modification $1 wikitexte et vous pouvez avoir un $2 à tout moment.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|utilise le marquage]]",
+ "flow-ve-mention-inspector-invalid-user": "Le nom d’utilisateur « $1 » n’est pas enregistré.",
+ "flow-wikitext-editor-help": "$1 wikicode.",
+ "flow-wikitext-editor-help-and-preview": "Votre modification $1 wikicode et vous pouvez avoir un $2 à tout moment.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|utilise le balisage]]",
"flow-wikitext-editor-help-preview-the-result": "aperçu du résultat",
- "flow-wikitext-switch-editor-tooltip": "Basculer vers l'éditeur visuel",
- "flow-ve-switch-editor-tool-title": "Basculer vers l'éditeur de wikicode",
+ "flow-wikitext-switch-editor-tooltip": "Basculer vers l’éditeur visuel",
+ "flow-ve-switch-editor-tool-title": "Basculer vers l’éditeur de wikicode",
"flow-mark-revision-patrolled-link-text": "Marquer cette page comme relue",
"flow-mark-revision-patrolled-link-title": "Marquer cette page comme relue",
"flow-mark-diff-patrolled-link-text": "Marquer comme relue",
"flow-mark-diff-patrolled-link-title": "Marquer comme relue",
- "flow-talk-page-beta-feature-message": "Flux sur la discussion de l'utilisateur",
- "flow-talk-page-beta-feature-description": "Active un nouveau système de discussion structurée sur votre page de discussion utilisateur. Flow simplifie les discussions de la page avec des emplacements clairs pour écrire et répondre, et permet des notifications au niveau de la conversation. Les discussions existantes en wikitexte sont déplacées dans une archive. Cette fonctionnalité n’est pas activée automatiquement ; les utilisateurs devront l’activer séparément. Désactiver cette fonctionnalité déplacera le tableau Flow dans une sous-page et désarchivera la page de discussion précédente.",
- "flow-notification-link-text-enabled-on-talkpage": "Afficher la page de discussion de l'utilisateur",
- "flow-notification-enabled-on-talkpage-title": "Nouveau système de discussion activé pour votre page de discussion utilisateur<br /><small>Disponible à [[$1]]</small>",
+ "flow-talk-page-beta-feature-message": "Les discussions structurées sur la page de discussion de l’utilisateur",
+ "flow-talk-page-beta-feature-description": "Active un nouveau système de discussion structurée sur {{GENDER:|votre}} page de discussion utilisateur. Discussions Structurées simplifie les discussions de la page avec des emplacements clairs pour écrire et répondre, et permet des notifications au niveau de la conversation. Cette fonctionnalité n’est pas activée automatiquement ; les utilisateurs devront l’activer séparément.<br /><br />Les discussions existantes en wikitexte sont déplacées dans une archive. Désactiver cette fonctionnalité déplacera le flux de discussion Discussions Structurées dans une sous-page et désarchivera la page de discussion précédente. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|En savoir plus sur l’activation]].",
+ "flow-notification-link-text-enabled-on-talkpage": "Afficher ma page de discussion",
+ "flow-notification-enabled-on-talkpage-title": "Nouveau système de discussion activé pour {{GENDER:$1|votre}} page de discussion utilisateur<br /><small>Disponible sur [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Nouveau système de discussion sur $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, le nouveau système de discussion de wiki, a été activé sur votre page de discussion sur {{SITENAME}}. Vous pouvez obtenir plus d’information, donner votre avis ou désactiver le nouveau système n’importe quand depuis la section fonctionnalités bêta dans vos préférences.",
- "flow-beta-feature-add-archive-template-edit-summary": "Ajouter le modèle d'archive",
- "flow-beta-feature-remove-archive-template-edit-summary": "Supprimer le modèle d'archive",
- "flow-dialog-cancelconfirm-title": "Êtes-vous sûr ?",
- "flow-dialog-cancelconfirm-message": "Êtes-vous sûr de vouloir annuler sans enregistrer d’abord ?",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Discussions Structurées, le nouveau système de discussion de wiki, a été activé sur {{GENDER:$1|votre}} page de discussion sur {{SITENAME}}. Vous pouvez obtenir plus d’information, donner votre avis ou désactiver le nouveau système n’importe quand depuis la section Fonctionnalités bêta dans {{GENDER:$1|vos}} préférences.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Ajouter le modèle d’archive",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Supprimer le modèle d’archive",
+ "flow-dialog-cancelconfirm-title": "Êtes-vous {{GENDER:|sûr|sûre}} ?",
+ "flow-dialog-cancelconfirm-message": "Êtes-vous {{GENDER:|sûr|sûre}} de vouloir annuler sans enregistrer d’abord ?",
"flow-dialog-cancelconfirm-keep": "Continuer à modifier",
"flow-dialog-cancelconfirm-discard": "Annuler les modifications",
+ "flow-optin-archive-wikitext": "Renommage de la page en wikitexte pour permettre son remplacement par un flux de discussion.",
+ "flow-optin-archive-flow-board": "Renommage du flux de discussion pour permettre son remplacement par une page en wikitexte.",
+ "flow-optin-restore-wikitext": "Restauration de la page en wikitexte archivée.",
+ "flow-optin-restore-flow-board": "Restauration du flux de discussion archivé.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Bienvenue}} dans {{GENDER:$1|votre}} nouvelle page de discussion utilisateur",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Votre}} page de discussion est l’endroit où les autres éditeurs peuvent {{GENDER:$1|vous}} contacter. Avec Flow, il est plus facile de démarrer de nouveaux sujets et garder trace des conversations.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Votre}} page de discussion est l’endroit où les autres éditeurs peuvent {{GENDER:$1|vous}} contacter. Avec les discussions structurées, il est plus facile de démarrer de nouveaux sujets et de garder trace des conversations.",
"flow-guidedtour-optin-find-old-conversations": "Trouver {{GENDER:$1|vos}} anciennes conversations",
"flow-guidedtour-optin-find-old-conversations-description": "Les conversations précédentes ont été déplacées dans une page d’archive.",
- "flow-guidedtour-optin-feedback": "Donnez nous {{GENDER:$1|votre}} avis !",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Vous}} pouvez obtenir plus d’information, donner votre avis, ou désactiver le nouveau système n’importe quand depuis la section Fonctionnalités bêta."
+ "flow-guidedtour-optin-feedback": "Donnez-nous {{GENDER:$1|votre}} avis !",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Vous}} pouvez obtenir plus d’information, donner votre avis, ou désactiver le nouveau système n’importe quand depuis la section Fonctionnalités bêta.",
+ "flow-action-not-page": "L’objet associé à la page est une instance de la mauvaise classe",
+ "flow-action-wrong-title-content-model": "La page est gérée par les Discussions Structurées, mais la classe du titre indique que le modèle de contenu est '$1'. C'est un problème de configuration ou un état incohérent. Par exemple, il pourrait s'agir d'une page qui ne soit pas une Discussion Structurée dans l'espace de noms des Discussions Structurées, avec <code>rev_content_model</code> non renseigné."
}
diff --git a/Flow/i18n/gl.json b/Flow/i18n/gl.json
index 6b0e8ec0..5532106e 100644
--- a/Flow/i18n/gl.json
+++ b/Flow/i18n/gl.json
@@ -3,25 +3,52 @@
"authors": [
"Toliño",
"Elisardojm",
- "Banjo"
+ "Banjo",
+ "Nnemo",
+ "Quiddity",
+ "Macofe",
+ "Matiia"
]
},
- "enableflow": "Activar Flow",
- "flow-desc": "Sistema de xestión do fluxo de traballo",
- "flow-talk-taken-over-comment": "/* Esta páxina foi convertida a un taboleiro de discusión de Flow */",
- "log-name-flow": "Rexistro de actividade de Flow",
+ "enablestructureddiscussions": "Activar as conversas estruturadas",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Parar}} de vixiar nova actividade en \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Xa}} non está a vixiar a páxina \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Isto non afectará ós temas individuais que {{GENDER:$3|está}} a vixiar. Pode vixiar [$2 esta páxina] en calquera momento.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Parar}} de vixiar este tema",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Xa}} non está a vixiar \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Pode}} vixiar [$2 este tema] en calquera momento.",
+ "flow-desc": "Sistema de conversa",
+ "flow-talk-taken-over-comment": "/* Esta páxina foi convertida a un taboleiro de conversas estruturadas */",
+ "log-name-flow": "Rexistro de actividade das conversas estruturadas",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|borrou}} unha [$4 publicación] sobre «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} unha mensaxe nun tema en [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurou}} unha [$4 publicación] sobre «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} unha mensaxe nun tema en [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|eliminou}} unha [$4 publicación] sobre «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} unha mensaxe nun tema en [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|borrou}} unha [$4 publicación] en «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} unha mensaxe nun tema en [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|borrou}} o tema «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} un tema en [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restaurou}} o tema «[[$3|$5]]» en [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} un tema en [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|eliminou}} o tema «[[$3|$5]]» en [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} un tema en [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|borrou}} o tema \"[[$3|$5]]\" en [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] en [[$3]] importouse a Flow desde LiquidThreads",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} un tema en [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marcou}} o tema \"[[$3|$5]]\" como resolto en [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|marcou}} un tema como resolto en [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reabríu}} o tema \"[[$3|$5]]\" en [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|reabriu}} un tema en [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] en [[$3]] importouse a conversas estruturadas desde LiquidThreads",
+ "abusefilter-edit-builder-vars-board-articleid": "ID da páxina do taboleiro das conversas estruturadas",
+ "abusefilter-edit-builder-vars-board-namespace": "Espazo de nomes do taboleiro das conversas estruturadas",
+ "abusefilter-edit-builder-vars-board-text": "Título do taboleiro das conversas estruturadas",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Título completo do taboleiro das conversas estruturadas",
"flow-user-moderated": "Usuario moderado",
"flow-board-header-browse-topics-link": "Explorar os temas",
"flow-board-header": "Acerca deste panel de conversa",
+ "flow-board-description-can-not-edit": "Non modificable",
"flow-board-collapse-description": "Agochar a descrición",
"flow-board-expand-description": "Mostrar descrición",
"flow-topic-collapse-siderail": "Ler en largo completo",
@@ -47,19 +74,19 @@
"flow-post-actions": "Accións",
"flow-topic-actions": "Accións",
"flow-cancel": "Cancelar",
- "flow-skip-summary": "Saltar o resumo",
+ "flow-skip-summary": "Omitir",
"flow-edit-summary-placeholder": "Describa brevemente o resultado desta conversa",
"flow-summary-authored": "Resumo por $1",
"flow-summary-edited": "Resumo {{GENDER:$1|editado}} por última vez por $1",
"flow-show-change": "Mostrar os cambios",
"flow-last-modified-by": "Última modificación por $1",
- "flow-stub-post-content": "''Non se puido recuperar esta publicación a causa dun erro técnico.''",
- "flow-newtopic-title-placeholder": "Novo fío",
+ "flow-stub-post-content": "<em>Non se puido recuperar este contido a causa dun erro técnico.</em>",
+ "flow-newtopic-title-placeholder": "Novo tema",
"flow-newtopic-content-placeholder": "Publicar unha mensaxe nova en \"$1\"",
- "flow-newtopic-header": "Engadir un novo fío",
+ "flow-newtopic-header": "Engadir un novo tema",
"flow-newtopic-save": "Nova sección",
"flow-newtopic-save-anonymously": "Engadir tema anonimamente",
- "flow-newtopic-start-placeholder": "Iniciar un novo fío",
+ "flow-newtopic-start-placeholder": "Iniciar un novo tema",
"flow-newtopic-first-heading": "Iniciar un tema novo en $1",
"flow-summarize-topic-placeholder": "Por favor resuma esta conversa",
"flow-reply-topic-placeholder": "{{GENDER:$1|Comentario}} en \"$2\"",
@@ -114,27 +141,28 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Recibirá}} unha notificación cando se cree un tema novo neste panel de conversa.",
"flow-topic-action-watchlist-add": "Subscribirse a este tema",
"flow-topic-action-watchlist-remove": "Cancelar a subscrición",
- "flow-error-allowcreation-no-usedb": "allowCreation require que <var>$wgContentHandlerUseDB</var> sexa <code>true</code> (certo).",
- "flow-error-allowcreation-already-exists": "Xa existe a páxina pero precisábase que non existise",
+ "flow-error-allowcreation-no-usedb": "Habilitar conversas estruturadas nunha páxina específica require que <var>$wgContentHandlerUseDB</var> sexa <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Xa existe a páxina no destino, polo que o taboleiro de conversas estruturadas non pode moverse alí.",
"flow-error-allowcreation-flow-create-board": "O usuario non ten o permiso de \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Non pode participar actualmente. Pode intentalo conectándose.",
+ "flow-error-can-not-edit-logged-in": "Non pode participar actualmente porque non ten os permisos requiridos.",
"flow-error-http": "Produciuse un erro ao contactar co servidor.",
- "flow-error-other": "Produciuse un erro inesperado.",
- "flow-error-external": "Produciuse un erro.<br />A mensaxe de erro recibida foi: $1",
+ "flow-error-external": "Produciuse un erro. A mensaxe de erro recibida foi: $1",
"flow-error-topic-is-locked": "O tema está resolto, polo que calquera actividade adicional non é posible.",
"flow-error-lock-moderated-post": "Non pode marcar unha publicación moderada como resolta.",
- "flow-error-external-multi": "Producíronse varios erros.<br />$1",
"flow-error-missing-content": "A mensaxe non ten contido. O contido é obrigatorio para gardar unha mensaxe.",
"flow-error-missing-summary": "Debe indicar un resumo.",
- "flow-error-missing-title": "O fío non ten título. O título é obrigatorio para gardar un fío.",
- "flow-error-parsoid-failure": "Non é posible analizar o contido debido a un fallo do Parsoid.",
+ "flow-error-missing-title": "O tema non ten título. O título é obrigatorio para gardar un tema.",
+ "flow-error-parsoid-failure": "Non é posible transferir o contido: Erro contactando co servidor para a conversión de texto wiki e HTML. Por favor, revise a súa conexión a Internet ou volva a intentalo máis tarde se o problema persiste. Se aínda ve este erro por favor informe dun problema",
+ "flow-error-protected-autoconfirmed-logged-in": "Este taboleiro está protexido. Só usuarios autoconfirmados poden participar. Razón: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Este taboleiro está protexido. Só usuarios conectados que estean autoconfirmados poden participar. Razón: $1",
+ "flow-error-protected-sysop-logged-in": "Este taboleiro está protexido. Só usuarios con permiso de administrador poden participar. Razón: $1",
+ "flow-error-protected-sysop-logged-out": "Este taboleiro está protexido. Só usuarios conectados con permisos de administrador poden participar. Razón: $1",
+ "flow-error-protected-unknown-reason": "Descoñecida",
"flow-error-missing-replyto": "Non se achegou ningún parámetro de resposta. Este parámetro é obrigatorio para a acción \"responder\".",
- "flow-error-invalid-replyto": "O parámetro de resposta non é válido. Non se puido atopar a mensaxe especificada.",
- "flow-error-delete-failure": "Houbo un erro ao borrar este elemento.",
- "flow-error-hide-failure": "Houbo un erro ao agochar este elemento.",
"flow-error-missing-postId": "Non se achegou ningún parámetro de identificación. Este parámetro é obrigatorio para a manipular unha mensaxe.",
"flow-error-invalid-postId": "O parámetro de identificación non é válido. Non se puido atopar a mensaxe especificada ($1).",
- "flow-error-restore-failure": "Houbo un erro ao restaurar este elemento.",
- "flow-error-invalid-moderation-state": "Enviouse un valor de parámetro ('moderationState') non válido á API de Flow.",
+ "flow-error-invalid-moderation-state": "Enviouse un valor de parámetro ('moderationState') non válido á API de conversas estruturadas.",
"flow-error-invalid-moderation-reason": "Por favor, achegue o motivo para a moderación.",
"flow-error-not-allowed": "Permisos insuficientes para executar esta acción.",
"flow-error-not-allowed-hide": "Este tema foi agochado.",
@@ -155,17 +183,19 @@
"flow-error-missing-prev-revision-identifier": "O identificador da revisión anterior non se atopa.",
"flow-error-prev-revision-mismatch": "Outro usuario acaba de editar esta publicación fai algúns segundos. Está {{GENDER:$3|seguro|segura}} que desexa sobrescribir o cambio recente?",
"flow-error-prev-revision-does-not-exist": "A revisión anterior non puido ser atopada.",
- "flow-error-core-topic-deletion": "Para borrar un tema, use ...menu no taboleiro Flow ou [$1 páxina do tema]. Non visite directamente action=delete para o tema.",
+ "flow-error-core-topic-deletion": "Para borrar un tema, use ...menu no taboleiro de conversas estruturadas ou [$1 páxina do tema]. Non visite directamente action=delete para o tema.",
"flow-error-default": "Houbo un erro.",
- "flow-error-invalid-input": "Proporcionouse un valor de carga de contido de Flow non válido.",
+ "flow-error-invalid-input": "Proporcionouse un valor de carga de contido de conversas estruturadas non válido.",
"flow-error-invalid-title": "Proporcionouse un título de páxina non válido.",
+ "flow-error-invalid-parameter": "Parámetro ausente ou incorrecto na chamada ó método",
"flow-error-fail-load-history": "Erro ó cargar o contido do histórico.",
- "flow-error-missing-revision": "Non se puido atopar unha revisión para cargar o contido do Flow.",
- "flow-error-fail-commit": "Erro ó gardar o contido do Flow.",
+ "flow-error-missing-revision": "Non se puido atopar unha revisión para cargar o contido das conversas estruturadas.",
+ "flow-error-fail-commit": "Erro ó gardar o contido das conversas estruturadas.",
"flow-error-insufficient-permission": "Permisos insuficientes para acceder ó contido.",
"flow-error-revision-comparison": "A operación de comparación só pode facerse entre dúas revisións que pertencen a unha mesma publicación.",
"flow-error-missing-topic-title": "Non se puido atopar o título do tema para o fluxo de traballo actual.",
"flow-error-missing-metadata": "Non foi posible atopar os metadatos necesarios para esta revisión.",
+ "flow-error-different-page": "O proceso de conversas estruturadas non está asociado con esta páxina.",
"flow-error-fail-load-data": "Erro ó cargar os datos solicitados.",
"flow-error-invalid-workflow": "Non se puido atopar o fluxo de traballo solicitado.",
"flow-error-process-data": "Houbo un erro ó procesar os datos da súa solicitude.",
@@ -175,12 +205,12 @@
"flow-error-no-commit": "No se puido gardar a acción especificada.",
"flow-error-content-too-long": "O contido é demasiado longo. O contido despois da súa expansión está limitado a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-move-topic": "Polo momento non é posible mover os temas.",
- "flow-error-move-no-create-permissions": "É necesario o permiso \"{{int:right-flow-create-board}}\" para mover un taboleiro de Flow.",
"flow-error-invalid-topic-uuid-title": "Título incorrecto",
- "flow-error-invalid-topic-uuid": "O título da páxina solicitada é inválido. As páxinas no espazo de nomes Tema son creadas automaticamente polo Flow.",
+ "flow-error-invalid-topic-uuid": "O título da páxina solicitada é inválido. As páxinas no espazo de nomes Tema son creadas automaticamente polas conversas estruturadas.",
"flow-error-unknown-workflow-id-title": "Tema descoñecido",
"flow-error-unknown-workflow-id": "El tema solicitado non existe.",
"flow-error-search": "Non puidemos completar a súa procura debido a un problema temporal. Inténteo de novo máis tarde.",
+ "flow-error-invalid-undelete": "A páxina non pode restaurarse porque actualmente hai unha conversa en curso.",
"flow-edit-header-placeholder": "Describa este panel de conversa",
"flow-edit-header-submit": "Gardar a descrición",
"flow-edit-header-submit-anonymously": "Gardar descrición anonimamente",
@@ -192,9 +222,9 @@
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Editou}} unha mensaxe",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|comentou}}] en \"$4\" (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|comentario|comentarios}}</strong>\n{{PLURAL:$1|foi engadido|foron engadidos}}",
- "flow-rev-message-new-post": "$1 {{GENDER:$2|creou}} o fío \"[$3 $4]\"",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|creou}} o tema \"[$3 $4]\"",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Creou}} un novo tema",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|cambiou}} o título do fío de \"$5\" a \"[$3 $4]\"",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|cambiou}} o título do tema de \"$5\" a \"[$3 $4]\"",
"flow-rev-message-create-header": "$1 {{GENDER:$2|creou}} a descrición",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|editou}} a descrición",
"flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|creou}} o resumo do tema en $3",
@@ -206,14 +236,14 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|agochou}} o [$4 tema] \"$6\" (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|eliminou}} o [$4 tema] \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suprimiu}} o [$4 tema] \"$6\" (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|bloqueou}} o [$4 tema] $6 coma resolto (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|bloqueou}} o [$4 tema] \"$6\" coma resolto (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "marcado como resolto",
"flow-rev-message-restore-topic-reason": "reaberto",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restaurou}} o [$4 tema] \"$6\" (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 en $2",
"flow-board-history": "Historial de \"$1\"",
"flow-board-history-empty": "Este panel de conversa non ten historial actualmente.",
- "flow-topic-history": "Historial do fío \"$1\"",
+ "flow-topic-history": "Historial do tema \"$1\"",
"flow-post-history": "Historial da mensaxe «Comentario por {{GENDER:$2|$2}}»",
"flow-history-last4": "Últimas 4 horas",
"flow-history-day": "Hoxe",
@@ -229,33 +259,75 @@
"flow-comment-moderated": "Comentario moderado",
"flow-last-modified": "Última modificación $1",
"flow-workflow": "fluxo de traballo",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 \"$2\"]</span><br />$1 {{GENDER:$1|respondeu}} en \"'''$4'''\".",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 \"$2\"]</span><br />$1 e {{PLURAL:$6|outra persoa|outras $5 persoas}} {{GENDER:$1|responderon}} en \"'''$3'''\".",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 \"$2\"]</span><br />$1 {{GENDER:$1|respondeu}} en \"<strong>$4</strong>\".",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 \"$2\"]</span><br />$1 e {{PLURAL:$5|outra persoa|outras $5 persoas|100=máis de 99 persoas}} {{GENDER:$1|responderon}} en <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|editou}} a súa <span class=\"plainlinks\">[$5 mensaxe]</span> en [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 e {{PLURAL:$6|outra persoa|outras $5 persoas}} {{GENDER:$1|responderon}} á <span class=\"plainlinks\">[$4 mensaxe]</span> de \"$2\" en \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 \"$4\"]</span><br />$1 {{GENDER:$1|creou}} un novo tema en \"'''$3'''\".",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 novo tema|$1 novos temas|250=+250 novos temas}} en '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 e {{PLURAL:$5|outra persoa|outras $5 persoas|100=máis de 99 persoas}} {{GENDER:$1|responderon}} á <span class=\"plainlinks\">[$4 mensaxe]</span> de \"$2\" en \"$3\".",
+ "notification-header-flow-new-topic-v2": "Novo tema creado en <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Un novo tema|$1 novos temas|100=Máis de 100 novos temas}} en <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Creouse un novo tema na súa <strong>páxina de conversa</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Un novo tema|$1 novos temas|100=Máis de 100 novos temas}} na <strong>súa páxina de conversa</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|respondeu}} en \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Unha nova resposta|$1 novas respostas|100=Máis de 100 novas respostas}} en \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|respondeu}} na súa <strong>páxina de conversa</strong> en \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Unha nova resposta|$1 novas respostas|100=Máis de 100 novas respostas}} na súa <strong>páxina de conversa</strong> en \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "A {{GENDER:$2|súa}} mensaxe en \"<strong>$1</strong>\" foi editada.",
+ "notification-bundle-header-flow-post-edited-v2": "A {{GENDER:$2|súa}} mensaxe en \"<strong>$1</strong>\" foi editada varias veces.",
+ "notification-header-flow-post-edited-user-talk": "Un comentario en \"<strong>$1</strong>\" foi modificado na {{GENDER:$2|súa}} <strong>páxina de conversa</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Un comentario en \"<strong>$1</strong>\" foi modificado varias veces na <strong>{{GENDER:$2|súa}} páxina de conversa</strong>.",
+ "notification-header-flow-topic-renamed-v2": "O tema \"<strong>$1</strong>\" cambiou de nome a \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "O tema \"<strong>$1</strong>\" foi renomeado a \"<strong>$2</strong>\" na <strong>{{GENDER:$3|súa}} páxina de conversa</strong>.",
+ "notification-header-flow-summary-edited": "Actualizouse o resumo de \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-first": "Resumiuse o tema \"<strong>$1</strong>\".",
+ "notification-bundle-header-flow-summary-edited": "Actualizouse varias veces o resumo de \"<strong>$1</strong>\".",
+ "notification-header-flow-summary-edited-user-talk": "Actualizouse o resumo de \"<strong>$1</strong>\" <strong>{{GENDER:$2|na túa}} páxina de conversa</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Resumiuse o tema \"</strong>$1</strong>\" <strong>{{GENDER:$2|na túa}} páxina de conversa</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Actualizouse varias veces o resumo de \"<strong>$1</strong>\" <strong>{{GENDER:$2|na túa}} páxina de conversa</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|actualizou}} o resumo en $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|actualizou}} o resumo en $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "\n$1 e {{PLURAL:$3|outro máis|$3 máis|100=máis de 99 máis}} {{GENDER:$1|actualizaron}} o resumo en $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|mencionou}}{{GENDER:$4|no|na}} en \"<strong>$5<strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|mencionou}}{{GENDER:$4|no|na}} na descrición de <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mencionou}}{{GENDER:$4|no|na}} en \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "O novo sistema de conversa habilitouse na <strong>{{GENDER:$2|súa}} páxina de conversa de usuario</strong>.",
+ "notification-header-flow-description-edited": "Editouse a descrición de <strong>$1</strong>.",
+ "notification-header-flow-description-edited-user-talk": "A descrición foi editada na <strong>{{GENDER:$2|súa}} páxina de conversa</strong>.",
+ "notification-bundle-header-flow-description-edited": "A descrición de <strong>$1</strong> foi editada varias veces.",
+ "notification-bundle-header-flow-description-edited-user-talk": "A descrición foi editada varias veces na <strong>{{GENDER:$2|súa}} páxina de conversa</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Ver}} páxina",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$2|editou}} a descrición en $2",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$2|editou}} a descrición en $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 e {{PLURAL:$3|outro|$3 outros|100=máis de 99 máis}} {{GENDER:$1|editaron}} a descrición en $2",
+ "notification-header-flow-topic-resolved": "O tema \"<strong>$1</strong>\" foi resolto.",
+ "notification-header-flow-topic-reopened": "Reabriuse o tema \"<strong>$1</strong>\".",
+ "notification-header-flow-topic-resolved-user-talk": "O tema \"<strong>$1</strong>\" foi resolto na <strong>súa páxina de conversa</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "O tema \"<strong>$1</strong>\" foi reaberto na <strong>súa páxina de conversa</strong>.",
+ "notification-email-subject-flow-topic-resolved": "O tema \"<strong>$2</strong>\" foi resolto.",
+ "notification-email-batch-body-flow-topic-resolved": "O tema \"<strong>$2</strong>\" foi resolto.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 \"$4\"]</span><br />$1 {{GENDER:$1|creou}} un novo tema en <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un novo tema|$1 novos temas|100=Máis de 99 novos temas}} en <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|cambiou}} o título de \"<span class=\"plainlinks\">[$2 $3]</span>\" a \"$4\" en \"[[$5|$6]]\".",
"flow-notification-mention": "$1 {{GENDER:$5|fíxolle}} {{GENDER:$1|unha mención}} na {{GENDER:$1|súa}} <span class=\"plainlinks\">[$2 mensaxe]</span> de \"$3\" en \"$4\".",
"flow-notification-link-text-view-post": "Ver a mensaxe",
- "flow-notification-link-text-view-topic": "Ver o fío",
+ "flow-notification-link-text-view-topic": "Ver o tema",
+ "flow-notification-link-text-view-topics": "Ver temas",
"flow-notification-reply-email-subject": "\"$2\" en \"$3\"",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondeu}} a \"$2\" en $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$5|outra persoa|outras $4 persoas}} {{GENDER:$1|responderon}} a \"$2\" en $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$4|outra persoa|outras $4 persoas|100=máis de 99 persoas}} {{GENDER:$1|responderon}} a \"$2\" en $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$3|fíxolle}} {{GENDER:$1|unha mención}} en $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|fíxolle}} {{GENDER:$1|unha mención}} na {{GENDER:$1|súa}} mensaxe de \"$2\" en $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|editou}} unha mensaxe",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|editou}} unha mensaxe de \"$2\" en $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$5|outra persoa|outras $4 persoas}} {{GENDER:$1|editaron}} unha mensaxe de \"$2\" en $3.",
- "flow-notification-rename-email-subject": "$1 {{GENDER:$1|renomeou}} o seu fío",
- "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renomeou}} o seu fío \"$2\" a \"$3\" en $4",
- "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|creou}} un novo fío en $2",
- "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|creou}} un novo fío co título \"$2\" en \"$3\"",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 novo tema|$1 novos temas|250=+250 novos temas}} en $2",
- "echo-category-title-flow-discussion": "Fluxo",
- "echo-pref-tooltip-flow-discussion": "Notificádeme cando sucedan accións relacionadas comigo no fluxo.",
+ "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$4|outra persoa|outras $4 persoas|100=máis de 99 persoas}} {{GENDER:$1|editaron}} unha mensaxe de \"$2\" en $3.",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|renomeou}} o seu tema",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renomeou}} o seu tema \"$2\" a \"$3\" en $4",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|creou}} un novo tema en $2",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|creou}} un novo tema co título \"$2\" en \"$3\"",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Un novo tema|$1 novos temas|100=Máis de 99 novos temas}} en $2",
+ "echo-category-title-flow-discussion": "Conversas estruturadas",
+ "echo-pref-tooltip-flow-discussion": "Notificarme de cambios en temas ou páxinas que estea seguindo.",
"flow-link-post": "mensaxe",
- "flow-link-topic": "fío",
+ "flow-link-topic": "tema",
"flow-link-history": "historial",
"flow-link-post-revision": "revisión da mensaxe",
"flow-link-topic-revision": "revisión do tema",
@@ -285,18 +357,18 @@
"flow-moderation-confirm-unsuppress-topic": "Restaurar",
"flow-moderation-confirm-undelete-topic": "Restaurar",
"flow-moderation-confirm-unhide-topic": "Descubrir",
- "flow-moderation-confirmation-suppress-post": "A mensaxe foi suprimida con éxito.\n{{GENDER:$2|Considere}} enviar un comentario $1 sobre esta entrada.",
- "flow-moderation-confirmation-delete-post": "A mensaxe foi eliminada con éxito.\n{{GENDER:$2|Considere}} enviar un comentario $1 sobre esta entrada.",
- "flow-moderation-confirmation-hide-post": "A mensaxe agochouse correctamente.\n{{GENDER:$2|Considere}} enviar un comentario a $1 sobre esta entrada.",
- "flow-moderation-confirmation-unsuppress-post": "Retirou a supresión da mensaxe de arriba correctamente.",
- "flow-moderation-confirmation-undelete-post": "Restaura a mensaxe de arriba correctamente.",
- "flow-moderation-confirmation-unhide-post": "Mostrou de novo a mensaxe de arriba correctamente.",
+ "flow-moderation-confirmation-suppress-post": "A mensaxe foi suprimida.\n{{GENDER:$2|Considere}} enviar un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-delete-post": "A mensaxe foi eliminada.\n{{GENDER:$2|Considere}} enviar un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-hide-post": "A mensaxe agochouse.\n{{GENDER:$2|Considere}} enviar un comentario a $1 sobre esta entrada.",
+ "flow-moderation-confirmation-unsuppress-post": "Retirou a supresión da mensaxe de arriba.",
+ "flow-moderation-confirmation-undelete-post": "Restaurou a mensaxe de arriba.",
+ "flow-moderation-confirmation-unhide-post": "Mostrou de novo a mensaxe de arriba.",
"flow-moderation-confirmation-suppress-topic": "Este tema foi eliminado.",
"flow-moderation-confirmation-delete-topic": "Este tema foi borrado.",
"flow-moderation-confirmation-hide-topic": "Este tema foi agochado.",
- "flow-moderation-confirmation-unsuppress-topic": "Retirou a supresión do tema de arriba correctamente.",
- "flow-moderation-confirmation-undelete-topic": "Restaurou tema de arriba correctamente.",
- "flow-moderation-confirmation-unhide-topic": "Mostrou de novo o tema de arriba correctamente.",
+ "flow-moderation-confirmation-unsuppress-topic": "Retirou a supresión do tema.",
+ "flow-moderation-confirmation-undelete-topic": "Restaurou este tema.",
+ "flow-moderation-confirmation-unhide-topic": "Mostrou de novo este tema.",
"flow-moderation-title-suppress-topic": "Suprimir o tema?",
"flow-moderation-title-delete-topic": "Borrar o tema?",
"flow-moderation-title-hide-topic": "Quere agochar o tema?",
@@ -319,15 +391,15 @@
"flow-revision-permalink-warning-header-first": "Esta é unha ligazón permanente á primeira versión da descrición. \nPode ver outras versións na [$2 páxina do historial do taboleiro].",
"flow-compare-revisions-revision-header": "Versión de {{GENDER:$2|$2}} do $1",
"flow-compare-revisions-header-post": "Esta páxina mostra as {{GENDER:$3|modificacións}} entre dúas versións dunha mensaxe de $3, no tema \"[$5 $2]\" ee [$4 $1]. Pode ver outras versións desta mensaxe no seu [$6 historial].",
- "flow-compare-revisions-header-postsummary": "Esta páxina mostra as modificacións entre dúas versión de resumos da mensaxe \"[$4 $2]\" en [$3 $1]. \nPode ver outras versións desta mensaxe no seu [$5 historial].",
+ "flow-compare-revisions-header-postsummary": "Esta páxina mostra as modificacións entre dúas versións do resumo do tema \"[$4 $2]\" en [$3 $1].\nPode ver outras versións deste resumo do tema no seu [$5 historial].",
"flow-compare-revisions-header-header": "Esta páxina mostra as {{GENDER:$2|modificacións}} entre dúas versións da descrición en [$3 $1].\nPode ver outras versións da descrición no seu [$4 historial].",
- "action-flow-create-board": "crear taboleiros de conversa Flow en calquera sitio",
- "right-flow-create-board": "Crear taboleiros de conversa Flow en calquera sitio",
- "right-flow-hide": "Agochar temas e mensaxes de Flow",
- "right-flow-lock": "Marcar temas de Flow coma resoltos",
- "right-flow-delete": "Borrar temas e mensaxes de Flow",
- "right-flow-edit-post": "Editar mensaxes de Flow doutros usuarios",
- "right-flow-suppress": "Suprimir revisións de Flow",
+ "action-flow-create-board": "crear taboleiros de conversas estruturadas en calquera sitio",
+ "right-flow-create-board": "Crear taboleiros de conversas estruturadas en calquera sitio",
+ "right-flow-hide": "Agochar temas e mensaxes de conversas estruturadas",
+ "right-flow-lock": "Marcar temas de conversas estruturadas coma resoltos",
+ "right-flow-delete": "Borrar temas e mensaxes de conversas estruturadas",
+ "right-flow-edit-post": "Editar mensaxes de conversas estruturadas doutros usuarios",
+ "right-flow-suppress": "Suprimir revisións de conversas estruturadas",
"flow-terms-of-use-new-topic": "Ao premer no botón \"{{int:flow-newtopic-save}}\", acepta os termos de uso deste wiki.",
"flow-terms-of-use-reply": "Ao premer no botón \"{{int:flow-reply-link}}\", acepta os termos de uso deste wiki.",
"flow-terms-of-use-edit": "Ao gardar os seus cambios, acepta os termos de uso deste wiki.",
@@ -351,24 +423,25 @@
"flow-whatlinkshere-post": "desde unha [$1 mensaxe]",
"flow-whatlinkshere-header": "desde a [$1 descrición]",
"flow-whatlinkshere-post-summary": "do [$1 resumo]",
- "flow": "Flow",
- "flow-special-desc": "Esta páxina especial redirecciona a un fluxo de traballo de Flow ou a unha mensaxe de Flow dado un UUID.",
+ "structureddiscussions": "Conversas estruturadas",
+ "flow-special-desc": "Esta páxina especial redirecciona a un fluxo de traballo de conversas estruturadas ou a unha mensaxe de conversas estruturadas dado un UUID.",
"flow-special-type": "Tipo",
"flow-special-type-post": "Publicar",
"flow-special-type-workflow": "Fluxo de traballo",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Non foi posible atopar o contido asociado ó tipo e ó UUID.",
- "flow-special-enableflow-legend": "Activar Flow nunha páxina nova",
- "flow-special-enableflow-page": "Páxina donde se activará Flow",
- "flow-special-enableflow-header": "Descrición inicial do taboleiro de conversa Flow (wikitexto)",
- "flow-special-enableflow-board-already-exists": "Xa existe un taboleiro de mensaxes Flow en [[$1]]",
+ "flow-special-enableflow-legend": "Activar conversas estruturadas nunha páxina nova",
+ "flow-special-enableflow-page": "Páxina onde se activarán as conversas estruturadas",
+ "flow-special-enableflow-header": "Descrición inicial do taboleiro de conversas estruturadas (wikitexto)",
+ "flow-special-enableflow-board-already-exists": "Xa existe un taboleiro de conversas estruturadas en [[$1]]",
"flow-special-enableflow-invalid-title": "Proporcionouse un título de páxina non válido",
- "flow-special-enableflow-board-creation-not-allowed": "Non ten permiso para crear un taboleiro Flow en [[:$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "Non ten permiso para crear un taboleiro conversas estruturadas en [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Hai unha páxina LiquidThreads en [[:$1]].",
- "flow-special-enableflow-confirmation": "Creou un novo taboleiro de conversa de Flow en [[$1]].",
+ "flow-special-enableflow-confirmation": "Creou un taboleiro conversas estruturadas en [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Arquivo %d\n%s/Arquivo%d\n%s/arquivo %d\n%s/arquivo%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Ficheiro Flow %d\n%s/FicheiroFlow%d",
- "flow-spam-confirmedit-form": "Confirme que é un humano resolvendo o seguinte captha: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Ficheiro conversas estruturadas %d\n%s/Ficheiroconversas estruturadas%d",
+ "flow-spam-confirmedit-form": "Por favor, confirme que é un humano resolvendo o seguinte CAPTCHA: $1",
+ "flow-spam-confirmedit-using-failure": "Houbo un problema técnico co CAPTCHA. Se non puideches enviar os teus cambios, por favor copia o teu texto, recarga a páxina e téntao de novo.",
"flow-embedding-unsupported": "As conversas aínda non poden ser incorporadas.",
"mw-ui-unsubmitted-confirm": "Ten cambios sen gardar nesta páxina. Está seguro que desexa sair e perder o seu traballo?",
"flow-post-undo-hide": "retiro a ocultación",
@@ -377,126 +450,27 @@
"flow-topic-undo-hide": "retiro a ocultación",
"flow-topic-undo-delete": "desfacer borrar",
"flow-topic-undo-suppress": "desfacer suprimir",
- "flow-importer-lqt-moved-thread-template": "Bosquexo de fío LQT trasladado e convertido a Flow",
+ "flow-importer-lqt-moved-thread-template": "Bosquexo de tema LQT trasladado e convertido a conversas estruturadas",
"flow-importer-lqt-moved-thread-template-content": "A mensaxe de {{{author}}} foi movida o {{{date}}}. Pode atoparse en [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "Páxina LQT convertida a Flow",
+ "flow-importer-lqt-converted-template": "Páxina LQT convertida a conversas estruturadas",
"flow-importer-lqt-converted-template-content": "O historial de páxina anterior gardouse como respaldo en <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> o {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-lqt-converted-archive-template": "Arquivo da páxina LQT convertida",
- "flow-importer-lqt-converted-archive-template-content": "Esta páxina é unha páxina LiquidThreads gardada. '''Non edite os contidos desta páxina'''. Dirixa calquera comentario adicional á [[{{{from}}}|páxina de conversa actual]].",
- "flow-importer-wt-converted-template": "Páxina de conversa en wikitexto convertida a Flow",
+ "flow-importer-lqt-converted-archive-template-content": "Esta páxina é unha páxina LiquidThreads gardada. <strong>Non edite os contidos desta páxina</strong>. Dirixa calquera comentario adicional á [[{{{from}}}|páxina de conversa actual]].",
+ "flow-importer-wt-converted-template": "Páxina de conversa en wikitexto convertida a conversas estruturadas",
"flow-importer-wt-converted-template-content": "A conversa anterior gardouse en <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> o {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-wt-converted-archive-template": "Arquivo da páxina de conversa en wikitexto convertida",
- "flow-importer-wt-converted-archive-template-content": "Esta páxina está gardada. '''Non edite os contidos desta páxina'''. Dirixa calquera comentario adicional á [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|páxina de conversa actual]].",
+ "flow-importer-wt-converted-archive-template-content": "Esta páxina está gardada. <strong>Non edite os contidos desta páxina</strong>. Dirixa calquera comentario adicional á [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|páxina de conversa actual]].",
"flow-importer-lqt-suppressed-user-template": "Mensaxe importada de LiquidThreads cun usuario suprimido.",
"flow-importer-lqt-suppressed-user-template-content": "Esta revisión importouse desde LiquidThreads cun usuario suprimido. Foi reasignada ó usuario actual.",
"flow-importer-lqt-different-author-signature-template": "Mensaxe de LQT importado cunha sinatura de usuario diferente.",
- "flow-importer-lqt-different-author-signature-template-content": "''Este comentario fíxoo [[User:{{{authorUser}}}|{{{authorUser}}}]], pero firmou como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Permitir accións a ser realizadas nas páxinas de Flow.",
- "apihelp-flow-param-submodule": "Submódulo do Flow a invocar.",
- "apihelp-flow-param-page": "Páxina sobre a que se realizará a acción.",
- "apihelp-flow-example-1": "Editar a descrición de \"[[Talk:Sandbox]]\".",
- "apihelp-flow+close-open-topic-description": "Obsoleto en favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Estado no que deixar o tema, \"bloqueado\" ou \"desbloqueado\".",
- "apihelp-flow+close-open-topic-param-reason": "Motivo para bloquear ou desbloquear o tema.",
- "apihelp-flow+edit-header-description": "Editar a descrición dun taboleiro de conversa.",
- "apihelp-flow+edit-header-param-prev_revision": "Identificador da revisión actual da descrición, para comprobar conflitos de edición.",
- "apihelp-flow+edit-header-param-content": "Contido da descrición.",
- "apihelp-flow+edit-header-param-format": "Formato da descrición (wikitexto|html)",
- "apihelp-flow+edit-header-example-1": "Editar a descrición de [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Cambiar o contido dunha mensaxe.",
- "apihelp-flow+edit-post-param-postId": "Identificador da mensaxe.",
- "apihelp-flow+edit-post-param-prev_revision": "Identificador da revisión actual da mensaxe, para comprobar conflitos de edición.",
- "apihelp-flow+edit-post-param-content": "Contido para a mensaxe.",
- "apihelp-flow+edit-post-param-format": "Formato do contido da mensaxe (wikitexto|html)",
- "apihelp-flow+edit-post-example-1": "Editar unha mensaxe en [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Edita o título dun tema.",
- "apihelp-flow+edit-title-param-prev_revision": "Identificador da revisión actual do título, para comprobar conflitos de edición.",
- "apihelp-flow+edit-title-param-content": "Contido para o título.",
- "apihelp-flow+edit-title-example-1": "Editar o título de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Editar o contido do resumo dun tema.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Identificador da revisión actual do resumo do tema, se hai, para comprobar conflitos de edición.",
- "apihelp-flow+edit-topic-summary-param-summary": "Contido para o resumo.",
- "apihelp-flow+edit-topic-summary-param-format": "Formato do resumo (wikitexto|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Editar o resumo de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Bloquear ou desbloquear un tema do Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Estado no que deixar o tema, <kbd>bloqueado</kbd>ou <kbd>desbloqueado</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Motivo para bloquear ou desbloquear o tema. Teña en conta que o cliente Flow da wiki usa aquí \"Marcado como resolto\" e, opcionalmente, engade información adicional no resumo.",
- "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Moderar unha mensaxe Flow.",
- "apihelp-flow+moderate-post-param-moderationState": "A que nivel moderar.",
- "apihelp-flow+moderate-post-param-reason": "Motivo da moderación.",
- "apihelp-flow+moderate-post-param-postId": "Identificador da mensaxe a moderar.",
- "apihelp-flow+moderate-post-example-1": "Borrar unha mensaxe no tema [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Moderar un tema Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "A que nivel moderar.",
- "apihelp-flow+moderate-topic-param-reason": "Motivo da moderación.",
- "apihelp-flow+moderate-topic-example-1": "Borrar o tema [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Crear un novo tema de Flow no fluxo de traballo indicado.",
- "apihelp-flow+new-topic-param-topic": "Texto para o novo título de tema.",
- "apihelp-flow+new-topic-param-content": "Contido para a resposta inicial do tema.",
- "apihelp-flow+new-topic-param-format": "Formato da resposta inicial do novo tema (wikitexto|html)",
- "apihelp-flow+new-topic-example-1": "Crear un novo tema en [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Responder a unha mensaxe.",
- "apihelp-flow+reply-param-replyTo": "Identificador da mensaxe á que responder.",
- "apihelp-flow+reply-param-content": "Contido para a nova mensaxe.",
- "apihelp-flow+reply-param-format": "Formato da nova mensaxe (wikitexto|html)",
- "apihelp-flow+reply-example-1": "Responder a unha mensaxe en [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Formato no que devolver o contido.",
- "apihelp-flow+view-header-description": "Ver a descrición dun taboleiro de conversas.",
- "apihelp-flow+view-header-param-revId": "Cargar esta revisión, no canto da máis recente.",
- "apihelp-flow+view-header-example-1": "Buscar a descrición de [[Talk:Sandbox]] como wikitexto",
- "apihelp-flow+view-post-description": "Ver unha mensaxe.",
- "apihelp-flow+view-post-param-postId": "Identificador da mensaxe a visualizar.",
- "apihelp-flow+view-post-param-format": "Formato no que devolver o contido.",
- "apihelp-flow+view-post-example-1": "Obter o contido dunha mensaxe en [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-post-history-description": "Ollar o historial de revisións dunha publicación.",
- "apihelp-flow+view-post-history-param-postId": "Identificador da publicación da que ver o historial de revisións.",
- "apihelp-flow+view-post-history-param-format": "Formato no que devolver o contido.",
- "apihelp-flow+view-post-history-example-1": "Obter as revisións dunha publicación en [[Topic:S2tycnas4hcucw8w]] como texto wiki",
- "apihelp-flow+view-topic-description": "Ver un tema.",
- "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Ollar o historial de revisións dun fío.",
- "apihelp-flow+view-topic-history-param-format": "Formato no que devolver o contido.",
- "apihelp-flow+view-topic-history-example-1": "Obter as revisións das publicacións en [[Topic:S2tycnas4hcucw8w]] como texto wiki",
- "apihelp-flow+view-topic-summary-description": "Ver o resumo dun tema.",
- "apihelp-flow+view-topic-summary-param-format": "Formato no que devolver o contido.",
- "apihelp-flow+view-topic-summary-param-revId": "Cargar esta revisión, no canto da máis recente.",
- "apihelp-flow+view-topic-summary-example-1": "Visualizar o resumo de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topiclist-description": "Ver a lista de temas.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Dirección na que ordenar os temas.",
- "apihelp-flow+view-topiclist-param-sortby": "Opción de ordenación dos temas, <kbd>actualización</kbd> (ordenados por hora de actualización do tema), ou <kbd>máis novo</kbd> (ordenados por hora de creación do tema).",
- "apihelp-flow+view-topiclist-param-savesortby": "Gardar a opción de ordenación nas preferencias do usuario, se está definida.",
- "apihelp-flow+view-topiclist-param-offset-id": "Valor inicial (en formato UUID) para a obtención de temas, só usado con ordenación <kbd>máis novo</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Valor inicial (selo de tempo do tema, en formato <code>TS_MW</code> (<code>AAAAMMDDHHMMSS</code>)) para a obtención de temas, só usado coa ordenación <kbd>actualización</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Número de temas a obter.",
- "apihelp-flow+view-topiclist-example-1": "Lista de temas en [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Converter texto entre wikitexto e HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Formato do contido a converter.",
- "apihelp-flow-parsoid-utils-param-to": "Formato ó que converter o contido.",
- "apihelp-flow-parsoid-utils-param-content": "Contido a converter.",
- "apihelp-flow-parsoid-utils-param-title": "Título da páxina Non pode usarse xunto con $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "Identificador da páxina. Non pode usarse xunto con $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Converter wikitexto <nowiki>'''lorem''' ''blá''</nowiki> a HTML",
- "apihelp-query+flowinfo-description": "Obter información básica de Flow sobre unha páxina.",
- "apihelp-query+flowinfo-example-1": "Obter información de Flow sobre [[Talk:Sandbox]], [[Main Page]], e [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Obter a información necesaria para desfacer edicións de descricións.",
- "apihelp-flow+undo-edit-header-param-startId": "Identificador de revisión no que comezar a desfacer.",
- "apihelp-flow+undo-edit-header-param-endId": "Identificador de revisión no que rematar de desfacer.",
- "apihelp-flow+undo-edit-header-example-1": "Recuperar información sobre desfacer unha modificación da descrición en [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Obter a información necesaria para desfacer a edición dunha mensaxe.",
- "apihelp-flow+undo-edit-post-param-postId": "Identificador de mensaxe a desfacer.",
- "apihelp-flow+undo-edit-post-param-startId": "Identificador de revisión no que comezar a desfacer.",
- "apihelp-flow+undo-edit-post-param-endId": "Identificador de revisión no que rematar de desfacer.",
- "apihelp-flow+undo-edit-post-example-1": "Obter información sobre como desfacer unha edición nunha mensaxe nun tema específico.",
- "apihelp-flow+undo-edit-topic-summary-description": "Obter a información necesaria para desfacer a edición dun resumo de tema.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Identificador de revisión no que comezar a desfacer.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Identificador de revisión no que rematar de desfacer.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Obter información sobre como desfacer unha edición nun resumo de tema nun tema específico.",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Este comentario fíxoo [[User:{{{authorUser}}}|{{{authorUser}}}]], pero firmou como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Editado",
"flow-edited-by": "Editado por $1",
- "flow-lqt-redirect-reason": "Redireccionando unha mensaxe de LiquidThreads retirada á súa mensaxe convertida en Flow",
- "flow-talk-conversion-move-reason": "Conversión da conversa en wikicode de $1 a Flow",
- "flow-talk-conversion-archive-edit-reason": "Conversión de páxina de conversa en wikitexto a Flow",
+ "flow-edited-by-header": "$1 editou a descrición do taboleiro",
+ "flow-edited-by-topic-title": "$1 editou o título do tema",
+ "flow-lqt-redirect-reason": "Redireccionando unha mensaxe de LiquidThreads retirada á súa mensaxe convertida en conversas estruturadas",
+ "flow-talk-conversion-move-reason": "Conversión da conversa en wikicode de $1 a conversas estruturadas",
+ "flow-talk-conversion-archive-edit-reason": "Conversión de páxina de conversa en wikitexto a conversas estruturadas",
"flow-previous-diff": "← Edición máis vella",
"flow-next-diff": "Edición máis nova →",
"flow-undo": "desfacer",
@@ -507,9 +481,9 @@
"flow-undo-edit-post": "Edición dunha publicación",
"flow-undo-edit-content": "A edición pódese desfacer.\nComprobe a comparación que aparece a continuación para confirmar que isto é o que desexa facer, e despois garde os cambios para desfacer a edición.",
"flow-undo-edit-failure": "Non se pode desfacer a edición debido a un conflito con algunha das edicións intermedias.",
- "group-flow-bot": "Bots para Flow",
- "group-flow-bot-member": "Bot de Flow",
- "grouppage-flow-bot": "Project:Bots de Flow",
+ "group-flow-bot": "Bots de conversas estruturadas",
+ "group-flow-bot-member": "bot de conversas estruturadas",
+ "grouppage-flow-bot": "Project:Bots de conversas estruturadas",
"flow-ve-mention-context-item-label": "Mencionar",
"flow-ve-mention-inspector-title": "Mención",
"flow-ve-mention-inspector-remove-label": "Eliminar",
@@ -519,7 +493,7 @@
"flow-ve-mention-inspector-invalid-user": "O nome de usuario \"$1\" non está rexistrado.",
"flow-wikitext-editor-help": "O texto wiki $1.",
"flow-wikitext-editor-help-and-preview": "O texto wiki $1 e vostede pode $2 en calquera momento.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|usa un formato específico]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|usa un formato específico]]",
"flow-wikitext-editor-help-preview-the-result": "previsualizar o resultado",
"flow-wikitext-switch-editor-tooltip": "Cambiar ao editor visual",
"flow-ve-switch-editor-tool-title": "Cambiar ao editor de texto wiki",
@@ -527,21 +501,28 @@
"flow-mark-revision-patrolled-link-title": "Marcar esta páxina como revisada",
"flow-mark-diff-patrolled-link-text": "Marcar como revisada",
"flow-mark-diff-patrolled-link-title": "Marcar como revisada",
- "flow-talk-page-beta-feature-message": "Flow na páxina de conversa",
- "flow-notification-link-text-enabled-on-talkpage": "Ver a páxina de conversa do usuario",
+ "flow-talk-page-beta-feature-message": "Conversas estruturadas na páxina de conversa do usuario",
+ "flow-talk-page-beta-feature-description": "Habilita un novo sistema de conversa estructurado na {{GENDER:|súa}} páxina de conversa. As conversas estruturadas simplifican as conversas con seccións claras para escribir e responder, e permite notificacións por cada tema.<br /><br /> As conversas existentes en wikitexto gardaranse. Esta característica non está habilitada por defecto; os usuarios terán que activala por separado. Se se desactiva esta característica, o taboleiro de conversas estruturadas trasladarase a unha subpáxina e restaurarase a páxina de conversa previa. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Máis información sobre a activación]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Ver}} a páxina de conversa do usuario",
"flow-notification-enabled-on-talkpage-title": "Novo sistema de conversa activado para a {{GENDER:$1|súa}} páxina de conversa<br /><small>Dispoñible en [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Novo sistema de conversa en $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, o novo sistema de conversa da wiki, foi activado na {{GENDER:$1|súa}} páxina de conversa de {{SITENAME}}. Podes obter máis información, realizar comentarios ou desactivar o novo sistema en calquera momento desde a sección de funcións beta nas {{GENDER:$1|súas}} preferencias.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "As conversas estruturadas, o novo sistema de conversa da wiki, foi activado na {{GENDER:$1|súa}} páxina de conversa de {{SITENAME}}. Podes obter máis información, realizar comentarios ou desactivar o novo sistema en calquera momento desde a sección de funcións beta nas {{GENDER:$1|súas}} preferencias.",
"flow-beta-feature-add-archive-template-edit-summary": "Engadindo modelo de ficheiro",
"flow-beta-feature-remove-archive-template-edit-summary": "Eliminación modelo de ficheiro",
- "flow-dialog-cancelconfirm-title": "Está seguro?",
- "flow-dialog-cancelconfirm-message": "Está seguro de que quere cancelar sen gardar primeiro?",
+ "flow-dialog-cancelconfirm-title": "Está {{GENDER:|seguro|segura}}?",
+ "flow-dialog-cancelconfirm-message": "Está {{GENDER:|seguro|segura}} de que quere cancelar sen gardar primeiro?",
"flow-dialog-cancelconfirm-keep": "Continuar editando",
"flow-dialog-cancelconfirm-discard": "Descartar as modificacións",
+ "flow-optin-archive-wikitext": "Trasládase a páxina de wikitexto para facer sitio para un taboleiro de conversa.",
+ "flow-optin-archive-flow-board": "Trasládase taboleiro de conversa para facer sitio para unha páxina de wikitexto.",
+ "flow-optin-restore-wikitext": "Restáurase páxina de wikitexto gardada.",
+ "flow-optin-restore-flow-board": "Restáurase taboleiro de conversa gardado.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Benvido|Benvida}} á súa nova páxina de conversa de usuario",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|A súa}} páxina de conversa é o lugar onde outros editores poden poñerse en contacto contigo. Con Flow, é máis doado comezar temas novos e realizar un seguimento das conversas.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|A súa}} páxina de conversa é o lugar onde outros editores poden poñerse en contacto contigo. Coas conversas estruturadas, é máis doado comezar temas novos e realizar un seguimento das conversas.",
"flow-guidedtour-optin-find-old-conversations": "Ver {{GENDER:$1|as súas}} conversas antigas",
"flow-guidedtour-optin-find-old-conversations-description": "As conversas previas foron trasladadas a unha páxina de arquivo.",
"flow-guidedtour-optin-feedback": "Envíanos {{GENDER:$1|os teus}} comentarios!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Pode}} obter máis información, realizar comentarios ou desactivar o novo sistema en calquera momento desde a sección de características beta nas súas preferencias."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Pode}} obter máis información, realizar comentarios ou desactivar o novo sistema en calquera momento desde a sección de características beta nas súas preferencias.",
+ "flow-action-not-page": "O obxecto de páxina é unha instancia da clase incorrecta",
+ "flow-action-wrong-title-content-model": "A páxina está a ser controlada polas conversas estruturadas, pero a clase Título indica que o modelo de contido é '$1'. Isto é un fallo de configuración ou un estado inconsistente. Por exemplo, isto pode ser realmente unha páxina non-conversa estruturada nun nome de espazos de conversas estruturadas, con <code>rev_content_model</code> non definido."
}
diff --git a/Flow/i18n/gom-deva.json b/Flow/i18n/gom-deva.json
index 003cf9ad..8010d654 100644
--- a/Flow/i18n/gom-deva.json
+++ b/Flow/i18n/gom-deva.json
@@ -1,11 +1,139 @@
{
"@metadata": {
"authors": [
- "Vaishali Parab"
+ "Vaishali Parab",
+ "The Discoverer",
+ "Matiia"
]
},
+ "logentry-delete-flow-delete-post": "$1 हाणें \"[[$3|$5]]\" एक [$4 प्रकास्णी] [[$6]] -चेर {{GENDER:$2|काडुन उडोयलां}}",
+ "abusefilter-edit-builder-vars-board-articleid": "फ्लो बोर्डाच्या पानाची वळख",
+ "abusefilter-edit-builder-vars-board-text": "फ्लो बोर्डाचो माथाळो",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "फ्लो बोर्डाचो पुराय माथाळो",
+ "flow-user-moderated": "बदलणी केल्लो वापरपी",
+ "flow-board-header-browse-topics-link": "विशयो पळय",
+ "flow-board-header": "ह्या फळ्या वीशीं",
+ "flow-board-description-can-not-edit": "बदल करूंक मेळना",
+ "flow-board-collapse-description": "वर्णन लिपयात",
+ "flow-board-expand-description": "वर्णन दाखयात",
+ "flow-topic-collapse-siderail": "पुराय आकारान वाचन करात",
+ "flow-topic-expand-siderail": "मर्यादीत आकारान वाचन करात",
+ "flow-edit-header-link": "वर्णन संपादित कर",
+ "flow-post-moderated-toggle-hide-show": "शेरो दाखय {{लिंग:$1|लिपयल्लो}} वरवीं $2",
+ "flow-post-moderated-toggle-delete-show": "शेरो दाखय {{लिंग:$1|काडून उडयिल्लो}} वरवीं $2",
+ "flow-post-moderated-toggle-suppress-show": "शेरो दाखय {{लिंग:$1|suppressed}} वरवीं $2",
+ "flow-post-moderated-toggle-hide-hide": "शेरो लिपय {{लिंग:$1|लिपयल्लो}} वरवीं $2",
+ "flow-post-moderated-toggle-delete-hide": "शेरो लिपय {{लिंग:$1|काडून उडयल्लो}} वरवीं $2",
+ "flow-post-moderated-toggle-suppress-hide": "शेरो लिपय {{लिंग:$1|suppressed}} वरवीं $2",
+ "flow-topic-moderated-reason-prefix": "कारण",
+ "flow-hide-header-content": "{{लिंग:$1|लिपयल्लो}} वरवीं $2",
+ "flow-delete-header-content": "{{लिंग:$1|काडून उडयल्लो}} वरवीं $2",
+ "flow-post-actions": "क्रिया",
+ "flow-topic-actions": "क्रिया",
+ "flow-cancel": "रद्द करात",
"flow-skip-summary": "सारांश सोड",
+ "flow-summary-authored": "$1 वरवीं सारांश",
+ "flow-show-change": "बदल दाखयात",
+ "flow-last-modified-by": "निमाणें {{लिंग:$1|बदल केल्लें}} वरवीं $1",
+ "flow-newtopic-title-placeholder": "नवो विशय",
+ "flow-newtopic-content-placeholder": "\"$1\" -चेर नवो संदेश बरय.",
+ "flow-newtopic-header": "नवो विशय जोडात",
+ "flow-newtopic-save": "विशय जोडात",
+ "flow-newtopic-save-anonymously": "अनवळखी विशय जोडात",
+ "flow-newtopic-start-placeholder": "नोवो विशय सुरु कर",
+ "flow-newtopic-first-heading": "$1 हाचेर नवो विशय सुरू करात",
+ "flow-reply-topic-placeholder": "\"$2\" हाचेर {{लिंग:$1|शेरो}}",
+ "flow-reply-topic-title-placeholder": "\"$1\" हाका जबाब दी",
+ "flow-reply-link": "{{GENDER:$1|जबाब}}",
+ "flow-reply-link-anonymously": "अनवळखी रावन जाप दी",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|दिनवास}}}}",
+ "flow-history-action-delete-post": "काडून उडय",
+ "flow-history-action-hide-post": "लिपय",
+ "flow-history-action-undelete-post": "काडून उडोवंक ना",
+ "flow-history-action-unhide-post": "लिपोवंक ना",
+ "flow-history-action-lock-topic": "सोडयात",
"flow-history-action-unlock-topic": "परत उगड",
+ "flow-post-edited": "$1 हाणें $2, ह्या वेळार प्रकास्णी {{GENDER:$1|बदललां}}.",
+ "flow-post-action-view": "तोगपी जोडणी",
+ "flow-post-action-post-history": "इतिहास",
+ "flow-post-action-delete-post": "काडून उडयात",
+ "flow-post-action-hide-post": "लिपयात",
+ "flow-post-action-edit-post": "बदल",
+ "flow-post-action-edit-post-submit": "बदल सांबाळात",
+ "flow-post-action-edit-post-submit-anonymously": "अनवळखी रावन बदल सांबाळात",
+ "flow-post-action-undelete-post": "काडून उडोवंक ना",
+ "flow-post-action-unhide-post": "लिपोवंक ना",
+ "flow-post-action-undo-moderation": "केल्लें परतावचें",
+ "flow-topic-action-view": "तोगपी जोडणी",
+ "flow-topic-action-watchlist": "सादुरवळेरी",
+ "flow-topic-action-edit-title": "नांवाचे संपादन",
+ "flow-topic-action-history": "इतिहास",
+ "flow-topic-action-hide-topic": "विशय लिपय",
+ "flow-topic-action-delete-topic": "विशय काडात",
"flow-topic-action-unlock-topic": "विशय परत उगडात",
- "flow-rev-message-restore-topic-reason": "परत उगडील्लें"
+ "flow-topic-action-summarize-topic": "सार तयार कर",
+ "flow-topic-action-unhide-topic": "विशय लिपय",
+ "flow-topic-action-undelete-topic": "विशय काडात",
+ "flow-topic-action-undo-moderation": "केल्लें परतावचें",
+ "flow-topic-notification-subscribe-title": "हो विशय {{लिंग:$1|तुमचे}} सादूरवळेरेक जोडला.",
+ "flow-error-missing-summary": "तुमकां सारांशूय दिवंचो पडटलो.",
+ "flow-error-missing-title": "ह्या विशयाक माथाळो ना. विशय सांबाळून दवरपाक माथाळो गरजेचो आसा.",
+ "flow-error-protected-unknown-reason": "अनवळखी",
+ "flow-error-invalid-postId": "\"replyTo\" हें पीरामीटर चुकीचें आसा. निर्दिष्ट प्रकास्णी ($1) मेळुंक ना.",
+ "flow-error-not-allowed-hide": "हो विशय लिपयला.",
+ "flow-error-not-allowed-reply-to-hide-topic": "हो विशय लिपयल्ल्या कारणान तुमकां जाप दिवंक मेळना.",
+ "flow-error-not-allowed-delete": "हो विशय काडून उडयला.",
+ "flow-error-not-allowed-reply-to-delete-topic": "हो विशय काडून उडयल्ल्या कारणान तुमकां जाप दिवंक मेळना.",
+ "flow-error-not-allowed-suppress": "हो विशय काडून उडयला.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "हो विशय काडून उडयल्ल्या कारणान तुमकां जाप दिवंक मेळना.",
+ "flow-error-not-a-post": "विशय्याचें नांवाक प्रकासणी कशी सांबालुंक जायना.",
+ "flow-error-invalid-topic-uuid-title": "वायट माथाळो",
+ "flow-error-unknown-workflow-id-title": "अनवळखी विशय",
+ "flow-edit-header-submit": "वर्णन सांबाळात",
+ "flow-edit-header-submit-anonymously": "अनवळखी रावन वर्णन सांबाळात",
+ "flow-edit-title-submit": "माथाळो बदलात",
+ "flow-edit-title-submit-anonymously": "अनवळखी रावन माथाळो बदलात",
+ "flow-edit-post-submit": "बदल जमा करात",
+ "flow-edit-post-submit-anonymously": "अनवळखी रावन बदल जमा करात",
+ "flow-rev-message-edit-post-recentchanges-summary": "एक प्रकासणी {{GENDER:$2|बदल्ला}}",
+ "flow-rev-message-restore-topic-reason": "परत उगडील्लें",
+ "flow-rc-topic-of-board": "$2 हाचेर $1",
+ "flow-board-history": "\"$1\" इतिहास",
+ "flow-topic-history": "विशयाचो इतिहास",
+ "flow-history-last4": "निमाणीं ४ वरां",
+ "flow-history-day": "आयज",
+ "flow-history-week": "फाटलो सप्तक",
+ "flow-comment-deleted": "काडून उडयल्लो शेरो",
+ "flow-comment-hidden": "लिपयल्लो शेरो",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 हाणें [[$3|$4]] -चेर तूजी <span class=\"plainlinks\">[$5 प्रकास्णी]</span> {{GENDER:$1|बदल्ला}}.",
+ "notification-header-flow-post-reply-user-talk": "$1 हाणें <strong>तुज्या उलवपाचे पानार</strong> \"<strong>$4</strong>\" -आन {{GENDER:$2|जबाब दिला}}.",
+ "notification-header-flow-post-edited-v2": "\"'''$1'''\" -आंत {{GENDER:$2|तुजी}} प्रकासणी बदल्ला.",
+ "notification-header-flow-post-edited-user-talk": "'''{{GENDER:$2|तुज्या}} उलवपाचे पानार''' \"'''$1'''\" -आंत एक प्रकासणी बदल्ला.",
+ "flow-notification-link-text-view-topic": "विशय पळयात",
+ "flow-notification-link-text-view-topics": "विशय पळयात",
+ "flow-notification-reply-email-subject": "$2 चेर $3",
+ "flow-notification-edit-email-batch-body": "$1 हाणें $3 हाचेर \"$2\" -आंत एक प्रकासणी {{GENDER:$1|बदल्ला}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 आनी आनीक {{PLURAL:$4|एक वांगदियान|$4 वांगदियानीं}} $3 हाचेर \"$2\" -आंत एक प्रकासणी {{GENDER:$1|बदल्ला}}",
+ "flow-link-post": "प्रकासणी",
+ "flow-link-topic": "विशय",
+ "flow-link-history": "इतिहास",
+ "flow-link-post-revision": "प्रकासण्येची उजळनी",
+ "flow-moderation-title-hide-post": "प्रकासणी लिपय?",
+ "flow-moderation-confirm-delete-post": "काडून उडयात",
+ "flow-moderation-confirm-hide-post": "लिपयात",
+ "flow-moderation-confirm-undelete-post": "काडून उडोवंक ना",
+ "flow-moderation-confirm-unhide-post": "लिपोवंक ना",
+ "flow-moderation-confirm-delete-topic": "काडून उडयात",
+ "flow-moderation-confirm-hide-topic": "लिपयात",
+ "flow-moderation-confirm-undelete-topic": "काडून उडोवंक ना",
+ "flow-moderation-confirm-unhide-topic": "लिपोवंक ना",
+ "flow-moderation-title-hide-topic": "विशय लिपय?",
+ "right-flow-hide": "फ्लोवाचे विशय आनी प्रकासणी लिपय",
+ "right-flow-delete": "फ्लोवाचे विशय आनी प्रकासणी काडुन उडय",
+ "flow-topic-html-title": "$2 हाचेर $1",
+ "flow-no-more-fwd": "हाचे कीन पर्ण्यो विशय नान",
+ "flow-newest-topics": "सग्ळ्यावोन नव्यो विशय",
+ "flow-whatlinkshere-post": "एके [$1 प्रकासणेसून]",
+ "flow-special-type-post": "प्रकासणी",
+ "flow-undo-edit-post": "प्रकासणी बदल्ताय"
}
diff --git a/Flow/i18n/gom-latn.json b/Flow/i18n/gom-latn.json
index 3ddd0f36..184608e1 100644
--- a/Flow/i18n/gom-latn.json
+++ b/Flow/i18n/gom-latn.json
@@ -1,11 +1,312 @@
{
"@metadata": {
"authors": [
- "The Discoverer"
+ "The Discoverer",
+ "Macofe",
+ "Matiia"
]
},
- "flow-skip-summary": "Sar pollounk naka",
+ "flow-talk-taken-over-comment": "/* Hea panak Flow bhasabhas follean bodol'la */",
+ "logentry-delete-flow-delete-post": "$1 hannem [[$6]] -cher \"[[$3|$5]]\" hantuntlem ek [$4 prokasnni] {{GENDER:$2|kadun udoila}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoiachi ek prokasnni {{GENDER:$2|kadun udoila}}",
+ "logentry-delete-flow-restore-post": "$1 hannem [[$6]] -cher \"[[$3|$5]]\" hantunt ek [$4 prokasnni] {{GENDER:$2|porot haddlea}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoiachi ek prokasnni {{GENDER:$2|porot haddlea}}",
+ "logentry-suppress-flow-suppress-post": "$1 hannem [[$6]] -cher \"[[$3|$5]]\" hantuntlem ek [$4 prokasnni] {{GENDER:$2|vogllaila}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoiachi ek prokasnni {{GENDER:$2|vogllaila}}",
+ "logentry-suppress-flow-restore-post": "$1 hannem [[$6]] -cher \"[[$3|$5]]\" hantuntlem ek [$4 prokasnni] {{GENDER:$2|kadun udoila}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoiachi ek prokasnni {{GENDER:$2|kadun udoila}}",
+ "logentry-delete-flow-delete-topic": "$1 hannem \"[[$3|$5]]\" ho vixoi [[$6]] -cher {{GENDER:$2|kadun udoila}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoi {{GENDER:$2|kadun udoila}}",
+ "logentry-delete-flow-restore-topic": "$1 hannem [[$6]] -cher \"[[$3|$5]]\" ho vixoi {{GENDER:$2|porot haddlea}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoi {{GENDER:$2|porot haddlea}}",
+ "logentry-suppress-flow-suppress-topic": "$1 hannem \"[[$3|$5]]\" ho vixoi [[$6]] -cher {{GENDER:$2|vogllaila}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoi {{GENDER:$2|vogllaila}}",
+ "logentry-suppress-flow-restore-topic": "$1 hannem \"[[$3|$5]]\" ho vixoi [[$6]] -cher {{GENDER:$2|kadun udoila}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoi {{GENDER:$2|kadun udoila}}",
+ "logentry-lock-flow-restore-topic": "$1 hannem \"[[$3|$5]]\" ho vixoi [[$6]] -cher {{GENDER:$2|porot ugodla}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 hannem [[$3]] hantuntlem ek vixoi {{GENDER:$2|porot ugodla}}",
+ "flow-board-header-browse-topics-link": "Vixoio polloi",
+ "flow-board-header": "Hea follea vixim",
+ "flow-board-description-can-not-edit": "Bodlunk zaina",
+ "flow-board-collapse-description": "Vornon lipoi",
+ "flow-board-expand-description": "Vornon dakhoi",
+ "flow-topic-collapse-siderail": "Akhi rundaien vach",
+ "flow-topic-expand-siderail": "Ordhi rundaien vach",
+ "flow-edit-header-link": "Vornon bodol",
+ "flow-post-moderated-toggle-hide-show": "$2 hannem {{GENDER:$1|lipoilolo}} comentario dakhoi",
+ "flow-post-moderated-toggle-delete-show": "$2 hannem {{GENDER:$1|kadun udoilolo}} comentario dakhoi",
+ "flow-post-moderated-toggle-suppress-show": "$2 hannem {{GENDER:$1|vogllailolo}} comentario dakhoi",
+ "flow-post-moderated-toggle-hide-hide": "$2 hannem {{GENDER:$1|lipoilolo}} comentario lipoi",
+ "flow-post-moderated-toggle-delete-hide": "$2 hannem {{GENDER:$1|kadun udoilolo}} comentario lipoi",
+ "flow-post-moderated-toggle-suppress-hide": "$2 hannem {{GENDER:$1|vogllailolo}} comentario dakhoi",
+ "flow-topic-moderated-reason-prefix": "Karonn:",
+ "flow-hide-post-content": "$1 ([$2 itihas]) hannem ho comentario {{GENDER:$1|lipoila}}",
+ "flow-hide-title-content": "$1 hannem ho vixoi {{GENDER:$1|lipoila}}",
+ "flow-hide-header-content": "$2 hannem {{GENDER:$1|lipoila}}",
+ "flow-delete-post-content": "$1 ([$2 itihas]) hannem ho comentario {{GENDER:$1|kadun udoila}}",
+ "flow-delete-title-content": "$1 hannem ho vixoi {{GENDER:$1|kadun udoila}}",
+ "flow-delete-header-content": "$2 hannem {{GENDER:$1|kadun udoila}}",
+ "flow-suppress-post-content": "$1 ([$2 itihas]) hannem ho comentario {{GENDER:$1|vogllaila}}",
+ "flow-suppress-title-content": "$1 hannem ho vixoi {{GENDER:$1|vogllaila}}",
+ "flow-suppress-header-content": "$2 hannem {{GENDER:$1|vogllailelem}}",
+ "flow-suppress-usertext": "<em>Vaporpeachem nanv vogllaila suppressed</em>",
+ "flow-post-actions": "Kornnio",
+ "flow-topic-actions": "Kornnio",
+ "flow-cancel": "Rod'd kor",
+ "flow-skip-summary": "Sar polloi naka",
+ "flow-summary-authored": "$1 hannem kel'li sar",
+ "flow-summary-edited": "Ho sar nimannem $1 hannem {{GENDER:$1|bodol'la}}",
+ "flow-show-change": "Bodolpam dakhoi",
+ "flow-last-modified-by": "Nimannem $1 vorvim bodolelem",
+ "flow-newtopic-title-placeholder": "Novo vixoi",
+ "flow-newtopic-content-placeholder": "\"$1\" -cher novo sondex boroi.",
+ "flow-newtopic-header": "Novo vixoi zodd",
+ "flow-newtopic-save": "Vixoi zodd",
+ "flow-newtopic-save-anonymously": "Aplem nanv lipovn vixoi zodd",
+ "flow-newtopic-start-placeholder": "Novo vixoi suru kor",
+ "flow-newtopic-first-heading": "$1 hacher novo vixoi suru kor",
+ "flow-summarize-topic-placeholder": "Upkar korun hea bhasabhasecho sar kor",
+ "flow-reply-topic-placeholder": "\"$2\" -cher {{GENDER:$1|comentar kor}}",
+ "flow-reply-topic-title-placeholder": "\"$1\" haka zobab di",
+ "flow-reply-link": "{{GENDER:$1|Zobab}}",
+ "flow-reply-link-anonymously": "Aplem nanv lipovn zobab di",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Dinvas}}}}",
+ "flow-history-action-suppress-post": "vogllai",
+ "flow-history-action-delete-post": "kadun udoi",
+ "flow-history-action-hide-post": "lipoi",
+ "flow-history-action-restore-post": "porot hadd",
"flow-history-action-unlock-topic": "porot ugod",
+ "flow-post-edited": "$1 hannem $2, hea vellar prokasnni {{GENDER:$1|bodol'la}}.",
+ "flow-post-action-view": "Togpi zoddni",
+ "flow-post-action-post-history": "Itihas",
+ "flow-post-action-suppress-post": "Vogllai",
+ "flow-post-action-delete-post": "Kadun udoi",
+ "flow-post-action-hide-post": "Lipoi",
+ "flow-post-action-edit-post": "Bodol",
+ "flow-post-action-edit-post-submit": "Bodlopam samball",
+ "flow-post-action-edit-post-submit-anonymously": "Aplem nanv lipovn bodlopam samball",
+ "flow-post-action-restore-post": "Porot hadd",
+ "flow-post-action-undo-moderation": "Kel'lem portavchem",
+ "flow-topic-action-view": "Togpi zoddni",
+ "flow-topic-action-watchlist": "Sadurvolleri",
+ "flow-topic-action-edit-title": "Nanv bodol",
+ "flow-topic-action-history": "Itihas",
+ "flow-topic-action-hide-topic": "Vixoi lipoi",
+ "flow-topic-action-delete-topic": "Vixoi kadun udoi",
"flow-topic-action-unlock-topic": "Vixoi porot ugod",
- "flow-rev-message-restore-topic-reason": "porot ugodlele"
+ "flow-topic-action-summarize-topic": "Sar toiar kor",
+ "flow-topic-action-resummarize-topic": "Vixoiacho sar bodol",
+ "flow-topic-action-suppress-topic": "Vixoi vogllai",
+ "flow-topic-action-restore-topic": "Vixoi porot hadd",
+ "flow-topic-action-undo-moderation": "Kel'lem portavchem",
+ "flow-topic-notification-subscribe-title": "Ho vixoi {{GENDER:$1|tujea}} sadurvollerek zoddla.",
+ "flow-board-notification-subscribe-description": "Hea folleacher novo vixoi rochtolo tednam {{GENDER:$1|tuka}} kollovnni mellteli.",
+ "flow-error-allowcreation-flow-create-board": "Vapurpeak \"{{int:right-flow-create-board}}\" porvangi na",
+ "flow-error-external": "Chuk ghodli.Chuke vixim ho sondex mel'lam: $1",
+ "flow-error-missing-title": "Vixoiachem nanv na. Vixoi samballpak nanv gorjechem.",
+ "flow-error-invalid-postId": "\"replyTo\" hem parameter chukichem asa. Nirdisht prokasnni ($1) mellunk na.",
+ "flow-error-not-allowed-hide": "Ho vixoi lipoilolo asa.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Tujean zobab diunk zaina kiteak ho vixoi lipoilelem asa.",
+ "flow-error-not-allowed-delete": "Ho vixoi kadun udoilolo asa.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Tujean zobab diunk zaina kiteak ho vixoi kadun udoilelem asa.",
+ "flow-error-not-allowed-suppress": "Ho vixoi kadun udoila",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Tujean zobab diunk zaina kiteak ho vixoi kadun udoilelem asa.",
+ "flow-error-not-allowed-hide-extract": "Ho vixoi lipoilolo asa.\nVixoiache lipounechi sotr sondorba khatir sokoil dilea.",
+ "flow-error-not-allowed-delete-extract": "Ho vixoi kadun udoilolo asa.\nVixoiache kadun udounechi sotr sondorba khatir sokoil dilea.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Tujean zobab diunk zaina kiteak ho vixoi kadun udoilolo asa.\nVixoiache kadun udounechi sotr sondorba khatir sokoil dilea.",
+ "flow-error-not-allowed-suppress-extract": "Ho vixoi kadun udoilolo asa.\nVixoiache kadun udounechi sotr sondorba khatir sokoil dilea.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Tujean zobab diunk zaina kiteak ho vixoi vogllailolo asa.\nVixoiache vogllaunechi sotr sondorba khatir sokoil dilea.",
+ "flow-error-not-a-post": "Vixoiachem nanvak prokasnni koxi sambalunk zaina.",
+ "flow-error-prev-revision-does-not-exist": "Fattli uzollni mellunk na.",
+ "flow-error-default": "Ek chuk ghodli.",
+ "flow-error-invalid-topic-uuid-title": "Chukichem nanv",
+ "flow-error-unknown-workflow-id-title": "Khobor naslelem vixoi",
+ "flow-error-unknown-workflow-id": "Maglolo vixoi ostitvant nam.",
+ "flow-edit-header-placeholder": "Hea bhasabhaseche folleacho vornon kor",
+ "flow-edit-header-submit": "Vornon samball",
+ "flow-edit-header-submit-anonymously": "Aplem nanv lipovn vornon samball",
+ "flow-edit-title-submit": "Nanv bodol",
+ "flow-edit-title-submit-anonymously": "Aplem nanv lipovn vixoiachem nanv bodol",
+ "flow-rev-message-edit-post": "$1 hannem \"$4\" -cher ek [$3 comentario] {{GENDER:$2|bodol'la}}",
+ "flow-rev-message-edit-post-recentchanges-summary": "Ek prokasnni {{GENDER:$2|bodol'la}}",
+ "flow-rev-message-reply": "$1 hannem \"$4\" -cher [$3 {{GENDER:$2|comentar kela}}] (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|comentario}}</strong> {{PLURAL:$1|zoddla|zoddleat}}",
+ "flow-rev-message-new-post": "$1 hannem \"[$3 $4]\" ho vixoi {{GENDER:$2|rochla}}",
+ "flow-rev-message-new-post-recentchanges-summary": "Novo vixoi {{GENDER:$2|rochla}}",
+ "flow-rev-message-edit-title": "$1 hannem vixoiachem nanv \"$5\" {{GENDER:$2|bodlun}} \"[$3 $4]\" kela",
+ "flow-rev-message-create-header": "$1 hannem vornon {{GENDER:$2|rochlem}}",
+ "flow-rev-message-edit-header": "$1 hannem vornon {{GENDER:$2|bodol'lam}}",
+ "flow-rev-message-create-topic-summary": "$1 hannem $3 vixoiacho sar {{GENDER:$2|rochla}}",
+ "flow-rev-message-edit-topic-summary": "$1 hannem $3 vixoiacho sar {{GENDER:$2|bodol'la}}",
+ "flow-rev-message-hid-post": "$1 hannem \"$6\" -cher ek [$4 commentario] {{GENDER:$2|lipoila}} (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 hannem \"$6\" -cher ek [$4 commentario]{{GENDER:$2|kadun udoila}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 hannem \"$6\" -cher ek [$4 commentario]{{GENDER:$2|vogllaila}} (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 hannem \"$6\" -cher ek [$4 commentario] {{GENDER:$2|porot haddla}} (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 hannem \"$6\" -cher [$4 vixoi] {{GENDER:$2|lipoila}} (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 hannem \"$6\" -cher [$4 vixoi] {{GENDER:$2|kadun udoila}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 hannem \"$6\" [$4 vixoi] {{GENDER:$2|vogllaila}} (<em>$5</em>)",
+ "flow-rev-message-restore-topic-reason": "porot ugodlele",
+ "flow-rev-message-restored-topic": "$1 hannem ho [$4 vixoi] \"$6\" {{GENDER:$2|porot haddlea}} (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$2 hacher $1",
+ "flow-board-history": "\"$1\" hacho itihas",
+ "flow-board-history-empty": "Hea folleacho sodheak kai itihas na.",
+ "flow-topic-history": "\"$1\" ho vixoiacho itihas",
+ "flow-post-history": "\"{{GENDER:$2|$2}} cho comentario\" hea prokasnniecho itihas",
+ "flow-history-last4": "Fatleo 4 vhoram",
+ "flow-history-day": "Aiz",
+ "flow-history-week": "Fatlo suman",
+ "flow-history-pages-topic": "[$1 \"$2\" hea folleacher] dista",
+ "flow-history-pages-post": "[$1 $2] hacher dista",
+ "flow-topic-comments": "{{PLURAL:$1|$1 comentario|0=Comentar korpak {{GENDER:$2|poilo za|poilem za}}!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Comentario polloi}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Comentario lipoi}}",
+ "flow-comment-restored": "Porot haddlolo comentario",
+ "flow-comment-deleted": "Kadun udoilolo comentario",
+ "flow-comment-hidden": "Lipoilolo comentario",
+ "flow-last-modified": "Nimannem bodololem $1",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 hannem <strong>$4</strong> -cher {{GENDER:$1|zobzb dila}}.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ani anik {{PLURAL:$5|ek vangdian|$5 vangdianim|100=99+ vangdianim}} <strong>$3</strong> -cher {{GENDER:$1|zobab dila}}.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 hannem [[$3|$4]] -cher tuji <span class=\"plainlinks\">[$5 prokasnni]</span> {{GENDER:$1|bodol'la}}.",
+ "flow-notification-edit-bundle": "$1 ani anik {{PLURAL:$5|ek vangdian|$5 vangdianim|100=99+ vangdianim}} \"$3\" -cher $2 hantun ek <span class=\"plainlinks\">[$4 prokasnni]</span> {{GENDER:$1|bodol'la}}.",
+ "notification-header-flow-new-topic-v2": "<strong>$3</strong> hacher novo vixoi rochla: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> hacher {{PLURAL:$1|ek novo vixoi|$1 noveo vixoi|100=99+ noveo vixoi}}",
+ "notification-header-flow-new-topic-user-talk": "<strong>Tujea uloupache panar</strong> ek novo vixoi rochla: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "<strong>Tujea uloupache panar</strong> {{PLURAL:$1|ek novo vixoi|$1 noveo vixoi|100=99+ noveo vixoi}}.",
+ "notification-header-flow-post-reply": "$1 hannem \"<strong>$4</strong>\" -ant {{GENDER:$2|zobab dila}}.",
+ "notification-bundle-header-flow-post-reply-v2": "\"<strong>$3</strong>\" -ant {{PLURAL:$1|ek novo zobab|$1 noveo zobab|100=99+ noveo zobab}}.",
+ "notification-header-flow-post-reply-user-talk": "$1 hannem <strong>tujea uloupache panar</strong> \"<strong>$4</strong>\" -an {{GENDER:$2|zobab dila}}.",
+ "notification-bundle-header-flow-post-reply-user-talk": "<strong>Tujea uloupache panar</strong> \"<strong>$3</strong>\" -ant {{PLURAL:$1|ek novo zobab|$1 noveo zobab|100=99+ noveo zobab}}.",
+ "notification-header-flow-post-edited-v2": "\"<strong>$1</strong>\" -ant {{GENDER:$2|tuji}} prokasnni bodol'la.",
+ "notification-bundle-header-flow-post-edited-v2": "\"<strong>$1</strong>\" -ant {{GENDER:$2|tuji}} prokasnni zaite pauti bodol'la.",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong> \"<strong>$1</strong>\" -ant ek prokasnni bodol'la.",
+ "notification-bundle-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong>, <strong>$1</strong> -an ek prokasnni zaite pauti bodol'la.",
+ "notification-header-flow-topic-renamed-v2": "\"<strong>$1</strong>\" vixoiachem nanv bodlun \"<strong>$2</strong>\" zala.",
+ "notification-header-flow-topic-renamed-user-talk": "<strong>{{GENDER:$3|Tujea}} uloupache panar</strong>. \"<strong>$1</strong>\" vixoiachem nanv bodlun \"<strong>$2</strong>\" kela.",
+ "notification-header-flow-summary-edited-first": "\"<strong>$1</strong>\" vixoiacho sar toiar zala.",
+ "notification-bundle-header-flow-summary-edited": "\"<strong>$1</strong>\" achem sar zaite pauti bodol'la.",
+ "notification-header-flow-summary-edited-first-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong> \"<strong>$1</strong>\" vixoiacho sar toiar zala.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong> <strong>$1</strong> achem sar zaite pauti bodol'la.",
+ "notification-header-flow-description-edited": "<strong>$1</strong> hachem vornon bodol'lam.",
+ "notification-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong> vornan bodol'la.",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong> achem vornon zaite pauti bodol'la.",
+ "notification-bundle-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|Tujea}} uloupache panar</strong> vornon kai pauti bodol'la.",
+ "notification-links-flow-description-edited-view-page": "Pan {{GENDER:$1|polloi}}",
+ "notification-email-subject-flow-description-edited": "$1 hannem $2 -cher vornon {{GENDER:$1|bodol'la}}.",
+ "notification-email-batch-body-flow-description-edited": "$1 hannem $2 -cher vornon bodol'la.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 ani anik {{PLURAL:$3|ek vapurpean|$3 vapurpeanim|100=99+ others}} $2 -cher vornon bodol'la",
+ "notification-header-flow-topic-reopened": "\"<strong>$1</strong>\" ho vixoi porot ugodla",
+ "notification-header-flow-topic-reopened-user-talk": "\"<strong>$1</strong>\" ho vixoi <strong>tujea uloupache panar</strong> porot ugodla.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 hannem <strong>$3</strong> -cher novem vixoi {{GENDER:$1|rochla}}.",
+ "flow-notification-newtopic-bundle": "<strong><span class=\"plainlinks\">[$3 $2]</span></strong> -cher {{PLURAL:$1|ek novo vixoi|$1 noveo vixoi|100=99+ noveo vixoi}}",
+ "flow-notification-rename": "$1 hannem [[$5|$6]] -cher <span class=\"plainlinks\">[$2 $3]</span> vixoiachem nanv {{GENDER:$1|bodlun}} \"$4\" kela.",
+ "flow-notification-link-text-view-post": "Prokasnni polloi",
+ "flow-notification-link-text-view-topic": "Vixoi polloi",
+ "flow-notification-link-text-view-topics": "Vixoi polloi",
+ "flow-notification-reply-email-subject": "$3 panar $2",
+ "flow-notification-reply-email-batch-body": "$1 hannem $3 -cher \"$2\" haka {{GENDER:$1|zobab dila}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 ani anik {{PLURAL:$4|ek vangdian|$4 vangdianim|100=99+ vangdianim}} $3 -cher \"$2\" haka {{GENDER:$1|zobab dila}}",
+ "flow-notification-edit-email-subject": "$1 hannem ek prokasnni {{GENDER:$1|bodol'la}}",
+ "flow-notification-edit-email-batch-body": "$1 hannem $3 hacher \"$2\" -ant ek prokasnni {{GENDER:$1|bodol'la}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 ani anik {{PLURAL:$4|ek vangdian|$4 vangdianim|100=99+ vangdianim}} $3 hacher \"$2\" -ant ek prokasnni {{GENDER:$1|bodol'la}}",
+ "flow-notification-rename-email-subject": "$1 hannem tujea vixoiachem nanv {{GENDER:$1|bodol'la}}",
+ "flow-notification-rename-email-batch-body": "$1 hannem $4 -cher tujea vixoiachem nanv \"$2\" {{GENDER:$1|bodlun}} \"$3\" kela",
+ "flow-notification-newtopic-email-subject": "$1 -an $2 -cher novem vixoi {{GENDER:$1|rochla}}",
+ "flow-notification-newtopic-email-batch-body": "$1 hannem $3 -cher \"$2\" nanvacho novo vixoi {{GENDER:$1|rochla}}",
+ "flow-notification-newtopic-email-batch-bundle-body": "$2 -cher {{PLURAL:$1|ek novo vixoi|$1 noveo vixoi|100=99+ noveo vixoi}}",
+ "echo-category-title-flow-discussion": "Flow bhasabhas",
+ "echo-pref-tooltip-flow-discussion": "Hanven lokx dovorlele vixoi vo pananche bodolam vixim mhaka kollit kor.",
+ "flow-link-post": "prokasnni",
+ "flow-link-topic": "vixoi",
+ "flow-link-history": "itihas",
+ "flow-link-post-revision": "prokasnniechi uzollni",
+ "flow-link-topic-revision": "vixoiachi uzollni",
+ "flow-link-header-revision": "vornonachi uzollni",
+ "flow-link-summary-revision": "sarachi uzollni",
+ "flow-moderation-title-suppress-post": "Prokasnni vogllai?",
+ "flow-moderation-title-delete-post": "Prokasnni kadun udoi?",
+ "flow-moderation-title-hide-post": "Prokasnni lipoi?",
+ "flow-moderation-confirm-suppress-post": "Vogllai",
+ "flow-moderation-confirm-delete-post": "Kadun udoi",
+ "flow-moderation-confirm-hide-post": "Lipoi",
+ "flow-moderation-confirm-suppress-topic": "Vogllai",
+ "flow-moderation-confirm-delete-topic": "Kadun udoi",
+ "flow-moderation-confirm-hide-topic": "Lipoi",
+ "flow-moderation-confirmation-suppress-topic": "Ho vixoi vogllailolo asa.",
+ "flow-moderation-confirmation-delete-topic": "Ho vixoi kadun udoilolo asa.",
+ "flow-moderation-confirmation-hide-topic": "Ho vixoi lipoilolo asa.",
+ "flow-moderation-title-suppress-topic": "Vixoi vogllai?",
+ "flow-moderation-title-delete-topic": "Vixoi kadun udoi?",
+ "flow-moderation-title-hide-topic": "Vixoi lipoi?",
+ "flow-topic-permalink-warning": "Ho vixoi [$2 $1] cher suru kel'lo",
+ "flow-topic-permalink-warning-user-board": "Ho vixoi [$2 {{GENDER:$1|$1}} hachea folleacher] suru kel'lo",
+ "flow-revision-permalink-warning-post": "Hi zaun asa hea prokasnnieche ekli avruttik togpi zoddni.\nHi avrutti $1, hea vellachi.\nTum [$5 fattli avruttiksun fork] polleunk xoktai, vo [$4 prokasnnieche itihasache panar] dusreo avrutteo polleunk xoktai.",
+ "flow-revision-permalink-warning-post-first": "Hi zaun asa hea prokasnnieche poili avruttik togpi zoddni.\nTum [$4 prokasnnieche itihasache panar] hachekin noveo avrutteo polleunk xoktai.",
+ "flow-revision-permalink-warning-postsummary": "Hi zaun asa hea prokasnnieche sarache ekli avruttik togpi zoddni. Hi avrutti $1, hea vellachi.\nTum [$5 fattli avruttiksun fork] polleunk xoktai, vo [$4 prokasnnieche itihasache panar] dusreo avrutteo polleunk xoktai.",
+ "flow-revision-permalink-warning-postsummary-first": "Hi zaun asa hea prokasnnieche sarachi poili avruttik togpi zoddni.\nTum [$4 prokasnnieche itihasache panar] hachekin noveo avrutteo polleunk xoktai.",
+ "flow-revision-permalink-warning-header": "Hi zaun asa vornonache ekli avruttik togpi zoddni.\nHi avrutti $1, hea vellachi. Tum [$3 fattli avruttiksun fork] polleunk xoktai, vo [$2 follieche itihasache panar] dusreo avrutteo polleunk xoktai.",
+ "flow-revision-permalink-warning-header-first": "Hi zaun asa vornoneche poili avruttik togpi zoddni.\nTum [$2 follieche itihasache panar] hachekin noveo avrutteo polleunk xoktai.",
+ "flow-compare-revisions-revision-header": "{{GENDER:$2|$2}} hannem $1, hea vellar kelli avrutti",
+ "flow-compare-revisions-header-post": "Hem pan [$4 $1] -cher \"[$5 $2]\" hea vixoiant prokasnniecheo don avrutti modem {{GENDER:$3|bodlopam}} dakhoita.\nTum he prokasnnieche dusreo avrutteo teche [$6 itihasache panar] polleunk xoktai.",
+ "flow-compare-revisions-header-postsummary": "Hem pan [$3 $1] -cher \"[$4 $2]\" hea vixoiacheo saracheo don avrutti modem {{GENDER:$3|bodlopam}} dakhoita.\nTum hea vixoiacheo saracheo dusreo avrutteo vixoiacho [$5 itihasache panar] polleunk xoktai.",
+ "flow-compare-revisions-header-header": "Hem pan [$3 $1] -cher vornonacheo don avrutti modem {{GENDER:$2|bodlopam}} dakhoita.\nTum he vornonache dusreo avrutteo teche [$4 itihasache panar] polleunk xoktai.",
+ "right-flow-hide": "Flowache vixoi ani prokasnni lipoipache",
+ "right-flow-delete": "Flowache vixoi ani prokasnni kadun udoipache",
+ "right-flow-edit-post": "Dusrea vapurpeachim Flowache prokasnni bodolpachem",
+ "right-flow-suppress": "Flowache uzollnio vogllaipache",
+ "flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\" cher click kelea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-terms-of-use-reply": "\"{{int:flow-reply-link}}\" cher click kelea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-terms-of-use-edit": "Tujeo bodlopam samballea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-anon-warning": "Tuven sotrorombh korunk nai. Tujea IP pot'te che bodlek tujea nanvak xrey mellche khatir, tujean [$1 sotrorombh korunk zata] vo [$2 kont rochunk zata].",
+ "flow-topic-first-heading": "$1 cher vixoi",
+ "flow-topic-html-title": "$2 hacher $1",
+ "flow-topic-count": "Vixoi ($1)",
+ "flow-no-more-fwd": "Hache kin pornneo vixoi nan",
+ "flow-newest-topics": "Soglleavon noveo vixoi",
+ "flow-recent-topics": "Halinch sakriya asleleo vixoio",
+ "flow-terms-of-use-summarize": "\"{{int:flow-topic-action-update-topic-summary}}\" cher click kelea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-terms-of-use-lock-topic": "\"{{int:flow-topic-action-lock-topic}}\" cher click kelea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-terms-of-use-unlock-topic": "\"{{int:flow-topic-action-unlock-topic}}\" cher click kelea vorvim, tu hea wikiche vapurpeache ati manun ghetai.",
+ "flow-whatlinkshere-post": "Eke [$1 prokasnnesun]",
+ "flow-whatlinkshere-header": "[$1 Vornona] savn",
+ "flow-whatlinkshere-post-summary": "[$1 Sara] savn",
+ "structureddiscussions": "Flow",
+ "flow-special-type": "Prokar",
+ "flow-special-type-post": "Prokasnni",
+ "flow-special-uuid": "UUID",
+ "flow-special-enableflow-invalid-title": "Dil'lem panachem nanv chukichem asa",
+ "flow-special-enableflow-board-creation-not-allowed": "Tuka [[:$1]] panacher Flow follo rochpak porvangi na.",
+ "flow-post-undo-hide": "lipovop rod'd kor",
+ "flow-post-undo-delete": "kadun udovop rod'd kor",
+ "flow-post-undo-suppress": "vogllavop rod'd kor",
+ "flow-topic-undo-hide": "lipovop rod'd kor",
+ "flow-topic-undo-delete": "kadun udovop rod'd kor",
+ "flow-topic-undo-suppress": "vogllavop rod'd kor",
+ "flow-importer-lqt-moved-thread-template-content": "Hea prokasnniek {{{date}}} tarkher {{{author}}} -an halloila. Tuka tem hangasor melltelem: [[{{{title}}}]].",
+ "flow-edited": "Bodolelem",
+ "flow-edited-by": "$1 an bodolelem",
+ "flow-edited-by-header": "$1 -an folleacho vornon bodol'la",
+ "flow-edited-by-topic-title": "$1 -an vixoiacho mathallo bodol'la",
+ "flow-previous-diff": "← Adlo bodol",
+ "flow-next-diff": "Fuddlem bodol →",
+ "flow-undo": "kel'lem portavchem",
+ "flow-undo-latest-revision": "Sogleanvon novi uzollnni",
+ "flow-undo-your-text": "Tuzo mozkur",
+ "flow-undo-edit-header": "Vornon bodoltai",
+ "flow-undo-edit-topic-summary": "Vixoiacho sar bodoltai",
+ "flow-undo-edit-post": "Prokasnni bodoltai",
+ "group-flow-bot": "Flow robotam",
+ "group-flow-bot-member": "Flow robot",
+ "grouppage-flow-bot": "Project:Flow roboram",
+ "flow-ve-mention-inspector-remove-label": "Kad",
+ "flow-ve-mention-placeholder": "Vapurpeachem nanv",
+ "flow-wikitext-editor-help-preview-the-result": "porinamachem zolok polloi",
+ "flow-mark-revision-patrolled-link-text": "Hem pan topaslam mhonn khunnai",
+ "flow-mark-revision-patrolled-link-title": "Hem pan topaslam mhonn khunnai",
+ "flow-mark-diff-patrolled-link-text": "Topaslele mhonn khunnai",
+ "flow-mark-diff-patrolled-link-title": "Topaslele mhonn khunnai",
+ "flow-talk-page-beta-feature-message": "Vapurpi uloupacher Flow",
+ "flow-notification-link-text-enabled-on-talkpage": "Vapurpeacho charchecho pan {{GENDER:|polloi}}",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "$2 -cher bhasabhasachi novi pranali",
+ "flow-optin-archive-wikitext": "Bhasabhasechea follea pasot zago korunk wikimozkurachem pan halloi.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Tujea}} novea vapurpeachea uloupachea panar ievkar!"
}
diff --git a/Flow/i18n/gsw.json b/Flow/i18n/gsw.json
index 129a1e9b..5b9094f8 100644
--- a/Flow/i18n/gsw.json
+++ b/Flow/i18n/gsw.json
@@ -1,9 +1,12 @@
{
"@metadata": {
"authors": [
- "J. 'mach' wust"
+ "J. 'mach' wust",
+ "Als-Holder"
]
},
+ "flow-post-action-edit-post-submit": "Änderige spychere",
+ "flow-post-action-edit-post-submit-anonymously": "Änderigen anonym spychere",
"echo-category-title-flow-discussion": "Flow",
"echo-pref-tooltip-flow-discussion": "Hiwyse, we mi en Aktion im Flow betrifft."
}
diff --git a/Flow/i18n/gu.json b/Flow/i18n/gu.json
index 8137afe3..635f9ef1 100644
--- a/Flow/i18n/gu.json
+++ b/Flow/i18n/gu.json
@@ -2,23 +2,35 @@
"@metadata": {
"authors": [
"KartikMistry",
- "Sushant savla"
+ "Sushant savla",
+ "Nizil Shah"
]
},
- "enableflow": "ફ્લો સક્રિય કરો",
- "flow-board-header": "આ ચર્ચા વિષે",
+ "enablestructureddiscussions": "ફ્લો સક્રિય કરો",
+ "flow-board-header": "આ ચર્ચાપત્ર વિષે",
"flow-board-collapse-description": "વર્ણન છુપાવો",
"flow-board-expand-description": "વર્ણન દર્શાવો",
+ "flow-topic-collapse-siderail": "પૂરી પહોળાઈમાં વાંચવા વિસ્તારો",
+ "flow-topic-expand-siderail": "ઓછી પહોળાઈમાં વાંચવા સંકોચો",
"flow-edit-header-link": "વર્ણન સુધારો",
+ "flow-post-moderated-toggle-hide-show": "$2 દ્વારા કરવામાં આવેલ અને {{$1|છુપાવેલ}} ટિપ્પણી બતાવો.",
+ "flow-post-moderated-toggle-delete-show": "$2 દ્વારા {{$1|રદ}} કરવામાં આવેલ ટિપ્પણી બતાવો",
+ "flow-post-moderated-toggle-suppress-show": "$2 દ્વારા {{$1|દબાવી દેવાયેલ}} ટિપ્પણી બતાવો",
+ "flow-post-moderated-toggle-hide-hide": "$2 દ્વારા {{$1|છુપાવેલ}} ટિપ્પણી છુપાડો",
+ "flow-post-moderated-toggle-delete-hide": "$2 દ્વારા {{GENDER:$1|રદ કરાયેલ}} ટિપ્પણી છુપાડો",
+ "flow-post-moderated-toggle-suppress-hide": "$2 દ્વારા {{GENDER:$1|દબાવી દેવાયેલ}} ટિપ્પણી છુપાડો",
"flow-topic-moderated-reason-prefix": "કારણ:",
+ "flow-hide-post-content": "આ ટિપ્પણી $1 દ્વારા છ્પવાયેલ છે ([$2 ઈતિહાસ])",
+ "flow-hide-title-content": "આ વિષય $1 દ્વારા છુપાવાયેલ છે",
+ "flow-hide-header-content": "$2 દ્વારા {{$1|છુપાવાયેલ}}",
"flow-cancel": "રદ કરો",
+ "flow-show-change": "ફેરફારો દર્શાવો",
"flow-newtopic-title-placeholder": "નવો વિષય",
"flow-newtopic-header": "નવો વિષય ઉમેરો",
"flow-newtopic-save": "વિષય ઉમેરો",
"flow-newtopic-start-placeholder": "નવો વિષય શરુ કરો",
"flow-newtopic-first-heading": "$1 પર નવો વિષય શરુ કરો",
"flow-reply-topic-title-placeholder": "\"$1\" નો જવાબ આપો",
- "flow-reply-submit": "{{GENDER:$1|જવાબ}}",
"flow-reply-link": "{{GENDER:$1|જવાબ}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|આભાર}}}}",
"flow-topic-notification-subscribe-title": "આ વિષયને {{GENDER:$1|તમારી}} ધ્યાનસૂચિમાં ઉમેરી દેવામાં આવ્યો છે.",
diff --git a/Flow/i18n/hak.json b/Flow/i18n/hak.json
new file mode 100644
index 00000000..2b6183d8
--- /dev/null
+++ b/Flow/i18n/hak.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "唐吉訶德的侍從"
+ ]
+ },
+ "flow-post-action-edit-post-submit": "Pó-chhùn siû-kói"
+}
diff --git a/Flow/i18n/he.json b/Flow/i18n/he.json
index 608082d7..aff8fbe7 100644
--- a/Flow/i18n/he.json
+++ b/Flow/i18n/he.json
@@ -8,30 +8,56 @@
"Danny-w",
"YaronSh",
"LaG roiL",
- "Avner"
+ "Avner",
+ "ערן",
+ "Macofe",
+ "Rotemliss"
]
},
- "enableflow": "הפעלת זרימה",
- "flow-desc": "מערכת ניהול תהליכי עבודה",
+ "enablestructureddiscussions": "הפעלת זרימה",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|הפסקת}} המעקב אחרי פעילות חדשה בלוח \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|אתה כבר לא עוקב|את כבר לא עוקבת|אתם כבר לא עוקבים}} יותר אחרי הלוח \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "זה לא ישפיע על נושאים נפרדים {{GENDER:$3|שאתה עוקב|שאת עוקבת|שאתם עוקבים}} אחריהם. {{GENDER:$3|באפשרותך|באפשרותך|באפשרותכם}} לעקוב אחרי [$2 הלוח הזה] בכל עת.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|הפסקת}} המעקב אחרי הנושא הזה",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|אתה כבר לא עוקב|את כבר לא עוקבת|אתם כבר לא עוקבים}} יותר אחרי הנושא \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|באפשרותך|באפשרותך|באפשרותכם}} לעקוב אחרי [$2 הנושא הזה] בכל עת.",
+ "flow-desc": "מערכת דיונים",
"flow-talk-taken-over-comment": "/* הדף הזה הומר ללוח דיונים של זרימה */",
"log-name-flow": "יומן פעילות זרימה",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|מחק|מחקה}} [$4 רשומה] בנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|מחק|מחקה}} רשומה בנושא בלוח [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|שחזר|שחזרה}} [$4 רשומה] בנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|שחזר|שחזרה}} רשומה בנושא בלוח [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|העלים|העלימה}} [$4 רשומה] בנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|העלים|העלימה}} רשומה בנושא בלוח [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|מחק|מחקה}} [$4 רשומה] בנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|מחק|מחקה}} רשומה בנושא בלוח [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|מחק|מחקה}} את הנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|מחק|מחקה}} נושא בלוח [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|שחזר|שחזרה}} את הנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|שחזר|שחזרה}} נושא בלוח [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|העלים|העלימה}} את הנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|העלים|העלימה}} רשומה בנושא בלוח [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|מחק|מחקה}} את הנושא \"[[$3|$5]]\" בלוח [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|מחק|מחקה}} נושא בלוח [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|סימן|סימנה}} את הנושא \"[[$3|$5]]\" כפתור בדף [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|סימן|סימנה}} נושא בתור פתור בלוח [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|פתח מחדש}} את הנושא \"[[$3|$5]]\" בדף [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|פתח|פתחה}} מחדש נושא בלוח [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] בלוח [[$3]] יובא מ־LiquidThreads לזרימה",
+ "abusefilter-edit-builder-vars-board-articleid": "מזהה דף או לוח זרימה",
+ "abusefilter-edit-builder-vars-board-namespace": "מרחב שם של לוח הזרימה",
+ "abusefilter-edit-builder-vars-board-text": "כותרת של לוח זרימה",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "כותרת שלמה של לוח זרימה",
"flow-user-moderated": "משתמש בפיקוח",
"flow-board-header-browse-topics-link": "עיון בנושאים",
"flow-board-header": "על הלוח הזה",
+ "flow-board-description-can-not-edit": "לא ניתן לעריכה",
"flow-board-collapse-description": "הסתרת התיאור",
"flow-board-expand-description": "הצגת התיאור",
"flow-topic-collapse-siderail": "לקרוא ברוחב מלא",
"flow-topic-expand-siderail": "לקרוא ברוחב קבוע",
- "flow-edit-header-link": "לערוך את התיאור",
+ "flow-edit-header-link": "עריכת התיאור",
"flow-post-moderated-toggle-hide-show": "הצגת התגובה ש{{GRAMMAR:תחילית|$2}} {{GENDER:$1|הסתיר|הסתירה}}",
"flow-post-moderated-toggle-delete-show": "הצגת התגובה ש{{GRAMMAR:תחילית|$2}} {{GENDER:$1|מחק|מחקה}}",
"flow-post-moderated-toggle-suppress-show": "הצגת התגובה ש{{GRAMMAR:תחילית|$2}} {{GENDER:$1|העלים|העלימה}}",
@@ -52,13 +78,13 @@
"flow-post-actions": "פעולות",
"flow-topic-actions": "פעולות",
"flow-cancel": "ביטול",
- "flow-skip-summary": "לדלג על הסיכום",
+ "flow-skip-summary": "לדלג",
"flow-edit-summary-placeholder": "נא לתאר בקצרה את תוצאת הדיון",
"flow-summary-authored": "סיכום מאת $1",
"flow-summary-edited": "הסיכום נערך בפעם האחרונה על־ידי $1",
"flow-show-change": "הצגת שינויים",
"flow-last-modified-by": "שוּנה לאחרונה על־ידי $1",
- "flow-stub-post-content": "'''בשל בעיה טכנית, לא ניתן לאחזר את הרשומה הזאת.'''",
+ "flow-stub-post-content": "<em>בשל בעיה טכנית, לא ניתן לאחזר את הרשומה הזאת.</em>",
"flow-newtopic-title-placeholder": "כותרת חדשה",
"flow-newtopic-content-placeholder": "שליחת הודעה חדשה בדף \"$1\"",
"flow-newtopic-header": "הוספת נושא חדש",
@@ -72,7 +98,7 @@
"flow-reply-link": "{{GENDER:$1|השב|השיבי|להשיב}}",
"flow-reply-link-anonymously": "תשובה כאלמוני",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|תודה}}}}",
- "flow-thank-link-title": "{{GENDER:$1|תודה ציבורית {{GENDER:$2|לשולח|לשולחת}}}}",
+ "flow-thank-link-title": "שליחת {{GENDER:$1|תודה {{GENDER:$2|לשולח|לשולחת}}}} באופן ציבורי",
"flow-history-action-suppress-post": "העלמה",
"flow-history-action-delete-post": "מחיקה",
"flow-history-action-hide-post": "הסתרה",
@@ -119,26 +145,27 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|תקבל|תקבלי}} הודעה כאשר נושא חדש נוצר בלוח הזה.",
"flow-topic-action-watchlist-add": "מינוי לנושא הזה",
"flow-topic-action-watchlist-remove": "ביטול מינוי לנושא הזה",
- "flow-error-allowcreation-no-usedb": "בעת שימוש ב־allowCreation, המשתנה ‎<var>$wgContentHandlerUseDB</var> חייב להיות <code>true</code>.",
- "flow-error-allowcreation-already-exists": "הדף כבר קיים, אבל לא היה צריך להיות",
+ "flow-error-allowcreation-no-usedb": "כשזרימה מופעלת בדף מסוים, המשתנה ‎<var>$wgContentHandlerUseDB</var> חייב להיות <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "הדף כבר קיים בכותרת היעד, אז אי־אפשר להעביר לשם לוח זרימה.",
"flow-error-allowcreation-flow-create-board": "למשתמש אין הרשאה \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "אין באפשרותך להשתתף כעת. אפשר לנסות להיכנס לחשבון.",
+ "flow-error-can-not-edit-logged-in": "אין לך עכשיו אפשרות להשתתף כי אין לך הרשאות נדרשות.",
"flow-error-http": "אירעה שגיאה בעת יצירת קשר עם השרת.",
- "flow-error-other": "אירעה שגיאה בלתי־צפויה.",
- "flow-error-external": "אירעה שגיאה.<br />התקבלה הודעת השגיאה הבאה: $1",
+ "flow-error-external": "אירעה שגיאה. התקבלה הודעת השגיאה הבאה: $1",
"flow-error-topic-is-locked": "הנושא הזה נפתר, ולכן לא ניתן לעשות בו עוד פעילות.",
"flow-error-lock-moderated-post": "לא ניתן לסמן רשומה מפוקחת בתור פתורה.",
- "flow-error-external-multi": "אירעו שגיאות.<br />\n$1",
"flow-error-missing-content": "ברשומה אין תוכן. דרוש תוכן כדי לשמור רשומה",
"flow-error-missing-summary": "יש לשלוח סיכום.",
"flow-error-missing-title": "לנושא אין כותרת. דרושה כותרת כדי לשמור נושא.",
- "flow-error-parsoid-failure": "לא ניתן לפענח את התוכן עקב כשל בפרסואיד.",
+ "flow-error-parsoid-failure": "לא ניתן להעביר את התוכן: שגיאה בהתחברות לשרת להמרה בין קוד ויקי לבין HTML. נא לבדוק את חיבור האינטרנט שלך או לנסות שוב מאוחר יותר אם הבעיה ממשיכה. אם שוב מופיעה לך השגיאה הזאת, נא לדווח באג",
+ "flow-error-protected-autoconfirmed-logged-in": "הלוח הזה מוכן. רק משתמשים ותיקים יכולים להשתתף. סיבה: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "הלוח הזה מוגן. רק משתתפים שנכנסו לחשבון יכולים להשתתף. סיבה: $1",
+ "flow-error-protected-sysop-logged-in": "הלוח הזה מוגן. רק משתתפים עם הרשאות מפעיל יכולים להשתתף. סיבה: $1",
+ "flow-error-protected-sysop-logged-out": "הלוח הזה מוגן. רק משתתפים שנכנסו לחשבון עם הרשאות מפעיל יכולים להשתתף. סיבה: $1",
+ "flow-error-protected-unknown-reason": "אינה ידועה",
"flow-error-missing-replyto": "לא נשלח פרמטר \"replyTo\". הפרמטר הזה דרוש לפעולת \"reply\".",
- "flow-error-invalid-replyto": "פרמטר \"replyTo\" שנשלח היה בלתי־תקין. לא נמצאה הרשומה שצוינה.",
- "flow-error-delete-failure": "מחיקת הפריט הזה נכשלה.",
- "flow-error-hide-failure": "הסתרת הפריט הזה נכשלה.",
"flow-error-missing-postId": "לא ניתן פרמטר \"postId\". הפרמטר הזה דרוש כדי לשנות רשומה.",
"flow-error-invalid-postId": "פרמטר \"postId\" שנשלח היה בלתי־תקין. הרשומה שצוינה ($1) לא נמצאה.",
- "flow-error-restore-failure": "שחזור הפריט הזה נכשל.",
"flow-error-invalid-moderation-state": "ערך בלתי־תקין לפרמטר ('moderationState') נשלח ל־API של Flow.",
"flow-error-invalid-moderation-reason": "נא לתת סיבה להחלת הפיקוח",
"flow-error-not-allowed": "אין הרשאות מספיקות לביצוע הפעולה הזאת.",
@@ -153,7 +180,7 @@
"flow-error-not-allowed-reply-to-delete-topic-extract": "אינך {{GENDER:|יכול|יכולה}} לענות כי הנושא הזה נמחק. יומן המחיקה של הנושא מוצג להלן לעיון.",
"flow-error-not-allowed-suppress-extract": "הנושא הזה נמחק. יומן המחיקה עבור הנושא הזה מסופק להלן לעיון.",
"flow-error-not-allowed-reply-to-suppress-topic-extract": "אינך {{GENDER:|יכול|יכולה}} להשיב כי הנושא הזה הועלם. יומן ההעלמה מוצג להלן לעיון.",
- "flow-error-title-too-long": "כותרות של נושאים מוגבלות {{PLURAL:$1|לבית אחד|ל־$1 בתים}}",
+ "flow-error-title-too-long": "כותרות של נושאים מוגבלות {{PLURAL:$1|לבית אחד|ל־$1 בתים}}.",
"flow-error-no-existing-workflow": "הזרימה הזאת עוד לא קיימת.",
"flow-error-not-a-post": "לא ניתן לשמור כותרת נושא בתור רשומה.",
"flow-error-missing-header-content": "יש לשלוח תיאור.",
@@ -164,6 +191,7 @@
"flow-error-default": "אירעה שגיאה.",
"flow-error-invalid-input": "ערך בלתי־תקין ניתן ניתן לטעינת תוכן זרימה.",
"flow-error-invalid-title": "ניתנה כותרת דף בלתי־תקינה.",
+ "flow-error-invalid-parameter": "פרמטר חסר או בלתי־תקין בקריאה לשיטה",
"flow-error-fail-load-history": "טעינת תוכן ההיסטוריה נכשלה.",
"flow-error-missing-revision": "לא נמצאה גרסה שממנה ייטען תוכן הזרימה.",
"flow-error-fail-commit": "שמירת תוכן הזרימה נכשלה.",
@@ -171,6 +199,7 @@
"flow-error-revision-comparison": "פעולת השוואה יכולה להיעשות רק בין שתי גרסאות של אותה רשומה.",
"flow-error-missing-topic-title": "לא נמצאה כותרת נושא עבור הזרימה הנוכחית.",
"flow-error-missing-metadata": "לא נמצאו מטא־נתונים עבור הגרסה הזאת.",
+ "flow-error-different-page": "זרימת העבודה של זרימה לא משויכת עם הדף הזה.",
"flow-error-fail-load-data": "טעינת הנתונים המובקשים נכשלה.",
"flow-error-invalid-workflow": "הזרימה המובקשת לא נמצאה.",
"flow-error-process-data": "אירעה שגיאה בעת עיבוד הנתונים בבקשה שלך.",
@@ -180,14 +209,14 @@
"flow-error-no-commit": "לא היה אפשר לשמור את הפעולה שצוינה.",
"flow-error-content-too-long": "התוכן גדול מדי. תוכן אחרי פענוח מוגבל {{PLURAL:$1|לבית אחד|ל־$1 בתים}}.",
"flow-error-move-topic": "העברת דף נושא אינה נתמכת כעת.",
- "flow-error-move-no-create-permissions": "ההרשאה \"{{int:right-flow-create-board}}\" נדרשת כדי להעביר לוח זרימה.",
"flow-error-invalid-topic-uuid-title": "כותרת שגויה",
"flow-error-invalid-topic-uuid": "כותרת הדף שביקשת אינה חוקית. דפים במרחב השם \"נושא\" נוצרים באופן אוטומטי.",
"flow-error-unknown-workflow-id-title": "נושא לא יודע",
"flow-error-unknown-workflow-id": "הנושא המבוקש לא נמצא.",
"flow-error-search": "לא הצלחנו להשלים את החיפוש שלך בשל בעיה זמנית. נא לנסות שוב מאוחר יותר.",
+ "flow-error-invalid-undelete": "לא היה אפשר לשחזר את הדף, כי יש עכשיו לוח דיונים במקומו.",
"flow-edit-header-placeholder": "נא לתאר את לוח הדיונים הזה",
- "flow-edit-header-submit": "שמירת תיאור",
+ "flow-edit-header-submit": "שמירת התיאור",
"flow-edit-header-submit-anonymously": "שמירת תיאור כאלמוני",
"flow-edit-title-submit": "שינוי כותרת",
"flow-edit-title-submit-anonymously": "שינוי כותרת כאלמוני",
@@ -211,7 +240,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|הסתיר|הסתירה}} את [$4 הנושא] \"$6‏\" (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|מחק|מחקה}} את [$4 הנושא] \"$6‏\" (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|העלים|העלימה}} את [$4 הנושא] \"$6‏\" (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|סימן|סימנה}} את [$4 הנושא] $6 בתור פתור (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|סימן|סימנה}} את [$4 הנושא] \"$6\" בתור פתור (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "סומן בתור פתור",
"flow-rev-message-restore-topic-reason": "נפתח מחדש",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|שחזר|שחזרה}} את [$4 הנושא] \"$6‏\" (<em>$5</em>).",
@@ -234,31 +263,73 @@
"flow-comment-moderated": "תגובה מפוקחת",
"flow-last-modified": "שוּנה לאחרונה $1",
"flow-workflow": "זרימת עבודה",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|השיב|השיבה}} בדף '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ועוד {{PLURAL:$6|אדם אחד|$5 אנשים אחרים}} {{GENDER:$1|השיבו}} בדף '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|השיב|השיבה}} בדף <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ועוד {{PLURAL:$5|מישהו|$5 אנשים אחרים|יותר מ־99 אנשים אחרים}} {{GENDER:$1|השיבו}} בדף <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|ערך|ערכה}} <span class=\"plainlinks\">[$5 רשומה]</span> בנושא \"$2\" בדף [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 {{PLURAL:$6|ועוד אדם אחד|ועוד $5 אנשים}} ערכו <span class=\"plainlinks\">[$4 רשומה]</span> שלך בנושא \"$2\" בדף \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|יצר|יצרה}} נושא חדש בדף '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|נושא חדש אחד|$1 נושאים חדשים|250=יותר מ־250 נושאים חדשים}} בדף '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 ועוד {{PLURAL:$5|ועוד מישהו|ועוד $5 אנשים|100=יותר מ־99 אנשים}} ערכו <span class=\"plainlinks\">[$4 רשומה]</span> שלך בנושא \"$2\" בדף \"$3\".",
+ "notification-header-flow-new-topic-v2": "נושא חדש נוצר בלוח <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|נושא חדש|$1 נושאים חדשים|100=99+ נושאים חדשים}} בדף <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "נושא חדש נוצר ב<strong>דף השיחה שלך</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|נושא חדש|$1 נושאים חדשים|100=99+ נושאים חדשים}} ב<strong>דף השיחה שלך</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|הגיב|הגיבה}} בנושא \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|תגובה חדשה|$1 תגובות חדשות|100=99+ תגובות חדשות}} בנושא \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|שלח|שלחה}} תגובה ב<strong>דף השיחה שלך</strong> בנושא \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|תגובה חדשה|$1 תגובות חדשות|100=99+ תגובות חדשות}} ב<strong>דף השיחה שלך</strong> בנושא \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "הרשומה {{GENDER:$2|שלך}} בנושא \"<strong>$1</strong>\" נערכה.",
+ "notification-bundle-header-flow-post-edited-v2": "הרשומה {{GENDER:$2|שלך}} בנושא \"<strong>$1</strong>\" נערכה מספר פעמים.",
+ "notification-header-flow-post-edited-user-talk": "רשומה בנושא \"<strong>$1</strong>\" נערכה ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "רשומה בנושא \"<strong>$1</strong>\" נערכה מספר פעמים ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-header-flow-topic-renamed-v2": "שם הנושא \"<strong>$1</strong>\" שוּנה אל \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "שם הנושא \"<strong>$1</strong>\" שוּנה אל \"<strong>$2</strong>\" ב<strong>דף השיחה {{GENDER:$3|שלך}}</strong>.",
+ "notification-header-flow-summary-edited": "הסיכום של הנושא \"<strong>$1</strong>\" עודכן.",
+ "notification-header-flow-summary-edited-first": "הנושא \"<strong>$1</strong>\" סוכם.",
+ "notification-bundle-header-flow-summary-edited": "הסיכום של הנושא \"<strong>$1</strong>\" נערך מספר פעמים.",
+ "notification-header-flow-summary-edited-user-talk": "הסיכום של הנושא \"<strong>$1</strong>\" עודכן ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "הנושא \"<strong>$1</strong>\" סוכם ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "הסיכום של הנושא \"<strong>$1</strong>\" נערך מספר פעמים ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|עדכן|עדכנה}} את הסיכום של $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|עדכן|עדכנה}} את הסיכום של $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 {{PLURAL:$3|ועוד מישהו|ועוד $3 אנשים|100=ועוד יותר מ־99 אנשים}} {{GENDER:$1|עדכנו}} את הסיכום של $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$4|אותך}} בנושא \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$4|אותך}} בתיאור של הלוח <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|הזכיר|הזכירה}} {{GENDER:$4|אותך}} בנושא \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "מערכת שיחות חדשה הופעלה ב<strong>דף השיחה {{GENDER:$2|שלך}}</strong>.",
+ "notification-header-flow-description-edited": "התיאור של הלוח <strong>$1</strong> נערך.",
+ "notification-header-flow-description-edited-user-talk": "התיאור של <strong>דף השיחה {{GENDER:$2|שלך}}</strong> נערך.",
+ "notification-bundle-header-flow-description-edited": "התיאור של הלוח <strong>$1</strong> נערך מספר פעמים.",
+ "notification-bundle-header-flow-description-edited-user-talk": "התיאור של <strong>דף השיחה {{GENDER:$2|שלך}}</strong> נערך מספר פעמים.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|הצגת}} דף",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|ערך|ערכה}} את התיאור בדף $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|ערך|ערכה}} את התיאור בדף $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 ועוד {{PLURAL:$3|מישהו|$3 אנשים|100=יותר מ־99 אנשים}} ערכו את התיאור בדף $2",
+ "notification-header-flow-topic-resolved": "הנושא \"<strong>$1</strong>\" סומן כפתוּר.",
+ "notification-header-flow-topic-reopened": "הנושא \"<strong>$1</strong>\" נפתח מחדש.",
+ "notification-header-flow-topic-resolved-user-talk": "הנושא \"<strong>$1</strong>\" סומן כפתוּר ב<strong>דף השיחה שלך</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "הנושא \"<strong>$1</strong>\" נפתח מחדש ב<strong>דף השיחה שלך</strong>.",
+ "notification-email-subject-flow-topic-resolved": "הנושא <strong>$2</strong> נפתר.",
+ "notification-email-batch-body-flow-topic-resolved": "הנושא \"<strong>$2</strong> נפתר.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|יצר|יצרה}} נושא חדש בדף <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|נושא חדש אחד|$1 נושאים חדשים|100=יותר מ־99 נושאים חדשים}} בדף <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|שינה|שינתה}} את הכותרת של <span class=\"plainlinks\">[$2 $3]</span> אל \"$4\" בדף [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|הזכיר|הזכירה}} {{GENDER:$5|אותך}} ב<span class=\"plainlinks\">[$2 רשומה]</span> {{GENDER:$1|שלו|שלה}} בנושא \"$3\" בדף \"$4\".",
"flow-notification-link-text-view-post": "הצגת הרשומה",
"flow-notification-link-text-view-topic": "הצגת הנושא",
+ "flow-notification-link-text-view-topics": "הצגת נושאים",
"flow-notification-reply-email-subject": "$2 ב־$3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|השיב|השיבה}} לנושא \"$2\" בדף $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 {{PLURAL:$5|ועוד אדם אחד|ועוד $4 אנשים}} השיבו לרשומה שלך בנושא \"$2\" בדף $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 ועוד {{PLURAL:$4|מישהו|$4 אנשים|100=יותר מ־99 אנשים}} השיבו לרשומה שלך בנושא \"$2\" בדף $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|הזכיר|הזכירה}} {{GENDER:$3|אותך}} ברשומה $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|הזכיר|הזכירה}} {{GENDER:$4|אותך}} ברשומה {{GENDER:$1|שלו|שלה}} בנושא \"$2\" בדף $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|ערך|ערכה}} רשומה",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|ערך|ערכה}} רשומה בנושא \"$2\" בדף $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 {{PLURAL:$5|ועוד אדם אחד|ועוד $4 אנשים}} ערכו רשומה בנושא \"$2\" בדף $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 ועוד {{PLURAL:$4|מישהו|$4 אנשים|100=ועוד יותר מ־99 אנשים}} ערכו רשומה בנושא \"$2\" בדף $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|שינה|שינתה}} את השם של נושא שלך",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|שינה|שינתה}} את השם של הנושא שלך \"$2\" אל \"$3\" בדף $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|יצר|יצרה}} נושא חדש בדף $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|יצר|יצרה}} נושא חדש עם הכותרת \"$2\" ב{{GRAMMAR:תחלילית|$3}}",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|נושא אחד חדש|$1 נושאים חדשים|250=250+ נושאים חדשים}} בדף $2",
- "echo-category-title-flow-discussion": "זרימה",
- "echo-pref-tooltip-flow-discussion": "להודיע לי כשיש פעולות שקשורות אליי בזרימה.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|נושא אחד חדש|$1 נושאים חדשים|100=יותר מ־99 נושאים חדשים}} בדף $2",
+ "echo-category-title-flow-discussion": "דיון זרימה",
+ "echo-pref-tooltip-flow-discussion": "להודיע לי על פעילות בנושאים או בדפים ברשימת המעקב שלי.",
"flow-link-post": "רשומה",
"flow-link-topic": "נושא",
"flow-link-history": "היסטוריה",
@@ -290,18 +361,18 @@
"flow-moderation-confirm-unsuppress-topic": "ביטול העלמה",
"flow-moderation-confirm-undelete-topic": "ביטול מחיקה",
"flow-moderation-confirm-unhide-topic": "ביטול הסתרה",
- "flow-moderation-confirmation-suppress-post": "הרשומה הזאת הועלמה בהצלחה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
- "flow-moderation-confirmation-delete-post": "הרשומה נמחקה בהצלחה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
- "flow-moderation-confirmation-hide-post": "הרשמה הועלמה בהצלחה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
- "flow-moderation-confirmation-unsuppress-post": "ביטלת בהצלחה את ההעלמה של הרשומה הזאת.",
- "flow-moderation-confirmation-undelete-post": "ביטלת בהצלחה את המחיקה של הרשומה הזאת.",
- "flow-moderation-confirmation-unhide-post": "ביטלת בהצלחה את ההסתרה של הרשומה הזאת.",
+ "flow-moderation-confirmation-suppress-post": "הרשומה הזאת הועלמה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
+ "flow-moderation-confirmation-delete-post": "הרשומה נמחקה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
+ "flow-moderation-confirmation-hide-post": "הרשומה הוסתרה.\nאנא {{GENDER:$2|שקול|שקלי}} לתת ל{{GRAMMAR:תחילית|$1}} משוב על הרשומה הזאת.",
+ "flow-moderation-confirmation-unsuppress-post": "ביטלת את ההעלמה של הרשומה הזאת.",
+ "flow-moderation-confirmation-undelete-post": "ביטלת את המחיקה של הרשומה הזאת.",
+ "flow-moderation-confirmation-unhide-post": "ביטלת את ההסתרה של הרשומה הזאת.",
"flow-moderation-confirmation-suppress-topic": "הנושא הזה הועלם.",
"flow-moderation-confirmation-delete-topic": "הנושא הזה נמחק.",
"flow-moderation-confirmation-hide-topic": "הנושא הזה הוסתר.",
- "flow-moderation-confirmation-unsuppress-topic": "ביטלת בהצלחה את ההעלמה של הנושא הזה.",
- "flow-moderation-confirmation-undelete-topic": "ביטלת בהצלחה את המחיקה של הנושא הזה.",
- "flow-moderation-confirmation-unhide-topic": "ביטלת בהצלחה את ההסתרה של הנושא הזה.",
+ "flow-moderation-confirmation-unsuppress-topic": "ביטלת את ההעלמה של הנושא הזה.",
+ "flow-moderation-confirmation-undelete-topic": "ביטלת את המחיקה של הנושא הזה.",
+ "flow-moderation-confirmation-unhide-topic": "ביטלת את ההסתרה של הנושא הזה.",
"flow-moderation-title-suppress-topic": "להעלים את הנושא?",
"flow-moderation-title-delete-topic": "למחוק את הנושא?",
"flow-moderation-title-hide-topic": "להסתיר את הנושא?",
@@ -324,13 +395,13 @@
"flow-revision-permalink-warning-header-first": "זהו קישור קבוע לגרסה הראשונה של התיאור.\nבאפשרותך לראות גרסאות חדשות יותר ב[$2 דף ההיסטוריה של הלוח].",
"flow-compare-revisions-revision-header": "גרסה מאת $2 מ{{GRAMMAR:תחילית|$1}}",
"flow-compare-revisions-header-post": "הדף הזה מציג את ההבדלים בין שתי גרסאות של רשומה מאת $3 בנושא \"[$5 $2]\" בלוח [$4 $1].\n\nבאפשרותך לראות גרסאות אחרות של הרשומה הזאת ב[$6 דף ההיסטוריה] שלו.",
- "flow-compare-revisions-header-postsummary": "הדף הזה מראה את ההבדלים בין שתי גרסאות של סיכום רשומה ברשומה \"[$4 $2]\" בלוח [$3 $1].\nבאפשרותך לראות גרסאות אחרות של הרשומה ב[$5 דף ההיסטוריה שלה].",
+ "flow-compare-revisions-header-postsummary": "הדף הזה מציג את ההבדלים בין שתי גרסאות של הסיכום של הרשומה \"[$4 $2]\" בלוח [$3 $1].\nבאפשרותך לראות גרסאות אחרות של הרשומה ב[$5 דף ההיסטוריה שלה].",
"flow-compare-revisions-header-header": "הדף הזה מציג את {{GENDER:$2|ההבדלים}} בין שתי גרסאות של התיאור של [$3 $1]. אפשר לראות גרסאות אחרות של התיאור ב[$4 דף ההיסטוריה].",
- "action-flow-create-board": "ליצור לוחות זרימה בכל מיקום שהוא",
+ "action-flow-create-board": "ליצור לוחות זרימה בכל מקום",
"right-flow-create-board": "יצירת לוחות זרימה בכל מקום",
- "right-flow-hide": "הסתרת נושאים ברשומות בזרימה",
- "right-flow-lock": "סימון נושאים בזרימה בתור פתורים",
- "right-flow-delete": "מחיקת נושאים בזרימה",
+ "right-flow-hide": "הסתרת נושאים ורשומות בזרימה",
+ "right-flow-lock": "סימון נושאים בזרימה כ\"פתורים\"",
+ "right-flow-delete": "מחיקת נושאים ורשומות בזרימה",
"right-flow-edit-post": "עריכה רשומות זרימה של משתמשים אחרים",
"right-flow-suppress": "העלמת גרסאות בזרימה",
"flow-terms-of-use-new-topic": "לחיצה על \"{{int:flow-newtopic-save}}\" מהווה את הסכמתך לתנאי השימוש של הוויקי הזה.",
@@ -356,7 +427,7 @@
"flow-whatlinkshere-post": "מתוך [$1 רשומה]",
"flow-whatlinkshere-header": "מתוך [$1 התיאור]",
"flow-whatlinkshere-post-summary": "מה[$1 סיכום]",
- "flow": "זרימה",
+ "structureddiscussions": "זרימה",
"flow-special-desc": "הדף המיוחד הזה מפנה לזרימת עבודה של זרימה או לרשומה של זרימה דרך UUID.",
"flow-special-type": "סוג",
"flow-special-type-post": "רשומה",
@@ -370,10 +441,11 @@
"flow-special-enableflow-invalid-title": "ניתנה כותרת דף שגויה",
"flow-special-enableflow-board-creation-not-allowed": "אין לך הרשאה ליצור לוח זרימה בדף [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "יש דף LiquidThreads בשם [[:$1]].",
- "flow-special-enableflow-confirmation": "מיקמת בהצלחה לוח זרימה בדף [[$1]].",
+ "flow-special-enableflow-confirmation": "יצרת לוח זרימה בדף [[$1]].",
"flow-conversion-archive-page-name-format": "%s/ארכיון %d",
"flow-conversion-archive-flow-page-name-format": "%s/ארכיון זרימה %d",
- "flow-spam-confirmedit-form": "נא לאשר שאתה אנושי באמצעות פתרון התמונה להלן: $1",
+ "flow-spam-confirmedit-form": "אנא אשרו שאתם אנושיים באמצעות הקלדת האותיות שלהלן: $1",
+ "flow-spam-confirmedit-using-failure": "חלה שגיאה טכנית בפתרון ה־CAPTCHA. אם {{GENDER:|אינך מצליח|אינך מצליחה|אינכם מצליחים}} לבצע את השינוי, אנא {{GENDER:|העתק|העתיקי|העתיקו}} את הטקסט {{GENDER:|שלך|שלך|שלכם}}, {{GENDER:|טען|טעני|טענו}} את הדף מחדש, ולאחר מכן {{GENDER:|נסה|נסי|נסו}} שוב.",
"flow-embedding-unsupported": "בינתיים אין אפשרות להטמיע דיונים.",
"mw-ui-unsubmitted-confirm": "עשית בדף הזה שינויים ולא שלחת אותם. האם ברצונך לצאת מכאן ולעבד את עבודתך?",
"flow-post-undo-hide": "ביטול הסתרה",
@@ -387,118 +459,19 @@
"flow-importer-lqt-converted-template": "דף LQT מומר לזרימה",
"flow-importer-lqt-converted-template-content": "היסטוריית הדף הקודמת אורכבה לשם גיבוי ב<span class='flow-link-to-archive'>[[{{{archive}}}]]</span> ב־{{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-lqt-converted-archive-template": "ארכיון לדף LQT מאורכב",
- "flow-importer-lqt-converted-archive-template-content": "זהו דף LiquidThreads מאורכב. '''אין לערוך את תוכן הדף הזה'''. נא לכתוב תגובות נוספות ל[[{{{from}}}|דף השיחה הנוכחי]].",
+ "flow-importer-lqt-converted-archive-template-content": "זהו דף LiquidThreads מאורכב. <strong>אין לערוך את תוכן הדף הזה</strong>. נא לכתוב תגובות נוספות ל[[{{{from}}}|דף השיחה הנוכחי]].",
"flow-importer-wt-converted-template": "דף קוד ויקי מומר לזרימה",
"flow-importer-wt-converted-template-content": "דיונים קודמים אורכבו בדף <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> ב־{{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-wt-converted-archive-template": "ארכיון לדף קוד ויקי מומר",
- "flow-importer-wt-converted-archive-template-content": "הדף הזה הוא ארכיון. '''אין לערוך את תוכן הדף הזה'''. נא לכתוב תגובות נוספות ב[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|דף השיחה הנוכחי]].",
+ "flow-importer-wt-converted-archive-template-content": "הדף הזה הוא ארכיון. <strong>אין לערוך את תוכן הדף הזה</strong>. נא לכתוב תגובות נוספות ב[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|דף השיחה הנוכחי]].",
"flow-importer-lqt-suppressed-user-template": "רשות LQT שיובאה עם משמש מועלם",
"flow-importer-lqt-suppressed-user-template-content": "הגרסה הזאת יובאה מ־LiquidThreads עם משתמש מועלם. היא שויכה למשתמש הנוכחי.",
"flow-importer-lqt-different-author-signature-template": "רשומת LQT שיובאה עם חתימה של משתמש שונה",
- "flow-importer-lqt-different-author-signature-template-content": "''הרשומה הזאת נשלחה בתור [[User:{{{authorUser}}}|{{{authorUser}}}]], אבל נחתמה בתור [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "מאפשר ביצוע פעולות על דפים זרימה.",
- "apihelp-flow-param-submodule": "איזה תת-מודול של זרימה להפעיל.",
- "apihelp-flow-param-page": "באיזה דף ברצונך לפעול.",
- "apihelp-flow-example-1": "עריכת התיאור של \"[[Talk:Sandbox]]\"",
- "apihelp-flow+close-open-topic-description": "הוכרז המיושן לטובת [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "באיזה מצב לשים את הנושא, \"lock\" או \"unlock\".",
- "apihelp-flow+close-open-topic-param-reason": "סיבה לנעילה או פתיחת נעילה של נושא.",
- "apihelp-flow+edit-header-description": "עריכת תיאור לוח.",
- "apihelp-flow+edit-header-param-prev_revision": "מזהה הגרסה של גרסת התיאור הנוכחית, כדי לבדוק אם יש התנגשויות עריכה.",
- "apihelp-flow+edit-header-param-content": "תוכן לתיאור",
- "apihelp-flow+edit-header-param-format": "תסדיר התיאור (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "עריכת התיאור של [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "עריכת תוכן של רשומה.",
- "apihelp-flow+edit-post-param-postId": "מזהה רשומה.",
- "apihelp-flow+edit-post-param-prev_revision": "מזהה הגרסה של גרסת הרשומה הנוכחית, כדי לבדוק אם יש התנגשויות עריכה.",
- "apihelp-flow+edit-post-param-content": "תוכן לרשומה.",
- "apihelp-flow+edit-post-param-format": "תסדיר תוכן הרשומה (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "עריכת רשומה ב־[[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "עריכת כותרת של נושא",
- "apihelp-flow+edit-title-param-prev_revision": "מזהה גרסה של גרסת הכותרת הנוכחית, כדי לבדוק התנגשויות עריכה.",
- "apihelp-flow+edit-title-param-content": "תוכן לכותרת.",
- "apihelp-flow+edit-title-example-1": "עריכת הכותרת של [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "עריכת תוכן סיכום נושא",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "מזהה גרסה של הגרסה הנוכחית של סיכום הנושא, אם יש כזה, כדי לבדוק התנגשויות עריכה.",
- "apihelp-flow+edit-topic-summary-param-summary": "תוכן הסיכום.",
- "apihelp-flow+edit-topic-summary-param-format": "תסדיר הסיכום (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "עריכת הסיכום של [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "נעילה או פתיחת נעילה של נושא בזרימה.",
- "apihelp-flow+lock-topic-param-moderationState": "באיזה מצב לשים את הנושא, <kbd>lock</kbd> או לא <kbd>unlock</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "סיבה לנעילה או פתיחת נעילה של נושא. שימו לב שלקוח זרימה קורא לזה \"סימון בתור פתור\" ומוסיף מידע לסיכום.",
- "apihelp-flow+lock-topic-example-1": "נעילת [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "פיקוח על רשומת זרימה.",
- "apihelp-flow+moderate-post-param-moderationState": "באיזו רמה לפקח.",
- "apihelp-flow+moderate-post-param-reason": "סיבה לפיקוח.",
- "apihelp-flow+moderate-post-param-postId": "מזהה הרשומה שצריך לפקח עליה.",
- "apihelp-flow+moderate-post-example-1": "מחיקת רשומה בנושה [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "פיקוח על נושא בזרימה.",
- "apihelp-flow+moderate-topic-param-moderationState": "באיזו רמה לפקח.",
- "apihelp-flow+moderate-topic-param-reason": "סיבה לפיקוח.",
- "apihelp-flow+moderate-topic-example-1": "מחיקת הנושה [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "יצירת נושא זרימה חדש בזרם עבודה נתון.",
- "apihelp-flow+new-topic-param-topic": "טקסט לכותרת הנושא החדש.",
- "apihelp-flow+new-topic-param-content": "תוכן לתגובה ההתחלתית בנושא.",
- "apihelp-flow+new-topic-param-format": "תסדיר לתגובה ההתחלתית בנושא החדש (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "יצירת נושא חדש ב־[[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "תגובות לרשומה.",
- "apihelp-flow+reply-param-replyTo": "המזהה של הרשומה שצריך להשיב עליה.",
- "apihelp-flow+reply-param-content": "תוכן לרשומה החדשה.",
- "apihelp-flow+reply-param-format": "תסדיר לרשומה החדשה (wikitext|html)",
- "apihelp-flow+reply-example-1": "תגובה לרשימה ב־[[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "באיזה תסדיר להחזיר את התוכן.",
- "apihelp-flow+view-header-description": "הצגת תיאור הלוח.",
- "apihelp-flow+view-header-param-revId": "טעינת הגרסה הזאת, ולא האחרונה.",
- "apihelp-flow+view-header-example-1": "אחזור התיאור של [[Talk:Sandbox]] בתור קוד ויקי",
- "apihelp-flow+view-post-description": "הצגת רשומה.",
- "apihelp-flow+view-post-param-postId": "מזהה הרשומה שרצים להציג.",
- "apihelp-flow+view-post-param-format": "באיזה תסדיר להחזיר את התוכן.",
- "apihelp-flow+view-post-example-1": "אחזור תוכן הרשומה ב־[[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
- "apihelp-flow+view-post-history-description": "הצגת היסטוריית הגרסאות של הרשומה.",
- "apihelp-flow+view-post-history-param-postId": "מזהה הרשומה שעבורה ברצונך לראות את היסטוריית הגרסאות.",
- "apihelp-flow+view-post-history-param-format": "באיזה תסדיר להחזיר את התוכן.",
- "apihelp-flow+view-post-history-example-1": "אחזור גרסאות של רשומה בנושא [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
- "apihelp-flow+view-topic-description": "תצוגת נושא.",
- "apihelp-flow+view-topic-example-1": "תצוגת [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "הצגת היסטוריית הגרסאות של נושא.",
- "apihelp-flow+view-topic-history-param-format": "באיזה תסדיר להחזיר את התוכן.",
- "apihelp-flow+view-topic-history-example-1": "הצגת גרסאות של רשומות בנושא [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
- "apihelp-flow+view-topic-summary-description": "הצגת סיכום נושא.",
- "apihelp-flow+view-topic-summary-param-format": "באיזה תסדיר להחזיר את התוכן.",
- "apihelp-flow+view-topic-summary-param-revId": "טעינת הגרסה הזאת, ולא האחרונה.",
- "apihelp-flow+view-topic-summary-example-1": "הצגת הסיכום של [[Topic:S2tycnas4hcucw8w]] בתור קוד ויקי",
- "apihelp-flow+view-topiclist-description": "הצגת רשימת נושאים.",
- "apihelp-flow+view-topiclist-param-offset-dir": "באיזה סדר למיין את הנושאים.",
- "apihelp-flow+view-topiclist-param-sortby": "אפשרות המיון של הנושאים, לפי <kbd>updated</kbd> (מיון לפי זמן העדכון הנושא), או <kbd>newest</kbd> (לפי זמן יצירת הנושא).",
- "apihelp-flow+view-topiclist-param-savesortby": "שמירת האפשרות \"sortby\" להעדפות, אם היא מוגדרת.",
- "apihelp-flow+view-topiclist-param-offset-id": "ערך ההיסט (בתסדיר UUID) שבו יתחיל אחזור הנושאים; משמש רק עם מיון <kbd>newest</kbd>.",
- "apihelp-flow+view-topiclist-param-offset": "ערך ההיסט (בתסדיר חותם זמן <code>TS_MW</code> (כלומר <code>YYYYMMDDHHMMSS</code>)), שבו יתחיל אחזור הנושאים; משמש רק עם מיון <kbd>updated</kbd>.",
- "apihelp-flow+view-topiclist-param-limit": "כמה נושאים לאחזר.",
- "apihelp-flow+view-topiclist-example-1": "לקבל רשימת נושאים ב־[[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "להמיר טקסט בין קוד ויקי לבין HTML.",
- "apihelp-flow-parsoid-utils-param-from": "מאיזה תסדיר להמיר את התוכן.",
- "apihelp-flow-parsoid-utils-param-to": "לאיזה תסדיר להמיר את התוכן.",
- "apihelp-flow-parsoid-utils-param-content": "איזה תוכן להמיר.",
- "apihelp-flow-parsoid-utils-param-title": "כותרת הדף. לא ניתן לשימוש יחד עם $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "מזהה הדף. לא יכול לשמש יחד עם $1pageid.",
- "apihelp-flow-parsoid-utils-example-1": "המרת קוד הוויקי <nowiki>'''lorem''' ''blah''</nowiki> ל־HTML",
- "apihelp-query+flowinfo-description": "קבלת מידע זרימה בסיסי על דף.",
- "apihelp-query+flowinfo-example-1": "אחזור מידע זרימה על [[Talk:Sandbox]]‏, [[Main Page]], ו־[[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "אחזור המידע הנחוץ לביטול עריכות של התיאור.",
- "apihelp-flow+undo-edit-header-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
- "apihelp-flow+undo-edit-header-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
- "apihelp-flow+undo-edit-header-example-1": "אחזור מידע על ביטול עריכת תיאור ב־[[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "אחזור המידע הנחוץ לביטול עריכת רשומה.",
- "apihelp-flow+undo-edit-post-param-postId": "מזהה של הרשומה שצריך לבטל.",
- "apihelp-flow+undo-edit-post-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
- "apihelp-flow+undo-edit-post-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
- "apihelp-flow+undo-edit-post-example-1": "אחזור מידע על ביטול עריכת רשומה בנושא מסוים.",
- "apihelp-flow+undo-edit-topic-summary-description": "אחזור מידע נחוץ לביטול עריכות הסיכום.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "באיזה מזהה גרסה להתחיל את הביטול.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "באיזה מזהה גרסה לסיים את הביטול.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "אחזור מידע על ביטול עריכת סיכום נושא בנושא מסוים",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>הרשומה הזאת נשלחה בתור [[User:{{{authorUser}}}|{{{authorUser}}}]], אבל נחתמה בתור [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "נערכה",
"flow-edited-by": "נערכה על־ידי $1",
+ "flow-edited-by-header": "תיאור הלוח נערך על־ידי $1",
+ "flow-edited-by-topic-title": "כותרת הנושא נערכה על־ידי $1",
"flow-lqt-redirect-reason": "הפניה של רשומת LiquidThreads מיושנת לרשומת זרימה מומרת",
"flow-talk-conversion-move-reason": "המרה של שיחה בקוד מקור לזרימה מהדף $1",
"flow-talk-conversion-archive-edit-reason": "המרה משיחה בקוד וויקי לזרימה",
@@ -510,8 +483,8 @@
"flow-undo-edit-header": "עריכת התיאור",
"flow-undo-edit-topic-summary": "עריכת סיכום הנושא",
"flow-undo-edit-post": "עריכת רשומה",
- "flow-undo-edit-content": "ניתן לבטל את העריכה. נא לבדוק את השוואת הגרסאות למטה כדי לוודא שזה מה שרצית לעשות, ואז לשמור את השינויים למטה כדי לסיים את ביטול העריכה.",
- "flow-undo-edit-failure": "לא היה אפשר לבטל את העריכה עקב התנגשות עם עריכות שנעשו בינתיים.",
+ "flow-undo-edit-content": "ניתן לבטל את העריכה. אנא בִּדקו את השוואת הגרסאות למטה כדי לוודא שזה אכן מה שאתם רוצים לעשות, ואז שִׁמרו את השינויים למטה כדי לסיים את ביטול העריכה.",
+ "flow-undo-edit-failure": "לא ניתן היה לבטל את העריכה עקב התנגשות עם עריכות מאוחרות יותר.",
"group-flow-bot": "בוטי זרימה",
"group-flow-bot-member": "בוט זרימה",
"grouppage-flow-bot": "Project:בוטי זרימה",
@@ -524,7 +497,7 @@
"flow-ve-mention-inspector-invalid-user": "שם המשתמש \"$1\" אינו רשום.",
"flow-wikitext-editor-help": "קוד ויקי $1.",
"flow-wikitext-editor-help-and-preview": "קוד ויקי $1 ובאפשרותך $2 בכל זמן.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|משתמש בשפת עיצוב]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|משתמש בשפת עיצוב]]",
"flow-wikitext-editor-help-preview-the-result": "לראות תצוגה מקדימה של התוצאה",
"flow-wikitext-switch-editor-tooltip": "מעבר לעורך החזותי",
"flow-ve-switch-editor-tool-title": "מעבר לעורך קוד ויקי",
@@ -533,21 +506,27 @@
"flow-mark-diff-patrolled-link-text": "סימון השינוי כבדוק",
"flow-mark-diff-patrolled-link-title": "סימון השינוי כבדוק",
"flow-talk-page-beta-feature-message": "זרימה בדף השיחה",
- "flow-talk-page-beta-feature-description": "הפעלת מערכת דיונים מובנית בדף שיחת המשתמש שלך. זרימה מפשטת את הדיונים בדפי השיחה עם מקומות ברורים לכתיבה ולתשובה ומאפשרת התראות ברמת שיחה. דיונים קיימים בקוד ויקי מועברים לארכיון. האפשרות הזאת לא מופעלת באופן אוטומטי; משתמשים יצטרכו להפעיל אותה פרטנית. כיבוי האפשרות הזאת יעביר את לוח הזרימה לדף־משנה ויוציא את דף השיחה הקודם מהארכיון.",
+ "flow-talk-page-beta-feature-description": "הפעלת מערכת דיונים מובנית בדף שיחת המשתמש שלך. זרימה מפשטת את הדיונים בדפי השיחה עם מקומות ברורים לכתיבה ולתשובה ומאפשרת התראות ברמת שיחה. האפשרות הזאת לא מופעלת באופן אוטומטי; משתמשים יצטרכו להפעיל אותה באופן פרטני.<br /><br />דיונים קיימים בקוד ויקי מועברים לארכיון. כיבוי האפשרות הזאת יעביר את לוח הזרימה לדף־משנה ויוציא את דף השיחה הקודם מהארכיון. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|מידע נוסף על הפעלה]].",
"flow-notification-link-text-enabled-on-talkpage": "הצגת דף שיחת המשתמש",
"flow-notification-enabled-on-talkpage-title": "מערכת דיונים חדשה הופעלה עבור דף המשתמש {{GENDER:$1|שלך}}<br /><small>זמין בדף [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "מערכת דיונים חדשה בדף $2",
"flow-notification-enabled-on-talkpage-email-batch-body": "זרימה, מערכת הדיונים החדשה לוויקי, הופעלה בדך השיחה {{GENDER:$1|שלך}} ב{{GRAMMAR:תחילית{{SITENAME}}}}. באפשרותך לקבל יותר מידע, לשלוח משוב או לכבות את מערכת דפי השיחה החדשה בכל זמן דרך לשונית בטא בהעדפות {{GENDER:$1|שלך}}.",
"flow-beta-feature-add-archive-template-edit-summary": "הוספת תבנית ארכיון",
"flow-beta-feature-remove-archive-template-edit-summary": "הסרת תבנית ארכיון",
- "flow-dialog-cancelconfirm-title": "באמת?",
- "flow-dialog-cancelconfirm-message": "האם ברצונך באמת לבטל בלי לשמור תחילה?",
+ "flow-dialog-cancelconfirm-title": "האם {{GENDER:|אתה בטוח|את בטוחה}}?",
+ "flow-dialog-cancelconfirm-message": "האם {{GENDER:|אתה בטוח שאתה|את בטוחה שאת}} לבטל בלי לשמור תחילה?",
"flow-dialog-cancelconfirm-keep": "להמשיך לערוך",
"flow-dialog-cancelconfirm-discard": "זריקת שינויים",
+ "flow-optin-archive-wikitext": "העברת קובץ עם קוד ויקי כדי לפנות מקום ללוח דיונים.",
+ "flow-optin-archive-flow-board": "העברת דף עם לוח דיונים כדי לפנות מקום לקובץ עם קוד ויקי.",
+ "flow-optin-restore-wikitext": "שחזור דף קוד ויקי מאורכב.",
+ "flow-optin-restore-flow-board": "שחזור לוח דיונים מאורכב.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|ברוך הבא|ברוכה הבאה}} לדף השיחה החדש שלך",
"flow-guidedtour-optin-welcome-description": "דף השיחה {{GENDER:$1|שלך}} הוא המקום שבו עורכים אחרים יכולים ליצר אתך קשר. עם זימה, קל יותר להתחיל נושאים חדשים ולעקוב אחרי שיחות.",
"flow-guidedtour-optin-find-old-conversations": "כאן מוצאים את השיחות הישנות {{GENDER:$1|שלך}}.",
"flow-guidedtour-optin-find-old-conversations-description": "השיחות הקודמות הועברו לדף ארכיון.",
"flow-guidedtour-optin-feedback": "{{GENDER:$1|תן|תני}} לנו את המשוב שלך!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|אתה יכול|את יכולה}} לקבל יותר מידע, לשלוח משוב, או לכבות את המערכת החדשה באזור אפשרויות הבטא שלך."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|אתה יכול|את יכולה}} לקבל יותר מידע, לשלוח משוב, או לכבות את המערכת החדשה באזור אפשרויות הבטא שלך.",
+ "flow-action-not-page": "עצם הדף הוא מופע של המחלקה הלא־נכונה",
+ "flow-action-wrong-title-content-model": "הדף הזה מטופל על־ידי זרימה, אבל מהשימוש במחלקה Title משתמע שמודל התוכן הוא '$1'. זוהי הגדרה שגויה או מצב בלתי־עקבי. למשל, ייתכן שזה דף שאינו דף זרימה במרחב שם שכן משתמש בזרימה, וב־<code>rev_content_model</code> אין תוכן."
}
diff --git a/Flow/i18n/hi.json b/Flow/i18n/hi.json
index 3596aa4b..49434868 100644
--- a/Flow/i18n/hi.json
+++ b/Flow/i18n/hi.json
@@ -4,94 +4,335 @@
"Vivek Rai",
"संजीव कुमार",
"Phoenix303",
- "NehalDaveND"
+ "NehalDaveND",
+ "Sfic",
+ "चक्रपाणी",
+ "हिंदुस्थान वासी",
+ "Jayprakash12345",
+ "Anamdas",
+ "Sachinkatiyar"
]
},
- "enableflow": "प्रवाह को सक्षम करें",
+ "enablestructureddiscussions": "प्रवाह को सक्षम करें",
+ "notification-dynamic-actions-flow-board-unwatch": "\"$1\" में नई गतिविधि देखना {{GENDER:$3|बंद}} करें",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|आप}} अब \"$1\" पन्ने को ध्यानसूची से हटा चुके हैं।",
+ "notification-dynamic-actions-flow-topic-unwatch": "इस विषय को देखना {{GENDER:$3|बंद}} करें",
+ "flow-desc": "चर्चा प्रणाली",
+ "log-name-flow": "फ्लो गतिविधि लॉग",
+ "logentry-delete-flow-delete-topic": "$1 ने [[$6]] पर \"[[$3|$5]]\" विषय को {{GENDER:$2|हटा}} दिया।",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 ने [[$3]] पर विषय को {{GENDER:$2|हटा}} दिया।",
+ "logentry-suppress-flow-restore-topic": "$1 ने [[$6]] पर \"[[$3|$5]]\" विषय को {{GENDER:$2|हटा}} दिया।",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 ने [[$3]] पर विषय को {{GENDER:$2|हटा}} दिया।",
+ "logentry-lock-flow-lock-topic": "$1 ने [[$6]] पर \"[[$3|$5]]\" विषय को हल हुआ {{GENDER:$2|चिन्हित}} किया।",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 ने [[$3]] पर विषय को हल हुआ {{GENDER:$2|चिन्हित}} किया।",
+ "logentry-lock-flow-restore-topic": "$1 ने [[$6]] पर \"[[$3|$5]]\" विषय को {{GENDER:$2|फिर खोल}} दिया।",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 ने [[$3]] पर विषय को {{GENDER:$2|फिर खोल}} दिया।",
+ "abusefilter-edit-builder-vars-board-articleid": "फ्लो पटल का पृष्ठ आईडी",
+ "abusefilter-edit-builder-vars-board-namespace": "फ्लो पटल का नामस्थान",
+ "abusefilter-edit-builder-vars-board-text": "फ्लो पटल का शीर्षक",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "फ्लो पटल का पूरा शीर्षक",
+ "flow-user-moderated": "जाँचा हुआ सदस्य",
+ "flow-board-header-browse-topics-link": "विषय ब्राउज़ करें",
+ "flow-board-header": "इस पटल के बारे में",
+ "flow-board-description-can-not-edit": "संपादन योग्य नहीं",
"flow-board-collapse-description": "विवरण छिपाएं",
"flow-board-expand-description": "विवरण दिखाएं",
+ "flow-topic-collapse-siderail": "पूरी चौड़ाई में पढ़ें",
+ "flow-topic-expand-siderail": "निश्चित चौड़ाई में पढ़ें",
+ "flow-edit-header-link": "विवरण सम्पादित करें",
+ "flow-post-moderated-toggle-hide-show": "$2 द्वारा {{GENDER:$1|छुपाई}} गई टिप्पणी दिखाएँ",
+ "flow-post-moderated-toggle-delete-show": "$2 द्वारा {{GENDER:$1|हटाई}} गई टिप्पणी दिखाएँ",
+ "flow-post-moderated-toggle-suppress-show": "$2 द्वारा {{GENDER:$1|सप्रेस की}} गई टिप्पणी दिखाएँ",
+ "flow-post-moderated-toggle-hide-hide": "$2 द्वारा {{GENDER:$1|छुपाई}} गई टिप्पणी छुपाएँ",
+ "flow-post-moderated-toggle-delete-hide": "$2 द्वारा {{GENDER:$1|हटाई}} गई टिप्पणी छुपाएँ",
+ "flow-post-moderated-toggle-suppress-hide": "$2 द्वारा {{GENDER:$1|सप्रेस की}} गई टिप्पणी छुपाएँ",
"flow-topic-moderated-reason-prefix": "कारण :",
+ "flow-hide-post-content": "$1 ने इस टिप्पणी को {{GENDER:$1|छुपा}} दिया ([$2 इतिहास])",
+ "flow-hide-title-content": "$1 ने इस विषय को {{GENDER:$1|छुपा}} दिया",
+ "flow-hide-header-content": "$2 ने {{GENDER:$1|छुपा}} दिया",
+ "flow-delete-post-content": "$1 ने इस टिप्पणी को {{GENDER:$1|हटा}} दिया ([$2 इतिहास])",
+ "flow-delete-title-content": "$1 ने इस विषय को {{GENDER:$1|हटा}} दिया",
+ "flow-delete-header-content": "$2 ने {{GENDER:$1|हटा}} दिया",
+ "flow-suppress-post-content": "$1 ने इस टिप्पणी को {{GENDER:$1|सप्रेस}} कर दिया ([$2 इतिहास])",
+ "flow-suppress-title-content": "$1 ने इस विषय को {{GENDER:$1|सप्रेस}} कर दिया",
+ "flow-suppress-header-content": "$2 ने {{GENDER:$1|सप्रेस}} कर दिया",
+ "flow-suppress-usertext": "<em>सदस्य नाम सप्रेस</em>",
"flow-post-actions": "क्रिया",
"flow-topic-actions": "क्रिया",
"flow-cancel": "रद्द करें",
+ "flow-skip-summary": "छोड़ें",
+ "flow-edit-summary-placeholder": "संक्षेप में इस चर्चा के परिणाम का वर्णन करें",
+ "flow-summary-authored": "$1 द्वारा सारांश",
+ "flow-summary-edited": "सारांश अन्तिम बार $1 द्वारा {{GENDER:$1|संपादित}} किया गया।",
"flow-show-change": "बदलाव दिखाएँ",
+ "flow-last-modified-by": "अंतिम बार $1 जी ने {{GENDER:$1|बदला}} था।",
+ "flow-stub-post-content": "<em>तकनीकी त्रुटि के कारण, इस पोस्ट को पुनर्प्राप्त नहीं किया जा सका।</em>",
"flow-newtopic-title-placeholder": "नया विषय",
+ "flow-newtopic-content-placeholder": "\"$1\" पर संदेश भेजें",
"flow-newtopic-header": "नया विषय जोडा",
"flow-newtopic-save": "विषय जोड़ें",
+ "flow-newtopic-save-anonymously": "अनाम रूप से विषय जोड़ें",
+ "flow-newtopic-start-placeholder": "नया विषय शुरू करें",
"flow-newtopic-first-heading": "$1 पर नया विषय आरम्भ करें",
+ "flow-summarize-topic-placeholder": "इस चर्चा को संक्षेप में प्रस्तुत करें",
+ "flow-reply-topic-placeholder": "\"$2\" पर {{GENDER:$1|टिप्पणी}}",
"flow-reply-topic-title-placeholder": "\"$1\" के उत्तर दें",
- "flow-reply-submit": "{{GENDER:$1|उत्तर दें}}",
"flow-reply-link": "{{GENDER:$1|उत्तर दें}}",
+ "flow-reply-link-anonymously": "अनाम रूप से उत्तर दें",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|धन्यवाद दें}}}}",
- "flow-lock-link": "{{GENDER:$1|अवरोध}}",
+ "flow-thank-link-title": "पोस्ट करने वाले को सार्वजनिक {{GENDER:$1|{{GENDER:$2|धन्यवाद}}}} दें",
"flow-history-action-suppress-post": "दबाएँ",
"flow-history-action-delete-post": "निकाले",
"flow-history-action-hide-post": "छुपाएँ",
+ "flow-history-action-unsuppress-post": "असप्रेस",
"flow-history-action-undelete-post": "हटाना वापस लें",
"flow-history-action-unhide-post": "दिखाएँ",
"flow-history-action-restore-post": "पुनःस्थापित करें",
- "flow-history-action-lock-topic": "अवरोध",
- "flow-history-action-unlock-topic": "अवरोध हटाएँ",
+ "flow-history-action-lock-topic": "हल हुआ",
+ "flow-history-action-unlock-topic": "फिर खोला",
+ "flow-post-edited": "पोस्ट $1 द्वारा $2 संपादित हुआ",
+ "flow-post-action-view": "स्थायीकड़ी",
"flow-post-action-post-history": "इतिहास",
"flow-post-action-suppress-post": "दबाएँ",
"flow-post-action-delete-post": "हटाएँ",
"flow-post-action-hide-post": "छुपाएँ",
"flow-post-action-edit-post": "सम्पादन करें",
"flow-post-action-edit-post-submit": "बदलाव सहेजें",
+ "flow-post-action-edit-post-submit-anonymously": "अज्ञात रहकर बदलाव सहेजें",
+ "flow-post-action-unsuppress-post": "असप्रेस",
"flow-post-action-undelete-post": "हटाना वापस लें",
"flow-post-action-unhide-post": "दिखाएँ",
"flow-post-action-restore-post": "पुनःस्थापित करें",
"flow-post-action-undo-moderation": "पूर्ववत्",
+ "flow-topic-action-view": "स्थायीकड़ी",
"flow-topic-action-watchlist": "ध्यानसूची",
+ "flow-topic-action-edit-title": "शीर्षक संपादित करें",
"flow-topic-action-history": "इतिहास",
+ "flow-topic-action-hide-topic": "विषय छुपाएँ",
+ "flow-topic-action-delete-topic": "विषय हटाएँ",
+ "flow-topic-action-lock-topic": "हल हुआ चिन्हित करें",
+ "flow-topic-action-unlock-topic": "विषय फिर से खोलें",
"flow-topic-action-summarize-topic": "सारांश",
+ "flow-topic-action-resummarize-topic": "विषय सारांश संपादित करें",
+ "flow-topic-action-update-topic-summary": "सारांश अद्यतन करें",
+ "flow-topic-action-suppress-topic": "विषय सप्रेस करें",
+ "flow-topic-action-unhide-topic": "विषय दिखाएँ",
+ "flow-topic-action-undelete-topic": "विषय पुनः स्थापित करें",
+ "flow-topic-action-unsuppress-topic": "विषय असप्रेस करें",
+ "flow-topic-action-restore-topic": "विषय स्थापित करें",
"flow-topic-action-undo-moderation": "पूर्ववत करें",
+ "flow-topic-notification-subscribe-title": "यह विषय {{GENDER:$1|आपकी}} ध्यानसूची में जोड़ा गया।",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|आप}} इस विषय की सभी गतिविधियों पर सूचनाएँ प्राप्त करेंगे।",
+ "flow-topic-action-watchlist-add": "इस विषय की सदस्यता लें",
+ "flow-topic-action-watchlist-remove": "सदस्यता रद्द करें",
+ "flow-error-allowcreation-flow-create-board": "सदस्य के पास \"{{int:right-flow-create-board}}\" अधिकार नहीं है।",
+ "flow-error-can-not-edit-logged-out": "आप वर्तमान में इसमें भाग लेने में सक्षम नहीं हैं। आप लॉग इन करने का प्रयास कर सकते हैं।",
+ "flow-error-can-not-edit-logged-in": "आप वर्तमान में इसमें भाग लेने में सक्षम नहीं हैं, क्योंकि आपके पास आवश्यक अधिकार नहीं हैं।",
+ "flow-error-http": "सर्वर से संपर्क करते समय कोई त्रुटि हुई।",
+ "flow-error-external": "कोई त्रुटि हुई। $1 प्राप्त त्रुटि संदेश था।",
+ "flow-error-topic-is-locked": "इस विषय का हल हो गया है, इसलिए आगे की गतिविधि संभव नहीं है।",
+ "flow-error-missing-content": "पोस्ट में कोई सामग्री नहीं है। पोस्ट को सहेजने के लिए सामग्री की आवश्यकता है।",
+ "flow-error-missing-summary": "आपको सारांश भी देना होगा।",
+ "flow-error-missing-title": "विषय का कोई शीर्षक नहीं है। विषय सहेजने के लिए शीर्षक जरूरी है।",
+ "flow-error-protected-autoconfirmed-logged-in": "यह पटल सुरक्षित है, केवल स्वतःस्थापित सदस्य ही इसमें शामिल हो सकते हैं। कारण : $1",
+ "flow-error-protected-autoconfirmed-logged-out": "यह पटल सुरक्षित है, केवल स्वतःस्थापित सदस्य ही खाते में प्रवेश कर शामिल हो सकते हैं। कारण : $1",
+ "flow-error-protected-sysop-logged-in": "यह पटल सुरक्षित है, केवल प्रबन्धक अधिकार वाले सदस्य ही इसमें शामिल हो सकते हैं। कारण : $1",
+ "flow-error-protected-sysop-logged-out": "यह पटल सुरक्षित है, केवल प्रबन्धक अधिकार वाले सदस्य ही खाते में प्रवेश कर शामिल हो सकते हैं। कारण : $1",
+ "flow-error-protected-unknown-reason": "अज्ञात",
+ "flow-error-not-allowed": "इस क्रिया को अंजाम देने के लिए पर्याप्त अधिकार मौजूद नहीं।",
+ "flow-error-not-allowed-hide": "यह विषय छुपाया गया है।",
+ "flow-error-not-allowed-reply-to-hide-topic": "आप इस विषय में उत्तर नहीं दे सकते क्योंकि इस विषय को छिपा दिया गया है।",
+ "flow-error-not-allowed-delete": "यह विषय हटाया गया है।",
+ "flow-error-not-allowed-reply-to-delete-topic": "आप इस विषय में उत्तर नहीं दे सकते है, क्योंकि यह हटा दिया गया है।",
+ "flow-error-not-allowed-suppress": "यह विषय हटाया गया है।",
+ "flow-error-not-allowed-reply-to-suppress-topic": "आप इस विषय में उत्तर नहीं दे सकते है, क्योंकि यह हट चुका है।",
+ "flow-error-not-allowed-delete-extract": "यह विषय हटाया जा चुका है। पृष्ठ के हटाने का लॉग संदर्भ के लिए नीचे दिया गया है।",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "आप उत्तर नहीं दे सकते क्योंकि यह विषय हटाया जा चुका है। पृष्ठ के हटाने का लॉग संदर्भ के लिए नीचे दिया गया है।",
+ "flow-error-not-allowed-suppress-extract": "यह विषय हटाया जा चुका है। पृष्ठ के हटाने का लॉग संदर्भ के लिए नीचे दिया गया है।",
+ "flow-error-no-existing-workflow": "यह वर्कफ्लो उपस्थित नहीं है।",
+ "flow-error-not-a-post": "विषय का शीर्षक पोस्ट के रूप में नहीं सहेजा जा सकता है।",
+ "flow-error-missing-header-content": "आपको विवरण भी देना होगा।",
+ "flow-error-missing-prev-revision-identifier": "पिछले अवतरण ज्ञात करने वाला गुम है।",
+ "flow-error-prev-revision-mismatch": "अभी कुछ समय पहले किसी ने इस पोस्ट पर लिखा था, क्या {{GENDER:$3|आप}} उस बदलाव के ऊपर अपना सम्पादन करना चाहते हैं?",
+ "flow-error-prev-revision-does-not-exist": "पिछला अवतरण नहीं मिला",
+ "flow-error-core-topic-deletion": "विषय हटाने हेतु कृपया ... मेनू में फ्लो बोर्ड या [$1 विषय पृष्ठ] पर जाएँ, सीधे action=delete के द्वारा न हटायें",
+ "flow-error-default": "त्रुटि उत्पन्न हुआ",
+ "flow-error-invalid-input": "फ्लो जानकारी लोड करने हेतु गलत मान दिया गया।",
+ "flow-error-invalid-title": "अमान्य पृष्ठ शीर्षक दिया गया",
+ "flow-error-invalid-parameter": "कॉल विधि हेतु गुम या अमान्य प्राचल का उपयोग हुआ",
+ "flow-error-fail-load-history": "सामग्री इतिहास लोड करने में विफल।",
+ "flow-error-missing-revision": "फ्लो सामग्री हेतु कोई अवतरण नहीं मिला",
+ "flow-error-fail-commit": "फ्लो सामग्री सहेजने में विफल।",
+ "flow-error-insufficient-permission": "सामग्री देखने हेतु अपर्याप्त अधिकार।",
+ "flow-error-revision-comparison": "अंतर आप तभी देख सकते हैं, जब एक ही पोस्ट के दो अवतरण हों।",
+ "flow-error-missing-topic-title": "वर्तमान वर्कफ्लो हेतु विषय का शीर्षक नहीं मिला",
+ "flow-error-missing-metadata": "इस अवतरण हेतु अनिवार्य मेटाडाटा नहीं मिला",
+ "flow-error-different-page": "फ्लो वर्कफ्लो इस पृष्ठ से जुड़ा नहीं है।",
+ "flow-error-fail-load-data": "अनुरोधित डाटा लोड होने में विफल",
+ "flow-error-invalid-workflow": "अनुरोधित वर्कफ्लो नहीं मिला",
+ "flow-error-process-data": "आपके अनुरोध अनुसार डाटा प्राप्त करने में त्रुटि हुई।",
+ "flow-error-process-wikitext": "एचटीएमएल/विकिपाठ में बदलने के समय त्रुटि हुई।",
+ "flow-error-no-index": "डाटा खोजने हेतु इंडेक्स नहीं मिला",
+ "flow-error-no-render": "अनुरोधित कार्य समझ नहीं आया",
+ "flow-error-no-commit": "अनुरोधित कार्य सहेजा नहीं जा सका।",
+ "flow-error-content-too-long": "सामग्री बहुत अधिक है। सामग्री विस्तार के बाद $1 {{PLURAL:$1|बाइट|बाइट्स}} पर सीमित है।",
+ "flow-error-move-topic": "विषय का स्थानांतरण अभी संभव नहीं है।",
+ "flow-error-invalid-topic-uuid-title": "बेकार शीर्षक",
+ "flow-error-invalid-topic-uuid": "अनुरोधित पृष्ठ शीर्षक अमान्य है। विषय नामस्थान के पृष्ठ फ्लो द्वारा अपने आप बनते हैं।",
"flow-error-unknown-workflow-id-title": "अज्ञात विषय",
- "flow-summarize-topic-submit": "सारांश",
- "flow-summarize-topic-submit-overwrite": "सारांश पर लिखेँ",
- "flow-lock-topic-submit": "विषय अवरोध",
- "flow-unlock-topic-submit": "विषय का अवरोध हटाएँ",
+ "flow-error-unknown-workflow-id": "अनुरोधित विषय उपलब्ध नहीं है।",
+ "flow-error-search": "अस्थाई परेशानी के कारण हम आपके खोज को पूरा नहीं कर सके। कृपया थोड़ी देर बाद प्रयास करें।",
+ "flow-edit-header-placeholder": "चर्चा पटल का वर्णन करें",
+ "flow-edit-header-submit": "विवरण सहेजें",
+ "flow-edit-header-submit-anonymously": "विवरण अज्ञात रहकर सहेजें",
"flow-edit-title-submit": "विषय बदलें",
+ "flow-edit-title-submit-anonymously": "शीर्षक अज्ञात रहकर बदलें",
"flow-edit-post-submit": "बदलाव जमा करें",
+ "flow-edit-post-submit-anonymously": "अज्ञात रहकर बदलाव करें",
+ "flow-rev-message-new-post-recentchanges-summary": "नया विषय {{GENDER:$2|बनाया गया}}",
+ "flow-rev-message-create-header": "$1 ने विवरण {{GENDER:$2|बनाया}}",
+ "flow-rev-message-edit-header": "$1 ने विवरण {{GENDER:$2|संपादित}} किया",
"flow-rev-message-deleted-post": "$1 {{GENDER:$2|हटाया हुआ}} एक [ $4 टिप्पणी] पर $6 (<em> $5 </em>)।",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|हटाया हुआ}} [ $4 विषय] $6 (<em> $5 </em>)।",
+ "flow-rev-message-lock-topic-reason": "हल हुआ चिन्हित करें",
+ "flow-rev-message-restore-topic-reason": "फिर खोला गया",
"flow-rc-topic-of-board": "$2 पर $1",
"flow-board-history": "\"$1\" इतिहास",
+ "flow-topic-history": "\"$1\" विषय का इतिहास",
"flow-history-last4": "अन्तिम 4 घण्टे",
"flow-history-day": "आज",
"flow-history-week": "पिछले सप्ताह",
+ "flow-comment-restored": "वापस लाई टिप्पणी",
+ "flow-comment-deleted": "हटाई टिप्पणी",
+ "flow-comment-hidden": "छुपी टिप्पणी",
+ "flow-workflow": "वर्कफ्लो",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 और {{PLURAL:$5|एक अन्य सदस्य|$5 others|100=99+ सदस्यों}} ने <strong>$3</strong> पर {{GENDER:$1|उत्तर दिया।}}",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 ने आपके <span class=\"plainlinks\">[$5 पोस्ट]</span> पर [[$3|$4]] में {{GENDER:$1|सम्पादन}} किया।",
+ "notification-header-flow-post-reply": "$1 ने \"<strong>$4</strong>\" में {{GENDER:$2|उत्तर दिया}}।",
+ "notification-links-flow-description-edited-view-page": "पृष्ठ {{GENDER:$1|देखें}}",
+ "notification-email-subject-flow-description-edited": "$1 ने $2 का विवरण {{GENDER:$1|संपादित}} किया।",
+ "notification-email-batch-body-flow-description-edited": "$1 ने $2 का विवरण {{GENDER:$2|संपादित}} किया।",
+ "notification-header-flow-topic-resolved": "विषय \"<strong>$1</strong>\" हल हो चुका।",
+ "notification-header-flow-topic-reopened": "विषय \"<strong>$1</strong>\" फिर से खोला गया",
+ "notification-header-flow-topic-resolved-user-talk": "विषय \"<strong>$1</strong>\" <strong>आपके वार्ता पृष्ठ पर</strong> हल हो चुका।",
+ "notification-header-flow-topic-reopened-user-talk": "विषय \"<strong>$1</strong>\" <strong>आपके वार्ता पृष्ठ पर</strong> फिर खुल गया।",
+ "notification-email-subject-flow-topic-resolved": "विषय \"<strong>$2</strong>\" हल हो चुका",
+ "notification-email-batch-body-flow-topic-resolved": "विषय \"<strong>$2</strong>\" हल हो चुका",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 ने नया विषय <strong>$3</strong> में {{GENDER:$1|बनाया}}",
+ "flow-notification-link-text-view-post": "पोस्ट देखें",
"flow-notification-link-text-view-topic": "विषय देखें",
+ "flow-notification-link-text-view-topics": "विषय देखें",
"flow-notification-reply-email-subject": "$3 पर $2",
+ "flow-notification-mention-email-subject": "$1 ने $2 पर {{GENDER:$3|आपका}} {{GENDER:$1|उल्लेख}} किया।",
+ "flow-notification-edit-email-subject": "$1 ने पोस्ट {{GENDER:$1|संपादित}} किया",
+ "flow-notification-edit-email-batch-body": "$3 में \"$2\" पर $1 ने सम्पादन किया।",
+ "flow-notification-rename-email-subject": "$1 ने आपके विषय का नाम {{GENDER:$1|बदल दिया}}।",
+ "echo-category-title-flow-discussion": "फ्लो चर्चा",
+ "flow-link-post": "पोस्ट",
"flow-link-topic": "विषय",
"flow-link-history": "इतिहास",
"flow-link-post-revision": "पोस्ट अवतरण",
"flow-link-topic-revision": "विषय का अवतरण",
+ "flow-link-header-revision": "अवतरण का विवरण",
"flow-link-summary-revision": "सारांश संशोधन",
+ "flow-moderation-title-suppress-post": "पोस्ट सप्रेस करें?",
+ "flow-moderation-title-delete-post": "पोस्ट हटाएँ?",
+ "flow-moderation-title-hide-post": "पोस्ट छुपाएँ?",
+ "flow-moderation-title-unsuppress-post": "पोस्ट असप्रेस करें?",
+ "flow-moderation-title-undelete-post": "पोस्ट वापस लाएँ?",
+ "flow-moderation-title-unhide-post": "पोस्ट दिखाएँ?",
+ "flow-moderation-placeholder-suppress-post": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों पोस्ट सप्रेस करना चाहते हैं।",
+ "flow-moderation-placeholder-delete-post": "कृपया {{GENDER:$3|समझाएँ}} कि आप क्यों इस पोस्ट को हटा रहे हैं",
+ "flow-moderation-placeholder-hide-post": "कृपया {{GENDER:$3|समझाएँ}} कि आप पोस्ट को क्यों छुपाना चाह रहे",
+ "flow-moderation-confirm-suppress-post": "सप्रेस",
"flow-moderation-confirm-delete-post": "हटाएँ",
"flow-moderation-confirm-hide-post": "छुपाएँ",
+ "flow-moderation-confirm-unsuppress-post": "असप्रेस",
"flow-moderation-confirm-undelete-post": "हटाना वापस लें",
"flow-moderation-confirm-unhide-post": "दिखाएँ",
"flow-moderation-confirm-suppress-topic": "दबाएँ",
"flow-moderation-confirm-delete-topic": "हटाएँ",
"flow-moderation-confirm-hide-topic": "छुपाएँ",
- "flow-moderation-confirm-lock-topic": "अवरोध",
+ "flow-moderation-confirm-unsuppress-topic": "असप्रेस",
"flow-moderation-confirm-undelete-topic": "हटाना वापस लें",
"flow-moderation-confirm-unhide-topic": "दिखाएँ",
- "flow-moderation-confirm-unlock-topic": "अवरोध हटाएँ",
+ "flow-moderation-confirmation-suppress-topic": "इस विषय को हटा दिया गया है।",
+ "flow-moderation-confirmation-delete-topic": "यह विषय हटाया गया है।",
+ "flow-moderation-confirmation-hide-topic": "यह विषय छुपाया गया है।",
"flow-moderation-title-suppress-topic": "विषय दबाएँ ?",
"flow-moderation-title-delete-topic": "विषय हटाएँ ?",
"flow-moderation-title-hide-topic": "विषय छुपाएँ ?",
"flow-moderation-title-undelete-topic": "विषय पुनः स्थापित करें ?",
"flow-moderation-title-unhide-topic": "विषय दिखाएँ ?",
+ "flow-moderation-placeholder-suppress-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय सप्रेस करना चाहते हैं।",
+ "flow-moderation-placeholder-delete-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय हटाना चाहते हैं।",
+ "flow-moderation-placeholder-hide-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय छुपाना चाहते हैं।",
+ "flow-moderation-placeholder-unsuppress-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय असप्रेस करना चाहते हैं।",
+ "flow-moderation-placeholder-undelete-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय वापस लाना चाहते हैं।",
+ "flow-moderation-placeholder-unhide-topic": "कृपया {{GENDER:$3|लिखें}} कि आप क्यों विषय को दिखाना चाहते हैं।",
"action-flow-create-board": "किसी भी स्थान पर प्रवाह-पट्ट बनायें",
+ "flow-topic-first-heading": "$1 पर विषय",
+ "flow-topic-html-title": "$2 पर $1",
+ "flow-topic-count": "विषय ($1)",
+ "flow-load-more": "और पढ़ें",
+ "flow-no-more-fwd": "यहाँ कोई पुराना विषय नहीं है।",
+ "flow-newest-topics": "नए विषय",
+ "flow-recent-topics": "हाल में सक्रिय विषय",
+ "flow-toggle-small-topics": "छोटे विषय दृश्य पर स्विच करें",
+ "flow-toggle-topics": "विषय केवल दृश्य में स्विच करें",
+ "structureddiscussions": "फ्लो",
"flow-special-type": "प्रकार",
"flow-special-type-post": "पोस्ट",
+ "flow-special-type-workflow": "वर्कफ्लो",
"flow-special-uuid": "UUID",
- "flow-special-enableflow-header": "प्रवाह-पट्ट की प्रारम्भिक शीर्षणी (विकिपाठ)",
- "flow-special-enableflow-archive-title-format-default-value": "%s/Archive_%d",
- "apihelp-flow+edit-post-param-postId": "पोस्ट आई डी",
- "apihelp-flow+view-post-description": "पोस्ट देखेँ",
+ "flow-special-enableflow-legend": "नए पन्नों हेतु फ्लो सक्रिय करें",
+ "flow-special-enableflow-page": "फ्लो सक्रिय करने हेतु पृष्ठ",
+ "flow-special-enableflow-header": "फ्लो बोर्ड पर शुरुआती विवरण (विकिपाठ)",
+ "flow-special-enableflow-board-already-exists": "[[$1]] पर पहले से फ्लो बोर्ड है",
+ "flow-special-enableflow-invalid-title": "अमान्य पृष्ठ शीर्षक दिया गया",
+ "flow-special-enableflow-board-creation-not-allowed": "आपको [[:$1]] पर फ्लो बोर्ड बनाने की अनुमति नहीं है।",
+ "flow-special-enableflow-page-is-liquidthreads": "[[:$1]] पर लिक्विडथ्रिड पृष्ठ है।",
+ "flow-post-undo-hide": "छुपाना पूर्ववत करें",
+ "flow-post-undo-delete": "हटाना पूर्ववत करें",
+ "flow-post-undo-suppress": "सप्रेस पूर्ववत करें",
+ "flow-topic-undo-hide": "छुपाना पूर्ववत करें",
+ "flow-topic-undo-delete": "हटाना पूर्ववत करें",
+ "flow-topic-undo-suppress": "सप्रेस पूर्ववत करें",
+ "flow-edited": "संपादित",
+ "flow-edited-by": "$1 द्वारा संपादित",
+ "flow-previous-diff": "← पुराना सम्पादन",
+ "flow-next-diff": "नया सम्पादन →",
"flow-undo": "पूर्ववत करें",
"flow-undo-latest-revision": "सद्य अवतरण",
- "flow-undo-your-text": "आपका पाठ"
+ "flow-undo-your-text": "आपका पाठ",
+ "flow-undo-edit-header": "विवरण संपादित करें",
+ "flow-undo-edit-topic-summary": "विषय सारांश संपादित करें",
+ "flow-undo-edit-post": "पोस्ट संपादित करें",
+ "group-flow-bot": "फ्लो बोट",
+ "group-flow-bot-member": "फ्लो बोट",
+ "grouppage-flow-bot": "Project:फ्लो बोट",
+ "flow-ve-mention-context-item-label": "उल्लेख",
+ "flow-ve-mention-inspector-title": "उल्लेख",
+ "flow-ve-mention-inspector-remove-label": "हटायें",
+ "flow-ve-mention-placeholder": "सदस्यनाम",
+ "flow-ve-mention-tool-title": "उल्लेखित सदस्य",
+ "flow-ve-mention-template-title": "फ्लोउल्लेख",
+ "flow-ve-mention-inspector-invalid-user": "सदस्य नाम \"$1\" पंजीकृत नहीं है।",
+ "flow-wikitext-editor-help": "विकिपाठ $1",
+ "flow-wikitext-editor-help-preview-the-result": "परिमाण की झलक",
+ "flow-wikitext-switch-editor-tooltip": "यथादृश्य संपादिका में जाएँ",
+ "flow-ve-switch-editor-tool-title": "स्रोत संपादक में जाएँ",
+ "flow-mark-revision-patrolled-link-text": "इस पृष्ठ को जाँचा हुआ चिन्हित करें",
+ "flow-mark-revision-patrolled-link-title": "इस पृष्ठ को जाँचा हुआ चिन्हित करें",
+ "flow-mark-diff-patrolled-link-text": "जाँचा हुआ चिन्हित करें",
+ "flow-mark-diff-patrolled-link-title": "जाँचा हुआ चिन्हित करें",
+ "flow-talk-page-beta-feature-message": "सदस्य पृष्ठ पर फ्लो",
+ "flow-notification-link-text-enabled-on-talkpage": "सदस्य वार्ता पृष्ठ {{GENDER:|देखें}}",
+ "flow-beta-feature-add-archive-template-edit-summary": "पूरालेख साँचा जोड़ें",
+ "flow-beta-feature-remove-archive-template-edit-summary": "पूरालेख साँचा निकालें",
+ "flow-dialog-cancelconfirm-title": "क्या {{GENDER:|आप}} निश्चित हो?",
+ "flow-dialog-cancelconfirm-keep": "संपादन जारी रखें",
+ "flow-dialog-cancelconfirm-discard": "परिवर्तनों को त्यागें",
+ "flow-guidedtour-optin-feedback": "{{GENDER:$1|अपनी}} प्रतिक्रिया दें!",
+ "flow-action-not-page": "पन्ने पर दिखाया गया वस्तु किसी समस्या के कारण है।"
}
diff --git a/Flow/i18n/hr.json b/Flow/i18n/hr.json
index 851fcbb2..5dd3d526 100644
--- a/Flow/i18n/hr.json
+++ b/Flow/i18n/hr.json
@@ -1,8 +1,29 @@
{
"@metadata": {
"authors": [
- "MaGa"
+ "MaGa",
+ "Vrhnje",
+ "Macofe",
+ "Bugoslav"
]
},
- "flow-notification-mention-email-subject": "$1 {{GENDER:$1|Vas je spomenuo|Vas je spomenula}} na projektu $2"
+ "enablestructureddiscussions": "Omogući Protočne rasprave",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Zahvali}}}} na poruci",
+ "notification-header-flow-new-topic-v2": "Nova tema stvorena na '''$3''': <bdi>\"'''$4'''\"</bdi>.",
+ "notification-header-flow-new-topic-user-talk": "Nova tema otvorena je na <strong>Vašoj razgovornoj stranici</strong>: »<strong>$4</strong>«.",
+ "notification-header-flow-topic-renamed-v2": "Tema \"'''$1'''\" preimenovana je u \"'''$2'''\".",
+ "notification-header-flow-enabled-on-talkpage": "Novi sustav za protočne rasprave uključen je na <strong>{{GENDER:$2|Vašoj}} suradničkoj razgovornoj stranici</strong>.",
+ "notification-email-batch-body-flow-topic-resolved": "Tema \"<strong>$2</strong>\" dovedena je k koncu.",
+ "flow-notification-mention": "$1 {{GENDER:$5|Vas}} je {{GENDER:$1|spomenuo|spomenula}} u {{GENDER:$1|njegovoj|njenoj}} <span class=\"plainlinks\">[$2 poruci]</span> pod naslovom \"$3\" na stranici \"$4\".",
+ "flow-notification-link-text-view-topics": "Pogledajte teme",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|Vas je spomenuo|Vas je spomenula}} na projektu $2",
+ "flow-notification-mention-email-batch-body": "$1 Vas je {{GENDER:$1|spomenuo|spomenula}} u {{GENDER:$1|njegovoj|njenoj}} poruci pod naslovom \"$2\" na stranici $3.",
+ "echo-category-title-flow-discussion": "Protočne rasprave",
+ "structureddiscussions": "Protočne rasprave",
+ "group-flow-bot": "Botovi za Protočne rasprave",
+ "group-flow-bot-member": "bot za Protočne rasprave",
+ "grouppage-flow-bot": "Project:Botovi za Protočne rasprave",
+ "flow-wikitext-switch-editor-tooltip": "Prebaci na vizualno uređivanje",
+ "flow-ve-switch-editor-tool-title": "Prebaci na uređivanje wikiteksta",
+ "flow-dialog-cancelconfirm-message": "Jeste li sigurni da želite odustati bez prethodnog spremanja?"
}
diff --git a/Flow/i18n/hu.json b/Flow/i18n/hu.json
index c8deff2a..03b6ef51 100644
--- a/Flow/i18n/hu.json
+++ b/Flow/i18n/hu.json
@@ -2,32 +2,87 @@
"@metadata": {
"authors": [
"Csega",
- "Tacsipacsi"
+ "Tacsipacsi",
+ "Tgr",
+ "Wolf Rex",
+ "Dj",
+ "Bencemac",
+ "Rodrigo"
]
},
- "enableflow": "Flow engedélyezése",
- "log-name-flow": "Flow-aktivitás naplója",
+ "enablestructureddiscussions": "Flow engedélyezése",
+ "flow-desc": "Megbeszélésrendszer",
+ "flow-talk-taken-over-comment": "/* Ez a lap át lett alakítva egy strukturált beszélgetőoldallá */",
+ "log-name-flow": "Strukturált Beszélgetések naplója",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|törölt}} egy [$4 hozzászólást] a(z) „[[$3|$5]]” témából a(z) [[$6]] lapon",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|törölt}} egy hozzászólást egy témából a(z) [[$3]] lapon",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|helyreállított}} egy [$4 hozzászólást] a(z) „[[$3|$5]]” témából a(z) [[$6]] lapon",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|helyreállított}} egy hozzászólást egy témából a(z) [[$3]] lapon",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|elrejtett}} egy [$4 hozzászólást] a(z) „[[$3|$5]]” témából a(z) [[$6]] lapon",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|elrejtett}} egy hozzászólást egy témából a(z) [[$3]] lapon",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|törölt}} egy [$4 hozzászólást] a(z) „[[$3|$5]]” témából a(z) [[$6]] lapon",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|törölt}} egy hozzászólást egy témából a(z) [[$3]] lapon",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|törölte}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|törölt}} egy témát a(z) [[$3]] lapon",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|helyreállította}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|helyreállított}} egy témát a(z) [[$3]] lapon",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|elrejtette}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|elrejtett}} egy témát a(z) [[$3]] lapon",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|törölte}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|törölt}} egy témát a(z) [[$3]] lapon",
+ "logentry-lock-flow-lock-topic": "$1 megoldottnak {{GENDER:$2|jelölte}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 megoldottnak {{GENDER:$2|jelölt}} egy témát a(z) [[$3]] lapon",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|újranyitotta}} a(z) „[[$3|$5]]” témát a(z) [[$6]] lapon",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|újranyitott}} egy témát a(z) [[$3]] lapon",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] a(z) [[$3]] lapon importálva lett LiquidThreadsből strukturált beszélgetésbe",
"flow-user-moderated": "Moderált felhasználó",
"flow-board-header-browse-topics-link": "Témák böngészése",
"flow-board-header": "Erről a megbeszélésről",
+ "flow-board-description-can-not-edit": "Nem szerkeszthető",
"flow-board-collapse-description": "Leírás elrejtése",
"flow-board-expand-description": "Leírás megjelenítése",
+ "flow-topic-collapse-siderail": "Olvasás teljes szélességgel",
+ "flow-topic-expand-siderail": "Olvasás rögzített szélességgel",
"flow-edit-header-link": "Leírás szerkesztése",
+ "flow-post-moderated-toggle-hide-show": "Mutasd a(z) $2 által {{GENDER:$1|elrejtett}} hozzászólást",
+ "flow-post-moderated-toggle-delete-show": "Mutasd a(z) $2 által {{GENDER:$1|törölt}} hozzászólást",
+ "flow-post-moderated-toggle-suppress-show": "Mutasd a(z) $2 által {{GENDER:$1|titkosított}} hozzászólást",
+ "flow-post-moderated-toggle-hide-hide": "Ne mutasd a(z) $2 által {{GENDER:$1|elrejtett}} hozzászólást",
+ "flow-post-moderated-toggle-delete-hide": "Ne mutasd a(z) $2 által {{GENDER:$1|törölt}} hozzászólást",
+ "flow-post-moderated-toggle-suppress-hide": "Ne mutasd a(z) $2 által {{GENDER:$1|titkosított}} hozzászólást",
"flow-topic-moderated-reason-prefix": "Indoklás:",
+ "flow-hide-post-content": "Ezt a hozzászólást $1 {{GENDER:$1|elrejtette}} ([$2 történet])",
+ "flow-hide-title-content": "Ezt a témát $1 {{GENDER:$1|elrejtette}}",
+ "flow-hide-header-content": "$2 {{GENDER:$1|elrejtette}}",
+ "flow-delete-post-content": "Ezt a hozzászólást $1 {{GENDER:$1|törölte}} ([$2 történet])",
+ "flow-delete-title-content": "Ezt a témát $1 {{GENDER:$1|törölte}}",
+ "flow-delete-header-content": "$2 {{GENDER:$1|törölte}}",
+ "flow-suppress-post-content": "Ezt a hozzászólást $1 {{GENDER:$1|titkosította}} ([$2 történet])",
+ "flow-suppress-title-content": "Ezt a témát $1 {{GENDER:$1|elrejtette}}",
+ "flow-suppress-header-content": "$2 {{GENDER:$1|titkosította}}",
+ "flow-suppress-usertext": "<em>Felhasználónév titkosítva</em>",
"flow-post-actions": "Műveletek",
"flow-topic-actions": "Műveletek",
"flow-cancel": "Mégse",
+ "flow-skip-summary": "Kihagy",
+ "flow-edit-summary-placeholder": "Foglald össze röviden ennek a megbeszélésnek a kimentelét",
+ "flow-summary-authored": "$1 összefoglalója",
+ "flow-summary-edited": "Az összefoglalót utoljára $1 {{GENDER:$1|szerkesztette}}",
"flow-show-change": "Változtatások megjelenítése",
+ "flow-last-modified-by": "Utoljára $1 {{GENDER:$1|szerkesztette}}",
+ "flow-stub-post-content": "<em>A tartalmat műszaki hiba miatt nem sikerült megjeleníteni.</em>",
"flow-newtopic-title-placeholder": "Új téma",
"flow-newtopic-content-placeholder": "Új üzenet küldése a(z) „$1” lapra",
"flow-newtopic-header": "Új téma hozzáadása",
"flow-newtopic-save": "Téma hozzáadása",
+ "flow-newtopic-save-anonymously": "Téma létrehozása névtelenül",
"flow-newtopic-start-placeholder": "Új téma indítása",
"flow-newtopic-first-heading": "Új téma indítása a(z) $1 lapra",
"flow-summarize-topic-placeholder": "Kérlek, összegezd a megbeszélést",
"flow-reply-topic-placeholder": "{{GENDER:$1|Hozzászólás}} a(z) „$2” témához",
"flow-reply-topic-title-placeholder": "Válasz a(z) „$1” üzenetre",
"flow-reply-link": "{{GENDER:$1|Válasz}}",
+ "flow-reply-link-anonymously": "Válasz névtelenül",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Köszönet}}}}",
"flow-thank-link-title": "Nyilvános {{GENDER:$1|{{GENDER:$2|köszönetküldés}}}} az üzenet küldőjének",
"flow-history-action-suppress-post": "elrejtés (suppress)",
@@ -37,6 +92,8 @@
"flow-history-action-undelete-post": "helyreállítás",
"flow-history-action-unhide-post": "megjelenítés",
"flow-history-action-restore-post": "visszaállítás",
+ "flow-history-action-lock-topic": "megoldottnak jelölés",
+ "flow-history-action-unlock-topic": "újranyitás",
"flow-post-edited": "A hozzászólást $1 szerkesztette $2",
"flow-post-action-view": "Állandó hivatkozás",
"flow-post-action-post-history": "Történet",
@@ -45,6 +102,7 @@
"flow-post-action-hide-post": "Elrejt",
"flow-post-action-edit-post": "Szerkesztés",
"flow-post-action-edit-post-submit": "Változtatások mentése",
+ "flow-post-action-edit-post-submit-anonymously": "Változtatások mentése névtelenül",
"flow-post-action-unsuppress-post": "Felfedés",
"flow-post-action-undelete-post": "Helyreállítás",
"flow-post-action-unhide-post": "Megjelenítés",
@@ -67,15 +125,313 @@
"flow-topic-action-unsuppress-topic": "Téma felfedése",
"flow-topic-action-restore-topic": "Téma visszaállítása",
"flow-topic-action-undo-moderation": "Visszavonás",
+ "flow-topic-notification-subscribe-title": "A téma felkerült {{GENDER:$1|a}} figyelőlistádra.",
+ "flow-topic-notification-subscribe-description": "Értesítést {{GENDER:$1|fogsz}} kapni minden tevékenységről ebben a témában.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Feliratkoztál}} erre a megbeszélésre!",
+ "flow-board-notification-subscribe-description": "Értesítést {{GENDER:$1|fogsz}} kapni, ha egy új témát nyitnak ebben a megbeszélésben.",
+ "flow-topic-action-watchlist-add": "Feliratkozás erre a témára",
+ "flow-topic-action-watchlist-remove": "Leiratkozás",
+ "flow-error-allowcreation-no-usedb": "A Strukturált Beszélgetés bekapcsolásához egy adott lapon a <var>$wgContentHandlerUseDB</var> beállításnak igaznak (<code>true</code>) kell lennie.",
+ "flow-error-allowcreation-already-exists": "Már létezik lap a célhelyen, így nem lehet odamozgatni egy Strukturált Beszélgetés-felületet.",
+ "flow-error-allowcreation-flow-create-board": "A felhasználó nem rendelkezik „{{int:right-flow-create-board}}” jogosultsággal",
+ "flow-error-can-not-edit-logged-out": "Jelenleg nem tudsz közreműködni. Megpróbálhatsz bejelentkezni.",
+ "flow-error-can-not-edit-logged-in": "Jelenleg nem tudsz közreműködni, mivel nem rendelkezel a szükséges jogosultságokkal.",
+ "flow-error-http": "Hiba történt a szerverhez történő kapcsolódáskor.",
+ "flow-error-external": "Hiba történet: A kapott hibaüzenet a következő: $1",
+ "flow-error-topic-is-locked": "A téma meg van oldva, így további tevékenység nem lehetséges.",
+ "flow-error-lock-moderated-post": "Nem jelölhetsz moderált bejegyzést megoldottnak.",
"flow-error-missing-content": "A hozzászólásnak nincs tartalma. Ez szükséges az elmentéséhez.",
"flow-error-missing-summary": "Meg kell adnod egy összefoglalást.",
"flow-error-missing-title": "A témának nincs címe. Ez szükséges az elmentéséhez.",
- "flow-error-parsoid-failure": "A tartalom feldolgozása nem lehetséges egy Parsoid-hiba miatt.",
- "flow-error-delete-failure": "Az elem törlése nem sikertelen.",
- "flow-error-hide-failure": "Az elem elrejtése sikertelen.",
- "flow-error-restore-failure": "Az elem helyreállítása sikertelen.",
+ "flow-error-parsoid-failure": "A tartalom átvitele sikertelen: Hiba történt a szerverhez való kapcsolódáskor a wikiszöveg–HTML átalakításhoz. Ellenőrizd az internetkapcsolatodat vagy próbáld újra később, ha probléma továbbra is fennáll. Ha továbbra is ezt a hibaüzenetet kapod, kérjük, készíts egy hibajelentést.",
+ "flow-error-protected-autoconfirmed-logged-in": "Ez a megbeszélés védett. Csak automatikusan megerősített felhasználók vehetnek részt benne. Indoklás: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Ez a megbeszélés védett. Csak bejelentkezett és automatikusan megerősített felhasználók vehetnek részt benne. Indoklás: $1",
+ "flow-error-protected-sysop-logged-in": "Ez a megbeszélés védett. Csak adminisztrátorok vehetnek részt benne. Indoklás: $1",
+ "flow-error-protected-sysop-logged-out": "Ez a megbeszélés védett. Csak adminisztrátor jogosultsággal rendelkező, bejelentkezett felhasználók vehetnek részt benne. Indoklás: $1",
+ "flow-error-protected-unknown-reason": "Ismeretlen",
+ "flow-error-missing-replyto": "Nincs „válasz erre” paraméter megadva. Ez a paraméter szükséges a „válasz” művelethez.",
+ "flow-error-missing-postId": "Nincs „üzenetazonosító” paraméter megadva. Ez a paraméter szükséges egy hozzászólás módosításához.",
+ "flow-error-invalid-postId": "Az „üzenetazonosító” paraméter érvénytelen. A megadott hozzászólás ($1) nem található.",
+ "flow-error-invalid-moderation-state": "Egy paraméter („moderationState”) érvénytelen értékkel lett továbbítva a Strukturált Beszélgetés API-nak.",
+ "flow-error-invalid-moderation-reason": "Adj meg egy okot a moderációhoz.",
+ "flow-error-not-allowed": "Nincsenek megfelelő jogosultságaid a művelet végrehajtásához.",
+ "flow-error-not-allowed-hide": "A témát elrejtették.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Nem válaszolhatsz, mert a téma rejtett.",
+ "flow-error-not-allowed-delete": "A témát törölték.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Nem válaszolhatsz, mert a témát törölték.",
+ "flow-error-not-allowed-suppress": "A témát törölték.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Nem válaszolhatsz, mert a témát törölték.",
+ "flow-error-not-allowed-hide-extract": "Ez a téma el van rejtve. A téma elrejtési naplója alább látható.",
+ "flow-error-not-allowed-delete-extract": "Ezt a témát törölték. A téma törlési naplója alább látható.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Nem válaszolhatsz, mert a témát törölték. A törlési naplója alább látható.",
+ "flow-error-not-allowed-suppress-extract": "Ezt a témát törölték. A téma törlési naplója alább látható.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Nem válaszolhatsz, mert a témát elrejtették. A téma elrejtési naplója alább látható.",
+ "flow-error-title-too-long": "A témák címei legfeljebb $1 bájt hosszúak lehetnek.",
+ "flow-error-not-a-post": "A téma címe nem menthető hozzászólásként.",
+ "flow-error-missing-header-content": "Meg kell adnod a leírást.",
+ "flow-error-missing-prev-revision-identifier": "Az előző változat azonosítója hiányzik.",
+ "flow-error-prev-revision-mismatch": "Egy másik felhasználó éppen módosította ezt a hozzászólást egy pár másodperce. Biztosan felül {{GENDER:$3|szeretnéd}} írni a változtatását?",
+ "flow-error-prev-revision-does-not-exist": "Nem található az előző verzió.",
+ "flow-error-core-topic-deletion": "Egy téma törléséhez használd a … menüt a rendezett megbeszélésnél vagy a [$1 téma lapját]. Ne használd az action=delete műveletet közvetlenül.",
+ "flow-error-default": "Hiba történt.",
+ "flow-error-invalid-input": "Érvénytelen érték volt megadva a rendezett beszélgetés betöltéséhez.",
+ "flow-error-invalid-title": "Érvénytelen lapcím volt megadva.",
+ "flow-error-fail-load-history": "A laptörténet tartalmának betöltése sikertelen.",
+ "flow-error-missing-revision": "Nem található lapváltozat a rendezett beszélgetés betöltéséhez.",
+ "flow-error-fail-commit": "A rendezett beszélgetés adatok elmentése nem sikerült.",
+ "flow-error-revision-comparison": "Csak ugyanazon hozzászólás két változata hasonlítható össze.",
+ "flow-error-missing-metadata": "Nem találhatók a szükséges metaadatok ehhez a lapváltozathoz.",
+ "flow-error-fail-load-data": "Nem sikerült betölteni a kért adatokat.",
+ "flow-error-process-data": "Hiba történt a kérésedben található adatok feldolgozásakor.",
+ "flow-error-process-wikitext": "Hiba történt a HTML/wikiszöveg átalakítás feldolgozása közben.",
+ "flow-error-no-index": "Nem található index az adatkeresés végrehajtásához.",
+ "flow-error-no-render": "A megadott művelet felismerése sikertelen.",
+ "flow-error-no-commit": "A megadott művelet elmentése sikertelen.",
+ "flow-error-content-too-long": "A tartalom túl nagy. A kibontott tartalom mérete nem lehet több $1 bájtnál.",
+ "flow-error-move-topic": "A témalapok mozgatása jelenleg nem támogatott.",
+ "flow-error-invalid-topic-uuid-title": "Hibás cím",
+ "flow-error-invalid-topic-uuid": "A kért cím érvénytelen. A Téma névtérben található lapokat a rendezett beszélgetés rendszere hozza létre automatikusan.",
+ "flow-error-unknown-workflow-id-title": "Ismeretlen téma",
+ "flow-error-unknown-workflow-id": "A kért téma nem létezik.",
+ "flow-error-search": "Egy átmeneti hiba miatt nem tudtuk végrehajtani a keresést. Kérjük, próbálkozz később.",
"flow-edit-header-submit": "Leírás mentése",
+ "flow-edit-header-submit-anonymously": "A leírás mentése névtelenül",
+ "flow-edit-title-submit": "Cím módosítása",
+ "flow-edit-title-submit-anonymously": "Cím módosítása névtelenül",
+ "flow-edit-post-submit": "Módosítások mentése",
+ "flow-edit-post-submit-anonymously": "Módosítások mentése névtelenül",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|szerkesztett}} egy [$3 hozzászólást] a(z) „$4” témában",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Szerkesztett}} egy hozzászólást",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|hozzászólt}}] a(z) „$4” témához (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 hozzászólás</strong> hozzáadva",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|létrehozta}} a(z) „[$3 $4]” témát",
+ "flow-rev-message-new-post-recentchanges-summary": "Téma {{GENDER:$2|létrehozva}}",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|átnevezte}} a témát „$5” címről „[$3 $4]” címre",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|létrehozta}} a leírást",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|szerkesztette}} a leírást",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|létrehozta}} a(z) $3 téma összefoglalóját",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|szerkesztette}} a(z) $3 téma összefoglalóját",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|elrejtette}} a(z) „$6” téma egy [$4 hozzászólását] (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|törölte}} a(z) „$6” téma egy [$4 hozzászólását] (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|hejreállította}} a(z) „$6” téma egy [$4 hozzászólását] (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|elrejtette}} a(z) „[$4 $6]” témát (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|törölte}} a(z) „[$4 $6]” témát (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 megoldottnak {{GENDER:$2|jelölte}} a(z) „[$4 $6]” témát (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "megoldottnak jelölve",
+ "flow-rev-message-restore-topic-reason": "újranyitva",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|helyreállította}} a(z) „[$4 $6]” témát (<em>$5</em>)",
+ "flow-board-history": "A(z) „$1” története",
+ "flow-topic-history": "A(z) „$1” téma története",
+ "flow-post-history": "$2 hozzászólásának története",
+ "flow-history-last4": "Utolsó 4 óra",
+ "flow-history-day": "Ma",
+ "flow-history-week": "Múlt héten",
+ "flow-history-pages-post": "A(z) [$1 $2] témában jelenik meg",
+ "flow-topic-comments": "{{PLURAL:$1|1 hozzászólás|0={{GENDER:$2|Legyél}} az első hozzászóló!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Hozzászólás|Hozzászólások}} megtekintése",
+ "flow-hide-comments-title": "{{PLURAL:$1|Hozzászólás|Hozzászólások}} elrejtése",
+ "flow-comment-restored": "Visszaállított hozzászólás",
+ "flow-comment-deleted": "Törölt hozzászólás",
+ "flow-comment-hidden": "Rejtett hozzászólás",
+ "flow-comment-moderated": "Moderált hozzászólás",
+ "flow-last-modified": "Utoljára módosítva nagyjából $1",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 válaszolt a(z) <strong>$4</strong> lapon.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 és {{PLURAL:$5|még valaki|$5 másik ember|100=99+ másik ember}} válaszolt a(z) <strong>$3</strong> lapon.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 módosította a <span class=\"plainlinks\">[$5 hozzászólásodat]</span> a(z) [[$3|$4]] lapon.",
+ "flow-notification-edit-bundle": "$1 és {{PLURAL:$5|még valaki|$5 másik ember|100=99+ másik ember}} módosította a(z) „$2” téma egy <span class=\"plainlinks\">[$4 hozzászólását]</span> a(z) „$3” lapon.",
+ "notification-header-flow-new-topic-v2": "Új téma létrehozva a(z) <strong>$3</strong> lapon: <bdi>„<strong>$4</strong>”</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Egy|$1|100=99+}} új téma a(z) <strong>$3</strong> lapon.",
+ "notification-header-flow-new-topic-user-talk": "Új téma jött létre a <strong>vitalapodon</strong>: „<strong>$4</strong>”.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Egy|$1|100=99+}} új téma a <strong>vitalapodon</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|válaszolt}} a(z) „<strong>$4</strong>” témában.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Egy|$1|100=99+}} új válasz a(z) „<strong>$3</strong>” témában.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|válaszolt}} a(z) „<strong>$4</strong>” témára a <strong>vitalapodon</strong>.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Egy|$1|100=99+}} új válasz a <strong>vitalapodon</strong> a(z) „<strong>$3</strong>” témában.",
+ "notification-header-flow-post-edited-v2": "Szerkesztették a {{GENDER:$2|hozzászólásodat}} a(z) „<strong>$1</strong>” témában.",
+ "notification-bundle-header-flow-post-edited-v2": "Többször szerkesztették a {{GENDER:$2|hozzászólásodat}} a(z) „<strong>$1</strong>” témában.",
+ "notification-header-flow-post-edited-user-talk": "Egy hozzászólást szerkesztettek a(z) „<strong>$1</strong>” témában a <strong>{{GENDER:$2|vitalapodon}}</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Egy hozzászólást többször szerkesztettek a(z) „<strong>$1</strong>” témában a <strong>{{GENDER:$2|vitalapodon}}</strong>.",
+ "notification-header-flow-topic-renamed-v2": "A(z) „<strong>$1</strong>” témát átnevezték „<strong>$2</strong>” címre.",
+ "notification-header-flow-topic-renamed-user-talk": "A(z) „<strong>$1</strong>” témát átnevezték „<strong>$2</strong>” címre a <strong>{{GENDER:$3|vitalapodon}}</strong>.",
+ "notification-header-flow-summary-edited": "A(z) „<strong>$1</strong>” téma összefoglalóját frissítették.",
+ "notification-header-flow-summary-edited-first": "A(z) „<strong>$1</strong>” témát összefoglalták.",
+ "notification-bundle-header-flow-summary-edited": "A(z) „<strong>$1</strong>” téma összefoglalóját többször frissítették.",
+ "notification-header-flow-summary-edited-user-talk": "A(z) „<strong>$1</strong>” téma összefoglalóját frissítették a <strong>{{GENDER:$2|vitalapodon}}</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "A(z) „<strong>$1</strong>” témát összefoglalták a <strong>{{GENDER:$2|vitalapodon}}</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "A(z) „<strong>$1</strong>” téma összefoglalóját többször frissítették a <strong>{{GENDER:$2|vitalapodon}}</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 frissítette a(z) $2 téma összefoglalóját.",
+ "notification-email-batch-body-flow-summary-edited": "$1 frissítette a(z) $2 téma összefoglalóját.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 és {{PLURAL:$3|még valaki|$3 másik ember|100=99+ másik ember}} firssítette a(z) $2 téma összefoglalóját",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2$4|megemlített}} a(z) „<strong>$5</strong>” témában.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2$4|megemlített}} a(z) „<strong>$5</strong>” témában.",
+ "notification-header-flow-description-edited-user-talk": "Szerkesztették a <strong>{{GENDER:$2|vitalapod}}</strong> összefoglalóját.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Többször szerkesztették a <strong>{{GENDER:$2|vitalapod}}</strong> összefoglalóját.",
+ "notification-links-flow-description-edited-view-page": "Lap {{GENDER:$1|megtekintése}}",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|módosította}} a(z) $2 téma leírását.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|módosította}} a(z) $2 téma leírását.",
+ "notification-header-flow-topic-resolved": "A(z) „<strong>$1</strong>” témát megoldották.",
+ "notification-header-flow-topic-reopened": "A(z) „<strong>$1</strong>” témát újranyitották.",
+ "notification-header-flow-topic-resolved-user-talk": "A(z) „<strong>$1</strong>” témát megoldották a <strong>vitalapodon</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "A(z) „<strong>$1</strong>” témát újranyitották a <strong>vitalapodon</strong>.",
+ "notification-email-subject-flow-topic-resolved": "A(z) „<strong>$2</strong>” témát megoldották.",
+ "notification-email-batch-body-flow-topic-resolved": "A(z) „<strong>$2</strong>” témát megoldották.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 új témát indított a(z) <strong>$3</strong> lapon.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Egy|$1|100=99+}} új téma a(z) <strong><span class=\"plainlinks\">[$3 $2]</span></strong> lapon",
+ "flow-notification-rename": "$1 megváltoztatta a(z) <span class=\"plainlinks\">[$2 $3]</span> téma címét „$4” címre a(z) [[$5|$6]] lapon.",
+ "flow-notification-mention": "$1 {{GENDER:$5|megemlített}} a <span class=\"plainlinks\">[$2 hozzászólásában]</span> a(z) „$3” témában a(z) „$4” lapon.",
+ "flow-notification-link-text-view-post": "Hozzászólás megtekintése",
+ "flow-notification-link-text-view-topic": "Téma megtekintése",
+ "flow-notification-link-text-view-topics": "Témák megtekintése",
+ "flow-notification-reply-email-batch-body": "$1 válaszolt a(z) „$2” témára a(z) $3 lapon",
+ "flow-notification-reply-email-batch-bundle-body": "$1 és {{PLURAL:$4|még valaki|$4 másik ember|100=99+ másik ember}} válaszolt a(z) „$2” témára a(z) $3 lapon",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|megemlített}} a hozzászólásában a(z) „$2” témában a(z) $3 lapon",
+ "flow-notification-edit-email-subject": "$1 szerkesztett egy hozzászólást",
+ "flow-notification-edit-email-batch-body": "$1 szerkesztett egy hozzászólást a(z) „$2” témában a(z) $3 lapon",
+ "flow-notification-edit-email-batch-bundle-body": "$1 és {{PLURAL:$4|még valaki|$4 másik ember|100=99+ másik ember}} szerkesztett egy hozzászólást a(z) „$2” témában a(z) $3 lapon",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|átnevezte}} a témád",
+ "flow-notification-rename-email-batch-body": "$1 átnevezte a(z) „$2” témádat „$3” címre a(z) $4 lapon",
+ "flow-notification-newtopic-email-subject": "$1 új témát indított a(z) $2 lapon",
+ "flow-notification-newtopic-email-batch-body": "$1 „$2” címmel új témát indított a(z) $3 lapon",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Egy|$1|100=99+}} új téma a(z) $2 lapon",
+ "echo-category-title-flow-discussion": "Rendezett beszélgetés",
+ "echo-pref-tooltip-flow-discussion": "Értesítést kérek a lapokon vagy témákban történt engem érintő változtatásokról.",
+ "flow-link-post": "hozzászólás",
+ "flow-link-topic": "téma",
+ "flow-link-history": "laptörténet",
+ "flow-link-post-revision": "hozzászólás-változat",
+ "flow-link-topic-revision": "témaváltozat",
+ "flow-link-header-revision": "leírásváltozat",
+ "flow-link-summary-revision": "összefoglaló-változat",
+ "flow-moderation-title-delete-post": "Törlöd a hozzászólást?",
+ "flow-moderation-title-hide-post": "Elrejted a hozzászólást?",
+ "flow-moderation-title-undelete-post": "Helyreállítod a hozzászólást?",
+ "flow-moderation-title-unhide-post": "Megjeleníted a hozzászólást?",
+ "flow-moderation-placeholder-delete-post": "{{GENDER:$3|Magyarázd meg}}, miért törlöd ezt a hozzászólást.",
+ "flow-moderation-placeholder-hide-post": "{{GENDER:$3|Magyarázd meg}}, miért rejted el ezt a hozzászólást.",
+ "flow-moderation-placeholder-undelete-post": "{{GENDER:$3|Magyarázd meg}}, miért állítod helyre ezt a hozzászólást.",
+ "flow-moderation-placeholder-unhide-post": "{{GENDER:$3|Magyarázd meg}}, miért jeleníted meg ezt a hozzászólást.",
+ "flow-moderation-confirm-delete-post": "Törlés",
+ "flow-moderation-confirm-hide-post": "Elrejtés",
+ "flow-moderation-confirm-undelete-post": "Helyreállítás",
+ "flow-moderation-confirm-unhide-post": "Megjelenítés",
+ "flow-moderation-confirm-delete-topic": "Törlés",
+ "flow-moderation-confirm-hide-topic": "Elrejtés",
+ "flow-moderation-confirm-undelete-topic": "Helyreállítás",
+ "flow-moderation-confirm-unhide-topic": "Megjelenítés",
+ "flow-moderation-confirmation-delete-post": "A hozzászólás törölve.\n{{GENDER:$2|Fontold meg}}, hogy visszajelzést adsz $1 részére a hozzászólásról.",
+ "flow-moderation-confirmation-hide-post": "A hozzászólás elrejtve.\n{{GENDER:$2|Fontold meg}}, hogy visszajelzést adsz $1 részére a hozzászólásról.",
+ "flow-moderation-confirmation-undelete-post": "Helyreállítottad a fenti hozzászólást.",
+ "flow-moderation-confirmation-unhide-post": "Megjelenítetted a fenti hozzászólást.",
+ "flow-moderation-confirmation-delete-topic": "A téma törölted.",
+ "flow-moderation-confirmation-hide-topic": "A témát elrejtetted.",
+ "flow-moderation-confirmation-undelete-topic": "Helyreállítottad a témát.",
+ "flow-moderation-confirmation-unhide-topic": "Megjelenítetted a témát.",
+ "flow-moderation-title-delete-topic": "Törlöd a témát?",
+ "flow-moderation-title-hide-topic": "Elrejted a témát?",
+ "flow-moderation-title-undelete-topic": "Helyreállítod a témát?",
+ "flow-moderation-title-unhide-topic": "Megjeleníted a témát?",
+ "flow-moderation-placeholder-delete-topic": "{{GENDER:$3|Magyarázd meg}}, miért törlöd ezt a témát.",
+ "flow-moderation-placeholder-hide-topic": "{{GENDER:$3|Magyarázd meg}}, miért rejted el ezt a témát.",
+ "flow-moderation-placeholder-undelete-topic": "{{GENDER:$3|Magyarázd meg}}, miért állítod helyre ezt a témát.",
+ "flow-moderation-placeholder-unhide-topic": "{{GENDER:$3|Magyarázd meg}}, miért jeleníted meg ezt a témát.",
+ "flow-revision-permalink-warning-post-first": "Ez egy állandó link a hozzászólás első verziójára.\nA későbbi változatokat a [$4 hozzászólás laptörténetében] nézheted meg.",
+ "flow-revision-permalink-warning-postsummary-first": "Ez egy állandó link a hozzászólás-összefoglaló első verziójára.\nA későbbi változatokat a [$4 hozzászólás laptörténetében] nézheted meg.",
+ "flow-compare-revisions-revision-header": "$2 változata ($1)",
+ "right-flow-hide": "rendezettbeszélgetés-témák és -hozzászólások elrejtése",
+ "right-flow-lock": "rendezettbeszélgetés-témák megjelölése megoldottként",
+ "right-flow-delete": "rendezettbeszélgés-témák és -hozzászólások törlése",
+ "right-flow-edit-post": "más felhasználók rendezettbeszélgetés-hozzászólásainak szerkesztése",
+ "flow-terms-of-use-new-topic": "A „{{int:flow-newtopic-save}}” gombra kattintással elfogadod ezen wiki felhasználási feltételeit.",
+ "flow-terms-of-use-reply": "A „{{int:flow-reply-link}}” gombra kattintással elfogadod ezen wiki felhasználási feltételeit.",
+ "flow-terms-of-use-edit": "A változtatásaid elmentésével egyetértesz ezen wiki felhasználási feltételeivel.",
+ "flow-anon-warning": "Nem vagy bejelentkezve. Ha azt szeretnéd, hogy a nevedhez kapcsolódjon a szerkesztés az IP-címed helyett, [$1 jelentkezz be] vagy [$2 regisztrálj].",
+ "flow-cancel-warning": "Írtál be szöveget ebbe az űrlapba. Biztosan el akarod vetni?",
+ "flow-topic-html-title": "$1 a(z) $2 lapon",
+ "flow-topic-count": "Témák ($1)",
+ "flow-load-more": "Továbbiak",
+ "flow-no-more-fwd": "Nincsenek régebbi témák",
+ "flow-newest-topics": "Legújabb témák",
+ "flow-recent-topics": "Nemrég aktív témák",
+ "flow-sorting-tooltip-newest": "Jelenleg a legújabb témákat olvasod először. Kattints ide további rendezési lehetőségekért.",
+ "flow-sorting-tooltip-recent": "Jelenleg a legutóbb aktív témákat olvasod először. Kattints ide további rendezési lehetőségekért.",
+ "flow-terms-of-use-summarize": "Az „{{int:flow-topic-action-update-topic-summary}}” gombra kattintással elfogadod ezen wiki felhasználási feltételeit.",
+ "flow-terms-of-use-lock-topic": "A „{{int:flow-topic-action-lock-topic}}” gombra kattintással elfogadod ezen wiki felhasználási feltételeit.",
+ "flow-terms-of-use-unlock-topic": "A „{{int:flow-topic-action-unlock-topic}}” gombra kattintással elfogadod ezen wiki felhasználási feltételeit.",
+ "flow-whatlinkshere-post": "[$1 hozzászólásból]",
+ "flow-whatlinkshere-header": "[$1 a leírásból]",
+ "flow-whatlinkshere-post-summary": "[$1 az összefoglalóból]",
+ "structureddiscussions": "Flow",
+ "flow-special-type": "Típus",
+ "flow-special-type-post": "Hozzászólás",
+ "flow-special-enableflow-legend": "Rendezett beszélgetés engedélyezése egy új lapon",
+ "flow-special-enableflow-invalid-title": "Érvénytelen lapcím megadva",
+ "flow-special-enableflow-page-is-liquidthreads": "Már van egy LiquidThreads- (Folyékony beszélgetések-) oldal a(z) [[:$1]] címen.",
+ "flow-conversion-archive-page-name-format": "%s/Archív %d\n%s/Archív%d\n%s/archív %d\n%s/archív%d",
+ "flow-spam-confirmedit-form": "Erősítsd meg az alábbi CAPTCHA megoldásával, hogy ember vagy: $1",
+ "flow-spam-confirmedit-using-failure": "Technikai probléma volt a CAPTCHA-val. Ha nem tudod közzétenni a változtatásodat, másold ki a szöveget, töltsd újra a lapot és próbáld újra.",
+ "flow-embedding-unsupported": "Megbeszélések jelenleg nem illeszthetők be.",
+ "mw-ui-unsubmitted-confirm": "Vannak változtatásaid a lapon, amiket még nem tettél közzé. Biztosan el akarsz navigálni és elveszteni a munkádat?",
+ "flow-post-undo-hide": "elrejtés visszavonása",
+ "flow-post-undo-delete": "törlés visszavonása",
+ "flow-topic-undo-hide": "elrejtés visszavonása",
+ "flow-topic-undo-delete": "törlés visszavonása",
+ "flow-importer-lqt-moved-thread-template-content": "{{{author}}} ezen hozzászólását elmozgatták {{{date}}} időpontban, [[{{{title}}}|itt]] találod meg.",
+ "flow-importer-lqt-converted-template": "LQT-lap konvertálva Rendezett beszélgetéssé",
+ "flow-importer-lqt-converted-template-content": "A korábbi laptörténetet archiválták biztonsági mentés céljából a(z) <span class=\"flow-link-to-archive\">[[{{{archive}}}]]</span> lapra {{#time:Y. F j.|{{{date}}} }} dátummal.",
+ "flow-importer-lqt-converted-archive-template": "Konvertált LQT-lap archívuma",
+ "flow-importer-lqt-converted-archive-template-content": "Ez a lap egy archivált LiquidThreads- (Folyékony beszélgetések-) lap. <strong>Ne változtass a tartalmán</strong>. Bármilyen további megjegyzést az [[{{{from}}}|aktuális vitalapra]] írj.",
+ "flow-importer-wt-converted-template": "Wikiszöveges vitalap konvertálva Rendezett beszélgetéssé",
+ "flow-importer-wt-converted-template-content": "A korábbi laptörténetet archiválták a(z) <span class=\"flow-link-to-archive\">[[{{{archive}}}]]</span> lapra {{#time:Y. F j.|{{{date}}} }} dátummal.",
+ "flow-importer-wt-converted-archive-template": "Konvertált wikiszöveges vitalap archívuma",
+ "flow-importer-wt-converted-archive-template-content": "Ez a lap egy archívum. <strong>Ne változtass a tartalmán</strong>. Bármilyen további megjegyzést az [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|aktuális vitalapra]] írj.",
+ "flow-importer-lqt-different-author-signature-template": "LQT-hozzászólás eltérő aláírású szerkesztőtől",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Ezt a hozzászólást [[User:{{{authorUser}}}|{{{authorUser}}}]] írta, de [[User:{{{signatureUser}}}|{{{signatureUser}}}]] aláírása szerepelt alatta.</em>",
+ "flow-edited": "Szerkesztve",
+ "flow-edited-by": "Szerkesztette $1",
+ "flow-talk-conversion-archive-edit-reason": "Wikiszöveges vitalap konvertálása Rendezett beszélgetéssé",
+ "flow-previous-diff": "← Régebbi szerkesztés",
+ "flow-next-diff": "Újabb szerkesztés →",
+ "flow-undo": "visszavonás",
+ "flow-undo-latest-revision": "Aktuális változat",
+ "flow-undo-your-text": "A te változatod",
+ "flow-undo-edit-header": "Leírás szerkesztése",
+ "flow-undo-edit-topic-summary": "A téma összefoglalójának szerkesztése",
+ "flow-undo-edit-post": "Hozzászólás szerkesztése",
+ "flow-undo-edit-content": "A szerkesztés visszavonható. Kérlek ellenőrizd alább a változásokat, hogy valóban ezt szeretnéd-e tenni, majd kattints a változtatások mentése gombra a visszavonás véglegesítéséhez.",
+ "flow-undo-edit-failure": "A szerkesztést nem lehet automatikusan visszavonni vele ütköző későbbi szerkesztések miatt.",
+ "group-flow-bot": "Rendezettbeszélgetés-botok",
+ "group-flow-bot-member": "Rendezett beszélgetések-bot",
+ "grouppage-flow-bot": "Project:Rendezettbeszélgetés-botok",
+ "flow-ve-mention-context-item-label": "Említés",
+ "flow-ve-mention-inspector-title": "Említés",
+ "flow-ve-mention-inspector-remove-label": "Törlés",
+ "flow-ve-mention-placeholder": "Felhasználónév",
+ "flow-ve-mention-tool-title": "Egy felhasználó megemlítése",
+ "flow-ve-mention-template-title": "Flow-említés",
+ "flow-ve-mention-inspector-invalid-user": "„$1” felhasználó nincs regisztrálva.",
+ "flow-wikitext-editor-help": "Wikiszöveg $1.",
+ "flow-wikitext-editor-help-and-preview": "A wikiszöveg $1 és bármikor $2.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|jelölést használ]]",
+ "flow-wikitext-editor-help-preview-the-result": "megtekintheted az eredmény előnézetét",
+ "flow-wikitext-switch-editor-tooltip": "Váltás vizuális szerkesztésre",
+ "flow-ve-switch-editor-tool-title": "Váltás wikiszöveg-szerkesztésre",
+ "flow-mark-revision-patrolled-link-text": "A lap megjelölése ellenőrzöttként",
"flow-mark-revision-patrolled-link-title": "A lap megjelölése ellenőrzöttként",
"flow-mark-diff-patrolled-link-text": "Ellenőrzöttnek jelölés",
- "flow-mark-diff-patrolled-link-title": "Ellenőrzöttnek jelölés"
+ "flow-mark-diff-patrolled-link-title": "Ellenőrzöttnek jelölés",
+ "flow-talk-page-beta-feature-message": "Rendezett beszélgetés a vitalapodon",
+ "flow-notification-link-text-enabled-on-talkpage": "Felhasználói vitalap megtekintése",
+ "flow-beta-feature-add-archive-template-edit-summary": "Archívumsablon hozzáadása",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Archívumsablon eltávolítása",
+ "flow-dialog-cancelconfirm-title": "Biztos vagy benne?",
+ "flow-dialog-cancelconfirm-message": "Biztosan el szeretnéd hagyni a szerkesztés módot mentés nélkül?",
+ "flow-dialog-cancelconfirm-keep": "Szerkesztés folytatása",
+ "flow-dialog-cancelconfirm-discard": "Változtatások elvetése",
+ "flow-optin-restore-wikitext": "Archivált wikiszöveges lap helyreállítása.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Üdvözlünk}} új vitalapodon",
+ "flow-guidedtour-optin-welcome-description": "A vitalapodon érhet el {{GENDER:$1|téged}} a többi szerkesztő. A Rendezett beszélgetéssel egyszerűbb a témák indítása és nyomon követése.",
+ "flow-guidedtour-optin-find-old-conversations": "Régi {{GENDER:$1|beszélgetéseid}} megtalálása",
+ "flow-guidedtour-optin-find-old-conversations-description": "A régi beszélgetéseid archiválva lettek.",
+ "flow-guidedtour-optin-feedback": "Várjuk {{GENDER:$1|visszajelzésed}}!",
+ "flow-guidedtour-optin-feedback-description": "További információt {{GENDER:$1|kaphatsz}}, visszajelzést adhatsz vagy letilthatod az új rendszert bármikor a Béta funkciók szakaszban."
}
diff --git a/Flow/i18n/hy.json b/Flow/i18n/hy.json
index f25b28a8..f0950006 100644
--- a/Flow/i18n/hy.json
+++ b/Flow/i18n/hy.json
@@ -4,14 +4,77 @@
"M hamlet",
"Vadgt",
"Xelgen",
- "Aram1985"
+ "Aram1985",
+ "Աշոտ1997",
+ "Kareyac"
]
},
+ "enablestructureddiscussions": "Միացնել հոսքը",
+ "flow-board-header-browse-topics-link": "Դիտել թեմաները",
+ "flow-board-expand-description": "Ցուցադրել նկարագրությունը",
"flow-edit-header-link": "Խմբագրել նկարագրությունը",
+ "flow-topic-moderated-reason-prefix": "Պատճառ՝",
+ "flow-hide-post-content": "$1 մասնակիցը թաքցրել է այս մեկնաբանությունը ([$2 պատմություն])",
+ "flow-hide-title-content": "$1 մասնակիցը թաքցրել է այս թեման",
+ "flow-post-actions": "Գործողություններ",
+ "flow-topic-actions": "Գործողություններ",
+ "flow-cancel": "Չեղարկել",
+ "flow-skip-summary": "Բաց թողնել",
+ "flow-show-change": "Կատարված փոփոխությունները",
+ "flow-newtopic-title-placeholder": "Նոր թեմա",
+ "flow-newtopic-start-placeholder": "Սկսել նոր թեմա",
+ "flow-reply-link": "Պատասխանել",
+ "flow-thank-link": "Շնորհակալություն",
+ "flow-history-action-delete-post": "ջնջել",
+ "flow-history-action-hide-post": "թաքցնել",
+ "flow-history-action-undelete-post": "վերականգնել",
+ "flow-post-action-post-history": "Պատմություն",
+ "flow-post-action-delete-post": "Ջնջել",
+ "flow-post-action-hide-post": "Թաքցնել",
+ "flow-post-action-edit-post": "Խմբագրել",
+ "flow-post-action-edit-post-submit": "Պահպանել փոփոխությունները",
+ "flow-post-action-restore-post": "Վերականգնել",
+ "flow-post-action-undo-moderation": "Հետ շրջել",
+ "flow-topic-action-view": "Մշտական հղում",
+ "flow-topic-action-watchlist": "Հսկացանկ",
+ "flow-topic-action-edit-title": "Խմբագրել վերնագիրը",
+ "flow-topic-action-history": "Պատմություն",
+ "flow-topic-action-hide-topic": "Թաքցնել թեման",
+ "flow-topic-action-delete-topic": "Ջնջել թեման",
+ "flow-topic-action-lock-topic": "Նշել որպես լուծված",
+ "flow-topic-action-unlock-topic": "Վերաբացել թեման",
+ "flow-topic-action-summarize-topic": "Ամփոփել",
+ "flow-error-not-allowed-hide": "Այս թեման թաքցվել է",
+ "flow-error-not-allowed-reply-to-hide-topic": "Դուք չեք կարող պատասխանել, քանի որ այս թեման թաքցվել է",
+ "flow-error-not-allowed-delete": "Այս թեման ջնջվել է",
+ "flow-error-not-allowed-suppress": "Այս թեման ջնջվել է",
"flow-edit-header-submit": "Պահպանել նկարագրությունը:",
+ "flow-history-day": "Այսօր",
+ "flow-history-week": "Անցած շաբաթ",
+ "flow-comment-deleted": "Ջնջված մեկնաբանություն",
+ "flow-comment-hidden": "Թաքցված մեկնաբանություն",
"flow-notification-edit": "$1 մասնակիցը {{GENDER:$1|խմբագրեց}} <span class=\"plainlinks\">[$5 գրառումը]</span> [[$3|$4]] էջի «$2» թեմայում։",
"flow-notification-rename": "$1՝ {{GENDER:$1|փոխեց}} վերնագրիրը [$2 $3]-ի \"$4\"-ում [[$5|$6]]-ի վրա:",
- "flow-revision-permalink-warning-header-first": "Սա ժամանակավոր հղում է դեպի նկարագրության առաջին տարբերակ:\nԴուք կարող եք դիտել ավելի ուշ տարբերակները [$2 էջի պատմության ցուցակ]ում.",
- "flow-special-enableflow-archive-title-format-default-value": "%s/Պահոց_%d",
- "flow-undo-edit-header": "Նկարագրությունը խմբագրվում է"
+ "flow-notification-mention-email-subject": "$1 մասնակիցը հիշատակալ է Ձեզ $2 քննարկումում",
+ "flow-moderation-confirm-delete-post": "Ջնջել",
+ "flow-moderation-confirm-delete-topic": "Ջնջել",
+ "flow-moderation-title-delete-topic": "Ջնջե՞լ թեման",
+ "flow-revision-permalink-warning-header-first": "Սա նկարագրության առաջին տարբերակ մշտական հղումն է:\nԴուք կարող եք դիտել ավելի ուշ տարբերակները [$2 էջի պատմության ցուցակ]ում:",
+ "flow-special-uuid": "UUID",
+ "flow-special-enableflow-legend": "Միացնել հոսքը նոր էջում",
+ "flow-edited": "Խմբագրված",
+ "flow-previous-diff": "← ավելի հին",
+ "flow-next-diff": "ավելի նոր →",
+ "flow-undo-your-text": "Ձեր տեքստը",
+ "flow-undo-edit-header": "Նկարագրությունը խմբագրվում է",
+ "flow-undo-edit-topic-summary": "Խմբագրել թեմայի ամփոփումը",
+ "group-flow-bot": "Հոսքի բոտեր",
+ "group-flow-bot-member": "Հոսքի բոտ",
+ "flow-ve-mention-placeholder": "Մասնակցային անուն",
+ "flow-wikitext-editor-help-preview-the-result": "նախադիտել արդյունքը",
+ "flow-dialog-cancelconfirm-title": "Դուք վստա՞հ եք",
+ "flow-dialog-cancelconfirm-message": "Չեղարկե՞լ առանց փոփոխությունները պահելու",
+ "flow-dialog-cancelconfirm-keep": "Շարունակել խմբագրել",
+ "flow-dialog-cancelconfirm-discard": "Չեղարկել փոփոխությունները",
+ "flow-guidedtour-optin-find-old-conversations": "Գտնել Ձեր հին խոսակցությունները"
}
diff --git a/Flow/i18n/ia.json b/Flow/i18n/ia.json
index 17fb813d..f11335af 100644
--- a/Flow/i18n/ia.json
+++ b/Flow/i18n/ia.json
@@ -1,101 +1,180 @@
{
"@metadata": {
"authors": [
- "McDutchie"
+ "McDutchie",
+ "Nnemo"
]
},
+ "enablestructureddiscussions": "Activar Flow",
"flow-desc": "Systema de gestion de fluxo de travalio",
+ "flow-talk-taken-over-comment": "/* Iste pagina ha essite convertite in un tabuliero de discussion Flow */",
"log-name-flow": "Registro de activitate de fluxo",
- "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|deleva}} un [$4 message] in [[$3]]",
- "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurava}} un [$4 message] in [[$3]]",
- "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|deleva}} un [$4 message] in [[$3]]",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|deleva}} un [$4 message] sur \"[[$3|$5]]\" in [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|deleva}} un message de un topico sur [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurava}} un [$4 message] sur \"[[$3|$5]]\" in [[$6]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|deleva}} un [$4 message] sur \"[[$3|$5]]\" in [[$6]]",
"flow-user-moderated": "Usator moderate",
- "flow-edit-header-link": "Modificar titulo",
+ "flow-board-header-browse-topics-link": "Percurrer topicos",
+ "flow-board-header": "A proposito de iste foro",
+ "flow-board-description-can-not-edit": "Non modificabile",
+ "flow-board-collapse-description": "Celar description",
+ "flow-board-expand-description": "Monstrar description",
+ "flow-topic-collapse-siderail": "Leger a latitude plen",
+ "flow-topic-expand-siderail": "Leger a latitude fixe",
+ "flow-edit-header-link": "Modificar description",
+ "flow-topic-moderated-reason-prefix": "Motivo:",
"flow-suppress-usertext": "<em>Nomine de usator supprimite</em>",
"flow-post-actions": "Actiones",
"flow-topic-actions": "Actiones",
"flow-cancel": "Cancellar",
- "flow-preview": "Previsualisar",
+ "flow-skip-summary": "Saltar",
+ "flow-edit-summary-placeholder": "Describe brevemente le resultato de iste discussion",
+ "flow-summary-authored": "Summario per $1",
+ "flow-summary-edited": "Summario {{GENDER:$1|modificate}} pro le ultime vice per $1",
+ "flow-show-change": "Detaliar modificationes",
+ "flow-last-modified-by": "Ultime {{GENDER:$1|modification}} per $1",
+ "flow-stub-post-content": "<em>A causa de un error technic, iste message non pote esser recuperate.</em>",
"flow-newtopic-title-placeholder": "Nove topico",
- "flow-newtopic-content-placeholder": "Adde detalios si tu vole",
+ "flow-newtopic-content-placeholder": "Publicar un nove message in \"$1\"",
"flow-newtopic-header": "Adder un nove topico",
"flow-newtopic-save": "Adder topico",
+ "flow-newtopic-save-anonymously": "Adder topico anonymemente",
"flow-newtopic-start-placeholder": "Initiar un nove discussion",
+ "flow-newtopic-first-heading": "Initiar un nove topico sur $1",
+ "flow-summarize-topic-placeholder": "Per favor summarisa iste discussion",
"flow-reply-topic-placeholder": "{{GENDER:$1|Commentar}} \"$2\"",
- "flow-reply-submit": "{{GENDER:$1|Responder}}",
+ "flow-reply-topic-title-placeholder": "Responder a \"$1\"",
"flow-reply-link": "{{GENDER:$1|Responder}}",
- "flow-thank-link": "{{GENDER:$1|Regratiar}}",
+ "flow-reply-link-anonymously": "Responder anonymemente",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Regratiar}}}}",
+ "flow-thank-link-title": "Publicamente {{GENDER:$1|{{GENDER:$2|regratiar}}}} le autor",
+ "flow-history-action-suppress-post": "supprimer",
+ "flow-history-action-delete-post": "deler",
+ "flow-history-action-hide-post": "celar",
+ "flow-history-action-unsuppress-post": "disfacer suppression",
+ "flow-history-action-undelete-post": "disfacer deletion",
+ "flow-history-action-unhide-post": "disfacer celamento",
+ "flow-history-action-restore-post": "restaurar",
+ "flow-history-action-lock-topic": "resolver",
+ "flow-history-action-unlock-topic": "reaperir",
"flow-post-edited": "Entrata {{GENDER:$1|modificate}} per $1 $2",
"flow-post-action-view": "Permaligamine",
- "flow-post-action-post-history": "Historia de messages",
+ "flow-post-action-post-history": "Historia",
"flow-post-action-suppress-post": "Supprimer",
"flow-post-action-delete-post": "Deler",
"flow-post-action-hide-post": "Celar",
- "flow-post-action-edit-post": "Modificar entrata",
- "flow-post-action-restore-post": "Restaurar entrata",
+ "flow-post-action-edit-post": "Modificar",
+ "flow-post-action-edit-post-submit": "Salveguardar modificationes",
+ "flow-post-action-edit-post-submit-anonymously": "Salveguardar modificationes anonymemente",
+ "flow-post-action-unsuppress-post": "Disfacer suppression",
+ "flow-post-action-undelete-post": "Disfacer deletion",
+ "flow-post-action-unhide-post": "Disfacer celamento",
+ "flow-post-action-restore-post": "Restaurar",
+ "flow-post-action-undo-moderation": "Disfacer",
"flow-topic-action-view": "Permaligamine",
"flow-topic-action-watchlist": "Observatorio",
"flow-topic-action-edit-title": "Modificar titulo",
- "flow-topic-action-history": "Historia del topico",
+ "flow-topic-action-history": "Historia",
"flow-topic-action-hide-topic": "Celar topico",
"flow-topic-action-delete-topic": "Deler topico",
+ "flow-topic-action-lock-topic": "Marcar como resolvite",
+ "flow-topic-action-unlock-topic": "Reaperir topico",
+ "flow-topic-action-summarize-topic": "Summarisar",
+ "flow-topic-action-resummarize-topic": "Modificar le summario del topico",
+ "flow-topic-action-update-topic-summary": "Actualisar summario",
"flow-topic-action-suppress-topic": "Supprimer topico",
+ "flow-topic-action-unhide-topic": "Disfacer celamento del topico",
+ "flow-topic-action-undelete-topic": "Disfacer deletion del topico",
+ "flow-topic-action-unsuppress-topic": "Disfacer suppression del topico",
"flow-topic-action-restore-topic": "Restaurar topico",
+ "flow-topic-action-undo-moderation": "Disfacer",
+ "flow-topic-notification-subscribe-title": "Iste topico ha essite addite a {{GENDER:$1|tu}} observatorio.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Tu}} recipera notificationes sur tote le activitates sur iste topico.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Tu}} es subscribite a iste foro de discussion!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Tu}} recipera notification quando un nove topico es create sur iste foro.",
+ "flow-topic-action-watchlist-add": "Subscriber te a iste topico",
+ "flow-topic-action-watchlist-remove": "Cancellar subscription",
+ "flow-error-allowcreation-already-exists": "Le pagina jam existe in le destination, dunque un tabuliero Flow non pote esser displaciate illac.",
+ "flow-error-allowcreation-flow-create-board": "Le usator non ha le permission \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Tu non pote participar ora. Proba aperir session.",
+ "flow-error-can-not-edit-logged-in": "Tu non pote participar actualmente, perque tu non ha le derectos requisite.",
"flow-error-http": "Un error occurreva durante le communication con le servitor.",
- "flow-error-other": "Un error inexpectate ha occurrite.",
- "flow-error-external": "Un error ha occurrite.<br />Le message de error recipite es: $1",
- "flow-error-edit-restricted": "Tu non es autorisate a modificar iste entrata.",
- "flow-error-external-multi": "Errores ha occurrite.<br />$1",
+ "flow-error-external": "Un error ha occurrite. Le message de error recipite es: $1",
+ "flow-error-topic-is-locked": "Iste topico es resolvite, dunque ulterior activitate non es possibile.",
+ "flow-error-lock-moderated-post": "Tu non pote marcar un message moderate como resolvite.",
"flow-error-missing-content": "Le message non ha contento. Contento es necessari pro salveguardar un message.",
+ "flow-error-missing-summary": "Tu debe submitter un summario.",
"flow-error-missing-title": "Le topico non ha titulo. Le titulo es necessari pro salveguardar un topico.",
- "flow-error-parsoid-failure": "Impossibile interpretar le contento a causa de un fallimento de Parsoid.",
+ "flow-error-parsoid-failure": "Impossibile transferer contento: Error in contactar le servitor pro conversion inter wikitexto e HTML. Verifica tu connexion a Internet o reproba plus tarde si le problema persiste. Si tu sempre recipe iste error, per favor submitte un reporto de defecto.",
+ "flow-error-protected-autoconfirmed-logged-in": "Iste tabuliero es protegite. Solmente usatores autoconfirmate pote participar. Motivo: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Iste tabuliero es protegite. Solmente usatores autoconfirmate que ha aperite session pote participar. Motivo: $1",
+ "flow-error-protected-sysop-logged-in": "Iste tabuliero es protegite. Solmente usatores con privilegios de administrator pote participar. Motivo: $1",
+ "flow-error-protected-sysop-logged-out": "Iste tabuliero es protegite. Solmente usatores con privilegios de administrator que ha aperite session pote participar. Motivo: $1",
+ "flow-error-protected-unknown-reason": "Incognite",
"flow-error-missing-replyto": "Nulle parametro \"replyTo\" ha essite fornite. Iste parametro es necessari pro le action \"responder\".",
- "flow-error-invalid-replyto": "Le parametro \"replyTo\" es invalide. Le entrata specificate non pote esser trovate.",
- "flow-error-delete-failure": "Le deletion de iste elemento ha fallite.",
- "flow-error-hide-failure": "Le celamento de iste elemento ha fallite.",
"flow-error-missing-postId": "Nulle parametro \"postId\" ha essite specificate. Iste parametro es necessari pro manipular un entrata.",
"flow-error-invalid-postId": "Le parametro \"postId\" es invalide. Le entrata specificate ($1) non poteva esser trovate.",
- "flow-error-restore-failure": "Le restauration de iste elemento ha fallite.",
- "flow-error-invalid-moderation-state": "Un valor invalide ha essite fornite pro moderationState",
+ "flow-error-invalid-moderation-state": "Un valor invalide pro un parametro ('moderationState') ha essite fornite al API de Flow.",
"flow-error-invalid-moderation-reason": "Per favor da un motivo pro le moderation",
"flow-error-not-allowed": "Permissiones insufficiente pro exequer iste action",
+ "flow-error-not-allowed-hide": "Iste topico ha essite celate.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Tu non pote responder perque iste topico ha essite celate.",
+ "flow-error-not-allowed-delete": "Iste topico ha essite delite.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Tu non pote responder perque iste topico ha essite delite.",
+ "flow-error-not-allowed-suppress": "Iste topico ha essite delite.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Tu non pote responder perque iste topico ha essite delite.",
+ "flow-error-not-allowed-hide-extract": "Iste topico ha essite celate. Ecce le registro de celamentos pro le topico.",
+ "flow-error-not-allowed-delete-extract": "Iste topico ha essite delite. Ecce le registro de deletiones pro le topico.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Tu non pote responder perque iste topico ha essite delite. Ecce le registro de deletiones pro le topico.",
+ "flow-error-not-allowed-suppress-extract": "Iste topico ha essite delite. Ecce le registro de deletiones pro le topico.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Tu non pote responder perque iste topico ha essite supprimite. Ecce le registro de suppressiones pro le topico.",
+ "flow-error-title-too-long": "Titulos de topicos non pote esser plus longe de $1 {{PLURAL:$1|byte|bytes}}.",
+ "flow-error-no-existing-workflow": "Iste fluxo de labor non existe ancora.",
+ "flow-error-not-a-post": "Le titulo del topico non pote esser salveguardate como un message.",
+ "flow-error-missing-header-content": "Tu debe submitter un description.",
+ "flow-error-missing-prev-revision-identifier": "Le identificator del version precedente es mancante.",
+ "flow-error-prev-revision-mismatch": "Un altere usator ha justo modificate iste message alcun secundas retro. Es {{GENDER:$3|tu}} secur de voler superscriber iste modification recente?",
+ "flow-error-prev-revision-does-not-exist": "Impossibile trovar le version precedente.",
"flow-error-invalid-topic-uuid-title": "Titulo invalide",
"flow-error-invalid-topic-uuid": "Le titulo de pagina requestate non es valide. Paginas in le spatio de nomines Topic es create automaticamente per Flow.",
"flow-error-unknown-workflow-id-title": "Topico incognite",
"flow-error-unknown-workflow-id": "Le topico requestate non existe.",
- "flow-edit-header-submit": "Salveguardar titulo",
+ "flow-edit-header-submit": "Salveguardar description",
"flow-edit-title-submit": "Cambiar titulo",
"flow-edit-post-submit": "Submitter modificationes",
- "flow-rev-message-edit-post": "$1 {{GENDER:$2|modificava}} un [$3 commento].",
- "flow-rev-message-reply": "$1 {{GENDER:$2|addeva}} un [$3 commento].",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|modificava}} un [$3 commento] sur \"$4\"",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|commentava}}] \"$4\" (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|commento|commentos}}</strong> ha essite addite.",
- "flow-rev-message-new-post": "$1 {{GENDER:$2|creava}} le topico [$3 $4].",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|cambiava}} le titulo del topico de $5 in [$3 $4].",
- "flow-rev-message-create-header": "$1 {{GENDER:$2|creava}} le titulo del tabuliero.",
- "flow-rev-message-edit-header": "$1 {{GENDER:$2|modificava}} le titulo del tabuliero.",
- "flow-rev-message-hid-post": "$1 {{GENDER:$2|celava}} un [$4 commento] (<em>$5</em>).",
- "flow-rev-message-deleted-post": "$1 {{GENDER:$2|deleva}} un [$4 commento] (<em>$5</em>).",
- "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|supprimeva}} un [$4 commento] (<em>$5</em>).",
- "flow-rev-message-restored-post": "$1 {{GENDER:$2|restaurava}} un [$4 commento] (<em>$5</em>).",
- "flow-rev-message-hid-topic": "$1 {{GENDER:$2|celava}} le [$4 topico] (<em>$5</em>).",
- "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|deleva}} le [$4 topico] (<em>$5</em>).",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|supprimeva}} le [$4 topico] (<em>$5</em>).",
- "flow-rev-message-restored-topic": "$1 {{GENDER:$2|restaurava}} le [$4 topico] (<em>$5</em>).",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|creava}} le topico \"[$3 $4]\"",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|cambiava}} le titulo del topico de \"$5\" in \"[$3 $4]\"",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|creava}} le description",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|modificava}} le description",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|celava}} un [$4 commento] sur \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|deleva}} un [$4 commento] sur \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|supprimeva}} un [$4 commento] sur \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|restaurava}} un [$4 commento] sur \"$6\" (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|celava}} le [$4 topico] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|deleva}} le [$4 topico] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|supprimeva}} le [$4 topico] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|restaurava}} le [$4 topico] \"$6\" (<em>$5</em>)",
"flow-topic-history": "Historia del topico \"$1\"",
"flow-comment-restored": "Commento restaurate",
"flow-comment-deleted": "Commento delite",
"flow-comment-hidden": "Commento celate",
"flow-comment-moderated": "Commento moderate",
"flow-last-modified": "Ultime modification circa $1",
- "flow-notification-reply": "$1 {{GENDER:$1|respondeva}} a <span class=\"plainlinks\">[$5 $2]</span> sur \"$4\".",
- "flow-notification-reply-bundle": "$1 e $5 {{PLURAL:$6|altere|alteres}} {{GENDER:$1|respondeva}} a <span class=\"plainlinks\">[$4 $2]</span> sur \"$3\".",
- "flow-notification-edit": "$1 {{GENDER:$1|modificava}} un [$5 message] in $2 sur [[$3|$4]].",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|creava}} un nove topico super '''$3'''.",
- "flow-notification-rename": "$1 {{GENDER:$1|cambiava}} le titulo de [$2 $3] a \"$4\" super [[$5|$6]].",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|respondeva}} in <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e {{PLURAL:$5|un altere|$5 alteres|100=99+ alteres}} {{GENDER:$1|respondeva}} in <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 ha {{GENDER:$1|modificate}} tu <span class=\"plainlinks\">[$5 message]</span> in [[$3|$4]].",
+ "notification-header-flow-new-topic-v2": "Nove topico create sur <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|creava}} un nove topico in <strong>$3</strong>.",
+ "flow-notification-rename": "$1 {{GENDER:$1|cambiava}} le titulo de <span class=\"plainlinks\">[$2 $3]</span> a \"$4\" in [[$5|$6]].",
"flow-notification-link-text-view-post": "Vider message",
- "flow-notification-reply-email-subject": "$1 {{GENDER:$1|respondeva}} a un topico",
- "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondeva}} a \"$2\" sur \"$3\"",
- "flow-notification-reply-email-batch-bundle-body": "$1 e $4 {{PLURAL:$5|altere|alteres}} {{GENDER:$1|respondeva}} a \"$2\" sur \"$3\"",
+ "flow-notification-reply-email-subject": "$2 in $3",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondeva}} a \"$2\" in $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 e $4 {{PLURAL:$4|un altere|$4 alteres|100=99+ alteres}} {{GENDER:$1|respondeva}} a \"$2\" in \"$3\"",
"echo-category-title-flow-discussion": "Fluxo",
- "echo-pref-tooltip-flow-discussion": "Notificar me quando actiones concernente me occurre in Fluxo."
+ "echo-pref-tooltip-flow-discussion": "Notificar me quando actiones concernente me occurre in Fluxo.",
+ "flow-action-not-page": "Le objecto del pagina es un instantia del classe incorrecte",
+ "flow-action-wrong-title-content-model": "Le pagina es sub gerentia de Flow, ma le classe Title indica que le modello de contento es '$1'. Isto es un configuration incorrecte o stato inconsistente. Per exemplo, il poterea tractar se de un pagina non Flow in un spatio de nomines Flow e sin datos pro <code>rev_content_model</code>."
}
diff --git a/Flow/i18n/id.json b/Flow/i18n/id.json
index 6765e4bf..9171ae96 100644
--- a/Flow/i18n/id.json
+++ b/Flow/i18n/id.json
@@ -2,13 +2,483 @@
"@metadata": {
"authors": [
"Ahdan",
- "William Surya Permana"
+ "William Surya Permana",
+ "Kenrick95",
+ "Arief",
+ "Macofe",
+ "Matiia",
+ "Beeyan",
+ "Hidayatsrf"
]
},
+ "enablestructureddiscussions": "Aktifkan Flow",
+ "flow-desc": "Sistem manajemen alur kerja",
+ "flow-talk-taken-over-comment": "/* Halaman ini telah diubah menjadi forum diskusi Flow */",
+ "log-name-flow": "Catatan aktivitas Flow",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|menghapus}} sebuah [$4 kiriman] di \"[[$3|$5]]\" di [[$6]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|mengembalikan}} sebuah [$4 kiriman] di \"[[$3|$5]]\" di [[$6]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|merahasiakan}} sebuah [$4 kiriman] di \"[[$3|$5]]\" di [[$6]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|menghapus}} sebuah [$4 kiriman] di \"[[$3|$5]]\" di [[$6]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|menghapus}} topik \"[[$3|$5]]\" di [[$6]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|mengembalikan}} topik \"[[$3|$5]]\" di [[$6]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|merahasiakan}} topik \"[[$3|$5]]\" di [[$6]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|menghapus}} topik \"[[$3|$5]]\" di [[$6]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|menandai}} topik \"[[$3|$5]]\" sebagai terselesaikan di [[$6]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|membuka kembali}} topik \"[[$3|$5]]\" di [[$6]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] di [[$3]] merupakan hasil impor dari LiquidThreads ke Flow",
+ "flow-user-moderated": "Pengguna termoderasi",
+ "flow-board-header-browse-topics-link": "Lihat topik-topik",
+ "flow-board-header": "Tentang forum ini",
+ "flow-board-collapse-description": "Sembunyikan deskripsi",
+ "flow-board-expand-description": "Perlihatkan deskripsi",
+ "flow-topic-collapse-siderail": "Baca dalam lebar penuh",
+ "flow-topic-expand-siderail": "Baca dalam lebar tetap",
+ "flow-edit-header-link": "Sunting deskripsi",
+ "flow-post-moderated-toggle-hide-show": "Lihat komentar yang {{GENDER:$1|disembunyikan}} oleh $2",
+ "flow-post-moderated-toggle-delete-show": "Lihat komentar yang {{GENDER:$1|dihapus}} oleh $2",
+ "flow-post-moderated-toggle-suppress-show": "Lihat komentar yang {{GENDER:$1|dirahasiakan}} oleh $2",
+ "flow-post-moderated-toggle-hide-hide": "Sembunyikan komentar yang {{GENDER:$1|disembunyikan}} oleh $2",
+ "flow-post-moderated-toggle-delete-hide": "Sembunyikan komentar yang {{GENDER:$1|dihapus}} oleh $2",
+ "flow-post-moderated-toggle-suppress-hide": "Sembunyikan komentar yang {{GENDER:$1|dirahasiakan}} oleh $2",
"flow-topic-moderated-reason-prefix": "Alasan:",
+ "flow-hide-post-content": "Komentar ini disembunyikan oleh $1 ([$2 riwayat])",
+ "flow-hide-title-content": "Topik ini disembunyikan oleh $1",
+ "flow-hide-header-content": "{{GENDER:$1|Disembunyikan}} oleh $2",
+ "flow-delete-post-content": "Komentar ini dihapus oleh $1 ([$2 riwayat])",
+ "flow-delete-title-content": "Topik ini dihapus oleh $1",
+ "flow-delete-header-content": "{{GENDER:$1|Dihapus}} oleh $2",
+ "flow-suppress-post-content": "Komentar ini dirahasiakan oleh $1 ([$2 riwayat])",
+ "flow-suppress-title-content": "Topik ini dirahasiakan oleh $1",
+ "flow-suppress-header-content": "{{GENDER:$1|Dirahasiakan}} oleh $2",
+ "flow-suppress-usertext": "<em>Nama pengguna dirahasiakan</em>",
+ "flow-post-actions": "Tindakan",
+ "flow-topic-actions": "Tindakan",
+ "flow-cancel": "Batal",
+ "flow-skip-summary": "Lewati ringkasan",
+ "flow-edit-summary-placeholder": "Deskripsikan secara singkat hasil diskusi ini",
+ "flow-summary-authored": "Ringkasan oleh $1",
+ "flow-summary-edited": "Ringkasan terakhir diubah oleh $1",
+ "flow-show-change": "Lihat perubahan",
+ "flow-last-modified-by": "Terakhir diubah oleh $1",
+ "flow-stub-post-content": "<em>Karena gangguan teknis, kiriman ini tidak dapat dimuat.</em>",
+ "flow-newtopic-title-placeholder": "Topik baru",
+ "flow-newtopic-content-placeholder": "Kirimkan pesan baru ke \"$1\"",
+ "flow-newtopic-header": "Tambahkan topik baru",
+ "flow-newtopic-save": "Tambahkan topik",
+ "flow-newtopic-save-anonymously": "Tambahkan topik secara anonim",
+ "flow-newtopic-start-placeholder": "Mulai topik baru",
+ "flow-newtopic-first-heading": "Mulai topik baru di $1",
+ "flow-summarize-topic-placeholder": "Silakan merangkum diskusi ini",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Komentari}} \"$2\"",
+ "flow-reply-topic-title-placeholder": "Balas \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|Balas}}",
+ "flow-reply-link-anonymously": "Balas secara anonim",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Berterima kasih}}}}",
+ "flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Berterima kasih}}}} secara publik ke pemulai kiriman",
+ "flow-history-action-suppress-post": "rahasiakan",
+ "flow-history-action-delete-post": "hapus",
+ "flow-history-action-hide-post": "sembunyikan",
+ "flow-history-action-unsuppress-post": "batal merahasiakan",
+ "flow-history-action-undelete-post": "batal menghapus",
+ "flow-history-action-unhide-post": "batal menyembunyikan",
+ "flow-history-action-restore-post": "kembalikan",
+ "flow-history-action-lock-topic": "selesaikan",
+ "flow-history-action-unlock-topic": "buka kembali",
+ "flow-post-edited": "Kiriman $2 disunting oleh $1",
+ "flow-post-action-view": "Permalink",
+ "flow-post-action-post-history": "Riwayat",
+ "flow-post-action-suppress-post": "Rahasiakan",
+ "flow-post-action-delete-post": "Hapus",
+ "flow-post-action-hide-post": "Sembunyikan",
+ "flow-post-action-edit-post": "Sunting",
+ "flow-post-action-edit-post-submit": "Simpan perubahan",
+ "flow-post-action-edit-post-submit-anonymously": "Simpan perubahan secara anonim",
+ "flow-post-action-unsuppress-post": "Batal merahasiakan",
+ "flow-post-action-undelete-post": "Batal menghapus",
+ "flow-post-action-unhide-post": "Batal menyembunyikan",
+ "flow-post-action-restore-post": "Kembalikan",
+ "flow-post-action-undo-moderation": "Batal",
+ "flow-topic-action-view": "Permalink",
+ "flow-topic-action-watchlist": "Daftar pantauan",
+ "flow-topic-action-edit-title": "Sunting judul",
+ "flow-topic-action-history": "Riwayat",
+ "flow-topic-action-hide-topic": "Sembunyikan topik",
+ "flow-topic-action-delete-topic": "Hapus topik",
+ "flow-topic-action-lock-topic": "Tandai selesai",
+ "flow-topic-action-unlock-topic": "Buka kembali topik",
+ "flow-topic-action-summarize-topic": "Merangkum",
+ "flow-topic-action-resummarize-topic": "Sunting ringkasan topik",
+ "flow-topic-action-update-topic-summary": "Perbarui ringkasan",
+ "flow-topic-action-suppress-topic": "Rahasiakan topik",
+ "flow-topic-action-unhide-topic": "Batal menyembunyikan topik",
+ "flow-topic-action-undelete-topic": "Batal menghapus topik",
+ "flow-topic-action-unsuppress-topic": "Batal merahasiakan topik",
+ "flow-topic-action-restore-topic": "Kembalikan topik",
"flow-topic-action-undo-moderation": "Batal",
+ "flow-topic-notification-subscribe-title": "Topik ini telah ditambahkan ke daftar pantauan {{GENDER:$1|Anda}}.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Anda}} akan menerima pemberitahuan tentang semua aktivitas topik ini.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Anda}} telah berlangganan ke forum ini!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Anda}} akan mendapatkan pemberitahuan tentang topik baru di forum ini.",
+ "flow-topic-action-watchlist-add": "Berlangganan ke topik ini",
+ "flow-topic-action-watchlist-remove": "Berhenti berlangganan",
+ "flow-error-allowcreation-no-usedb": "Mengaktifkan Flow di halaman tertentu membutuhkan <var>$wgContentHandlerUseDB</var> disetel sebagai <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Halaman telah tersedia di tujuan, jadi sebuah forum Flow tidak dapat dipindahkan ke sana.",
+ "flow-error-allowcreation-flow-create-board": "Pengguna tidak memiliki hak \"{{int:right-flow-create-board}}\"",
+ "flow-error-http": "Terjadi galat ketika menghubungi server.",
+ "flow-error-external": "Sebuah galat terjadi. Pesan kesalahan yang diterima: $1",
+ "flow-error-topic-is-locked": "Topik ini terselesaikan, jadi aktivitas lebih lanjut tidaklah diizinkan.",
+ "flow-error-lock-moderated-post": "Anda tidak dapat menandai kiriman termoderasi sebagai terselesaikan.",
+ "flow-error-missing-content": "Kiriman tidak memiliki isi. Diperlukan isi untuk menyimpan sebuah kiriman.",
+ "flow-error-missing-summary": "Anda harus menyediakan sebuah ringkasan.",
+ "flow-error-missing-title": "Topik tidak memiliki judul. Diperlukan judul untuk menyimpan sebuah topik.",
+ "flow-error-parsoid-failure": "Tidak dapat memindahkan isi: Galat dalam menghubungi server untuk konversi antara teks wiki dan HTML. Silakan periksa koneksi internet Anda atau coba lagi jika masalah tetap terjadi. Jika Anda tetap mendapati galat ini, silakan laporkan sebagai bug.",
+ "flow-error-missing-replyto": "Parameter \"replyTo\" tidak disediakan. Parameter ini dibutuhkan untuk membalas pesan.",
+ "flow-error-missing-postId": "Parameter \"postId\" tidak disediakan. Parameter ini diperlukan untuk mengubah sebuah kiriman.",
+ "flow-error-invalid-postId": "Parameter \"postId\" tidaklah valid. Kiriman terebut ($1) tidak ditemukan.",
+ "flow-error-invalid-moderation-state": "Nilai tidak sah untuk parameter ('moderationState') telah dikirim ke API Flow.",
+ "flow-error-invalid-moderation-reason": "Silakan tuliskan alasan moderasi ini.",
+ "flow-error-not-allowed": "Izin melakukan hal ini tidaklah mencukupi.",
+ "flow-error-not-allowed-hide": "Topik ini telah disembunyikan",
+ "flow-error-not-allowed-reply-to-hide-topic": "Anda tidak dapat membalas karena topik ini telah disembunyikan.",
+ "flow-error-not-allowed-delete": "Topik ini telah dihapus.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Anda tidak dapat membalas karena topik ini telah dihapus.",
+ "flow-error-not-allowed-suppress": "Topik ini telah dihapus.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Anda tidak dapat membalas karena topik ini telah dihapus.",
+ "flow-error-not-allowed-hide-extract": "Topik ini telah disembunyikan. Log penyembunyian tersedia di bawah sebagai referensi.",
+ "flow-error-not-allowed-delete-extract": "Topik ini telah dihapus. Log penghapusannya tersedia di bawah sebagai referensi.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Anda tidak dapat membalas karena topik ini telah dihapus. Log penghapusannya tersedia di bawah sebagai referensi.",
+ "flow-error-not-allowed-suppress-extract": "Topik ini telah dihapus. Log penghapusannya tersedia di bawah sebagai referensi.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Anda tidak dapat membalas karena topik ini telah dirahasiakan. Log perahasiaan tersedia di bawah sebagai referensi.",
+ "flow-error-title-too-long": "Judul topik tidak boleh lebih besar dari $1 bita.",
+ "flow-error-no-existing-workflow": "Alur kerja ini belum tersedia.",
+ "flow-error-not-a-post": "Topik ini tidak dapat disimpan sebagai sebuah kiriman.",
+ "flow-error-missing-header-content": "Anda harus menyediakan sebuah deskripsi.",
+ "flow-error-missing-prev-revision-identifier": "Tidak ada pengenal revisi sebelumnya.",
+ "flow-error-prev-revision-mismatch": "Pengguna lain juga telah menyunting kiriman ini beberapa saat yang lalu. Apakah {{GENDER:$3|Anda}} yakin ingin menimpa perubahan itu?",
+ "flow-error-prev-revision-does-not-exist": "Tidak dapat menemukan revisi sebelumnya.",
+ "flow-error-core-topic-deletion": "Untuk menghapus topik, pakai menu ... di forum Flow atau [$1 halaman topik]. Jangan memakai action=delete secara langsung.",
+ "flow-error-default": "Terjadi sebuah galat.",
+ "flow-error-invalid-input": "Nilai tidak valid disediakan untuk memuat isi Flow.",
+ "flow-error-invalid-title": "Judul halaman yang diberikan tidaklah valid.",
+ "flow-error-fail-load-history": "Gagal memuat isi riwayat.",
+ "flow-error-missing-revision": "Tidak dapat menemukan revisi untuk memuat isi Flow.",
+ "flow-error-fail-commit": "Gagal menyimpan isi Flow.",
+ "flow-error-insufficient-permission": "Izin tidak terpenuhi untuk bisa mengakses konten yang ada.",
+ "flow-error-revision-comparison": "Operasi diff hanya dapat dilakukan untuk dua revisi yang berada dalam kiriman yang sama.",
+ "flow-error-missing-topic-title": "Tidak dapat menemukan judul topik untuk alur kerja ini.",
+ "flow-error-missing-metadata": "Tidak dapat menemukan metadata untuk revisi ini.",
+ "flow-error-fail-load-data": "Gagal memuat data yang diminta.",
+ "flow-error-invalid-workflow": "Tidak dapat menemukan alur kerja yang diminta.",
+ "flow-error-process-data": "Sebuah galat terjadi ketika memproses data dalam permintaan Anda.",
+ "flow-error-process-wikitext": "Sebuah galat terjadi ketika memproses konversi HTML/teks wiki.",
+ "flow-error-no-index": "Gagal menemukan indeks untuk mencari data.",
+ "flow-error-no-render": "Hal yang akan dilakukan tidak dikenal.",
+ "flow-error-no-commit": "Hal yang akan dilakukan tidak dapat disimpan.",
+ "flow-error-content-too-long": "Isi terlalu besar. Isi setelah ekspansi dibatasi sebanyak $1 bita.",
+ "flow-error-move-topic": "Memindahkan halaman topik tidaklah didukung untuk saat ini.",
+ "flow-error-invalid-topic-uuid-title": "Judul tidak sah",
+ "flow-error-invalid-topic-uuid": "Judul halaman yang diminta tidak valid. Halaman di ruang nama Topik akan otomatis dibuat oleh Flow.",
+ "flow-error-unknown-workflow-id-title": "Topik yang tidak diketahui",
+ "flow-error-unknown-workflow-id": "Topik yang diminta tidak ada.",
+ "flow-error-search": "Tidak dapat melakukan pencarian karena galat sementara. Silakan coba lagi nanti.",
+ "flow-error-invalid-undelete": "Artikel tidak dapat dikembalikan karena telah ada forum diskusi di sana.",
+ "flow-edit-header-placeholder": "Deskripsikan forum ini",
+ "flow-edit-header-submit": "Simpan deskripsi",
+ "flow-edit-header-submit-anonymously": "Simpan deskripsi secara anonim",
+ "flow-edit-title-submit": "Sunting judul",
+ "flow-edit-title-submit-anonymously": "Sunting judul secara anonim",
+ "flow-edit-post-submit": "Simpan perubahan",
+ "flow-edit-post-submit-anonymously": "Simpan perubahan secara anonim",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|menyunting}} sebuah [$3 komentar] di \"$4\"",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Menyunting}} sebuah kiriman",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|mengomentari}}] pada \"$4\" (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|komentar}}</strong> telah ditambahkan",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|membuat}} topik \"[$3 $4]\"",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Membuat}} topik baru",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|mengubah}} judul topik dari \"$5\" ke \"[$3 $4]\"",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|membuat}} deskripsi",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|menyunting}} deskripsi",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|membuat}} ringkasan topik di $3",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|menyunting}} ringkasan topik di $3",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|menyembunyikan}} sebuah [$4 komentar] di \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|menghapus}} sebuah [$4 komentar] di \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|merahasiakan}} sebuah [$4 komentar] di \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|mengembalikan}} sebuah [$4 komentar] di \"$6\" (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|menyembunyikan}} [$4 topik] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|menghapus}} [$4 topik] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|merahasiakan}} [$4 topik] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|menandai}} [$4 topik] \"$6\" terselesaikan (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "Tandai terselesaikan",
+ "flow-rev-message-restore-topic-reason": "dibuka kembali",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|mengembalikan}} [$4 topik] \"$6\" (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 pada $2",
+ "flow-board-history": "Riwayat \"$1\"",
+ "flow-board-history-empty": "Saat ini, forum ini tidak memiliki riwayat.",
+ "flow-topic-history": "Riwayat topik \"$1\"",
+ "flow-post-history": "Riwayat kiriman \"Komentar oleh $2\"",
+ "flow-history-last4": "Empat jam terakhir",
+ "flow-history-day": "Hari ini",
+ "flow-history-week": "Minggu lalu",
+ "flow-history-pages-topic": "Muncul di [$1 forum \"$2\"]",
+ "flow-history-pages-post": "Muncul di [$1 $2]",
+ "flow-topic-comments": "{{PLURAL:$1|$1 komentar|$1 komentar|0={{GENDER:$2|Berikan}} komentar pertama!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Lihat komentar}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Sembunyikan komentar}}",
+ "flow-comment-restored": "Komentar terkembalikan",
+ "flow-comment-deleted": "Komentar terhapus",
+ "flow-comment-hidden": "Komentar tersembunyi",
+ "flow-comment-moderated": "Komentar termoderasi",
+ "flow-last-modified": "Terakhir diubah sekitar $1",
+ "flow-workflow": "alur kerja",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|membalas}} di <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 dan {{PLURAL:$5|satu|$5|100=99+}} lainnya {{GENDER:$1|membalas}} di <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 telah menyunting <span class=\"plainlinks\">[$5 kiriman Anda]</span> di [[$3|$4]].",
+ "flow-notification-edit-bundle": "$1 dan {{PLURAL:$5|satu|$5|100=99+}} lainnya {{GENDER:$1|menyunting}} sebuah <span class=\"plainlinks\">[$4 kiriman]</span> tentang \"$2\" di \"$3\".",
+ "notification-header-flow-new-topic-v2": "Topik baru dibuat di <strong>$3</strong>: <strong>$4</strong>.",
+ "notification-bundle-header-flow-new-topic": "$1 {{PLURAL:$1|topik}} baru di <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Sebuah topik baru telah dibuat di <strong>halaman pembicaraan Anda</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "$1 {{PLURAL:$1|topik}} baru di <strong>halaman pembicaraan Anda</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|membalas}} di \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "$1 {{PLURAL:$1|balasan}} baru di \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|mengirim}} balasan di <strong>halaman pembicaraan Anda</strong> di \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "$1 {{PLURAL:$1|balasan}} baru di <strong>halaman pembicaraan Anda</strong> di \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "Kiriman {{GENDER:$2|Anda}} di \"<strong>$1</strong>\" telah disunting.",
+ "notification-bundle-header-flow-post-edited-v2": "Kiriman {{GENDER:$2|Anda}} di \"<strong>$1</strong>\" telah disunting beberapa kali.",
+ "notification-header-flow-post-edited-user-talk": "Kiriman tentang \"<strong>$1</strong>\" telah disunting di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Kiriman tentang \"<strong>$1</strong>\" telah disunting beberapa kali di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Topik \"<strong>$1</strong>\" diubah nama menjadi \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "Topik \"<strong>$1</strong>\" diubah nama menjadi \"<strong>$2</strong>\" di <strong>halaman pembicaraan Anda</strong>.",
+ "notification-header-flow-summary-edited": "Ringkasan tentang \"<strong>$1</strong>\" telah diperbarui.",
+ "notification-header-flow-summary-edited-first": "Topik \"<strong>$1</strong>\" telah diringkas.",
+ "notification-bundle-header-flow-summary-edited": "Ringkasan tentang \"<strong>$1</strong>\" telah diperbarui beberapa kali.",
+ "notification-header-flow-summary-edited-user-talk": "Ringkasan tentang \"<strong>$1</strong>\" telah diperbarui di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Topik \"<strong>$1</strong>\" telah diringkas di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Ringkasan tentang \"<strong>$1</strong>\" telah diperbarui beberapa kali di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|memperbarui}} ringkasan di $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|memperbarui}} ringkasan di $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 dan {{PLURAL:$3|satu|$3|100=99+}} lainnya {{GENDER:$1|memperbarui}} ringkasan di $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|menyebutkan}} {{GENDER:$4|Anda}} di \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|menyebutkan}} {{GENDER:$4|Anda}} di deskripsi \"<strong>$3</strong>\".",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|menyebutkan}} {{GENDER:$4|Anda}} di \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Sistem diskusi baru telah diaktifkan di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-header-flow-description-edited": "Deskripsi <strong>$1</strong> telah disunting.",
+ "notification-header-flow-description-edited-user-talk": "Deskripsi telah disunting di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-bundle-header-flow-description-edited": "Deskripsi di <strong>$1</strong> telah disunting beberapa kali.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Deskripsi telah beberapa kali disunting di <strong>halaman pembicaraan {{GENDER:$2|Anda}}</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Lihat}} halaman",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$2|menyunting}} deskripsi di $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$2|menyunting}} deskripsi di $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 dan {{PLURAL:$3|satu lainnya|$3 lainnya|100=99+ lainnya}} {{GENDER:$1|menyunting}} deskripsi di $2",
+ "notification-header-flow-topic-resolved": "Topik \"<strong>$1</strong>\" telah terselesaikan.",
+ "notification-header-flow-topic-reopened": "Topik \"<strong>$1</strong>\" telah dibuka kembali.",
+ "notification-header-flow-topic-resolved-user-talk": "Topik \"<strong>$1</strong>\" telah terselesaikan di <strong>halaman pembicaraan Anda</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Topik \"<strong>$1</strong>\" telah dibuka kembali di <strong>halaman pembicaraan Anda</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Topik \"<strong>$2</strong>\" telah terselesaikan.",
+ "notification-email-batch-body-flow-topic-resolved": "Topik \"<strong>$2</strong>\" telah terselesaikan.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|membuat}} topik baru di <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Satu topik baru|$1 topik baru|100=99+ topik baru}} di <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "flow-notification-rename": "$1 {{GENDER:$1|mengubah}} judul <span class=\"plainlinks\">[$2 $3]</span> ke \"$4\" di [[$5|$6]].",
+ "flow-notification-mention": "$1 {{GENDER:$1|menyebutkan}} {{$GENDER:$5|Anda}} di <span class=\"plainlinks\">[$2 kirimannya]</span> dalam \"$3\" di \"$4\".",
+ "flow-notification-link-text-view-post": "Lihat kiriman",
+ "flow-notification-link-text-view-topic": "Lihat topik",
+ "flow-notification-link-text-view-topics": "Lihat topik",
+ "flow-notification-reply-email-subject": "$2 di $3",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|membalas}} ke \"$2\" di $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 dan {{PLURAL:$4|satu|$4|100=99+}} lainnya {{GENDER:$1|membalas}} ke \"$2\" di $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|menyebutkan}} {{GENDER:$3|Anda}} di $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|menyebutkan}} {{GENDER:$4|Anda}} di kirimannya di \"$2\" pada $3",
+ "flow-notification-edit-email-subject": "$1 menyunting sebuah kiriman",
+ "flow-notification-edit-email-batch-body": "$1 menyunting sebuah kiriman di \"$2\" di $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 dan {{PLURAL:$4|satu|$3|100=99+}} lainnya {{GENDER:$1|menyunting}} sebuah kiriman \"$2\" di $3",
+ "flow-notification-rename-email-subject": "$1 mengganti nama topik Anda",
+ "flow-notification-rename-email-batch-body": "$1 mengubah judul topik Anda \"$2\" ke \"$3\" di $4",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|membuat}} topik baru di $2",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|membuat}} topik baru berjudul \"$2\" di $3",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Satu|$1|100=99+}} topik baru di $2",
+ "echo-category-title-flow-discussion": "Flow",
"echo-pref-tooltip-flow-discussion": "Beritahu saya saat ada tindakan yang berhubungan dengan saya terjadi di Flow.",
+ "flow-link-post": "kiriman",
+ "flow-link-topic": "topik",
+ "flow-link-history": "riwayat",
+ "flow-link-post-revision": "revisi kiriman",
+ "flow-link-topic-revision": "revisi topik",
+ "flow-link-header-revision": "revisi deskripsi",
+ "flow-link-summary-revision": "revisi ringkasan",
+ "flow-moderation-title-suppress-post": "Rahasiakan kiriman?",
+ "flow-moderation-title-delete-post": "Hapus kiriman?",
+ "flow-moderation-title-hide-post": "Sembunyikan kiriman?",
+ "flow-moderation-title-unsuppress-post": "Batal merahasiakan kiriman?",
+ "flow-moderation-title-undelete-post": "Batal menghapus kiriman?",
+ "flow-moderation-title-unhide-post": "Batal menyembunyikan kiriman?",
+ "flow-moderation-placeholder-suppress-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda merahasiakan kiriman ini.",
+ "flow-moderation-placeholder-delete-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda menghapus kiriman ini.",
+ "flow-moderation-placeholder-hide-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda menyembunyikan kiriman ini.",
+ "flow-moderation-placeholder-unsuppress-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan perahasiaan kiriman ini.",
+ "flow-moderation-placeholder-undelete-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan penghapusan kiriman ini.",
+ "flow-moderation-placeholder-unhide-post": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan penyembunyian kiriman ini.",
+ "flow-moderation-confirm-suppress-post": "Rahasiakan",
+ "flow-moderation-confirm-delete-post": "Hapus",
+ "flow-moderation-confirm-hide-post": "Sembunyikan",
+ "flow-moderation-confirm-unsuppress-post": "Batal merahasiakan",
+ "flow-moderation-confirm-undelete-post": "Batal menghapus",
+ "flow-moderation-confirm-unhide-post": "Batal menyembunyikan",
+ "flow-moderation-confirm-suppress-topic": "Rahasiakan",
+ "flow-moderation-confirm-delete-topic": "Hapus",
+ "flow-moderation-confirm-hide-topic": "Sembunyikan",
+ "flow-moderation-confirm-unsuppress-topic": "Batal merahasiakan",
+ "flow-moderation-confirm-undelete-topic": "Batal menghapus",
+ "flow-moderation-confirm-unhide-topic": "Batal menyembunyikan",
+ "flow-moderation-confirmation-suppress-post": "Kiriman ini telah dirahasiakan. {{GENDER:$2|Silakan}} berikan umpan balik ke $1 tentang kiriman ini.",
+ "flow-moderation-confirmation-delete-post": "Kiriman ini telah dihapus. {{GENDER:$2|Silakan}} berikan umpan balik ke $1 tentang kiriman ini.",
+ "flow-moderation-confirmation-hide-post": "Kiriman ini telah disembunyikan. {{GENDER:$2|Silakan}} berikan umpan balik ke $1 tentang kiriman ini.",
+ "flow-moderation-confirmation-unsuppress-post": "Anda telah membatalkan perahasiaan kiriman di atas.",
+ "flow-moderation-confirmation-undelete-post": "Anda telah membatalkan penghapusan kiriman di atas.",
+ "flow-moderation-confirmation-unhide-post": "Anda telah membatalkan penyembunyian kiriman di atas.",
"flow-moderation-confirmation-suppress-topic": "Topik ini telah dipadamkan",
"flow-moderation-confirmation-delete-topic": "Topik ini telah dihapus",
- "flow-moderation-confirmation-hide-topic": "Topik ini telah disembunyikan"
+ "flow-moderation-confirmation-hide-topic": "Topik ini telah disembunyikan",
+ "flow-moderation-confirmation-unsuppress-topic": "Anda telah membatalkan perahasiaan topik ini.",
+ "flow-moderation-confirmation-undelete-topic": "Anda telah membatalkan penghapusan topik ini.",
+ "flow-moderation-confirmation-unhide-topic": "Anda telah membatalkan penyembunyian topik ini.",
+ "flow-moderation-title-suppress-topic": "Rahasiakan topik?",
+ "flow-moderation-title-delete-topic": "Hapus topik?",
+ "flow-moderation-title-hide-topic": "Sembunyikan topik?",
+ "flow-moderation-title-unsuppress-topic": "Batal merahasiakan topik?",
+ "flow-moderation-title-undelete-topic": "Batal menghapus topik?",
+ "flow-moderation-title-unhide-topic": "Batal menyembunyikan topik?",
+ "flow-moderation-placeholder-suppress-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda merahasiakan topik ini.",
+ "flow-moderation-placeholder-delete-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda menghapus topik ini.",
+ "flow-moderation-placeholder-hide-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda menyembunyikan topik ini.",
+ "flow-moderation-placeholder-unsuppress-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan perahasiaan topik ini.",
+ "flow-moderation-placeholder-undelete-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan penghapusan topik ini.",
+ "flow-moderation-placeholder-unhide-topic": "Silakan {{GENDER:$3|jelaskan}} mengapa Anda membatalakan penyembunyian topik ini.",
+ "flow-topic-permalink-warning": "Topik ini dimulai di [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Topik ini dimulai di [$2 forumnya $1]",
+ "flow-revision-permalink-warning-post": "Ini adalah pranala permanen ke sebuah versi dari kiriman ini.\nVersi ini dibuat $1.\nAnda dapat melihat [$5 beda dengan versi sebelumnya], atau melihat versi lainnya di [$4 halaman riwayat kiriman].",
+ "flow-revision-permalink-warning-post-first": "Ini adalah pranala permanen ke versi terawal dari kiriman ini.\nAnda dapat melihat versi selanjutnya di [$4 halaman riwayat kiriman].",
+ "flow-revision-permalink-warning-postsummary": "Ini adalah pranala permanen ke sebuah ringkasan dari kiriman ini. Versi ini dibuat $1.\nAnda dapat melihat [$5 beda dengan versi sebelumnya], atau melihat versi lainnya di [$4 halaman riwayat kiriman].",
+ "flow-revision-permalink-warning-postsummary-first": "Ini adalah pranala permanen ke versi terawal dari ringkasan kiriman ini.\nAnda dapat melihat versi selanjutnya di [$4 halaman riwayat kiriman].",
+ "flow-revision-permalink-warning-header": "Ini adalah pranala permanen ke sebuah versi dari deskripsi ini.\nVersi ini dibuat $1. Anda dapat melihat [$3 beda dengan versi sebelumnya], atau melihat versi lainnya di [$2 halaman riwayat kiriman].",
+ "flow-revision-permalink-warning-header-first": "Ini adalah pranala permanen ke versi terawal dari deskripsi kiriman ini.\nAnda dapat melihat versi selanjutnya di [$2 halaman riwayat kiriman].",
+ "flow-compare-revisions-revision-header": "Versi $1 oleh $2",
+ "flow-compare-revisions-header-post": "Halaman ini menunjukkan {{GENDER:$3|perbedaan}} antara dua revisi dari sebuah kiriman oleh $3 di topik \"[$5 $2]\" di [$4 $1].\nAnda dapat melihat versi lain dari kiriman ini di [$6 halaman riwayat].",
+ "flow-compare-revisions-header-postsummary": "Halaman ini menunjukkan perbedaan antara dua revisi dari sebuah ringkasan kiriman di topik \"[$4 $2]\" di [$3 $1].\nAnda dapat melihat versi lain dari kiriman ini di [$5 halaman riwayat].",
+ "flow-compare-revisions-header-header": "Halaman ini menunjukkan {{GENDER:$2|perbedaan}} antara dua revisi dari deskripsi di [$3 $1].\nAnda dapat melihat versi lain dari kiriman ini di [$4 halaman riwayat].",
+ "action-flow-create-board": "buat forum Flow di mana saja",
+ "right-flow-create-board": "Buat forum Flow di mana saja",
+ "right-flow-hide": "Sembunyikan topik dan kiriman Flow",
+ "right-flow-lock": "Tandai topik Flow sebagai terselesaikan",
+ "right-flow-delete": "Hapus topik dan kiriman Flow",
+ "right-flow-edit-post": "Sunting kiriman Flow oleh pengguna lain",
+ "right-flow-suppress": "Rahasiakan revisi Flow",
+ "flow-terms-of-use-new-topic": "Dengan mengeklik \"{{int:flow-newtopic-save}}\", Anda menyetujui syarat pengunaan wiki ini.",
+ "flow-terms-of-use-reply": "Dengan mengeklik \"{{int:flow-reply-link}}\", Anda menyetujui syarat pengunaan wiki ini.",
+ "flow-terms-of-use-edit": "Dengan menyimpan perubahan ini, Anda setuju dengan syarat penggunaan wiki ini.",
+ "flow-anon-warning": "Anda belum masuk log. Untuk mencantumkan nama Anda alih-alih alamat IP Anda, Anda dapat [$1 masuk log] atau [$2 buat akun baru].",
+ "flow-cancel-warning": "Anda telah memasukkan tulisan di formulir ini. Apakah Anda yakin membuang tulisan ini?",
+ "flow-topic-first-heading": "Topik tentang $1",
+ "flow-topic-html-title": "$1 pada $2",
+ "flow-topic-count": "Topik ($1)",
+ "flow-load-more": "Baca lebih lanjut",
+ "flow-no-more-fwd": "Tidak ada topik yang lebih lama",
+ "flow-newest-topics": "Topik terbaru",
+ "flow-recent-topics": "Topik aktif terkini",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Anda}} sedang membaca dengan urutan yang pertama adalah topik terbaru. Klik untuk menemukan opsi pengurutan lainnya.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Anda}} sedang membaca dengan urutan yang pertama adalah topik aktif terbaru. Klik untuk menemukan opsi pengurutan lainnya.",
+ "flow-toggle-small-topics": "Ganti ke tampilan kecil topik",
+ "flow-toggle-topics": "Ganti ke tampilan topik saja",
+ "flow-toggle-topics-posts": "Ganti ke tampilan topik dan kiriman",
+ "flow-terms-of-use-summarize": "Dengan mengeklik \"{{int:flow-topic-action-update-topic-summary}}\", Anda menyetujui syarat pengunaan wiki ini.",
+ "flow-terms-of-use-lock-topic": "Dengan mengeklik \"{{int:flow-topic-action-lock-topic}}\", Anda menyetujui syarat pengunaan wiki ini.",
+ "flow-terms-of-use-unlock-topic": "Dengan mengeklik \"{{int:flow-topic-action-unlock-topic}}\", Anda menyetujui syarat pengunaan wiki ini.",
+ "flow-whatlinkshere-post": "dari sebuah [$1 kiriman]",
+ "flow-whatlinkshere-header": "dari [$1 deskripsi]",
+ "flow-whatlinkshere-post-summary": "dari [$1 ringkasan]",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Halaman istimewa ini mengalihkan ke sebuah alur kerja Flow atau kiriman Flow jika diberikan sebuah UUID.",
+ "flow-special-type": "Jenis",
+ "flow-special-type-post": "Kiriman",
+ "flow-special-type-workflow": "Alur kerja",
+ "flow-special-uuid": "UUID",
+ "flow-special-invalid-uuid": "Tidak dapat menemukan jenis dan UUID yang sesuai dengan isi.",
+ "flow-special-enableflow-legend": "Aktifkan Flow di halaman baru",
+ "flow-special-enableflow-page": "Halaman tempat Flow akan diaktifkan",
+ "flow-special-enableflow-header": "Deskripsi awal forum Flow (teks wiki)",
+ "flow-special-enableflow-board-already-exists": "Telah ada forum Flow di [[$1]].",
+ "flow-special-enableflow-invalid-title": "Judul halaman yang diberikan tidaklah valid.",
+ "flow-special-enableflow-board-creation-not-allowed": "Anda tidak diizinkan membuat forum flow di [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Telah ada halaman LiquidThreads di [[:$1]].",
+ "flow-special-enableflow-confirmation": "Anda telah membuat forum Flow di [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Arsip %d\n%s/Arsip%d\n%s/arsip %d\n%s/arsip%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Arsip Flow %d\n%s/ArsipFlow%d",
+ "flow-spam-confirmedit-form": "Silakan buktikan bahwa Anda merupakan manusia dengan cara menyelesaikan captcha berikut: $1",
+ "flow-embedding-unsupported": "Diskusi belum dapat ditransklusi.",
+ "mw-ui-unsubmitted-confirm": "Anda memiliki revisi yang belum dikirim. Apakah Anda yakin ingin beranjak dan menghilangkan kiriman Anda?",
+ "flow-post-undo-hide": "batal menyembunyikan",
+ "flow-post-undo-delete": "batal menghapus",
+ "flow-post-undo-suppress": "batal merahasiakan",
+ "flow-topic-undo-hide": "batal menyembunyikan",
+ "flow-topic-undo-delete": "batal menghapus",
+ "flow-topic-undo-suppress": "batal merahasiakan",
+ "flow-importer-lqt-converted-template": "Halaman LQT terkonversi ke Flow",
+ "flow-importer-wt-converted-template": "Halaman pembicaraan teks wiki terkonversi ke Flow",
+ "flow-importer-wt-converted-archive-template": "Arsip untuk halaman pembicaraan teks wiki yang terkonversi",
+ "flow-edited": "Tersunting",
+ "flow-edited-by": "Disunting oleh $1",
+ "flow-talk-conversion-move-reason": "Mengonversi halaman pembicaraan teks wiki ke Flow dari $1",
+ "flow-talk-conversion-archive-edit-reason": "Konversi halaman pembicaraan teks wiki ke Flow",
+ "flow-previous-diff": "← Revisi sebelumnya",
+ "flow-next-diff": "Revisi selanjutnya →",
+ "flow-undo": "balikkan",
+ "flow-undo-latest-revision": "Revisi terkini",
+ "flow-undo-your-text": "Teks Anda",
+ "flow-undo-edit-header": "Menyunting deskripsi",
+ "flow-undo-edit-topic-summary": "Menyunting ringkasan topik",
+ "flow-undo-edit-post": "Sunting sebuah kiriman",
+ "flow-undo-edit-content": "Suntingan ini tidak dapat dibalikkan. Silakan periksa perbandingan di bawah untuk meyakinkan bahwa benar itu yang Anda ingin lakukan, lalu simpan perubahan tersebut untuk menyelesaikan pembalikkan suntingan.",
+ "flow-undo-edit-failure": "Suntingan ini tidak dapat dibalikkan karena konflik penyuntingan antara.",
+ "group-flow-bot": "Bot Flow",
+ "group-flow-bot-member": "Bot Flow",
+ "grouppage-flow-bot": "Project:Bot Flow",
+ "flow-ve-mention-context-item-label": "Sebutkan",
+ "flow-ve-mention-inspector-title": "Sebutkan",
+ "flow-ve-mention-inspector-remove-label": "Hapus",
+ "flow-ve-mention-placeholder": "Nama pengguna",
+ "flow-ve-mention-tool-title": "Sebutkan pengguna",
+ "flow-ve-mention-template-title": "FlowMention",
+ "flow-ve-mention-inspector-invalid-user": "Pengguna \"$1\" tidak terdaftar.",
+ "flow-wikitext-editor-help": "Teks wiki $1.",
+ "flow-wikitext-editor-help-and-preview": "Teks wiki $1 dan Anda dapat $2 kapan saja.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|menggunakan markah]]",
+ "flow-wikitext-editor-help-preview-the-result": "lihat pratayang hasil",
+ "flow-wikitext-switch-editor-tooltip": "Ganti ke penyunting visual",
+ "flow-ve-switch-editor-tool-title": "Ganti ke editor teks wiki",
+ "flow-mark-revision-patrolled-link-text": "Tandai halaman ini telah dipatroli",
+ "flow-mark-revision-patrolled-link-title": "Tandai halaman ini telah dipatroli",
+ "flow-mark-diff-patrolled-link-text": "Tandai telah dipatroli",
+ "flow-mark-diff-patrolled-link-title": "Tandai telah dipatroli",
+ "flow-talk-page-beta-feature-message": "Flow di halaman pembicaraan pengguna",
+ "flow-talk-page-beta-feature-description": "Mengaktifkan sistem diskusi baru yang terstruktur di halaman pembicaraan {{GENDER:|Anda}}. Flow menyederhanakan diskusi di halaman pembicaraan dengan tempat jelas untuk menulis dan membalas, dan memungkinkan pemberitahuan tingkat percapakan. Diskusi teks wiki sekarang ini akan dipindahkan ke sebuah arsip. Fitur ini tidak diaktifkan secara baku; pengguna harus mengaktifkannya secara manual. Menonaktifkan fitur ini akan memindahkan forum Flow ke sebuah subhalaman dan mengembalikan arsip dari halaman pembicaraan sebelumnya.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Lihat}} halaman pembicaraan pengguna",
+ "flow-notification-enabled-on-talkpage-title": "Sistem diskusi baru telah diaktifkan di halaman pembicaraan {{GENDER:$1|Anda}}<br /><small>Tersedia di [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Sistem diskusi baru di $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, sistem diksusi wiki yang baru, telah diaktifkan di halaman pembicaraan {{GENDER:$1|Anda}} di {{SITENAME}}. Anda dapat mendapatkan informasi lebih lanjut, memberikan umpan balik, atau menonaktifkan sistem baru ini kapan saja dari bagian fitur Beta di preferensi {{GENDER:$1|Anda}}",
+ "flow-beta-feature-add-archive-template-edit-summary": "Menambahkan templat arsip",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Menghapus templat arsip",
+ "flow-dialog-cancelconfirm-title": "Apakah Anda yakin?",
+ "flow-dialog-cancelconfirm-message": "Apakah Anda yakin ingin membatalkan tanpa menyimpan terlebih dahulu?",
+ "flow-dialog-cancelconfirm-keep": "Lanjutkan penyuntingan",
+ "flow-dialog-cancelconfirm-discard": "Buang perubahan",
+ "flow-optin-archive-wikitext": "Pindahkan halaman teks wiki agar dapat membuat forum diskusi di ini.",
+ "flow-optin-archive-flow-board": "Pindahkan halaman diskusi agar dapat membuat halaman teks wiki di sini.",
+ "flow-optin-restore-wikitext": "Mengembalikan halaman teks wiki yang terarsipkan.",
+ "flow-optin-restore-flow-board": "Mengembalikan forum diskusi yang terarsipkan.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Selamat datang}} di halaman pembicaraan {{GENDER:$1|Anda}} yang baru",
+ "flow-guidedtour-optin-welcome-description": "Halaman pembicaraan {{GENDER:$1|Anda}} merupakan tempat penyunting lainnya dapat menghubungi {{GENDER:$1|Anda}}. Dengan Flow, topik baru akan lebih mudah dimulai dan pembicaraan lebih mudah dipantau.",
+ "flow-guidedtour-optin-find-old-conversations": "Temukan pembicaraan lama {{GENDER:$1|Anda}}",
+ "flow-guidedtour-optin-find-old-conversations-description": "Pembicaraan lama Anda telah dipindahkan ke halaman arsip.",
+ "flow-guidedtour-optin-feedback": "Berikan umpan balik {{GENDER:$1|Anda}}!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Anda}} dapat mendapatkan informasi lebih banyak, memberikan umpan balik, atau menonaktifkan sistem baru ini kapan saja dari bagian fitur Beta.",
+ "flow-action-not-page": "Objek halaman merupakan turunan dari kelas yang salah.",
+ "flow-action-wrong-title-content-model": "Halaman ini diurus oleh Flow, namun kelas Title menyatakan bahwa model isi adalah '$1'. Ini adalah salah konfigurasi atau keadaan yang tidak konsisten. Contohnya, bisa jadi ini merupakan halaman non-Flow yang berada dalam ruang nama Flow, dengan <code>rev_content_model</code> tidak terpopulasi."
}
diff --git a/Flow/i18n/inh.json b/Flow/i18n/inh.json
new file mode 100644
index 00000000..ca018c25
--- /dev/null
+++ b/Flow/i18n/inh.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Adam-Yourist"
+ ]
+ },
+ "flow-topic-action-watchlist": "Зем бара хьаязъяьр"
+}
diff --git a/Flow/i18n/it.json b/Flow/i18n/it.json
index 01cbd57b..d61bacd5 100644
--- a/Flow/i18n/it.json
+++ b/Flow/i18n/it.json
@@ -14,26 +14,56 @@
"Ricordisamoa",
"Alexmar983",
"Erasmo Barresi",
- "Statix64"
+ "Statix64",
+ "Nnemo",
+ "Matteocng",
+ "Anto",
+ "Fringio"
]
},
- "enableflow": "Attiva Flow",
- "flow-desc": "Sistema di gestione del flusso di lavoro",
- "log-name-flow": "Attività sui flussi",
+ "enablestructureddiscussions": "Attiva discussioni strutturate",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Rimuovi}} le nuove attività su \"$1\" dagli osservati speciali",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Non {{GENDER:$3|stai}} più osservando la pagina \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Questo non influenzerà i singoli argomenti che {{GENDER:$3|stai}} seguendo. {{GENDER:$3|Puoi}} inserire [$2 questa pagina] negli osservati speciali in qualsiasi momento.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Rimuovi}} questo argomento dagli osservati speciali",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Non {{GENDER:$3|stai}} più osservando \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Puoi}} inserire [$2 questo argomento] negli osservati speciali in qualsiasi momento.",
+ "flow-desc": "Sistema di discussione",
+ "flow-talk-taken-over-comment": "/* Questa pagina è stata convertita in una bacheca di discussioni strutturate */",
+ "log-name-flow": "Attività sulle discussioni strutturate",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|ha cancellato}} un [$4 messaggio] su \"[[$3|$5]]\" su [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|ha cancellato}} un messaggio di un argomento su [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|ha ripristinato}} un [$4 messaggio] su \"[[$3|$5]]\" su [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|ha ripristinato}} un messaggio di un argomento su [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|ha soppresso}} un [$4 messaggio] su \"[[$3|$5]]\" su [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|ha soppresso}} un messaggio di un argomento su [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|ha cancellato}} un [$4 messaggio] su \"[[$3|$5]]\" su [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|ha cancellato}} un messaggio di un argomento su [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|ha cancellato}} l'argomento \"[[$3|$5]]\" su [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha cancellato}} un argomento su [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|ha ripristinato}} l'argomento \"[[$3|$5]]\" su [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha ripristinato}} un argomento su [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ha soppresso}} l'argomento \"[[$3|$5]]\" su [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha soppresso}} un argomento su [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|ha cancellato}} l'argomento \"[[$3|$5]]\" su [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] su [[$3]] è stato importato da LiquidThreads a Flow",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha cancellato}} un argomento su [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|ha contrassegnato}} l'argomento \"[[$3|$5]]\" come risolto su [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha contrassegnato}} un argomento come risolto su [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|ha riaperto}} l'argomento \"[[$3|$5]]\" su [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|ha riaperto}} un argomento su [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] su [[$3]] è stato importato da LiquidThreads a discussioni strutturate",
+ "abusefilter-edit-builder-vars-board-articleid": "ID pagina della bacheca di discussioni strutturate",
+ "abusefilter-edit-builder-vars-board-namespace": "Namespace della bacheca di discussioni strutturate",
+ "abusefilter-edit-builder-vars-board-text": "Titolo della bacheca di discussioni strutturate",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Titolo completo della bacheca di discussioni strutturate",
"flow-user-moderated": "Utente moderato",
"flow-board-header-browse-topics-link": "Sfoglia argomenti",
- "flow-board-header": "A proposito di questa discussione",
+ "flow-board-header": "A proposito di questa bacheca",
+ "flow-board-description-can-not-edit": "Non modificabile",
"flow-board-collapse-description": "Nascondi descrizione",
"flow-board-expand-description": "Mostra descrizione",
+ "flow-topic-collapse-siderail": "Leggi a larghezza piena",
+ "flow-topic-expand-siderail": "Leggi a larghezza fissa",
"flow-edit-header-link": "Modifica descrizione",
"flow-post-moderated-toggle-hide-show": "Mostra commenti {{GENDER:$1|nascosti}} da $2",
"flow-post-moderated-toggle-delete-show": "Mostra commenti {{GENDER:$1|cancellati}} da $2",
@@ -55,24 +85,27 @@
"flow-post-actions": "Azioni",
"flow-topic-actions": "Azioni",
"flow-cancel": "Annulla",
- "flow-skip-summary": "Salta il riepilogo",
+ "flow-skip-summary": "Salta",
"flow-edit-summary-placeholder": "Descrivi brevemente l'esito di questa discussione",
- "flow-summary-authored": "Sintesi di $1",
+ "flow-summary-authored": "Riassunto di $1",
"flow-summary-edited": "Sintesi modificata per l'ultima volta da $1",
"flow-show-change": "Mostra modifiche",
"flow-last-modified-by": "Ultima {{GENDER:$1|modifica}} di $1",
- "flow-stub-post-content": "''A causa di un errore tecnico, questo messaggio non può essere recuperato.''",
+ "flow-stub-post-content": "<em>A causa di un errore tecnico, questo contenuto non può essere recuperato.</em>",
"flow-newtopic-title-placeholder": "Nuovo argomento",
"flow-newtopic-content-placeholder": "Scrivi un nuovo messaggio su \"$1\"",
"flow-newtopic-header": "Aggiungi un nuovo argomento",
"flow-newtopic-save": "Aggiungi argomento",
+ "flow-newtopic-save-anonymously": "Aggiungi argomento anonimamente",
"flow-newtopic-start-placeholder": "Inizia un nuovo argomento",
"flow-newtopic-first-heading": "Inizia un nuovo argomento su $1",
"flow-summarize-topic-placeholder": "Riassumi questo argomento",
"flow-reply-topic-placeholder": "{{GENDER:$1|Commento}} su \"$2\"",
"flow-reply-topic-title-placeholder": "Risposta a \"$1\"",
"flow-reply-link": "{{GENDER:$1|Rispondi}}",
+ "flow-reply-link-anonymously": "Rispondi anonimamente",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Ringrazia}}}}",
+ "flow-thank-link-title": "{{GENDER:$1|Ringrazia}} pubblicamente {{GENDER:$2|l'autore|l'autrice|l'autore/trice}}",
"flow-history-action-suppress-post": "sopprimi",
"flow-history-action-delete-post": "cancella",
"flow-history-action-hide-post": "nascondi",
@@ -80,7 +113,7 @@
"flow-history-action-undelete-post": "ripristina",
"flow-history-action-unhide-post": "rendi visibile",
"flow-history-action-restore-post": "ripristina",
- "flow-history-action-lock-topic": "chiudi",
+ "flow-history-action-lock-topic": "risolvi",
"flow-history-action-unlock-topic": "riapri",
"flow-post-edited": "Messaggio {{GENDER:$1|modificato}} da $1 $2",
"flow-post-action-view": "Link permanente",
@@ -90,6 +123,7 @@
"flow-post-action-hide-post": "Nascondi",
"flow-post-action-edit-post": "Modifica",
"flow-post-action-edit-post-submit": "Salva modifiche",
+ "flow-post-action-edit-post-submit-anonymously": "Salva modifiche anonimamente",
"flow-post-action-unsuppress-post": "Annulla soppressione",
"flow-post-action-undelete-post": "Ripristina",
"flow-post-action-unhide-post": "Rendi visibile",
@@ -101,7 +135,7 @@
"flow-topic-action-history": "Cronologia",
"flow-topic-action-hide-topic": "Nascondi argomento",
"flow-topic-action-delete-topic": "Cancella argomento",
- "flow-topic-action-lock-topic": "Segnala come chiuso",
+ "flow-topic-action-lock-topic": "Contrassegna come risolto",
"flow-topic-action-unlock-topic": "Riapri argomento",
"flow-topic-action-summarize-topic": "Riassumi",
"flow-topic-action-resummarize-topic": "Modifica riassunto dell'argomento",
@@ -118,25 +152,28 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Riceverai}} una notifica quando un nuovo argomento verrà creato su questa bacheca.",
"flow-topic-action-watchlist-add": "Iscriviti a questo argomento",
"flow-topic-action-watchlist-remove": "Cancella l'iscrizione",
- "flow-error-allowcreation-no-usedb": "allowCreation richiede che <var>$wgContentHandlerUseDB</var> sia <code>true</code>.",
+ "flow-error-allowcreation-no-usedb": "L'attivazione delle discussioni strutturate su una pagina specifica richiede che <var>$wgContentHandlerUseDB</var> sia <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "La pagina già esiste nella destinazione, perciò una bacheca di discussioni strutturate non può essere spostata lì.",
+ "flow-error-allowcreation-flow-create-board": "L'utente non ha l'autorizzazione \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Al momento non puoi partecipare. Prova ad accedere.",
+ "flow-error-can-not-edit-logged-in": "Al momento non puoi partecipare, perché non hai i diritti richiesti.",
"flow-error-http": "Si è verificato un errore durante la comunicazione con il server.",
- "flow-error-other": "Si è verificato un errore imprevisto.",
- "flow-error-external": "Si è verificato un errore.<br />Il messaggio di errore ricevuto è: $1",
+ "flow-error-external": "Si è verificato un errore. Il messaggio di errore ricevuto è: $1",
"flow-error-topic-is-locked": "Questo argomento è risolto, ulteriore attività non è pertanto possibile.",
- "flow-error-lock-moderated-post": "Non puoi segnalare come chiuso un messaggio moderato.",
- "flow-error-external-multi": "Si sono verificati errori.<br />$1",
+ "flow-error-lock-moderated-post": "Non puoi contrassegnare come risolto un messaggio moderato.",
"flow-error-missing-content": "Il tuo messaggio non ha contenuto. Un minimo di contenuto è necessario per poter salvare un messaggio.",
"flow-error-missing-summary": "È necessario inserire un riassunto.",
"flow-error-missing-title": "L'argomento non ha titolo. Serve un titolo per salvare un argomento.",
- "flow-error-parsoid-failure": "Impossibile analizzare il contenuto a causa di un errore di Parsoid.",
+ "flow-error-parsoid-failure": "Impossibile trasferire il contenuto: errore nel contattare il server per la conversione tra il wikitesto e HTML. Controlla la tua connessione a internet o riprova più tardi se il problema persiste. Se ricevi ancora questo errore invia una segnalazione.",
+ "flow-error-protected-autoconfirmed-logged-in": "Questa bacheca Flow è protetta. Solo gli utenti autoconfermati possono partecipare. Motivo: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Questa bacheca Flow è protetta. Solo gli utenti registrati che sono autoconfermati possono partecipare. Motivo: $1",
+ "flow-error-protected-sysop-logged-in": "Questa bacheca Flow è protetta. Solo gli utenti con funzioni di amministratore possono partecipare. Motivo: $1",
+ "flow-error-protected-sysop-logged-out": "Questa bacheca Flow è protetta. Solo gli utenti registrati con funzioni di amministratore possono partecipare. Motivo: $1",
+ "flow-error-protected-unknown-reason": "Sconosciuto",
"flow-error-missing-replyto": "Non è stato indicato un parametro \"rispondi_a\". Questo parametro è richiesto per la funzione \"rispondi\".",
- "flow-error-invalid-replyto": "Il parametro \"rispondi_a\" non era valido. Il messaggio indicato non è stato trovato.",
- "flow-error-delete-failure": "La cancellazione di questo elemento non è riuscita.",
- "flow-error-hide-failure": "Il tentativo di nascondere questo elemento non è riuscito.",
"flow-error-missing-postId": "Non è stato fornito alcun parametro \"ID_messaggio\". Questo parametro è necessario per poter elaborare un messaggio.",
"flow-error-invalid-postId": "Il parametro \"ID_messaggio\" non era valido. Il messaggio indicato ($1) non è stato trovato.",
- "flow-error-restore-failure": "Il ripristino di questo elemento non è riuscito.",
- "flow-error-invalid-moderation-state": "È stato fornito un valore non valido per il parametro ('moderationState') alle API Flow.",
+ "flow-error-invalid-moderation-state": "È stato fornito un valore non valido per il parametro ('moderationState') alle API di discussioni strutturate.",
"flow-error-invalid-moderation-reason": "Fornisci una motivazione per la moderazione",
"flow-error-not-allowed": "Autorizzazioni insufficienti per eseguire questa azione",
"flow-error-not-allowed-hide": "Questo argomento è stato nascosto.",
@@ -145,6 +182,7 @@
"flow-error-not-allowed-reply-to-delete-topic": "Non puoi rispondere perché questo argomento è stato cancellato.",
"flow-error-not-allowed-suppress": "Questo argomento è stato cancellato.",
"flow-error-not-allowed-reply-to-suppress-topic": "Non puoi rispondere perché questo argomento è stato cancellato.",
+ "flow-error-not-allowed-hide-extract": "Questo argomento è stato nascosto. Il registro delle occultazioni per l'argomento è disponibile qui sotto per riferimento.",
"flow-error-not-allowed-delete-extract": "Questo argomento è stato cancellato. Il registro delle cancellazioni per l'argomento è disponibile qui sotto per riferimento.",
"flow-error-not-allowed-reply-to-delete-topic-extract": "Non puoi rispondere perché questo argomento è stato cancellato. Il registro delle cancellazioni per l'argomento è disponibile qui sotto per riferimento.",
"flow-error-not-allowed-suppress-extract": "Questo argomento è stato cancellato. Il registro delle cancellazioni per l'argomento è disponibile qui sotto per riferimento.",
@@ -156,15 +194,19 @@
"flow-error-missing-prev-revision-identifier": "L'Identificatore della versione precedente è mancante.",
"flow-error-prev-revision-mismatch": "Un altro utente ha modificato questo messaggio pochi secondi fa. Sei {{GENDER:$3|sicuro|sicura}} di voler sovrascrivere la recente modifica?",
"flow-error-prev-revision-does-not-exist": "Impossibile trovare la versione precedente.",
+ "flow-error-core-topic-deletion": "Per cancellare un argomento, usa il menu ... nella bacheca di discussioni strutturate o nella [$1 pagina dell'argomento]. Non visitare direttamente action=delete per l'argomento.",
"flow-error-default": "Si è verificato un errore.",
- "flow-error-invalid-input": "È stato fornito un valore non valido per il caricamento dei contenuti Flow.",
+ "flow-error-invalid-input": "È stato fornito un valore non valido per il caricamento dei contenuti di discussioni strutturate.",
"flow-error-invalid-title": "È stato fornito un titolo di pagina non valido.",
+ "flow-error-invalid-parameter": "Parametro mancante o non valido nella chiamata al metodo",
"flow-error-fail-load-history": "Impossibile caricare la cronologia.",
- "flow-error-missing-revision": "Non è possibile trovare una versione per il caricamento dei contenuti Flow.",
- "flow-error-fail-commit": "Impossibile salvare il contenuto del flusso.",
+ "flow-error-missing-revision": "Non è possibile trovare una versione per il caricamento dei contenuti di discussioni strutturate.",
+ "flow-error-fail-commit": "Impossibile salvare il contenuto delle discussioni strutturate.",
"flow-error-insufficient-permission": "Autorizzazioni insufficienti per accedere al contenuto.",
"flow-error-revision-comparison": "Le differenze possono essere visualizzate solo per due versioni dello stesso messaggio.",
"flow-error-missing-topic-title": "Impossibile trovare il titolo dell'argomento per il flusso di lavoro attuale.",
+ "flow-error-missing-metadata": "Non è possibile trovare i metadati necessari per questa versione.",
+ "flow-error-different-page": "Il flusso di lavoro di discussioni strutturate non è associato a questa pagina.",
"flow-error-fail-load-data": "Impossibile caricare i dati richiesti.",
"flow-error-invalid-workflow": "Impossibile trovare il flusso di lavoro richiesto.",
"flow-error-process-data": "Si è verificato un errore durante l'elaborazione dei dati nella tua richiesta.",
@@ -173,13 +215,20 @@
"flow-error-no-render": "L'azione indicata non è stata riconosciuta.",
"flow-error-no-commit": "L'azione specificata non può essere salvata.",
"flow-error-content-too-long": "Il contenuto è troppo grande. Il contenuto, dopo l'espansione, deve essere minore di $1 {{PLURAL:$1|byte}}.",
+ "flow-error-move-topic": "Lo spostamento della pagine di un argomento non è attualmente supportato.",
"flow-error-invalid-topic-uuid-title": "Titolo non corretto",
+ "flow-error-invalid-topic-uuid": "Il titolo della pagina richiesto non è valido. Le pagine nel namespace Topic sono create automaticamente dalle discussioni strutturate.",
"flow-error-unknown-workflow-id-title": "Argomento sconosciuto",
"flow-error-unknown-workflow-id": "L'argomento richiesto non esiste.",
+ "flow-error-search": "Non si è riuscito a completare la tua ricerca a causa di un problema temporaneo. Riprova più tardi.",
+ "flow-error-invalid-undelete": "La pagina non può essere ripristinata poiché attualmente c'è una bacheca di discussione al suo posto.",
"flow-edit-header-placeholder": "Descrivi questa bacheca di discussione",
"flow-edit-header-submit": "Salva descrizione",
+ "flow-edit-header-submit-anonymously": "Salva descrizione anonimamente",
"flow-edit-title-submit": "Cambia titolo",
+ "flow-edit-title-submit-anonymously": "Modifica titolo anonimamente",
"flow-edit-post-submit": "Invia modifiche",
+ "flow-edit-post-submit-anonymously": "Salva modifiche anonimamente",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|ha modificato}} un [$3 commento] su \"$4\".",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Modificato}} un messaggio",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|ha commentato}}] su \"$4\" (<em>$5</em>).",
@@ -189,7 +238,7 @@
"flow-rev-message-edit-title": "$1 {{GENDER:$2|ha modificato}} il titolo dell'argomento da \"$5\" a \"[$3 $4]\".",
"flow-rev-message-create-header": "$1 {{GENDER:$2|ha creato}} la descrizione.",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|ha modificato}} la descrizione.",
- "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|ha creato}} la sintesi dell'argomento $3.",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|ha creato}} il riassunto dell'argomento $3.",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|ha modificato}} la sintesi dell'argomento $3.",
"flow-rev-message-hid-post": "$1 {{GENDER:$2|ha nascosto}} un [$4 commento] su \"$6\" (<em>$5</em>).",
"flow-rev-message-deleted-post": "$1 {{GENDER:$2|ha cancellato}} un [$4 commento] su \"$6\" (<em>$5</em>).",
@@ -198,7 +247,8 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ha nascosto}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|ha cancellato}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|ha soppresso}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|ha segnalato}} come chiuso [$4 l'argomento] $6 (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|ha contrassegnato}} come risolto [$4 l'argomento] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "contrassegnato come risolto",
"flow-rev-message-restore-topic-reason": "riaperto",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|ha ripristinato}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
"flow-rc-topic-of-board": "$1 su $2",
@@ -220,37 +270,80 @@
"flow-comment-moderated": "Commento moderato",
"flow-last-modified": "Ultima modifica $1",
"flow-workflow": "flusso di lavoro",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|ha risposto}} su '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e {{PLURAL:$6|un altro|altri $5}} {{GENDER:$1|hanno risposto}} su '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|ha risposto}} su <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e {{PLURAL:$5|un altro utente|altri $5 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno risposto}} su <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|ha modificato}} il tuo <span class=\"plainlinks\">[$5 messaggio]</span> su [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 e {{PLURAL:$6|un altro|altri $5}} utenti {{GENDER:$1|hanno modificato}} un <span class=\"plainlinks\">[$4 messaggio]</span> in \"$2\" su \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 ha {{GENDER:$1|creato}} un nuovo argomento su '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nuovo argomento|$1 nuovi argomenti|250=250+ nuovi argomenti}} su '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 e {{PLURAL:$5|un altro utente|altri $5 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno modificato}} un <span class=\"plainlinks\">[$4 messaggio]</span> in \"$2\" su \"$3\".",
+ "notification-header-flow-new-topic-v2": "Nuovo argomento creato su <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Un nuovo argomento|$1 nuovi argomenti|100=Più di 99 nuovi argomenti}} su <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Un nuovo argomento è stato creato sulla <strong>tua pagina di discussione</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Un nuovo argomento|$1 nuovi argomenti|100=Più di 99 nuovi argomenti}} nella <strong>tua pagina di discussione</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|ha risposto}} in \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Una nuova risposta|$1 nuove risposte|100=Più di 99 nuove risposte}} in \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|ha lasciato}} una risposta sulla <strong>tua pagina di discussione</strong> in \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Una nuova risposta|$1 nuove risposte|100=Più di 99 nuove risposte}} nella <strong>tua pagina di discussione</strong> in \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "Il {{GENDER:$2|tuo}} messaggio in \"<strong>$1</strong>\" è stato modificato.",
+ "notification-bundle-header-flow-post-edited-v2": "Il {{GENDER:$2|tuo}} messaggio in \"<strong>$1</strong>\" è stato modificato più volte.",
+ "notification-header-flow-post-edited-user-talk": "Un messaggio in \"<strong>$1</strong>\" è stato modificato sulla <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Un messaggio in \"<strong>$1</strong>\" è stato modificato più volte sulla <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-header-flow-topic-renamed-v2": "L'argomento \"<strong>$1</strong>\" è stato rinominato in \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "L'argomento \"<strong>$1</strong>\" è stato rinominato in \"<strong>$2</strong>\" sulla <strong>{{GENDER:$3|tua}} pagina di discussione</strong>.",
+ "notification-header-flow-summary-edited": "Il riassunto per \"<strong>$1</strong>\" è stato aggiornato.",
+ "notification-header-flow-summary-edited-first": "L'argomento \"<strong>$1</strong>\" è stato riassunto.",
+ "notification-bundle-header-flow-summary-edited": "Il riassunto per \"<strong>$1</strong>\" è stato aggiornato più volte.",
+ "notification-header-flow-summary-edited-user-talk": "Il riassunto per \"<strong>$1</strong>\" è stato aggiornato sulla <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "L'argomento \"<strong>$1</strong>\" è stato riassunto sulla <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Il riassunto per \"<strong>$1</strong>\" è stato aggiornato più volte sulla <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|ha aggiornato}} il riassunto su $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|ha aggiornato}} il riassunto su $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 e {{PLURAL:$3|un altro utente|altri $3 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno aggiornato}} il riassunto su $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|ti}} ha {{GENDER:$4|menzionato|menzionata|menzionato/a}} in \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|ti}} ha {{GENDER:$4|menzionato|menzionata|menzionato/a}} nella descrizione di <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|ti}} ha {{GENDER:$4|menzionato|menzionata|menzionato/a}} in \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Nuovo sistema di discussione attivato per la <strong>{{GENDER:$2|tua}} pagina di discussione utente</strong>.",
+ "notification-header-flow-description-edited": "La descrizione di <strong>$1</strong> è stata modificata.",
+ "notification-header-flow-description-edited-user-talk": "La descrizione è stata modificata nella <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-bundle-header-flow-description-edited": "La descrizione di <strong>$1</strong> è stata modificata più volte.",
+ "notification-bundle-header-flow-description-edited-user-talk": "La descrizione è stata modificata più volte nella <strong>{{GENDER:$2|tua}} pagina di discussione</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Vedi}} pagina",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|ha modificato}} la descrizione su $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|ha modificato}} la descrizione su $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 e {{PLURAL:$3|un altro utente|altri $3 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno modificato}} la descrizione su $2",
+ "notification-header-flow-topic-resolved": "L'argomento \"<strong>$1</strong>\" è stato risolto.",
+ "notification-header-flow-topic-reopened": "L'argomento \"<strong>$1</strong>\" è stato riaperto.",
+ "notification-header-flow-topic-resolved-user-talk": "L'argomento \"<strong>$1</strong>\" è stato risolto sulla <strong>tua pagina di discussione</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "L'argomento \"<strong>$1</strong>\" è stato riaperto sulla <strong>tua pagina di discussione</strong>.",
+ "notification-email-subject-flow-topic-resolved": "L'argomento \"<strong>$2</strong>\" è stato risolto.",
+ "notification-email-batch-body-flow-topic-resolved": "L'argomento \"<strong>$2</strong>\" è stato risolto.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 ha {{GENDER:$1|creato}} un nuovo argomento su <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Un nuovo argomento|$1 nuovi argomenti|100=Più di 99 nuovi argomenti}} su <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 ha {{GENDER:$1|cambiato}} il titolo di <span class=\"plainlinks\">[$2 $3]</span> in \"$4\" su [[$5|$6]]",
"flow-notification-mention": "$1 {{GENDER:$5|ti}} {{GENDER:$1|ha menzionato}} nel suo <span class=\"plainlinks\">[$2 messaggio]</span> in \"$3\" su \"$4\".",
"flow-notification-link-text-view-post": "Vedi messaggio",
"flow-notification-link-text-view-topic": "Vedi argomento",
+ "flow-notification-link-text-view-topics": "Vedi argomenti",
"flow-notification-reply-email-subject": "$2 su $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|ha risposto}} a \"$2\" su $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$5|un altro|altri $4}} {{GENDER:$1|hanno risposto}} a \"$2\" su $3",
- "flow-notification-mention-email-subject": "$1 {{GENDER:$3|ti}} {{GENDER:$1|ha menzionato}} su $2",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|ti}} {{GENDER:$1|ha menzionato}} nel suo messaggio in \"$2\" su $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$4|un altro utente|altri $4 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno risposto}} a \"$2\" su $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|ti}} ha {{GENDER:$3|menzionato|menzionata|menzionato/a}} su $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|ti}} ha {{GENDER:$4|menzionato|menzionata|menzionato/a}} nel suo messaggio in \"$2\" su $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|ha modificato}} un messaggio",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|ha modificato}} un messaggio in \"$2\" su $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$5|un altro|altri $4}} utenti {{GENDER:$1|hanno modificato}} un messaggio in \"$2\" su $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$4|un altro utente|altri $4 utenti|100=più di 99 altri utenti}} {{GENDER:$1|hanno modificato}} un messaggio in \"$2\" su $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|ha rinominato}} il tuo argomento",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|ha rinominato}} l'argomento \"$2\" in \"$3\" su $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|ha creato}} un nuovo argomento su $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|ha creato}} un nuovo argomento \"$2\" su $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nuovo argomento|$1 nuovi argomenti|250=250+ nuovi argomenti}} su $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Avvisami quando vengono eseguite azioni connesse a me su Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Un nuovo argomento|$1 nuovi argomenti|100=Più di 99 nuovi argomenti}} su $2",
+ "echo-category-title-flow-discussion": "Discussioni strutturate",
+ "echo-pref-tooltip-flow-discussion": "Avvisami su attività in argomenti o pagine che sto seguendo.",
"flow-link-post": "messaggio",
"flow-link-topic": "argomento",
"flow-link-history": "cronologia",
"flow-link-post-revision": "versione messaggio",
"flow-link-topic-revision": "versione argomento",
"flow-link-header-revision": "Versione descrizione",
+ "flow-link-summary-revision": "versione riassunto",
"flow-moderation-title-suppress-post": "Sopprimere il messaggio?",
"flow-moderation-title-delete-post": "Cancellare il messaggio?",
"flow-moderation-title-hide-post": "Nascondere il messaggio?",
@@ -275,18 +368,18 @@
"flow-moderation-confirm-unsuppress-topic": "Annulla soppressione",
"flow-moderation-confirm-undelete-topic": "Ripristina",
"flow-moderation-confirm-unhide-topic": "Rendi visibile",
- "flow-moderation-confirmation-suppress-post": "Il messaggio è stato soppresso con successo.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
- "flow-moderation-confirmation-delete-post": "Il messaggio è stato cancellato con successo.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
- "flow-moderation-confirmation-hide-post": "Il messaggio è stato nascosto con successo.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
- "flow-moderation-confirmation-unsuppress-post": "Hai annullato la soppressione con successo per il messaggio precedente.",
- "flow-moderation-confirmation-undelete-post": "Hai ripristinato con successo il messaggio precedente.",
- "flow-moderation-confirmation-unhide-post": "Hai reso visibile con successo il messaggio precedente.",
+ "flow-moderation-confirmation-suppress-post": "Il messaggio è stato soppresso.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
+ "flow-moderation-confirmation-delete-post": "Il messaggio è stato cancellato.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
+ "flow-moderation-confirmation-hide-post": "Il messaggio è stato nascosto.\n{{GENDER:$2|Scrivi}} a $1 riguardo a questo messaggio.",
+ "flow-moderation-confirmation-unsuppress-post": "Hai annullato la soppressione per il messaggio precedente.",
+ "flow-moderation-confirmation-undelete-post": "Hai ripristinato il messaggio precedente.",
+ "flow-moderation-confirmation-unhide-post": "Hai reso visibile il messaggio precedente.",
"flow-moderation-confirmation-suppress-topic": "Questo argomento è stato soppresso.",
"flow-moderation-confirmation-delete-topic": "Questo argomento è stato cancellato.",
"flow-moderation-confirmation-hide-topic": "Questo argomento è stato nascosto.",
- "flow-moderation-confirmation-unsuppress-topic": "Hai annullato la soppressione con successo per questo argomento.",
- "flow-moderation-confirmation-undelete-topic": "Hai ripristinato con successo questo argomento.",
- "flow-moderation-confirmation-unhide-topic": "Hai reso visibile con successo questo argomento.",
+ "flow-moderation-confirmation-unsuppress-topic": "Hai annullato la soppressione per questo argomento.",
+ "flow-moderation-confirmation-undelete-topic": "Hai ripristinato questo argomento.",
+ "flow-moderation-confirmation-unhide-topic": "Hai reso visibile questo argomento.",
"flow-moderation-title-suppress-topic": "Sopprimere l'argomento?",
"flow-moderation-title-delete-topic": "Cancellare l'argomento?",
"flow-moderation-title-hide-topic": "Nascondere l'argomento?",
@@ -305,17 +398,19 @@
"flow-revision-permalink-warning-post-first": "Questo è un collegamento permanente alla prima versione di questo messaggio.\nPuoi vedere le versioni successive nella [$4 cronologia della pagina].",
"flow-revision-permalink-warning-postsummary": "Questo è un collegamento permanente ad una singola versione del riassunto di questo messaggio.\nQuesta versione è del $1.\nPuoi vedere le [$5 differenze dalla versione precedente] o le altre versioni nella [$4 cronologia della pagina].",
"flow-revision-permalink-warning-postsummary-first": "Questo è un collegamento permanente alla prima versione del riassunto di questo messaggio.\nPuoi vedere le versioni successive nella [$4 cronologia della pagina].",
- "flow-revision-permalink-warning-header": "Questo è un collegamento permanente ad una singola versione della descrizione.\nQuesta versione è del $1. Puoi vedere le [$3 differenze dalla versione precedente] o le altre versioni nella [$2 cronologia della pagina].",
+ "flow-revision-permalink-warning-header": "Questo è un collegamento permanente ad una singola versione della descrizione.\nQuesta versione è del $1. Puoi vedere le [$3 differenze dalla versione precedente] o le altre versioni nella [$2 cronologia della bacheca].",
"flow-revision-permalink-warning-header-first": "Questo è un collegamento permanente alla prima versione della descrizione.\nPuoi vedere le versioni successive nella [$2 cronologia della pagina].",
"flow-compare-revisions-revision-header": "Versione di {{GENDER:$2|$2}} del $1",
"flow-compare-revisions-header-post": "Questa pagina mostra le {{GENDER:$3|modifiche}} tra due versioni del messaggio di $3, nell'argomento \"[$5 $2]\" su [$4 $1].\nPuoi vedere le altre versioni nella [$6 cronologia della pagina].",
- "flow-compare-revisions-header-postsummary": "Questa pagina mostra le modifiche tra due versioni del riassunto del messaggio, nell'argomento \"[$4 $2]\" su [$3 $1].\nPuoi vedere le altre versioni nella [$5 cronologia della pagina].",
+ "flow-compare-revisions-header-postsummary": "Questa pagina mostra le modifiche tra due versioni del riassunto del'argomento \"[$4 $2]\" su [$3 $1].\nPuoi vedere le altre versioni nella [$5 cronologia della pagina].",
"flow-compare-revisions-header-header": "Questa pagina mostra le {{GENDER:$2|modifiche}} tra due versioni della descrizione su [$3 $1].\nPuoi vedere le altre versioni nella [$4 cronologia della pagina].",
- "right-flow-hide": "Nasconde messaggi e argomenti Flow",
- "right-flow-lock": "Segnala argomenti Flow come chiusi",
- "right-flow-delete": "Cancella messaggi e argomenti Flow",
- "right-flow-edit-post": "Modifica messaggi di altri utenti Flow",
- "right-flow-suppress": "Sopprime versioni Flow",
+ "action-flow-create-board": "creare bacheche discussioni strutturate in qualsiasi posizione",
+ "right-flow-create-board": "Crea bacheche di discussioni strutturate in qualsiasi posizione",
+ "right-flow-hide": "Nasconde messaggi e argomenti in discussioni strutturate",
+ "right-flow-lock": "Contrassegna argomenti di discussioni strutturate come risolti",
+ "right-flow-delete": "Cancella messaggi e argomenti in discussioni strutturate",
+ "right-flow-edit-post": "Modifica messaggi di discussioni strutturate di altri utenti",
+ "right-flow-suppress": "Sopprime versioni di discussioni strutturate",
"flow-terms-of-use-new-topic": "Cliccando su \"{{int:flow-newtopic-save}}\", accetti le condizioni d'uso per questo wiki.",
"flow-terms-of-use-reply": "Cliccando su \"{{int:flow-reply-link}}\", accetti le condizioni d'uso per questo wiki.",
"flow-terms-of-use-edit": "Salvando le modifiche, accetti le condizioni d'uso per questo wiki.",
@@ -329,6 +424,7 @@
"flow-newest-topics": "Argomenti più recenti",
"flow-recent-topics": "Ultimi argomenti attivi",
"flow-sorting-tooltip-newest": "{{GENDER:|Stai}} attualmente leggendo gli argomenti più recenti. Fai clic per ulteriori opzioni di ordinamento.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Stai}} attualmente leggendo gli argomenti più attivi ultimamente. Fai clic per ulteriori opzioni di ordinamento.",
"flow-toggle-small-topics": "Passa alla vista ridotta",
"flow-toggle-topics": "Passa alla vista degli argomenti",
"flow-toggle-topics-posts": "Passa alla vista degli argomenti e dei messaggi",
@@ -337,47 +433,107 @@
"flow-terms-of-use-unlock-topic": "Cliccando su \"{{int:flow-topic-action-unlock-topic}}\", accetti le condizioni d'uso per questo wiki.",
"flow-whatlinkshere-post": "da un [$1 messaggio]",
"flow-whatlinkshere-header": "dalla [$1 descrizione]",
- "flow": "Flusso",
- "flow-special-desc": "Questa pagina speciale reindirizza a un messaggio o a un flusso di lavoro Flow dato un UUID.",
+ "flow-whatlinkshere-post-summary": "dal [$1 riassunto]",
+ "structureddiscussions": "Discussioni strutturate",
+ "flow-special-desc": "Questa pagina speciale reindirizza a un messaggio o a un flusso di lavoro di discussioni strutturate dato un UUID.",
"flow-special-type": "Tipo",
"flow-special-type-post": "Messaggio",
"flow-special-type-workflow": "Flusso di lavoro",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Impossibile trovare il contenuto corrispondente il tipo e l'UUID.",
- "flow-special-enableflow-legend": "Abilita Flow in una nuova pagina",
- "flow-special-enableflow-page": "Pagina nella quale abilitare Flow",
+ "flow-special-enableflow-legend": "Attiva le discussioni strutturate in una nuova pagina",
+ "flow-special-enableflow-page": "Pagina nella quale abilitare le discussioni strutturate",
+ "flow-special-enableflow-header": "Descrizione iniziale di una bacheca di discussioni strutturate (wikitesto)",
+ "flow-special-enableflow-board-already-exists": "Esiste già una bacheca discussioni strutturate in [[$1]].",
"flow-special-enableflow-invalid-title": "È stato specificato un titolo di pagina non valido.",
- "flow-spam-confirmedit-form": "Conferma che sei una persona risolvendo il captcha qui sotto: $1",
+ "flow-special-enableflow-board-creation-not-allowed": "Non hai i permessi necessari per creare una bacheca di discussioni strutturate su [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Esiste già una pagina LiquidThreads in [[:$1]].",
+ "flow-special-enableflow-confirmation": "Hai creato una bacheca di discussioni strutturate su [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Archivio %d\n%s/Archivio%d\n%s/archivio %d\n%s/archivio%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Archivio discussioni strutturate %d\n%s/ArchivioDiscussioniStrutturate%d\n%s/ArchivioStructuredDiscussions%d",
+ "flow-spam-confirmedit-form": "Conferma che sei una persona risolvendo il CAPTCHA qui sotto: $1",
+ "flow-spam-confirmedit-using-failure": "Si è verificato un errore tecnico con il CAPTCHA. Se non è possibile inviare la modifica, copia il testo, ricarica e riprova.",
"flow-embedding-unsupported": "Gli argomenti non possono essere incorporati, ancora.",
"mw-ui-unsubmitted-confirm": "Ci sono modifiche non salvate su questa pagina. Sei sicuro di vole uscire e perderle?",
- "apihelp-flow+close-open-topic-param-reason": "Motivo per bloccare o sbloccare l'argomento.",
- "apihelp-flow+edit-header-param-content": "Contenuto per la descrizione.",
- "apihelp-flow+edit-header-param-format": "Formato della descrizione (wikitext|html)",
- "apihelp-flow+edit-title-param-content": "Contenuto per il titolo.",
- "apihelp-flow+edit-title-example-1": "Modifica il titolo di [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-param-reason": "Motivo per bloccare o sbloccare l'argomento.",
- "apihelp-flow+lock-topic-example-1": "Blocca [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-example-1": "Elimina l'argomento [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+undo-edit-header-description": "Recupera le informazioni necessarie per annullare le modifiche della descrizione.",
- "apihelp-flow+undo-edit-post-description": "Recuperare le informazioni necessarie per annullare la post-modifica.",
+ "flow-post-undo-hide": "rendo visibile",
+ "flow-post-undo-delete": "ripristino",
+ "flow-post-undo-suppress": "annullo soppressione",
+ "flow-topic-undo-hide": "rendo visibile",
+ "flow-topic-undo-delete": "ripristino",
+ "flow-topic-undo-suppress": "annullo soppressione",
+ "flow-importer-lqt-moved-thread-template": "LQT thread spostato e convertito in discussioni strutturate",
+ "flow-importer-lqt-moved-thread-template-content": "Questo messaggio di {{{author}}} è stato spostato il {{{date}}}. Puoi trovarlo in [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "Pagina LQT convertita a discussioni strutturate",
+ "flow-importer-lqt-converted-template-content": "La cronologia della precedente pagina è stata archiviata per scopi di backup in <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> il {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-lqt-converted-archive-template": "Archivio per pagine LQT convertite",
+ "flow-importer-lqt-converted-archive-template-content": "Questa pagina è un archivio LiquidThreads. <strong>Non modificare il contenuto di questa pagina</strong>. Scrivi eventuali ulteriori commenti nella [[{{{from}}}|pagina di discussione attuale]].",
+ "flow-importer-wt-converted-template": "Pagina di discussione con wikitesto convertita in discussioni strutturate",
+ "flow-importer-wt-converted-template-content": "Le discussioni precedenti sono state archiviate in <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> il {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Archivio per pagine di discussione con wikitesto convertite",
+ "flow-importer-wt-converted-archive-template-content": "Questa pagina è un archivio. <strong>Non modificare il contenuto di questa pagina</strong>. Scrivi eventuali ulteriori commenti nella [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|pagina di discussione attuale]].",
+ "flow-importer-lqt-suppressed-user-template": "Messaggio LQT importato con utente soppresso",
+ "flow-importer-lqt-suppressed-user-template-content": "Questa versione è stata importata da LiquidThreads con un utente soppresso. È stata riassegnata all'utente attuale.",
+ "flow-importer-lqt-different-author-signature-template": "Messaggio LQT importato con firma utente diversa",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Questo messaggio è stato pubblicato da [[User:{{{authorUser}}}|{{{authorUser}}}]], ma firmato come [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Modificato",
"flow-edited-by": "Modificato da $1",
+ "flow-edited-by-header": "Descrizione della bacheca modificata da $1",
+ "flow-edited-by-topic-title": "Titolo dell'argomento modificato da $1",
+ "flow-lqt-redirect-reason": "Reindirizzo il messaggio LiquidThreads al suo convertito su discussioni strutturate",
+ "flow-talk-conversion-move-reason": "Converto discussioni wikitesto a discussioni strutturate da $1",
+ "flow-talk-conversion-archive-edit-reason": "Converto discussioni wikitesto a discussioni strutturate",
"flow-previous-diff": "← Differenza precedente",
"flow-next-diff": "Differenza successiva →",
"flow-undo": "annulla",
"flow-undo-latest-revision": "Ultima revisione",
"flow-undo-your-text": "Il tuo testo",
"flow-undo-edit-header": "Modificare la descrizione",
- "flow-undo-edit-topic-summary": "Modifica della sintesi dell'argomento",
- "flow-undo-edit-post": "Modificare un post",
+ "flow-undo-edit-topic-summary": "Modifica il riassunto dell'argomento",
+ "flow-undo-edit-post": "Modifica un messaggio",
"flow-undo-edit-content": "Questa modifica può essere annullata.\nControlla le differenze mostrate sotto fra le due versioni per verificare che il contenuto corrisponda a quanto desiderato, e quindi salvare le modifiche per completare la procedura di annullamento.",
"flow-undo-edit-failure": "Impossibile annullare la modifica a causa di un conflitto con modifiche intermedie.",
+ "group-flow-bot": "Bot discussioni strutturate",
+ "group-flow-bot-member": "Bot discussioni strutturate",
+ "grouppage-flow-bot": "Project:Bot discussioni strutturate",
+ "flow-ve-mention-context-item-label": "Menziona",
+ "flow-ve-mention-inspector-title": "Menziona",
+ "flow-ve-mention-inspector-remove-label": "Rimuovi",
"flow-ve-mention-placeholder": "Nome utente",
"flow-ve-mention-tool-title": "Menziona un utente",
+ "flow-ve-mention-template-title": "MenzioneFlow",
"flow-ve-mention-inspector-invalid-user": "Il nome utente \"$1\" non è registrato.",
- "flow-wikitext-editor-help": "Wikitext $1.",
- "flow-wikitext-editor-help-and-preview": "Wikitext $1 e si può fare $2 in qualsiasi momento.",
+ "flow-wikitext-editor-help": "$1 wikitesto.",
+ "flow-wikitext-editor-help-and-preview": "Il wikitesto $1 e puoi guardare l'$2 in qualsiasi momento.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|uso del markup]]",
"flow-wikitext-editor-help-preview-the-result": "anteprima del risultato",
- "flow-wikitext-switch-editor-tooltip": "Passa a VisualEditor",
- "flow-dialog-cancelconfirm-discard": "Ignorare modifiche"
+ "flow-wikitext-switch-editor-tooltip": "Passa all'editor visuale",
+ "flow-ve-switch-editor-tool-title": "Passa all'editor wikitesto",
+ "flow-mark-revision-patrolled-link-text": "Segna questa pagina come verificata",
+ "flow-mark-revision-patrolled-link-title": "Segna questa pagina come verificata",
+ "flow-mark-diff-patrolled-link-text": "Segna come verificata",
+ "flow-mark-diff-patrolled-link-title": "Segna come verificata",
+ "flow-talk-page-beta-feature-message": "Discussioni strutturate in discussioni utente",
+ "flow-talk-page-beta-feature-description": "Attiva un nuovo sistema di discussioni strutturato nella {{GENDER:|tua}} pagina di discussioni utente. Le discussioni strutturate semplificano le discussioni con un posto chiaro dove scrivere e rispondere, e consente notifiche per ogni conversazione. Questa funzionalità non si attiva automaticamente; gli utenti dovranno abilitarla separatamente.<br /><br />Le discussioni esistenti in wikitesto saranno spostate in un archivio. Disabilitando questa funzione sarà spostata la bacheca di discussioni strutturate in una sottopagina e ripristinata dall'archivio la pagina di discussione precedente. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Ulteriori informazioni sull'attivazione]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Vedi}} la pagina di discussione utente",
+ "flow-notification-enabled-on-talkpage-title": "Nuovo sistema di discussione abilitato per la {{GENDER:$1|tua}} pagina discussione utente<br /><small>Disponibile su [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nuovo sistema di discussione su $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Discussioni strutturate, il nuovo sistema di discussione wiki, è stato attivato nella {{GENDER:$1|tua}} pagina di discussione su {{SITENAME}}. Puoi trovare ulteriori informazioni, lasciare un commento o disattivare il nuovo sistema in qualsiasi momento dalla sezione sulle funzionalità sperimentali nelle {{GENDER:$1|tue}} preferenze.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Aggiungo template di archivio",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Rimuovo template di archivio",
+ "flow-dialog-cancelconfirm-title": "Sei {{GENDER:|sicuro|sicura}}?",
+ "flow-dialog-cancelconfirm-message": "Sei {{GENDER:|sicuro|sicura}} di voler annullare senza prima salvare?",
+ "flow-dialog-cancelconfirm-keep": "Continuare a modificare",
+ "flow-dialog-cancelconfirm-discard": "Ignora modifiche",
+ "flow-optin-archive-wikitext": "Sposto pagina wikitesto per fare spazio a una bacheca di discussione.",
+ "flow-optin-archive-flow-board": "Sposto bacheca di discussione per fare spazio a una pagina wikitesto.",
+ "flow-optin-restore-wikitext": "Ripristino pagina wikitesto archiviata.",
+ "flow-optin-restore-flow-board": "Ripristino bacheca di discussione archiviata.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Benvenuto|Benvenuta|Benvenuto/a}} nella tua nuova pagina di discussione utente",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|La tua}} pagina di discussione è il luogo dove altri utenti possono contattarti. Con discussioni strutturate, è più facile iniziare nuovi argomenti e tenere traccia delle conversazioni.",
+ "flow-guidedtour-optin-find-old-conversations": "Trova {{GENDER:$1|le tue}} vecchie conversazioni",
+ "flow-guidedtour-optin-find-old-conversations-description": "Le conversazioni precedenti, sono state spostate in una pagina di archivio.",
+ "flow-guidedtour-optin-feedback": "Dacci {{GENDER:$1|la tua}} opinione!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Puoi avere}} più informazioni, lasciare opinioni, o disattivare il nuovo sistema in ogni momento dalla sezione delle funzionalità sperimentali.",
+ "flow-action-not-page": "L'oggetto pagina è un'istanza della classe sbagliata",
+ "flow-action-wrong-title-content-model": "La pagina viene gestita da discussioni strutturate, ma la classe del titolo indica che il modello di contenuto è '$1'. Si tratta di un errore di configurazione o di stato incoerente. Ad esempio, questo può effettivamente essere una pagina non discussioni strutturate in un namespace discussioni strutturate, con <code>rev_content_model</code> non popolato."
}
diff --git a/Flow/i18n/ja.json b/Flow/i18n/ja.json
index 97731fe3..921e8c33 100644
--- a/Flow/i18n/ja.json
+++ b/Flow/i18n/ja.json
@@ -8,28 +8,46 @@
"SkyDaisy9",
"2nd-player",
"Otokoume",
- "Sujiniku"
+ "Sujiniku",
+ "Nnemo",
+ "Macofe",
+ "Omotecho",
+ "Mirinano"
]
},
- "flow-desc": "ワークフロー管理システム",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "いつもで[$2 話題]を閲覧できます。",
+ "flow-desc": "議論管理システム",
"flow-talk-taken-over-comment": "/* このページは a Flow discussion board に変換されています */",
"log-name-flow": "Flow活動記録",
"logentry-delete-flow-delete-post": "$1 が [[$6]]上の \"[[$3|$5]]\" の [$4 投稿]を {{GENDER:$2|削除}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 が [[$3]] の話題での投稿を{{GENDER:$2|削除しました}}",
"logentry-delete-flow-restore-post": "$1 が [[$6]]の\"[[$3|$5]]\" の[$4 投稿]を{{GENDER:$2|復元}}",
- "logentry-suppress-flow-suppress-post": "$1 が [[$6]]の\"[[$3|$5]]\" の[$4 投稿]を{{GENDER:$2|秘匿}}",
- "logentry-suppress-flow-restore-post": "$1 が [[$6]]の\"[[$3|$5]]\" の[$4 投稿]を{{GENDER:$2|削除}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 が [[$3]] の話題での投稿を{{GENDER:$2|復元しました}}",
+ "logentry-suppress-flow-suppress-post": "$1 が [[$6]] の「[[$3|$5]]」での[$4 投稿]を{{GENDER:$2|秘匿しました}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 が [[$3]] の話題での投稿を{{GENDER:$2|秘匿しました}}",
+ "logentry-suppress-flow-restore-post": "$1 が [[$6]] の「[[$3|$5]]」での[$4 投稿]を{{GENDER:$2|削除しました}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 が [[$3]] の話題での投稿を{{GENDER:$2|削除しました}}",
"logentry-delete-flow-delete-topic": "$1 が [[$6]]の話題\"[[$3|$5]]\" を{{GENDER:$2|削除}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 が [[$3]] の話題を{{GENDER:$2|削除しました}}",
"logentry-delete-flow-restore-topic": "$1 が [[$6]]の話題\"[[$3|$5]]\" を{{GENDER:$2|復元}}",
- "logentry-suppress-flow-suppress-topic": "$1 が [[$6]]の話題\"[[$3|$5]]\"を{{GENDER:$2|秘匿}}",
- "logentry-suppress-flow-restore-topic": "$1 が [[$6]] の話題\"[[$3|$5]]\"を{{GENDER:$2|削除}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 が [[$3]] の話題を{{GENDER:$2|復元しました}}",
+ "logentry-suppress-flow-suppress-topic": "$1 が [[$6]] の話題「[[$3|$5]]」を{{GENDER:$2|秘匿しました}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 が [[$3]] の話題を{{GENDER:$2|秘匿しました}}",
+ "logentry-suppress-flow-restore-topic": "$1 が [[$6]] の話題「[[$3|$5]]」を{{GENDER:$2|削除しました}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 が [[$3]] の話題を{{GENDER:$2|削除しました}}",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 が [[$3]] の話題に解決済みとして{{GENDER:$2|印をつけました}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 が [[$3]] の話題を{{GENDER:$2|再開しました}}",
"flow-board-header-browse-topics-link": "話題を参照",
+ "flow-board-header": "このボードについて",
"flow-topic-collapse-siderail": "全幅で読む",
"flow-topic-expand-siderail": "固定幅で読む",
"flow-edit-header-link": "説明を編集",
"flow-post-moderated-toggle-hide-show": "$2 が{{GENDER:$1|非表示にした}}コメントを表示",
"flow-post-moderated-toggle-delete-show": "$2 が{{GENDER:$1|削除した}}コメントを表示",
+ "flow-post-moderated-toggle-suppress-show": "$2 が{{GENDER:$1|秘匿した}}コメントを表示",
"flow-post-moderated-toggle-hide-hide": "$2 が{{GENDER:$1|非表示にした}}コメントを非表示",
"flow-post-moderated-toggle-delete-hide": "$2 が{{GENDER:$1|削除した}}コメントを非表示",
+ "flow-post-moderated-toggle-suppress-hide": "$2 が{{GENDER:$1|秘匿した}}コメントを非表示",
"flow-topic-moderated-reason-prefix": "理由:",
"flow-hide-post-content": "このコメントは $1 によって{{GENDER:$1|非表示にされました}}([$2 履歴])",
"flow-hide-title-content": "この話題は $1 によって{{GENDER:$1|非表示にされました}}",
@@ -48,19 +66,25 @@
"flow-edit-summary-placeholder": "この議論の結果を簡単に説明してください",
"flow-show-change": "差分を表示",
"flow-last-modified-by": "最終{{GENDER:$1|更新}}者: $1",
- "flow-stub-post-content": "''技術的な問題が発生したため、この投稿を取得できませんでした。''",
+ "flow-stub-post-content": "<em>技術的な問題が発生したため、この投稿を取得できませんでした。</em>",
"flow-newtopic-title-placeholder": "新しい話題",
"flow-newtopic-content-placeholder": "「$1」に新規メッセージを投稿",
"flow-newtopic-header": "新しい話題の追加",
"flow-newtopic-save": "話題を追加",
+ "flow-newtopic-save-anonymously": "話題を匿名で追加",
"flow-newtopic-start-placeholder": "新しい話題の作成",
"flow-reply-topic-placeholder": "「$2」に{{GENDER:$1|コメントする}}",
"flow-reply-topic-title-placeholder": "「$1」への返信",
"flow-reply-link": "{{GENDER:$1|返信}}",
+ "flow-reply-link-anonymously": "匿名で返信",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|感謝}}}}",
+ "flow-history-action-suppress-post": "秘匿",
"flow-history-action-delete-post": "削除",
"flow-history-action-hide-post": "非表示",
+ "flow-history-action-unsuppress-post": "秘匿を解除",
+ "flow-history-action-undelete-post": "復元",
"flow-history-action-unhide-post": "非表示解除",
+ "flow-history-action-restore-post": "復元",
"flow-history-action-lock-topic": "解決する",
"flow-history-action-unlock-topic": "再開",
"flow-post-edited": "$1 が $2 に{{GENDER:$1|編集した}}投稿",
@@ -71,10 +95,12 @@
"flow-post-action-hide-post": "非表示にする",
"flow-post-action-edit-post": "編集",
"flow-post-action-edit-post-submit": "変更を保存",
+ "flow-post-action-edit-post-submit-anonymously": "匿名で変更を保存",
"flow-post-action-unsuppress-post": "秘匿を解除",
"flow-post-action-undelete-post": "削除を解除",
"flow-post-action-unhide-post": "非表示を解除",
"flow-post-action-restore-post": "復元",
+ "flow-post-action-undo-moderation": "取り消す",
"flow-topic-action-view": "固定リンク",
"flow-topic-action-watchlist": "ウォッチリスト",
"flow-topic-action-edit-title": "題名を編集",
@@ -85,7 +111,7 @@
"flow-topic-action-unlock-topic": "話題を再開",
"flow-topic-action-summarize-topic": "要約",
"flow-topic-action-resummarize-topic": "話題の要約を編集",
- "flow-topic-action-update-topic-summary": "更新の概要",
+ "flow-topic-action-update-topic-summary": "要約を更新",
"flow-topic-action-suppress-topic": "話題を秘匿",
"flow-topic-action-unhide-topic": "話題の非表示を解除",
"flow-topic-action-undelete-topic": "話題の削除を解除",
@@ -94,25 +120,33 @@
"flow-topic-action-undo-moderation": "取り消す",
"flow-topic-notification-subscribe-title": "この話題を{{GENDER:$1|}}ウォッチリストに追加しました。",
"flow-topic-notification-subscribe-description": "この話題に関する全ての活動の通知が{{GENDER:$1|あなた}}に届きます。",
- "flow-board-notification-subscribe-title": "{{GENDER:$1|あなたは}}、この議論ボードに記名されています!",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|あなたは}}、この議論ボードに記名されています。",
"flow-board-notification-subscribe-description": "この掲示板で新しい話題が立ち上がった時には{{GENDER:$1|あなた}}に通知が届きます。",
+ "flow-topic-action-watchlist-add": "この話題を購読",
+ "flow-topic-action-watchlist-remove": "購読解除",
"flow-error-http": "サーバーとの通信中にエラーが発生しました。",
- "flow-error-other": "予期しないエラーが発生しました。",
- "flow-error-external": "エラーが発生しました。<br />受信したエラーメッセージ: $1",
- "flow-error-external-multi": "複数のエラーが発生しました。<br /> $1",
+ "flow-error-external": "エラーが発生しました。受信したエラーメッセージ: $1",
"flow-error-missing-content": "投稿の本文がありません。投稿を保存するには本文が必要です。",
"flow-error-missing-summary": "要約を提出する必要があります。",
"flow-error-missing-title": "話題の題名がありません。話題を保存するには題名が必要です。",
- "flow-error-parsoid-failure": "Parsoid でエラーが発生したため、本文を構文解析できませんでした。",
+ "flow-error-parsoid-failure": "Parsoid の変換サーバーへの接続にエラーが発生したため、本文を構文解析できませんでした。インターネット接続を確認してください。",
+ "flow-error-protected-unknown-reason": "不明",
"flow-error-missing-replyto": "「返信先」のパラメーターを指定していません。「返信」するには、このパラメーターが必要です。",
- "flow-error-invalid-replyto": "「返信先」のパラメーターが無効です。指定した投稿が見つかりませんでした。",
- "flow-error-delete-failure": "この項目を削除できませんでした。",
- "flow-error-hide-failure": "この項目を非表示にできませんでした。",
"flow-error-missing-postId": "「投稿 ID」のパラメーターを指定していません。投稿を操作するには、このパラメーターが必要です。",
"flow-error-invalid-postId": "「投稿 ID」のパラメーターが無効です。指定した投稿 ($1) が見つかりませんでした。",
- "flow-error-restore-failure": "この項目を復元できませんでした。",
"flow-error-invalid-moderation-state": "フローAPIにパラメータ ('moderationState') の無効な値が送信されました。",
"flow-error-not-allowed": "この操作を実行するのに十分な権限がありません。",
+ "flow-error-not-allowed-hide": "この話題は非表示にされています。",
+ "flow-error-not-allowed-reply-to-hide-topic": "この話題は非表示化されたため、返信できません。",
+ "flow-error-not-allowed-delete": "この話題は削除されました。",
+ "flow-error-not-allowed-reply-to-delete-topic": "この話題は削除されたため、返信できません。",
+ "flow-error-not-allowed-suppress": "この話題は削除されました。",
+ "flow-error-not-allowed-reply-to-suppress-topic": "この話題は削除されたため、返信できません。",
+ "flow-error-not-allowed-hide-extract": "この話題は非表示にされています。参考のため、話題の非表示記録を以下に表示します。",
+ "flow-error-not-allowed-delete-extract": "この話題は削除されています。参考のため、話題の削除記録を以下に表示します。",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "この話題は削除されたため、返信できません。参考のため、話題の削除記録を以下に表示します。",
+ "flow-error-not-allowed-suppress-extract": "この話題は削除されています。参考のため、話題の削除記録を以下に表示します。",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "この話題は秘匿されたため、返信できません。参考のため、話題の秘匿記録を以下に表示します。",
"flow-error-title-too-long": "話題の題名は $1 {{PLURAL:$1|バイト}}までに制限されています。",
"flow-error-no-existing-workflow": "このワークフローはまだ存在しません。",
"flow-error-not-a-post": "話題の題名は投稿としては保存できません。",
@@ -134,11 +168,19 @@
"flow-error-process-data": "要求されたデータを処理する際にエラーが発生しました。",
"flow-error-process-wikitext": "HTML/ウィキテキスト変換を処理する際にエラーが発生しました。",
"flow-error-no-index": "データ検索を実行するためのインデックスが見つかりませんでした。",
+ "flow-error-no-render": "指定された操作は認識されませんでした。",
+ "flow-error-no-commit": "指定された操作を保存できませんでした。",
"flow-error-content-too-long": "本文が長すぎます。本文の展開後のサイズが $1 {{PLURAL:$1|バイト}}までに制限されています。",
+ "flow-error-move-topic": "話題ページの移動は、現在サポートされていません。",
+ "flow-error-unknown-workflow-id": "指定した話題は存在しません。",
+ "flow-error-search": "一時的な問題により検索を実行できませんでした。後でやり直してください。",
"flow-edit-header-placeholder": "この議論掲示板について説明してください",
"flow-edit-header-submit": "説明を保存",
+ "flow-edit-header-submit-anonymously": "匿名で説明を保存",
"flow-edit-title-submit": "題名を変更",
+ "flow-edit-title-submit-anonymously": "匿名でタイトルを保存",
"flow-edit-post-submit": "変更を保存",
+ "flow-edit-post-submit-anonymously": "匿名で変更を提出",
"flow-rev-message-edit-post": "$1 が「$4」の[$3 コメント]を{{GENDER:$2|編集}}",
"flow-rev-message-edit-post-recentchanges-summary": "投稿を{{GENDER:$2|編集}}",
"flow-rev-message-reply": "$1 が「$4」に[$3 {{GENDER:$2|コメントを追加}}] (<em>$5</em>)",
@@ -176,27 +218,61 @@
"flow-comment-hidden": "コメントを非表示",
"flow-last-modified": "最終更新 $1",
"flow-workflow": "ワークフロー",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 が '''$4''' で{{GENDER:$1|返信しました}}。",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 と他 $5 {{PLURAL:$6|人}}が '''$3''' で{{GENDER:$1|返信しました}}。",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 が <strong>$4</strong> で{{GENDER:$1|返信しました}}。",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 と他{{PLURAL:$5|1人|$5人|100=99人以上}}が <strong>$3</strong> で{{GENDER:$1|返信しました}}。",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 が [[$3|$4]] での<span class=\"plainlinks\">[$5 投稿]</span>を{{GENDER:$1|編集しました}}。",
- "flow-notification-edit-bundle": "$1 と他 $5 {{PLURAL:$6|人}}が「$3」の「$2」での<span class=\"plainlinks\">[$4 投稿]</span>を{{GENDER:$1|編集しました}}。",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 が '''$3''' で 新しい話題を{{GENDER:$1|作成しました}}。",
+ "flow-notification-edit-bundle": "$1 と他{{PLURAL:$5|1人|$5人|100=99人以上}}が「$3」の話題「$2」での<span class=\"plainlinks\">[$4 投稿]</span>を{{GENDER:$1|編集しました}}。",
+ "notification-header-flow-new-topic-v2": "新しい話題が<strong>$3</strong>で作成されました: <bdi>「<strong>$4</strong>」</bdi>",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|1件の新しい話題|$1件の新しい話題|100=99件以上の新しい話題}}が <strong>$3</strong> に作成されています。",
+ "notification-header-flow-new-topic-user-talk": "新しい話題が<strong>あなたのトークページ</strong>で作成されました: 「<strong>$4</strong>」",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|1件の新しい話題|$1件の新しい話題|100=99件以上の新しい話題}}が<strong>あなたのトークページ</strong>に作成されています。",
+ "notification-header-flow-post-reply": "$1 が話題「<strong>$4</strong>」で{{GENDER:$2|返信しました}}。",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|1件の新しい返信|$1件の新しい返信|100=99件以上の新しい返信}}が話題「<strong>$3</strong>」にあります。",
+ "notification-header-flow-post-reply-user-talk": "$1 が<strong>あなたのトークページ</strong>の話題「<strong>$4</strong>」に返信を{{GENDER:$2|投稿しました}}。",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|1件の新しい返信|$1件の新しい返信|100=99件以上の新しい返信}}が<strong>あなたのトークページ</strong>の話題「<strong>$3</strong>」にあります。",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|あなた}}の話題「<strong>$1</strong>」での投稿が編集されました。",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|あなた}}の話題「<strong>$1</strong>」での投稿が複数回編集されました。",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|あなた}}のトークページ</strong>で話題「<strong>$1</strong>」での投稿が編集されました。",
+ "notification-bundle-header-flow-post-edited-user-talk": "「<strong>$1</strong>」の投稿が<strong>{{GENDER:$2|あなた}}のトークページ</strong>で複数回編集されました。",
+ "notification-header-flow-topic-renamed-v2": "話題「<strong>$1</strong>」の題名が「<strong>$2</strong>」に変更されました。",
+ "notification-header-flow-topic-renamed-user-talk": "<strong>{{GENDER:$3|あなた}}のトークページ</strong>の話題「<strong>$1</strong>」の題名が「<strong>$2</strong>」に変更されました。",
+ "notification-header-flow-summary-edited": "話題「<strong>$1</strong>」の要約が更新されました。",
+ "notification-header-flow-summary-edited-first": "話題「<strong>$1</strong>」の要約が作成されました。",
+ "notification-bundle-header-flow-summary-edited": "話題「<strong>$1</strong>」の要約が複数回更新されました。",
+ "notification-header-flow-summary-edited-user-talk": "<strong>{{GENDER:$2|あなた}}のトークページ</strong>で話題「<strong>$1</strong>」の要約が更新されました。",
+ "notification-header-flow-summary-edited-first-user-talk": "<strong>{{GENDER:$2|あなた}}のトークページ</strong>で話題「<strong>$1</strong>」の要約が作成されました。",
+ "notification-bundle-header-flow-summary-edited-user-talk": "<strong>{{GENDER:$2|あなた}}のトークページ</strong>で話題「<strong>$1</strong>」の要約が複数回更新されました。",
+ "notification-email-subject-flow-summary-edited": "$1 が $2 で話題の要約を{{GENDER:$1|更新しました}}。",
+ "notification-email-batch-body-flow-summary-edited": "$1 が $2 で話題の要約を{{GENDER:$1|更新しました}}。",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 と他{{PLURAL:$3|1人|$3人|100=99人以上}}が $2 で話題の要約を{{GENDER:$1|更新しました}}",
+ "notification-header-flow-mention-post": "$1 が話題「<strong>$5</strong>」で{{GENDER:$4|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-flow-mention-header": "$1 が <strong>$3</strong> の説明で{{GENDER:$4|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-flow-mention-post-summary": "$1 が話題「<strong>$5</strong>」で{{GENDER:$4|あなた}}に{{GENDER:$2|言及しました}}。",
+ "notification-header-flow-enabled-on-talkpage": "新しい議論システムが<strong>{{GENDER:$2|あなたの}}利用者トークページ</strong>で有効化されました。",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 と他{{PLURAL:$3|1人|$3人|100=99人以上}}が $2 の説明を{{GENDER:$1|編集しました}}",
+ "notification-header-flow-topic-resolved": "話題「<strong>$1</strong>」が解決されました。",
+ "notification-email-subject-flow-topic-resolved": "話題「<strong>$2</strong>」が解決されました。",
+ "notification-email-batch-body-flow-topic-resolved": "話題「<strong>$2</strong>」が解決されました。",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 が <strong>$3</strong> で 新しい話題を{{GENDER:$1|作成しました}}。",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|1件の新しい話題|$1件の新しい話題|100=99件以上の新しい話題}}が <strong><span class=\"plainlinks\">[$3 $2]</span></strong> にあります",
"flow-notification-rename": "$1 が [[$5|$6]] で <span class=\"plainlinks\">[$2 $3]</span> のページ名を「$4」に{{GENDER:$1|変更しました}}。",
- "flow-notification-mention": "$1 が「$4」の「$3」での{{GENDER:$1|自身の}}<span class=\"plainlinks\">[$2 投稿]</span>で{{GENDER:$5|あなた}}に{{GENDER:$1|言及しました}}。",
+ "flow-notification-mention": "$1 が「$4」の話題「$3」での{{GENDER:$1|自身の}}<span class=\"plainlinks\">[$2 投稿]</span>で{{GENDER:$5|あなた}}に{{GENDER:$1|言及しました}}。",
"flow-notification-link-text-view-post": "投稿を閲覧",
"flow-notification-link-text-view-topic": "話題を閲覧",
+ "flow-notification-link-text-view-topics": "話題を閲覧",
"flow-notification-reply-email-subject": "$3 上の $2",
- "flow-notification-reply-email-batch-body": "$1 が$3の「$2」に{{GENDER:$1|返信しました}}",
- "flow-notification-reply-email-batch-bundle-body": "$1 と他 $4 {{PLURAL:$5|人}}が$3の「$2」に{{PLURAL:$1|返信しました}}",
+ "flow-notification-reply-email-batch-body": "$1 が $3 の話題「$2」に{{GENDER:$1|返信しました}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 と他{{PLURAL:$4|1人|$4人|100=99人以上}}が $3 の話題「$2」に{{PLURAL:$1|返信しました}}",
"flow-notification-mention-email-subject": "$1 が$2で{{GENDER:$3|あなた}}に{{GENDER:$1|言及しました}}",
- "flow-notification-mention-email-batch-body": "$1 が$3の「$2」での{{GENDER:$1|自身の}}投稿で{{GENDER:$4|あなた}}に{{GENDER:$1|言及しました}}",
+ "flow-notification-mention-email-batch-body": "$1 が $3 の話題「$2」での{{GENDER:$1|自身の}}投稿で{{GENDER:$4|あなた}}に{{GENDER:$1|言及しました}}",
"flow-notification-edit-email-subject": "$1 が投稿を{{GENDER:$1|編集しました}}",
- "flow-notification-edit-email-batch-body": "$1 が$3の「$2」で投稿を{{GENDER:$1|編集しました}}",
- "flow-notification-edit-email-batch-bundle-body": "$1 と他 $4 {{PLURAL:$5|人}}が$3の「$2」での投稿を{{GENDER:$1|編集しました}}",
+ "flow-notification-edit-email-batch-body": "$1 が $3 の話題「$2」で投稿を{{GENDER:$1|編集しました}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 と他{{PLURAL:$4|1人|$4人|100=99人以上}}が $3 の話題「$2」での投稿を{{GENDER:$1|編集しました}}",
"flow-notification-rename-email-subject": "$1 があなたの話題の{{GENDER:$1|題名を変更しました}}",
"flow-notification-rename-email-batch-body": "$1 が $4 のあなたの話題「$2」の題名を「$3」に{{GENDER:$1|変更しました}}",
"flow-notification-newtopic-email-subject": "$1 が $2 に新しい話題を{{GENDER:$1|作成しました}}",
"flow-notification-newtopic-email-batch-body": "$1 が $3 で新しい話題「$2」を{{GENDER:$1|作成しました}}",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|1件の新しい話題|$1件の新しい話題|100=99件以上の新しい話題}}が $2 にあります",
"echo-category-title-flow-discussion": "Flow",
"echo-pref-tooltip-flow-discussion": "Flow で私に関連する操作がなされたときに通知する。",
"flow-link-post": "投稿",
@@ -245,12 +321,16 @@
"flow-topic-permalink-warning-user-board": "この話題は [$2 {{GENDER:$1|$1}} の掲示板]で開始されました",
"flow-revision-permalink-warning-post": "これはこの投稿の特定の版への固定リンクです。\nこの版は $1 時点のものです。\n[$5 以前の版との差分]や、[$4 投稿の履歴ページ]でその他の版を閲覧することもできます。",
"flow-revision-permalink-warning-post-first": "これはこの投稿の初版への固定リンクです。\n[$4 投稿の履歴ページ]で以降の版を閲覧できます。",
+ "flow-revision-permalink-warning-postsummary": "これはこの投稿の要約の特定の版への固定リンクです。この版は $1 時点のものです。\n[$5 以前の版との差分]や、[$4 投稿の履歴ページ]でその他の版を閲覧することもできます。",
+ "flow-revision-permalink-warning-postsummary-first": "これはこの投稿の要約の初版への固定リンクです。\n[$4 投稿の履歴ページ]で以降の版を閲覧できます。",
"flow-revision-permalink-warning-header": "これは説明の特定の版への固定リンクです。\nこの版は $1 時点のものです。[$3 以前の版との差分]や、[$2 掲示板の履歴ページ]でその他の版を閲覧することもできます。",
"flow-revision-permalink-warning-header-first": "これは説明の初版への固定リンクです。\n[$2 掲示板の履歴ページ]で以降の版を閲覧できます。",
"flow-compare-revisions-revision-header": "$1における {{GENDER:$2|$2}} による版",
"flow-compare-revisions-header-post": "このページでは、[$4 $1] の話題「[$5 $2]」での $3 の投稿の 2 つの版の{{GENDER:$3|差分}}を表示しています。\nこの投稿の[$6 履歴ページ]でその他の版を閲覧できます。",
"flow-compare-revisions-header-postsummary": "このページでは、[$3 $1] の投稿「[$4 $2]」の要約の 2 つの版の差分を表示しています。\nこの要約の[$5 履歴ページ]でその他の版を閲覧できます。",
"flow-compare-revisions-header-header": "このページでは、[$3 $1] の説明の 2 つの版の{{GENDER:$2|差分}}を表示しています。\nこの説明の[$4 履歴ページ]でその他の版を閲覧できます。",
+ "right-flow-hide": "Flow の話題や投稿を非表示にする",
+ "right-flow-lock": "Flow の話題に解決済として印を付ける",
"right-flow-delete": "Flow の話題や投稿を削除",
"right-flow-edit-post": "他の利用者の Flow の投稿を編集",
"right-flow-suppress": "Flow の版を秘匿",
@@ -260,98 +340,45 @@
"flow-anon-warning": "ログインしていません。IP アドレスではなく名前が帰属として表示されるようにするには、[$1 ログイン]または[$2 アカウント作成]をしてください。",
"flow-topic-html-title": "$1 - $2",
"flow-load-more": "続きを表示",
+ "flow-no-more-fwd": "これより古い話題はありません",
+ "flow-newest-topics": "最も新しい話題",
"flow-recent-topics": "最近活発な話題",
"flow-toggle-topics": "話題のみの表示に切り替える",
"flow-toggle-topics-posts": "話題と投稿の表示に切り替える",
"flow-terms-of-use-summarize": "「{{int:flow-topic-action-update-topic-summary}}」をクリックすると、このウィキの利用規約に同意したと見なされます。",
"flow-whatlinkshere-post": "[$1 投稿]から",
"flow-whatlinkshere-header": "[$1 説明]から",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-type": "種類",
"flow-special-type-post": "投稿",
"flow-special-type-workflow": "ワークフロー",
"flow-special-uuid": "UUID",
+ "flow-special-enableflow-page": "Flow を有効にするページ",
"flow-importer-lqt-moved-thread-template-content": "この投稿は{{{author}}}によって{{{date}}}上に移動されました。それを[[{{{title}}}]]で発見できます。",
"flow-importer-lqt-converted-template-content": "前のページの履歴はアーカイブされています。バックアップの目的のためのアーカイブであり、<span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}にあります。",
"flow-importer-wt-converted-template-content": "前の決定は{{#time: Y-m-d|{{{date}}} }}上の<span class='flow-link-to-archive'>[[{{{archive}}}]]</span>にてアーカイブされています。",
- "flow-importer-wt-converted-archive-template-content": "このページはアーカイブです。'''けっして、このページを編集しないでください。'''コメントを追加したい場合は、[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|current talk page]]にダイレクトしてください。",
- "flow-importer-lqt-different-author-signature-template-content": "''この投稿は [[User:{{{authorUser}}}|{{{authorUser}}}]]によって投稿されましたが、しかし[[User:{{{signatureUser}}}|{{{signatureUser}}}]]としてサインされました。 ''",
- "apihelp-flow-description": "Flow ページに対して操作を行います。",
- "apihelp-flow-param-submodule": "実行する Flow サブモジュールです。",
- "apihelp-flow-param-page": "操作を行うページです。",
- "apihelp-flow-example-1": "\"[[Talk:Sandbox]]\" の説明を編集",
- "apihelp-flow+close-open-topic-param-moderationState": "変更後の話題の状態であり、\"lock\" または \"unlock\" です。",
- "apihelp-flow+close-open-topic-param-reason": "話題をロックまたはロック解除する理由です。",
- "apihelp-flow+edit-header-description": "ボードの説明を編集します。",
- "apihelp-flow+edit-header-param-prev_revision": "現在の説明の版 ID であり、編集競合を確認するためのものです。",
- "apihelp-flow+edit-header-param-content": "説明の内容です。",
- "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]] の説明を編集",
- "apihelp-flow+edit-post-description": "投稿の本文を編集します。",
- "apihelp-flow+edit-post-param-postId": "投稿 ID です。",
- "apihelp-flow+edit-post-param-prev_revision": "現在の投稿の版 ID であり、編集競合を確認するためのものです。",
- "apihelp-flow+edit-post-param-content": "投稿の本文です。",
- "apihelp-flow+edit-post-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿を編集します。",
- "apihelp-flow+edit-title-description": "話題の題名を編集します。",
- "apihelp-flow+edit-title-param-prev_revision": "現在のタイトルの版 ID であり、編集競合を確認するためのものです。",
- "apihelp-flow+edit-title-param-content": "題名の内容です。",
- "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]] の題名を編集",
- "apihelp-flow+edit-topic-summary-description": "話題の要約の内容を編集します。",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "現在の話題の要約の版 ID がある場合は指定します。編集競合を確認するためのものです。",
- "apihelp-flow+edit-topic-summary-param-summary": "要約の内容です。",
- "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] の要約を編集",
- "apihelp-flow+lock-topic-description": "Flow の話題をロックまたはロック解除します。",
- "apihelp-flow+lock-topic-param-moderationState": "変更後の話題の状態であり、<kbd>lock</kbd> または <kbd>unlock</kbd> です。",
- "apihelp-flow+lock-topic-param-reason": "話題をロックまたはロック解除する理由です。Note, the on-wiki Flow client uses \"Marked as resolved\" here, and puts optional additional information in the summary.",
- "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] をロック",
- "apihelp-flow+moderate-post-example-1": "話題 [[Topic:S2tycnas4hcucw8w]] の投稿を削除",
- "apihelp-flow+moderate-topic-example-1": "話題 [[Topic:S2tycnas4hcucw8w]] を削除",
- "apihelp-flow+new-topic-description": "指定したワークフローに Flow の話題を新規作成します。",
- "apihelp-flow+new-topic-param-topic": "新しい話題のタイトルのテキストです。",
- "apihelp-flow+new-topic-param-content": "初めのリプライの話題の本文です。",
- "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]] に話題を新規作成",
- "apihelp-flow+reply-description": "投稿に返信します。",
- "apihelp-flow+reply-param-replyTo": "返信先の投稿の ID です。",
- "apihelp-flow+reply-param-content": "新しい投稿の本文です。",
- "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿に返信",
- "apihelp-flow+view-header-param-format": "返す本文の形式です。",
- "apihelp-flow+view-header-description": "掲示板の説明を閲覧します。",
- "apihelp-flow+view-header-param-revId": "最新版の代わりに、この版を読み込みます。",
- "apihelp-flow+view-header-example-1": "[[Talk:Sandbox]] の説明をウィキテキスト形式で取得",
- "apihelp-flow+view-post-description": "投稿を閲覧します。",
- "apihelp-flow+view-post-param-postId": "閲覧する投稿の ID です。",
- "apihelp-flow+view-post-param-format": "返す本文の形式です。",
- "apihelp-flow+view-post-example-1": "[[Topic:S2tycnas4hcucw8w]] の投稿の本文をウィキテキスト形式で取得",
- "apihelp-flow+view-topic-description": "話題を閲覧します。",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] を閲覧",
- "apihelp-flow+view-topic-summary-description": "話題の要約を閲覧します。",
- "apihelp-flow+view-topic-summary-param-format": "返す本文の形式です。",
- "apihelp-flow+view-topic-summary-param-revId": "最新版の代わりに、この版を読み込みます。",
- "apihelp-flow+view-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]] の要約をウィキテキスト形式で閲覧",
- "apihelp-flow+view-topiclist-description": "話題の一覧を閲覧します。",
- "apihelp-flow+view-topiclist-param-offset-dir": "話題の並び順指定です。",
- "apihelp-flow+view-topiclist-param-sortby": "話題の並べ替えのオプションです。either <kbd>updated</kbd> (ordered by topic update time), or <kbd>newest</kbd> (ordered by topic creation time).",
- "apihelp-flow+view-topiclist-param-savesortby": "設定すると、ユーザー好みに並べ替えのオプションを保存します。",
- "apihelp-flow+view-topiclist-param-offset-id": "話題の取得を開始するオフセット値 (UUID 形式) です; <kbd>最新の</kbd> オーダリングとだけで使われます。",
- "apihelp-flow+view-topiclist-param-offset": "話題の取得を開始するオフセット値(話題の更新のタイムスタンプ、 <code>TS_MW</code> 形式 (<code>YYYYMMDDHHMMSS</code>))です。; used only with <kbd>updated</kbd> ordering",
- "apihelp-flow+view-topiclist-param-limit": "取得する話題の件数です。",
- "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]] の話題を列挙",
- "apihelp-flow-parsoid-utils-description": "テキストをウィキテキスト形式と HTML 形式の間で相互変換します。",
- "apihelp-flow-parsoid-utils-param-from": "変換元の形式です。",
- "apihelp-flow-parsoid-utils-param-to": "変換先の形式です。",
- "apihelp-flow-parsoid-utils-param-content": "変換する内容です。",
- "apihelp-flow-parsoid-utils-param-title": "ページ名です。$1pageid とは同時に使用できません。",
- "apihelp-flow-parsoid-utils-param-pageid": "ページの ID です。$1title とは同時に使用できません。",
- "apihelp-flow-parsoid-utils-example-1": "ウィキテキスト <nowiki>'''lorem''' ''blah''</nowiki> を HTML 形式に変換",
- "apihelp-query+flowinfo-description": "ページの Flow の基礎的な情報を取得します。",
- "apihelp-query+flowinfo-example-1": "[[Talk:Sandbox]]、[[Main Page]]、[[Talk:Flow]] の Flow の情報を取得",
+ "flow-importer-wt-converted-archive-template-content": "このページはアーカイブです。<strong>決して、このページを編集しないでください</strong>。コメントを追加したい場合は、[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|トークページ]]で行ってください。",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>この投稿は [[User:{{{authorUser}}}|{{{authorUser}}}]] により投稿されましたが、[[User:{{{signatureUser}}}|{{{signatureUser}}}]] として署名されました。</em>",
+ "flow-edited": "編集済み",
"flow-edited-by": "$1 が編集しました",
"flow-previous-diff": "← 古い編集",
"flow-next-diff": "新しい編集 →",
"flow-undo": "取り消し",
+ "group-flow-bot": "Flowボット",
+ "group-flow-bot-member": "Flowボット",
+ "grouppage-flow-bot": "Project:Flowボット",
+ "flow-ve-mention-context-item-label": "メンション",
+ "flow-ve-mention-tool-title": "ある利用者にメンション",
+ "flow-wikitext-editor-help-and-preview": "ウィキテキストは$1、また、いつでも$2できます。",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|マークアップを使用]]",
+ "flow-wikitext-editor-help-preview-the-result": "結果をプレビュー",
+ "flow-wikitext-switch-editor-tooltip": "ビジュアルエディターに切り替え",
+ "flow-ve-switch-editor-tool-title": "ウィキテキストエディターに切り替え",
"flow-mark-revision-patrolled-link-text": "このページを巡回済みにする",
"flow-mark-diff-patrolled-link-text": "巡回済みにする",
- "flow-notification-link-text-enabled-on-talkpage": "利用者の会話ページを見る",
- "flow-notification-enabled-on-talkpage-title": "利用者の会話ページで新しい議論システムが有効になりました<br />\n<small>[[$2]]で利用可能です</small>",
+ "flow-talk-page-beta-feature-description": "あなたの利用者トークページで、新しくシステム化された議論システムを有効化します。フローによって、トークページの議論の管理が簡単化され、書くべき場所と返信すべき場所とが明瞭になり、また通知が会話レベルになるでしょう。既存のウィキテキスト形式の議論は、アーカイブに移動します。この機能は、けっして自動では有効化されません。利用者が区別して有効化する必要があります。一方、機能を無効化すれば、フローボードはサブページおよび非アーカイブの以前のトークページに移動します。",
+ "flow-notification-link-text-enabled-on-talkpage": "利用者の会話ページを{{GENDER:|見る}}",
+ "flow-notification-enabled-on-talkpage-title": "{{GENDER:$1|あなたの}}利用者の会話ページで新しい議論システムが有効になりました<br /><small>[[$2]]で利用可能です</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "$2 の議論システムが新しくなりました",
"flow-beta-feature-add-archive-template-edit-summary": "アーカイブテンプレートの追加",
"flow-beta-feature-remove-archive-template-edit-summary": "アーカイブ・テンプレートの除去",
@@ -359,6 +386,10 @@
"flow-dialog-cancelconfirm-message": "保存せずにキャンセルしてもよろしいですか?",
"flow-dialog-cancelconfirm-keep": "編集を続行する",
"flow-dialog-cancelconfirm-discard": "変更内容を破棄しました",
+ "flow-optin-archive-wikitext": "ウィキテキスト・ページを移動して議論ボードのための部屋を作る",
+ "flow-optin-archive-flow-board": "議論ボード・ページを移動し、ウィキテキスト・ページのための部屋をつくる",
+ "flow-optin-restore-wikitext": "アーカイブ化されたウィキテキスト・ページを復元",
+ "flow-optin-restore-flow-board": "アーカイブ化された議論ボードを復元",
"flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|あなた}}の過去の会話を探す",
"flow-guidedtour-optin-feedback": "{{GENDER:$1|あなた}}のフィードバックをください。"
}
diff --git a/Flow/i18n/jbo.json b/Flow/i18n/jbo.json
index 1486e4a5..a2b7cd45 100644
--- a/Flow/i18n/jbo.json
+++ b/Flow/i18n/jbo.json
@@ -1,16 +1,34 @@
{
"@metadata": {
"authors": [
- "Gleki"
+ "Gleki",
+ "Xbony2",
+ "Olwe519"
]
},
"log-name-flow": "flecu fasnu citri",
"flow-post-actions": "loi se zukte",
"flow-topic-actions": "loi se zukte",
"flow-newtopic-save": "jmina la'e se casnu",
- "flow-post-action-delete-post": "daspo",
+ "flow-post-action-delete-post": "vimcu",
"flow-post-action-hide-post": "cancygau",
- "flow-post-action-edit-post": "stika lo se mrilu",
+ "flow-post-action-edit-post": "stika",
+ "notification-header-flow-summary-edited": "pu ningau lo torveki pe la lu $1 li'u",
+ "notification-bundle-header-flow-summary-edited": "pu za'uroi ningau lo torveki pe la lu $1 li'u",
+ "notification-header-flow-summary-edited-user-talk": "pu ningau lo torveki pe la lu $1 li'u ne'i lo {{GENDER:$2|do}} tavla papri",
+ "notification-bundle-header-flow-summary-edited-user-talk": "pu za'uroi ningau lo torveki pe la lu $1 li'u ne'i lo {{GENDER:$2|do}} tavla papri",
+ "notification-email-subject-flow-summary-edited": "la lu $1 li'u {{GENDER:$1|ningau}} lo torveki pe la lu $2 li'u",
+ "notification-email-batch-body-flow-summary-edited": "la lu $1 li'u {{GENDER:$1|ningau}} lo torveki pe la lu $2 li'u",
+ "notification-email-batch-bundle-body-flow-summary-edited": "la lu $1 li'u .e $3 {{PLURAL:$4|drata}} {{GENDER:$1|cu ningau}} lo torveki pe la lu $2 li'u",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mlauca}} {{GENDER:$4|do}} ne'i la lu $5 li'u",
+ "notification-header-flow-description-edited": "pu cusku'i le ve skicu be fe la lu $1 li'u",
+ "notification-header-flow-description-edited-user-talk": "pu cusku'i le ve skicu be fe le {{GENDER:$2|do}} tavla papri",
+ "notification-bundle-header-flow-description-edited": "pu za'uroi cusku'i le ve skicu be fe la lu $1 li'u",
+ "notification-bundle-header-flow-description-edited-user-talk": "pu za'uroi cusku'i le ve skicu be fe le {{GENDER:$2|do}} tavla papri",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|catlu}} lo papri",
+ "notification-email-subject-flow-description-edited": "$1 pu cusku'i le ve skicu be fe la lu $2 li'u",
+ "notification-email-batch-body-flow-description-edited": "$1 pu cusku'i le ve skicu be fe la lu $2 li'u",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 .e $3 {{PLURAL:$4|loi pa drata}} {{GENDER:$1|pu cusku'i}} le ve skicu be fe la lu $2 li'u",
"echo-category-title-flow-discussion": "lo flecu",
"flow-link-topic": "lo se casnu",
"flow-link-history": "lo citri"
diff --git a/Flow/i18n/jv.json b/Flow/i18n/jv.json
new file mode 100644
index 00000000..f1ab3af1
--- /dev/null
+++ b/Flow/i18n/jv.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "NoiX180"
+ ]
+ },
+ "flow-post-action-edit-post-submit": "Simpen owahan"
+}
diff --git a/Flow/i18n/ka.json b/Flow/i18n/ka.json
index 468fcfa4..e5aa2405 100644
--- a/Flow/i18n/ka.json
+++ b/Flow/i18n/ka.json
@@ -3,29 +3,31 @@
"authors": [
"David1010",
"MIKHEIL",
- "Otogi"
+ "Otogi",
+ "BRUTE"
]
},
- "enableflow": "ნაკადის ჩართვა",
+ "enablestructureddiscussions": "ნაკადის ჩართვა",
"log-name-flow": "მოქმედების ჟურნალის ნაკადი",
"flow-user-moderated": "განელებული მომხმარებელი",
"flow-board-header-browse-topics-link": "მიმოხილვის თემები",
+ "flow-board-description-can-not-edit": "არარედაქტირებადი",
"flow-board-collapse-description": "აღწერის დამალვა",
"flow-board-expand-description": "აღწერის ჩვენება",
+ "flow-topic-collapse-siderail": "წაკითხვა სრული გაფართოებით",
"flow-edit-header-link": "აღწერის რედაქტირება",
"flow-topic-moderated-reason-prefix": "მიზეზი:",
"flow-post-actions": "ქმედებები",
"flow-topic-actions": "ქმედებები",
"flow-cancel": "გაუქმება",
+ "flow-skip-summary": "რეზიუმეს გამოტოვება",
"flow-show-change": "ცვლილებების ჩვენება",
"flow-newtopic-title-placeholder": "ახალი თემა",
"flow-newtopic-header": "ახალი თემის დამატება",
"flow-newtopic-save": "თემის ჩამატება",
"flow-newtopic-start-placeholder": "ახალი თემის სტარტი",
- "flow-reply-submit": "{{GENDER:$1|პასუხი}}",
"flow-reply-link": "{{GENDER:$1|პასუხი}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|მადლობა}}}}",
- "flow-lock-link": "{{GENDER:$1|დაკეტვა}}",
"flow-thank-link-title": "შეტყობინების ავტორისთვის საჯარო {{GENDER:$1|{{GENDER:$2|მადლობის}}}} გადახდა",
"flow-history-action-suppress-post": "აკრძალვა",
"flow-history-action-delete-post": "წაშლა",
@@ -34,8 +36,8 @@
"flow-history-action-undelete-post": "აღდგენა",
"flow-history-action-unhide-post": "ჩვენება",
"flow-history-action-restore-post": "აღდგენა",
- "flow-history-action-lock-topic": "დახურვა",
- "flow-history-action-unlock-topic": "გახსნა",
+ "flow-history-action-lock-topic": "გასწორება",
+ "flow-history-action-unlock-topic": "ხელახლა გახსნა",
"flow-post-action-view": "მუდმივი ბმული",
"flow-post-action-post-history": "ისტორია",
"flow-post-action-suppress-post": "აკრძალვა",
@@ -64,18 +66,13 @@
"flow-topic-action-unsuppress-topic": "აკრძალული თემა",
"flow-topic-action-restore-topic": "თემის აღდგენა",
"flow-topic-action-undo-moderation": "დაბრუნება",
+ "flow-error-not-allowed-hide": "თემა დაიმალა.",
"flow-error-invalid-topic-uuid-title": "ცუდი სათაური",
"flow-error-unknown-workflow-id-title": "უცნობი თემა",
"flow-error-unknown-workflow-id": "მოთხოვნილი თემა არ არსებობს.",
"flow-edit-header-submit": "აღწერის შენახვა",
- "flow-edit-header-submit-overwrite": "აღწერის გადაწერა",
- "flow-summarize-topic-submit": "შეჯამება",
- "flow-lock-topic-submit": "თემის დახურვა",
- "flow-unlock-topic-submit": "თემის გახსნა",
"flow-edit-title-submit": "სათაურის შეცვლა",
- "flow-edit-title-submit-overwrite": "სათაურის გადაწერა",
"flow-edit-post-submit": "ცვლილებების მიღება",
- "flow-edit-post-submit-overwrite": "ცვლილებების გადაწერა",
"flow-rc-topic-of-board": "$1 $2-ზე",
"flow-history-last4": "ბოლო 4 საათში",
"flow-history-day": "დღეს",
@@ -84,6 +81,8 @@
"flow-comment-hidden": "დაფარული კომენტარი",
"flow-notification-link-text-view-post": "შეტყობინების ხილვა",
"flow-notification-link-text-view-topic": "თემის ხილვა",
+ "echo-category-title-flow-discussion": "ნაკადი",
+ "echo-pref-tooltip-flow-discussion": "შემატყობინე, როდესაც ჩემთან დაკავშირებული მოქმედება ნაკადში მიმდინარეობს.",
"flow-link-post": "შეტყობინება",
"flow-link-topic": "თემა",
"flow-link-history": "ისტორია",
@@ -104,11 +103,9 @@
"flow-moderation-confirm-suppress-topic": "აკრძალვა",
"flow-moderation-confirm-delete-topic": "წაშლა",
"flow-moderation-confirm-hide-topic": "დამალვა",
- "flow-moderation-confirm-lock-topic": "დახურვა",
"flow-moderation-confirm-unsuppress-topic": "აკრძალვის გაუქმება",
"flow-moderation-confirm-undelete-topic": "წაშლის გაუქმება",
"flow-moderation-confirm-unhide-topic": "დამალვის გაუქმება",
- "flow-moderation-confirm-unlock-topic": "გახსნა",
"flow-moderation-title-suppress-topic": "აიკრძალოს თემა?",
"flow-moderation-title-delete-topic": "წაიშალოს თემა?",
"flow-moderation-title-hide-topic": "დაიმალოს თემა?",
@@ -133,27 +130,6 @@
"flow-topic-undo-delete": "წაშლის გაუქმება",
"flow-topic-undo-suppress": "აკრძალვის გაუქმება",
"flow-importer-lqt-converted-archive-template": "არქივი კონვერტირებული LQT გვერდისთვის",
- "apihelp-flow+edit-header-param-content": "აღწერის შინაარსი.",
- "apihelp-flow+edit-header-param-format": "აღწერის ფორმატი (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]]-ის აღწერის რედაქტირება",
- "apihelp-flow+edit-post-description": "შეტყობინების შინაარსის რედაქტირებები.",
- "apihelp-flow+edit-post-param-postId": "შეტყობინების ID.",
- "apihelp-flow+edit-post-param-content": "შეტყობინების შინაარსი.",
- "apihelp-flow+edit-post-param-format": "შეტყობინების შინაარსის ფორმატი (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "შეტყობინების რედაქტირება [[Topic:S2tycnas4hcucw8w]]-ში",
- "apihelp-flow+edit-title-description": "თემის სათაურის რედაქტირება.",
- "apihelp-flow+edit-title-param-content": "სათაურის შინაარსი.",
- "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის სათაურის რედაქტირება",
- "apihelp-flow+edit-topic-summary-description": "თემის რეზიუმეს შინაარსის რედაქტირება.",
- "apihelp-flow+edit-topic-summary-param-summary": "რეზიუმეს შინაარსი.",
- "apihelp-flow+edit-topic-summary-param-format": "რეზიუმეს ფორმატი (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის რეზიუმეს რედაქტირება",
- "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის დახურვა",
- "apihelp-flow+view-post-description": "შეტყობინების ხილვა.",
- "apihelp-flow+view-post-param-postId": "სანახავი შეტყობინების ID.",
- "apihelp-flow+view-topic-description": "თემის ხილვა.",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]-ის ხილვა",
- "apihelp-flow+view-topic-summary-description": "თემის რეზიუმეს ხილვა.",
"flow-edited": "რედაქტირებულია",
"flow-edited-by": "დაარედაქტირა $1-მა",
"flow-previous-diff": "← წინა ცვლილება",
@@ -169,7 +145,6 @@
"flow-ve-mention-inspector-remove-label": "წაშლა",
"flow-ve-mention-placeholder": "მომხმარებლის სახელი",
"flow-ve-mention-tool-title": "მომხმარებლის შეხსენება",
- "flow-ve-mention-template": "პინგი",
"flow-ve-mention-inspector-invalid-user": "მოხმარებელი „$1“ არ არის რეგისტრირებული.",
"flow-wikitext-editor-help": "ვიკიტექსტი $1.",
"flow-wikitext-editor-help-and-preview": "ვიკი-ტექსტი $1 და თქვენ შეგიძლიათ $2 ნებისმიერ დროს.",
diff --git a/Flow/i18n/kab.json b/Flow/i18n/kab.json
new file mode 100644
index 00000000..40cc5ca9
--- /dev/null
+++ b/Flow/i18n/kab.json
@@ -0,0 +1,46 @@
+{
+ "@metadata": {
+ "authors": [
+ "Trizek (WMF)",
+ "SalemB",
+ "Belkacem77"
+ ]
+ },
+ "enablestructureddiscussions": "Rmed Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Ḥbes}} ẓer armud amaynu ɣef \"$1\"",
+ "flow-desc": "Anagraw n useqerdec",
+ "flow-talk-taken-over-comment": "/* Asebtar agi yettwasselket ar wanɣal n umyannan Flow */",
+ "log-name-flow": "Aɣmis n wurmud n Flow",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|yeffer|teffer}} yiwen n [$4 yizen] \"[[$3|$5]] \" ɣef [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|yekkes|tekkes}} izen n usentel di [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|yeffer|teffer}} asentel \"[[$3|$5]]\"  ɣef [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|yekkes|tekkes}} izen ɣef [[$3]]",
+ "flow-post-moderated-toggle-suppress-show": "Sken awennit i {{GENDER:$1|yeffer|teffer}} $2",
+ "flow-post-moderated-toggle-suppress-hide": "Ffer awennit i {{GENDER:$1|yedreg}} $2",
+ "flow-suppress-post-content": "Awennit-agi {{GENDER:$1|yeffer-it|teffer-it}} $1 ([$2 amazray])",
+ "flow-suppress-title-content": "Asentel-agi {{GENDER:$1|yeffer-it|teffer-it}} $1",
+ "flow-suppress-header-content": "{{GENDER:$1|yeffer-it}} $2",
+ "flow-history-action-suppress-post": "Ffer",
+ "flow-post-action-suppress-post": "Ffer",
+ "flow-post-action-edit-post-submit": "Sekles ibeddilen",
+ "flow-topic-action-suppress-topic": "Ffer asentel",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Ur tezmired ara ad terreḍ acku asentel-agi yeffer. Aɣmis n tuffra i usentel-agi yettunefk-d ddaw-a d tamsisɣelt.",
+ "flow-edit-header-submit": "Sekles aglam",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|yeffer|teffer}} [$4 awennit] ɣef \" $6\" (<em>$5</em>)..",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|yeffer|teffer}}[$4 asentel] \"$6 \" (<em>$5</em>).",
+ "flow-moderation-title-suppress-post": "Ffer izen?",
+ "flow-moderation-placeholder-suppress-post": "{{GENDER:$3|ini-d}} acuɣer teffreḍ izen-agi",
+ "flow-moderation-confirm-suppress-post": "Ffer",
+ "flow-moderation-confirm-suppress-topic": "Ffer",
+ "flow-moderation-confirmation-suppress-post": "IZen-agi yeffer. \n{{GENDER:$2|Wali}} akken ad tsegziḍ i $1 acuɣer tuffra-agi.",
+ "flow-moderation-confirmation-suppress-topic": "Asentel yeffer.",
+ "flow-moderation-title-suppress-topic": "Ffer asentel?",
+ "flow-moderation-placeholder-suppress-topic": "{{GENDER:$3|ini-d}} acuɣer teffreḍ asentel-agi",
+ "right-flow-suppress": "Ffer ileqwman n yiznan n Flow",
+ "flow-conversion-archive-page-name-format": "%s/Aɣbar %d \n%s/Aɣbar%d \n%s/aɣbar %d \n%s/aɣbar%d",
+ "flow-post-undo-suppress": "sefsex tuffra",
+ "flow-topic-undo-suppress": "asefsex n tuffra",
+ "flow-importer-wt-converted-template": "Asebtar n umyannan s Wikitexte yetturren ɣer Flow",
+ "flow-importer-wt-converted-template-content": "Asqerdec yezrin yettuɣber di <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> ass n {{#time: Y-m-d|{{{date}}} }}",
+ "flow-importer-lqt-suppressed-user-template-content": "Aceggir-agi yettwakter si LiquidThreads s useqdac yeffren. Yettunefk tura i useqdac amiran."
+}
diff --git a/Flow/i18n/kk-cyrl.json b/Flow/i18n/kk-cyrl.json
index 97aa5fdb..e27837cf 100644
--- a/Flow/i18n/kk-cyrl.json
+++ b/Flow/i18n/kk-cyrl.json
@@ -1,28 +1,34 @@
{
"@metadata": {
"authors": [
- "Arystanbek"
+ "Arystanbek",
+ "Nnemo",
+ "Quiddity",
+ "Matiia"
]
},
- "enableflow": "Flow кеңейтілімін іске қосу",
+ "enablestructureddiscussions": "Flow кеңейтілімін іске қосу",
"flow-desc": "Лекті жұмыстайтын басқару жүйесі",
- "flow-talk-taken-over": "Бұл талқылау бетін [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal Flow] кеңейтілімін қолдануда.",
- "flow-talk-username": "Flow талқылау бет басқармасы",
+ "flow-talk-taken-over-comment": "/* Бұл бет Flow талқылау тақтасына ауыстырылған */",
"log-name-flow": "Flow белсенділік журналы",
"logentry-delete-flow-delete-post": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген [$4 хабарламаны] {{GENDER:$2|жойды}}",
"logentry-delete-flow-restore-post": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген [$4 хабарламаны] {{GENDER:$2|қалпына келтірді}}",
"logentry-suppress-flow-suppress-post": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген [$4 хабарламаны] {{GENDER:$2|жасырды}}",
"logentry-suppress-flow-restore-post": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген [$4 хабарламаны] {{GENDER:$2|жойды}}",
- "logentry-delete-flow-delete-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген тақырыпты {{GENDER:$2|жойды}}",
- "logentry-delete-flow-restore-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген тақырыпты {{GENDER:$2|қалпына келтірді}}",
- "logentry-suppress-flow-suppress-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген тақырыпты {{GENDER:$2|жасырды}}",
- "logentry-suppress-flow-restore-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» деген тақырыпты {{GENDER:$2|жойды}}",
+ "logentry-delete-flow-delete-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» тақырыбын {{GENDER:$2|жойды}}",
+ "logentry-delete-flow-restore-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» тақырыбын {{GENDER:$2|қалпына келтірді}}",
+ "logentry-suppress-flow-suppress-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» тақырыбын {{GENDER:$2|жасырды}}",
+ "logentry-suppress-flow-restore-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» тақырыбын {{GENDER:$2|жойды}}",
+ "logentry-lock-flow-lock-topic": "$1 [[$6]] талқылау тақтасындағы \"[[$3|$5]]\" тақырыбын шешілді деп {{GENDER:$2|белгіледі}}",
+ "logentry-lock-flow-restore-topic": "$1 [[$6]] бетіндегі «[[$3|$5]]» тақырыбын {{GENDER:$2|қайта ашты}}",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] деген [[$3]] дегенге LiquidThreads-тен Flow-ға импортталды",
"flow-user-moderated": "Қадағалайтын қатысушы",
"flow-board-header-browse-topics-link": "Тақырыптарды шолу",
- "flow-board-header": "Бұл талқылау туралы",
+ "flow-board-header": "Бұл тақта туралы",
"flow-board-collapse-description": "Сипаттамасын жасыру",
"flow-board-expand-description": "Сипаттамасын көрсету",
+ "flow-topic-collapse-siderail": "Толық енде оқу",
+ "flow-topic-expand-siderail": "Тұрақты енде оқу",
"flow-edit-header-link": "Сипаттамасын өңдеу",
"flow-post-moderated-toggle-hide-show": "$2 {{GENDER:$1|жасырған}} пікірді көрсету",
"flow-post-moderated-toggle-delete-show": "$2 {{GENDER:$1|жойған}} пікірді көрсету",
@@ -44,21 +50,27 @@
"flow-post-actions": "Әрекеттер",
"flow-topic-actions": "Әрекеттер",
"flow-cancel": "Қажет емес",
+ "flow-skip-summary": "Түйіндемесін елемеу",
+ "flow-edit-summary-placeholder": "Осы талқылау нәтижесін қысқаша сипаттаңыз",
+ "flow-summary-authored": "$1 түйіндемесі",
+ "flow-summary-edited": "Түйіндемесі $1 арқылы соңғы рет {{GENDER:$1|өңделді}}",
"flow-show-change": "Өзгерістерді көрсету",
"flow-last-modified-by": "$1 соңғы рет {{GENDER:$1|өзгертті}}",
- "flow-stub-post-content": "«Техникалық қателерге байланысты, бұл хабарлама қабылданбады.»",
+ "flow-stub-post-content": "<em>Техникалық қателерге байланысты, бұл жазба қабылданбады.</em>",
"flow-newtopic-title-placeholder": "Жаңа тақырып",
- "flow-newtopic-content-placeholder": "«$1» деген бетке жаңа хабарлама жазу",
+ "flow-newtopic-content-placeholder": "«$1» бетіне жаңа хабарлама жазу",
"flow-newtopic-header": "Жаңа тақырып қосу",
"flow-newtopic-save": "Тақырып қосу",
+ "flow-newtopic-save-anonymously": "Анонимді түрде тақырып қосу",
"flow-newtopic-start-placeholder": "Жаңа тақырып бастау",
"flow-newtopic-first-heading": "$1 бетінде жаңа тақырып бастау",
"flow-summarize-topic-placeholder": "Бұл талқылауға түйіндемесін жазыңыз",
"flow-reply-topic-placeholder": "«$2» бетіндегі {{GENDER:$1|пікір}}",
- "flow-reply-topic-title-placeholder": " «$1» дегенге жауап беру",
+ "flow-reply-topic-title-placeholder": " «$1» тақырыбына жауап беру",
"flow-reply-link": "{{GENDER:$1|Жауап беру}}",
- "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Рахмет айту}}}}",
- "flow-thank-link-title": "Ашық түрде хабарлама жазушыға {{GENDER:$1|{{GENDER:$2|рахмет айту}}}}",
+ "flow-reply-link-anonymously": "Анонимді түрде жауап беру",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Алғыс білдіру}}}}",
+ "flow-thank-link-title": "Ашық түрде хабарлама жазушыға {{GENDER:$1|{{GENDER:$2|алғыс білдіру}}}}",
"flow-history-action-suppress-post": "жасыру",
"flow-history-action-delete-post": "жою",
"flow-history-action-hide-post": "жасыру",
@@ -66,8 +78,8 @@
"flow-history-action-undelete-post": "жоюды болдырмау",
"flow-history-action-unhide-post": "жасыруды болдырмау",
"flow-history-action-restore-post": "қалпына келтіру",
- "flow-history-action-lock-topic": "жабу",
- "flow-history-action-unlock-topic": "жабуды болдырмау",
+ "flow-history-action-lock-topic": "шешу",
+ "flow-history-action-unlock-topic": "қайта ашу",
"flow-post-edited": "$1 $2 хабарламаны өңдеді",
"flow-post-action-view": "Тұрақты сілтеме",
"flow-post-action-post-history": "Тарихы",
@@ -76,6 +88,7 @@
"flow-post-action-hide-post": "Жасыру",
"flow-post-action-edit-post": "Өңдеу",
"flow-post-action-edit-post-submit": "Өзгерістерді сақтау",
+ "flow-post-action-edit-post-submit-anonymously": "Өзгерістерді анонимді түрде сақтау",
"flow-post-action-unsuppress-post": "Жасыруды болдырмау",
"flow-post-action-undelete-post": "Жоюды болдырмау",
"flow-post-action-unhide-post": "Жасыруды болдырмау",
@@ -87,41 +100,37 @@
"flow-topic-action-history": "Тарихы",
"flow-topic-action-hide-topic": "Тақырыпты жасыру",
"flow-topic-action-delete-topic": "Тақырыпты жою",
- "flow-topic-action-lock-topic": "Тақырыпты жабу",
- "flow-topic-action-unlock-topic": "Тақырыпты жабуды болдырмау",
+ "flow-topic-action-lock-topic": "Шешілген деп белгілеу",
+ "flow-topic-action-unlock-topic": "Тақырыпты қайта ашу",
"flow-topic-action-summarize-topic": "Түйіндеу",
"flow-topic-action-resummarize-topic": "Тақырып түйіндемесін өңдеу",
+ "flow-topic-action-update-topic-summary": "Түйіндемесін жаңарту",
"flow-topic-action-suppress-topic": "Тақырыпты жасыру",
"flow-topic-action-unhide-topic": "Тақырыптың жасырылуын болдырмау",
"flow-topic-action-undelete-topic": "Тақырыптың жойылуын болдырмау",
"flow-topic-action-unsuppress-topic": "Тақырыптың жасырылуын болдырмау",
"flow-topic-action-restore-topic": "Тақырыпты қалпына келтіру",
"flow-topic-action-undo-moderation": "Қайту",
- "flow-topic-notification-subscribe-title": "Тақырып {{GENDER:$1|сіздің}} бақылау тізімізге қосылды.",
+ "flow-topic-notification-subscribe-title": "Тақырып {{GENDER:$1|бақылау тізімізге}} қосылды.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Сіз}} бұл тақырыптағы барлық іc-әрекеттер болғанда ескертпелер аласыз.",
"flow-board-notification-subscribe-title": "{{GENDER:$1|Сіз}} бұл талқылау тақтасына жазылдыңыз!",
"flow-board-notification-subscribe-description": "{{GENDER:$1|Сіз}} бұл тақтада жаңа тақырып басталғанда ескертпе алатын боласыз.",
- "flow-error-allowcreation-no-usedb": "allowCreation <code>true</code> болу үшін <var>$wgContentHandlerUseDB</var> қажет етеді.",
- "flow-error-allowcreation-already-exists": "Бет бұрыннан бар, бірақ қажет етілмеген",
+ "flow-topic-action-watchlist-add": "Бұл тақырыпқа жазылу",
+ "flow-topic-action-watchlist-remove": "Жазылудан бас тарту",
+ "flow-error-allowcreation-no-usedb": "Арнайы бетте Flow жұмыс легін іске қосу <var>$wgContentHandlerUseDB</var> <code>true</code> болуын қажет етеді.",
+ "flow-error-allowcreation-already-exists": "Тағайындалған орында бет бұрыннан бар, сондықтан мұнда Flow тақтасын жылжыту мүмкін емес.",
"flow-error-allowcreation-flow-create-board": "Қатысушыда «{{int:right-flow-create-board}}» рұқсаты жоқ",
"flow-error-http": "Серверге байланысу барысында қате кездесті.",
- "flow-error-other": "Күтпеген қате кездесті.",
- "flow-error-external": "Қате кездесті.<br />Қабылданған қате хабарлама: $1",
- "flow-error-edit-restricted": "Бұл хабарламаны өңдеуге рұқсатыңыз жоқ.",
- "flow-error-topic-is-locked": "Бұл тақырып кез келген әрекеттер үшін жабық.",
- "flow-error-lock-moderated-post": "Қадаланған хабарламаны жаба алмайсыз.",
- "flow-error-external-multi": "Қателер байқалды.<br />$1",
+ "flow-error-external": "Қате кездесті. Қабылданған қате хабарлама: $1",
+ "flow-error-topic-is-locked": "Бұл тақырып шешілген, сондықтан одан ары қарайғы әрекеттер жасау мүмкін емес.",
+ "flow-error-lock-moderated-post": "Қадаланған хабарламаны шешілді деп белгілей алмайсыз.",
"flow-error-missing-content": "Хабарламаның контенті жоқ. Хабарламаны сақтау үшін контент қажет.",
- "flow-error-missing-summary": "Түйіндеме контент жоқ. Түйіндемені сақтау үшін контент қажет.",
- "flow-error-missing-title": "Тақырыпша атаусыз. Тақырыпты сақтау үшін атау қажет.",
+ "flow-error-missing-summary": "Түйіндемесін жіберуіңіз керек.",
+ "flow-error-missing-title": "Тақырып атаусыз. Тақырыпты сақтау үшін атауды қажет етеді.",
"flow-error-parsoid-failure": "Parsoid сәтсіздігіне байланысты контент өңдетілуі мүмкін емес.",
"flow-error-missing-replyto": "«жауап беру» параметрі жабдықталмаған. Бұл параметр «жауап беру» әрекетін қажет етеді.",
- "flow-error-invalid-replyto": "«жауап беру» параметрі жарамсыз. Көрсетілген хабарлама табылмайды.",
- "flow-error-delete-failure": "Бұл элементті өшіру сәтсіз болды.",
- "flow-error-hide-failure": "Бұл элементті жасыру сәтсіз болды.",
- "flow-error-missing-postId": "«хабарлама идентификаторы» параметрі жабдықталмаған. Бұл параметр хабарламаны басқару үшін қажет.",
+ "flow-error-missing-postId": "«хабарлама идентификаторы» (\"postId\") параметрі жабдықталмаған. Бұл параметр хабарламаны басқару үшін қажет.",
"flow-error-invalid-postId": "«хабарлама сәкестендіргіші» параметрі жарамсыз. Көрсетілген ($1) хабарлама табылмайды.",
- "flow-error-restore-failure": "Бұл элементті қалпына келтіру мүмкін болмады.",
"flow-error-invalid-moderation-state": "('moderationState') параметрі үшін жарамсыз мән Flow API-ге жіберілген.",
"flow-error-invalid-moderation-reason": "Модерация себебін келтіріңіз.",
"flow-error-not-allowed": "Бұл әрекетті орындау үшін рұқсат жеткіліксіз.",
@@ -139,107 +148,150 @@
"flow-error-title-too-long": "Тақырып атауы $1 {{PLURAL:$1|байттан|байттан}} асып кеткен.",
"flow-error-no-existing-workflow": "Бұл жұмыс легі тағы жоқ.",
"flow-error-not-a-post": "Бұл атау хабарлама ретінде сақталмады.",
- "flow-error-missing-header-content": "Сипаттамада контент жоқ. Сипаттаманы сақтау үшін кейбір контент қажет етеді.",
- "flow-error-missing-prev-revision-identifier": "Алдыңғы нұсқа идентифткаторы жоқ.",
+ "flow-error-missing-header-content": "Сипаттамасын жіберуіңіз қажет.",
+ "flow-error-missing-prev-revision-identifier": "Алдыңғы нұсқа идентифткаторын қажет етеді.",
"flow-error-prev-revision-mismatch": "Басқа қатысушы хабарламаны біраз секунд бұрын ғана өңдеді. {{GENDER:$3|Сіз}} шыныменде жуырдағы өзгерістің үстінен жазғыңыз келе ме?",
"flow-error-prev-revision-does-not-exist": "Алдыңғы нұсқасы табылмады.",
"flow-error-core-topic-deletion": "Тақырыпты жою үшін Flow тақтасындағы ... мәзірін немесе [$1 тақырып бетін] пайдаланыңыз. Тақырыпқа тікелей action=delete әрекетін қолданбаңыз.",
"flow-error-default": "Белгісіз қате кездесті.",
- "flow-error-invalid-input": "Flow контентін жүктеу үшін жарамсыз мән қамтамасыз етілген.",
+ "flow-error-invalid-input": "Flow контентін оқу үшін жарамсыз мән қамтамасыз етілген.",
"flow-error-invalid-title": "Жарамсыз мән берілген.",
"flow-error-fail-load-history": "Контент тарихы жүктелмеді.",
"flow-error-missing-revision": "Flow контенін жүктегенде нұсқа табылмады.",
"flow-error-fail-commit": "Flow контені сақталмады.",
"flow-error-insufficient-permission": "Контентке қатынауға рұқсат жетіспейді.",
- "flow-error-revision-comparison": "Айырмашылықтарын салыстыру операциясы тек бірдей хабарламадағы тиесілі болатын екі нұсқаға ғана орындалады.",
+ "flow-error-revision-comparison": "Айырмашылықтарын салыстыру әрекеті тек бірдей хабарламаға тиесілі болатын екі нұсқаға ғана орындалады.",
"flow-error-missing-topic-title": "Қазіргі жұмыс ілегінен тақырып атауы табылмады.",
"flow-error-missing-metadata": "Бұл нұсқа үшін қажет ететін метадерегі табылмады.",
"flow-error-fail-load-data": "Сұратылған дерек жүктелмеді.",
"flow-error-invalid-workflow": "Сұратылған жұмыс легі табылмады.",
"flow-error-process-data": "Сіздің сұранысыңыз бойынша деректерді өңдеу кезінде қате орын алды.",
- "flow-error-process-wikitext": "HTML/уикимәтін түрлендіру кезінде қате орын алды.",
+ "flow-error-process-wikitext": "HTML/уикимәтін түрлендіруі кезінде қате орын алды.",
"flow-error-no-index": "Деректерді іздеуді орындау үшін индекс табылмады.",
"flow-error-no-render": "Көрсетілген әрекет танылмады.",
"flow-error-no-commit": "Көрсетілген әрекет сақталмайды.",
"flow-error-content-too-long": "Контент өте үлкен. Кеңейтілімнен кейінгі контент $1 {{PLURAL:$1|байтпен|байтпен}} шектелген.",
- "flow-error-move-topic": "Тақырып бетін қазіргі уақытта жылжытуды қолдамайды.",
- "flow-error-move-no-create-permissions": "Flow тақтасын жылжыту үшін «{{int:right-flow-create-board}}» құқығын қажет етеді.",
+ "flow-error-move-topic": "Тақырып бетін жылжытуды қазіргі уақытта қолдамайды.",
"flow-error-invalid-topic-uuid-title": "Жарамсыз атау",
- "flow-error-invalid-topic-uuid": "Сұратылған бет атауы дұрыс емес. Flow арқылы беттер Тақырып есім кеңістігіне автоматты түрде басталады.",
+ "flow-error-invalid-topic-uuid": "Сұратылған бет атауы дұрыс емес. Flow арқылы беттер Тақырып есім кеңістігінде автоматты түрде басталады.",
"flow-error-unknown-workflow-id-title": "Белгісіз тақырып",
"flow-error-unknown-workflow-id": "Сұратылған тақырып жоқ.",
- "flow-error-search": "Уақытша проблемаға байланысты іздеуіңізді бітіре алмаймыз. Біраздан кейін қайта байқап көріңіз.",
+ "flow-error-search": "Уақытша проблемаға байланысты іздеуіңізді аяқтай алмаймыз. Біраздан кейін қайта байқап көріңіз.",
+ "flow-error-invalid-undelete": "Мақала қалпына келтірілмейді, себебі онда қазіргі уақытта талқылау тақтасы орналасқан.",
"flow-edit-header-placeholder": "Бұл талқылау тақтасын сипаттаңыз",
"flow-edit-header-submit": "Сипаттамасын сақтау",
+ "flow-edit-header-submit-anonymously": "Анонимді түрде сипаттамасын сақтау",
"flow-edit-title-submit": "Атауын өзгерту",
+ "flow-edit-title-submit-anonymously": "Анонимді түрде атауын өзгерту",
"flow-edit-post-submit": "Өзгерістерді жіберу",
- "flow-rev-message-edit-post": "«$4» дегендегі [$3 пікірді] $1 {{GENDER:$2|өңдеді}}",
+ "flow-edit-post-submit-anonymously": "Өзгерістерді анонимді түрде сақтау",
+ "flow-rev-message-edit-post": "«$4» тақырыбындағы [$3 пікірді] $1 {{GENDER:$2|өңдеді}}",
"flow-rev-message-edit-post-recentchanges-summary": "Хабарламаны {{GENDER:$2|өңдеді}}",
- "flow-rev-message-reply": "$1 «$4» дегенде [$3 {{GENDER:$2|пікір жазды}}](<em>$5</em>)",
- "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|пікір|пікір}}</strong> қосты",
+ "flow-rev-message-reply": "$1 «$4» тақырыбына [$3 {{GENDER:$2|пікір жазды}}](<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|пікір|пікір}}</strong> қосылды",
"flow-rev-message-new-post": "$1 «[$3 $4]» деген тақырып {{GENDER:$2|бастады}}",
"flow-rev-message-new-post-recentchanges-summary": "Жаңа тақырып {{GENDER:$2|бастады}}",
"flow-rev-message-edit-title": "$1 «$5» дегеннен «[$3 $4]» дегенге тақырып атауын {{GENDER:$2|өзгертті}}",
"flow-rev-message-create-header": "$1 сипаттамасын {{GENDER:$2|бастады}}",
- "flow-rev-message-edit-header": "$1 сипаттамасын {{GENDER:$2|өзгертті}}",
- "flow-rev-message-create-topic-summary": "$1 $3 дегендегі тақырып түйіндемесін {{GENDER:$2|бастады}}",
- "flow-rev-message-edit-topic-summary": "$1 $3 дегендегі тақырып түйіндемесін {{GENDER:$2|өңдеді}}",
- "flow-rev-message-hid-post": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
- "flow-rev-message-deleted-post": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жойды}} (<em>$5</em>)",
- "flow-rev-message-suppressed-post": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
- "flow-rev-message-restored-post": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|қалпына келтірді}} (<em>$5</em>)",
- "flow-rev-message-hid-topic": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
- "flow-rev-message-deleted-topic": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жойды}} (<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1 «$6» дегендегі [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 «$6» дегендегі [$4 тақырыпты] {{GENDER:$2|жапты}} (<em>$5</em>)",
+ "flow-rev-message-edit-header": "$1 сипаттамасын {{GENDER:$2|өңдеді}}",
+ "flow-rev-message-create-topic-summary": "$1 $3 тақырыбындағы тақырып түйіндемесін {{GENDER:$2|бастады}}",
+ "flow-rev-message-edit-topic-summary": "$1 $3 тақырыбындағы тақырып түйіндемесін {{GENDER:$2|өңдеді}}",
+ "flow-rev-message-hid-post": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жойды}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|қалпына келтірді}} (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жойды}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 «$6» тақырыбындағы [$4 пікірді] {{GENDER:$2|жасырды}} (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 «$6» талқылау тақтасындағы [$4 тақырыпты] шешілді деп {{GENDER:$2|белгіледі}} (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "шешілген деп белгіледі",
+ "flow-rev-message-restore-topic-reason": "қайта ашты",
"flow-rev-message-restored-topic": "$1 «$6» дегендегі [$4 тақырыпты] {{GENDER:$2|қалпына келтірді}} (<em>$5</em>)",
- "flow-rc-topic-of-board": "$2 дегендегі $1",
+ "flow-rc-topic-of-board": "$2 тақтасындағы $1 тақырыбы",
"flow-board-history": "«$1» тарихы",
- "flow-board-history-empty": "Бұл тақта қазіргі уақытта тарихы жоқ.",
+ "flow-board-history-empty": "Бұл тақтаның қазіргі уақытта тарихы жоқ.",
"flow-topic-history": "«$1» тақырыбының тарихы",
"flow-post-history": "Хабарлама тарихындағы «{{GENDER:$2|$2}} пікірі»",
"flow-history-last4": "Соңы 4 сағатта",
"flow-history-day": "Бүгін",
"flow-history-week": "Өткен аптада",
"flow-history-pages-topic": "[$1 «$2» тақтасында] көрсетіледі",
- "flow-history-pages-post": "[$1 $2] дегенде көрсетіледі",
- "flow-topic-comments": "{{PLURAL:$1|$1 пікір|$1 пікір|0={{GENDER:$2|Бірінші болып}} пікір жазыңыз!}}",
+ "flow-history-pages-post": "[$1 $2] тақырыбында көрсетіледі",
+ "flow-topic-comments": "{{PLURAL:$1|Бір пікір|$1 пікір|0={{GENDER:$2|Бірінші болып}} пікір жазыңыз!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Пікірді көру|Пікірлерді көру}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Пікірді жасыру|Пікірлерді жасыру}}",
"flow-comment-restored": "Қалыпына келтірілген пікір",
"flow-comment-deleted": "Жойылған пікір",
"flow-comment-hidden": "Жасырылған пікір",
"flow-comment-moderated": "Модерацияланған пікір",
"flow-last-modified": "$1 шамасында соңғы рет өзгертілген",
"flow-workflow": "жұмыс легі",
- "flow-notification-reply": "'''$4''' бетінде <span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|жауап берді}}.",
- "flow-notification-reply-bundle": "'''$3''' бетінде <span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 және {{PLURAL:$6|басқа|басқа}} $5 қатысушы {{GENDER:$1|жауап берді}}.",
+ "flow-notification-reply": "<strong>$4</strong> бетінде <span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|жауап берді}}.",
+ "flow-notification-reply-bundle": "<strong>$3</strong> бетінде <span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 және {{PLURAL:$5|басқа бір|басқа $5|100=басқа 99+}} $5 қатысушы {{GENDER:$1|жауап берді}}.",
"flow-notification-edit": "[[$3|$4]] бетінде <span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 сіздің <span class=\"plainlinks\">[$5 хабарламаңызды]</span> {{GENDER:$1|өңдеді}}.",
- "flow-notification-edit-bundle": "«$3» бетіндегі «$2» тақырыпындағы <span class=\"plainlinks mw-echo-title-heading\">[$4 хабарламаны]</span><br />$1 және {{PLURAL:$6|тағы|тағы}} $5 қатысушы {{GENDER:$1|өңдеді}}.",
- "flow-notification-newtopic": "$1 '''$3''' бетінде <span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span> деген <br /> жаңа тақырыпты {{GENDER:$1|бастады}} .",
- "flow-notification-newtopic-bundle": "'''<span class=\"plainlinks\">[$3 $2]</span>''' бетінде {{PLURAL:$1|$1|250=250+}} жаңа {{PLURAL:$1|тақырып|тақырып}} {{GENDER:$1|басталды}}.",
- "flow-notification-rename": "$1 [[$5|$6]] бетінде <span class=\"plainlinks\">[$2 $3]</span> дегеннің атауын «$4» дегенге {{GENDER:$1|өзгертті}}.",
- "flow-notification-mention": "$1 «$4» бетіндегі «$3» бөлімінде {{GENDER:$5|сізді}} in {{GENDER:$1|өзінің|өзінің}} <span class=\"plainlinks\">[$2 хабарламасында]</span> {{GENDER:$1|атап өтті}}.",
+ "flow-notification-edit-bundle": "«$3» бетіндегі «$2» тақырыбындағы <span class=\"plainlinks mw-echo-title-heading\">[$4 хабарламаны]</span><br />$1 және {{PLURAL:$5|тағы бір|тағы $5|тағы 100=99+}} $5 қатысушы {{GENDER:$1|өңдеді}}.",
+ "notification-header-flow-new-topic-v2": "<strong>$3</strong> бетінде жаңа тақырып басталды: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> бетіндегі {{PLURAL:$1|Жаңа бір тақырып|$1 тақырып|100=99+ жаңа тақырып}}.",
+ "notification-header-flow-new-topic-user-talk": "Жаңа тақырып <strong>талқылау бетіңізде</strong> басталды: \"<strong>$4</strong>\"..",
+ "notification-bundle-header-flow-new-topic-user-talk": "$1 жаңа {{PLURAL:$1|Бір жаңа тақырып|$1 тақырып|100=99+ тақырып}} <strong>талқылау бетіңізде</strong> басталды.",
+ "notification-header-flow-post-reply": "$1 \"<strong>$4</strong>\" тақырыбына {{GENDER:$2|жауап берді}} .",
+ "notification-bundle-header-flow-post-reply-v2": "\"<strong>$3</strong>\" тақырыбындағы {{PLURAL:$1|Бір жаңа жауап|$1 жаңа жауап|100=99+ жаңа жауап}}.",
+ "notification-header-flow-post-reply-user-talk": "$1 <strong>талқылау бетіңіздегі</strong> \"<strong>$4</strong>\" тақырыбына жауап {{GENDER:$2|жазды}}.",
+ "notification-bundle-header-flow-post-reply-user-talk": "<strong>Талқылау бетіңіздегі</strong> \"<strong>$3</strong>\" тақырыбында {{PLURAL:$1|бір жаңа жауап|$1 жаңа жауап|100=99+ жаңа жауап}}.",
+ "notification-header-flow-post-edited-v2": "\"<strong>$1</strong>\" тақырыбындағы {{GENDER:$2|сіздің}} жазбаңыз өңделді.",
+ "notification-bundle-header-flow-post-edited-v2": "\"<strong>$1</strong>\" тақырыбындағы {{GENDER:$2|сіздің}} жазбаңыз бернеше рет өңделді.",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|талқылау бетіңіздегі}}</strong> \"<strong>$1</strong>\" тақырыбындағы жазба өңделді.",
+ "notification-bundle-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|талқылау бетіңіздегі}}</strong> \"<strong>$1</strong>\" тақырыбындағы жазба бірнеше рет өңделді.",
+ "notification-header-flow-topic-renamed-v2": "\"<strong>$1</strong>\" тақырып атауы \"<strong>$2</strong>\" болып өзгертілді.",
+ "notification-header-flow-topic-renamed-user-talk": "<strong>Талқылау бетіңіздегі</strong> \"<strong>$1</strong>\" тақырып атауы \"<strong>$2</strong>\" болып өзгертілді.",
+ "notification-header-flow-summary-edited": "\"<strong>$1</strong>\" тақырыбының түйіндемесі жаңартылды.",
+ "notification-header-flow-summary-edited-first": "\"<strong>$1</strong>\" тақырыбы түйінделді.",
+ "notification-bundle-header-flow-summary-edited": "\"<strong>$1</strong>\" тақырыбы бірнеше рет түйінделді.",
+ "notification-header-flow-summary-edited-user-talk": "<strong>{{GENDER:$2|Талқылау бетіңіздегі}}</strong> \"<strong>$1</strong>\" тақырыбындағы түйіндеме жаңартылды.",
+ "notification-header-flow-summary-edited-first-user-talk": "<strong>{{GENDER:$2|Талқылау бетіңіздегі}}</strong> \"<strong>$1</strong>\" тақырыбы түйінделді.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "<strong>{{GENDER:$2|Талқылау бетіңіздегі}}</strong> \"<strong>$1</strong>\" тақырыбындағы түйіндеме бірнеше рет жаңартылды.",
+ "notification-email-subject-flow-summary-edited": "$1 $2 тақырыбының түйіндемесін {{GENDER:$2|жаңартты}}.",
+ "notification-email-batch-body-flow-summary-edited": "$1 $2 тақырыбының түйіндемесін {{GENDER:$2|жаңартты}}.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 және {{PLURAL:$3|басқа біреу|басқа $3|100=басқа 99+}} $2 түйіндемесін {{GENDER:$1|жаңартты}}",
+ "notification-header-flow-mention-post": "$1 \"<strong>$5</strong>\" тақырыбында {{GENDER:$4|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-flow-mention-header": "$1 <strong>$3</strong> Flow тақтасының сипаттамасында {{GENDER:$4|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-flow-mention-post-summary": "$1 \"<strong>$5</strong>\" тақырыбында {{GENDER:$4|сізді}} {{GENDER:$2|атап өтті}}.",
+ "notification-header-flow-enabled-on-talkpage": "<strong>{{GENDER:$2|Сіздің}} қатысушы талқылау бетініңізде</strong> жаңа талқылау жүйесі іске қосылды.",
+ "notification-header-flow-description-edited": "<strong>$1</strong> сипаттамасы өңделді",
+ "notification-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|Талқылау бетіңіздің}}</strong> сипаттамасы өңделді.",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong> тақтасының сипаттамасы бірнеше рет өңделді.",
+ "notification-bundle-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|Талқылау бетіңіздің}}</strong> сипаттамасы бірнеше рет өңделді.",
+ "notification-links-flow-description-edited-view-page": "Бетті {{GENDER:$1|көру}}",
+ "notification-email-subject-flow-description-edited": "$1 $2 сипаттамасын {{GENDER:$1|өңдеді}}.",
+ "notification-email-batch-body-flow-description-edited": "$1 $2 сипаттамасын {{GENDER:$1|өңдеді}}.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 және {{PLURAL:$3|басқа біреу|басқа $3|100=басқа 99+}} қатысушы $2 сипаттамасын {{GENDER:$1|өңдеді}}",
+ "flow-notification-newtopic": "$1 <strong>$3</strong> бетінде <span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span> деген <br /> жаңа тақырып {{GENDER:$1|бастады}} .",
+ "flow-notification-newtopic-bundle": "<strong><span class=\"plainlinks\">[$3 $2]</span></strong> бетінде {{PLURAL:$1|бір жаңа тақырып|$1 жаңа тақырып|100=99+ жаңа тақырып}}",
+ "flow-notification-rename": "$1 [[$5|$6]] бетінде <span class=\"plainlinks\">[$2 $3]</span> тақырыбы атауын «$4» дегенге {{GENDER:$1|өзгертті}}.",
+ "flow-notification-mention": "$1 «$4» бетіндегі «$3» бөлімінде {{GENDER:$5|сізді}} {{GENDER:$1|өзінің|өзінің}} <span class=\"plainlinks\">[$2 хабарламасында]</span> {{GENDER:$1|атап өтті}}.",
"flow-notification-link-text-view-post": "Хабарламаны қарау",
"flow-notification-link-text-view-topic": "Тақырыпты қарау",
- "flow-notification-reply-email-subject": "$3 дегендегі $2",
+ "flow-notification-link-text-view-topics": "Тақырыптарды қарау",
+ "flow-notification-reply-email-subject": "$3 бетіндегі $2",
"flow-notification-reply-email-batch-body": "$1 $3 бетіндегі «$2» тақырыбына {{GENDER:$1|жауап жазды}}",
- "flow-notification-reply-email-batch-bundle-body": "$1 және {{PLURAL:$5|тағы}} $4 қатысушы $3 бетіндегі «$2» тақырыбына {{GENDER:$1|жауап жазды}}",
- "flow-notification-mention-email-subject": "$1 $2 дегенде {{GENDER:$3|сізді}} {{GENDER:$3|атап өтті}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 және {{PLURAL:$4|басқа біреу|басқа $4|100=басқа 99+}} $3 бетіндегі \"$2\" тақырыбында {{GENDER:$1|жауап берді}}",
+ "flow-notification-mention-email-subject": "$1 $2 тақтасында {{GENDER:$3|сізді}} {{GENDER:$3|атап өтті}}",
"flow-notification-mention-email-batch-body": "$1 $3 бетіндегі «$2» бөлімінде {{GENDER:$1|өзінің}} хабарламасында {{GENDER:$4|сізді}} {{GENDER:$3|атап өтті}}",
"flow-notification-edit-email-subject": "$1 хабарламаны {{GENDER:$1|өңдеді}}",
"flow-notification-edit-email-batch-body": "$1 $3 бетіндегі «$2» бөліміндегі хабарламаны {{GENDER:$1|өңдеді}}",
- "flow-notification-edit-email-batch-bundle-body": "$3 бетіндегі «$2» бөліміндегі хабарламаны $1 және {{PLURAL:$5|тағы басқа}} $4 қатысушы {{GENDER:$1|өңдеді}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 және $4 {{PLURAL:$4|басқа біреу|басқа $4|100=басқа 99+}} $3 бетіндегі \"$2\" жазбасын {{GENDER:$1|өңдеді}}",
"flow-notification-rename-email-subject": "$1 сіздің тақырыбыңыздың {{GENDER:$1|атауын өзгертті}}",
"flow-notification-rename-email-batch-body": "$1 $4 бетіндегі тақырыбыңыздың атауын «$2» дегенен «$3» дегенге {{GENDER:$1|өзгертті}}",
- "flow-notification-newtopic-email-subject": "$1 $2 бетіде жаңа тақырып {{GENDER:$1|бастады}}",
- "flow-notification-newtopic-email-batch-body": "$1 $3 бетіндегі «$2» деген атаумен жаңа тақырып {{GENDER:$1|бастады}}",
- "flow-notification-newtopic-email-batch-bundle-body": "$2 бетіндегі {{PLURAL:$1|$1|250=250+}} жаңа {{PLURAL:$1|тақырып|тақырып}}",
+ "flow-notification-newtopic-email-subject": "$1 $2 бетінде жаңа тақырып {{GENDER:$1|бастады}}",
+ "flow-notification-newtopic-email-batch-body": "$1 $3 бетінде «$2» деген атаумен жаңа тақырып {{GENDER:$1|бастады}}",
+ "flow-notification-newtopic-email-batch-bundle-body": "$2 бетіндегі {{PLURAL:$1|Жаңа бір тақырып|$1 жаңа тақырып|100=99+ жаңа тақырып}}",
"echo-category-title-flow-discussion": "Flow",
"echo-pref-tooltip-flow-discussion": "Flow қолданған тақтада маған қатысты әрекеттер болғанда маған ескерт",
"flow-link-post": "хабарлама",
"flow-link-topic": "тақырып",
"flow-link-history": "тарихы",
"flow-link-post-revision": "хабарлама нұсқасы",
- "flow-link-topic-revision": "Тақырып нұсқасы",
+ "flow-link-topic-revision": "тақырып нұсқасы",
"flow-link-header-revision": "сипаттама нұсқасы",
"flow-link-summary-revision": "түйіндеме нұсқасы",
"flow-moderation-title-suppress-post": "Хабарлама бастырылсын ба?",
@@ -248,12 +300,12 @@
"flow-moderation-title-unsuppress-post": "Хабарлама бастырылуы болдырылмасын ба?",
"flow-moderation-title-undelete-post": "Хабарлама жойылуы болдырылмасын ба?",
"flow-moderation-title-unhide-post": "Хабарлама жасырылуы болдырылмасын ба?",
- "flow-moderation-placeholder-suppress-post": "Бұл хабарламаны бастыру себебіңізді {{GENDER:$3|түсіндіріңіз}}",
- "flow-moderation-placeholder-delete-post": "Бұл хабарламаны жою себебіңізді {{GENDER:$3|түсіндіріңіз}}",
- "flow-moderation-placeholder-hide-post": "Бұл хабарламаны жасыру себебіңізді {{GENDER:$3|түсіндіріңіз}}",
- "flow-moderation-placeholder-unsuppress-post": "Бұл хабарламаны бастыруды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}",
- "flow-moderation-placeholder-undelete-post": "Бұл хабарламаны жоюды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}",
- "flow-moderation-placeholder-unhide-post": "Бұл хабарламаны жасыруды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}",
+ "flow-moderation-placeholder-suppress-post": "Бұл хабарламаны бастыру себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
+ "flow-moderation-placeholder-delete-post": "Бұл хабарламаны жою себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
+ "flow-moderation-placeholder-hide-post": "Бұл хабарламаны жасыру себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
+ "flow-moderation-placeholder-unsuppress-post": "Бұл хабарламаны бастыруды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
+ "flow-moderation-placeholder-undelete-post": "Бұл хабарламаны жоюды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
+ "flow-moderation-placeholder-unhide-post": "Бұл хабарламаны жасыруды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
"flow-moderation-confirm-suppress-post": "Бастыру",
"flow-moderation-confirm-delete-post": "Жою",
"flow-moderation-confirm-hide-post": "Жасыру",
@@ -266,22 +318,22 @@
"flow-moderation-confirm-unsuppress-topic": "Бастыруды болдырмау",
"flow-moderation-confirm-undelete-topic": "Жоюды болдырмау",
"flow-moderation-confirm-unhide-topic": "Жасыруды болдырмау",
- "flow-moderation-confirmation-suppress-post": "Бұл хабарлама сәтті жасырылды.\n$1 үшін бұл хабарламаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
- "flow-moderation-confirmation-delete-post": "Бұл хабарлама сәтті жойылды.\n$1 үшін бұл хабарламаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
- "flow-moderation-confirmation-hide-post": "Бұл хабарлама сәтті жасырылды.\n$1 үшін бұл хабарламаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
- "flow-moderation-confirmation-unsuppress-post": "Жоғарыдағы хабарламаны бастыруды сәтті болдырмадыңыз.",
- "flow-moderation-confirmation-undelete-post": "Жоғарыдағы хабарламаны жоюды сәтті болдырмадыңыз.",
- "flow-moderation-confirmation-unhide-post": "Жоғарыдағы хабарламаны жасыруды сәтті болдырмадыңыз.",
+ "flow-moderation-confirmation-suppress-post": "Бұл хабарлама бастырылды.\n$1 үшін бұл жазбаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
+ "flow-moderation-confirmation-delete-post": "Бұл хабарлама жойылды.\n$1 үшін бұл жазбаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
+ "flow-moderation-confirmation-hide-post": "Бұл хабарлама жасырылды.\n$1 үшін бұл жазбаға $1 пікір жазу мүмкіндігін {{GENDER:$2|беру}}",
+ "flow-moderation-confirmation-unsuppress-post": "Жоғарыдағы хабарламаны бастыруды болдырмадыңыз.",
+ "flow-moderation-confirmation-undelete-post": "Жоғарыдағы хабарламаны жоюды болдырмадыңыз.",
+ "flow-moderation-confirmation-unhide-post": "Жоғарыдағы хабарламаны жасыруды болдырмадыңыз.",
"flow-moderation-confirmation-suppress-topic": "Бұл тақырып бастырылған.",
"flow-moderation-confirmation-delete-topic": "Бұл тақырып жойылған.",
"flow-moderation-confirmation-hide-topic": "Бұл тақырып жасырылған.",
- "flow-moderation-confirmation-unsuppress-topic": "Бұл тақырыпты бастыруды сәтті болдырмадыңыз.",
- "flow-moderation-confirmation-undelete-topic": "Бұл тақырыпты жоюды сәтті болдырмадыңыз.",
- "flow-moderation-confirmation-unhide-topic": "Бұл тақырыпты жасыруды сәтті болдырмадыңыз.",
+ "flow-moderation-confirmation-unsuppress-topic": "Бұл тақырыпты бастыруды болдырмадыңыз.",
+ "flow-moderation-confirmation-undelete-topic": "Бұл тақырыпты жоюды болдырмадыңыз.",
+ "flow-moderation-confirmation-unhide-topic": "Бұл тақырыпты жасыруды болдырмадыңыз.",
"flow-moderation-title-suppress-topic": "Тақырыпты бастырасыз ба?",
"flow-moderation-title-delete-topic": "Тақырыпты жоясыз ба?",
"flow-moderation-title-hide-topic": "Тақырыпты жасырасыз ба?",
- "flow-moderation-title-unsuppress-topic": "Тақырыптың жасырылуын болдырмайсыз ба?",
+ "flow-moderation-title-unsuppress-topic": "Тақырыптың бастырылуын болдырмайсыз ба?",
"flow-moderation-title-undelete-topic": "Тақырыптың жойылуын болдырмайсыз ба?",
"flow-moderation-title-unhide-topic": "Тақырыптың жасырылуын болдырмайсыз ба?",
"flow-moderation-placeholder-suppress-topic": "Бұл тақырыпты бастыру себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
@@ -292,39 +344,39 @@
"flow-moderation-placeholder-unhide-topic": "Бұл тақырыпты жасыруды болдырмау себебіңізді {{GENDER:$3|түсіндіріңіз}}.",
"flow-topic-permalink-warning": "Бұл тақырып [$2 $1] тақтасында басталған",
"flow-topic-permalink-warning-user-board": "Бұл тақырып [$2 {{GENDER:$1|$1}} тақтасында] басталған",
- "flow-revision-permalink-warning-post": "Бұл осы хабарламаның жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 дегенен.\nСіз [$5 алдыңғы нұсқасынан айырмашылықтарын] көре не [$4 хабарламасының тарих бетінен] басқа нұсқаларын қарай аласыз.",
+ "flow-revision-permalink-warning-post": "Бұл осы хабарламаның жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 жасалған.\nСіз [$5 алдыңғы нұсқасынан айырмашылықтарын] көре не [$4 хабарламасының тарих бетінен] басқа нұсқаларын қарай аласыз.",
"flow-revision-permalink-warning-post-first": "Бұл осы хабарламаның алғашқы нұсқасының тұрақты сілтемесі.\n[$4 Хабарлама тарихы бетінен] соңғы нұсқаларын қарай аласыз.",
- "flow-revision-permalink-warning-postsummary": "Бұл осы хабарлама түйіндемесінің жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 дегенен.\nСіз [$5 алдыңғы нұсқасынан айырмашылықтарын] көре не [$4 хабарламасының тарих бетінен] басқа нұсқаларын қарай аласыз.",
+ "flow-revision-permalink-warning-postsummary": "Бұл осы хабарлама түйіндемесінің жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 жасалған.\nСіз [$5 алдыңғы нұсқасынан айырмашылықтарын] көре не [$4 хабарламасының тарих бетінен] басқа нұсқаларын қарай аласыз.",
"flow-revision-permalink-warning-postsummary-first": "Бұл осы хабарлама түйіндемесінің алғашқы нұсқасының тұрақты сілтемесі.\n[$4 Хабарлама тарихы бетінен] соңғы нұсқаларын қарай аласыз.",
- "flow-revision-permalink-warning-header": "Бұл сипаттаманың жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 дегенен.\nСіз [$3 алдыңғы нұсқасынан айырмашылықтарын] көре не [$2 тақта тарих бетінен] басқа нұсқаларын қарай аласыз.",
+ "flow-revision-permalink-warning-header": "Бұл сипаттаманың жалғыз нұсқасының тұрақты сілтемесі.\nБұл нұсқа $1 сақталған.\nСіз [$3 алдыңғы нұсқасынан айырмашылықтарын] көре не [$2 тақта тарих бетінен] басқа нұсқаларын қарай аласыз.",
"flow-revision-permalink-warning-header-first": "Бұл сипаттаманың алғашқы нұсқасының тұрақты сілтемесі.\n[$2 Тақта тарихы бетінен] соңғы нұсқаларын қарай аласыз.",
- "flow-compare-revisions-revision-header": "$1 кезіндегі {{GENDER:$2|$2}} жасаған нұсқа",
+ "flow-compare-revisions-revision-header": "$1 {{GENDER:$2|$2}} жасаған нұсқа",
"flow-compare-revisions-header-post": "Бұл бетте [$4 $1] бетінде орналасқан «[$5 $2]» тақырыбындағы $3 хабарламасының екі нұсқа арасындағы {{GENDER:$3|өзгерістер}} көрсетілген.\nСіз бұл хабарламаның басқа нұсқаларын [$6 тарих бетінен] қарай аласыз.",
- "flow-compare-revisions-header-postsummary": "Бұл бетте [$3 $1] бетінде орналасқан «[$4 $2]» тақырыбындағы хабарлама түйіндемесінің екі нұсқа арасындағы өзгерістер көрсетілген.\nСіз бұл хабарламаның басқа нұсқаларын [$5 тарих бетінен] қарай аласыз.",
- "flow-compare-revisions-header-header": "Бұл бетте [$3 $1] бетіндегі сипаттаманың екі нұсқа арасындағы {{GENDER:$2|өзгерістері}} көрсетілген.\nСіз сипаттаманың басқа нұсқаларын оның [$4 тарих бетінен] қарай аласыз.",
+ "flow-compare-revisions-header-postsummary": "Бұл бетте [$3 $1] бетінде орналасқан «[$4 $2]» тақырыбындағы хабарлама түйіндемесінің екі нұсқа арасындағы өзгерістер көрсетілген.\nБұл хабарламаның басқа нұсқаларын [$5 тарих бетінен] қарай аласыз.",
+ "flow-compare-revisions-header-header": "Бұл бетте [$3 $1] бетіндегі сипаттаманың екі нұсқа арасындағы {{GENDER:$2|өзгерістері}} көрсетілген.\nСипаттаманың басқа нұсқаларын оның [$4 тарих бетінен] қарай аласыз.",
"action-flow-create-board": "Flow тақталарын кез келген орында бастау",
"right-flow-create-board": "Flow тақталарын кез келген орында бастау",
"right-flow-hide": "Flow тақырыптары мен хабарламаларын жасыру",
- "right-flow-lock": "Flow тақырыптарын жабу",
+ "right-flow-lock": "Flow тақырыптарын шешілді деп белгілеу",
"right-flow-delete": "Flow тақырыптары мен хабарламаларын жою",
"right-flow-edit-post": "Басқа қатысушылардың Flow хабарламаларын өңдеу",
"right-flow-suppress": "Flow нұсқаларын бастыру",
- "flow-terms-of-use-new-topic": "«{{int:flow-newtopic-save}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келіскеніңіз болып табылады.",
- "flow-terms-of-use-reply": "«{{int:flow-reply-link}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келіскеніңіз болып табылады.",
+ "flow-terms-of-use-new-topic": "«{{int:flow-newtopic-save}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келісесіз.",
+ "flow-terms-of-use-reply": "«{{int:flow-reply-link}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келісесіз.",
"flow-terms-of-use-edit": "Өзгерістеріңізді сақтағанда, сіз осы уикидің қолдану шарттарымен келіскеніңіз болып табылады.",
"flow-anon-warning": "Сіз кірмегенсіз. IP мекенжайыңызбен бірге өз есіміңізге қатысты жіберу үшін [$1 кіріңіз] не [$2 тіркеліңіз].",
"flow-cancel-warning": "Сіз бұл формаға мәтін енгіздіңіз. Сіз бұны шынымен өшірмекшісіз бе?",
"flow-topic-first-heading": "$1 бетіндегі тақырып",
- "flow-topic-html-title": "$2 дегендегі $1",
+ "flow-topic-html-title": "$2 бетіндегі $1",
"flow-topic-count": "Тақырыптар ($1)",
"flow-load-more": "Көбірек оқу",
- "flow-no-more-fwd": "Мұнда ескі тақырыптар жоқ",
+ "flow-no-more-fwd": "Мұнда ескірек тақырыптар жоқ",
"flow-newest-topics": "Ең жаңа тақырыптар",
"flow-recent-topics": "Жуықтағы белсенді тақырыптар",
"flow-sorting-tooltip-newest": "{{GENDER:|Сіз}} алғашқы ең жаңа тақырыптарды оқып отырсыз. Сұрыптау параметрлерін таңдау үшін басыңыз.",
"flow-sorting-tooltip-recent": "{{GENDER:|Сіз}} алғашқы ең белсенді тақырыптарды оқып отырсыз. Сұрыптау параметрлерін таңдау үшін басыңыз.",
"flow-toggle-small-topics": "Кішкене тақырыптарды көруге ауысу",
- "flow-toggle-topics": "Кішкене тақырыптарға тек көруге ауысу",
+ "flow-toggle-topics": "Тақырыптарды тек қана көруге ауысу",
"flow-toggle-topics-posts": "Тақырыптарды және хабарламаларды көруге ауысу",
"flow-terms-of-use-summarize": "«{{int:flow-topic-action-update-topic-summary}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келіскеніңіз болып табылады.",
"flow-terms-of-use-lock-topic": "«{{int:flow-topic-action-lock-topic}}» батырмасын басу арқылы сіз осы уикидің қолдану шарттарымен келіскеніңіз болып табылады.",
@@ -332,7 +384,7 @@
"flow-whatlinkshere-post": "[$1 хабарламасынан]",
"flow-whatlinkshere-header": "[$1 сипаттамасынан]",
"flow-whatlinkshere-post-summary": "[$1 түйіндемесінен]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Бұл арнайы бет UUID берілген Flow хабарламасы немесе Flow жұмыс легіне бағыттайды",
"flow-special-type": "Түрі",
"flow-special-type-post": "Хабарлама",
@@ -342,14 +394,13 @@
"flow-special-enableflow-legend": "Жаңа бетте Flow жұмыс легін іске қосу",
"flow-special-enableflow-page": "Бетке Flow жұмыс легін қосу",
"flow-special-enableflow-header": "Flow тақтасындағы бастапқы сипаттамасы (уикимәтін)",
- "flow-special-enableflow-board-already-exists": "[[$1]] ретінде Flow тақтасы сонда әлдеқашан бар.",
+ "flow-special-enableflow-board-already-exists": "[[$1]] бетінде Flow тақтасы әлдеқашан қосылған.",
"flow-special-enableflow-invalid-title": "Жарамсыз бет атауы берілген.",
- "flow-special-enableflow-archive-title-format": "Бар контентті қайда мұрағаттау",
- "flow-special-enableflow-archive-title-format-default-value": "%s/Archive_%d",
- "flow-special-enableflow-board-creation-not-allowed": "[[:$1]] дегенге Flow тақтасын бастауыңызға жол берілмейді.",
- "flow-special-enableflow-page-is-liquidthreads": "[[:$1]] дегенде LiquidThreads беті бар.",
- "flow-special-enableflow-confirmation": "[[$1]] бетінде Flow тақтасын сәтті бастадыңыз.",
- "flow-spam-confirmedit-form": "Егер сіз робот болмасаңыз төмендегі суреттегі мәтінді енгізіңіз: $1",
+ "flow-special-enableflow-board-creation-not-allowed": "[[:$1]] бетіне Flow тақтасын бастауыңызға жол берілмейді.",
+ "flow-special-enableflow-page-is-liquidthreads": "[[:$1]] бетінде LiquidThreads беті бар.",
+ "flow-special-enableflow-confirmation": "[[$1]] бетінде Flow тақтасын бастадыңыз.",
+ "flow-conversion-archive-page-name-format": "%s/Мұрағат %d\n%s/Мұрағат%d\n%s/мұрағат %d\n%s/мұрағат%d",
+ "flow-spam-confirmedit-form": "Егер сіз адам болсаңыз (робот болмасаңыз) төмендегі captcha-ны шешіңіз: $1",
"flow-embedding-unsupported": "Талқылауларға ендірілмейді.",
"mw-ui-unsubmitted-confirm": "Бұл бетте сақталмаған өзгерістеріңіз бар. Сіз әрекетіңізді қалдырып кетіп бара жатқаныңызға сенімдісіз бе?",
"flow-post-undo-hide": "жасыруды болдырмау",
@@ -359,105 +410,16 @@
"flow-topic-undo-delete": "жоюды болдырмау",
"flow-topic-undo-suppress": "бастыруды болдырмау",
"flow-importer-lqt-moved-thread-template": "LQT Moved thread stub Flow жұмыс легіне түрлендірілді",
+ "flow-importer-lqt-moved-thread-template-content": "Бұл жазбаны {{{author}}} жазған {{{date}}} кезінде орны ауыстырылған. Оны [[{{{title}}}]] бетінен таба аласыз.",
"flow-importer-lqt-converted-template": "LQT беті Flow жұмыс легіне түрлендірілді",
+ "flow-importer-lqt-converted-template-content": "Алдыңғы бет тарихы сақтық мақсатында {{#time: Y-m-d|{{{date}}}}} кезінде мұрағатталған: <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> .",
"flow-importer-lqt-converted-archive-template": "LQT бетінің түрлендірілген мұрағаты",
"flow-importer-wt-converted-template": "Уикимәтінді талқылау беті Flow жұмыс легіне түрлендірілді",
+ "flow-importer-wt-converted-template-content": "Алдыңғы талқылау {{#time: Y-m-d|{{{date}}}}} кезінде мұрағатталған: <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> .",
"flow-importer-wt-converted-archive-template": "Уикимәтінді талқылау бетінің түрлендірілген мұрағаты",
- "flow-importer-lqt-suppressed-user-template": "LQT хабарламасы жасырылған қатысушысымен импортталды",
- "apihelp-flow-description": "Flow беттеріндегі көрінетін әрекеттерге рұқсат ету",
- "apihelp-flow-param-submodule": "Шақырылған Flow қарасты модулы",
- "apihelp-flow-param-page": "Әрекетке жол беретін бет.",
- "apihelp-flow-example-1": "«[[Talk:Sandbox]]» сипаттамасын өңдеу",
- "apihelp-flow+close-open-topic-description": "Пайдалануға ескірген [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Ашық не жабық жағдайы бойынша анықталған тақырып.",
- "apihelp-flow+close-open-topic-param-reason": "Тақырыпты жабу немесе жабуды болдырмау себебі.",
- "apihelp-flow+edit-header-description": "Тақта сипаттамасын өңдеу.",
- "apihelp-flow+edit-header-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа сипаттамасының нұсқа сәйкестендіргіші.",
- "apihelp-flow+edit-header-param-content": "Сипаттама үшін контент.",
- "apihelp-flow+edit-header-param-format": "(уикимәтін|html) сипаттамысының форматы",
- "apihelp-flow+edit-header-example-1": "[[Talk:Sandbox]]сипаттамасын өңдеу",
- "apihelp-flow+edit-post-description": "Хабарлама контетнтін өңдеу.",
- "apihelp-flow+edit-post-param-postId": "Сәйкестендіргіш хабарламасы.",
- "apihelp-flow+edit-post-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа хабарламасының нұсқа сәйкестендіргіші.",
- "apihelp-flow+edit-post-param-content": "Хабарламаға котент.",
- "apihelp-flow+edit-post-param-format": "(уикимәтін|html) хабарлама контентінің форматы",
- "apihelp-flow+edit-post-example-1": "Хабарламаны [[Topic:S2tycnas4hcucw8w]] дегенде өңдеу.",
- "apihelp-flow+edit-title-description": "Тақырыптың атауын өңдеу.",
- "apihelp-flow+edit-title-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа атауы нұсқа сәйкестендіргіші.",
- "apihelp-flow+edit-title-param-content": "Атауға контент.",
- "apihelp-flow+edit-title-example-1": "[[Topic:S2tycnas4hcucw8w]]дегеннің атауын өңдеу",
- "apihelp-flow+edit-topic-summary-description": "Тақырыптың түйіндеме контентін өңдеу.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Өңдеу қақтығыстарын тексеру үшін қазіргі нұсқа атауының түйіндемесі нұсқа сәйкестендіргіші.",
- "apihelp-flow+edit-topic-summary-param-summary": "Түйіндемеге контент.",
- "apihelp-flow+edit-topic-summary-param-format": "(уикимәтін|html) түйіндемесінің форматы",
- "apihelp-flow+edit-topic-summary-example-1": "[[Topic:S2tycnas4hcucw8w]]дегеннің түйіндемесін өңдеу",
- "apihelp-flow+lock-topic-description": "Flow тақырыбын жабу немесе жабуды болдырмау.",
- "apihelp-flow+lock-topic-param-moderationState": "Ашық не жабық жағдайы бойынша анықталған тақырып.",
- "apihelp-flow+lock-topic-param-reason": "Тақырыпты жабу немесе жабуды болдырмау себебі.",
- "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] дегенді жабу.",
- "apihelp-flow+moderate-post-description": "Flow хабарламысын модерациялау.",
- "apihelp-flow+moderate-post-param-moderationState": "Модерацияның қандай денгейі?",
- "apihelp-flow+moderate-post-param-reason": "Модерациялау себебі.",
- "apihelp-flow+moderate-post-param-postId": "Хабарлама сәйкестендіргішін модерациялау.",
- "apihelp-flow+moderate-post-example-1": "[[Topic:S2tycnas4hcucw8w]]тақырыбындағы хабарламаны жою.",
- "apihelp-flow+moderate-topic-description": "Flow тақырыбын модерациялайды.",
- "apihelp-flow+moderate-topic-param-moderationState": "Модерацияның қандай денгейі?",
- "apihelp-flow+moderate-topic-param-reason": "Модерациялау себебі.",
- "apihelp-flow+moderate-topic-example-1": "[[Topic:S2tycnas4hcucw8w]]тақырыбын жою.",
- "apihelp-flow+new-topic-description": "Берілген жұмыс легінен жаңа Flow тақырып бастайды.",
- "apihelp-flow+new-topic-param-topic": "Жаңа тақырып атауына мәтін.",
- "apihelp-flow+new-topic-param-content": "Тақырыптың алғашқы жауабына контент.",
- "apihelp-flow+new-topic-param-format": "Жаңа жатқырыптың алғашқы жауабының форматы (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "[[Talk:Sandbox]] дегенге жаңа тақырып бастау.",
- "apihelp-flow+reply-description": "Хабарламаға жауаптар.",
- "apihelp-flow+reply-param-replyTo": "Жауапқа хабарлама сәйкестендіргіш.",
- "apihelp-flow+reply-param-content": "Жаңа хабарламаға котент.",
- "apihelp-flow+reply-param-format": "(уикимәтін|html) жаңа хабарламасының форматы",
- "apihelp-flow+reply-example-1": "[[Topic:S2tycnas4hcucw8w]] дегенде хабарламаға жауап",
- "apihelp-flow+view-header-param-format": "Контентті қайтаратын формат.",
- "apihelp-flow+view-header-description": "Тақта сипаттамасын көру.",
- "apihelp-flow+view-header-param-revId": "Ағымдағының орнына мына нұсқаны жүктеңіз.",
- "apihelp-flow+view-header-example-1": "Уики мәтін секілді [[Talk:Sandbox]] сипаттамасын ығыстыру.",
- "apihelp-flow+view-post-description": "Хабарламаны қарау.",
- "apihelp-flow+view-post-param-postId": "Қарау үшін хабарламаның сәйкестендіргіші.",
- "apihelp-flow+view-post-param-format": "Контентті қайтаратын формат.",
- "apihelp-flow+view-post-example-1": "Уики мәтін секілді [[Topic:S2tycnas4hcucw8w]] хабарламасының контентін ығыстыру.",
- "apihelp-flow+view-topic-description": "Тақырыпты қарау.",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] дегенді қарау.",
- "apihelp-flow+view-topic-summary-description": "Тақырып түйіндемесін қарау.",
- "apihelp-flow+view-topic-summary-param-format": "Контентті қайтаратын формат.",
- "apihelp-flow+view-topic-summary-param-revId": "Ең соңғының орнына мына нұсқаны жүктеңіз.",
- "apihelp-flow+view-topic-summary-example-1": "Уики мәтіні секілді [[Topic:S2tycnas4hcucw8w]] түйіндемесін қарау.",
- "apihelp-flow+view-topiclist-description": "Тақырыптардың тізімін қарау.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Тақырыпты реттеу бағыты.",
- "apihelp-flow+view-topiclist-param-sortby": "Тақырыптарды сұрыпттау параметрі.",
- "apihelp-flow+view-topiclist-param-savesortby": "Егер сұрыптау параметрі орнатылған болса сақтау.",
- "apihelp-flow+view-topiclist-param-offset-id": "Алу тақырыбын бастау үшін орын ауыстыру мәні (UUID форматында).",
- "apihelp-flow+view-topiclist-param-offset": "Ығысу тақырыбын бастау үшін орын ауыстыру мәні.",
- "apihelp-flow+view-topiclist-param-limit": "Ығыстыратын тақырып саны.",
- "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]] бетіндегі тақырыптар саны",
- "apihelp-flow-parsoid-utils-description": "HTML және уикимәтін арасында мәтінді түрлендіру",
- "apihelp-flow-parsoid-utils-param-from": "Контент түрленетін форматтан.",
- "apihelp-flow-parsoid-utils-param-to": "Контент түрленетін форматқа.",
- "apihelp-flow-parsoid-utils-param-content": "Жұмсақ түрлендіруді қажет ететін контент.",
- "apihelp-flow-parsoid-utils-param-title": "Беттің атауы. $1pageaid дегенмен бірге қолданылмайды.",
- "apihelp-flow-parsoid-utils-param-pageid": "Бет сәйкестендіргіші. $1 дегенмен бірге қолданылмайды.",
- "apihelp-flow-parsoid-utils-example-1": "<nowiki>'''lorem''' ''blah''</nowiki> уики мәтінін HTML-ге түрлендіру.",
- "apihelp-query+flowinfo-description": "Flow туралы жай мәліметтер алу.",
- "apihelp-query+flowinfo-example-1": "[[Talk:Sandbox]], [[Main Page]], және [[Talk:Flow]] туралы мәліметтерді ығыстыру.",
- "apihelp-flow+undo-edit-header-description": "Сипаттама өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
- "apihelp-flow+undo-edit-header-param-startId": "Болдырмауды бастауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-header-param-endId": "Болдырмауды аяқтауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-header-example-1": "[[Talk:Sandbox]] дегендегі сипаттаманы болдырмау туралы мәліметті ығыстыру.",
- "apihelp-flow+undo-edit-post-description": "Хабарлама өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
- "apihelp-flow+undo-edit-post-param-postId": "Болдырмау үшін сәйкестендіргішті хабарлау.",
- "apihelp-flow+undo-edit-post-param-startId": "Болдырмауды бастауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-post-param-endId": "Болдырмауды аяқтауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-post-example-1": "Көрсетілген тақырыптағы хабарлама өңдемесін жоққа шығару туралы мәліметті ығыстыру.",
- "apihelp-flow+undo-edit-topic-summary-description": "Тақырып түйіндеме өңдемелерін жоққа шығару үшін мәліметтерді алу өте қажет.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Болдырмауды бастауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Болдырмауды аяқтауға сәйкестендіргіш нұсқа.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Көрсетілген тақырыптағы тақырып түйіндемесін өңдемесін жоққа шығару туралы мәліметті ығыстыру.",
+ "flow-importer-wt-converted-archive-template-content": "Бұл бет мұрағат. '''Бұл беттің мазмұнын өңдемеңіз'''. Қандай да бір қосымша пікірлерді [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|талқылау бетіне]] жазыңыз.",
+ "flow-importer-lqt-suppressed-user-template": "LQT хабарламасы бастырылған қатысушысы импортталған",
+ "flow-importer-lqt-different-author-signature-template-content": "''Бұл жазбаны [[User:{{{authorUser}}}|{{{authorUser}}}]] жазған, бірақ [[User:{{{signatureUser}}}|{{{signatureUser}}}]] ретінде қолтаңба қалдырған.''",
"flow-edited": "Өңделді",
"flow-edited-by": "$1 өңдеді",
"flow-lqt-redirect-reason": "Ескірген LiquidThreads хабарламасын оның түрлендірілген Flow хабарламасына бағыттау",
@@ -465,28 +427,54 @@
"flow-talk-conversion-archive-edit-reason": "Уикимәтін талқылауын Flow жұмыс легіне түрлендіру",
"flow-previous-diff": "← Алдыңғы өңдеме",
"flow-next-diff": "Келесі өңдеме →",
- "flow-undo": "қайту",
+ "flow-undo": "болдырмау",
"flow-undo-latest-revision": "Ең соңғы нұсқасы",
"flow-undo-your-text": "Мәтініңіз",
- "flow-undo-edit-header": "Сипаттамасы өңделуде",
- "flow-undo-edit-topic-summary": "Тақырып түйіндемесі өңделуде",
- "flow-undo-edit-post": "Хабарлама өңделуде",
+ "flow-undo-edit-header": "Сипаттамасын өңдеп жатырсыз",
+ "flow-undo-edit-topic-summary": "Тақырып түйіндемесін өңдеп жатырсыз",
+ "flow-undo-edit-post": "Хабарламаны өңдеп жатырсыз",
"flow-undo-edit-content": "Бұл өңдемені жоққа шығарымақшысыз. Алдымен алдын-ала төмендегі салыстыруды тексеріп шығыңыз да өңдемені жоққа шығаруды аяқтау үшін бетті сақтаңыз.",
- "flow-undo-edit-failure": "Бұл өңдеме жоққа шығарылмайды, себебі арада қақтығысты өңдемелер бар.",
+ "flow-undo-edit-failure": "Өңдемелер арасында қақтығысатындықтан өңдеме жоққа шығарылмайды.",
"group-flow-bot": "Flow боттар",
"group-flow-bot-member": "Flow бот",
"grouppage-flow-bot": "Project:Flow боттар",
"flow-ve-mention-context-item-label": "Атап өту",
"flow-ve-mention-inspector-title": "Атап өту",
- "flow-ve-mention-inspector-remove-label": "Аластау",
+ "flow-ve-mention-inspector-remove-label": "Алып тастау",
"flow-ve-mention-placeholder": "Қатысушы есімі",
"flow-ve-mention-tool-title": "Қатысушыны атап өту",
- "flow-ve-mention-template": "ping",
+ "flow-ve-mention-template-title": "FlowMention",
"flow-ve-mention-inspector-invalid-user": "«$1» қатысушы есімі тіркелмеген.",
"flow-wikitext-editor-help": "Уикимәтін: $1.",
"flow-wikitext-editor-help-and-preview": "Уикимәтінін $1 және кез келген уақытта $2",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|белгілеу қолданылады]]",
- "flow-wikitext-editor-help-preview-the-result": "нәтижесін қарай аласыз",
- "flow-wikitext-switch-editor-tooltip": "VisualEditor өңдегішіне ауысу",
- "flow-ve-switch-editor-tool-title": "Уикимәтін өңдегішіне ауысу"
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|белгілеу қолданылады]]",
+ "flow-wikitext-editor-help-preview-the-result": "нәтижесін алдын ала қарай аласыз",
+ "flow-wikitext-switch-editor-tooltip": "Көріп өңдегішке ауысу",
+ "flow-ve-switch-editor-tool-title": "Уикимәтін өңдегішіне ауысу",
+ "flow-mark-revision-patrolled-link-text": "Бұл бетті тексерілді деп белгілеу",
+ "flow-mark-revision-patrolled-link-title": "Бұл бетті тексерілді деп белгілеу",
+ "flow-mark-diff-patrolled-link-text": "Тексерілді деп белгіленді",
+ "flow-mark-diff-patrolled-link-title": "Тексерілді деп белгілеу",
+ "flow-talk-page-beta-feature-message": "Flow қатысушы талқылау бетінде",
+ "flow-talk-page-beta-feature-description": "{{GENDER:|Сіздің}} қатысушы талқылау бетіңізге жаңа құрылымданған талқылау жүйесін іске қосады. Flow талқылау беті талқылауларын қарапайым етеді және әңгімелесу ескертпелерін береді. Бұрыңғы уикимәтін талқылаулары мұрағатқа жылжытылады. Бұл мүмкіндік өздігінен іске қосылмайды; қатысушылар оны әрқайсысы бөлек іске қосады. Бұл мүмкіндікті өшіргенде Flow тақтасы төменгі бетке жылжытылады және алдыңғы талқалау беті мұрағатынан қайтады.",
+ "flow-notification-link-text-enabled-on-talkpage": "Қатысушы талқылау бетін {{GENDER:|қарау}}",
+ "flow-notification-enabled-on-talkpage-title": "Жаңа талқылау жүйесі {{GENDER:$1|талқылау бетіңізде}} іске қосылды <br /><small>Қарап көріңіз: [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "$2 бетіндегі жаңа талқылау жүйесі",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "{{SITENAME}} сайтында Flow жаңа уики талқылау жүйесі {{GENDER:$1|талқылау бетіңізде}} іске қосылды. Сіз көбірек мәлімет ала аласыз, пікіріңізді айтыңыз не кез келген уақытта жаңа жүйені бета {{GENDER:$1|баптауларыңыздан}} сөндіре аласыз.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Мұрағат үлгісін қосты",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Мұрағат үлгісін алып тастады",
+ "flow-dialog-cancelconfirm-title": "Сенімдісіз бе?",
+ "flow-dialog-cancelconfirm-message": "Бірінші сақтамай кетпекші болғаныңызға сенімдісіз бе?",
+ "flow-dialog-cancelconfirm-keep": "Өңдеуді жалғастыру",
+ "flow-dialog-cancelconfirm-discard": "Өзгерістерді болдырмау",
+ "flow-optin-archive-wikitext": "Талқылау тақтасына бөлме жасау үшін уикимәтін бетінің орынын ауыстыру.",
+ "flow-optin-archive-flow-board": "Уикимәтін бетіну бөлме жасау үшін талқылау тақтасының орынын ауыстыру.",
+ "flow-optin-restore-wikitext": "Мұрағатталған уикимәтін бетін қалпына келтіру",
+ "flow-optin-restore-flow-board": "Мұрағатталған талқылау тақтасын қалпына келтіру",
+ "flow-guidedtour-optin-welcome": "Жаңа қатысушы талқылау бетіңізге {{GENDER:$1|қош келдіңіз}}",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Талқылау бетіңіз}} {{GENDER:$1|сізбен}} басқа өңдеушілер байланыса алатын орын. Flow-мен жаңа тақырыптарды бастау және әңгімелерді қалағалау бұл оңайырақ.",
+ "flow-guidedtour-optin-find-old-conversations": "Ескі {{GENDER:$1|әңгімелеріңізді}} табу",
+ "flow-guidedtour-optin-find-old-conversations-description": "Ескі әңгімелесулер мұрағат бетіне ауыстырылған.",
+ "flow-guidedtour-optin-feedback": "Бізге {{GENDER:$1|ұсыныс пен пікірлеріңізді}} айтыңыз!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Сіз}} көбірек мәлімет ала аласыз, ұсыныс пен пікірлеріңізді айта аласыз не жаңа жүйені бета мүмкіндіктер бөлімінен өшіре аласыз."
}
diff --git a/Flow/i18n/ko.json b/Flow/i18n/ko.json
index 2047cf6c..010af40b 100644
--- a/Flow/i18n/ko.json
+++ b/Flow/i18n/ko.json
@@ -18,64 +18,92 @@
"Bluemersen",
"Kwj2772",
"LiteHell",
- "Hwangjy9"
+ "Hwangjy9",
+ "Nnemo",
+ "Yearning",
+ "Ykhwong",
+ "Jerrykim306"
]
},
- "enableflow": "Flow 활성화",
- "flow-desc": "워크플로우 관리 시스템",
+ "enablestructureddiscussions": "플로우 활성화",
+ "notification-dynamic-actions-flow-board-unwatch": "\"$1\"의 새로운 활동 주시를 {{GENDER:$3|해제}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|당신은}} 더 이상 \"$1\" 문서를 주시하지 않습니다",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "{{GENDER:$3|당신이}} 주시하고 있는 개별 주제에는 영향을 미치지 않습니다. 언제든지 [$2 이 문서]를 주시할 수 있습니다.",
+ "notification-dynamic-actions-flow-topic-unwatch": "이 주제의 주시를 {{GENDER:$3|해제}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|당신은}} 더 이상 \"$1\"을(를) 주시하지 않습니다",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|당신은}} 언제든지 [$2 이 주제]를 주시할 수 있습니다.",
+ "flow-desc": "토론 시스템",
+ "flow-talk-taken-over-comment": "/* 이 문서는 플로우 토론 게시판으로 변환되었습니다 */",
"log-name-flow": "플로우 활동 기록",
- "logentry-delete-flow-delete-post": "$1 사용자가 [[$3]] 문서의 [$4 게시물]을 {{GENDER:$2|삭제했습니다}}",
- "logentry-delete-flow-restore-post": "$1 사용자가 [[$3]] 문서의 [$4 게시물]을 {{GENDER:$2|되살렸습니다}}",
- "logentry-suppress-flow-suppress-post": "$1 사용자가 [[$3]] 문서의 [$4 게시물]을 {{GENDER:$2|숨겼습니다}}",
- "logentry-suppress-flow-restore-post": "$1 사용자가 [[$3]] 문서의 [$4 게시물]을 {{GENDER:$2|삭제했습니다}}",
- "logentry-delete-flow-delete-topic": "$1 사용자가 [[$6]] 문서의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|삭제했습니다}}",
- "logentry-delete-flow-restore-topic": "$1 사용자가 [[$6]] 문서의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|복원했습니다}}",
- "logentry-suppress-flow-suppress-topic": "$1 사용자가 [[$6]] 문서의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|숨겼습니다}}",
- "logentry-suppress-flow-restore-topic": "$1 사용자가 [[$6]] 문서의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-delete-post": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"의 [$4 게시물]을 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1님이 [[$3]]의 주제의 게시물을 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-restore-post": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"의 [$4 게시물]을 {{GENDER:$2|되살렸습니다}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1님이 [[$3]]의 주제의 게시물을 {{GENDER:$2|복구했습니다}}",
+ "logentry-suppress-flow-suppress-post": "$1님이 [[$6]]에서 \"[[$3|$5]]\" [$4 게시물]을 {{GENDER:$2|숨겼습니다}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1님이 [[$3]]의 주제의 게시물을 {{GENDER:$2|보이지 않게 했습니다}}",
+ "logentry-suppress-flow-restore-post": "$1님이 [[$6]]에서 \"[[$3|$5]]\" [$4 게시물]을 {{GENDER:$2|삭제했습니다}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1님이 [[$3]]의 주제의 게시물을 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-delete-topic": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1님이 [[$3]]의 주제를 {{GENDER:$2|삭제했습니다}}",
+ "logentry-delete-flow-restore-topic": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|되살렸습니다}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1님이 [[$3]]의 주제를 {{GENDER:$2|복구했습니다}}",
+ "logentry-suppress-flow-suppress-topic": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|숨겼습니다}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1님이 [[$3]]의 주제를 {{GENDER:$2|보이지 않게 했습니다}}",
+ "logentry-suppress-flow-restore-topic": "$1님이 [[$6]]의 주제 \"[[$3|$5]]\"를 {{GENDER:$2|삭제했습니다}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1님이 [[$3]]의 주제를 {{GENDER:$2|삭제했습니다}}",
+ "logentry-lock-flow-lock-topic": "$1님이 [[$6]]의 \"[[$3|$5]]\" 주제를 해결된 것으로 {{GERDER:$2|표시했습니다}}",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1님이 [[$3]]에서 주제를 해결된 것으로 {{GENDER:$2|표시했습니다}}",
+ "logentry-lock-flow-restore-topic": "$1님이 [[$6]]의 \"[[$3|$5]]\" 주제를 {{GERDER:$2|다시 열었습니다}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1님이 [[$3]]의 주제를 {{GENDER:$2|재개했습니다}}",
"logentry-import-lqt-to-flow-topic": "[[$3]]의 [[$1|$2]]는 LiquidThreads에서 Flow로 가져왔습니다",
"flow-user-moderated": "중재된 사용자",
"flow-board-header-browse-topics-link": "주제 둘러보기",
"flow-board-header": "이 게시물에 대한 정보",
+ "flow-board-description-can-not-edit": "편집 불가능",
"flow-board-collapse-description": "설명 숨기기",
"flow-board-expand-description": "설명 보이기",
"flow-edit-header-link": "설명 편집",
- "flow-post-moderated-toggle-hide-show": "$2 사용자가 {{GENDER:$1|숨긴}} 댓글 보이기",
- "flow-post-moderated-toggle-delete-show": "$2 사용자가 {{GENDER:$1|삭제한}} 댓글 보이기",
- "flow-post-moderated-toggle-suppress-show": "$2 사용자가 {{GENDER:$1|표시하지 않도록 한}} 댓글 보기",
- "flow-post-moderated-toggle-hide-hide": "$2 사용자가 {{GENDER:$1|숨긴}} 댓글 숨기기",
- "flow-post-moderated-toggle-delete-hide": "$2 사용자가 {{GENDER:$1|삭제한}} 댓글 숨기기",
- "flow-post-moderated-toggle-suppress-hide": "$2 사용자가 {{GENDER:$1|표시하지 않도록 한}} 댓글 숨기기",
+ "flow-post-moderated-toggle-hide-show": "$2님이 {{GENDER:$1|숨긴}} 댓글 보이기",
+ "flow-post-moderated-toggle-delete-show": "$2님이 {{GENDER:$1|삭제한}} 댓글 보이기",
+ "flow-post-moderated-toggle-suppress-show": "$2님이 {{GENDER:$1|표시하지 않도록 한}} 댓글 보기",
+ "flow-post-moderated-toggle-hide-hide": "$2님이 {{GENDER:$1|숨긴}} 댓글 숨기기",
+ "flow-post-moderated-toggle-delete-hide": "$2님이 {{GENDER:$1|삭제한}} 댓글 숨기기",
+ "flow-post-moderated-toggle-suppress-hide": "$2님이 {{GENDER:$1|표시하지 않도록 한}} 댓글 숨기기",
"flow-topic-moderated-reason-prefix": "이유:",
- "flow-hide-post-content": "이 댓글은 $1 사용자에 의해 {{GENDER:$1|숨겨졌}}습니다 ([$2 기록])",
- "flow-hide-title-content": "이 주제는 $1 사용자에 의해 {{GENDER:$1|숨겨졌}}습니다",
- "flow-hide-header-content": "$2 사용자가 {{GENDER:$1|숨김}}",
- "flow-delete-post-content": "이 댓글은 $1 사용자에 의해 {{GENDER:$1|삭제}}되었습니다 ([$2 기록])",
- "flow-delete-title-content": "이 주제는 $1 사용자에 의해 {{GENDER:$1|삭제}}되었습니다",
- "flow-delete-header-content": "$2 사용자가 {{GENDER:$1|삭제함}}",
- "flow-suppress-post-content": "이 댓글은 $1 사용자가 {{GENDER:$1|표시하지 않도록}} 했습니다 ([$2 기록])",
- "flow-suppress-title-content": "이 주제는 $1 사용자가 {{GENDER:$1|표시하지 않도록}} 했습니다",
- "flow-suppress-header-content": "$2 사용자가 {{GENDER:$1|표시하지 않도록 함}}",
+ "flow-hide-post-content": "이 댓글은 $1님에 의해 {{GENDER:$1|숨겨졌}}습니다 ([$2 기록])",
+ "flow-hide-title-content": "이 주제는 $1님에 의해 {{GENDER:$1|숨겨졌}}습니다",
+ "flow-hide-header-content": "$2님이 {{GENDER:$1|숨김}}",
+ "flow-delete-post-content": "이 댓글은 $1님에 의해 {{GENDER:$1|삭제}}되었습니다 ([$2 기록])",
+ "flow-delete-title-content": "이 주제는 $1님에 의해 {{GENDER:$1|삭제}}되었습니다",
+ "flow-delete-header-content": "$2님이 {{GENDER:$1|삭제함}}",
+ "flow-suppress-post-content": "이 댓글은 $1님이 {{GENDER:$1|표시하지 않도록}} 했습니다 ([$2 기록])",
+ "flow-suppress-title-content": "이 주제는 $1님이 {{GENDER:$1|표시하지 않도록}} 했습니다",
+ "flow-suppress-header-content": "$2님이 {{GENDER:$1|표시하지 않도록 함}}",
"flow-suppress-usertext": "<em>사용자 이름을 표시하지 않음</em>",
"flow-post-actions": "동작",
"flow-topic-actions": "동작",
"flow-cancel": "취소",
- "flow-skip-summary": "편집 요약 생략",
+ "flow-skip-summary": "건너뛰기",
+ "flow-edit-summary-placeholder": "이 토론의 결과를 간략하게 설명합니다",
"flow-summary-authored": "$1의 요약",
"flow-summary-edited": "$1이 마지막으로 {{GENDER:$1|편집한}} 요약",
"flow-show-change": "차이 보기",
- "flow-last-modified-by": "$1 사용자가 마지막으로 {{GENDER:$1|수정함}}",
- "flow-stub-post-content": "\"기술적인 오류로 인하여 이 게시물을 가져올 수 없었습니다.\"",
+ "flow-last-modified-by": "$1님이 마지막으로 {{GENDER:$1|수정함}}",
+ "flow-stub-post-content": "<em>기술적인 오류로 인하여 이 내용을 가져오지 못했습니다.</em>",
"flow-newtopic-title-placeholder": "새 주제",
"flow-newtopic-content-placeholder": "\"$1\"에 새 메시지 남기기",
"flow-newtopic-header": "새 항목 추가",
"flow-newtopic-save": "새 항목",
+ "flow-newtopic-save-anonymously": "익명으로 주제 추가",
"flow-newtopic-start-placeholder": "새 주제 시작하기",
"flow-newtopic-first-heading": "$1에 새 주제 시작하기",
"flow-summarize-topic-placeholder": "이 토론을 요약해 주세요",
"flow-reply-topic-placeholder": "$1의 \"$2\"에 대한 의견",
"flow-reply-topic-title-placeholder": "\"$1\"에 답변하기",
"flow-reply-link": "{{GENDER:$1|답변}}",
- "flow-thank-link": "{{GENDER:$1|감사합니다}}",
+ "flow-reply-link-anonymously": "익명으로 답장",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|감사를 표하기}}}}",
+ "flow-thank-link-title": "공개적으로 게시자에게 {{GENDER:$1|{{GENDER:$2|감사를 표합니다}}}}",
"flow-history-action-suppress-post": "숨기기",
"flow-history-action-delete-post": "삭제",
"flow-history-action-hide-post": "숨기기",
@@ -83,7 +111,9 @@
"flow-history-action-undelete-post": "삭제 취소",
"flow-history-action-unhide-post": "숨기기 취소",
"flow-history-action-restore-post": "복구",
- "flow-post-edited": "$1 사용자가 $2에 게시물을 {{GENDER:$1|편집했습니다}}",
+ "flow-history-action-lock-topic": "해결",
+ "flow-history-action-unlock-topic": "다시 열기",
+ "flow-post-edited": "$1님이 $2에 게시물을 {{GENDER:$1|편집했습니다}}",
"flow-post-action-view": "고유링크",
"flow-post-action-post-history": "역사",
"flow-post-action-suppress-post": "표시 안 함",
@@ -91,6 +121,7 @@
"flow-post-action-hide-post": "숨기기",
"flow-post-action-edit-post": "편집",
"flow-post-action-edit-post-submit": "바뀜 저장",
+ "flow-post-action-edit-post-submit-anonymously": "익명으로 편집 저장",
"flow-post-action-unsuppress-post": "숨김 해제",
"flow-post-action-undelete-post": "삭제 취소",
"flow-post-action-unhide-post": "숨기기 취소",
@@ -103,9 +134,10 @@
"flow-topic-action-hide-topic": "주제 숨기기",
"flow-topic-action-delete-topic": "주제 삭제",
"flow-topic-action-lock-topic": "해결한 것으로 표시",
- "flow-topic-action-unlock-topic": "주제 잠금 해제하기",
+ "flow-topic-action-unlock-topic": "주제 다시 열기",
"flow-topic-action-summarize-topic": "요약",
"flow-topic-action-resummarize-topic": "주제 요약 편집",
+ "flow-topic-action-update-topic-summary": "편집 요약 갱신",
"flow-topic-action-suppress-topic": "주제 숨겨놓기",
"flow-topic-action-unhide-topic": "주제 숨기기",
"flow-topic-action-undelete-topic": "주제 삭제 취소",
@@ -114,24 +146,28 @@
"flow-topic-action-undo-moderation": "되돌리기",
"flow-topic-notification-subscribe-title": "이 주제는 {{GENDER:$1|당신의}} 주시문서 목록에 추가되었습니다.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|당신은}} 이 주제의 모든 활동에 대한 알림을 받을 것입니다.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|당신은}} 이 토론 게시판을 구독합니다!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|당신은}} 새 주제가 이 게시판에 만들어질 때 알림을 받을 것입니다.",
"flow-topic-action-watchlist-add": "주제를 구독",
"flow-topic-action-watchlist-remove": "구독 해지",
+ "flow-error-allowcreation-flow-create-board": "사용자에게 \"{{int:right-flow-create-board}}\" 권한이 없습니다",
+ "flow-error-can-not-edit-logged-out": "현재 참여할 수 없습니다. 로그인을 시도할 수 있습니다.",
+ "flow-error-can-not-edit-logged-in": "필요한 권한이 없기 때문에 참여할 수 없습니다.",
"flow-error-http": "서버와 만나는 동안 오류가 발생했습니다.",
- "flow-error-other": "예기치 않은 오류가 발생했습니다.",
- "flow-error-external": "오류가 발생했습니다.<br />받은 오류 메시지는: $1",
- "flow-error-edit-restricted": "이 문서의 편집을 허용하지 않습니다.",
- "flow-error-external-multi": "오류가 발생했습니다.<br />$1",
+ "flow-error-external": "오류가 발생했습니다. 받은 오류 메시지는 다음과 같습니다: $1",
+ "flow-error-topic-is-locked": "이 주제는 해결되었으므로 더 이상의 활동은 불가능합니다.",
"flow-error-missing-content": "게시물에 내용이 없습니다. 게시물을 저장하려면 내용이 있어야 합니다.",
- "flow-error-missing-summary": "편집 요약에 내용이 없습니다. 요약을 저장하려면 내용이 있어야 합니다.",
+ "flow-error-missing-summary": "편집 요약을 입력해야 합니다.",
"flow-error-missing-title": "주제에 제목이 없습니다. 주제를 저장하려면 제목이 있어야 합니다.",
"flow-error-parsoid-failure": "Parsoid 오류로 인해 내용을 구문 분석할 수 없습니다.",
+ "flow-error-protected-autoconfirmed-logged-in": "이 게시판은 보호되었습니다. 자동 인증된 사용자만 참여할 수 있습니다. 이유: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "이 게시판은 보호되었습니다. 자동 인증된 사용자만 참여할 수 있습니다. 이유: $1",
+ "flow-error-protected-sysop-logged-in": "이 게시판은 보호되어 있습니다. 관리자만 참여할 수 있습니다. 이유: $1",
+ "flow-error-protected-sysop-logged-out": "이 게시판은 보호되었습니다. 관리자인 사용자만 참여할 수 있습니다. 이유: $1",
+ "flow-error-protected-unknown-reason": "알 수 없음",
"flow-error-missing-replyto": "\"ReplyTo\" 매개변수는 지원되지 않습니다. 이 매개변수는 \"답변\" 명령에 대해 필요합니다.",
- "flow-error-invalid-replyto": "\"replyTo\" 변수가 잘못되었습니다. 지정한 게시물을 찾을 수 없습니다.",
- "flow-error-delete-failure": "이 항목을 삭제하는 데 실패했습니다.",
- "flow-error-hide-failure": "이 항목을 표시하지 않음으로 설정하지 못하였습니다.",
"flow-error-missing-postId": "\"postId\" 매개변수를 지원하지 않습니다. 이 매개변수는 게시물을 조작하여야 합니다.",
"flow-error-invalid-postId": "\"postId\" 변수가 잘못되었습니다. 지정한 게시물($1)을 찾을 수 없습니다.",
- "flow-error-restore-failure": "이 항목을 복원하는 데 실패했습니다.",
"flow-error-invalid-moderation-state": "유효하지 않은 값이 조정상태에 입력되었습니다.",
"flow-error-invalid-moderation-reason": "조정의 이유를 알려주세요.",
"flow-error-not-allowed": "이 명령을 실행할 권한이 부족합니다.",
@@ -141,12 +177,16 @@
"flow-error-not-allowed-reply-to-delete-topic": "이 주제가 삭제되었기 때문에 댓글을 달 수 없습니다.",
"flow-error-not-allowed-suppress": "이 주제는 삭제되었습니다.",
"flow-error-not-allowed-reply-to-suppress-topic": "이 주제가 삭제되었기 때문에 댓글을 달 수 없습니다.",
+ "flow-error-not-allowed-hide-extract": "이 주제는 숨겨졌습니다. 주제의 숨김 기록은 다음 참고에 제공됩니다.",
+ "flow-error-not-allowed-delete-extract": "이 주제는 삭제되었습니다. 주제의 삭제 기록은 다음 참고에 제공됩니다.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "이 주제가 삭제되었기 때문에 댓글을 달 수 없습니다. 주제의 삭제 기록은 다음 참고에 제공됩니다.",
+ "flow-error-not-allowed-suppress-extract": "이 주제가 삭제되었습니다. 주제의 삭제 기록은 다음 참고에 제공됩니다.",
"flow-error-title-too-long": "주제 제목은 $1 {{PLURAL:$1|바이트}}로 제한됩니다.",
"flow-error-no-existing-workflow": "이 워크플로우는 아직 존재하지 않습니다.",
"flow-error-not-a-post": "주제 제목은 기여로 저장할 수 없습니다.",
- "flow-error-missing-header-content": "머릿글에 내용이 없습니다. 머릿글을 저장하려면 내용이 있어야 합니다.",
+ "flow-error-missing-header-content": "설명을 입력해야 합니다.",
"flow-error-missing-prev-revision-identifier": "이전 판 식별자가 없습니다.",
- "flow-error-prev-revision-mismatch": "다른 사용자가 이 게시물을 조금 전에 편집했습니다. 최근 바뀜을 덮어쓰시겠습니까?",
+ "flow-error-prev-revision-mismatch": "다른 사용자가 이 게시물을 조금 전에 편집했습니다. {{GENDER:$3}}최근 바뀜을 덮어쓰시겠습니까?",
"flow-error-prev-revision-does-not-exist": "이전 판을 찾을 수 없습니다.",
"flow-error-default": "오류가 발생했습니다.",
"flow-error-invalid-input": "유효하지 않은 값은 플로우 콘텐츠를 불러오기 위해 입력됩니다.",
@@ -162,32 +202,43 @@
"flow-error-process-data": "당신의 요청 데이터를 처리하는 도중 오류가 발생했습니다.",
"flow-error-process-wikitext": "HTML/위키텍스트 대화를 처리하는 도중 오류가 발생했습니다.",
"flow-error-no-index": "데이터 검색을 수행하기 위한 인덱스를 찾는 데 실패했습니다.",
- "flow-error-move-topic": "토픽 문서 옮기기는 현재 지원되지 않습니다.",
+ "flow-error-content-too-long": "내용이 너무 큽니다. 확장 후의 내용은 $1 {{PLURAL:$1|바이트}}로 제한됩니다.",
+ "flow-error-move-topic": "주제 문서 이동은 현재 지원되지 않습니다.",
+ "flow-error-invalid-topic-uuid-title": "잘못된 제목",
+ "flow-error-invalid-topic-uuid": "요청된 문서의 제목은 유효하지 않습니다. 주제 이름공간은 자동적으로 플로가 생성합니다.",
"flow-error-unknown-workflow-id-title": "알 수 없는 주제",
"flow-error-unknown-workflow-id": "요청된 주제는 존재하지 않습니다.",
+ "flow-error-search": "일시적인 문제 때문에 검색을 완료할 수 없습니다. 나중에 다시 시도하세요.",
+ "flow-error-invalid-undelete": "현재 토론 게시판이 존재하기 때문에 문서를 복구할 수 없습니다.",
+ "flow-edit-header-placeholder": "이 토론 게시판을 설명하기",
"flow-edit-header-submit": "설명을 저장",
+ "flow-edit-header-submit-anonymously": "익명으로 설명을 저장",
"flow-edit-title-submit": "제목 바꾸기",
- "flow-edit-post-submit": "변경된 내용을 제출합니다",
- "flow-rev-message-edit-post": "$1 사용자가 \"$4\"의 [$3 댓글]을 {{GENDER:$2|편집했습니다}}",
+ "flow-edit-title-submit-anonymously": "익명으로 제목을 바꿈",
+ "flow-edit-post-submit": "바뀐 내용 제출",
+ "flow-edit-post-submit-anonymously": "익명으로 편집 제출",
+ "flow-rev-message-edit-post": "$1님이 \"$4\"의 [$3 댓글]을 {{GENDER:$2|편집했습니다}}",
"flow-rev-message-edit-post-recentchanges-summary": "게시물을 {{GENDER:$2|편집했습니다}}",
- "flow-rev-message-reply": "$1 사용자가 \"$4\"에 [$3 {{GENDER:$2|댓글을 남겼습니다}}] (<em>$5</em>)",
+ "flow-rev-message-reply": "$1님이 \"$4\"에 [$3 {{GENDER:$2|댓글을 남겼습니다}}] (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|개의 댓글}}</strong>이 추가{{PLURAL:$1|되었습니다}}",
- "flow-rev-message-new-post": "$1 사용자가 \"[$3 $4]\" 주제를 {{GENDER:$2|만들었습니다}}.",
+ "flow-rev-message-new-post": "$1님이 \"[$3 $4]\" 주제를 {{GENDER:$2|만들었습니다}}",
"flow-rev-message-new-post-recentchanges-summary": "새 주제를 {{GENDER:$2|만들었습니다}}",
- "flow-rev-message-edit-title": "$1 사용자가 \"$5\"에서 \"[$3 $4]\"(으)로 주제의 제목을 {{GENDER:$2|바꾸었습니다}}.",
- "flow-rev-message-create-header": "$1 사용자가 설명을 {{GENDER:$2|만들었습니다}}",
- "flow-rev-message-edit-header": "$1 사용자가 설명을 {{GENDER:$2|편집했습니다}}",
- "flow-rev-message-create-topic-summary": "$1 사용자가 $3 주제의 주제 요약을 {{GENDER:$2|만들었습니다}}",
- "flow-rev-message-edit-topic-summary": "$1 사용자가 $3 의 주제 요약을 {{GENDER:$2|편집했습니다}}",
- "flow-rev-message-hid-post": "$1 사용자가 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|숨겼습니다}} (<em>$5</em>)",
- "flow-rev-message-deleted-post": "$1 사용자가 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|삭제했습니다}} (<em>$5</em>)",
- "flow-rev-message-suppressed-post": "$1 사용자가 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|표시 안하도록 했습니다}} (<em>$5</em>)",
- "flow-rev-message-restored-post": "$1 사용자가 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|되살렸습니다}} (<em>$5</em>)",
- "flow-rev-message-hid-topic": "$1 사용자가 \"$6\"의 [$4 주제]를 {{GENDER:$2|숨겼습니다}} (<em>$5</em>)",
- "flow-rev-message-deleted-topic": "$1 사용자가 \"$6\"의 [$4 주제]를 {{GENDER:$2|삭제했습니다}} (<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1 사용자가 \"$6\"의 [$4 주제]를 {{GENDER:$2|표시 안하도록 했습니다}} (<em>$5</em>)",
+ "flow-rev-message-edit-title": "$1님이 \"$5\"에서 \"[$3 $4]\"(으)로 주제 제목을 {{GENDER:$2|바꾸었습니다}}",
+ "flow-rev-message-create-header": "$1님이 설명을 {{GENDER:$2|만들었습니다}}",
+ "flow-rev-message-edit-header": "$1님이 설명을 {{GENDER:$2|편집했습니다}}",
+ "flow-rev-message-create-topic-summary": "$1님이 $3 주제의 주제 요약을 {{GENDER:$2|만들었습니다}}",
+ "flow-rev-message-edit-topic-summary": "$1님이 $3의 주제 요약을 {{GENDER:$2|편집했습니다}}",
+ "flow-rev-message-hid-post": "$1님이 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|숨겼습니다}} (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1님이 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|삭제했습니다}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1님이 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|표시하지 않도록 했습니다}} (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1님이 \"$6\"에서 [$4 댓글]을 {{GENDER:$2|되살렸습니다}} (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1님이 \"$6\"의 [$4 주제]를 {{GENDER:$2|숨겼습니다}} (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1님이 \"$6\"의 [$4 주제]를 {{GENDER:$2|삭제했습니다}} (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1님이 \"$6\"의 [$4 주제]를 {{GENDER:$2|표시하지 않도록 했습니다}} (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1님이 [$4 주제] \"$6\"을(를) 해결됨으로 {{GENDER:$2|표시했습니다}} (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "해결한 것으로 표시함",
- "flow-rev-message-restored-topic": "$1 사용자가 \"$6\"의 [$4 주제]를 {{GENDER:$2|되살렸습니다}} (<em>$5</em>)",
+ "flow-rev-message-restore-topic-reason": "다시 열림",
+ "flow-rev-message-restored-topic": "$1님이 \"$6\"의 [$4 주제]를 {{GENDER:$2|되살렸습니다}} (<em>$5</em>)",
"flow-rc-topic-of-board": "$2의 $1",
"flow-board-history": "\"$1\" 역사",
"flow-board-history-empty": "이 판에는 현재 역사가 없습니다.",
@@ -200,41 +251,67 @@
"flow-history-pages-post": "[$1 $2]에 나타납니다",
"flow-topic-comments": "{{PLURAL:$1|댓글 $1개|0=첫 댓글을 {{GENDER:$2|남기세요}}!}}",
"flow-show-comments-title": "{{PLURAL:$1|댓글 보기}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|댓글 숨기기}}",
"flow-comment-restored": "복원된 댓글",
"flow-comment-deleted": "삭제된 댓글",
"flow-comment-hidden": "숨긴 댓글",
"flow-comment-moderated": "검토 의견",
"flow-last-modified": "$1에 대한 마지막 수정",
"flow-workflow": "워크플로우",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 사용자가 '''$4'''에 {{GENDER:$1|답변을 남겼습니다}}.",
- "flow-notification-reply-bundle": "$1 사용자와 $5 {{PLURAL:$6|그 외 사용자}}가 당신이 \"$3\"에 남긴 <span class=\"plainlinks\">[$4 게시물] $2</span>에 {{GENDER:$1|답변을 남겼습니다}}.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1님이 <strong>$4</strong>에 {{GENDER:$1|답변을 남겼습니다}}.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1님과 {{PLURAL:$5|다른 사용자 한 명|다른 사용자 $5명|100=다른 사용자 99명 이상}}이 <strong>$3</strong>에 {{GENDER:$1|답변을 남겼습니다}}.",
"flow-notification-edit": "$1 [[$3|$4]]에 남긴 <span class=\"plainlinks\">[$5 게시물]</span> $2을 {{GENDER:$1|편집했습니다}}.",
- "flow-notification-edit-bundle": "$1 사용자와 $5 {{PLURAL:$6|그 외 사용자}}가 당신이 \"$3\"에 남긴 <span class=\"plainlinks\">[$4 게시물]</span> $2을 {{GENDER:$1|편집했습니다}}.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 사용자가 '''$3'''에 새 주제를 {{GENDER:$1|만들었습니다}}.",
- "flow-notification-rename": "$1 사용자가 [[$5|$6]]의 <span class=\"plainlinks\">[$2 $3]</span>의 제목을 \"$4\"으로 {{GENDER:$1|바꿨습니다}}.",
- "flow-notification-mention": "$1 사용자가 \"$4\"의 \"$3\" {{GENDER:$1|}} <span class=\"plainlinks\">[$2 게시물]</span>에서 {{GENDER:$5|당신을}} {{GENDER:$1|언급했습니다}}.",
+ "flow-notification-edit-bundle": "$1님과 {{PLURAL:$5|다른 사용자 한 명|다른 사용자 $5명|100=다른 사용자 99명 이상}}이 \"$3\"의 \"$2\"에서 <span class=\"plainlinks\">[$4 게시물]</span> $2을 {{GENDER:$1|편집했습니다}}.",
+ "notification-header-flow-post-reply": "$1님이 \"<strong>$4</strong>\"에서 {{GENDER:$2|답변을 남겼습니다}}.",
+ "notification-header-flow-post-edited-v2": "\"<strong>$1</strong>\"에서 {{GENDER:$2|당신의}} 게시물이 편집되었습니다.",
+ "notification-bundle-header-flow-post-edited-v2": "\"<strong>$1</strong>\"에서 {{GENDER:$2|당신의}} 게시물이 여러 번 편집되었습니다.",
+ "notification-header-flow-summary-edited": "\"<strong>$1</strong>\"의 요약이 갱신되었습니다.",
+ "notification-header-flow-summary-edited-first": "\"<strong>$1</strong>\" 주제가 요약되었습니다.",
+ "notification-bundle-header-flow-summary-edited": "\"<strong>$1</strong>\"의 요약이 여러 번 갱신되었습니다.",
+ "notification-email-subject-flow-summary-edited": "$1님이 $2의 요약을 {{GENDER:$1|갱신했습니다}}.",
+ "notification-email-batch-body-flow-summary-edited": "$1님이 $2의 요약을 {{GENDER:$1|갱신했습니다}}.",
+ "notification-header-flow-mention-post": "$1님이 \"<strong>$5</strong>\"에서 {{GENDER:$4|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-flow-mention-header": "$1님이 <strong>$3</strong>의 설명에서 {{GENDER:$4|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-flow-mention-post-summary": "$1님이 \"<strong>$5</strong>\"에서 {{GENDER:$4|당신을}} {{GENDER:$2|언급했습니다}}.",
+ "notification-header-flow-description-edited": "<strong>$1</strong>의 설명이 편집되었습니다.",
+ "notification-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|당신의}} 토론 문서</strong>의 설명이 편집되었습니다.",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong>의 설명이 여러 번 편집되었습니다.",
+ "notification-links-flow-description-edited-view-page": "문서 {{GENDER:$1|보기}}",
+ "notification-email-subject-flow-description-edited": "$1님이 $2의 설명을 {{GENDER:$1|편집했습니다}}.",
+ "notification-email-batch-body-flow-description-edited": "$1님이 $2의 설명을 {{GENDER:$2|편집했습니다}}",
+ "notification-header-flow-topic-resolved": "\"<strong>$1</strong>\" 주제가 해결되었습니다.",
+ "notification-header-flow-topic-reopened": "\"<strong>$1</strong>\" 주제가 다시 열렸습니다.",
+ "notification-header-flow-topic-resolved-user-talk": "<strong>당신의 토론 문서</strong>의 \"<strong>$1</strong>\" 주제가 해결되었습니다.",
+ "notification-header-flow-topic-reopened-user-talk": "<strong>당신의 토론 문서</strong>의 \"<strong>$1</strong>\" 주제가 다시 열렸습니다.",
+ "notification-email-subject-flow-topic-resolved": "\"<strong>$2</strong>\" 주제가 해결되었습니다.",
+ "notification-email-batch-body-flow-topic-resolved": "\"<strong>$2</strong>\" 주제가 해결되었습니다.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1님이 <strong>$3</strong>에 새 주제를 {{GENDER:$1|만들었습니다}}.",
+ "flow-notification-rename": "$1님이 [[$5|$6]]에서 <span class=\"plainlinks\">[$2 $3]</span>의 제목을 \"$4\"(으)로 {{GENDER:$1|바꾸었습니다}}.",
+ "flow-notification-mention": "$1님이 \"$4\"의 \"$3\"에서의 {{GENDER:$1|}}<span class=\"plainlinks\">[$2 게시물]</span>에서 {{GENDER:$5|당신을}} {{GENDER:$1|언급했습니다}}.",
"flow-notification-link-text-view-post": "게시물 보기",
"flow-notification-link-text-view-topic": "주제 보기",
+ "flow-notification-link-text-view-topics": "목차 보기",
"flow-notification-reply-email-subject": "$3의 $2",
- "flow-notification-reply-email-batch-body": "$1 사용자가 $3에 있는 \"$2\" 주제의 당신의 게시물에 {{GENDER:$1|답변을 남겼습니다}}.",
- "flow-notification-reply-email-batch-bundle-body": "$1 사용자 외 $4명의 {{PLURAL:$5|사용자}}가 $3에 남긴 \"$2\" 주제에 {{GENDER:$1|답변을 남겼습니다}}.",
- "flow-notification-mention-email-subject": "$1 사용자가 $2에서 {{GENDER:$3|당신}}을 {{GENDER:$1|언급했습니다}}.",
- "flow-notification-mention-email-batch-body": "$1 사용자가 {{GENDER:$4|당신}}을 $3에 있는 {{GENDER:$1|그의}} \"$2\" 게시물에 {{GENDER:$1|언급했습니다}}.",
- "flow-notification-edit-email-subject": "$1 사용자가 게시물을 {{GENDER:$1|편집했습니다}}",
- "flow-notification-edit-email-batch-body": "$1 사용자가 $3에 있는 \"$2\"의 게시물을 {{GENDER:$1|편집했습니다}}",
- "flow-notification-edit-email-batch-bundle-body": "$1 사용자와 $4 {{PLURAL:$5|그 외 사용자}}가 당신이 $3에 있는 \"$2\" [$4 게시물]을 {{GENDER:$1|편집했습니다}}.",
- "flow-notification-rename-email-subject": "$1 이 당신의 주제를 바꾸었습니다.",
- "flow-notification-rename-email-batch-body": "$1 사용자가 $4에 있는 당신의 \"$2\" 주제를 \"$3\"으로 {{GENDER:$1|이름을 바꿨습니다}}",
- "flow-notification-newtopic-email-subject": "$1 사용자가 $2의 새 주제를 {{GENDER:$1|만들었습니다}}",
- "flow-notification-newtopic-email-batch-body": "$1 사용자가 $3의 \"$2\" 문서와 새 주제를 {{GENDER:$1|만들었습니다}}",
- "echo-category-title-flow-discussion": "플로우",
- "echo-pref-tooltip-flow-discussion": "플로우에 나와 관련된 명령을 알림",
+ "flow-notification-reply-email-batch-body": "$1님이 $3에 있는 \"$2\" 주제의 당신의 게시물에 {{GENDER:$1|답변을 남겼습니다}}.",
+ "flow-notification-reply-email-batch-bundle-body": "$1님과 {{PLURAL:$4|다른 사용자 한 명|다른 사용자 $4명|100=다른 사용자 99명 이상}}이 $3에 남긴 \"$2\" 주제에 {{GENDER:$1|답변을 남겼습니다}}.",
+ "flow-notification-mention-email-subject": "$1님이 $2에서 {{GENDER:$3|당신}}을 {{GENDER:$1|언급했습니다}}.",
+ "flow-notification-mention-email-batch-body": "$1님이 $3에 있는 {{GENDER:$1}}\"$2\" 게시물에서 {{GENDER:$4|당신}}을 {{GENDER:$1|언급했습니다}}.",
+ "flow-notification-edit-email-subject": "$1님이 게시물을 {{GENDER:$1|편집했습니다}}",
+ "flow-notification-edit-email-batch-body": "$1님이 $3에 있는 \"$2\"의 게시물을 {{GENDER:$1|편집했습니다}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1님과 {{PLURAL:$4|다른 사용자 한 명|다른 사용자 $4명|100=다른 사용자 99명 이상}}이 $3의 \"$2\"에서 게시물을 {{GENDER:$1|편집했습니다}}.",
+ "flow-notification-rename-email-subject": "$1님이 당신의 주제의 {{GENDER:$1|이름을 바꾸었습니다}}",
+ "flow-notification-rename-email-batch-body": "$1님이 $4에서 당신의 주제의 이름을 \"$2\"에서 \"$3\"(으)로 {{GENDER:$1|바꾸었습니다}}",
+ "flow-notification-newtopic-email-subject": "$1님이 $2의 새 주제를 {{GENDER:$1|만들었습니다}}",
+ "flow-notification-newtopic-email-batch-body": "$1님이 $3의 \"$2\" 제목으로 된 새 주제를 {{GENDER:$1|만들었습니다}}",
+ "echo-category-title-flow-discussion": "플로우 토론",
+ "echo-pref-tooltip-flow-discussion": "플로우에 나와 관련된 명령을 알립니다.",
"flow-link-post": "게시물",
"flow-link-topic": "주제",
"flow-link-history": "역사",
"flow-link-post-revision": "게시물의 판",
"flow-link-topic-revision": "주제의 판",
- "flow-link-header-revision": "헤더 판",
+ "flow-link-header-revision": "설명 판",
+ "flow-link-summary-revision": "편집 요약 판",
"flow-moderation-title-suppress-post": "게시물을 숨기시겠습니까?",
"flow-moderation-title-delete-post": "게시물을 삭제하시겠습니까?",
"flow-moderation-title-hide-post": "게시물을 표시 안 함으로 설정하시겠습니까?",
@@ -259,18 +336,18 @@
"flow-moderation-confirm-unsuppress-topic": "숨김 해제",
"flow-moderation-confirm-undelete-topic": "삭제 취소",
"flow-moderation-confirm-unhide-topic": "숨기기 취소",
- "flow-moderation-confirmation-suppress-post": "게시물 숨김에 성공하였습니다. 이 게시물에 대한 피드백을 $1 사용자에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
- "flow-moderation-confirmation-delete-post": "게시물 삭제에 성공하였습니다. 이 게시물에 대한 피드백을 $1 사용자에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
- "flow-moderation-confirmation-hide-post": "게시물을 표시 안 함으로 설정하는 데 성공하였습니다. 이 게시물에 대한 피드백을 $1 사용자에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
- "flow-moderation-confirmation-unsuppress-post": "위의 게시물을 성공적으로 보여주기했습니다.",
- "flow-moderation-confirmation-undelete-post": "위의 게시물을 성공적으로 보여주기했습니다.",
- "flow-moderation-confirmation-unhide-post": "위의 게시물을 성공적으로 표시했습니다.",
+ "flow-moderation-confirmation-suppress-post": "게시물을 숨겼습니다.\n이 게시물에 대한 피드백을 $1님에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
+ "flow-moderation-confirmation-delete-post": "게시물을 삭제했습니다.\n이 게시물에 대한 피드백을 $1님에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
+ "flow-moderation-confirmation-hide-post": "게시물을 표시 안 함으로 설정했습니다.\n이 게시물에 대한 피드백을 $1님에게 주는 것을 {{GENDER:$2|고려해주세요}}.",
+ "flow-moderation-confirmation-unsuppress-post": "위의 게시물을 보여주기했습니다.",
+ "flow-moderation-confirmation-undelete-post": "위의 게시물을 보여주기했습니다.",
+ "flow-moderation-confirmation-unhide-post": "위의 게시물을 표시했습니다.",
"flow-moderation-confirmation-suppress-topic": "주제 숨김에 성공했습니다.",
"flow-moderation-confirmation-delete-topic": "주제 삭제에 성공하였습니다.",
"flow-moderation-confirmation-hide-topic": "이 주제는 숨겨졌습니다.",
- "flow-moderation-confirmation-unsuppress-topic": "이 게시물을 성공적으로 숨김 해제했습니다.",
- "flow-moderation-confirmation-undelete-topic": "이 게시물을 성공적으로 복원했습니다.",
- "flow-moderation-confirmation-unhide-topic": "이 게시물을 성공적으로 표시했습니다.",
+ "flow-moderation-confirmation-unsuppress-topic": "이 게시물을 숨김 해제했습니다.",
+ "flow-moderation-confirmation-undelete-topic": "이 게시물을 복원했습니다.",
+ "flow-moderation-confirmation-unhide-topic": "이 게시물을 표시했습니다.",
"flow-moderation-title-suppress-topic": "주제를 숨기겠습니까?",
"flow-moderation-title-delete-topic": "주제를 삭제하겠습니까?",
"flow-moderation-title-hide-topic": "주제를 숨기겠습니까?",
@@ -285,17 +362,17 @@
"flow-moderation-placeholder-unhide-topic": "이 주제를 보이는 이유를 {{GENDER:$3|설명해주세요}}.",
"flow-topic-permalink-warning": "이 주제는 [$2 $1]에 시작됐습니다",
"flow-topic-permalink-warning-user-board": "이 주제는 [$2 {{GENDER:$1|$1}}의 게시판]에서 시작됐습니다",
- "flow-revision-permalink-warning-post": "이 게시물의 하나의 판에 대한 영구 링크 입니다.\n이 판은 $1에서 가져왔습니다.\n[$5 이전 판]나 [$4 게시물 역사 문서]의 다른 판과의 차이를 볼 수 있습니다.",
+ "flow-revision-permalink-warning-post": "이 게시물의 하나의 판에 대한 영구 링크입니다.\n이 판은 $1에서 가져왔습니다.\n[$5 이전 판과의 차이]나 [$4 게시물 역사 문서]의 다른 판과의 차이를 볼 수 있습니다.",
"flow-revision-permalink-warning-post-first": "이 게시물의 첫 번째 판으로 연결된 영구 링크입니다.\n[$4 게시물 역사 문서]에서 이후의 판을 볼 수 있습니다.",
"flow-revision-permalink-warning-postsummary": "이 요약에 대한 고유링크입니다. 이 버전은 $1 에서 가져왔습니다.\n[$5 이전 버전과의 차이]를 보거나, [$4 역사]에서 다른 버전을 볼 수 있습니다.",
"flow-revision-permalink-warning-postsummary-first": "이 요약의 첫 판에 대한 고유링크입니다. [$4 역사]에서 이후의 버전을 볼 수 있습니다.",
- "flow-revision-permalink-warning-header": "이 링크는 헤더에 대한 고유 링크입니다.\n이 판은 $1에서 가져왔습니다. [$3 이전 판과의 차이]를 보거나, [$2 역사]에서 다른 판을 볼 수 있습니다.",
- "flow-revision-permalink-warning-header-first": "이것은 헤더의 첫 판에 대한 고유링크입니다. 이후 버전은 [$2 역사 문서]에서 볼 수 있습니다.",
- "flow-compare-revisions-revision-header": "$1에 {{GENDER:$2|$2}} 사용자가 작성한 판",
- "flow-compare-revisions-header-post": "이 문서는 $3 사용자가 [$4 $1]의 \"[$5 $2]\" 주제의 게시물의 두 판 사이의 {{GENDER:$3|차이}}를 보여줍니다.\n[$6 역사 문서]에서 이 게시물의 다른 판을 볼 수 있습니다.",
- "flow-compare-revisions-header-postsummary": "이 문서는 [$3 $1]의 \"[$4 $2]\" 주제의 게시글 요약의 두 판 사이의 차이를 보여줍니다.\n[$5 역사]에서 이 게시물의 다른 판을 볼 수 있습니다.",
- "flow-compare-revisions-header-header": "이 문서는 [$3 $1] 헤더의 {{GENDER:$2|차이}}를 보여주고 있습니다. [$4 역사 문서]에서 다른 판을 볼 수 있습니다.",
- "action-flow-create-board": "임의 장소에서 플로우 게시물 만들기",
+ "flow-revision-permalink-warning-header": "이 링크는 설명에 대한 고유 링크입니다.\n이 판은 $1에서 가져왔습니다. [$3 이전 판과의 차이]를 보거나, [$2 역사]에서 다른 판을 볼 수 있습니다.",
+ "flow-revision-permalink-warning-header-first": "이것은 설명의 첫 판에 대한 고유링크입니다. 이후 버전은 [$2 역사 문서]에서 볼 수 있습니다.",
+ "flow-compare-revisions-revision-header": "$1에 {{GENDER:$2|$2}}님이 작성한 판",
+ "flow-compare-revisions-header-post": "이 문서는 $3님이 [$4 $1]의 \"[$5 $2]\" 주제의 게시물의 두 판 사이의 {{GENDER:$3|차이}}를 보여줍니다.\n[$6 역사 문서]에서 이 게시물의 다른 판을 볼 수 있습니다.",
+ "flow-compare-revisions-header-postsummary": "이 문서는 [$3 $1]의 \"[$4 $2]\" 주제의 요약의 두 판 사이의 차이를 보여줍니다.\n[$5 역사 문서]에서 이 게시물의 다른 판을 볼 수 있습니다.",
+ "flow-compare-revisions-header-header": "이 문서는 [$3 $1] 설명의 {{GENDER:$2|차이}}를 보여주고 있습니다. [$4 역사 문서]에서 다른 판을 볼 수 있습니다.",
+ "action-flow-create-board": "임의 장소에서 플로우 게시판 만들기",
"right-flow-create-board": "임의 장소에서 플로우 게시물 만들기",
"right-flow-hide": "플로우 주제와 게시물 숨기기",
"right-flow-lock": "플로우 주제를 해결한 것으로 표시",
@@ -322,33 +399,28 @@
"flow-whatlinkshere-post": "[$1 게시글]에서",
"flow-whatlinkshere-header": "[$1 설명]에서",
"flow-whatlinkshere-post-summary": "[$1 요약]에서",
- "flow": "플로우",
+ "structureddiscussions": "플로우",
"flow-special-desc": "이 특수문서는 UUID를 플로우 워크플로우 혹은 플로우 문서로 넘겨줍니다.",
"flow-special-type": "종류",
"flow-special-type-post": "게시글",
"flow-special-type-workflow": "워크플로우",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "종류와 UUID에 맞는 콘텐츠를 찾을 수 없습니다.",
+ "flow-special-enableflow-board-already-exists": "[[$1]]에 이미 플로우 게시판이 있습니다.",
"flow-special-enableflow-invalid-title": "유효하지 않은 페이지 제목이 제공되었습니다.",
- "flow-special-enableflow-board-creation-not-allowed": "[[:$1]]에서 플로우 게시물을 만들 수 없습니다.",
+ "flow-special-enableflow-board-creation-not-allowed": "[[:$1]]에서 플로우 게시판을 만들 수 없습니다.",
"flow-special-enableflow-page-is-liquidthreads": "[[:$1]]의 LiquidThreads 문서입니다.",
- "flow-special-enableflow-confirmation": "[[$1]]의 플로우 게시물을 성공적으로 만들었습니다.",
+ "flow-special-enableflow-confirmation": "[[$1]]의 플로 게시판을 만들었습니다.",
+ "flow-spam-confirmedit-form": "아래 캡차를 풀어 당신이 사람임을 보여주세요: $1",
+ "flow-spam-confirmedit-using-failure": "캡차에 기술적인 오류가 있었습니다. 변경 내용을 저장할 수 없으면 본문을 복사하고 다시 불러온 다음 다시 시도해 주십시오.",
+ "flow-embedding-unsupported": "토론에는 아직 넣을 수 없습니다.",
"flow-post-undo-hide": "숨기기 취소",
"flow-post-undo-delete": "삭제 취소",
"flow-topic-undo-hide": "숨기기 취소",
"flow-topic-undo-delete": "삭제 취소",
- "apihelp-flow+edit-post-example-1": "[[Topic:S2tycnas4hcucw8w]]에서 게시물을 편집합니다",
- "apihelp-flow+edit-title-description": "주제의 제목을 편집합니다.",
- "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] 잠그기",
- "apihelp-flow+view-topic-description": "주제를 봅니다.",
- "apihelp-flow+view-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] 보기",
- "apihelp-flow+view-topic-summary-description": "주제 요약을 봅니다.",
- "apihelp-flow+view-topiclist-description": "주제 목록을 봅니다.",
- "apihelp-flow+undo-edit-post-description": "포스트 편집을 취소하기 위해 필요한 정보를 검색합니다.",
- "apihelp-flow+undo-edit-post-param-postId": "포스트 아이디는 취소할수 있습니다.",
- "apihelp-flow+undo-edit-post-param-endId": "끝으로 아이디 수정이 취소되었습니다.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "계정 아이디 취소를 시작합니다.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "끝으로 아이디 수정이 취소되었습니다.",
+ "flow-importer-lqt-moved-thread-template-content": "{{{author}}}님의 이 게시물이 {{{date}}}에 이동되었습니다. [[{{{title}}}]]에서 찾을 수 있습니다.",
+ "flow-importer-lqt-converted-template": "LQT 문서가 플로우로 변환되었습니다",
+ "flow-importer-lqt-converted-archive-template": "변환된 LQT 문서의 보존문서",
"flow-edited": "편집됨",
"flow-edited-by": "$1에 의해 편집됨",
"flow-talk-conversion-archive-edit-reason": "위키텍스트 토론을 Flow로 변환",
@@ -360,8 +432,8 @@
"flow-undo-edit-header": "설명 편집",
"flow-undo-edit-topic-summary": "주제 요약 편집",
"flow-undo-edit-post": "포스트 수정",
- "flow-undo-edit-content": "편집은 취소할수 있습니다. 당신이 무엇을 하려는지 확인 하고 편집을 취소 하려면 아래의 변경 사항을 확인 하시기 바랍니다.",
- "flow-undo-edit-failure": "중간 충돌 편집으로 인해 편집을 취소 할수 없습니다.",
+ "flow-undo-edit-content": "이 편집은 취소할 수 있습니다. 아래의 비교를 확인하여 정말 사용자가 바라던 편집인지 살펴보시고, 편집을 취소하려면 아래의 바뀐 내용을 저장하십시오.",
+ "flow-undo-edit-failure": "중간 충돌 편집으로 인해 편집을 취소할 수 없습니다.",
"group-flow-bot": "플로 봇",
"group-flow-bot-member": "플로 봇",
"grouppage-flow-bot": "Project:플로 봇",
@@ -373,10 +445,26 @@
"flow-ve-mention-inspector-invalid-user": "\"$1\" 계정명은 등록되어 있지 않습니다.",
"flow-wikitext-editor-help": "위키텍스트 $1",
"flow-wikitext-editor-help-preview-the-result": "결과 미리 보기",
- "flow-wikitext-switch-editor-tooltip": "시각편집기로 변환",
+ "flow-wikitext-switch-editor-tooltip": "시각편집기로 전환",
"flow-ve-switch-editor-tool-title": "위키텍스트 편집기로 전환",
"flow-mark-revision-patrolled-link-text": "이 문서를 점검한 것으로 표시",
"flow-mark-revision-patrolled-link-title": "이 문서를 점검한 것으로 표시",
"flow-mark-diff-patrolled-link-text": "점검한 문서로 표시",
- "flow-mark-diff-patrolled-link-title": "점검한 문서로 표시"
+ "flow-mark-diff-patrolled-link-title": "점검한 문서로 표시",
+ "flow-talk-page-beta-feature-message": "사용자토론의 플로우",
+ "flow-talk-page-beta-feature-description": "{{GENDER:|사용자의}} 사용자 토론 문서에 구조화된 새 토론을 활성화합니다. 플로우는 글을 쓰고 답변하는 장소가 명료해지는 것과 더불어 토론 문서의 토론을 단순하게 만들어 주며, 대화 수준의 알림을 가능하게 합니다. 기존의 위키텍스트 토론들은 보관 장소로 이동됩니다. 이 기능은 자동으로 활성화되지 않으므로 사용자들은 직접 이 기능을 활성화해야 합니다. 이 기능을 사용하지 않으면 플로우 게시판을 하위 문서로 이동하고 이전의 토론 문서의 보관을 해제합니다.",
+ "flow-notification-link-text-enabled-on-talkpage": "사용자토론 문서 {{GENDER:|보기}}",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "$2의 새 토론 시스템",
+ "flow-beta-feature-add-archive-template-edit-summary": "보존 틀 추가",
+ "flow-beta-feature-remove-archive-template-edit-summary": "보존 틀 제거",
+ "flow-dialog-cancelconfirm-title": "확실합니까?",
+ "flow-dialog-cancelconfirm-message": "우선 저장을 하지 않고 취소하시겠습니까?",
+ "flow-dialog-cancelconfirm-keep": "편집 계속",
+ "flow-dialog-cancelconfirm-discard": "바뀜 버리기",
+ "flow-optin-restore-wikitext": "보존된 위키텍스트 문서를 복구합니다.",
+ "flow-optin-restore-flow-board": "보존된 토론 게시판을 복구합니다.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|당신의}} 새 사용자토론 문서에 오신 것을 {{GENDER:$1|환영합니다}}",
+ "flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|나의}} 오래된 대화 찾기",
+ "flow-guidedtour-optin-find-old-conversations-description": "이전 대화는 보존 문서로 이동되었습니다.",
+ "flow-guidedtour-optin-feedback": "{{GENDER:$1|여러분의}} 의견을 주세요!"
}
diff --git a/Flow/i18n/krl.json b/Flow/i18n/krl.json
new file mode 100644
index 00000000..69f5f514
--- /dev/null
+++ b/Flow/i18n/krl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "flow-post-action-edit-post": "Kohentele"
+}
diff --git a/Flow/i18n/ksh.json b/Flow/i18n/ksh.json
index 9cfd90cf..b40639d6 100644
--- a/Flow/i18n/ksh.json
+++ b/Flow/i18n/ksh.json
@@ -1,14 +1,50 @@
{
"@metadata": {
"authors": [
- "Purodha"
+ "Purodha",
+ "Nnemo",
+ "Quiddity"
]
},
"flow-desc": "Süstehm för de Ärbeid iere Verlouf ze verwallde",
- "flow-edit-header-link": "Dä Kopp verändere",
+ "logentry-delete-flow-delete-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät [$4 ene Beijdrahch] zom Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ fottjeschmeße",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd ene Beidrrach zum Tehma $3 fott jeschmeße.",
+ "logentry-delete-flow-restore-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät [$4 ene Beijdrahch] zom Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ wider zerökjehollt",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd ene Beijdraach zoh enem Tehma op dä Sigg $3 wider zerök jehollt.",
+ "logentry-suppress-flow-suppress-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät [$4 ene Beijdrahch] zom Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ verschtoche",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd ene Beijdraach zoh enem Tehma op dä Sigg $3 ongerdrök.",
+ "logentry-suppress-flow-restore-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät [$4 ene Beijdrahch] zom Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ fottjeschmeße",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd ene Beijdraach zoh enem Tehma op dä Sigg $3 fott jeschmeße.",
+ "logentry-delete-flow-delete-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ fottjeschmeße",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 fott jeschmeße.",
+ "logentry-delete-flow-restore-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ wider zerökjehollt",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 wider zerök jehollt.",
+ "logentry-suppress-flow-suppress-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ verschtoche",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 ongerdrök.",
+ "logentry-suppress-flow-restore-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat Tehma „[[$3|$5]]“ op dä Klaafsigg „[[$6]]“ fottjeschmeße",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 fott jeschmeße.",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 älehdesch makkehrt.",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "{{GENDER:$2|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher|De Metmaacherėn|Dä Metmaacher}} $1 hädd e Tehma op dä Sigg $3 wider op jemaat.",
+ "flow-user-moderated": "Ene modderehrte Metmaacher",
+ "flow-board-header-browse-topics-link": "En de Tehme bläddere",
+ "flow-board-header": "Övver di Klaafsigg heh",
+ "flow-board-description-can-not-edit": "Kam_mer nit verändere",
+ "flow-board-collapse-description": "Ußblände",
+ "flow-board-expand-description": "Ennblände",
+ "flow-topic-collapse-siderail": "Met de jannze Beede aanzeije",
+ "flow-topic-expand-siderail": "Med en beschtemmpte Beede aanzeije",
+ "flow-edit-header-link": "De Övverseesch verändere",
"flow-topic-moderated-reason-prefix": "Der Jrond:",
- "flow-suppress-post-content": "Heh di Aanmärkong wood {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} $1 ongerdrök. Loer op de [$2 Verjangeheid].",
+ "flow-hide-title-content": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät heh dat Tehma verschtoche.",
+ "flow-hide-header-content": "{{GENDER:$1|Vum|Vum|Vumm Metmaacher|Vun dä|Vum}} $2 verschtoche.",
+ "flow-delete-title-content": "Heh dat Tehma wood {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} $1 fottjeschmeße.",
+ "flow-delete-header-content": "{{GENDER:$1|Vum|Vum|Vumm Metmaacher|Vun dä|Vum}} $2 fottjeschmeße.",
+ "flow-suppress-post-content": "Heh di Aanmärkong wood {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} $1 ongerdrök. Loer op de [$2 Verjangeheid].!1FUZZY!!",
+ "flow-suppress-title-content": "Heh dat Tehma wood {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} $1 ungerdrök",
+ "flow-suppress-header-content": "{{GENDER:$1|Vum|Vum|Vumm Metmaacher|Vun dä|Vum}} $2 ongerdrök.",
"flow-suppress-usertext": "Däm Metmaacher singe Nahme es ongerdrök",
+ "flow-post-actions": "Akßjuhne",
+ "flow-topic-actions": "Akßjuhne",
"flow-cancel": "Ophühre",
"flow-skip-summary": "Zosammefaßung övverjonn",
"flow-edit-summary-placeholder": "Jivv koot aan, wat bei däm Klaav_eruß_kohm",
@@ -16,77 +52,166 @@
"flow-summary-edited": "De Zesammefaßong wohd et läz {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} $1 beärrbeidt.",
"flow-show-change": "Änderonge aanzeije",
"flow-last-modified-by": "Zeläz verändert {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} „$1“",
+ "flow-stub-post-content": "<span style=\"color:gray\">Wähje enem täschnesche Fähler künne mer op dä Beijdrach jrahd nit zohjrihfe.</span>",
+ "flow-newtopic-title-placeholder": "Neu Tehma",
+ "flow-newtopic-content-placeholder": "Donn ene neuje Beijdraach för $1“ ennjävve",
+ "flow-newtopic-header": "Donn e neu Tehma derbeij",
+ "flow-newtopic-save": "Neu Tehma",
+ "flow-newtopic-save-anonymously": "Donn e neu Tehma derbeij als Nahmelosse",
+ "flow-newtopic-start-placeholder": "Fang e neu Tehma aan",
+ "flow-newtopic-first-heading": "Fang e neu Tehma op „$1“ aan",
+ "flow-summarize-topic-placeholder": "Bes esu johd un donn dä Klaaf zesammefaße",
+ "flow-reply-topic-title-placeholder": "Donn op „$1“ anntwoote",
+ "flow-reply-link": "Anntwoote{{GENDER:$1|}}",
+ "flow-reply-link-anonymously": "onn als nahmelosser anntwoote",
"flow-thank-link": "Lohß Jonn!{{GENDER:$1|}}{{GENDER:$2|}}",
"flow-thank-link-title": "Donn {{GENDER:$2|däm|däm|däm Metmaacher|dä|däm}} öffentlesch dangke, däh dät jeschrevve hät.{{GENDER:$1|}}",
- "flow-history-action-suppress-post": "ongerdrökke",
+ "flow-history-action-suppress-post": "verschteijsche",
"flow-history-action-delete-post": "fottschmiiße",
"flow-history-action-hide-post": "verschteijsche",
- "flow-history-action-unsuppress-post": "nimmih ongerdrökke",
+ "flow-history-action-unsuppress-post": "nimmih verschteijsche",
"flow-history-action-undelete-post": "zerökholle",
"flow-history-action-unhide-post": "nit mih verschteijsche",
"flow-history-action-restore-post": "zeröckholle",
"flow-history-action-lock-topic": "älehdeje",
"flow-history-action-unlock-topic": "widder opmaache",
+ "flow-post-edited": "Ene Beijdraach {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} „$1“ vun $2",
"flow-post-action-view": "Dohrhafte Lengk",
+ "flow-post-action-post-history": "Änderonge",
"flow-post-action-suppress-post": "Ongerdröke",
"flow-post-action-delete-post": "Fottschmiiße",
"flow-post-action-hide-post": "Verschteihsche",
"flow-post-action-edit-post": "Beärbeide",
"flow-post-action-edit-post-submit": "Lohß jonn!",
+ "flow-post-action-edit-post-submit-anonymously": "Donn de Ännderonge er ohne ene Nahme faßhallde",
"flow-post-action-unsuppress-post": "Nimmih ongerdroke",
"flow-post-action-undelete-post": "Zerökholle",
"flow-post-action-unhide-post": "Nit mih verschteische",
+ "flow-post-action-restore-post": "Wider zerök holle",
"flow-post-action-undo-moderation": "Retuhr nämme",
"flow-topic-action-view": "Dohrhafte Lengk",
"flow-topic-action-watchlist": "Oppaßleß",
- "flow-topic-action-edit-title": "De Övverschreff ändere",
+ "flow-topic-action-edit-title": "De Övverschreff änndere",
"flow-topic-action-history": "Väsjohne",
+ "flow-topic-action-hide-topic": "Donn dat Tehma verscheijsche",
+ "flow-topic-action-delete-topic": "Donn dat Tehma fottschmiiße",
"flow-topic-action-lock-topic": "Als älehdesch makkehre",
- "flow-topic-action-unlock-topic": " topic widder opmaache",
+ "flow-topic-action-unlock-topic": "Donn dat Tehma widder opmaache",
"flow-topic-action-summarize-topic": "Zosammefaßße",
- "flow-topic-action-resummarize-topic": "De Zosammefaßßong vum Jähjeschtand ändere",
+ "flow-topic-action-resummarize-topic": "Donn de Zosammefaßßong vum Tehma ändere",
"flow-topic-action-update-topic-summary": "De Zosammefaßong ändere",
+ "flow-topic-action-suppress-topic": "Donn dat Tehma ongerdröke",
+ "flow-topic-action-unhide-topic": "Donn dat Tehma nimmih verschteijsche",
+ "flow-topic-action-undelete-topic": "Donn dat Tehma widder zerök holle",
+ "flow-topic-action-unsuppress-topic": "Donn dat Tehma nit mih ongerdröke",
+ "flow-topic-action-restore-topic": "Donn dat Tehma widder freij jävve",
"flow-topic-action-undo-moderation": "Zeröknämme",
+ "flow-topic-notification-subscribe-title": "Dat Tehma es jäz op Dinge Oppaßleß{{GENDER:$1|}}",
+ "flow-topic-notification-subscribe-description": "Do kriss_en Meddeijlong, för alles, wat e dämm heh Tehma passehrd.{{GENDER:$1|}}",
+ "flow-board-notification-subscribe-title": "Do häs heh dä Klaaf abbonnehrt.{{GENDER:$1|}}",
+ "flow-board-notification-subscribe-description": "Do kriss_en Meddeijlong, wann e neu Tehma op heh dä Klaafsigg opjemaht weed.{{GENDER:$1|}}",
"flow-topic-action-watchlist-add": "Don dat Tehma abbonnehre",
"flow-topic-action-watchlist-remove": "Nit mih Abonehre",
+ "flow-error-allowcreation-no-usedb": "<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">allowCreation</code> bruch dat <var lang=\"en\" xml:lang=\"en\" dir=\"ltr\">$wgContentHandlerUseDB</var> op <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">true</code> jesaz es,",
"flow-error-allowcreation-already-exists": "Di Sigg jidd_et alld, sulld ävver noch nit doh sin.",
"flow-error-allowcreation-flow-create-board": "Dä metmaacher hät nit et Rääsch „{{int:right-flow-create-board}}“",
- "flow-error-other": "Ene Fähler es opjetrodde, woh mer nit met jerääschnet hatte.",
- "flow-error-external": "Ene Fähler es opjetrodde.<br />De Mäldong derzoh wohr: $1",
+ "flow-error-can-not-edit-logged-out": "Em Momang kanns De nit metschwahde. Versöhg ed ens mem Enlogge.",
+ "flow-error-http": "Ene Fähler es opjetrodde beijm Kuntak mem ẞööver.",
+ "flow-error-external": "Ene Fähler es opjetrodde. <br />De Mäldong derzoh wohr: $1",
+ "flow-error-topic-is-locked": "Dat Tehma es dorsch un älehdesch, doh jeit jäz nix mih.",
"flow-error-lock-moderated-post": "Do kanns keijne modderehrte topic als älehdesch makkehre",
- "flow-error-missing-summary": "Do moss_en Äkliehrong schrihve.",
- "flow-error-not-allowed-reply-to-hide-topic": "Do kanns nit antwoote, weil heh dä topic verschtoche woode es.",
- "flow-error-not-allowed-reply-to-delete-topic": "Do kanns nit antwoote, weil heh dä topic fottjeschmeße wohd.",
- "flow-error-not-allowed-suppress": "Heh dä topic wohd fottjeschmeße.",
- "flow-error-not-allowed-reply-to-suppress-topic": "Do kanns nit antwoote, weil heh dä topic fottjeschmeße wohd.",
- "flow-error-not-allowed-reply-to-delete-topic-extract": "Do kanns nit antwoote, weil heh dä topic fottjeschmeße wohd. Heh küdd ene Ußzoch uss_em Logbohch vum Fottschmiiße doh för.",
- "flow-error-not-allowed-suppress-extract": "Heh dä topic wohd fottjeschmeße. Heh küdd ene Ußzoch uss_em Logbohch vum Fottschmiiße doh för.",
- "flow-error-not-allowed-reply-to-suppress-topic-extract": "Do kanns nit antwoote, weil heh dä topic ongerdök woode es. Heh küdd ene Ußzoch uss_em Logbohch vum Ongerdöke doh för.",
+ "flow-error-missing-content": "En dämm Beidraach schteiht nix dren, doh hädd et Affspeijschere keine Senn.",
+ "flow-error-missing-summary": "Do moss_en Zesammefaßong schrihve.",
+ "flow-error-missing-title": "Et Tehma fählt. Esu künne mer dat nit affschpeijschere.",
+ "flow-error-protected-unknown-reason": "Onbikannt",
+ "flow-error-invalid-moderation-reason": "Jivv ene Jrond aan, woröm modderehre.",
+ "flow-error-not-allowed": "Din Beräschtejnge reichse nit uß, för dat ze donn.",
+ "flow-error-not-allowed-hide": "Dat Tehma es verschtoche.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Do kanns nit antwoote, weil heh dat Tehma verschtoche woode es.",
+ "flow-error-not-allowed-delete": "Dat Tehma es fottjeschmeße.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Do kanns nit antwoote, weil heh dat Tehma fottjeschmeße es.",
+ "flow-error-not-allowed-suppress": "Dat Tehma es fottjeschmeße.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Do kanns nit antwoote, weil heh dat Tehma fottjeschmeße es.",
+ "flow-error-not-allowed-hide-extract": "Dat Tehma es verschtoche. Dä Enndrahch em Logboch doh drövver es:",
+ "flow-error-not-allowed-delete-extract": "Dat Tehma es fottjeschmeße. Dä Enndrahch em Logboch doh drövver es:",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Do kanns nit antwoote, weil dat Tehma heh fottjeschmeße wohd. Heh küdd ene Ußzoch uss_em Logbohch vum Fottschmiiße doh för.",
+ "flow-error-not-allowed-suppress-extract": "Heh dat Tehma wohd fottjeschmeße. Heh küdd ene Ußzoch uss_em Logbohch vum Fottschmiiße doh för.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Do kanns nit antwoote, weil heh dat Tehma ongerdök woode es. Heh küdd ene Ußzoch uss_em Logbohch vum Ongerdöke doh för.",
+ "flow-error-title-too-long": "Övverschreffte met Tehme künne nit mih wi {{PLURAL:$1|eij <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Byte</i>|$1 <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Bytes</i>|keij <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Byte</i>}} lang sin.",
"flow-error-no-existing-workflow": "Dä Afflouf jidd_et noch nit.",
+ "flow-error-not-a-post": "De Övverschreff vun enem Tehma kam_mer nit och noch als ene Beidraach derbei donn.",
"flow-error-missing-header-content": "Do moss_en Äkliehrong schrihve.",
+ "flow-error-missing-prev-revision-identifier": "De Kännong för de vörrije Väsjohn fählt.",
+ "flow-error-prev-revision-mismatch": "Ene anndere Metmaacher hät jrahd vör e paa Sekonde och aan dämm Beijdraach heh jät jeänndert. Wells De dat verhaftesch övverschrihve un domet widder fott maache?{{GENDER:$3|}}",
"flow-error-prev-revision-does-not-exist": "Mer kunnte di Väsjohn derför nit fenge.",
"flow-error-default": "Ene Fähler es opjetrodde",
+ "flow-error-invalid-title": "En onjöltijje Sigge_Övverschreff wood aanjejovve.",
+ "flow-error-fail-load-history": "Mer kunnte de Verjangeheit nit lahde.",
+ "flow-error-insufficient-permission": "Keij Rääsch, ob dä Ennhalld zohzejrihfe.",
+ "flow-error-revision-comparison": "De Ongerscheijde ze fenge hät blohß senn för zwai Väsohne vum sälve Beijdrahch.",
"flow-error-fail-load-data": "Mer kunnte di aanjefrohchte Dahte nit lahde.",
"flow-error-invalid-workflow": "Mer kunnte dä aanjefrohchte Afflouf nit fenge.",
+ "flow-error-process-data": "Ene Fähler es beim Verärbeijde vun dä Dahte en Dingem Opdracht aan dä ẞööver opjetrodde.",
+ "flow-error-process-wikitext": "Ene Fähler es opjetrodde beim Verwanndelle vun Wikkitäx en <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i> udder retuhr.",
+ "flow-error-content-too-long": "Dä Ennhald es zo jruhß. Noh_m Wanndelle sin nit mih wi {{PLURAL:$1|eij <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Byte</i>|$1 <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Bytes</i>|keij <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Byte</i>}} zojelohße.",
"flow-error-invalid-topic-uuid-title": "Kapodde Övverschreff",
"flow-error-search": "Mer kunnte et Söhke nit fähdesch maache, wähje enem Problem, wat ävver flök verbei sin sullt. Bes esu johd un versöhg et schpääder norr_ens.",
"flow-edit-header-submit": "Lohß jonn!",
"flow-edit-title-submit": "Lohß jonn!",
"flow-edit-post-submit": "Lohß Jonn!",
- "flow-rev-message-create-header": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät de Övverschreff aanjelaat",
- "flow-rev-message-edit-header": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät de Övverschreff verändert.",
- "flow-rev-message-locked-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät [$4 dä topic] $6 als älehdesch makkehrt (<em>$5</em>)",
+ "flow-edit-post-submit-anonymously": "Donn di Ännderonge der ohne ene Nahme ennreijsche",
+ "flow-rev-message-edit-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ hät ene Kommäntaa för aanjelaat",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} hädd ene Beijdrahch beärrbeijdt",
+ "flow-rev-message-new-post": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat Tehma „[$3 $4]“ aanjelaat.",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} hädd e neu Tehma aanjelaat.",
+ "flow-rev-message-edit-title": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät de Överschreff vun däm Tehma vun „$5“ op „[$3 $4]“ verändert.",
+ "flow-rev-message-create-header": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di Övverseesch aanjelaat",
+ "flow-rev-message-edit-header": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di Övverseesch verändert.",
+ "flow-rev-message-create-topic-summary": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di Zesammefaßong zom Tehma $3 aanjelaat.",
+ "flow-rev-message-edit-topic-summary": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät di Zesammefaßong zom Tehma $3 veränndert.",
+ "flow-rev-message-hid-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat [$4 Tehma „$6“] verschtoche ($5)",
+ "flow-rev-message-deleted-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat [$4 Tehma „$6“] fottjeschmeße ($5)",
+ "flow-rev-message-suppressed-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat [$4 Tehma „$6“] ongerdrök ($5)",
+ "flow-rev-message-locked-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat [$4 Tehma „$6“] als älehdesch makkehrt ($5)",
"flow-rev-message-lock-topic-reason": "als älehdesch makkeht",
"flow-rev-message-restore-topic-reason": "widder opjemaat",
+ "flow-rev-message-restored-topic": "{{GENDER:$2|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät dat [$4 Tehma „$6“] widder zerök jehollt ($5)",
"flow-rc-topic-of-board": "$1 op $2",
+ "flow-board-history": "Verjangeheit vun „$1“",
+ "flow-board-history-empty": "Di Klaafsigg hät noch kein Verjangeheid.",
+ "flow-topic-history": "Verjangeheit vun de Tehme vun „$1“",
"flow-history-last4": "Läzde vier Woche",
"flow-history-day": "Hück",
"flow-history-week": "Läzde Woch",
"flow-history-pages-post": "Douch op op [$1 $2]",
"flow-show-comments-title": "{{PLURAL:$1|Dä Kommäntah|De Kommäntahre|Nix}} aanlohre",
"flow-hide-comments-title": "{{PLURAL:$1|Dä Kommäntah|De Kommäntahre|Nix}} verschteijsche",
+ "flow-last-modified": "Zeläz verändert onjefähr $1",
"flow-workflow": "Afflouf",
+ "flow-notification-edit-bundle": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ un {{PLURAL:$5|ein|$5|keij|100=mih wi nüngenünxesch}} anndere han <span class=\"plainlinks\">[$4 ene Beijdraach]</span> op dä Sigg „$3“ em Affschnett „$2“ jät je'änndert.{{GENDER:$1|}}",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Ein neu Tehma|$1 neuje Tehme|Keijn Tehma|100=övver 99 neu Tehme}} em Affschnedd „<strong>$3</strong>“.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Ein neu Tehma|$1 neuje Tehme|Keijn Tehma|100=övver 99 neu Tehme}} op <strong>Dinge Klaafsigg</strong>",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Ein neue Antwoot|$1 neue Antwoote|Keijn Antwood|100=övver 99 neu Antwoote}} em Affschnet „<strong>$3</strong>“.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Ein neue Antwoot|$1 neue Antwoote|Keijn Antwood|100=övver 99 neu Antwoote}} op <strong>Dinge Klaafsigg</strong> em Affschnedd „<strong>$3</strong>“.",
+ "notification-header-flow-post-edited-v2": "Dinge Beijdraach op „$1“ wood beärbeijdt.{{GENDER:$2|}}",
+ "notification-bundle-header-flow-post-edited-v2": "Dinge Beijdraach op „$1“ wood mihfach beärbeijdt.{{GENDER:$2|}}",
+ "notification-header-flow-summary-edited": "De Zesammenfaßong vum Tehma „$1“ wood je'änndert.",
+ "notification-header-flow-summary-edited-first": "Et Tehma „$1“ woode zesammenjefaß.",
+ "notification-bundle-header-flow-summary-edited": "De Zesammenfaßong vum Tehma „$1“ wood e paa Mohl je'änndert.",
+ "notification-email-subject-flow-summary-edited": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät Zosamefaßong vun dä Sigg „$2“ verändert.",
+ "notification-email-batch-body-flow-summary-edited": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät Zosamefaßong vun dä Sigg „$2“ verändert.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ un {{PLURAL:$3|ein|$3|keij|100=mih wi nüngenünxesch}} anndere han op dä Sigg „$2“ de Beschrihvong je'änndert.{{GENDER:$1|}}",
+ "notification-links-flow-description-edited-view-page": "Sigg belohre{{GENDER:$1|}}",
+ "notification-email-batch-bundle-body-flow-description-edited": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} „$1“ un {{PLURAL:$3|ein|$3|keij|100=mih wi nüngenünxesch}} anndere han op dä Sigg „$2“ de Beschrihvong je'änndert.{{GENDER:$1|}}",
+ "notification-header-flow-topic-resolved": "Et Tehma „<strong>$1</strong>“ woht älehdesch.",
+ "notification-header-flow-topic-reopened": "Et Tehma „<strong>$1</strong>“ wood wider opjemaat.",
+ "notification-header-flow-topic-resolved-user-talk": "Et Tehma „<strong>$1</strong>“ woht op <strong>Dinge Klaafsigg</strong> älehdesch.",
+ "notification-header-flow-topic-reopened-user-talk": "Et Tehma „<strong>$1</strong>“ woht op <strong>Dinge Klaafsigg</strong> wider opjemaat.",
+ "notification-email-subject-flow-topic-resolved": "Et Tehma „<strong>$2</strong>“ woht älehdesch.",
+ "notification-email-batch-body-flow-topic-resolved": "Et Tehma „<strong>$1</strong>“ woht älehdesch.",
"flow-notification-newtopic-bundle": "{{PLURAL:$1|ene neuje topic|$1 neuje topics|250=övver 250 neuje topics}} op '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-link-text-view-topic": "Tehma belohre",
+ "flow-notification-link-text-view-topics": "Tehme belohre",
"flow-notification-reply-email-subject": "$2 op $3",
"flow-notification-reply-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hädd op „$2“ op dä Sigg „$3“ jeantwoot.",
"flow-notification-reply-email-batch-bundle-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 un {{PLURAL:$5|eine andere hädd|$4 andere han|keine söns hädd}} op „$2“ op dä Sigg „$3“ jeantwoot.",
@@ -96,7 +221,8 @@
"flow-notification-edit-email-batch-bundle-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 un {{PLURAL:$5|eine|$4|keine}} andere {{PLURAL:$5|hät|han|hät}} ene Beijdraach onger „$2“ en dä Sigg „$3“ beärbeidt.",
"flow-notification-rename-email-batch-body": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät Dinge topic „$2“ op „$3“ ömjenannd op $4",
"flow-notification-newtopic-email-subject": "{{GENDER:$1|Dä|Dat|Dä Metmaacher|De|Dat}} $1 hät ene neuje Beijdraach onger „$2“ aanjelaat.",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|ene neuje topic|$1 neuje topics|250=övver 250 neuje topics}} op $2",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Ene neuje Affchnett|$1 neuje Affchnedde|250=Övver 250 neuje Affchnedde}} op dä Sigg „$2“",
+ "flow-link-topic": "Tehma",
"flow-link-history": "Ällder Väsjohne",
"flow-link-header-revision": "de Väsjohn vun dä Äkliehrong",
"flow-moderation-confirm-suppress-post": "Ongerdröke",
@@ -114,6 +240,9 @@
"flow-compare-revisions-revision-header": "De Väsjohn {{GENDER:$2|vum|vum|vumm Metmaacher|vun dä|vum}} „$1“ vum $2\n<!-- https://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Flow-compare-revisions-revision-header/en\n-->",
"flow-topic-html-title": "$1 op $2",
"flow-load-more": "Mih lahde",
+ "flow-no-more-fwd": "Mer han keijn ällder Tehme.",
+ "flow-newest-topics": "Neuste Tehme",
+ "flow-recent-topics": "Tehme, wo zeläz zoh jeschrevve wohd",
"flow-terms-of-use-summarize": "Wann De op „{{int:flow-topic-action-update-topic-summary}}“ kleks, schtemmps De dä Bedengonge för de Benözong för heh dat Wikki zoh.",
"flow-whatlinkshere-header": "vun dä [$1 Övverschreff]",
"flow-whatlinkshere-post-summary": "vun de [$1 Zersammefaßong]",
@@ -129,37 +258,6 @@
"flow-topic-undo-delete": "et Fottschmiiße ophävve",
"flow-topic-undo-suppress": "de Ongerdrökong ophävve",
"flow-importer-lqt-suppressed-user-template": "He di empottehrte Väsjohn uß LiquidThreads es vun enem ongerdrökte Metmaacher. Se wohd däm aktoälle Metmaacher zohjeschlonn.",
- "apihelp-flow-param-page": "De Sigg, fö di jät ze donn es.",
- "apihelp-flow-example-1": "Donn de Äkliehrong op dä Sigg „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Talk:Sandbox]]</code>“ verändere.",
- "apihelp-flow+edit-header-param-content": "Der Ennhalld för de Äkliehrong.",
- "apihelp-flow+edit-header-param-format": "Et Fommaht vun dä Äkliehrong, „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">wikitext</code>“ udder „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">html</code>“.",
- "apihelp-flow+edit-header-example-1": "Donn de Äkliehrong vum [[Talk:Sandbox|Klaaf övver de Schpellwiß]] ändere.",
- "apihelp-flow+edit-post-param-format": "Et Fommaht vum Enhalld vum neue post, Wikkitäx udder <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i>?\n<!-- \nhttps://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Apihelp-flow%2Breply-param-format/en\n-->",
- "apihelp-flow+edit-title-param-prev_revision": "De Kännong för de aktoölle Väsjohn vun dä Övverschreff, öm noh dubbelte Beärbeidonge ze söhke.",
- "apihelp-flow+edit-title-param-content": "Der Ennhalld för de Övverschreff.",
- "apihelp-flow+edit-topic-summary-param-summary": "Der Inhalt for et Resümeh.",
- "apihelp-flow+edit-topic-summary-param-format": "Et Fommaht vun dä Zosammefaßong, Wikkitäx udder <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i>?\n<!-- https://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Apihelp-flow%2Bedit-topic-summary-param-format/en_and_MediaWiki:Apihelp-flow%2Bedit-title-param-format/en\n-->",
- "apihelp-flow+new-topic-param-format": "Et Fommaht vum neue topic singe eezde Antwoot, „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">wikitext</code>“ udder „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">html</code>“.\n<!--\nhttps://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Apihelp-flow%2Bnew-topic-param-format/ksh\n-->",
- "apihelp-flow+reply-param-content": "Dä Enhald för dä neuje Beidraach.",
- "apihelp-flow+reply-param-format": "Et Fommaht vum neue post, Wikkitäx udder <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i>?\n<!-- \nhttps://translatewiki.net/wiki/Thread:Support/About_MediaWiki:Apihelp-flow%2Breply-param-format/en\n-->",
- "apihelp-flow+view-header-example-1": "Holl de Äkliehrong för „<code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Talk:Sandbox]]</code>“ em Wikkitäx Fommaht.",
- "apihelp-flow+view-post-history-param-format": "Dat Fommaht för der Enhalld dren ußzejävve.",
- "apihelp-flow+view-topic-history-example-1": "Belohr de Väsohne vun de Beijdrähsch zom <code lang=\"en\" xml:lang=\"en\" dir=\"ltr\">[[Topic:S2tycnas4hcucw8w]]</code> als Wikkitäx",
- "apihelp-flow+view-topiclist-param-sortby": "Enschtällonge för et Zottehre vun de topics, dadd es äntwehder „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">updated</kbd>“ för zem Zottehre noh de Zigg, woh dä topic et läz jeändert wohd, udder „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">newest</kbd>“ för et Zottehre noh dä Zigg vum Aanläje.",
- "apihelp-flow+view-topiclist-param-savesortby": "Donn de Enschtällong för woh noh ze zottehre en de Enschtällonge vum Metmaacher, wann jät ennjejovve es.",
- "apihelp-flow+view-topiclist-param-offset-id": "Der Wäät för der Bejenn — em <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"Universally unique identifier\">UUID</i>-Fommaht — vun woh aan Jähjeschtänd jehollt wähde sulle. Weed blohß beim Zottehre noh „<kbd lang=\"en\" xml:lang=\"en\" dir=\"ltr\">newest</kbd>“ jebruch.",
- "apihelp-flow-parsoid-utils-description": "Donn Täx zwesche Wikkitäx un <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"HyperText Markup Language\">HTML</i> wandelle.",
- "apihelp-flow-parsoid-utils-param-content": "Der Enhalld zom Ömwandelle.",
- "apihelp-flow+undo-edit-header-description": "Holl nühdejje Enfommazjuhne, öm de Änderong aan dä Äkliehrong retuhr ze nämme.",
- "apihelp-flow+undo-edit-header-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
- "apihelp-flow+undo-edit-header-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull.",
- "apihelp-flow+undo-edit-post-description": "Holl nühdejje Enfommazjuhne, öm de Änderong aan em Beijdrahch retuhr ze nämme.",
- "apihelp-flow+undo-edit-post-param-postId": "De Kännong vum Beijdrahch zom zerök nämme.",
- "apihelp-flow+undo-edit-post-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
- "apihelp-flow+undo-edit-post-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull.",
- "apihelp-flow+undo-edit-post-example-1": "Holl Enfommazjuhne, öm en Änderong aan ene beschtemmte topic retuhr ze nämme.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "De Kännong vun dä Väsohn, woh et Zeröcknämme aanfange sull.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "De Kännong vun dä Väsohn, woh et Zeröcknämme ophühre sull.",
"flow-edited": "Be'ärbeidt",
"flow-edited-by": "Be'ärbeidt {{GENDER:$1|vum|vum|vumm Metmaacher|vun dä|vum}} „$1“",
"flow-previous-diff": "←&nbsp;De Änderong dovör",
@@ -167,7 +265,7 @@
"flow-undo": "zeröck nämme",
"flow-undo-latest-revision": "De neuste Väsjohn",
"flow-undo-your-text": "Dinge Täx",
- "flow-undo-edit-header": "De Övverschreff ändere",
+ "flow-undo-edit-header": "De Övverschreff änndere",
"flow-undo-edit-content": "De Änderong künnte mer zerök nämme. Beloor Der de Ungerscheide un dann donn di Sigg avspeichere, wann De dengks, et es en Oodenong esu.",
"flow-undo-edit-failure": "Dat kunnt mer nit zerök nämme, weil et enzwesche ald widder beärbeidt wood.",
"flow-ve-mention-context-item-label": "Ä'wähne",
@@ -177,8 +275,10 @@
"flow-ve-mention-tool-title": "Ene Metmaacher ä'wähne",
"flow-ve-mention-inspector-invalid-user": "Ene Metmaacher met däm Nahme „$1“ es nit aanjemäldt.",
"flow-wikitext-editor-help": "Wikkitäx $1.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|Befähle]]",
- "flow-notification-link-text-enabled-on-talkpage": "Beloor de Klaafsigg",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|Befähle]]",
+ "flow-wikitext-switch-editor-tooltip": "Obb et Beärbeijde mem <i lang=\"en\" xml:lang=\"en\" dir=\"ltr\" title=\"„Projramm för ‚seeschbaa‘ aan Täxte jät ze änndere“\">VisualEditor</i> ömmschallde",
+ "flow-ve-switch-editor-tool-title": "Obb et Wikkitäx Beärbeijde ömmschallde",
+ "flow-notification-link-text-enabled-on-talkpage": "Beloor de Klaafsigg vum Metmaacher",
"flow-dialog-cancelconfirm-title": "Verhaftesch?",
"flow-dialog-cancelconfirm-message": "Wells de verhaftesch der ohne ze seschere ophühre?",
"flow-dialog-cancelconfirm-keep": "Wigger beärbeijde",
diff --git a/Flow/i18n/ku-latn.json b/Flow/i18n/ku-latn.json
index 9c1b1268..e60159e5 100644
--- a/Flow/i18n/ku-latn.json
+++ b/Flow/i18n/ku-latn.json
@@ -5,20 +5,68 @@
"George Animal"
]
},
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 mijareka li ser [[$3]] {{GENDER:$2|jê bir}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 mijareka li ser [[$3]] {{GENDER:$2|jê bir}}",
+ "flow-board-header-browse-topics-link": "Li mijaran bigere",
"flow-board-header": "Di derbarê vê gotûbêjê de",
"flow-board-collapse-description": "Danasînê veşêre",
"flow-board-expand-description": "Danasînê nîşan bide",
"flow-edit-header-link": "Danasînê biguherîne",
+ "flow-topic-moderated-reason-prefix": "Sedem:",
+ "flow-post-actions": "Çalakî",
+ "flow-topic-actions": "Çalakî",
+ "flow-cancel": "Betal bike",
+ "flow-show-change": "Guherandinan nîşan bide",
+ "flow-newtopic-title-placeholder": "Mijara Nû",
+ "flow-newtopic-save": "Mijarekê lê zêde bike",
+ "flow-newtopic-start-placeholder": "Dest bi mijareke nû bike",
+ "flow-reply-topic-title-placeholder": "Bersivê bide \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|Bersivê bide}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Spas}}}}",
+ "flow-history-action-delete-post": "jê bibe",
+ "flow-history-action-hide-post": "veşêre",
+ "flow-post-action-view": "Girêdana herdemî",
+ "flow-post-action-delete-post": "Jê bibe",
+ "flow-post-action-hide-post": "Veşêre",
+ "flow-post-action-edit-post": "Biguherîne",
+ "flow-post-action-edit-post-submit": "Guherandinan tomar bike",
+ "flow-topic-action-view": "Girêdana herdemî",
+ "flow-topic-action-edit-title": "Sernav biguherîne",
+ "flow-topic-action-history": "Dîrok",
+ "flow-topic-action-hide-topic": "Mijarê veşêre",
+ "flow-topic-action-delete-topic": "Mijarê jê bibe",
+ "flow-topic-action-unlock-topic": "Mijarê dîsa veke",
+ "flow-topic-action-summarize-topic": "Kurt bike",
+ "flow-topic-action-resummarize-topic": "Kurteya mijarê biguherîne",
+ "flow-topic-action-update-topic-summary": "Kurteyê rojane bike",
+ "flow-topic-action-watchlist-add": "Vê mijarê abone bike",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Tu nikarî bersivê bidî ji ber ku mijar hatiye jêbirin.",
+ "flow-error-missing-header-content": "Tu divê danasînekê tomar bikî.",
"flow-edit-header-submit": "Danasînê tomar bike",
- "apihelp-flow-example-1": "Danasîna \"[[Talk:Sandbox]]\" biguherîne",
- "apihelp-flow+edit-header-param-content": "Naveroka danasînê",
+ "flow-edit-title-submit": "Sernav biguherîne",
+ "flow-edit-post-submit": "Guherandinan tomar bike",
+ "flow-history-day": "Îro",
+ "flow-history-week": "Hefteya dawî",
+ "flow-hide-comments-title": "{{PLURAL:$1|Şîroveyê veşêre|Şîroveyan veşêre}}",
+ "flow-notification-mention-email-subject": "$1 li ser $2 qala {{GENDER:$3|te}} {{GENDER:$1|kir}}",
+ "flow-link-topic": "miajr",
+ "flow-link-history": "dîrok",
+ "flow-moderation-confirm-delete-post": "Jê bibe",
+ "flow-moderation-confirm-hide-post": "Veşêre",
+ "flow-topic-first-heading": "Mijara lis er $1",
+ "flow-topic-html-title": "$1 li ser $2",
+ "flow-topic-count": "Mijar($1)",
+ "flow-no-more-fwd": "Mijarên kevintir tune ne",
+ "flow-newest-topics": "Mijarên herî nû",
+ "flow-recent-topics": "Mijarên dawî yên çalak",
"flow-undo-your-text": "Nivîsara te",
"flow-undo-edit-header": "Danasîn tê guherandin",
+ "flow-ve-mention-context-item-label": "Qalkirin",
"flow-ve-mention-inspector-remove-label": "Jê bibe",
"flow-ve-mention-placeholder": "Navê bikarhêner",
- "flow-mark-revision-patrolled-link-text": "Vê rûpelê wek serrastkirî nîşan bide",
- "flow-mark-revision-patrolled-link-title": "Vê rûpelê wek serrastkirî nîşan bide",
- "flow-mark-diff-patrolled-link-text": "Wek serrastkirî nîşan bide",
+ "flow-ve-mention-tool-title": "Qala bikarhênerekî/ê bike",
+ "flow-mark-revision-patrolled-link-text": "Vê rûpelê wek sererastkirî nîşan bide",
+ "flow-mark-revision-patrolled-link-title": "Vê rûpelê wek sererastkirî nîşan bide",
+ "flow-mark-diff-patrolled-link-text": "Wek sererastkirî nîşan bide",
"flow-mark-diff-patrolled-link-title": "Wek serrastkirî nîşan bide"
}
diff --git a/Flow/i18n/lag.json b/Flow/i18n/lag.json
new file mode 100644
index 00000000..ead2def9
--- /dev/null
+++ b/Flow/i18n/lag.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Baba Tabita"
+ ]
+ },
+ "flow-history-action-delete-post": "honola",
+ "flow-post-action-delete-post": "Honola",
+ "flow-moderation-confirm-delete-post": "Honola",
+ "flow-moderation-confirm-delete-topic": "Honola",
+ "flow-moderation-confirm-hide-topic": "Visa",
+ "flow-moderation-confirm-unhide-topic": "Visʉla"
+}
diff --git a/Flow/i18n/lb.json b/Flow/i18n/lb.json
index fbc197a8..834e03e9 100644
--- a/Flow/i18n/lb.json
+++ b/Flow/i18n/lb.json
@@ -2,16 +2,24 @@
"@metadata": {
"authors": [
"Robby",
- "Soued031"
+ "Soued031",
+ "Nnemo"
]
},
- "enableflow": "Flow aktivéieren",
- "flow-desc": "Workflow-Management-System",
+ "enablestructureddiscussions": "Flow aktivéieren",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Ophalen}} nei Aktivitéiten iwwer \"$1\" z'iwwerwaachen",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Dir}} iwwerwaacht d'Säit \"$1\" net méi",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Ophalen}} dëse Sujet z'iwwerwaachen",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Dir}} iwwerwaacht \"$1\" net méi",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Dir}} kënnt [$2 dëse Sujet] zu all Ament iwwerwaachen.",
+ "flow-desc": "Diskussiouns-System",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|huet}} eng [$4 Matdeelung] iwwer \"[[$3|$5]]\" op [[$6]] geläscht",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|huet}} d'Thema \"[[$3|$5]]\" op [[$6]] geläscht",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|huet}} d'Thema \"[[$3|$5]]\" iwwer [[$6]] restauréiert",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|huet}} e Sujet op [[$3]] geläscht",
"flow-board-header-browse-topics-link": "Themen duerchsichen",
"flow-board-header": "Iwwer dëst Board",
+ "flow-board-description-can-not-edit": "Kann net geännert ginn",
"flow-board-collapse-description": "Beschreiwung verstoppen",
"flow-board-expand-description": "Beschreiwung weisen",
"flow-topic-collapse-siderail": "Mat der ganzer Breet liesen",
@@ -31,12 +39,12 @@
"flow-post-actions": "Aktiounen",
"flow-topic-actions": "Aktiounen",
"flow-cancel": "Ofbriechen",
- "flow-skip-summary": "Resumé iwwersprangen",
+ "flow-skip-summary": "Iwwersprangen",
"flow-summary-authored": "Resumé vum $1",
"flow-summary-edited": "Resumé fir d'lescht {{GENDER:$1|geännert}} vum $1",
"flow-show-change": "Ännerunge weisen",
"flow-last-modified-by": "Fir d'lescht {{GENDER:$1|geännert}} vum $1",
- "flow-stub-post-content": "\"Duerch en technesche Feeler konnt dës Matdeelung net ofgeruff ginn.\"",
+ "flow-stub-post-content": "<em>Duerch en technesche Feeler konnt dësen Inhalt net ofgeruff ginn</em>",
"flow-newtopic-title-placeholder": "Neit Thema",
"flow-newtopic-content-placeholder": "En neie Message iwwer \"$1\" schécken",
"flow-newtopic-header": "En neit Thema derbäisetzen",
@@ -79,16 +87,12 @@
"flow-board-notification-subscribe-title": "{{GENDER:$1|Dir}} sidd an dësen Diskussiouns-Board ageschriwwen!",
"flow-topic-action-watchlist-add": "Sech op dëse Sujet abonnéeieren",
"flow-topic-action-watchlist-remove": "Ofbestellen",
- "flow-error-allowcreation-already-exists": "Säit gëtt et schonn, awer et dierft se net ginn",
+ "flow-error-allowcreation-already-exists": "Säit gëtt et schonn, dofir kann eng Strukturéiert Diskussiouns-Wand net dohi geréckelt ginn.",
"flow-error-allowcreation-flow-create-board": "De Benotzer huetd'Recht \"{{int:right-flow-create-board}}\" net",
- "flow-error-other": "En onerwaarte Feeler ass geschitt.",
- "flow-error-external": "Et ass e Feeler geschitt.<br />De Feelermessage war:$1</ small>",
- "flow-error-external-multi": "Et si Feeler geschitt.<br />$1",
+ "flow-error-external": "Et ass e Feeler geschitt. De Feelermessage war: $1",
"flow-error-missing-summary": "Dir musst e Resumé eraschécken.",
"flow-error-missing-title": "D'Thema huet keen Titel. Den Titel ass obligatoresch fir een Thema ze späicheren.",
- "flow-error-delete-failure": "D'Läsche vun dësem Element huet net funktionéiert.",
- "flow-error-hide-failure": "Verstoppe vun dësem Element huet net funktionéiert.",
- "flow-error-restore-failure": "D'Restauréiere vun dësem Element huet net funktionéiert.",
+ "flow-error-protected-unknown-reason": "Onbekannt",
"flow-error-not-allowed": "Net genuch Rechter fir dës Aktioun ze maachen",
"flow-error-not-allowed-reply-to-hide-topic": "Dir kënnt net äntwerte well dëst Thema verstoppt gouf.",
"flow-error-not-allowed-reply-to-delete-topic": "Dir kënnt net äntwerte well dëst Thema geläscht gouf.",
@@ -101,12 +105,14 @@
"flow-error-default": "Et ass e Feeler geschitt.",
"flow-error-invalid-title": "En net valabelen Säitentitel gouf uginn.",
"flow-error-insufficient-permission": "Net genuch Rechter fir op den Inhalt zouzegräifen.",
+ "flow-error-different-page": "De Workflow vun de Strukturéierten-Diskussiounen ass net mat dëser Säit associéiert.",
"flow-error-no-render": "Déi spzifizéiert Aktioun gouf net erkannt.",
"flow-error-no-commit": "Déi spezifiséiert Aktioun konnt net gespäichert ginn",
"flow-error-move-topic": "D'Réckele vun enger Theme-Säit gëtt elo net ënnerstëtzt",
"flow-error-invalid-topic-uuid-title": "Schlechten Titel",
"flow-error-unknown-workflow-id-title": "Onbekannt Thema",
"flow-error-search": "Mir konnten Är Sich wéint engem temporäre Problem net maachen. Probéiert w.e.g. méi spéit nach eng Kéier.",
+ "flow-error-invalid-undelete": "D'Säit konnt net restauréiert gi well elo eng Diskussioun doriwwer am Gaang ass.",
"flow-edit-header-placeholder": "Dësen Diskussiouns-Board beschreiwen",
"flow-edit-header-submit": "Beschreiwung späicheren",
"flow-edit-header-submit-anonymously": "Beschreiwung anonym späicheren",
@@ -141,21 +147,34 @@
"flow-comment-moderated": "Moderéiert Bemierkung",
"flow-last-modified": "Fir d'lescht geännert ongeféier $1",
"flow-workflow": "workflow",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|huet}} een neit Thema iwwer '''$3''' ugeluecht.",
+ "notification-header-flow-new-topic-user-talk": "Eng nei Rubrik gouf op <strong>Ärer Diskussiounssäit</strong> ugeluecht: \"<strong>$4</strong>\"",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Eng nei Äntwert|$1 nei Äntwerten|100=méi wéi 99 nei Äntwerten}} op \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Äre}} Beitrag op \"<strong>$1</strong>\" gouf geännert.",
+ "notification-header-flow-topic-renamed-user-talk": "D'Rubrik ''<strong>$1</strong>'' op <strong>{{GENDER:$3|Ärer}} Diskussiounssäit</strong> gouf op ''<strong>$2</$2strong>'' ëmbenannt.",
+ "notification-header-flow-summary-edited": "De Resumé vun \"<strong>$1</strong>\" gouf aktualiséiert.",
+ "notification-header-flow-summary-edited-first": "D'Thema \"<strong>$1</strong>\" gouf resuméiert.",
+ "notification-email-subject-flow-summary-edited": "$1 huet de Resumé vu(n) $2 {{GENDER:$1|aktualiséiert}}.",
+ "notification-header-flow-mention-post": "$1 huet {{GENDER:$4|Iech}} op \"<strong>$5</strong>\" {{GENDER:$2|ernimmt}}.",
+ "notification-header-flow-mention-post-summary": "$1 huet {{GENDER:$4|Iech}} op \"<strong>$5</strong>\" {{GENDER:$2|ernimmt}}",
+ "notification-header-flow-enabled-on-talkpage": "Neien Diskussiounssystem fir <strong>{{GENDER:$2|Är}} Benotzerdiskussiounssäit</strong> aktivéiert.",
+ "notification-header-flow-description-edited": "D'Beschreiwung vu(n) <strong>$1</strong> gouf geännert.",
+ "notification-bundle-header-flow-description-edited-user-talk": "D'Beschreiwung gouf e puer mol op <strong>{{GENDER:$2|Ärer}} Diskussiounssäit</strong> geännert.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|huet}} een neit Thema iwwer <strong>$3</strong> ugeluecht.",
"flow-notification-rename": "$1 {{GENDER:$1|huet}} den Titel vu(n) span class=\"plainlinks\">[$2 $3]</span> op \"$4\" op [[$5|$6]] geännert.",
"flow-notification-link-text-view-topic": "Thema weisen",
+ "flow-notification-link-text-view-topics": "Rubrike weisen",
"flow-notification-reply-email-subject": "$2 op $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|huet}} op Är Matdeelung iwwer \"$2\" op $3 geäntwert",
"flow-notification-mention-email-subject": "$1 huet {{GENDER:$3|Iech}} op $2 {{GENDER:$1|ernimmt}}",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|huet}} eng Matdeelung geännert",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|huet}} e Message vu(n) \"$2\" iwwer $3 geännert",
- "flow-notification-edit-email-batch-bundle-body": "$1 {{PLURAL:$5|an een aneren|a(n) $4 anerer}} e Message post iwwer \"$2\" op $3 {{GENDER:$1|geännert}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 {{PLURAL:$4|an een aner Message| $4 anere Messagen|100=méi wéi 99 anere Messagen}} iwwer \"$2\" op $3 {{GENDER:$1|geännert}}",
"flow-notification-rename-email-subject": "$1 huet Ärt Thema {{GENDER:$1|ëmbenannt}}",
"flow-notification-rename-email-batch-body": "$1 huet Äre Sujet \"$2\" op \"$3\" op $4 {{GENDER:$1|ëmbenannt}}",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|huet}} een neie Sujet iwwer $2 ugeluecht",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Een neie Sujet|250=250+ nei Sujeten}} op $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Mech informéiere wann Aktiounen déi mech betreffen a geschéien.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Een neie Sujet|100=99 oder méi nei Sujeten}} op $2",
+ "echo-category-title-flow-discussion": "Strukturéiert Diskussioun",
+ "echo-pref-tooltip-flow-discussion": "Mech informéiere iwwer Aktivitéit op Sujeten oder Säiten Aktiounen déi ech iwwerwaachen.",
"flow-link-topic": "Thema",
"flow-link-history": "Versiounen",
"flow-link-post-revision": "Versioun vun der Matdeelung",
@@ -191,29 +210,24 @@
"flow-whatlinkshere-post": "vun engem [$1 Message]",
"flow-whatlinkshere-header": "vun der [$1 Beschreiwung]",
"flow-whatlinkshere-post-summary": "aus dem [$1 Resumé]",
+ "structureddiscussions": "Strukturéiert Diskussiounen",
"flow-special-type": "Typ",
"flow-special-uuid": "UUID",
+ "flow-special-enableflow-legend": "Strukturéiert Diskussiounen op enger neier Säit aktivéieren",
+ "flow-special-enableflow-page": "Säit fir d'Aktivatioun vu Strukturéierten Diskussiounen op",
"flow-special-enableflow-page-is-liquidthreads": "Et gëtt eng LiquidThreads-Säit op [[:$1]].",
"flow-conversion-archive-page-name-format": "%s/Archiv %d\n%s/Archiv%d\n%s/archiv %d\n%s/archiv%d",
+ "flow-spam-confirmedit-form": "Confirméiert datt Dir e Mënsch sidd andeem Dir de CAPTCHA hei drënner léist: $1",
"mw-ui-unsubmitted-confirm": "Dir hutt net gespäichert Ännerungen op dëser Säit. Sidd Dir sécher datt Dir vun dëser Säit wëllt erofgoen an Är Aarbecht verléieren?",
"flow-post-undo-hide": "verstoppe réckgängeg maachen",
"flow-post-undo-delete": "läsche réckgängeg maachen",
"flow-topic-undo-hide": "verstoppe réckgängeg maachen",
"flow-topic-undo-delete": "läsche réckgängeg maachen",
"flow-importer-lqt-moved-thread-template-content": "Dës Notiz vum {{{author}}} gouf de(n) {{{date}}} geréckelt. Dir fannt se op [[{{{title}}}]].",
- "apihelp-flow-example-1": "Ännert d'Beschreiwung vun ''[[Talk:Sandbox]]''",
- "apihelp-flow+edit-header-param-content": "Inhalt fir d'Beschreiwung.",
- "apihelp-flow+edit-header-param-format": "Format vun der Beschreiwung (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "D'Beschreiwung vun [[Talk:Sandbox]] änneren",
- "apihelp-flow+edit-title-param-content": "Inhalt fir den Titel.",
- "apihelp-flow+edit-topic-summary-param-summary": "Inhalt fir de Resumé.",
- "apihelp-flow+edit-topic-summary-param-format": "Format vum Resumé (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Ännert de Resumé vu(n) [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-param-reason": "Grond fir Moderatioun.",
- "apihelp-flow+view-topic-description": "En Thema weisen.",
- "apihelp-flow-parsoid-utils-param-to": "Format an deen den Inhalt ëmgewandelt soll ginn.",
"flow-edited": "Geännert",
"flow-edited-by": "Geännert vum $1",
+ "flow-edited-by-header": "Board-Beschreiwung geännert vum $1",
+ "flow-edited-by-topic-title": "Titel vum Sujet geännert vum $1",
"flow-previous-diff": "← Méi al Ännerung",
"flow-next-diff": "Méi nei Ännerung →",
"flow-undo": "réckgängeg maachen",
@@ -221,9 +235,9 @@
"flow-undo-your-text": "Ären Text",
"flow-undo-edit-header": "D'Beschreiwung änneren",
"flow-undo-edit-topic-summary": "De Resumé vum Thema änneren",
- "group-flow-bot": "Flow-Botten",
- "group-flow-bot-member": "Flow-Bot",
- "grouppage-flow-bot": "Project:Flow-Botten",
+ "group-flow-bot": "Strukturéiert Diskussiounen Botten",
+ "group-flow-bot-member": "Strukturéiert Diskussiounen Bot",
+ "grouppage-flow-bot": "Project:Botte vu Strukturéierten Disussiounen",
"flow-ve-mention-context-item-label": "Ernimmen",
"flow-ve-mention-inspector-title": "Ernimmen",
"flow-ve-mention-inspector-remove-label": "Ewechhuelen",
@@ -232,18 +246,19 @@
"flow-ve-mention-inspector-invalid-user": "De Benotzernumm ''$1'' ass net registréiert.",
"flow-wikitext-editor-help": "Wikitext $1.",
"flow-wikitext-editor-help-preview-the-result": "D'Resultat kucken ouni ze späicheren",
- "flow-wikitext-switch-editor-tooltip": "Op de VisualEditor wiesselen",
+ "flow-wikitext-switch-editor-tooltip": "Op de visuellen Editeur wiesselen",
"flow-ve-switch-editor-tool-title": "Op de Wikitext-Editeur wiesselen",
"flow-mark-revision-patrolled-link-text": "Dës Säit als nogekuckt markéieren",
"flow-mark-revision-patrolled-link-title": "Dës Säit als nogekuckt markéieren",
"flow-mark-diff-patrolled-link-text": "Als nogekuckt markéieren",
"flow-mark-diff-patrolled-link-title": "Als nogekuckt markéieren",
- "flow-notification-link-text-enabled-on-talkpage": "Benotzerdiskussiounssäit weisen",
+ "flow-talk-page-beta-feature-message": "Strukturéiert Diskussiounen op der Benotzerdiskussiouns Säit",
+ "flow-notification-link-text-enabled-on-talkpage": "Benotzerdiskussiounssäit {{GENDER:|weisen}}",
"flow-notification-enabled-on-talkpage-title": "Neien Diskussiounssystem aktivéiert fir {{GENDER:$1|Är}} Benotzerdiskussiounssäit<br /><small>Disponibel op [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Neien Diskussiounssystem op $2",
"flow-beta-feature-remove-archive-template-edit-summary": "Archiv-Schabloun gëtt ewechgeholl",
- "flow-dialog-cancelconfirm-title": "Sidd Dir sécher?",
- "flow-dialog-cancelconfirm-message": "Sidd Dir sécher datt Dir ofbrieche wëllt ouni fir d'éischt ze späicheren?",
+ "flow-dialog-cancelconfirm-title": "Sidd {{GENDER:|Dir}} sécher?",
+ "flow-dialog-cancelconfirm-message": "Sidd {{GENDER:|Dir}} sécher datt Dir ofbrieche wëllt ouni fir d'éischt ze späicheren?",
"flow-dialog-cancelconfirm-keep": "Virufuere mat Änneren",
"flow-dialog-cancelconfirm-discard": "Ännerungen annuléieren",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Wëllkomm}} op {{GENDER:$1|Ärer}} neier Benotzerdiskussiounssäit",
diff --git a/Flow/i18n/lij.json b/Flow/i18n/lij.json
new file mode 100644
index 00000000..4d084c54
--- /dev/null
+++ b/Flow/i18n/lij.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Giromin Cangiaxo"
+ ]
+ },
+ "flow-special-desc": "Questa paggina speciale a rendiriçça a un messaggio Flow ò a un flusso de travaggio Flow dæto un UUID."
+}
diff --git a/Flow/i18n/lki.json b/Flow/i18n/lki.json
index 752f4b9a..55cdab92 100644
--- a/Flow/i18n/lki.json
+++ b/Flow/i18n/lki.json
@@ -1,8 +1,25 @@
{
"@metadata": {
"authors": [
- "Hosseinblue"
+ "Hosseinblue",
+ "Lakzon",
+ "Quiddity"
]
},
- "flow-moderation-confirmation-delete-topic": "ئئ تاپیکۀ پاک بیۀسا"
+ "flow-board-collapse-description": "آشاردن توضیحةل",
+ "flow-board-expand-description": "نمایش توضیحات",
+ "flow-edit-header-link": "ویرایش توضیحةل",
+ "flow-error-missing-header-content": "باید توضیحاتی وارد کنید.",
+ "flow-error-search": "ما نمی‌توانیم جستجویتان به دلیل یک مشکل موقت کامل کنیم. لطفاً بعداً دوباره تلاش کنید.",
+ "flow-edit-header-submit": "توضیحات بِیل(ذخیره کە)",
+ "flow-edit-header-submit-anonymously": "توضیحات بەصورت نادیاری بِیل(ذخیره کە)",
+ "flow-rev-message-create-header": "$1 سرفصل وةڵگة {{GENDER:$2|ایجاد کردێ}}",
+ "flow-rev-message-edit-header": "$1 سرفصل صفحه را {{GENDER:$2|ویرایش کرد}}",
+ "flow-link-header-revision": "نسخهٔ توضیحات",
+ "flow-moderation-confirmation-delete-topic": "اێ تاپیکە پاک بیەسا",
+ "flow-whatlinkshere-header": "از [$1 توضیحات]",
+ "flow-special-enableflow-header": "توضیحات اولیه از تخت جریان (ویکی‌متن)",
+ "apihelp-flow+edit-header-param-content": "نۆم جِک(محتوا)أڕا توضیحەل",
+ "apihelp-flow+edit-header-param-format": "قالب توضیحات (wikitext|html)",
+ "flow-undo-edit-header": "در حال ویرایش توضیحات"
}
diff --git a/Flow/i18n/lt.json b/Flow/i18n/lt.json
index a1885da1..3380e814 100644
--- a/Flow/i18n/lt.json
+++ b/Flow/i18n/lt.json
@@ -2,20 +2,287 @@
"@metadata": {
"authors": [
"Robotukas11",
- "Pofka"
+ "Pofka",
+ "Zygimantus",
+ "Nnemo",
+ "Eitvys200"
]
},
- "flow-error-external": "Įvyko klaida.<br>Gautas klaidos pranešimas: $1",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Nebesekti}} naujos „$1“ veiklos",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Jūs}} nebesekate puslapio „$1“",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Tai nepaveiks atskirų temų, kurias {{GENDER:$3|jūs}} stebite. Gali bet kada vėl pradėti sekti [$2 šį puslapį].",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Nebestebėti}} šios temos",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Jūs}} nebesekate „$1“",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Jūs}} galite sekti [$2 šią temą] bet kada.",
+ "flow-desc": "Diskusijų sistema",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|ištrynė}} [$4 įrašą] „[[$3|$5]]“ [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|ištrynė}} įrašą temoje [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|atkūrė}} [$4 įrašą] „[[$3|$5]]“ [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|atkūrė}} įrašą temoje [[$3]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|ištrynė}} [$4 įrašą] „[[$3|$5]]“ [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|ištrynė}} įrašą temoje [[$3]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|ištrynė}} temą „[[$3|$5]]“ [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|ištrynė}} temą [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|atkūrė}} temą „[[$3|$5]]“ [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|atkūrė}} temą [[$3]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|ištrynė}} temą „[[$3|$5]]“ [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|ištrynė}} temą [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|pažymėjo}} temą „[[$3|$5]]“ kaip išspręsta [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|pažymėjo}} temą kaip išspręsta [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|atnaujino}} temą „[[$3|$5]]“ [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|atnaujino}} temą [[$3]]",
+ "flow-board-header-browse-topics-link": "Naršyti temas",
+ "flow-board-header": "Apie šį forumą",
+ "flow-board-description-can-not-edit": "Neredaguojamas",
+ "flow-board-collapse-description": "Slėpti aprašymą",
+ "flow-board-expand-description": "Rodyti aprašymą",
+ "flow-topic-collapse-siderail": "Skaityti visame plotyje",
+ "flow-topic-expand-siderail": "Skaityti fiksuotame plotyje",
+ "flow-edit-header-link": "Redaguoti aprašymą",
+ "flow-post-moderated-toggle-hide-show": "Rodyti komentarą, kurį {{GENDER:$1|paslėpė}} $2",
+ "flow-post-moderated-toggle-delete-show": "Rodyti komentarą, kurį {{GENDER:$1|ištrynė}} $2",
+ "flow-post-moderated-toggle-hide-hide": "Slėpti komentarą, kurį {{GENDER:$1|paslėpė}} $2",
+ "flow-post-moderated-toggle-delete-hide": "Slėpti komentarą, kurį {{GENDER:$1|ištrynė}} $2",
+ "flow-topic-moderated-reason-prefix": "Priežastis:",
+ "flow-hide-post-content": "Šį komentarą {{GENDER:$1|paslėpė}} 1$ ([$2 istorija])",
+ "flow-hide-title-content": "Tema buvo {{GENDER:$1|paslėpta}} $1",
+ "flow-hide-header-content": "{{GENDER:$1|Paslėpta}} $2",
+ "flow-delete-post-content": "Komentaras buvo {{GENDER:$1|ištrintas}} $1 ([$2 istorija])",
+ "flow-delete-title-content": "Tema buvo {{GENDER:$1|ištrinta}} $1",
+ "flow-delete-header-content": "{{GENDER:$1|Ištrinta}} $2",
+ "flow-post-actions": "Veiksmai",
+ "flow-topic-actions": "Veiksmai",
+ "flow-cancel": "Atšaukti",
+ "flow-skip-summary": "Praleisti",
+ "flow-edit-summary-placeholder": "Trumpai aprašykite šios diskusijos rezultatą",
+ "flow-summary-authored": "$1 santrauka",
+ "flow-summary-edited": "Santrauką paskutinį kartą {{GENDER:$1|redagavo}} $1",
+ "flow-show-change": "Rodyti pakeitimus",
+ "flow-last-modified-by": "Paskutinį kartą {{GENDER:$1|keitė}} $1",
+ "flow-stub-post-content": "<em>Dėl techninės klaidos šis įrašas negali būti pateiktas.</em>",
+ "flow-newtopic-title-placeholder": "Nauja tema",
+ "flow-newtopic-content-placeholder": "Rašyti naujų žinutę „$1“",
+ "flow-newtopic-header": "Pridėti naują temą",
+ "flow-newtopic-save": "Pridėti temą",
+ "flow-newtopic-save-anonymously": "Pridėti temą anonimiškai",
+ "flow-newtopic-start-placeholder": "Pradėti naują temą",
+ "flow-newtopic-first-heading": "Pradėti naują temą $1",
+ "flow-summarize-topic-placeholder": "Prašome apibendrinti šią diskusiją",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Pakomentavo}} „$2“",
+ "flow-reply-topic-title-placeholder": "Atsakyti „$1“",
+ "flow-reply-link": "{{GENDER:$1|Atsakyti}}",
+ "flow-reply-link-anonymously": "Atsakyti anonimiškai",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Padėkoti}}}}",
+ "flow-thank-link-title": "Viešai {{GENDER:$1|{{GENDER:$2|padėkoti}}}} autoriui",
+ "flow-history-action-delete-post": "ištrinti",
+ "flow-history-action-hide-post": "slėpti",
+ "flow-history-action-undelete-post": "atkurti ištrintą",
+ "flow-history-action-unhide-post": "neslėpti",
+ "flow-history-action-restore-post": "atkurti",
+ "flow-history-action-lock-topic": "išspręsti",
+ "flow-history-action-unlock-topic": "atidaryti iš naujo",
+ "flow-post-edited": "Įrašas {{GENDER:$1|redaguotas}} $1 $2",
+ "flow-post-action-view": "Nuoroda į šią vietą",
+ "flow-post-action-post-history": "Istorija",
+ "flow-post-action-delete-post": "Ištrinti",
+ "flow-post-action-hide-post": "Slėpti",
+ "flow-post-action-edit-post": "Redaguoti",
+ "flow-post-action-edit-post-submit": "Išsaugoti pakeitimus",
+ "flow-post-action-edit-post-submit-anonymously": "Išsaugoti pakeitimus anonimiškai",
+ "flow-post-action-undelete-post": "Atkurti ištrintą",
+ "flow-post-action-unhide-post": "Neslėpti",
+ "flow-post-action-restore-post": "Atkurti",
+ "flow-post-action-undo-moderation": "Anuliuoti",
+ "flow-topic-action-view": "Nuoroda į šią vietą",
+ "flow-topic-action-watchlist": "Stebimų sąrašas",
+ "flow-topic-action-edit-title": "Redaguoti pavadinimą",
+ "flow-topic-action-history": "Istorija",
+ "flow-topic-action-hide-topic": "Slėpti temą",
+ "flow-topic-action-delete-topic": "Trinti temą",
+ "flow-topic-action-lock-topic": "Pažymėti kaip išspręstą",
+ "flow-topic-action-unlock-topic": "Atnaujinti temą",
+ "flow-topic-action-summarize-topic": "Apibendrinti",
+ "flow-topic-action-resummarize-topic": "Redaguoti temos santrauką",
+ "flow-topic-action-update-topic-summary": "Atnaujinti santrauką",
+ "flow-topic-action-unhide-topic": "Nebeslėpti temos",
+ "flow-topic-action-undelete-topic": "Atkurti ištrintą temą",
+ "flow-topic-action-restore-topic": "Atkurti temą",
+ "flow-topic-action-undo-moderation": "Anuliuoti",
+ "flow-topic-notification-subscribe-title": "Ši tema buvo pridėta prie {{GENDER:$1|jūsų}} stebimųjų sąrašo.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Jūs}} gausite pranešimus apie visą veiklą šioje temoje.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Jūs}} prenumeruojate ši diskusijų forumą!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Jūs}} gausite pranešimą, kai bus sukurta nauja tema šiame forume.",
+ "flow-topic-action-watchlist-add": "Prenumeruoti šią temą",
+ "flow-topic-action-watchlist-remove": "Nutraukti prenumeratą",
+ "flow-error-allowcreation-flow-create-board": "Vartotojas neturi „{{int:right-flow-create-board}}“ teisės",
+ "flow-error-can-not-edit-logged-out": "Šiuo metu negalite dalyvauti. Galite pabandyti prisijungti.",
+ "flow-error-can-not-edit-logged-in": "Šiuo metu negalite dalyvauti, nes neturi reikiamų teisių.",
+ "flow-error-http": "Įvyko klaida susisiekiant su serveriu.",
+ "flow-error-external": "Įvyko klaida. Gautas klaidos pranešimas: $1",
+ "flow-error-topic-is-locked": "Tema išspręsta, tad tolesnė veikla nėra galima.",
+ "flow-error-missing-content": "Įrašas neturi turinio. Turinys privalomas, kad įrašas būtų išsaugotas.",
+ "flow-error-missing-summary": "Turite pateikti santrauką.",
+ "flow-error-missing-title": "Tema neturi pavadinimo. Pavadinimas būtinas, kad tema būtų išsaugota.",
+ "flow-error-protected-autoconfirmed-logged-in": "Šis forumas yra apsaugotas. Tik automatiškai patvirtinti vartotojai gali dalyvauti. Priežastis: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Šis forumas yra apsaugotas. Tik prisijungę, automatiškai patvirtinti vartotojai gali dalyvauti. Priežastis: $1",
+ "flow-error-protected-sysop-logged-in": "Šis forumas yra apsaugotas. Tik vartotojai su administratoriaus privilegijomis gali dalyvauti. Priežastis: $1",
+ "flow-error-protected-sysop-logged-out": "Šis forumas yra apsaugotas. Tik prisijungę vartotojai su administratoriaus privilegijomis gali dalyvauti. Priežastis: $1",
+ "flow-error-protected-unknown-reason": "Nežinoma",
+ "flow-error-invalid-moderation-reason": "Prašome pateikti priežastį moderavimui.",
+ "flow-error-not-allowed": "Nepakanka teisių, kad būtų atliktas šis veiksmas.",
+ "flow-error-not-allowed-hide": "Ši tema buvo paslėpta.",
"flow-error-not-allowed-reply-to-hide-topic": "Jūs negalite atsakyti, nes ši tema buvo paslėpta.",
+ "flow-error-not-allowed-delete": "Ši tema buvo ištrinta.",
"flow-error-not-allowed-reply-to-delete-topic": "Jūs negalite atsakyti, nes ši tema buvo ištrinta.",
"flow-error-not-allowed-suppress": "Ši tema buvo ištrinta.",
"flow-error-not-allowed-reply-to-suppress-topic": "Jūs negalite atsakyti, nes ši tema buvo ištrinta.",
+ "flow-error-not-allowed-hide-extract": "Ši tema buvo paslėpta. Temos slėpimo žurnalas pateiktas žemiau.",
+ "flow-error-not-allowed-delete-extract": "Ši tema buvo ištrinta. Temos ištrynimo žurnalas pateiktas žemiau.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Negalite atsakyti, nes tema buvo ištrinta. Temos trynimo žurnalas pateikiamas žemiau.",
+ "flow-error-not-allowed-suppress-extract": "Tema buvo ištrinta. Temos trynimo žurnalas pateikiamas žemiau.",
+ "flow-error-title-too-long": "Temų pavadinimai apriboti iki $1 {{PLURAL:$1|baito|baitų}}.",
+ "flow-error-not-a-post": "Temos pavadinimas negali būti išsaugotas kaip įrašas.",
+ "flow-error-missing-header-content": "Jūs turite pateikti aprašymą.",
+ "flow-error-default": "Įvyko klaida.",
+ "flow-error-invalid-title": "Buvo pateiktas negalimas puslapio pavadinimas.",
+ "flow-error-fail-load-history": "Nepavyko įkelti istorijos turinio.",
+ "flow-error-insufficient-permission": "Nepakankamos teisės prieigai prie turinio.",
+ "flow-error-fail-load-data": "Nepavyko įkelti prašomų duomenų.",
+ "flow-error-process-data": "Įvyko klaida apdorojant duomenys jūsų užklausoje.",
+ "flow-error-no-render": "Nurodytas veiksmas nebuvo atpažintas.",
+ "flow-error-no-commit": "Nurodytas veiksmas negali būti išsaugotas.",
+ "flow-error-move-topic": "Temos puslapio perkėlimas šiuo metu nepalaikomas.",
+ "flow-error-invalid-topic-uuid-title": "Blogas pavadinimas",
+ "flow-error-unknown-workflow-id-title": "Nežinoma tema",
+ "flow-error-unknown-workflow-id": "Prašoma tema neegzistuoja.",
+ "flow-edit-header-placeholder": "Apibūdinkite šį diskusijų forumą",
+ "flow-edit-header-submit": "Išsaugoti aprašymą",
+ "flow-edit-header-submit-anonymously": "Išsaugoti aprašymą anonimiškai",
+ "flow-edit-title-submit": "Keisti pavadinimą",
+ "flow-edit-title-submit-anonymously": "Keisti pavadinimą anonimiškai",
+ "flow-edit-post-submit": "Siųsti pakeitimus",
+ "flow-edit-post-submit-anonymously": "Siųsti pakeitimus anonimiškai",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|redagavo}} [$3 komentarą] temoje „$4“",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Redagavo}} įrašą",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|pakomentavo}}] „$4“ (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|komentaras|komentarai}}</strong> {{PLURAL:$1|buvo pridėtas|buvo pridėti}}",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|sukūrė}} temą „[$3 $4]“",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Sukūrė}} naują temą",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|pakeitė}} temos pavadinimą iš „$5“ į „[$3 $4]“",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|sukūrė}} aprašymą",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|redagavo}} aprašymą",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|sukūrė}} temos santrauką $3",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|redagavo}} temos santrauką $3",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|paslėpė}} „$6“ [$4 komentarą] (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|ištrynė}} „$6“ [$4 komentarą] (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|atkūrė}} „$6“ [$4 komentarą] (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|paslepė}} „$6“ [$4 temą] (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|ištrynė}} „$6“ [$4 temą] (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|pažymėjo}} „$6“ [$4 temą] kaip išspręsta (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "pažymėtas kaip išspręstas",
+ "flow-rev-message-restore-topic-reason": "atidarytas iš naujo",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|atkūrė}} „$6“ [$4 temą] (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 $2",
+ "flow-board-history": "„$1“ istorija",
+ "flow-board-history-empty": "Šis forumas šiuo metu neturi istorijos.",
+ "flow-topic-history": "„$1“ temos istorija",
+ "flow-history-last4": "Pastarosios 4 valandos",
+ "flow-history-day": "Šiandien",
+ "flow-history-week": "Praėjusią savaitę",
+ "flow-history-pages-topic": "Yra [$1 „$2“ forume]",
+ "flow-history-pages-post": "Yra [$1 $2]",
+ "flow-topic-comments": "{{PLURAL:$1|Vienas komentaras|$1 komentarų|0={{GENDER:$2|Būkite pirmas pakomentavęs|Būkite pirma pakomentavusi}}!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Žiūrėti komentarą|Žiūrėti komentarus}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Slėpti komentarą|Slėpti komentarus}}",
+ "flow-comment-restored": "Komentaras atkurtas",
+ "flow-comment-deleted": "Komentaras ištrintas",
+ "flow-comment-hidden": "Komentaras paslėptas",
+ "flow-comment-moderated": "Komentaras moderuotas",
+ "flow-last-modified": "Paskutinį kartą keista prieš $1",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|atsakė}} <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 ir {{PLURAL:$5|dar vienas|$5 kitų|100=99+ kitų}} {{GENDER:$1|atsakė}} į <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|redagavo}} jūsų <span class=\"plainlinks\">[$5 įrašą]</span> [[$3|$4]].",
+ "flow-notification-edit-bundle": "$1 ir {{PLURAL:$5|dar vienas|$5 kitų|100=99+ kitų}} {{GENDER:$1|redagavo}} <span class=\"plainlinks\">[$4 įrašą]</span> „$2“ „$3“.",
+ "notification-header-flow-new-topic-v2": "Nauja tema sukurta <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Viena nauja tema|$1 naujos temos|100=99+ naujos temos}} <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Nauja tema buvo sukurta <strong>jūsų aptarimo puslapyje</strong>: „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Viena nauja tema|$1 naujos temos|100=99+ naujos temos}} <strong>jūsų aptarimo puslapyje</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|atsakė}} į „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Vienas naujas atsakymas|$1 nauji atsakymai|100=99+ nauji atsakymai}} „<strong>$3</strong>“.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|atsakė}} <strong>jūsų aptarimo puslapyje „$4“</strong>.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Vienas naujas atsakymas|$1 naujų atsakymų|100=99+ naujų atsakymų}} <strong>jūsų aptarimų puslapyje</strong> „<strong>$3</strong>“.",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Jūsų}} įrašas „<strong>$1</strong>“ buvo pakeistas.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Jūsų}} įrašas „<strong>$1</strong>“ buvo pakeistas kelis kartus.",
+ "notification-header-flow-topic-renamed-v2": "Tema „<strong>$1</strong>“ buvo pervadinta į „<strong>$2</strong>“.",
+ "flow-notification-link-text-view-post": "Žiūrėti įrašą",
+ "flow-notification-link-text-view-topic": "Žiūrėti temą",
+ "flow-notification-link-text-view-topics": "Žiūrėti temas",
+ "flow-notification-reply-email-subject": "$2 $3",
+ "flow-link-post": "įrašas",
+ "flow-link-topic": "tema",
+ "flow-link-history": "istorija",
+ "flow-link-post-revision": "įrašo peržiūra",
+ "flow-link-topic-revision": "temos peržiūra",
+ "flow-link-header-revision": "aprašymo peržiūra",
"flow-link-summary-revision": "santraukos peržiūra",
- "apihelp-flow+edit-header-param-format": "Antraštės formatas (wikitext|html)",
- "apihelp-flow+reply-param-format": "Naujo pranešimo formatas (wikitext|html)",
+ "flow-moderation-title-delete-post": "Ištrinti įrašą?",
+ "flow-moderation-title-hide-post": "Slėpti įrašą?",
+ "flow-moderation-title-undelete-post": "Atkurti įrašą?",
+ "flow-moderation-title-unhide-post": "Nebeslėpti įrašo?",
+ "flow-moderation-confirm-delete-post": "Ištrinti",
+ "flow-moderation-confirm-hide-post": "Slėpti",
+ "flow-moderation-confirm-undelete-post": "Atkurti",
+ "flow-moderation-confirm-unhide-post": "Neslėpti",
+ "flow-moderation-confirm-delete-topic": "Ištrinti",
+ "flow-moderation-confirm-hide-topic": "Slėpti",
+ "flow-moderation-confirm-undelete-topic": "Atkurti",
+ "flow-moderation-confirm-unhide-topic": "Neslėpti",
+ "flow-moderation-confirmation-delete-topic": "Ši tema buvo ištrinta.",
+ "flow-moderation-confirmation-hide-topic": "Ši tema buvo paslėpta.",
+ "flow-moderation-title-delete-topic": "Ištrinti temą?",
+ "flow-moderation-title-hide-topic": "Paslėpti temą?",
+ "flow-moderation-title-undelete-topic": "Atkurti temą?",
+ "flow-moderation-title-unhide-topic": "Nebeslėpti temos?",
+ "flow-topic-first-heading": "$1 tema",
+ "flow-topic-html-title": "$1 $2",
+ "flow-topic-count": "Temos ($1)",
+ "flow-load-more": "Įkelti daugiau",
+ "flow-no-more-fwd": "Nėra senesnių temų",
+ "flow-newest-topics": "Naujausios temos",
+ "flow-recent-topics": "Neseniai aktyvios temos",
+ "flow-special-type": "Tipas",
+ "flow-special-type-post": "Įrašas",
+ "flow-special-uuid": "UUID",
+ "flow-post-undo-hide": "anuliuoti slėpimą",
+ "flow-post-undo-delete": "anuliuoti trynimą",
+ "flow-topic-undo-hide": "anuliuoti slėpimą",
+ "flow-topic-undo-delete": "anuliuoti trynimą",
+ "flow-edited": "Redaguota",
+ "flow-edited-by": "Redagavo $1",
+ "flow-edited-by-header": "Forumo aprašymą redagavo $1",
+ "flow-edited-by-topic-title": "Temos pavadinimą redagavo $1",
+ "flow-previous-diff": "← Senesnis keitimas",
+ "flow-next-diff": "Naujesnis keitimas →",
"flow-undo": "atšaukti",
"flow-undo-latest-revision": "Dabartinė versija",
"flow-undo-your-text": "Jūsų tekstas",
+ "flow-undo-edit-header": "Aprašymas redaguojamas",
"flow-undo-edit-topic-summary": "Temos santraukos redagavimas",
- "flow-undo-edit-post": "Pranešimo redagavimas"
+ "flow-undo-edit-post": "Pranešimo redagavimas",
+ "flow-ve-mention-context-item-label": "Paminėti",
+ "flow-ve-mention-inspector-title": "Paminėjimas",
+ "flow-ve-mention-inspector-remove-label": "Pašalinti",
+ "flow-ve-mention-placeholder": "Vartotojo vardas",
+ "flow-ve-mention-tool-title": "Paminėti vartotoją",
+ "flow-wikitext-editor-help-preview-the-result": "peržiūrėti rezultatą",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nauja diskusijų sistema $2",
+ "flow-dialog-cancelconfirm-title": "Ar esate tikri?",
+ "flow-dialog-cancelconfirm-message": "Ar esate tikri, kad norite atšaukti neišsaugoję?",
+ "flow-dialog-cancelconfirm-keep": "Tęsti redagavimą",
+ "flow-dialog-cancelconfirm-discard": "Atsisakyti pakeitimų",
+ "flow-optin-archive-wikitext": "Perkelti vikiteksto puslapį, kad diskusijų lentoje atsirastų kambarys.",
+ "flow-optin-archive-flow-board": "Perkelti diskusijų puslapį vikiteksto puslapio kambario sukūrimui.",
+ "flow-optin-restore-wikitext": "Atkurti archyvuotą vikiteksto puslapį.",
+ "flow-optin-restore-flow-board": "Atkurti archyvuotas diskusijų lentas.",
+ "flow-action-not-page": "Puslapio objektas yra bloga klasė"
}
diff --git a/Flow/i18n/lv.json b/Flow/i18n/lv.json
index 4939b3ac..d7e5531d 100644
--- a/Flow/i18n/lv.json
+++ b/Flow/i18n/lv.json
@@ -3,20 +3,28 @@
"authors": [
"Papuass",
"Edgars2007",
- "Silraks"
+ "Silraks",
+ "Nnemo",
+ "Macofe",
+ "Matiia"
]
},
- "enableflow": "Aktivizēt Flow",
+ "enablestructureddiscussions": "Aktivizēt Flow",
+ "notification-dynamic-actions-flow-topic-unwatch": "Pārtraukt šīs tēmas vērošanu",
"log-name-flow": "Flow darbību reģistrs",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|izdzēsa}} [$4 ierakstu] lapas [[$6]] tēmā \"[[$3|$5]]\"",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|atjaunoja}} [$4 ierakstu] lapas [[$6]] tēmā \"[[$3|$5]]\"",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|cenzēja}} [$4 ierakstu] par \"[[$3|$5]]\" lapā [[$6]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|izdzēsa}} [$4 ierakstu] tēmā \"[[$3|$5]]\" lapā [[$6]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|izdzēsa}} tēmu \"[[$3|$5]]\" lapā [[$6]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|atjaunoja}} tēmu \"[[$3|$5]]\" lapā [[$6]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|cenzēja}} tematu \"[[$3|$5]]\" par [[$6]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|izdzēsa}} tēmu \"[[$3|$5]]\" lapā [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|izdzēsa}} tēmu [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$3]] esošai [[$1|$2]] tika pārveidots no LiquidThreads uz Flow",
"flow-board-header-browse-topics-link": "Pārlūkot tēmas",
"flow-board-header": "Par šo lapu",
+ "flow-board-description-can-not-edit": "Nav labojams",
"flow-board-collapse-description": "Paslēpt aprakstu",
"flow-board-expand-description": "Rādīt aprakstu",
"flow-topic-collapse-siderail": "Lasīt pilnā platumā",
@@ -24,6 +32,7 @@
"flow-edit-header-link": "Labot aprakstu",
"flow-post-moderated-toggle-hide-show": "Rādīt komentāru, ko {{GENDER:$1|paslēpis|paslēpusi}} $2",
"flow-post-moderated-toggle-delete-show": "Rādīt komentāru, ko {{GENDER:$1|dzēsis|dzēsusi}} $2",
+ "flow-post-moderated-toggle-suppress-show": "Rādīt komentāru, ko {{GENDER:$1|cenzēja}} $2",
"flow-post-moderated-toggle-hide-hide": "Slēpt komentāru, ko {{GENDER:$1|paslēpis|paslēpusi}} $2",
"flow-post-moderated-toggle-delete-hide": "Slēpt komentāru, ko {{GENDER:$1|dzēsis|dzēsusi}} $2",
"flow-topic-moderated-reason-prefix": "Iemesls:",
@@ -33,10 +42,12 @@
"flow-delete-post-content": "Šo komentāru {{GENDER:$1|izdzēsa}} $1 ([$2 vēsture])",
"flow-delete-title-content": "Šo tēmu {{GENDER:$1|izdzēsa}} $1",
"flow-delete-header-content": "{{GENDER:$1|Idzēsa}} $2",
+ "flow-suppress-post-content": "Šo komentāru {{GENDER:$1|cenzēja}} $1 ([$2 vēsture])",
+ "flow-suppress-header-content": "{{GENDER:$1|Cenzējis|Cenzējusi}} $2",
"flow-post-actions": "Darbības",
"flow-topic-actions": "Darbības",
"flow-cancel": "Atcelt",
- "flow-skip-summary": "Izlaist kopsavilkumu",
+ "flow-skip-summary": "Izlaist",
"flow-edit-summary-placeholder": "Īsumā apraksti diskusijas iznākumu",
"flow-summary-authored": "$1 publicēts kopsavilkums",
"flow-summary-edited": "Pēdējais kopsavilkumu {{GENDER:$1|laboja}} $1",
@@ -54,6 +65,7 @@
"flow-reply-link": "{{GENDER:$1|Atbildēt}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Pateikties}}}}",
"flow-thank-link-title": "Publiski {{GENDER:$1|{{GENDER:$2|pateikties}}}} lietotājam",
+ "flow-history-action-suppress-post": "cenzēt",
"flow-history-action-delete-post": "dzēst",
"flow-history-action-hide-post": "paslēpt",
"flow-history-action-undelete-post": "atcelt dzēšanu",
@@ -62,6 +74,7 @@
"flow-post-edited": "Ierakstu $2 {{GENDER:$1|laboja}} $1",
"flow-post-action-view": "Pastāvīgā saite",
"flow-post-action-post-history": "Vēsture",
+ "flow-post-action-suppress-post": "Cenzēt",
"flow-post-action-delete-post": "Dzēst",
"flow-post-action-hide-post": "Slēpt",
"flow-post-action-edit-post": "Labot",
@@ -78,6 +91,8 @@
"flow-topic-action-summarize-topic": "Pievienot kopsavilkumu",
"flow-topic-action-resummarize-topic": "Labot tēmas kopsavilkumu",
"flow-topic-action-update-topic-summary": "Atjaunināt kopsavilkumu",
+ "flow-topic-action-suppress-topic": "Cenzēt tēmu",
+ "flow-topic-action-restore-topic": "Atjaunot tēmu",
"flow-topic-action-undo-moderation": "Atcelt",
"flow-topic-notification-subscribe-title": "Tēma pievienota {{GENDER:$1|tavam}} uzraugāmo tēmu sarakstam.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Tu}} saņemsi paziņojumus par visām darbībām šajā tēmā.",
@@ -85,15 +100,12 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Tu}} saņemsi paziņojumu, kad šajā lapā tiks izveidota jauna tēma.",
"flow-topic-action-watchlist-add": "Uzraudzīt šo tēmu",
"flow-error-http": "Sazinoties ar serveri, radās kļūda.",
- "flow-error-other": "Neparedzēta kļūda.",
- "flow-error-external": "Notikusi kļūda.<br />Saņemtais kļūdas ziņojums: $1",
+ "flow-error-external": "Notikusi kļūda. <br />Saņemtais kļūdas ziņojums: $1",
"flow-error-topic-is-locked": "Šī tēma ir atrisināta, tāpēc turpmākas darbības nav iespējamas.",
- "flow-error-external-multi": "Radušās kļūdas:<br />$1",
"flow-error-missing-content": "Šim ierakstam nav satura. Tas ir nepieciešams ieraksta saglabāšanai.",
"flow-error-missing-summary": "Kopsavilkumam nav satura. Tas ir vajadzīgs kopsavilkuma saglabāšanai",
"flow-error-missing-title": "Tēmai nav nosaukuma. Tas ir vajadzīgs tēmas saglabāšanai",
- "flow-error-delete-failure": "Dzēšana nebija veiksmīga.",
- "flow-error-hide-failure": "Paslēpšana nebija veiksmīga.",
+ "flow-error-protected-unknown-reason": "Nav zināms",
"flow-error-not-allowed-hide": "Šī tēma ir tikusi paslēpta.",
"flow-error-not-allowed-reply-to-hide-topic": "Tu nevari atbildēt, jo šī tēma ir paslēpta",
"flow-error-not-allowed-delete": "Tēma tikusi dzēsta.",
@@ -101,10 +113,11 @@
"flow-error-not-allowed-suppress": "Tēma tikusi dzēsta.",
"flow-error-not-allowed-reply-to-suppress-topic": "Tu nevari atbildēt, jo šī tēma ir izdzēsta",
"flow-error-not-allowed-suppress-extract": "Tēma ir tikusi izdzēsta. Zemāk parādīts dzēšanas reģistrs tēmai.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Tu nevari atbildēt, jo šis temats ir cenzēts. Zemāk pieejams cenzēšanas žurnāla ieraksts.",
"flow-error-title-too-long": "Tēmas nosaukums nedrīkst būt lielāks par $1 {{PLURAL:$1|baitu|baitiem}}.",
"flow-error-no-existing-workflow": "Šī lapa vēl neeksistē.",
"flow-error-not-a-post": "Tēmas nosaukums nevar tikt saglabāts kā ieraksts.",
- "flow-error-missing-header-content": "Aprakstam nav satura. Tas ir vajadzīgs apraksta saglabāšanai.",
+ "flow-error-missing-header-content": "Tev ir jānorāda apraksts.",
"flow-error-missing-prev-revision-identifier": "Trūkst iepriekšējās versijas identifikatora.",
"flow-error-prev-revision-mismatch": "Cits lietotājs pirms dažām sekundēm laboja šo ierakstu. Esi pārliecināts, ka {{GENDER:$3|Tu}} vēlies pārrakstīt pēdējo labojumu?",
"flow-error-prev-revision-does-not-exist": "Nevarēja atrast iepriekšējo versiju.",
@@ -126,7 +139,7 @@
"flow-edit-header-submit": "Saglabāt aprakstu",
"flow-edit-title-submit": "Nomainīt nosaukumu",
"flow-edit-post-submit": "Apstiprināt labojumus",
- "flow-rev-message-edit-post": "Labot ieraksta saturu",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|laboja}} [$3 komentāru] par \"$4\"",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Laboja}} ierakstu",
"flow-rev-message-new-post": "$1 {{GENDER:$2|izveidoja}} tēmu \"[$3 $4]\"",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Izveidoja}} jaunu tēmu",
@@ -135,10 +148,11 @@
"flow-rev-message-edit-header": "$1 {{GENDER:$2|izmainīja}} aprakstu",
"flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|izveidoja}} tēmas \"$3\" kopsavilkumu",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|laboja}} tēmas \"$3\" kopsavilkumu",
- "flow-rev-message-deleted-post": "Dzēsts ieraksts",
- "flow-rev-message-suppressed-post": "Cenzēts ieraksts",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|izdzēsa}} [$4 komentāru] par \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|cenzēja}} [$4 komentāru] par \"$6\" (<em>$5</em>)",
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|paslēpa}} [$4 tēmu] \"$6\" (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|izdzēsa}} [$4 tēmu] \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|cenzēja}} [$4 tematu] \"$6\" (<em>$5</em>)",
"flow-rev-message-locked-topic": "$1 {{GENDER:$2|atzīmēja}} [$4 tēmu] \"$6\" kā atrisinātu (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "Atzīmēta kā atrisinātu",
"flow-rc-topic-of-board": "$1 lapā \"$2\"",
@@ -159,10 +173,12 @@
"flow-last-modified": "Pēdējoreiz labots apmēram $1",
"flow-notification-reply": "$1 {{GENDER:$1|atbildēja}} par <span class=\"plainlinks\">[$5 $2]</span> lapā \"$4\".",
"flow-notification-reply-bundle": "$1 un $5 {{PLURAL:$6|citi|cits|citi}} {{GENDER:$1|atbildēja}} par <span class=\"plainlinks\">[$4 $2]</span> lapā \"$3\".",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|atbildēja}} tēmā \"<strong>$4</strong>\".",
"flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|izveidoja}} jaunu tēmu lapā \"'''$3'''\".",
"flow-notification-link-text-view-post": "Skatīt ierakstu",
"flow-notification-link-text-view-topic": "Skatīt tēmu",
- "flow-notification-reply-email-subject": "$1 {{GENDER:$1|atbildēja}} par tēmu",
+ "flow-notification-link-text-view-topics": "Apskatīt tēmas",
+ "flow-notification-reply-email-subject": "$2 par $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|atbildēja}} par \"$2\" lapā \"$3\"",
"flow-notification-reply-email-batch-bundle-body": "$1 un $4 {{PLURAL:$5|citi|cits|citi}} {{GENDER:$1|atbildēja}} par \"$2\" lapā \"$3\"",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|pieminēja}} {{GENDER:$3|Tevi}} lapā \"$2\"",
@@ -178,22 +194,31 @@
"flow-link-topic-revision": "ieraksta versija",
"flow-link-header-revision": "apraksta versija",
"flow-link-summary-revision": "kopsavilkuma versija",
+ "flow-moderation-title-suppress-post": "Cenzēt ierakstu?",
"flow-moderation-title-delete-post": "Dzēst ierakstu?",
"flow-moderation-title-hide-post": "Paslēpt ierakstu?",
+ "flow-moderation-placeholder-suppress-post": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc tu cenzē šo ierakstu.",
"flow-moderation-placeholder-delete-post": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc Tu dzēs šo ierakstu.",
"flow-moderation-placeholder-hide-post": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc Tu slēp šo ierakstu.",
+ "flow-moderation-confirm-suppress-post": "Cenzēt",
"flow-moderation-confirm-delete-post": "Dzēst",
"flow-moderation-confirm-hide-post": "Slēpt",
+ "flow-moderation-confirm-suppress-topic": "Cenzēt",
"flow-moderation-confirm-delete-topic": "Dzēst",
"flow-moderation-confirm-hide-topic": "Slēpt",
+ "flow-moderation-confirmation-suppress-post": "Šis ieraksts tika cenzēts.\n{{GENDER:$2|Apsver}} apspriest šo ierakstu ar $1.",
+ "flow-moderation-confirmation-suppress-topic": "Šis temats ir ticis cenzēts.",
"flow-moderation-confirmation-delete-topic": "Šī tēma tika izdzēsta.",
"flow-moderation-confirmation-hide-topic": "Šī tēma tika paslēpta.",
+ "flow-moderation-title-suppress-topic": "Cenzēt tēmu?",
"flow-moderation-title-delete-topic": "Dzēst tēmu?",
"flow-moderation-title-hide-topic": "Paslēpt tēmu?",
+ "flow-moderation-placeholder-suppress-topic": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc tu cenzē šo tematu.",
"flow-moderation-placeholder-delete-topic": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc Tu dzēs šo tēmu.",
"flow-moderation-placeholder-hide-topic": "Lūdzu, {{GENDER:$3|paskaidro}}, kāpēc Tu slēp šo tēmu.",
"flow-topic-permalink-warning-user-board": "Tēma tika sākta [$2 {{GENDER:$1|$1}} lapā]",
"right-flow-hide": "Paslēpt Flow tēmas un ierakstus",
+ "right-flow-suppress": "Cenzēt Flow versijas",
"flow-topic-count": "Tēmas ($1)",
"flow-load-more": "Ielādēt vairāk",
"flow-no-more-fwd": "Nav vecāku tēmu",
@@ -203,13 +228,16 @@
"flow-whatlinkshere-post": "no [$1 ieraksta]",
"flow-whatlinkshere-header": "no [$1 apraksta]",
"flow-whatlinkshere-post-summary": "no [$1 kopsavilkuma]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
+ "flow-special-type": "Veids",
"flow-special-type-post": "Ieraksts",
"flow-special-type-workflow": "Darbplūsma",
"flow-special-uuid": "UUID",
"flow-special-enableflow-header": "Sākotnējais lapas apraksts (vikiteksts)",
"flow-special-enableflow-board-creation-not-allowed": "Tev nav atļauts izveidot Flow lapu [[:$1]].",
"flow-special-enableflow-confirmation": "Tu esi veiksmīgi izveidojis Flow lapu [[:$1]].",
+ "flow-post-undo-suppress": "atcelt cenzēšanu",
+ "flow-topic-undo-suppress": "atcelt cenzēšanu",
"flow-edited": "Labots",
"flow-previous-diff": "← Vecāks labojums",
"flow-next-diff": "Jaunāks labojums →",
@@ -219,6 +247,8 @@
"flow-undo-edit-header": "Labots apraksts",
"flow-undo-edit-topic-summary": "Labots tēmas kopsavilkums",
"flow-undo-edit-post": "Labots ieraksts",
+ "group-flow-bot": "Flow boti",
+ "group-flow-bot-member": "Flow bots",
"flow-ve-mention-context-item-label": "Pieminēt",
"flow-ve-mention-inspector-title": "Pieminēt",
"flow-ve-mention-inspector-remove-label": "Noņemt",
@@ -226,12 +256,13 @@
"flow-ve-mention-tool-title": "Pieminēt lietotāju",
"flow-ve-mention-inspector-invalid-user": "Lietotājvārds \"$1\" nav reģistrēts.",
"flow-wikitext-editor-help-and-preview": "Vikiteksts $1, Tu vari $2 jebkurā laikā.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|izmanto formatējumu]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|izmanto formatējumu]]",
"flow-wikitext-editor-help-preview-the-result": "apskatīt pirmskatu",
- "flow-wikitext-switch-editor-tooltip": "Pārslēgties uz VisualEditor",
+ "flow-wikitext-switch-editor-tooltip": "Pārslēgties uz vizuālo redaktoru",
"flow-ve-switch-editor-tool-title": "Pārslēgties uz vikitekstu",
"flow-mark-revision-patrolled-link-text": "Atzīmēt šo lapu kā pārbaudītu",
"flow-mark-revision-patrolled-link-title": "Atzīmēt šo lapu kā pārbaudītu",
"flow-mark-diff-patrolled-link-text": "Atzīmēt kā pārbaudītu",
- "flow-mark-diff-patrolled-link-title": "Atzīmēt kā pārbaudītu"
+ "flow-mark-diff-patrolled-link-title": "Atzīmēt kā pārbaudītu",
+ "flow-dialog-cancelconfirm-title": "Vai esi pārliecināts?"
}
diff --git a/Flow/i18n/mai.json b/Flow/i18n/mai.json
index d4ac7426..6957dd2a 100644
--- a/Flow/i18n/mai.json
+++ b/Flow/i18n/mai.json
@@ -1,10 +1,13 @@
{
"@metadata": {
"authors": [
- "Bijay chaurasia"
+ "Bijay chaurasia",
+ "बिप्लब आनन्द"
]
},
"flow-edit-header-link": "संचिका वर्णन",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|धन्यवाद दी}}}}",
"flow-edit-header-submit": "संचिका वर्णन",
- "flow-undo-edit-header": "वर्णन सम्पादनकरु"
+ "flow-undo-edit-header": "वर्णन सम्पादन करी",
+ "group-flow-bot": "फ्लो स्वचालक"
}
diff --git a/Flow/i18n/mg.json b/Flow/i18n/mg.json
index 689567bc..af97d171 100644
--- a/Flow/i18n/mg.json
+++ b/Flow/i18n/mg.json
@@ -3,6 +3,5 @@
"authors": [
"Jagwar"
]
- },
- "flow-edit-post-submit-overwrite": "Hanitsaka ny fiovana"
+ }
}
diff --git a/Flow/i18n/mk.json b/Flow/i18n/mk.json
index bb5b5d75..4da80b3c 100644
--- a/Flow/i18n/mk.json
+++ b/Flow/i18n/mk.json
@@ -3,25 +3,51 @@
"authors": [
"Amire80",
"Bjankuloski06",
- "Macofe"
+ "Macofe",
+ "Nnemo",
+ "Quiddity",
+ "Matiia"
]
},
- "enableflow": "Вклучи го Тек",
- "flow-desc": "Систем за раководење со работниот тек",
- "flow-talk-taken-over-comment": "/* Оваа страница е претворена во разговорница на Тек */",
- "log-name-flow": "Дневник на активности во текот",
+ "enablestructureddiscussions": "Вклучи го Тек",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Престанете}} со набљудување на новите активности на „$1“",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Повеќе не ја {{GENDER:$3|набљудувате}} страницата „$1“",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Ова нема да се однесува на поединечните теми што ги {{GENDER:$3|набљудувате}}. Можете да ја набљудувате [$2 страницава] во во секое време.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Престани}} со набљудување на темава",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Повеќе на ја {{GENDER:$3|набљудувате}} темата „$1“",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "Можете да ја {{GENDER:$3|набљудувате}} [$2 темава] во секое време.",
+ "flow-desc": "Разговорен систем",
+ "flow-talk-taken-over-comment": "/* Оваа страница е претворена во разговорница на Структурираните дискусии */",
+ "log-name-flow": "Дневник на активности во Структурираните дискусии",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|избриша}} [$4 објава] на „[[$3|$5]]“ на [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|избриша}} објава на тема на [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|поврати}} [$4 објава] на „[[$3|$5]]“ на [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|поврати}} објава на тема на [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|притаи}} [$4 објава] на „[[$3|$5]]“ на [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|скри}} објава на тема на [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|избриша}} [$4 објава] на „[[$3|$5]]“ на [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|избриша}} објава на тема на [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|ја избриша}} темата „[[$3|$5]]“ на [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|избриша}} тема на [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|ја избриша}} темата „[[$3|$5]]“ на [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|поврати}} тема на [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ја избриша}} темата „[[$3|$5]]“ на [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|скри}} тема на [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|ја избриша}} темата „[[$3|$5]]“ на [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] на [[$3]] е увезена во Flow од LiquidThreads",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|избриша}} тема на [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|ја означи}} темата „[[$3|$5]]“ како решена на [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|означи}} тема како решена на [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|повторно ја отвори}} темата „[[$3|$5]]“ на [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|повторно отвори}} тема на [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] на [[$3]] е увезена од LiquidThreads во Структурирани дискусии",
+ "abusefilter-edit-builder-vars-board-articleid": "Назнака на страницата во разговорницата на Структурираните дискусии",
+ "abusefilter-edit-builder-vars-board-namespace": "Именски простор за разговорницата на Структурираните дискусии",
+ "abusefilter-edit-builder-vars-board-text": "Наслов на разговорницата на Структурираните дискусии",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Полн наслов на разговорницата на Структурираните дискусии",
"flow-user-moderated": "Модериран корисник",
"flow-board-header-browse-topics-link": "Прегледај теми",
- "flow-board-header": "За оваа разговорница",
+ "flow-board-header": "За разговорницава",
+ "flow-board-description-can-not-edit": "Не може да се уредува",
"flow-board-collapse-description": "Скриј опис",
"flow-board-expand-description": "Прикажи опис",
"flow-topic-collapse-siderail": "Читајте на полна ширина",
@@ -47,13 +73,13 @@
"flow-post-actions": "Дејства",
"flow-topic-actions": "Дејства",
"flow-cancel": "Откажи",
- "flow-skip-summary": "Прескокни го краткиот опис",
+ "flow-skip-summary": "Прескокни",
"flow-edit-summary-placeholder": "Накратко опишете го исходот од овој разговор",
"flow-summary-authored": "Краток опис од $1",
"flow-summary-edited": "Краткиот опис последен пат е {{GENDER:$1|изменет}} од $1",
"flow-show-change": "Прикажи промени",
"flow-last-modified-by": "Последно {{GENDER:$1|изменето}} од $1",
- "flow-stub-post-content": "''Објавата не може да се добие поради техничка грешка.''",
+ "flow-stub-post-content": "<em>Содржината не може да се добие поради техничка грешка.</em>",
"flow-newtopic-title-placeholder": "Нова тема",
"flow-newtopic-content-placeholder": "Напишете нова порака на „$1“",
"flow-newtopic-header": "Додај нова тема",
@@ -113,28 +139,29 @@
"flow-board-notification-subscribe-title": "Сега сте {{GENDER:$1|претплатени}} на разговорницава!",
"flow-board-notification-subscribe-description": "Ќе {{GENDER:$1|бидете}} автоматски известувани за сите нови теми создадени на разговорницава.",
"flow-topic-action-watchlist-add": "Претплати се на темава",
- "flow-topic-action-watchlist-remove": "Откажани претплата",
- "flow-error-allowcreation-no-usedb": "allowCreation бара <var>$wgContentHandlerUseDB</var> за да биде <code>true</code>",
- "flow-error-allowcreation-already-exists": "Страницата веќе постои, но се бараше да не постои",
+ "flow-topic-action-watchlist-remove": "Отпиши ме",
+ "flow-error-allowcreation-no-usedb": "Вклчувањето на Структурираните дискусии на поединечните страници бара <var>$wgContentHandlerUseDB</var> да биде <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Страницата веќе постои на тоа одредиште, па затоа не може таму да се премести разговорница на Структурираните дискусии.",
"flow-error-allowcreation-flow-create-board": "Корисникот ја нема дозволата „{{int:right-flow-create-board}}“",
+ "flow-error-can-not-edit-logged-out": "Сега не можете да учествувате. Најавете се.",
+ "flow-error-can-not-edit-logged-in": "Сега не можете да учествувате бидеќи ги немате потребните права.",
"flow-error-http": "Се јави грешка при поврзувањето со опслужувачот.",
- "flow-error-other": "Се појави неочекувана грешка.",
- "flow-error-external": "Се појави грешка.<br />Објаснувањето гласи: $1",
+ "flow-error-external": "Се појави грешка. Пораката гласи: $1",
"flow-error-topic-is-locked": "Темава е решена, за да се оневозможат понатамошните активности.",
"flow-error-lock-moderated-post": "Не можете да означите модерирана објава како решена.",
- "flow-error-external-multi": "Наидов на грешки.<br />$1",
"flow-error-missing-content": "Пораката нема содржина. За да се зачува, мора да има содржина.",
"flow-error-missing-summary": "Ќе мора да поднесете краток опис.",
"flow-error-missing-title": "Темата нема наслов. Се бара наслов за да може да се зачува темата.",
- "flow-error-parsoid-failure": "Не можам да ја расчленам содржината поради проблем со Parsoid.",
+ "flow-error-parsoid-failure": "Нем ожам да ја префрлам содржината: Грешка при поврзувањето со опслужувачот за претворање од викитекст во HTML. Проверете си ја врската со семрежјето, или обидете се подоцна. Доколку проблемот продолжи да се јавува, пријавете грешка.",
+ "flow-error-protected-autoconfirmed-logged-in": "Оваа разговорница е заштитена. Можат да учествуваат само автопотврдени корисници. Причина: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Оваа разговорница е заштитена. Во неа можат да учествуваат само автопотврдени корисници. Причина: $1",
+ "flow-error-protected-sysop-logged-in": "Оваа разговорница е заштитена. Во неа можат да учествуваат само администратори. Причина: $1",
+ "flow-error-protected-sysop-logged-out": "Оваа разговорница е заштитена. Во неа можат да учествуваат само наајвени администратори. Причина: $1",
+ "flow-error-protected-unknown-reason": "Непозната",
"flow-error-missing-replyto": "Нема зададено параметар „replyTo“. Овој параметар е потребен за да може да се даде одговор.",
- "flow-error-invalid-replyto": "Параметарот на „replyTo“ е неважечки. Не можев да ја најдам укажаната порака.",
- "flow-error-delete-failure": "Бришењето на ставката не успеа.",
- "flow-error-hide-failure": "Не успеав да ја скријам ставката.",
"flow-error-missing-postId": "Нема зададено параметар „postId“. Овој параметар е потребен за работа со пораката.",
"flow-error-invalid-postId": "Параметарот на „postId“ е неважечки. Не можев да ја најдам укажаната порака ($1).",
- "flow-error-restore-failure": "Повраќањето на ставката не успеа.",
- "flow-error-invalid-moderation-state": "На извршникот на Тек му е укажана неважечка вредност за параметар („moderationState“) .",
+ "flow-error-invalid-moderation-state": "На извршникот на Структурираните дискусии му е укажана неважечка вредност за параметар („moderationState“) .",
"flow-error-invalid-moderation-reason": "Наведете причина за модерирањето",
"flow-error-not-allowed": "Немате дозвола за да го извршите ова дејство",
"flow-error-not-allowed-hide": "Темата е скриена.",
@@ -155,17 +182,19 @@
"flow-error-missing-prev-revision-identifier": "Недостасува назнака на претходната преработка.",
"flow-error-prev-revision-mismatch": "Објавава ја измени друг корисник пред неколку секунди. Дали {{GENDER:$3|сте}} сигурни дека сакате да презапишете врз оваа последна промена?",
"flow-error-prev-revision-does-not-exist": "Не можев да ја надам претходната преработка.",
- "flow-error-core-topic-deletion": "За да избришете тема, послужете се со менито ... на разговорница или на [$1 страницата на темата]. Не го посетувајте action=delete за темата непосредно.",
+ "flow-error-core-topic-deletion": "За да избришете тема, послужете се со менито ... на разговорница на Структурираните дискусии или на [$1 страницата на темата]. Не го посетувајте action=delete за темата непосредно.",
"flow-error-default": "Се појави грешка.",
- "flow-error-invalid-input": "Укажана е неважечка вредност за вчитување на содржините на текот.",
+ "flow-error-invalid-input": "Укажана е неважечка вредност за вчитување на содржините на Структурираните дискусии.",
"flow-error-invalid-title": "Укажан е неважечки наслов на страницата.",
+ "flow-error-invalid-parameter": "Отсутен или неважечки параметар во повикот на методот",
"flow-error-fail-load-history": "Не успеав да ја вчитам содржината на историјата.",
- "flow-error-missing-revision": "Не можев да ја пронајдам преработката од која би ја вчитал содржината на текот.",
- "flow-error-fail-commit": "Не успеав да ја зачувам содржината на текот.",
+ "flow-error-missing-revision": "Не можев да ја пронајдам преработката од која би ја вчитал содржината на Структурираните дискусии.",
+ "flow-error-fail-commit": "Не успеав да ја зачувам содржината на Структурираните дискусии.",
"flow-error-insufficient-permission": "Немате доволно дозволи за пристап до содржината.",
- "flow-error-revision-comparison": "Операцијата за разлика може да се врши само кога две преработки припаѓаат на иста објава.",
+ "flow-error-revision-comparison": "Постапката за разлика може да се врши само кога две преработки припаѓаат на иста објава.",
"flow-error-missing-topic-title": "Не можев да го најдам насловот на темата во тековниот работен тек.",
"flow-error-missing-metadata": "Не можев да ги најдам потребните метаподатоци за оваа преработка.",
+ "flow-error-different-page": "Структурираните дискусии не се здружени со страницава.",
"flow-error-fail-load-data": "Не успеав да ги вчитам побараните податоци.",
"flow-error-invalid-workflow": "Не успеав да го најдам бараниот работен тек.",
"flow-error-process-data": "Се појави грешка при обработката на податоците во вашето барање.",
@@ -175,12 +204,12 @@
"flow-error-no-commit": "Не можев да го зачувам укажаното дејство.",
"flow-error-content-too-long": "Содржината е преголема. По проширувањето, содржината е ограничена на {{PLURAL:$1|1 бајт|$1 бајт}}.",
"flow-error-move-topic": "Преместувањето на тематската страница засега не е поддржано.",
- "flow-error-move-no-create-permissions": "Потребна ви е дозволата „{{int:right-flow-create-board}}“ за да преместите разговорница.",
"flow-error-invalid-topic-uuid-title": "Неисправен наслов",
- "flow-error-invalid-topic-uuid": "Побараниот наслов е неважечки. Страниците во именскиот простор „Тема“ се создаваат автоматски од страна на Тек.",
+ "flow-error-invalid-topic-uuid": "Побараниот наслов е неважечки. Страниците во именскиот простор „Тема“ се создаваат автоматски од страна на Структурираните дискусии.",
"flow-error-unknown-workflow-id-title": "Непозната тема",
"flow-error-unknown-workflow-id": "Бараната тема не постои.",
"flow-error-search": "Не можам наполно да го изведам пребарувањето поради привремен проблем. Обидете се подоцна.",
+ "flow-error-invalid-undelete": "Страницава не може да се поврати бидејќи во моментов на неа има разговорница.",
"flow-edit-header-placeholder": "Опишете ја разговорницава",
"flow-edit-header-submit": "Зачувај опис",
"flow-edit-header-submit-anonymously": "Зачувај опис анонимно",
@@ -206,7 +235,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ја скри}} [$4 темата] на „$6“ (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|ја избриша}} [$4 темата] „$6“ (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|ја притаи}} [$4 темата] „$6“ (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 ја {{GENDER:$2|означи}} [$4 темата] $6 како решена (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 ја {{GENDER:$2|означи}} [$4 темата] \"$6\" како решена (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "означено како решено",
"flow-rev-message-restore-topic-reason": "повторно отворено",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|ја поврати}} [$4 темата] „$6“ (<em>$5</em>).",
@@ -229,31 +258,75 @@
"flow-comment-moderated": "Модериран коментар",
"flow-last-modified": "Последна измена: $1",
"flow-workflow": "работен тек",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|одговори}} на '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и {{PLURAL:$6|еден друг одговори|$5 други одговорија}} {{GENDER:$1|на}} '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|одговори}} на <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и {{PLURAL:$5|уште еден|уште $5 други|100=99+ други}} {{GENDER:$1|одговорија}} на <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|ја измени}} вашата <span class=\"plainlinks\">[$5 објава]</span> на [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 и $5 {{PLURAL:$6|уште еден друг|уште $5 други}} {{GENDER:$1|изменија}} <span class=\"plainlinks\">[$4 post]</span> во „$2“ на „$3“.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|создаде}} нова тема на '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 нова тема|$1 нови теми|250=Преку 250 нови теми}} на '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 и {{PLURAL:$5|уште еден|уште $5 други|100=преку 99 други}} {{GENDER:$1|изменија}} <span class=\"plainlinks\">[$4 објава]</span> во „$2“ на „$3“.",
+ "notification-header-flow-new-topic-v2": "Создадена нова тема на <strong>$3</strong>: <bdi>„<strong>$4</strong>“</bdi>.",
+ "notification-compact-header-flow-new-topic": "„<strong>$1</strong>“",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Една нова тема|$1 нови теми|100=Преку 99 нови теми}} на <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Создадена е нова тема на <strong>вашата страница за разовор</strong>: „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Една нова тема|$1 нови теми|100=Преку 99 нови теми}} на <strong>вашата страница за разговор</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|одговори}} на „<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Еден нов одговор|$1 нови одговори|100=Преку 99 нови одговори}} на „<strong>$3</strong>“.",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|објави}} одговор на <strong>вашата страница за разговор</strong> на „\"<strong>$4</strong>“.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Еден нов одговор|$1 нови одговори|100=Преку 99 нови одговори}} на <strong>вашата страница за разговор</strong> на „<strong>$3</strong>“.",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Вашата}} објава на „<strong>$1</strong>“ е изменета.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Вашата}} објава на „<strong>$1</strong>“ е повеќепати изменета.",
+ "notification-header-flow-post-edited-user-talk": "На <strong>{{GENDER:$2|вашата}} страница за разговор</strong> „<strong>$1</strong>“ е изменета објава.",
+ "notification-bundle-header-flow-post-edited-user-talk": "На <strong>{{GENDER:$2|вашата}} страница за разговор</strong> „<strong>$1</strong>“ повеќепати е изменета објава.",
+ "notification-header-flow-topic-renamed-v2": "Темата „<strong>$1</strong>“ е преименувана во „<strong>$2</strong>“.",
+ "notification-header-flow-topic-renamed-user-talk": "На <strong>{{GENDER:$3|вашата}} страница за разговор</strong> темата „<strong>$1</strong>“ е преименувана во „<strong>$2</strong>“.",
+ "notification-header-flow-summary-edited": "Описот на „<strong>$1</strong>“ е изменет.",
+ "notification-header-flow-summary-edited-first": "Темата „<strong>$1</strong>“ доби опис.",
+ "notification-bundle-header-flow-summary-edited": "Описот на „<strong>$1</strong>“ е повеќепати изменет.",
+ "notification-header-flow-summary-edited-user-talk": "На <strong>{{GENDER:$2|вашата}} страница за разговор</strong> е изменет описот за „<strong>$1</strong>“.",
+ "notification-header-flow-summary-edited-first-user-talk": "На <strong>{{GENDER:$2|вашата}} страница за разговор</strong> темата „<strong>$1</strong>“ доби опис.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "На <strong>{{GENDER:$2|вашата}} страница за разговор</strong> описот за „<strong>$1</strong>“ е повеќепати изменет.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|го измени}} описот на $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|го измени}} описот на $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 и {{PLURAL:$3|уште есден|уште $3 други|100=99+ други}} {{GENDER:$1|го изменија}} описот на $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$4|ве}} {{GENDER:$2|спомна}} на „<strong>$5</strong>“.",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$4|ве}} {{GENDER:$2|спомна}} во описот на <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$4|ве}} {{GENDER:$2|спомна}} на „<strong>$5</strong>“.",
+ "notification-header-flow-enabled-on-talkpage": "Овозможен е нов систем за разговори на <strong>{{GENDER:$2|вашата}} страница за разговор.</strong>.",
+ "notification-header-flow-description-edited": "Описот на <strong>$1</strong> е изменет.",
+ "notification-header-flow-description-edited-user-talk": "описот е изменет на <strong>{{GENDER:$2|вашата}} страница за разговор</strong>.",
+ "notification-bundle-header-flow-description-edited": "Описот на <strong>$1</strong> е повеќепати изменет.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Описот е повеќепати изменет на <strong>{{GENDER:$2|вашата}} страница за разговор</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Погл.}} страница",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|го измени}} описот на $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|го измени}} описот на $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 и {{PLURAL:$3|уште еден|$3 други|100=преку 99 други}} {{GENDER:$1|го изменија}} описот на $2",
+ "notification-header-flow-topic-resolved": "Темата „<strong>$1</strong>“ е решена.",
+ "notification-header-flow-topic-reopened": "Темата „<strong>$1</strong>“ е повторно отворена.",
+ "notification-header-flow-topic-resolved-user-talk": "Темата „<strong>$1</strong>“ е решена на <strong>вашата страница за разговор</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Темата „<strong>$1</strong>“ е повторно отворена на <strong>вашата страница за разговор</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Темата „<strong>$2</strong>“ е решена.",
+ "notification-email-batch-body-flow-topic-resolved": "Темата „<strong>$2</strong>“ е решена.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|создаде}} нова тема на <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Една нова тема|$1 нови теми|100=Преку 99 нови теми}} на <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 го {{GENDER:$1|смени}} насловот на <span class=\"plainlinks\">[$2 $3]</span> во „$4“ на [[$5|$6]]",
"flow-notification-mention": "$1 {{GENDER:$5|вр}} спомна во {{GENDER:$1|неговата|нејзината|неговата}} <span class=\"plainlinks\">[$2 објава]</span> во „$3“ на „$4“",
"flow-notification-link-text-view-post": "Погл. објавата",
"flow-notification-link-text-view-topic": "Погл. темата",
+ "flow-notification-link-text-view-topics": "Погл. теми",
"flow-notification-reply-email-subject": "$2 на $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|одговори}} на „$2“ на $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 и уште {{PLURAL:$5|еден друг|$4 други}} {{GENDER:$1|одговорија}} на „$2“ на $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 и уште {{PLURAL:$4|еден друг|$4 други|100=повеќе од 99 други}} {{GENDER:$1|одговорија}} на „$2“ на $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$3|ве}} {{GENDER:$1|спомна}} на $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|ве}} спомна во {{GENDER:$1|неговата|нејзината|неговата}} објава во „$2“ на $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|измени}} објава",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|измени}} објава во „$2“ на $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 и {{PLURAL:$5|уште еден друг|уште $4 други}} {{GENDER:$1|ја изменија}} вашата објава во „$2“ на $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 и {{PLURAL:$4|уште еден друг|уште $4 други|100=повеќе од 99 други}} {{GENDER:$1|ја изменија}} вашата објава во „$2“ на $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|ја преименуваше}} вашата тема",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|ја преименуваше}} вашата тема „$2“ во „$3“ на $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|создаде}} нова тема на $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|создаде}} нова тема со наслов „$2“ на $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 нова тема|$1 нови теми|250=Преку 250 нови теми}} на $2",
- "echo-category-title-flow-discussion": "Тек",
- "echo-pref-tooltip-flow-discussion": "Извести ме кога во Тек ќе се случат дејства поврзани со мене.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 нова тема|$1 нови теми|100=Повеќе од 99 нови теми}} на $2",
+ "echo-category-title-flow-discussion": "Структурирана дискусија",
+ "echo-pref-tooltip-flow-discussion": "Известувај ме за активности на теми или страници што ги следам.",
"flow-link-post": "објава",
"flow-link-topic": "тема",
"flow-link-history": "историја",
@@ -285,18 +358,18 @@
"flow-moderation-confirm-unsuppress-topic": "Отпритаи",
"flow-moderation-confirm-undelete-topic": "Обнови",
"flow-moderation-confirm-unhide-topic": "Откриј",
- "flow-moderation-confirmation-suppress-post": "Објавата е успешно притаена. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
- "flow-moderation-confirmation-delete-post": "Објавата е успешно избришана. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
- "flow-moderation-confirmation-hide-post": "Објавата е успешно скриена. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
- "flow-moderation-confirmation-unsuppress-post": "Успешно ја отпритаивте објавата.",
- "flow-moderation-confirmation-undelete-post": "Успешно ја обновивте објавата.",
- "flow-moderation-confirmation-unhide-post": "Успешно ја откривте објавата.",
+ "flow-moderation-confirmation-suppress-post": "Објавата е притаена. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
+ "flow-moderation-confirmation-delete-post": "Објавата е избришана. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
+ "flow-moderation-confirmation-hide-post": "Објавата е скриена. {{GENDER:$2|Ви препорачуваме}} на корисникот $1 да му дадете образложение и/или совет за објавата.",
+ "flow-moderation-confirmation-unsuppress-post": "Ја отпритаивте објавата.",
+ "flow-moderation-confirmation-undelete-post": "Ја обновивте објавата.",
+ "flow-moderation-confirmation-unhide-post": "Ја откривте објавата.",
"flow-moderation-confirmation-suppress-topic": "Темава е притаена.",
"flow-moderation-confirmation-delete-topic": "Темава е избришана.",
"flow-moderation-confirmation-hide-topic": "Темава е скриена.",
- "flow-moderation-confirmation-unsuppress-topic": "Успешно ја отпритаивте темата.",
- "flow-moderation-confirmation-undelete-topic": "Успешно ја обновивте темата.",
- "flow-moderation-confirmation-unhide-topic": "Успешно ја откривте темата.",
+ "flow-moderation-confirmation-unsuppress-topic": "Ја отпритаивте темата.",
+ "flow-moderation-confirmation-undelete-topic": "Ја обновивте темата.",
+ "flow-moderation-confirmation-unhide-topic": "Ја откривте темата.",
"flow-moderation-title-suppress-topic": "Да ја притаам темата?",
"flow-moderation-title-delete-topic": "Да ја избришам темата?",
"flow-moderation-title-hide-topic": "Да ја скријам темата?",
@@ -319,15 +392,15 @@
"flow-revision-permalink-warning-header-first": "Ова е постојана врска до првата верзија на описот.\nМожете да ги погледате подоцнежните верзии во [$2 историјата].",
"flow-compare-revisions-revision-header": "Верзија на {{GENDER:$2|$2}} од $1",
"flow-compare-revisions-header-post": "На страницава се прикажани {{GENDER:$3|разликите}} помеѓу две верзии на објава на $3 во темата „[$5 $2]“ на [$4 $1].\nМожете да ги погледате другите верзии на објавата во [$6 нејзината историја].",
- "flow-compare-revisions-header-postsummary": "На страницава се прикажани разликите помеѓу две верзии на опис на објавата „[$4 $2]“ на [$3 $1].\nМожете да ги погледате другите верзии на објавата во [$5 нејзината историја].",
+ "flow-compare-revisions-header-postsummary": "На страницава се прикажани разликите помеѓу две верзии на описот на темата „[$4 $2]“ на [$3 $1].\nМожете да ги погледате другите верзии на описот на темата во [$5 нејзината историја].",
"flow-compare-revisions-header-header": "На страницава се прикажани {{GENDER:$2|промените}} помеѓу две верзии на описот на [$3 $1].\nДругите верзии на описот можете да ги видите во [$4 неговата историја].",
- "action-flow-create-board": "создавање на разгласници на било кое место",
- "right-flow-create-board": "Создавање на разговорници на било кое место",
- "right-flow-hide": "Скривање на теми и објави во „Тек“",
- "right-flow-lock": "Означи ги темите како решени",
- "right-flow-delete": "Бришење на теми и објави во „Тек“",
- "right-flow-edit-post": "Менување на објави на други корисници во „Тек“",
- "right-flow-suppress": "Скривање на преработки во „Тек“",
+ "action-flow-create-board": "создавање на разгласници на Структурираните дискусии на било кое место",
+ "right-flow-create-board": "Создавање на разговорници на Структурираните дискусии на било кое место",
+ "right-flow-hide": "Скривање на теми и објави во Структурираните дискусии",
+ "right-flow-lock": "Означи ги темите во Структурираните дискусии како решени",
+ "right-flow-delete": "Бришење на теми ои објави во Структурираните дискусии",
+ "right-flow-edit-post": "Менување на објави на други корисници во Структурираните дискусии",
+ "right-flow-suppress": "Скривање на преработки во Структурираните дискусии",
"flow-terms-of-use-new-topic": "Стискајќи на „{{int:flow-newtopic-save}}“, се согласувате со условите на употреба на ова вики.",
"flow-terms-of-use-reply": "Стискајќи на „{{int:flow-reply-link}}“, се согласувате со условите на употреба на ова вики.",
"flow-terms-of-use-edit": "Зачувувајќи ги промените, се согласувате со условите на употреба на ова вики.",
@@ -351,24 +424,25 @@
"flow-whatlinkshere-post": "од [$1 објава]",
"flow-whatlinkshere-header": "од [$1 описот]",
"flow-whatlinkshere-post-summary": "пд [$1 описот]",
- "flow": "Тек",
- "flow-special-desc": "Оваа службена страница пренасочува кон работниот тек или објава на „Тек“ со зададен UUID.",
+ "structureddiscussions": "Тек",
+ "flow-special-desc": "Оваа службена страница пренасочува кон работниот тек или објава на Структурираните дискусии со зададен UUID.",
"flow-special-type": "Тип",
"flow-special-type-post": "Објава",
"flow-special-type-workflow": "Работен тек",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Не можев да пронајдам содржини што одговараат на дадениот тип и UUID.",
- "flow-special-enableflow-legend": "Вклучи го Тек на нова страница",
- "flow-special-enableflow-page": "На која страница да се вклучи Тек",
- "flow-special-enableflow-header": "Првичен опис на разговорница (викитекст)",
- "flow-special-enableflow-board-already-exists": "Веќе има разговорница на [[$1]].",
+ "flow-special-enableflow-legend": "Вклучи ги Структурираните дискусии на нова страница",
+ "flow-special-enableflow-page": "На која страница да се вклучат Структурираните дискусии",
+ "flow-special-enableflow-header": "Првичен опис на разговорница на Структурираните дискусии (викитекст)",
+ "flow-special-enableflow-board-already-exists": "Веќе има разговорница на Структурираните дискусии на [[$1]].",
"flow-special-enableflow-invalid-title": "Укажан е неважечки наслов на страницата",
- "flow-special-enableflow-board-creation-not-allowed": "Не ви е дозволено да создадете разговорник на [[:$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "Не ви е дозволено да создадете разговорник на Структурираните дискусии на [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Страницата [[:$1]] има LiquidThreads.",
- "flow-special-enableflow-confirmation": "Успешно создадовте разговорница на [[$1]].",
+ "flow-special-enableflow-confirmation": "Создадовте разговорница на Структурираните дискусии на [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Архив %d\n%s/Архив%d\n%s/архив %d\n%s/архив%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Flow Archive %d\n%s/FlowArchive%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Архив на Структурирани дискусии %d\n%s/Архив на Структурираните дискусии%d",
"flow-spam-confirmedit-form": "Поврдете дека не сте робот, внесувајќи го прикажаното во полето: $1",
+ "flow-spam-confirmedit-using-failure": "Се појави техничка грешка во CAPTCHA. Ако не можете да ја поднесете промената, ископирајте го текстот, превчитајте и обидете се повторно.",
"flow-embedding-unsupported": "Дискусиите засега не може да се вметнуваат.",
"mw-ui-unsubmitted-confirm": "Имате неподнесени промени на страницата. Дали сигурно сакате да ја напуштите, губејќи го напишаното?",
"flow-post-undo-hide": "откажи го скривањето",
@@ -377,126 +451,27 @@
"flow-topic-undo-hide": "откажи го скривањето",
"flow-topic-undo-delete": "откажи го бришењето",
"flow-topic-undo-suppress": "откажи го притајувањето",
- "flow-importer-lqt-moved-thread-template": "LQT премести нишка-никулец претворена во Тек",
+ "flow-importer-lqt-moved-thread-template": "LQT премести нишка-никулец претворена во Структурирани дискусии",
"flow-importer-lqt-moved-thread-template-content": "Оваа објава на {{{author}}} е преместена на {{{date}}}. Можете да ја најдете на [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "LQT-страница пертворена во Тек",
+ "flow-importer-lqt-converted-template": "LQT-страница пертворена во Структурирани дискусии",
"flow-importer-lqt-converted-template-content": "Изминатата историја на страницата е архивирана како резерва во <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> на {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-lqt-converted-archive-template": "Архив за претворената LQT-страница",
- "flow-importer-lqt-converted-archive-template-content": "Ова е архивирана страница со LiquidThreads. '''Не менувајте ја нејзината содржина'''. Сите коментари упатувајте ги на [[{{{from}}}|тековната страница за разговор]].",
- "flow-importer-wt-converted-template": "Бикитекстуална страница за разговор што треба да се претвори во Тек",
+ "flow-importer-lqt-converted-archive-template-content": "Ова е архивирана страница со LiquidThreads. <strong>Не менувајте ја нејзината содржина</strong>. Сите коментари упатувајте ги на [[{{{from}}}|тековната страница за разговор]].",
+ "flow-importer-wt-converted-template": "Бикитекстуална страница за разговор што треба да се претвори во Структурирани дискусии",
"flow-importer-wt-converted-template-content": "Претходните разговори се архивирани во <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> на {{#time: Y-m-d|{{{date}}} }}.",
"flow-importer-wt-converted-archive-template": "Архива за претворени викитекстуални страници за разговор",
- "flow-importer-wt-converted-archive-template-content": "Оваа страница е архива. '''Не менувајте ја нејзината содржина'''. Сите коментари упатувајте ги на [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|тековната страница за разговор]].",
+ "flow-importer-wt-converted-archive-template-content": "Оваа страница е архива. </strong>Не менувајте ја нејзината содржина</strong>. Сите коментари упатувајте ги на [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|тековната страница за разговор]].",
"flow-importer-lqt-suppressed-user-template": "Објава од LiquidThreads увезена со со притаен корисник.",
"flow-importer-lqt-suppressed-user-template-content": "Оваа преработка е увезена од LiquidThreads сои притаен корисник. Му беше доделена на тековниот корисник.",
"flow-importer-lqt-different-author-signature-template": "LQT-објава увезена од корисникот со различен опис",
- "flow-importer-lqt-different-author-signature-template-content": "''Ова е објава на корисникот [[User:{{{authorUser}}}|{{{authorUser}}}]], кој на неа е потпишан како [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Овозможува вршење дејства брз страници со Тек.",
- "apihelp-flow-param-submodule": "Подмодулот на Тек што треба да се повика.",
- "apihelp-flow-param-page": "Врз која страница да се изврши дејството.",
- "apihelp-flow-example-1": "Измени го описот на „[[Talk:Sandbox]]“",
- "apihelp-flow+close-open-topic-description": "Застарено и заменето со [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Која состојба да ѝ се зададе на темата: „заклучена“ или „отклучена“.",
- "apihelp-flow+close-open-topic-param-reason": "Причина за заклучување или отклучување на темата.",
- "apihelp-flow+edit-header-description": "Уредува опис на разговорницата.",
- "apihelp-flow+edit-header-param-prev_revision": "Назнака на тековната преработка на описот, за проверка на можни спротиставености во уредувањето.",
- "apihelp-flow+edit-header-param-content": "Содржина на описот.",
- "apihelp-flow+edit-header-param-format": "Формат на описот (викитекст|HTML)",
- "apihelp-flow+edit-header-example-1": "Измени го описот на [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Измени ја содржината на објавата.",
- "apihelp-flow+edit-post-param-postId": "Назнака на објавата.",
- "apihelp-flow+edit-post-param-prev_revision": "Назнака на тековната преработка на објавата, за проверка на можни спротиставености во уредувањето.",
- "apihelp-flow+edit-post-param-content": "Содржина на објавата.",
- "apihelp-flow+edit-post-param-format": "Формат на содржината на објавата (викитекст|HTML)",
- "apihelp-flow+edit-post-example-1": "Измени објава во [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Уредува наслов на објава.",
- "apihelp-flow+edit-title-param-prev_revision": "Назнака на тековната преработка на насловот, за проверка на можни спротиставености во уредувањето.",
- "apihelp-flow+edit-title-param-content": "Содржина на насловот.",
- "apihelp-flow+edit-title-example-1": "Измени го насловот на [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Измени ја содржината на краткиот преглед на темата.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Назнака на тековната преработка на краткиот преглед на темата, за проверка на можни спротиставености во уредувањето.",
- "apihelp-flow+edit-topic-summary-param-summary": "Содржина на краткиот преглед.",
- "apihelp-flow+edit-topic-summary-param-format": "Формат на описот (викитекст|HTML)",
- "apihelp-flow+edit-topic-summary-example-1": "Измени го краткиот преглед на [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Заклучи или отклучи тема со Тек.",
- "apihelp-flow+lock-topic-param-moderationState": "Која состојба да ѝ се зададе на темата: <kbd>lock</kbd> или <kbd>unlock</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Причина за заклучување или отклучување на темата. Имајте на ум дека клиентот на „Тек“ на викито тука користи „Означено како решено“, и става незадолжителни дополнителни информации во описот.",
- "apihelp-flow+lock-topic-example-1": "Заклучи ја [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Модерирај објава со Тек.",
- "apihelp-flow+moderate-post-param-moderationState": "На кое ниво да се модерира.",
- "apihelp-flow+moderate-post-param-reason": "Причина за модерирањето.",
- "apihelp-flow+moderate-post-param-postId": "Назнака на објавата што ќе се модерира.",
- "apihelp-flow+moderate-post-example-1": "Избриши објава на темата [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Модерира тема со Тек.",
- "apihelp-flow+moderate-topic-param-moderationState": "На кое ниво да се модерира.",
- "apihelp-flow+moderate-topic-param-reason": "Причина за модерирањето.",
- "apihelp-flow+moderate-topic-example-1": "Избриши ја темата [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Создава нова тема со Тек за дадениот работен тек.",
- "apihelp-flow+new-topic-param-topic": "Текст на насловот на новата тема.",
- "apihelp-flow+new-topic-param-content": "Содржина на првичниот одговор на темата.",
- "apihelp-flow+new-topic-param-format": "Формат на првичниот одговор на темата (викитекст|HTML)",
- "apihelp-flow+new-topic-example-1": "Создај нова тема на [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Одговара на објава.",
- "apihelp-flow+reply-param-replyTo": "Назнака на објавата на која се одговара.",
- "apihelp-flow+reply-param-content": "Содржина на новата објава.",
- "apihelp-flow+reply-param-format": "Формат на новата објава (викитекст|HTML)",
- "apihelp-flow+reply-example-1": "Одговори на објава на [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Во кој формат да се даде содржината.",
- "apihelp-flow+view-header-description": "Погл. описот на разговорницата.",
- "apihelp-flow+view-header-param-revId": "Вчитај ја оваа преработка наместо најновата.",
- "apihelp-flow+view-header-example-1": "Дај го описот на [[Talk:Sandbox]] како викитекст",
- "apihelp-flow+view-post-description": "Погл. објава.",
- "apihelp-flow+view-post-param-postId": "Назнака на објавата што треба да се погледа.",
- "apihelp-flow+view-post-param-format": "Во кој формат да се даде содржината.",
- "apihelp-flow+view-post-example-1": "Дај ја содржината на објава на [[Topic:S2tycnas4hcucw8w]] како викитекст",
- "apihelp-flow+view-post-history-description": "Погледајте ја историјата на преработки на објавата.",
- "apihelp-flow+view-post-history-param-postId": "Назнака на објавата за која ја барате историјата на преработки.",
- "apihelp-flow+view-post-history-param-format": "Во кој формат да се даде содржината.",
- "apihelp-flow+view-post-history-example-1": "Добијте ги преработките на една објава на [[Topic:S2tycnas4hcucw8w]] како викитекст",
- "apihelp-flow+view-topic-description": "Погл. тема.",
- "apihelp-flow+view-topic-example-1": "Погл. [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Преглед на историјата на преработките на една тема.",
- "apihelp-flow+view-topic-history-param-format": "Во кој формат да се даде содржината.",
- "apihelp-flow+view-topic-history-example-1": "Добијте ги преработките на објавите на [[Topic:S2tycnas4hcucw8w]] како викитекст",
- "apihelp-flow+view-topic-summary-description": "Погл. опис на темата.",
- "apihelp-flow+view-topic-summary-param-format": "Во кој формат да се даде содржината.",
- "apihelp-flow+view-topic-summary-param-revId": "Вчитај ја оваа преработка наместо најновата.",
- "apihelp-flow+view-topic-summary-example-1": "Погл. описот на [[Topic:S2tycnas4hcucw8w]] како викитекст",
- "apihelp-flow+view-topiclist-description": "Погл. список на теми.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Насока на подредување на темите.",
- "apihelp-flow+view-topiclist-param-sortby": "Можност за подредување на темите, или <kbd>updated</kbd> (подредени по ден/време на поднова) или <kbd>newest</kbd> (подредување по ден/време на создавање).",
- "apihelp-flow+view-topiclist-param-savesortby": "Зачувај ја подреденоста во корисничките нагодувања, ако е зададена.",
- "apihelp-flow+view-topiclist-param-offset-id": "Вредност на отстапката (во форматот UUID) од каде ќе се почне со давање на темите. Се користи само со подреденоста <kbd>newest</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Вредност на отстапката (како ден и време на поднова на темата, во формат <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), од која ќе се почне со давање на темите. Се користи само со подреденоста <kbd>updated</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Колку теми да се дадат.",
- "apihelp-flow+view-topiclist-example-1": "Испиши ги темите во [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Претвори го текстот од викитекст во HMTL и обратно.",
- "apihelp-flow-parsoid-utils-param-from": "Од кој формат да се претвори содржината.",
- "apihelp-flow-parsoid-utils-param-to": "Во кој формат да се претвори содржината.",
- "apihelp-flow-parsoid-utils-param-content": "Содржина за претворање.",
- "apihelp-flow-parsoid-utils-param-title": "Наслов на страницата. Не може да се користи заедно со $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "Назнака на страницата. Не може да се користи заедно со $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Претвори го викитекстот <nowiki>'''пример''' ''бла''</nowiki> во HTML",
- "apihelp-query+flowinfo-description": "Дај основни информации за текот на една страница.",
- "apihelp-query+flowinfo-example-1": "Дај информации за текот на [[Talk:Sandbox]], [[Main Page|Главната страница]] и [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Испис на информации неопходни за отповикување на уредување на опис.",
- "apihelp-flow+undo-edit-header-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
- "apihelp-flow+undo-edit-header-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
- "apihelp-flow+undo-edit-header-example-1": "Испиши информации за отповикување на уредување на описот во [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Испис на информации неопходни за отповикување на уредување на објава.",
- "apihelp-flow+undo-edit-post-param-postId": "Назнака на објавата што треба да се отповика.",
- "apihelp-flow+undo-edit-post-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
- "apihelp-flow+undo-edit-post-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
- "apihelp-flow+undo-edit-post-example-1": "Испиши информации за отповикување на уредување на објава на дадена тема",
- "apihelp-flow+undo-edit-topic-summary-description": "Испис на информации неопходни за отповикување на уредување во опис на тема.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Назнака на преработката од која ќе се почне отповикувањето.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Назнака на преработката со која ќе се заврши отповикувањето.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Испиши информации за отповикување на уредување на опис на дадена тема",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Ова е објава на корисникот [[User:{{{authorUser}}}|{{{authorUser}}}]], кој на неа е потпишан како [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Изменета",
"flow-edited-by": "Изменил: $1",
- "flow-lqt-redirect-reason": "Пренасочување на повлечена објава во LiquidThreads кон нејзината претворана објава во Тек",
- "flow-talk-conversion-move-reason": "Претворање на викитекстуален разговор во Тек од $1",
- "flow-talk-conversion-archive-edit-reason": "Претворање на викитекстуален развговор во Тек",
+ "flow-edited-by-header": "Описот на разговорницата е изменет од $1",
+ "flow-edited-by-topic-title": "Насловот на темата е изменет од $1",
+ "flow-lqt-redirect-reason": "Пренасочување на повлечена објава во LiquidThreads кон нејзината претворана објава во Структурираните дискусии",
+ "flow-talk-conversion-move-reason": "Претворање на викитекстуален разговор во Структурирани дискусии од $1",
+ "flow-talk-conversion-archive-edit-reason": "Претворање на викитекстуален развговор во Структурираните дискусии",
"flow-previous-diff": "← Постаро уредување",
"flow-next-diff": "Поново уредување →",
"flow-undo": "отповикај",
@@ -507,9 +482,9 @@
"flow-undo-edit-post": "Уредување на објавата",
"flow-undo-edit-content": "Уредувањето може да се отповика.\nВе молиме споредете ги промените со претходната верзија за да проверите дали тоа е сигурно она што сакате да го направите, а потоа зачувајте ги промените за да го завршите отповикувањето на претходното уредување.",
"flow-undo-edit-failure": "Уредувањето не можеше да се отповика заради меѓувремени спротиставени уредувања.",
- "group-flow-bot": "Ботови за „Тек“",
- "group-flow-bot-member": "Бот на „Тек“",
- "grouppage-flow-bot": "Project:Ботови за Тек",
+ "group-flow-bot": "Ботови за Структурираните дискусии",
+ "group-flow-bot-member": "Бот на Структурираните дискусии",
+ "grouppage-flow-bot": "Project:Ботови за Структурирани дискусии",
"flow-ve-mention-context-item-label": "Спомнување",
"flow-ve-mention-inspector-title": "Спомнување",
"flow-ve-mention-inspector-remove-label": "Отстрани",
@@ -519,30 +494,36 @@
"flow-ve-mention-inspector-invalid-user": "Корисничкото име „$1“ не е регистрирано.",
"flow-wikitext-editor-help": "Викитекстот $1.",
"flow-wikitext-editor-help-and-preview": "Викитекстот $1 и можете да го $2 во секое време.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|користи означување]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|користи означување]]",
"flow-wikitext-editor-help-preview-the-result": "прегледате исходот",
- "flow-wikitext-switch-editor-tooltip": "Префрли на ВизуеленУредник",
+ "flow-wikitext-switch-editor-tooltip": "Префрли на визуелниот уредник",
"flow-ve-switch-editor-tool-title": "Префрли на викитекст",
"flow-mark-revision-patrolled-link-text": "Означи страницава како проверена",
"flow-mark-revision-patrolled-link-title": "Означи страницава како проверена",
"flow-mark-diff-patrolled-link-text": "Означи како проверено",
"flow-mark-diff-patrolled-link-title": "Означи како проверено",
- "flow-talk-page-beta-feature-message": "Тек на разговор со корисник",
- "flow-talk-page-beta-feature-description": "Дава нов систем за структурирани дискусии на {{GENDER:|вашата}} корисничка страница. „Тек“ го упростува сето она што се дискутира на страницата за разговор, овозможувајќи јасни места за пишување пораки и давање одговори. Исто така, дава известувања на разговорно ниво. Постоечките разговори во викитекст ќе се преместат во архив. Оваа можност не се вклучува самата, туку корисниците ќе треба тоа да го направат самите. Доколку го исклучите, „Тек“ ќе биде преместен на потстраница, а претходната страница за разговор ќе се одархивира (т.е. ќе врати како што си била).",
- "flow-notification-link-text-enabled-on-talkpage": "Погл. разговор со корисник",
+ "flow-talk-page-beta-feature-message": "Структурирани дискусии во разговор со корисник",
+ "flow-talk-page-beta-feature-description": "Дава нов систем за структурирани дискусии на {{GENDER:|вашата}} корисничка страница. Структурираните дискусии го упростуваат сето она што се дискутира на страницата за разговор, овозможувајќи јасни места за пишување пораки и давање одговори. Исто така, дава известувања на разговорно ниво.<br /><br />Постоечките разговори во викитекст ќе се преместат во архив. Оваа можност не се вклучува самата, туку корисниците ќе треба тоа да го направат самите. Доколку го исклучите, Структурираните дискусии ќе бидат преместени на потстраница, а претходната страница за разговор ќе се одархивира (т.е. ќе врати како што си била).\n[[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Дознајте повеќе за активацијата]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Погл.}} разговор со корисник",
"flow-notification-enabled-on-talkpage-title": "Овозможен е нов систем за разговори за {{GENDER:$1|вашата}} корисничка страница за разговор<br /><small>Ќе го најдете на [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Нов систем за разговори на $2",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Новиот систем за викиразговори „Тек“ е вклучен на {{GENDER:$1|вашата}} корисничка страница за разговор на {{SITENAME}}. Можете да дознаете повеќе, да ни дадете ваше мислење, или пак да го исклучите новиот систем во секое време во делот за бета-можности во {{GENDER:$1|вашите}} нагодувања.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Новиот систем за викиразговори „Структурирани дискусии“ е вклучен на {{GENDER:$1|вашата}} корисничка страница за разговор на {{SITENAME}}. Можете да дознаете повеќе, да ни дадете ваше мислење, или пак да го исклучите новиот систем во секое време во делот за бета-можности во {{GENDER:$1|вашите}} нагодувања.",
"flow-beta-feature-add-archive-template-edit-summary": "ДОдаден архивен шаблон",
"flow-beta-feature-remove-archive-template-edit-summary": "Отстранет архивен шаблон",
- "flow-dialog-cancelconfirm-title": "Дали сте сигурни?",
- "flow-dialog-cancelconfirm-message": "Дали сте сигурни дека сакате да откажете без претходно да зачувате?",
+ "flow-dialog-cancelconfirm-title": "Дали {{GENDER:|сте}} сигурни?",
+ "flow-dialog-cancelconfirm-message": "Дали {{GENDER:|сте}} сигурни дека сакате да откажете без претходно да зачувате?",
"flow-dialog-cancelconfirm-keep": "Продолжи со уредување",
"flow-dialog-cancelconfirm-discard": "Отфрли ги промените",
+ "flow-optin-archive-wikitext": "Преместување на страницата со викитекст за да се направи место за разговорница.",
+ "flow-optin-archive-flow-board": "Преместување на разговорница за да се направи место за страница со викитекст.",
+ "flow-optin-restore-wikitext": "Повраток на архивираниата страница со викитекст.",
+ "flow-optin-restore-flow-board": "Повраток на архивираната разговорница.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Добре дојдовте}} на {{GENDER:$1|вашата}} нова корисничка страница",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Вашата}} корисничка страница е место кајшто уредниците можат да {{GENDER:$1|ви}} се обратат. „Тек“ овозможува полесно започнување нови теми и следење на разговорите.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Вашата}} корисничка страница е место кајшто уредниците можат да {{GENDER:$1|ви}} се обратат. Структурираните дискусии овозможуваат полесно започнување нови теми и следење на разговорите.",
"flow-guidedtour-optin-find-old-conversations": "Најдете ги {{GENDER:$1|вашите}} стари разговори",
"flow-guidedtour-optin-find-old-conversations-description": "Претходните разговори се преместени на архивска страница.",
"flow-guidedtour-optin-feedback": "Дајте ни {{GENDER:$1|ваше}} мислење!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Можете}} да добиете повеќе информации, да ни дадете ваше мислење или пак да го исклучите новиот систем во било кое време од делот за бета-можности."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Можете}} да добиете повеќе информации, да ни дадете ваше мислење или пак да го исклучите новиот систем во било кое време од делот за бета-можности.",
+ "flow-action-not-page": "Предметот на страницата е пример за погрешна класа.",
+ "flow-action-wrong-title-content-model": "Страницава работи со Структурираните дискусии, но насловната класа укажува на тоа дека содржинскиот модел е „$1“. Ова може да биде погрешна поставеност или недоследна состојба. На пример, може да се работи за страница што не ги применува Структурираните дискусии, а е погрешно сместена во нивниот именски простор, без да има пополнето <code>rev_content_model</code>."
}
diff --git a/Flow/i18n/ml.json b/Flow/i18n/ml.json
index 6c4d36f1..e98cf23f 100644
--- a/Flow/i18n/ml.json
+++ b/Flow/i18n/ml.json
@@ -4,12 +4,12 @@
"Praveenp",
"Suresh.balasubra",
"Hamnashafeer",
- "Nesi"
+ "Nesi",
+ "Nnemo"
]
},
- "enableflow": "ഫ്ലോ സജ്ജമാക്കുക",
+ "enablestructureddiscussions": "ഫ്ലോ സജ്ജമാക്കുക",
"flow-desc": "പ്രവൃത്തി കൈകാര്യ സൗകര്യം",
- "flow-talk-taken-over": "ഈ സംവാദത്താൾ [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal ഫ്ലോ] ഉപയോഗിക്കുന്നു.",
"log-name-flow": "ഫ്ലോ പ്രവർത്തനരേഖ",
"logentry-delete-flow-delete-post": "[[$6]] താളിലെ \"[[$3|$5]]\" എന്നതിലുള്ള ഒരു [$4 കുറിപ്പ്] $1 {{GENDER:$2|മായ്ച്ചു}}",
"logentry-delete-flow-restore-post": "[[$6]] താളിലെ \"[[$3|$5]]\" എന്നതിലുള്ള താളിലെ ഒരു [$4 കുറിപ്പ്] $1 {{GENDER:$2|പുനഃസ്ഥാപിച്ചു}}",
@@ -25,6 +25,8 @@
"flow-board-header": "ഈ ചർച്ചയുടെ വിവരണം",
"flow-board-collapse-description": "വിവരണം മറയ്ക്കുക",
"flow-board-expand-description": "വിവരണം പ്രദർശിപ്പിക്കുക",
+ "flow-topic-collapse-siderail": "മൊത്തം വീതിയിൽ വായിക്കുക",
+ "flow-topic-expand-siderail": "നിജപ്പെടുത്തിയ വീതിയിൽ വായിക്കുക",
"flow-edit-header-link": "വിവരണം തിരുത്തുക",
"flow-post-moderated-toggle-hide-show": "$2 {{GENDER:$1|മറച്ച}} അഭിപ്രായം പ്രദർശിപ്പിക്കുക",
"flow-post-moderated-toggle-delete-show": "$2 {{GENDER:$1|മായ്ച്ച}} അഭിപ്രായം പ്രദർശിപ്പിക്കുക",
@@ -111,22 +113,15 @@
"flow-topic-action-watchlist-add": "ഈ വിഷയത്തിന്റെ വരിക്കാരുക",
"flow-topic-action-watchlist-remove": "വരിക്കാരനല്ലാതാക്കുക",
"flow-error-http": "സെർവറുമായി ബന്ധപ്പെടുന്നതിനിടെ ഒരു പിഴവുണ്ടായി.",
- "flow-error-other": "അപ്രതീക്ഷിതമായ പിഴവ് ഉണ്ടായി.",
- "flow-error-external": "പിഴവുണ്ടായി.<br />പിഴവ് സംബന്ധിച്ച് ലഭിച്ച സന്ദേശം: $1",
- "flow-error-edit-restricted": "ഈ കുറിപ്പ് തിരുത്താൻ താങ്കൾക്ക് അനുവാദമില്ല.",
+ "flow-error-external": "പിഴവുണ്ടായി. <br />പിഴവ് സംബന്ധിച്ച് ലഭിച്ച സന്ദേശം: $1",
"flow-error-topic-is-locked": "ഈ വിഷയം പരിഹരിച്ചിരിക്കുന്നു, കൂടുതൽ നടപടികൾ ആവശ്യമില്ല.",
- "flow-error-external-multi": "പിഴവുകൾ നേരിടേണ്ടി വന്നു.<br />$1",
"flow-error-missing-content": "കുറിപ്പിൽ ഉള്ളടക്കമൊന്നുമില്ല. കുറിപ്പ് സേവ് ചെയ്യാനായി ഉള്ളടക്കം വേണം.",
"flow-error-missing-summary": "സംഗ്രഹത്തിൽ ഉള്ളടക്കമൊന്നുമില്ല. സംഗ്രഹം സേവ് ചെയ്യാനായി ഉള്ളടക്കം വേണം.",
"flow-error-missing-title": "വിഷയത്തിനു തലക്കെട്ട് നൽകിയിട്ടില്ല. വിഷയം സേവ് ചെയ്യുന്നതിനായി തലക്കെട്ട് നൽകിയിരിക്കണം.",
"flow-error-parsoid-failure": "പാഴ്സോയ്ഡ് പരാജയപ്പെട്ടതിനാൽ ഉള്ളടക്കം പാഴ്സ് ചെയ്യാനായില്ല.",
"flow-error-missing-replyto": "\"ഇദ്ദേഹത്തിനുമറുപടിയിടുക\" എന്ന ചരം നൽകിയിട്ടില്ല. \"മറുപടിയിടുക\" എന്ന പ്രവൃത്തി ചെയ്യുന്നതിനു ഈ ചരം ആവശ്യമാണ്.",
- "flow-error-invalid-replyto": "\"ഇദ്ദേഹത്തിനുമറുപടിയിടുക\" എന്ന ചരം അസാധുവാണ്. ആവശ്യപ്പെട്ട കുറിപ്പ് കണ്ടെത്താനായില്ല.",
- "flow-error-delete-failure": "ഈ ഇനം മായ്ക്കൽ പരാജയപ്പെട്ടു.",
- "flow-error-hide-failure": "ഈ ഇനം മറയ്ക്കൽ പരാജയപ്പെട്ടു.",
"flow-error-missing-postId": "\"postId\" എന്ന ചരം നൽകിയിട്ടില്ല. കുറിപ്പ് കൈകാര്യം ചെയ്യുന്നതിനായി ഈ ചരം ആവശ്യമാണ്.",
"flow-error-invalid-postId": "\"postId\" എന്ന ചരം അസാധുവാണ്. ആവശ്യപ്പെട്ട കുറിപ്പ് ($1) കണ്ടെത്താനായില്ല.",
- "flow-error-restore-failure": "ഈ ഇനം പുനഃസ്ഥാപിക്കൽ പരാജയപ്പെട്ടു.",
"flow-error-invalid-moderation-state": "നിയന്ത്രണസ്ഥിതിയ്ക്ക് അസാധുവായ വിലയാണ് നൽകിയിരിക്കുന്നത്.",
"flow-error-invalid-moderation-reason": "മയപ്പെടുത്തുന്നതിനുള്ള കാരണം ദയവായി നൽകുക.",
"flow-error-not-allowed": "ഈ പ്രവൃത്തി ചെയ്യുന്നതിനാവശ്യമായ അനുമതികൾ ഇല്ല.",
@@ -204,10 +199,9 @@
"flow-no-more-fwd": "പഴയ വിഷയങ്ങൾ ഒന്നുമില്ല",
"flow-newest-topics": "ഏറ്റവും പുതിയ വിഷയങ്ങൾ",
"flow-recent-topics": "സമീപകാലത്ത് സജീവമായ വിഷയങ്ങൾ",
- "flow": "പ്രവാഹം",
+ "structureddiscussions": "പ്രവാഹം",
"flow-special-type": "തരം",
"flow-special-type-post": "കുറിപ്പ്",
- "apihelp-flow+view-topic-history-description": "ഒരു വിഷയത്തിന്റെ നാൾവഴി പരിശോധിക്കുക.",
"flow-previous-diff": "← പഴയ തിരുത്ത്",
"flow-next-diff": "പുതിയ തിരുത്ത് →",
"flow-undo": "തിരസ്കരിക്കുക",
@@ -224,6 +218,5 @@
"flow-wikitext-editor-help": "വിക്കിഎഴുത്ത് $1.",
"flow-wikitext-editor-help-preview-the-result": "ഫലം എങ്ങനെയുണ്ടെന്ന് കാണുക",
"flow-wikitext-switch-editor-tooltip": "കണ്ടുതിരുത്തൽ ഉപകരണത്തിലേക്ക് മാറുക",
- "flow-ve-switch-editor-tool-title": "വിക്കി എഴുത്തിലേക്ക് മാറുക",
- "flow-description-last-modified-at": "ഈ വിവരണം അവസാനം തിരുത്തിയത് $1 -നു $2 മണിക്കാണ്"
+ "flow-ve-switch-editor-tool-title": "വിക്കി എഴുത്തിലേക്ക് മാറുക"
}
diff --git a/Flow/i18n/mn.json b/Flow/i18n/mn.json
index 20954a29..93c5caf5 100644
--- a/Flow/i18n/mn.json
+++ b/Flow/i18n/mn.json
@@ -9,6 +9,5 @@
"flow-topic-notification-subscribe-title": "Энэ сэдэв өөрийн тань watchlist -д орлоо.",
"flow-topic-notification-subscribe-description": "Энэ сэдвийн дагуух бүх үйл явдлын тоймыг хүлээх авах болно.",
"flow-board-notification-subscribe-title": "Энэ хэлэлцүүлгийн самбарт feed хийсэн байна!",
- "flow-board-notification-subscribe-description": "Энэ самбарт шинээр үүссэн бүх сэдвийг автоматаар хүлээн авах болно.",
- "flow-error-move": "Хэлэлцүүлгийн самбарыг шилжүүлэх боломжгүй. одоогоор."
+ "flow-board-notification-subscribe-description": "Энэ самбарт шинээр үүссэн бүх сэдвийг автоматаар хүлээн авах болно."
}
diff --git a/Flow/i18n/mr.json b/Flow/i18n/mr.json
index 63a2d2ba..2486b0b3 100644
--- a/Flow/i18n/mr.json
+++ b/Flow/i18n/mr.json
@@ -2,22 +2,376 @@
"@metadata": {
"authors": [
"V.narsikar",
- "संतोष दहिवळ"
+ "संतोष दहिवळ",
+ "Nnemo",
+ "अभय नातू",
+ "Macofe"
]
},
- "flow-newtopic-title-placeholder": "संदेशाचा विषय",
+ "enablestructureddiscussions": "प्रवाहास(फ्लो) सक्षम करा",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "आपण [$2 हा विषय] कधीही बघु शकता.",
+ "flow-desc": "कार्यप्रवाह व्यवस्थापन प्रणाली",
+ "flow-talk-taken-over-comment": "/* हे पान प्रवाह चर्चा फलकात रुपांतरित केल्या गेले आहे*/",
+ "log-name-flow": "प्रवाह क्रियांच्या नोंदी",
+ "logentry-delete-flow-delete-post": "[[$6]]च्या \"[[$3|$5]]\" वर असलेले एक [$4 टपालन] $1 ने {{GENDER:$2|वगळले}}",
+ "logentry-delete-flow-restore-post": "[[$6]]च्या \"[[$3|$5]]\" वर असलेले एक [$4 टपालन] $1 ने {{GENDER:$2|पुनर्स्थापित केले}}",
+ "logentry-suppress-flow-suppress-post": "[[$6]]च्या \"[[$3|$5]]\" वर असलेले एक [$4 टपालन] $1 ने {{GENDER:$2|दमन केले}}",
+ "logentry-suppress-flow-restore-post": "[[$6]]च्या \"[[$3|$5]]\" वर असलेले एक [$4 टपालन] $1 ने {{GENDER:$2|वगळले}}",
+ "logentry-delete-flow-delete-topic": "[[$6]]च्या \"[[$3|$5]]\" वर असलेला एक विषय $1 ने {{GENDER:$2|वगळला}}",
+ "logentry-delete-flow-restore-topic": "[[$6]]च्या \"[[$3|$5]]\" वर असलेला एक विषय $1 ने {{GENDER:$2|पुनर्स्थापित केला}}",
+ "logentry-suppress-flow-suppress-topic": "[[$6]]च्या \"[[$3|$5]]\" वर असलेला एक विषय $1 ने {{GENDER:$2|दमन केला}}",
+ "logentry-suppress-flow-restore-topic": "[[$6]]च्या \"[[$3|$5]]\" वर असलेला एक विषय $1 ने {{GENDER:$2|वगळला}}",
+ "logentry-lock-flow-lock-topic": "$1 ने [[$6]] वर,\"[[$3|$5]]\" हा विषय सोडविण्यात आला अशी {{GENDER:$2|खूण केली}}",
+ "logentry-lock-flow-restore-topic": "$1 ने [[$6]] वर,\"[[$3|$5]]\" हा विषय पुन्हा सुरु करण्यात आला अशी {{GENDER:$2|खूण केली}}",
+ "flow-user-moderated": "नेमलेला सदस्य",
+ "flow-board-header-browse-topics-link": "विषय न्याहाळा",
+ "flow-board-header": "या फलकाबाबत",
+ "flow-board-collapse-description": "वर्णन लपवा",
+ "flow-board-expand-description": "वर्णन दाखवा",
+ "flow-topic-collapse-siderail": "वाचनासाठी पूर्ण रुंदीचे करा",
+ "flow-topic-expand-siderail": "वाचनासाठी नियत रुंदीचे करा",
+ "flow-edit-header-link": "वर्णन संपादित करा",
+ "flow-post-moderated-toggle-hide-show": "$2 द्वारे {{GENDER:$1|लपविलेला}} अभिप्राय दाखवा",
+ "flow-post-moderated-toggle-delete-show": "$2 द्वारे {{GENDER:$1|वगळलेला}} अभिप्राय दाखवा",
+ "flow-post-moderated-toggle-suppress-show": "$2 द्वारे {{GENDER:$1|दमन केलेला}} अभिप्राय दाखवा",
+ "flow-post-moderated-toggle-hide-hide": "$2 द्वारे {{GENDER:$1|लपविलेला}} अभिप्राय लपवा",
+ "flow-post-moderated-toggle-delete-hide": "$2 द्वारे {{GENDER:$1|वगळलेला}} अभिप्राय लपवा",
+ "flow-post-moderated-toggle-suppress-hide": "$2 द्वारे {{GENDER:$1|दमन केलेला}} अभिप्राय लपवा",
+ "flow-topic-moderated-reason-prefix": "कारण:",
+ "flow-hide-post-content": "हा अभिप्राय $1 द्वारे {{GENDER:$1|लपविलेला}} होता ([$2 इतिहास])",
+ "flow-hide-title-content": "हा विषय $1 द्वारे {{GENDER:$1|लपविलेला}} होता",
+ "flow-hide-header-content": "$2 द्वारे {{GENDER:$1|लपविला}}",
+ "flow-delete-post-content": "हा अभिप्राय $1 द्वारे {{GENDER:$1|वगळलेला}} होता ([$2 इतिहास])",
+ "flow-delete-title-content": "हा विषय $1 द्वारे {{GENDER:$1|वगळलेला}} होता",
+ "flow-delete-header-content": "$2 द्वारे {{GENDER:$1|वगळला}}",
+ "flow-suppress-post-content": "हा अभिप्राय $1 द्वारे {{GENDER:$1|दमन केला}} होता ([$2 इतिहास])",
+ "flow-suppress-title-content": "हा विषय $1 द्वारे {{GENDER:$1|दमन केला}} होता",
+ "flow-suppress-header-content": "$2 द्वारे {{GENDER:$1|दमन केला}}",
+ "flow-suppress-usertext": "<em>सदस्यनाव दमन केले</em>",
+ "flow-post-actions": "क्रिया",
+ "flow-topic-actions": "क्रिया",
+ "flow-cancel": "रद्द करा",
+ "flow-skip-summary": "गोषवाऱ्यास बगल द्या",
+ "flow-edit-summary-placeholder": "या चर्चेच्या निष्कर्षाचे थोडक्यात वर्णन करा",
+ "flow-summary-authored": "$1 द्वारे गोषवारा",
+ "flow-summary-edited": "$1 द्वारे शेवटचा {{GENDER:$1|संपादलेला}} सारांश",
+ "flow-show-change": "बदल दाखवा",
+ "flow-last-modified-by": "$1 द्वारे शेवटचा फेरबदल",
+ "flow-stub-post-content": "\"तांत्रिक कारणामुळे, हे टपालन(पोस्ट) हुडकता आले नाही,\"",
+ "flow-newtopic-title-placeholder": "नवा विषय",
+ "flow-newtopic-content-placeholder": "\"$1\"ला नविन संदेश टाका",
+ "flow-newtopic-header": "नया विषय जोडा",
+ "flow-newtopic-save": "विषय जोडा",
+ "flow-newtopic-save-anonymously": "अनामिकरित्या विषय जोडा",
+ "flow-newtopic-start-placeholder": "नविन विषय सुरु करा",
+ "flow-newtopic-first-heading": "$1 वर नविन विषय सुरु करा",
+ "flow-summarize-topic-placeholder": "कृपया चर्चेचा गोषवारा तयार करा",
+ "flow-reply-topic-placeholder": "\"$2\" वरचे {{GENDER:$1|अभिप्राय}}",
+ "flow-reply-topic-title-placeholder": " \"$1\" ला उत्तर द्या",
+ "flow-reply-link": "{{GENDER:$1|उत्तर}}",
+ "flow-reply-link-anonymously": "अनामिकरित्या उत्तर द्या",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|धन्यवाद}}}}",
+ "flow-thank-link-title": "टपालन करणाऱ्याला(पोस्टर) सार्वजनिकरित्या {{GENDER:$1|{{GENDER:$2|धन्यवाद द्या}}}}",
+ "flow-history-action-suppress-post": "दमन करा(सप्रेस)",
+ "flow-history-action-delete-post": "वगळा",
+ "flow-history-action-hide-post": "लपवा",
+ "flow-history-action-unsuppress-post": "दमन केलेले काढा",
+ "flow-history-action-undelete-post": "वगळलेले पुनर्स्थापित करा",
+ "flow-history-action-unhide-post": "प्रगट करा",
+ "flow-history-action-restore-post": "पुनर्स्थापन करा",
+ "flow-history-action-lock-topic": "निराकरण करा",
+ "flow-history-action-unlock-topic": "पुन्हा सुरू करा",
+ "flow-post-edited": "$1 $2 द्वारे टपालन {{GENDER:$1|संपादल्या गेले}}",
+ "flow-post-action-view": "शाश्वतदुवा",
"flow-post-action-post-history": "इतिहास",
+ "flow-post-action-suppress-post": "दमन करा(सप्रेस)",
+ "flow-post-action-delete-post": "वगळा",
+ "flow-post-action-hide-post": "लपवा",
"flow-post-action-edit-post": "संपादन",
+ "flow-post-action-edit-post-submit": "बदल जतन करा",
+ "flow-post-action-edit-post-submit-anonymously": "अनामिकरित्या बदल जतन करा",
+ "flow-post-action-unsuppress-post": "दमन (सप्रेस) केलेले काढा",
+ "flow-post-action-undelete-post": "वगळलेले पुनर्स्थापित करा",
+ "flow-post-action-unhide-post": "प्रगट करा",
+ "flow-post-action-restore-post": "पुनर्स्थापन करा",
+ "flow-post-action-undo-moderation": "केलेले रद्द करा",
+ "flow-topic-action-view": "शाश्वतदुवा",
+ "flow-topic-action-watchlist": "निरीक्षणसूची",
+ "flow-topic-action-edit-title": "शीर्षक संपादा",
"flow-topic-action-history": "इतिहास",
- "flow-error-external": "आपले उत्तर जतन करण्यात त्रूटी घडली.<br />मिळालेला त्रूटी संदेश असा होता: $1",
- "flow-error-external-multi": "आपले उत्तर जतन करण्यात त्रूटी आढळल्या.आपले उत्तर जतन झाले नाही.<br />$1",
- "flow-error-missing-title": "विषयास मथळा नाही.एखाद्या विषयास जतन करावयाचे तर मथळा हवा.",
- "flow-error-prev-revision-mismatch": "काही सेकंदांपूर्वी दुसऱ्या सदस्याने हे टपालन संपादन केले आहे.अलीकडील बदलांवर आपणास उपरीलेखन(ओव्हरराईट) करावयाचे हे नक्की काय?",
+ "flow-topic-action-hide-topic": "विषय लपवा",
+ "flow-topic-action-delete-topic": "विषय वगळा",
+ "flow-topic-action-lock-topic": "निराकरण केले म्हणून खूण करा",
+ "flow-topic-action-unlock-topic": "विषय पुन्हा सुरु करा",
+ "flow-topic-action-summarize-topic": "सारांशित करा",
+ "flow-topic-action-resummarize-topic": "विषय सारांशाचे संपादन करा",
+ "flow-topic-action-update-topic-summary": "सारांश अद्यतन करा",
+ "flow-topic-action-suppress-topic": "विषयाचे दमन करा(सप्रेस)",
+ "flow-topic-action-unhide-topic": "विषय प्रगट करा",
+ "flow-topic-action-undelete-topic": "वगळलेला विषय पुनर्स्थापा",
+ "flow-topic-action-unsuppress-topic": "विषयाचे दमन काढा",
+ "flow-topic-action-restore-topic": "विषयाची पुनर्स्थापना करा",
+ "flow-topic-action-undo-moderation": "उलटवा",
+ "flow-topic-notification-subscribe-title": "हा विषय {{GENDER:$1|आपल्या}} निरीक्षणसूचीत जोडल्या गेला आहे.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|आपणास}} या विषयावरच्या सर्व क्रियाकलापांबद्दल अधिसूचना मिळतील",
+ "flow-board-notification-subscribe-title": "या चर्चाफलकाचे {{GENDER:$1|आपण}} वर्गणीदार झाला आहात!",
+ "flow-board-notification-subscribe-description": "या फलकावर नविन विषय तयार झाला तर त्याची {{GENDER:$1|आपणास}} अधिसूचना मिळेल.",
+ "flow-topic-action-watchlist-add": "या विषयाचे वर्गणीद्वार व्हा",
+ "flow-error-allowcreation-no-usedb": "allowCreation ला <var>$wgContentHandlerUseDB</var> to be <code>खरे</code> हवे.",
+ "flow-error-allowcreation-already-exists": "पान पूर्वीच अस्तित्वात आहे परंतु ते (अस्तित्वात) नसणे हवे आहे",
+ "flow-error-allowcreation-flow-create-board": "सदस्यास \"{{int:right-flow-create-board}}\" परवानगी नाही",
+ "flow-error-http": "विदागारास संपर्क करायच्या प्रयत्नात त्रुटी उद्भवली.",
+ "flow-error-external": "एक त्रुटी घडली.<br />प्राप्त त्रुटी संदेश असा होता: $1",
+ "flow-error-topic-is-locked": "या विषयाचे निराकरण झाले आहे,सबब पुढील क्रिया शक्य नाही.",
+ "flow-error-lock-moderated-post": "नेमस्त टपालनावर (मॉडरेटेड पोस्ट) आपण निराकरण केल्याची खूण करु शकत नाही.",
+ "flow-error-missing-content": "टपालनात काहीच आशय नाही. टपालन जतन करण्यास त्यात काहीतरी आशय हवा.",
+ "flow-error-missing-summary": "आपण सारांश सादर करावयास हवा.",
+ "flow-error-missing-title": "या विषयास शीर्षक नाही.एखाद्या विषयास जतन करावयाचे तर मथळा हवा.",
+ "flow-error-missing-replyto": "\"ला उत्तर\" हा प्राचल पुरविल्या गेला नाही. \"उत्तर देणे\" या क्रियेत हा प्राचल हवा.",
+ "flow-error-missing-postId": "\"टपालनऑळखण\" प्राचल पुरविल्या गेला नाही.टपालनाची रदबदली करण्यास हा प्राचल आवश्यक आहे.",
+ "flow-error-invalid-postId": "\"टपालनऑळखण\" प्राचल अवैध होता.नमूद केलेले टपालन ($1) सापडले नाही.",
+ "flow-error-invalid-moderation-state": "फ्लो एपीआय ला ('moderationState') या प्राचलाची अवैध किंमत सादर केल्या गेली.",
+ "flow-error-invalid-moderation-reason": "नेमस्त करण्यासाठी कारण द्या.",
+ "flow-error-not-allowed": "ही क्रिया करण्यास परवानग्या अपर्याप्त आहेत.",
+ "flow-error-not-allowed-hide": "हा विषय लपविल्या गेला आहे.",
+ "flow-error-not-allowed-reply-to-hide-topic": "आपण उत्तर देऊ शकत नाही कारण हा विषय लपविण्यात आलेला आहे.",
+ "flow-error-not-allowed-delete": "हा विषय वगळला आहे.",
+ "flow-error-not-allowed-reply-to-delete-topic": "आपण उत्तर देऊ शकत नाही कारण हा विषय वगळला आहे.",
+ "flow-error-not-allowed-suppress": "हा विषय वगळला आहे.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "आपण उत्तर देऊ शकत नाही कारण हा विषय वगळला आहे.",
+ "flow-error-not-allowed-hide-extract": "हा विषय लपविल्या गेला आहे. या विषयावरच्या लपविलेल्याच्या नोंदी संदर्भासाठी खाली दिलेल्या आहेत.",
+ "flow-error-not-allowed-delete-extract": "हा विषय वगळल्या गेला आहे. या विषयावरच्या वगळल्याच्या नोंदी संदर्भासाठी खाली दिलेल्या आहेत.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "आपण उत्तर देऊ शकत नाही कारण हा विषय वगळल्या गेला आहे. या विषयावरच्या वगळल्याच्या नोंदी संदर्भासाठी खाली दिलेल्या आहेत.",
+ "flow-error-not-allowed-suppress-extract": "हा विषय वगळल्या गेला आहे. या विषयावरच्या वगळल्याच्या नोंदी संदर्भासाठी खाली दिलेल्या आहेत.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "आपण उत्तर देऊ शकत नाही कारण या विषयाचे दमन केल्या गेले आहे. या विषयावरच्या दमनाच्या नोंदी संदर्भासाठी खाली दिलेल्या आहेत.",
+ "flow-error-title-too-long": "विषयाचे शीर्षक हे $1 {{PLURAL:$1|बाइट|बाइटस्}} पर्यंतच मर्यादित आहेत.",
+ "flow-error-no-existing-workflow": "अद्याप हा कार्यप्रवाह अस्तित्वात नाही.",
+ "flow-error-not-a-post": "विषय शीर्षक हे टपालन म्हणून जतन केल्या जाऊ शकत नाही.",
+ "flow-error-missing-header-content": "आपण वर्णन सादर करावयास हवे.",
+ "flow-error-missing-prev-revision-identifier": "मागील आवृत्तीची ओळखण हरवली आहे.",
+ "flow-error-prev-revision-mismatch": "काही सेकंदांपूर्वी दुसऱ्या सदस्याने हे टपालन संपादन केले आहे.अलीकडील बदलांवर {{GENDER:$3|आपणास}} उपरीलेखन(ओव्हरराईट) करावयाचे याची खात्री देता काय?",
"flow-error-prev-revision-does-not-exist": "मागील आवृत्ती शोधता आली नाही.",
- "flow-notification-mention-email-subject": "$1 ने \"$2\"वर आपला {{GENDER:$1|उल्लेख केला}}",
+ "flow-error-core-topic-deletion": "विषय वगळन्यास, प्रवाह फलकावर असलेला ...मेनु वापरा किंवा [$1 विषय पान] हा. विषयासाठीच्या क्रिया=वगळा वर थेट पोहोचु नका.",
+ "flow-error-default": "एक त्रुटी घडली",
+ "flow-error-invalid-input": "प्रवाह आशय प्रभारण्यास अवैध किंमत टाकल्या गेली.",
+ "flow-error-invalid-title": "अवैध पान शीर्षक टाकल्या गेले.",
+ "flow-error-fail-load-history": "इतिहास भारण करण्यात अयशस्वी.",
+ "flow-error-missing-revision": "प्रवाह आशय प्रभारण करण्यास आवृत्ती सापडली नाही.",
+ "flow-error-fail-commit": "प्रवाह आशय जतन करण्यात अयशस्वी.",
+ "flow-error-insufficient-permission": "आशयावर पोहोचण्यास अपुरी परवानगी.",
+ "flow-error-revision-comparison": "एकाच टपालनाच्या असलेल्या दोन आवृत्यात Diff क्रिया केल्या जाऊ शकते.",
+ "flow-error-missing-topic-title": "सध्याच्या कार्यप्रवाहात विषय मथळा सापडला नाही.",
+ "flow-error-missing-metadata": "या आवृत्तीसाठी आवश्यक मेटाडाटा सापडला नाही.",
+ "flow-error-fail-load-data": "विनंती केलेला डाटा प्रभारण करण्यात अयशस्वी.",
+ "flow-error-invalid-workflow": "विनंती केलेला कार्यप्रवाह सापडला नाही.",
+ "flow-error-process-data": "आपल्या विनंतीतील डाटावर प्रक्रिया करण्यादरम्यान त्रुटी घडली.",
+ "flow-error-process-wikitext": "एचटीएमएल/विकिमजकूर यातील बदलक्रियेच्या प्रक्रियेदरम्यान,त्रुटी घडली.",
+ "flow-error-no-index": "डाटा शोध घेण्यासाठी, अनुक्रमणिका सापडण्यात अयशस्वी.",
+ "flow-error-no-render": "नमूद केलेली क्रिया ओळखल्या गेली नाही.",
+ "flow-error-no-commit": "नमूद केलेली क्रिया जतन करता आली नाही.",
+ "flow-error-content-too-long": "आशय हा बऱ्याच लांबीचा आहे. प्रसरणानंतरचा आशय हा $1 {{PLURAL:$1|बाइट|बाइटस्}} पुरता मर्यादित आहे.",
+ "flow-error-move-topic": "विषय पानाचे स्थलांतरण सध्या सहाय्यीकृत नाही.",
+ "flow-error-invalid-topic-uuid-title": "खराब शीर्षक",
+ "flow-error-invalid-topic-uuid": "विनंती केलेले पानशीर्षक अवैध आहे.विषय नामविश्वात असणारी पाने प्रवाहाद्वारे स्वयंचलितरित्या तयार केल्या जातात.",
+ "flow-error-unknown-workflow-id-title": "अज्ञात विषय",
+ "flow-error-unknown-workflow-id": "आपण विनंती केलेला विषय अस्तित्वात नाही.",
+ "flow-error-search": "आम्ही आपला शोध काही तारपुरत्या अडचणींमुळे पूर्ण करु शकलो नाही. कृपया नंतर पुन्हा प्रयत्न करा.",
+ "flow-edit-header-placeholder": "या चर्चा फलकाचे वर्णन करा",
+ "flow-edit-header-submit": "वर्णन जतन करा",
+ "flow-edit-header-submit-anonymously": "वर्णन अनामिकरित्या जतन करा",
+ "flow-edit-title-submit": "शीर्षक बदला",
+ "flow-edit-title-submit-anonymously": "शीर्षक अनामिकरित्या बदला",
+ "flow-edit-post-submit": "बदल सादर करा",
+ "flow-edit-post-submit-anonymously": "बदल अनामिकरित्या सादर करा",
+ "flow-rev-message-edit-post": "$1 ने \"$4\" वर एका [$3 अभिप्रायाचे] {{GENDER:$2|संपादन केले}}",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|एक पोस्टात बदल केला}}",
+ "flow-rev-message-reply": "$1 ने \"$4\" वर(<em>$5</em>)[$3 {{GENDER:$2|अभिप्राय दिला}}]",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|अभिप्राय}}</strong> {{PLURAL:$1|जोडल्या गेला|जोडल्या गेलेत}}",
+ "flow-rev-message-new-post": "$1 ने \"[$3 $4]\" हा विषय {{GENDER:$2|तयार केला}}",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|नवीन विषय तयार केला}}",
+ "flow-rev-message-edit-title": "$1 ने \"$5\" हुन \"[$3 $4]\" ला विषय शीर्षक {{GENDER:$2|बदलले}}",
+ "flow-rev-message-create-header": "$1 ने वर्णन {{GENDER:$2|तयार केले}}",
+ "flow-rev-message-edit-header": "$1 ने वर्णन {{GENDER:$2|संपादन केले}}",
+ "flow-rev-message-create-topic-summary": "$1 ने $3 वर विषय सारांश {{GENDER:$2|तयार केला}}",
+ "flow-rev-message-edit-topic-summary": "$1 ने $3 वर विषय सारांश {{GENDER:$2|संपादन केला}}",
+ "flow-rev-message-hid-post": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 अभिप्राय] {{GENDER:$2|लपविला}}",
+ "flow-rev-message-deleted-post": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 अभिप्राय] {{GENDER:$2|वगळला}}",
+ "flow-rev-message-suppressed-post": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 अभिप्राय] {{GENDER:$2|दमन केला}}",
+ "flow-rev-message-restored-post": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 अभिप्राय] {{GENDER:$2|पुनर्स्थापित केला}}",
+ "flow-rev-message-hid-topic": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 विषय] {{GENDER:$2|लपविला}}",
+ "flow-rev-message-deleted-topic": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 विषय] {{GENDER:$2|वगळला}}",
+ "flow-rev-message-suppressed-topic": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 विषय] {{GENDER:$2|दमन केला}}",
+ "flow-rev-message-locked-topic": "$1 ने [$4 विषय] $6 वियोजित म्हणुन (<em>$5</em>){{GENDER:$2|खूण केली}}",
+ "flow-rev-message-lock-topic-reason": "'वियोजित' म्हणून खूण केली",
+ "flow-rev-message-restore-topic-reason": "पुन्हा सुरु केला",
+ "flow-rev-message-restored-topic": "$1 ने \"$6\" वर (<em>$5</em>) एक [$4 विषय] {{GENDER:$2|पुनर्स्थापित केला}}",
+ "flow-rc-topic-of-board": "$2 वर $1",
+ "flow-board-history": "\"$1\" इतिहास",
+ "flow-board-history-empty": "या फलकास सध्या इतिहास नाही.",
+ "flow-topic-history": "\"$1\" विषय इतिहास",
+ "flow-history-last4": "शेवटचे ४ तास",
+ "flow-history-day": "आज",
+ "flow-history-week": "मागील आठवडयात",
+ "flow-history-pages-topic": "[$1 \"$2\" फलकावर] दिसते",
+ "flow-history-pages-post": "[$1 \"$2\"] वर दिसते",
+ "flow-topic-comments": "{{PLURAL:$1|$1 अभिप्राय|0={{GENDER:$2|अभिप्राय देणारे प्रथम असा!}} }}",
+ "flow-show-comments-title": "{{PLURAL:$1|अभिप्राय बघा}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|अभिप्राय लपवा}}",
+ "flow-comment-restored": "पुनर्स्थापिलेले अभिप्राय",
+ "flow-comment-deleted": "वगळलेले अभिप्राय",
+ "flow-comment-hidden": "लपविलेले अभिप्राय",
+ "flow-comment-moderated": "नेमस्त केलेले अभिप्राय",
+ "flow-last-modified": "$1 बद्दल शेवटचा बदल",
+ "flow-workflow": "कार्यप्रवाह",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> वर {{PLURAL:$1|एक नविन विषय|$1 नविन विषय|100=99+ नविन विषय}}",
+ "notification-header-flow-enabled-on-talkpage": "{{GENDER:$2|आपल्या}} चर्चा पानासाठी नविन चर्चा प्रणाली सक्षम केली आहे",
+ "flow-notification-link-text-view-post": "टपालन बघा",
+ "flow-notification-link-text-view-topic": "विषय बघा",
+ "flow-notification-reply-email-subject": "$3 वर $2",
+ "flow-notification-reply-email-batch-body": "$1 ने \"$2\" ला $3 वर {{GENDER:$1|प्रतिसाद दिला}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 व $4 {{PLURAL:$5|इतरांनी}} $3 वर \"$2\"ला {{GENDER:$1|प्रतिसाद दिला}}",
+ "flow-notification-mention-email-subject": "$1 ने \"$2\"वर {{GENDER:$3|आपला}} {{GENDER:$1|उल्लेख केला}}",
+ "flow-notification-edit-email-subject": "एक टपालन $1 ने{{GENDER:$1|संपादन केले}}",
"flow-notification-newtopic-email-subject": "$1 ने \"$2\" वर एक नविन विषय {{GENDER:$1|तयार केला}}",
+ "echo-category-title-flow-discussion": "प्रवाह",
+ "echo-pref-tooltip-flow-discussion": "प्रवाहावर माझ्यासंबंधी एखादी क्रिया घडल्यास मला कळवा.",
+ "flow-link-post": "टपालन",
+ "flow-link-topic": "विषय",
+ "flow-link-history": "इतिहास",
+ "flow-link-post-revision": "टपालन आवृत्ती",
+ "flow-link-topic-revision": "विषय उजळणी",
+ "flow-link-header-revision": "वर्णन उजळणी",
+ "flow-link-summary-revision": "सारांश उजळणी",
+ "flow-moderation-title-suppress-post": "टपालन दमन करु?",
+ "flow-moderation-title-delete-post": "टपालन वगळु?",
+ "flow-moderation-title-hide-post": "टपालन लपवु?",
+ "flow-moderation-placeholder-suppress-post": "आपण या टपालनाचे कां दमन करीत आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-placeholder-delete-post": "आपण या टपालनास कां वगळत आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-placeholder-hide-post": "आपण या टपालनास कां लपवित आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-placeholder-unsuppress-post": "आपण या टपालनाचे दमन कां काढीत आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-placeholder-undelete-post": "आपण या टपालनाचे पुनर्स्थापन कां करीत आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-placeholder-unhide-post": "आपण या टपालनास उघड कां करीत आहे याचा कृपया {{GENDER:$3|खुलासा करा}}.",
+ "flow-moderation-confirm-suppress-post": "दमन करा(सप्रेस)",
+ "flow-moderation-confirm-delete-post": "वगळा",
+ "flow-moderation-confirm-hide-post": "लपवा",
+ "flow-moderation-confirm-unsuppress-post": "दमन केलेले काढा",
+ "flow-moderation-confirm-undelete-post": "वगळलेले पुनर्स्थापित करा",
+ "flow-moderation-confirm-unhide-post": "दर्शवा",
+ "flow-moderation-confirm-suppress-topic": "दमन करा(सप्रेस)",
+ "flow-moderation-confirm-delete-topic": "वगळा",
+ "flow-moderation-confirm-hide-topic": "लपवा",
+ "flow-moderation-confirm-unsuppress-topic": "दमन काढा",
+ "flow-moderation-confirm-undelete-topic": "वगळलेले पुनर्स्थापित करा",
+ "flow-moderation-confirm-unhide-topic": "दर्शवा",
+ "flow-moderation-confirmation-suppress-post": "हे टपालन यशस्वीरित्या दमन केल्या गेले. $1ला याबद्दल प्रतिक्रिया देण्याबाबत {{GENDER:$2|विचार करा}}.",
+ "flow-moderation-confirmation-delete-post": "हे टपालन यशस्वीरित्या वगळल्या गेली. $1ला याबद्दल प्रतिक्रिया देण्याबाबत {{GENDER:$2|विचार करा}}.",
+ "flow-moderation-confirmation-hide-post": "हे टपालन यशस्वीरित्या लपविल्या गेली. $1ला याबद्दल प्रतिक्रिया देण्याबाबत {{GENDER:$2|विचार करा}}.",
+ "flow-moderation-confirmation-unsuppress-post": "आपण यशस्वीरित्या वरील टपालनाचे दमन काढले.",
+ "flow-moderation-confirmation-undelete-post": "आपण यशस्वीरित्या वरील टपालनाचे पुनर्स्थापन केले.",
+ "flow-moderation-confirmation-unhide-post": "आपण यशस्वीरित्या वरील टपालन प्रगट केले.",
+ "flow-moderation-confirmation-suppress-topic": "हा विषय दमन केल्या गेला आहे.",
+ "flow-moderation-confirmation-delete-topic": "हा विषय वगळल्या गेला आहे.",
+ "flow-moderation-confirmation-hide-topic": "हा विषय लपविल्या गेला आहे.",
+ "flow-moderation-confirmation-unsuppress-topic": "आपण यशस्वीरित्या या विषयाचे दमन काढले.",
+ "flow-moderation-confirmation-undelete-topic": "आपण यशस्वीरित्या या विषयाचे पुनर्स्थापन केले.",
+ "flow-moderation-confirmation-unhide-topic": "आपण यशस्वीरित्या या विषयास प्रगट केले.",
+ "flow-moderation-title-suppress-topic": "विषय दमन करु?",
+ "flow-moderation-title-delete-topic": "विषय वगळु?",
+ "flow-moderation-title-hide-topic": "विषय लपवु?",
+ "flow-moderation-title-unsuppress-topic": "विषयाचे दमन काढु?",
+ "flow-moderation-title-undelete-topic": "विषयास पुनर्स्थापित करु?",
+ "flow-moderation-title-unhide-topic": "विषयाचे प्रगट करु?",
+ "flow-moderation-placeholder-suppress-topic": "कृपया हा विषय आपण कां दमन करीत आहे ते {{GENDER:$3|समजवा}}.",
+ "flow-moderation-placeholder-delete-topic": "कृपया हा विषय आपण कां वगळत आहे ते {{GENDER:$3|समजवा}}.",
+ "flow-moderation-placeholder-hide-topic": "कृपया हा विषय आपण कां लपवित आहे ते {{GENDER:$3|समजवा}}.",
+ "flow-moderation-placeholder-unsuppress-topic": "कृपया हा विषय आपण कां प्रगट करीत आहे ते {{GENDER:$3|समजवा}}.",
+ "flow-moderation-placeholder-undelete-topic": "कृपया हा विषय आपण कां पुनर्स्थापित करीत आहे ते {{GENDER:$3|समजवा}}.",
+ "flow-moderation-placeholder-unhide-topic": "हा विषय प्रकट करण्याचे कारण कृपया {{GENDER:$3|समजवा}}.",
+ "flow-topic-permalink-warning": "हा विषय [$2 $1] या वेळी सुरु केला गेला होता",
+ "flow-topic-permalink-warning-user-board": "[$2 {{GENDER:$1|$1}}च्या फलकावर] हा विषय सुरु केला गेला",
+ "flow-compare-revisions-revision-header": "$1 मार्फतची {{GENDER:$2|$2}} ची आवृत्ती",
+ "action-flow-create-board": "कोणत्याही ठिकाणी प्रवाह फलक निर्माण करा",
+ "right-flow-create-board": "कोणत्याही ठिकाणी प्रवाह फलक निर्माण करा",
+ "right-flow-hide": "प्रवाहित विषय व टपालन लपवा",
+ "right-flow-lock": "प्रवाहित विषयास वियोजित केला म्हणून खूण करा",
+ "right-flow-delete": "प्रवाहित विषय व टपालन वगळा",
+ "right-flow-edit-post": "दुसऱ्या सदस्याचे टपालन संपादा",
+ "right-flow-suppress": "प्रवाही आवृत्त्यांचे दमन करा",
"flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\" टिचकण्याने,आपण या विकिच्या वापरण्याच्या अटी मान्य करीत आहात.",
"flow-terms-of-use-reply": "\"{{int:flow-reply-link}}\" टिचकण्याने, आपण या विकिच्या 'वापरण्याच्या अटी' मान्य करीत आहात.",
"flow-terms-of-use-edit": "आपले बदल 'जतन करण्याने',आपण या विकिच्या 'वापरण्याच्या अटी' मान्य करीत आहात.",
- "flow-anon-warning": "आपण सनोंद प्रवेशित नाहीत."
+ "flow-anon-warning": "आपण सनोंद प्रवेशित नाहीत.आपल्या अंकपत्त्याऐवही आपल्या नावास श्रेय मिळण्यास [$1 सनोंद प्रवेश करा] किंवा [$2 खाते तयार करा].",
+ "flow-cancel-warning": "या आवेदनात आपण मजकूर टाकला आहे. आपण शाबीत करता कि ते हटवायचे आहे?",
+ "flow-topic-first-heading": "$1 वरील विषय",
+ "flow-topic-html-title": "$2 वर $1",
+ "flow-topic-count": "($1) विषय",
+ "flow-load-more": "अधिक प्रभारण करा",
+ "flow-no-more-fwd": "जूने विषय नाहीत",
+ "flow-newest-topics": "नविनतम विषय",
+ "flow-recent-topics": "सध्या सक्रिय असलेले विषय",
+ "flow-sorting-tooltip-newest": "{{GENDER:|आपण}} सध्या नविनतम विषयांचे वाचन करीत आहात. अधिक पृथक-पर्याय निवडण्यासाठी टिचका.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|आपण}} सध्या अलीकडील सर्वात सक्रिय विषयांचे वाचन करीत आहात. अधिक पृथक-पर्याय निवडण्यासाठी टिचका.",
+ "flow-terms-of-use-summarize": "\"{{int:flow-topic-action-update-topic-summary}}\" हे टिचकण्याने आपण या विकिकरीता असलेल्या वापराच्या अटी मान्य करता.",
+ "flow-terms-of-use-lock-topic": "\"{{int:flow-topic-action-lock-topic}}\" हे टिचकण्याने आपण या विकिकरीता असलेल्या वापराच्या अटी मान्य करता.",
+ "flow-terms-of-use-unlock-topic": "\"{{int:flow-topic-action-unlock-topic}}\" हे टिचकण्याने आपण या विकिकरीता असलेल्या वापराच्या अटी मान्य करता.",
+ "flow-whatlinkshere-header": "[$1 वर्णना] मधून",
+ "flow-whatlinkshere-post-summary": "[$1 सारांशा] मधून",
+ "structureddiscussions": "प्रवाह",
+ "flow-special-desc": "हे विशेष पान, प्रवाहाच्या कार्यप्रवाहास किंवा, जर यूयूआयडी (UUID) दिली असल्यास, प्रवाह टपालनास पुनर्निर्देशित करते.",
+ "flow-special-type": "प्रकार",
+ "flow-special-type-post": "टपालन",
+ "flow-special-type-workflow": "कार्यप्रवाह",
+ "flow-special-uuid": "यूयूआयडी (UUID)",
+ "flow-special-invalid-uuid": "या प्रकाराशी व यूयूआयडीशी (UUID) साधर्म्य असलेला आशय सापडला नाही.",
+ "flow-special-enableflow-legend": "नविन पानावर प्रवाह सक्षम करा",
+ "flow-special-enableflow-page": "प्रवाह सक्षम करण्यासाठीचे पान",
+ "flow-special-enableflow-header": "प्रवाह फलकाचे प्राथमिक वर्णन (विकिमजकूर)",
+ "flow-special-enableflow-board-already-exists": "[[$1]] वर पूर्वीच एक प्रवाह फलक आहे.",
+ "flow-special-enableflow-invalid-title": "अवैध पान शीर्षक टाकल्या गेले.",
+ "flow-special-enableflow-board-creation-not-allowed": "आपणस [[:$1]]वर प्रवाह फलक निर्माण करण्याची परवानगी नाही.",
+ "flow-special-enableflow-confirmation": "आपण [[$1]] वर यश्स्वीरित्या एक प्रवाह फलक निर्माण केला आहे.",
+ "flow-post-undo-hide": "लपविणे काढा",
+ "flow-post-undo-delete": "वगळणे काढा",
+ "flow-post-undo-suppress": "दमन काढा",
+ "flow-topic-undo-hide": "लपविणे काढा",
+ "flow-topic-undo-delete": "वगळणे काढा",
+ "flow-topic-undo-suppress": "दमन काढा",
+ "flow-edited": "संपादित",
+ "flow-edited-by": "$1 द्वारे संपादित",
+ "flow-previous-diff": "← मागील संपादन",
+ "flow-next-diff": "पुढील संपादन →",
+ "flow-undo": "उलटवा",
+ "flow-undo-latest-revision": "सध्याची आवृत्ती",
+ "flow-undo-your-text": "तुमचा मजकूर",
+ "flow-undo-edit-header": "वर्णनाचे संपादन करीत आहे",
+ "flow-undo-edit-topic-summary": "विषय सारांशाचे संपादन करीत आहे",
+ "flow-undo-edit-post": "टपालनाचेसंपादन करीत आहे",
+ "flow-undo-edit-failure": "विसंवादी आंतरवर्ती संपादने झाल्यामुळे आपण हे संपादन परतवू शकत नाही.",
+ "group-flow-bot": "प्रवाह सांगकामे",
+ "group-flow-bot-member": "प्रवाह सांगकाम्या",
+ "grouppage-flow-bot": "Project:प्रवाह सांगकामे",
+ "flow-ve-mention-context-item-label": "उल्लेख करा",
+ "flow-ve-mention-inspector-title": "उल्लेख करा",
+ "flow-ve-mention-inspector-remove-label": "हटवा",
+ "flow-ve-mention-placeholder": "सदस्य नाव",
+ "flow-ve-mention-tool-title": "सदस्याचा उल्लेख करा",
+ "flow-ve-mention-template-title": "प्रवाहौल्लेख",
+ "flow-ve-mention-inspector-invalid-user": "\"$1\" हे सदस्यनाव नोंदविलेले नाही.",
+ "flow-wikitext-editor-help": "विकिमजकूर$1.",
+ "flow-wikitext-editor-help-and-preview": "विकिमजकूर $1 व आपण कधीही $2 करु शकता.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|मार्कअप वापरते]]",
+ "flow-wikitext-editor-help-preview-the-result": "निकालाची झलक बघा",
+ "flow-wikitext-switch-editor-tooltip": "दृश्यसंपादकाकडे बदलवा",
+ "flow-ve-switch-editor-tool-title": "विकिमजकूर संपादकाकडे चला",
+ "flow-mark-revision-patrolled-link-text": "या पानावर गस्त झाल्याची खूण करा",
+ "flow-mark-revision-patrolled-link-title": "या पानावर गस्त झाल्याची खूण करा",
+ "flow-mark-diff-patrolled-link-text": "टेहळणी केल्याची खूण करा",
+ "flow-mark-diff-patrolled-link-title": "टेहळणी केल्याची खूण करा",
+ "flow-talk-page-beta-feature-message": "सदस्य चर्चापानावर प्रवाह",
+ "flow-notification-link-text-enabled-on-talkpage": "सदस्य चर्चा पान{{GENDER:|बघा}}",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|आपण}}खात्री करता?",
+ "flow-dialog-cancelconfirm-message": "जतन करण्याआधीच आपणास वगळावयाचे आहे काय?",
+ "flow-dialog-cancelconfirm-keep": "संपादन सुरु ठेवा",
+ "flow-dialog-cancelconfirm-discard": "बदल हटवा",
+ "flow-optin-archive-wikitext": "चर्चाफलकास जागा करुन देण्यास विकिमजकूर असणारे पान हलवा."
}
diff --git a/Flow/i18n/ms.json b/Flow/i18n/ms.json
index 2178940f..9ab6ee7b 100644
--- a/Flow/i18n/ms.json
+++ b/Flow/i18n/ms.json
@@ -41,9 +41,6 @@
"flow-moderation-confirmation-suppress-topic": "Topik ini telah disekat.",
"flow-moderation-confirmation-delete-topic": "Tred ini telah dihapuskan.",
"flow-moderation-confirmation-hide-topic": "Tred ini telah disembunyikan.",
- "flow-topic-collapsed-one-line": "Paparan kecil",
- "flow-topic-collapsed-full": "Paparan terlipat",
- "flow-topic-complete": "Paparan penuh",
"flow-topic-html-title": "$1 di $2",
"flow-importer-wt-converted-template": "Laman perbincangan Wikiteks ditukarkan ke Flow",
"flow-importer-wt-converted-archive-template": "Arkib untuk laman perbincangan wikiteks yang ditukarkan",
diff --git a/Flow/i18n/mwl.json b/Flow/i18n/mwl.json
new file mode 100644
index 00000000..f6b0fda7
--- /dev/null
+++ b/Flow/i18n/mwl.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "MokaAkashiyaPT"
+ ]
+ },
+ "flow-newtopic-save": "Poner un nuobo cacho",
+ "flow-post-action-unhide-post": "Amostrar",
+ "flow-topic-action-watchlist": "Páiginas begiadas",
+ "echo-category-title-flow-discussion": "Cumbersa de l Flow",
+ "echo-pref-tooltip-flow-discussion": "Abisar-me subre la atebidade ne ls tópicos ó nas páiginas que stou a seguir.",
+ "flow-moderation-confirm-unhide-post": "Amostrar",
+ "flow-moderation-confirm-unhide-topic": "Amostrar",
+ "flow-terms-of-use-edit": "Al grabar las sues altaraçones, cuncorda culas cundiçones de outelizaçon desta wiki.",
+ "structureddiscussions": "Flow",
+ "flow-ve-mention-inspector-title": "Mençon"
+}
diff --git a/Flow/i18n/my.json b/Flow/i18n/my.json
index b910cee2..0c88f8ca 100644
--- a/Flow/i18n/my.json
+++ b/Flow/i18n/my.json
@@ -1,8 +1,11 @@
{
"@metadata": {
"authors": [
- "Sanlinnaing"
+ "Sanlinnaing",
+ "Ninjastrikers"
]
},
- "flow-edited-by": "$1 က ပြင်ထားသည်။"
+ "notification-header-flow-enabled-on-talkpage": "<strong>{{GENDER:$2|သင်၏}} ဆွေးနွေးချက်စာမျက်နှာ</strong>အတွက် ဆွေးနွေးမှုစနစ်အသစ် ရနိုင်ပါပြီ",
+ "flow-edited-by": "$1 က ပြင်ထားသည်။",
+ "flow-notification-link-text-enabled-on-talkpage": "အသုံးပြုသူ ဆွေးနွေးချက် စာမျက်နှာကို {{GENDER:|ကြည့်ရန်}}"
}
diff --git a/Flow/i18n/nan.json b/Flow/i18n/nan.json
new file mode 100644
index 00000000..108003a6
--- /dev/null
+++ b/Flow/i18n/nan.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "唐吉訶德的侍從"
+ ]
+ },
+ "flow-post-action-edit-post-submit": "Pó-chûn siu-kái"
+}
diff --git a/Flow/i18n/nap.json b/Flow/i18n/nap.json
index aed7f44f..233203fb 100644
--- a/Flow/i18n/nap.json
+++ b/Flow/i18n/nap.json
@@ -5,17 +5,251 @@
"C.R."
]
},
+ "enablestructureddiscussions": "Appiccia 'o Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Fernisce}} 'e cuntrullà attività nuova nocpp'a \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Vedite ca}} nun state cchiù a cuntrullà 'a paggena \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Chisto nun cagnasse ogne argomento ca {{GENDER:$3|state}} a secutà. {{GENDER:$3|Putite}} miettere [$2 sta paggena] dint'a ll'elenco 'e paggen cuntrullate int'a ogne mumento.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Lèva}} st'argomento 'a ll'elenco 'e cuntrullate",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Vedite ca}} nun state cchiù a cuntrullà \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Vuje}} putite cuntrullà [$2 stu tema] quanno vulite.",
+ "flow-desc": "Sistema 'e Gistione 'e Flusso 'e Fatica",
+ "flow-talk-taken-over-comment": "/* Sta paggena s'è scagnata int'a na bacheca 'e discussione Flow */",
+ "log-name-flow": "Riggistro 'attività Flow",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|scangellaje}} na [$4 mmasciata] 'o \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|scancellaje}} na mmasciata ncopp'a nu tema 'e [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|arrepigliaje}} nu [$4 mmasciate] 'o \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|arrepigliaje}} na mmasciata ncopp'a n'argomento 'e [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|luvaje}} nu [$4 mmasciate] 'o \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|luvaje}} na mmasciata ncopp'a n'argomento 'e [[$3]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|scangellaje}} na [$4 mmasciata] 'o \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|scancellaje}} na mmasciata ncopp'a n'argomento 'e [[$3]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|scancellaje}} l'argomento \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|scancellaje}} n'argomento 'e [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|arrepigliaje}} l'argomento \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|arrepigliaje}} n'argomento 'e [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|luvaje}} l'argomento \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|luvaje}} n'argomento 'e [[$3]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|scancellaje}} l'argomento \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|scancellaje}} n'argomento 'e [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|nzegnaje}} 'o topic \"[[$3|$5]]\" comm'a risolto ncopp'a [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|nzegnaje}} n'argomento comme fosse lésto [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|riarapette}} topic \"[[$3|$5]]\" ncopp'a [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|arapette}} n'argomento ncopp'a [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] ncopp'a [[$3]] fuje mpurtato 'a LiquidThreads a Flow",
+ "flow-user-moderated": "Utente moderato",
+ "flow-board-header-browse-topics-link": "Circa argomenti",
+ "flow-board-header": "Ncopp'a sta bacheca",
+ "flow-board-description-can-not-edit": "Nun cagnabbele",
+ "flow-board-collapse-description": "Annascunne descriziona",
+ "flow-board-expand-description": "Ffà veré descriziona",
+ "flow-topic-collapse-siderail": "LIegge a larghezza chiena",
+ "flow-topic-expand-siderail": "Liegge a larghezza fissa",
+ "flow-edit-header-link": "Cagna 'a descriziona",
+ "flow-post-moderated-toggle-hide-show": "Fà vedè 'o commento {{GENDER:$1|annascunnuto}} 'a $2",
+ "flow-post-moderated-toggle-delete-show": "Fà vedè 'o commento {{GENDER:$1|scancellato}} 'a $2",
+ "flow-post-moderated-toggle-suppress-show": "Fà vedè 'o commento {{GENDER:$1|luvato}} 'a $2",
+ "flow-post-moderated-toggle-hide-hide": "Annascunne 'o commento {{GENDER:$1|annascunnuto}} 'a $2",
+ "flow-post-moderated-toggle-delete-hide": "Annascunne 'o commento {{GENDER:$1|scancellato}} 'a $2",
+ "flow-post-moderated-toggle-suppress-hide": "Annascune 'o commento {{GENDER:$1|luvato}} 'a $2",
+ "flow-topic-moderated-reason-prefix": "Mutivo:",
+ "flow-hide-post-content": "Stu commento è stato {{GENDER:$1|annascunnuto}} 'a $1 ([$2 cronologgia])",
+ "flow-hide-title-content": "St'argomento è stato {{GENDER:$1|annascunnuto}} 'a $1",
+ "flow-hide-header-content": "{{GENDER:$1|Annascunnuto}} 'a $2",
+ "flow-delete-post-content": "Stu commento è stato {{GENDER:$1|scancellato}} 'a $1 ([$2 cronologgia])",
+ "flow-delete-title-content": "St'argomento è stato {{GENDER:$1|scancellato}} 'a $1",
+ "flow-delete-header-content": "{{GENDER:$1|Scancellato}} 'a $2",
+ "flow-suppress-post-content": "Stu commento è stato {{GENDER:$1|luvato}} 'a $1 ([$2 cronologgia])",
+ "flow-suppress-title-content": "St'argomento è stato {{GENDER:$1|luvato}} 'a $1",
+ "flow-suppress-header-content": "{{GENDER:$1|Luvato}} 'a $2",
+ "flow-suppress-usertext": "<em>Nomme utente luvato</em>",
+ "flow-post-actions": "Aziune",
+ "flow-topic-actions": "Aziune",
+ "flow-cancel": "Scancella",
+ "flow-skip-summary": "Zompa 'o riassunto",
+ "flow-edit-summary-placeholder": "Descrive ampress'ampress l'asciuta 'e sta chiàcchiera",
+ "flow-summary-authored": "Riassunto 'e $1",
+ "flow-summary-edited": "Sintesi {{GENDER:$1|cagnata}} ll'urdema vota 'e $1",
"flow-show-change": "Vere 'e cagnamiente",
+ "flow-last-modified-by": "Ùrdema {{GENDER:$1|modifica}} 'e $1",
+ "flow-stub-post-content": "<em>A causa 'e n'errore tecnico, sta mmasciata nun se pò arrepiglià.</em>",
+ "flow-newtopic-title-placeholder": "Argomento nuovo",
"flow-newtopic-content-placeholder": "Scrivite na mmasciata nova a \"$1\"",
+ "flow-newtopic-header": "Azzecca n'argomento nuovo",
+ "flow-newtopic-save": "Azzecca argomento",
+ "flow-newtopic-save-anonymously": "Azzecca argomento anonimamente",
+ "flow-newtopic-start-placeholder": "Accummencia n'argomento nuovo",
+ "flow-newtopic-first-heading": "Accummencia n'argomento nuovo ncopp'a $1",
+ "flow-summarize-topic-placeholder": "Fà nu riepilego 'e sta chiacchiera",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Commento}} ncopp'a \"$2\"",
+ "flow-reply-topic-title-placeholder": "Respunne a \"$1\"",
+ "flow-reply-link": "{{GENDER:$1|Respunne}}",
+ "flow-reply-link-anonymously": "Rispunne anonimamente",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Ringrazia}}}}",
+ "flow-thank-link-title": "{{GENDER:$1|Ringrazia}} pubbrecamente {{GENDER:$2|l'autore|l'autrice|l'autore/trice}}",
+ "flow-history-action-suppress-post": "sopprime",
+ "flow-history-action-delete-post": "scancèlla",
+ "flow-history-action-hide-post": "annascunne",
+ "flow-history-action-unsuppress-post": "annulla soppressione",
+ "flow-history-action-undelete-post": "arrepiglia",
+ "flow-history-action-unhide-post": "tuorna a fà vedè",
+ "flow-history-action-restore-post": "arrepiglia",
+ "flow-history-action-lock-topic": "arrisolve",
+ "flow-history-action-unlock-topic": "arape n'ata vota",
+ "flow-post-edited": "Post {{GENDER:$1|cagnàto}} 'a $1 $2",
+ "flow-post-action-view": "Permalink",
"flow-post-action-post-history": "Cronologgia",
+ "flow-post-action-suppress-post": "Supprime",
+ "flow-post-action-delete-post": "Scancèlla",
+ "flow-post-action-hide-post": "Annascunne",
"flow-post-action-edit-post": "Càgna",
+ "flow-post-action-edit-post-submit": "Sarva 'e cagnamiénte",
+ "flow-post-action-edit-post-submit-anonymously": "Sarva 'a modifica anonimamente",
+ "flow-post-action-unsuppress-post": "annulla suppresiona",
+ "flow-post-action-undelete-post": "Arrepiglia",
+ "flow-post-action-unhide-post": "Tuorna a fà vedè",
+ "flow-post-action-restore-post": "Arrepiglia",
+ "flow-post-action-undo-moderation": "Annulla",
+ "flow-topic-action-view": "Permalink",
+ "flow-topic-action-watchlist": "Paggene cuntrullate",
+ "flow-topic-action-edit-title": "Cagna titolo",
+ "flow-topic-action-history": "Cronologgia",
+ "flow-topic-action-hide-topic": "Annascunne l'argomento",
+ "flow-topic-action-delete-topic": "Scancella argomento",
+ "flow-topic-action-lock-topic": "Nzegna comme fosse risolto",
+ "flow-topic-action-unlock-topic": "Arape n'ata vota l'argomento",
+ "flow-topic-action-summarize-topic": "Fà nu riepilego",
+ "flow-topic-action-resummarize-topic": "Cagna 'o riepilego 'e ll'argomento",
+ "flow-topic-action-update-topic-summary": "Agghiuorna 'a sintesi",
+ "flow-topic-action-suppress-topic": "Sopprime l'argomento",
+ "flow-topic-action-unhide-topic": "Fà vedè l'argomento",
+ "flow-topic-action-undelete-topic": "Arrepiglia st'argomento",
+ "flow-topic-action-unsuppress-topic": "Annulla suppressione 'e ll'argomento",
+ "flow-topic-action-restore-topic": "Arrepiglia l'argomento",
+ "flow-topic-action-undo-moderation": "Annulla",
"flow-topic-notification-subscribe-title": "Chist'argomento è stat'azzeccato dint'a l'elenco 'e paggene cuntrullate {{GENDER:$1|vuoste}}.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Ve facite}} ricevere 'e notifche pe' tuttuquante attività ncopp'a st'argomento.",
"flow-board-notification-subscribe-title": "Mo' te sì {{GENDER:$1|scritto|scritta}} dint'a sta bacheca 'e discussione!",
- "flow-error-other": "All'intrasatta s'è verificato n'errore.",
- "flow-error-move": "Rimpizzanno na bacheca 'e discussione ca nun è cchiù supportata.",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Te fosse mannata}} na notifica quanno n'argomento sarrà criato ncopp'a sta bacheca.",
+ "flow-topic-action-watchlist-add": "Fatte 'a suscrizziona a st'argomento",
+ "flow-topic-action-watchlist-remove": "Cancella l'iscriziona",
+ "flow-error-allowcreation-no-usedb": "L'attivaziona d' 'a funziona Flow ncopp'a na paggena specifica addimannasse ca <var>$wgContentHandlerUseDB</var> fosse overo: <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "'A paggena esiste già 'n destinazione, picciò na bacheca Flow nun se pò mòvere lànn.",
+ "flow-error-allowcreation-flow-create-board": "L'utente nun téne 'autorizzazione \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "A 'o mumento nun putite partercipà. Pruvate a trasì.",
+ "flow-error-can-not-edit-logged-in": "A 'o mumento nun putite partecipà, pecché nun tenite 'e deritte richieste.",
+ "flow-error-http": "N'errore cumparette pe' tramente ca se steva a cuntattà 'o server.",
+ "flow-error-external": "N'errore cumparette. 'A mmasciata 'errore ricevuta è: $1",
+ "flow-error-topic-is-locked": "St'argomento fosse già risolto, picciò nun se pò ffà attività cchiù annanze.",
+ "flow-error-lock-moderated-post": "Nun putite nzegnà comme fosse risolta na mmasciata moderata.",
+ "flow-error-missing-content": "'O post nun tene cuntenute. Nu minimo 'e cuntenuto servesse pe' puté astipà 'o post.",
+ "flow-error-missing-summary": "Avit'a nzertà nu riassunto.",
+ "flow-error-missing-title": "L'argomento nun tene titolo. Servesse nu titolo pe' puté astipà l'argomento.",
+ "flow-error-parsoid-failure": "Nun se pò trasferì 'o cuntenuto: errore a cuntattà 'o server pe' puté scagnà wikitesto e HTML. Cuntrullate 'a connessione vosta a internet o tentate cchiù tarde si 'o prublema cuntinuasse. Si st'errore ve cuntinuasse a cumparì, mannate na segnalaziona.",
+ "flow-error-protected-autoconfirmed-logged-in": "Sta tavola 'e cchiacchiere fosse prutetta. Surtanto auture autucunfermate putessero partecipà. Mutivo: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Sta tavola 'e cchiacchiere fosse prutetta. Surtanto 'utente ca songo autucunfermate putessero partecipà. Mutivo: $1",
+ "flow-error-protected-sysop-logged-in": "Sta tavola 'e cchiacchiere fosse prutetta. Surtanto l'utente ch' 'e deritte ammenistratore putessero partecipà. Mutivo: $1",
+ "flow-error-protected-sysop-logged-out": "Sta tavola 'e cchiacchiere fosse prutetta. Surtanto l'utente trasute ch' 'e deritte ammenistratore putessero partecipà. Mutivo: $1",
+ "flow-error-protected-unknown-reason": "Scanusciuto",
+ "flow-error-missing-replyto": "Nun è stato indicato nu parammetro \"replyTo\" (rispunneA). Stu parammetro fosse richiesto p' 'a funziuna \"reply\" (rispunne).",
+ "flow-error-missing-postId": "Nun s'è dato nu parammetro \"postId\". Stu parammetro ce bùo pe' puté faticà cu na mmasciata.",
+ "flow-error-invalid-postId": "'O parammetro \"postID\" nun è buono. 'A mmasciata indicata ($1) nun è stata truvata.",
+ "flow-error-invalid-moderation-state": "S'è dato nu valore nun valido p' 'o parammetro ('moderationState') a ll'API Flow.",
+ "flow-error-invalid-moderation-reason": "Dàte na motivazione p' 'a moderazione.",
+ "flow-error-not-allowed": "Auturizzaziune nsufficiente pe' puté secutà st'aziona.",
+ "flow-error-not-allowed-hide": "St'argomento è stato annascunnuto.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Nun putite risponnere pecché st'argomento è stato annascunnuto.",
+ "flow-error-not-allowed-delete": "St'argomento è stato scancellato.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Nun putite risponnere pecché st'argomento è stato scancellato.",
+ "flow-error-not-allowed-suppress": "St'argomento è stato scancellato.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Nun putite risponnere pecché st'argomento è stato scancellato.",
+ "flow-error-not-allowed-hide-extract": "St'argomento è stato annascunnuto. 'O riggistro 'occultazione pe' l'argomento fosse disponibbele ccà sotto p' 'o riferimento.",
+ "flow-error-not-allowed-delete-extract": "St'argomento è stato scancellato. 'O riggistro 'e scancellamiente se fà veré ccà abbascio pe' v' 'o purtà comme riferimento.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Nun putite risponnere pecché st'argomento è stato scancellato. 'O riggistro d' 'e cancellaziune pe' stargomento so' disponibbele ccà abbascio p' 'o riferimento.",
+ "flow-error-not-allowed-suppress-extract": "St'argomento è stato scancellato. 'O riggistro scanzellazione pe' l'argomento fosse disponibbele ccà sotto p' 'o riferimento.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Nun putite risponnere pecché st'argomento è stato scancellato. 'O riggistro 'e suppressiune pe' st'argomento se fà vedé ccà abbascio pe' ve purtà nu riferimento.",
+ "flow-error-title-too-long": "'E titole 'e ll'argomento so' lemmitate a $1 {{PLURAL:$1|byte}}.",
+ "flow-error-no-existing-workflow": "Stu flusso 'e fatica nun esiste ancora.",
+ "flow-error-not-a-post": "'O titolo 'e l'argomento nun se pò sarvà comm'a mmasciata.",
+ "flow-error-missing-header-content": "Vuje avit'a cunfermà na descriziona.",
+ "flow-error-missing-prev-revision-identifier": "L'identificatore d' 'a verziona 'e primma è mancante.",
+ "flow-error-prev-revision-mismatch": "N'at'utente ave cagnata sta mmasciata nu poch' 'e secunde fa. Site {{GENDER:$3|sicuro|sicura}} 'e vulé scrivere stu cagnamiento pe' coppa?",
+ "flow-error-prev-revision-does-not-exist": "Nun se po' truvà 'a verzion' 'e primma.",
+ "flow-error-core-topic-deletion": "Pe' pute scancellà n'argomento, ausate 'o menu... ncopp' 'a bacheca Flow o ncopp' 'a [$1 paggena 'e ll'argomento]. Nun ghì a visità direttamente action=delete pe' l'argomento.",
+ "flow-error-default": "N'errore è cumparuto.",
+ "flow-error-invalid-input": "È stato fornito nu valore p' 'a carreca 'e cuntenute Flow invalido.",
+ "flow-error-invalid-title": "S'è fornito nu titolo 'e paggena invalido.",
+ "flow-error-fail-load-history": "È ghiuto malamente a carrecà 'a cronologgia.",
+ "flow-error-missing-revision": "Nun s'è pututa truvà 'a verziona p' 'a carreca 'e cuntenute Flow.",
+ "flow-error-fail-commit": "Nun se pò sarvà 'o cuntenuto d' 'o flusso.",
+ "flow-error-insufficient-permission": "Ll'autorizzaziune nun abbastano pe' puté trasì a 'o cuntenuto.",
+ "flow-error-revision-comparison": "'E differenze se ponno fà vedé surtanto pe' dduje verziune d' 'a stessa mmasciata.",
+ "flow-error-missing-topic-title": "Nun se pò truvà nu titolo 'e ll'argomento pe' nu flusso 'e fatica 'e mò.",
+ "flow-error-missing-metadata": "Nun se ponno truvà 'e metadate ca servessero pe' sta verziona.",
+ "flow-error-fail-load-data": "Nun se ponno carrecà 'e date addimannate.",
+ "flow-error-invalid-workflow": "nun se ò truvà 'o flusso 'e fatica addimannato.",
+ "flow-error-process-data": "S'è verificato n'errore pe' tramente ca se faceva elaborazione d' 'e date d' 'a richiesta vosta.",
+ "flow-error-process-wikitext": "N'errore è cumparuto pe' tramente ca se faceva 'o prucesso 'e scagnà HTML/wikitesto.",
+ "flow-error-no-index": "È guastato a tràuv n'indice pe' puté secutà 'a ricerca 'e date.",
+ "flow-error-no-render": "L'aziona specifica nun s'è ricanusciuta.",
+ "flow-error-no-commit": "L'aziona specifica nun se puteva sarvà.",
+ "flow-error-content-too-long": "'E cuntenute songo luonghe assaje. Sti cuntenute aropp'a se spannere fossero lémmetate a $1 {{PLURAL:$1|byte}}.",
+ "flow-error-move-topic": "'O spustà na paggena 'argomento p' 'o mumento nun è suppurtato.",
+ "flow-error-invalid-topic-uuid-title": "Titulo malamente",
+ "flow-error-invalid-topic-uuid": "'A richiesta d' 'o titolo 'e paggena nun era valida. 'E paggene c' 'o Topic 'e namespace songo criate automaticamente p' 'o Flow.",
+ "flow-error-unknown-workflow-id-title": "Argomento scanusciuto",
+ "flow-error-unknown-workflow-id": "L'argomento addimannato nun esiste.",
+ "flow-error-search": "Nun putimmo cumpretà 'a ricerca d' 'a vuosta pe' nu probblema temporaneo. Pe' piacere pruvate n'ata vota cchiù tarde.",
+ "flow-error-invalid-undelete": "'A voce nun se putess'arrepiglià pecché mo mò nce stesse na discussione ncopp'a chisto.",
"flow-edit-header-placeholder": "Descrive sta bacheca 'e discussione",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|rispunnette}} ncopp'a '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e $5 {{PLURAL:$6|ato|ati}} {{GENDER:$1|rispunnettero}} ncopp'a '''$3'''.",
+ "flow-edit-header-submit": "Astipa descriziona",
+ "flow-edit-header-submit-anonymously": "Astipa descriziona anonimamente",
+ "flow-edit-title-submit": "Cagna 'o titolo",
+ "flow-edit-title-submit-anonymously": "Cagna 'o titolo anonimamente",
+ "flow-edit-post-submit": "Manna 'e cagnamiente",
+ "flow-edit-post-submit-anonymously": "Sarva 'e modifiche anonimamente",
+ "flow-rev-message-edit-post": "$1 {{GENDER:$2|cagnaje}} nu [$3 cummento] ncopp'a \"$4\".",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Cagnaje}} na mmasciata",
+ "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|facette 'e cummente}}] ncopp'a \"$4\" (<em>$5</em>).",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|cummento|cummente}}</strong> {{PLURAL:$1|è stato azzeccato|so' state azzeccate}}.",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|criaje}} l'argomento \"[$3 $4]\"",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Criaje}} n'argomento nuovo nuovo",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|cagnaje}} 'o titolo 'e ll'argomento 'e \"$5\" a \"[$3 $4]\"",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|criaje}} 'a descriziona",
+ "flow-rev-message-edit-header": "$1 {{GENDER:$2|cagnaje}} 'a descriziona",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|criaje}} 'o riassunto 'e ll'argomento $3",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|cagnaje}} 'o riassuonto 'e ll'argomento $3",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|annascunnette}} nu [$4 cummento] ncopp'a \"$6\" (<em>$5</em>).",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|scancellaje}} nu [$4 cumment] ncopp'a \"$6\" (<em>$5</em>)",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2|luvaje}} nu [$4 cummento] ncopp'a \"$6\" (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|arrepigliaje}} nu [$4 cummento] ncopp'a \"$6\" (<em>$5</em>).",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|annascunnette}} ll' [$4 argomento] \"$6\" (<em>$5</em>).",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|scancellaje}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|luvaje}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|nzegnaje}} ll'[$4 argomento] \"$6\" comme fosse risolto (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "nzegnato comme fosse risolto",
+ "flow-rev-message-restore-topic-reason": "araputo n'ata vota",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|arrepigliaje}} [$4 l'argomento] \"$6\" (<em>$5</em>).",
+ "flow-rc-topic-of-board": "$1 ncopp'a $2",
+ "flow-board-history": "Cronologia 'e \"$1\"",
+ "flow-board-history-empty": "Sta bacheca mò mò nun tene cronologgia.",
+ "flow-topic-history": "Cronologia 'e ll'argomento \"$1\"",
+ "flow-post-history": "Cronologgia d' 'e \"cummente 'e {{GENDER:$2|$2}}\"",
+ "flow-history-last4": "Ùrdeme quatt'ore",
+ "flow-history-day": "Ogge",
+ "flow-history-week": "Urdema semmana",
+ "flow-history-pages-topic": "Cumpare ncopp' 'a [$1 bacheca \"$2\"]",
+ "flow-history-pages-post": "Cumpare ncopp'a [$1 $2]",
+ "flow-topic-comments": "{{PLURAL:$1|Nu cummento|$1 cummente|0={{GENDER:$2|Facite pe' primma}} a ffà nu cumment!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Fà veré cummento|Fà veré 'e cummente}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Annascunne 'o cummento|Annascunne 'e cummente}}",
+ "flow-comment-restored": "Cummento arrepigliato",
+ "flow-comment-deleted": "Cummento scancellato",
+ "flow-comment-hidden": "Cummento annascunnuto",
+ "flow-comment-moderated": "Cummento moderato",
+ "flow-last-modified": "Ùrdemo cagnamento $1",
+ "flow-workflow": "flusso 'e fatica",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|rispunnette}} ncopp'a <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e $5 {{PLURAL:$6|ato|ati}} {{GENDER:$1|rispunnettero}} ncopp'a <strong>$3</strong>.",
"flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|criaje}} nu tema nuovo ncopp'a '''$3'''.",
"flow-notification-reply-email-subject": "$2 ncopp'a $3",
"flow-topic-first-heading": "Chiàcchiera ncopp'â $1"
diff --git a/Flow/i18n/nb.json b/Flow/i18n/nb.json
index 6db60740..58ea330f 100644
--- a/Flow/i18n/nb.json
+++ b/Flow/i18n/nb.json
@@ -5,27 +5,53 @@
"Jeblad",
"Laaknor",
"Kingu",
- "Tarjeimo"
+ "Tarjeimo",
+ "Nnemo",
+ "Macofe",
+ "Cocu",
+ "Kjetil r",
+ "Jon Harald Søby"
]
},
- "enableflow": "Aktiver Flow",
- "flow-desc": "Styringssystem for arbeidsflyt",
- "flow-talk-taken-over-comment": "/* Denne siden har blitt konvertert til en Flow-diskusjonsside */",
+ "enablestructureddiscussions": "Aktiver Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Slutt}} å følge med på ny aktivitet på «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Du}} følger ikke lenger siden «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Dette vil ikke påvirke individuelle saker {{GENDER:$3|du}} følger. Du kan overvåke [$2 denne siden] når som helst.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Slutt}} å overvåke dette emnet",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Du}} overvåker ikke lenger «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Du}} kan overvåke [$2 dette emnet] når som helst.",
+ "flow-desc": "Diskusjonssystem",
+ "flow-talk-taken-over-comment": "/* Denne siden har blitt konvertert til en Flow-tavle */",
"log-name-flow": "Aktivitetslogg for Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|slettet}} et [$4 innlegg] på «[[$3|$5]]» på [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|slettet}} en post i et emne på [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|gjenopprettet}} et [$4 innlegg] på «[[$3|$5]]» på [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|gjenopprettet}} en post i et emne på [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|sensurerte}} et [$4 innlegg] på «[[$3|$5]]» på [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|undertrykte}} en post i et emne på [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|slettet}} et [$4 innlegg] på «[[$3|$5]]» på [[$6]]",
- "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|slettet}} innlegget «[[$3|$5]]» på [[$6]]",
- "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|gjenopprettet}} innlegget «[[$3|$5]]» på [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|sensurerte}} innlegget «[[$3|$5]]» på [[$6]]",
- "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|slettet}} innlegget «[[$3|$5]]» på [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|slettet}} en post i et emne på [[$3]]",
+ "logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|slettet}} saken «[[$3|$5]]» på [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|slettet}} et emne på [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|gjenopprettet}} saken «[[$3|$5]]» på [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|gjenopprettet}} et emne på [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|sensurerte}} saken «[[$3|$5]]» på [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|undertrykte}} et emne på [[$3]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|slettet}} saken «[[$3|$5]]» på [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|slettet}} et emne på [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|merket}} saken «[[$3|$5]]» som løst på [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|merket}} et emne som løst på [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|gjenåpnet}} saken «[[$3|$5]]» på [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|gjenåpnet}} et emne på [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] på [[$3]] ble importert fra LiquidThreads til Flow",
"flow-user-moderated": "Moderert bruker",
- "flow-board-header-browse-topics-link": "Bla gjennom diskusjoner",
- "flow-board-header": "Om denne diskusjonen",
+ "flow-board-header-browse-topics-link": "Bla gjennom saker",
+ "flow-board-header": "Om denne tavlen",
+ "flow-board-description-can-not-edit": "Ikke redigerbar",
"flow-board-collapse-description": "Skjul beskrivelse",
"flow-board-expand-description": "Vis beskrivelse",
+ "flow-topic-collapse-siderail": "Les i full bredde",
+ "flow-topic-expand-siderail": "Les med fast bredde",
"flow-edit-header-link": "Rediger beskrivelse",
"flow-post-moderated-toggle-hide-show": "Vis kommentar {{GENDER:$1|skjult}} av $2",
"flow-post-moderated-toggle-delete-show": "Vis kommentar {{GENDER:$1|slettet}} av $2",
@@ -35,45 +61,49 @@
"flow-post-moderated-toggle-suppress-hide": "Skjul kommentar {{GENDER:$1|sensurert}} av $2",
"flow-topic-moderated-reason-prefix": "Begrunnelse:",
"flow-hide-post-content": "Denne kommentaren ble {{GENDER:$1|skjult}} av $1 ([$2 historikk])",
- "flow-hide-title-content": "Denne diskusjonen ble {{GENDER:$1|skjult}} av $1",
+ "flow-hide-title-content": "Denne saken ble {{GENDER:$1|skjult}} av $1",
"flow-hide-header-content": "{{GENDER:$1|Skjult}} av $2",
"flow-delete-post-content": "Denne kommentaren ble {{GENDER:$1|slettet}} av $1 ([$2 historikk])",
- "flow-delete-title-content": "Denne diskusjonen ble {{GENDER:$1|slettet}} av $1",
+ "flow-delete-title-content": "Denne saken ble {{GENDER:$1|slettet}} av $1",
"flow-delete-header-content": "{{GENDER:$1|Slettet}} av $2",
"flow-suppress-post-content": "Denne kommentaren ble {{GENDER:$1|sensurert}} av $1 ([$2 historikk])",
- "flow-suppress-title-content": "Denne diskusjonen ble {{GENDER:$1|dempet}} av $1",
+ "flow-suppress-title-content": "Denne saken ble {{GENDER:$1|sensurert}} av $1",
"flow-suppress-header-content": "{{GENDER:$1|Sensurert}} av $2",
"flow-suppress-usertext": "<em>Brukernavn sensurert</em>",
"flow-post-actions": "Handlinger",
"flow-topic-actions": "Handlinger",
"flow-cancel": "Avbryt",
- "flow-skip-summary": "Hopp over sammendrag",
+ "flow-skip-summary": "Hopp over",
"flow-edit-summary-placeholder": "Gi et kortfattet sammendrag av diskusjonen",
"flow-summary-authored": "Sammendrag av $1",
"flow-summary-edited": "Sammendrag sist {{GENDER:$1|redigert}} av $1",
"flow-show-change": "Vis endringer",
"flow-last-modified-by": "Sist {{GENDER:$1|endret}} av $1",
- "flow-stub-post-content": "«På grunn av en teknisk feil kunne ikke dette innlegget hentes.»",
- "flow-newtopic-title-placeholder": "Ny diskusjon",
+ "flow-stub-post-content": "<em>På grunn av en teknisk feil kunne ikke dette innlegget hentes.</em>",
+ "flow-newtopic-title-placeholder": "Ny sak",
"flow-newtopic-content-placeholder": "Skriv en melding på «$1»",
- "flow-newtopic-header": "Start en ny diskusjon",
- "flow-newtopic-save": "Lagre",
- "flow-newtopic-start-placeholder": "Start en ny diskusjon",
- "flow-newtopic-first-heading": "Start et nytt innlegg på $1",
+ "flow-newtopic-header": "Start en ny sak",
+ "flow-newtopic-save": "Opprett sak",
+ "flow-newtopic-save-anonymously": "Opprett saken anonymt",
+ "flow-newtopic-start-placeholder": "Start en ny sak",
+ "flow-newtopic-first-heading": "Start en ny sak på «$1»",
"flow-summarize-topic-placeholder": "Sammenfatt denne diskusjonen",
- "flow-reply-topic-placeholder": "{{GENDER:$1|Kommentér}} «$2»",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Kommentér}} på «$2»",
"flow-reply-topic-title-placeholder": "Svar på «$1»",
"flow-reply-link": "{{GENDER:$1|Svar}}",
"flow-reply-link-anonymously": "Svar anonymt",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Takk}}}}",
"flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Takk}}}} forfatteren offentlig",
+ "flow-history-action-suppress-post": "sensurer",
"flow-history-action-delete-post": "slett",
"flow-history-action-hide-post": "skjul",
+ "flow-history-action-unsuppress-post": "avsensurer",
"flow-history-action-undelete-post": "gjenopprett",
"flow-history-action-unhide-post": "vis igjen",
"flow-history-action-restore-post": "gjenopprett",
"flow-history-action-lock-topic": "løs",
"flow-history-action-unlock-topic": "gjenåpne",
+ "flow-post-interaction-separator": "&#32;•&#32;",
"flow-post-edited": "Innlegg {{GENDER:$1|redigert}} av $1 $2",
"flow-post-action-view": "Permanent lenke",
"flow-post-action-post-history": "Historikk",
@@ -82,7 +112,8 @@
"flow-post-action-hide-post": "Skjul",
"flow-post-action-edit-post": "Rediger",
"flow-post-action-edit-post-submit": "Lagre endringer",
- "flow-post-action-unsuppress-post": "Avdemp",
+ "flow-post-action-edit-post-submit-anonymously": "Lagre endringer anonymt",
+ "flow-post-action-unsuppress-post": "Avsensurer",
"flow-post-action-undelete-post": "Gjenopprett",
"flow-post-action-unhide-post": "Vis",
"flow-post-action-restore-post": "Gjenopprett",
@@ -91,55 +122,80 @@
"flow-topic-action-watchlist": "Overvåkningsliste",
"flow-topic-action-edit-title": "Rediger overskrift",
"flow-topic-action-history": "Historikk",
- "flow-topic-action-hide-topic": "Skjul diskusjonen",
- "flow-topic-action-delete-topic": "Slett diskusjonen",
+ "flow-topic-action-hide-topic": "Skjul sak",
+ "flow-topic-action-delete-topic": "Slett sak",
"flow-topic-action-lock-topic": "Merk som løst",
- "flow-topic-action-unlock-topic": "Gjenåpne diskusjonen",
+ "flow-topic-action-unlock-topic": "Gjenåpne sak",
"flow-topic-action-summarize-topic": "Sammenfatt",
- "flow-topic-action-resummarize-topic": "Rediger sammendrag av diskusjonen",
+ "flow-topic-action-resummarize-topic": "Rediger sakssammendraget",
"flow-topic-action-update-topic-summary": "Oppdater sammendrag",
- "flow-topic-action-suppress-topic": "Sensurer diskusjonen",
- "flow-topic-action-unhide-topic": "Vis diskusjonen",
- "flow-topic-action-undelete-topic": "Gjenopprett diskusjonen",
- "flow-topic-action-unsuppress-topic": "Ikke sensurer diskusjonen lenger",
- "flow-topic-action-restore-topic": "Gjenopprett diskusjonen",
+ "flow-topic-action-suppress-topic": "Sensurer saken",
+ "flow-topic-action-unhide-topic": "Vis saken",
+ "flow-topic-action-undelete-topic": "Gjenopprett saken",
+ "flow-topic-action-unsuppress-topic": "Avsensurer saken",
+ "flow-topic-action-restore-topic": "Gjenopprett saken",
"flow-topic-action-undo-moderation": "Angre",
- "flow-topic-notification-subscribe-title": "Diskusjonen har blitt lagt til i overvåkningslisten {{GENDER:$1|din}}.",
- "flow-topic-notification-subscribe-description": "{{GENDER:$1|Du}} vil motta varsler for all aktivitet knyttet til denne diskusjonen.",
+ "flow-topic-notification-subscribe-title": "Saken har blitt lagt til i overvåkningslisten {{GENDER:$1|din}}.",
+ "flow-topic-notification-subscribe-description": "{{GENDER:$1|Du}} vil motta varsler for all aktivitet knyttet til denne saken.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Du}} abonnerer nå på denne diskusjonstavlen!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Du}} vil bli varslet når en ny sak startes på denne tavlen.",
+ "flow-topic-action-watchlist-add": "Abonner på denne saken.",
+ "flow-topic-action-watchlist-remove": "Avslutt abonnement",
+ "flow-error-allowcreation-no-usedb": "Å slå på Flow på en spesifikk side forutsetter at <var>$wgContentHandlerUseDB</var> er satt til <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Siden finnes allerede på destinasjonen, så et Flow-tavle kan ikke bli flyttet dit.",
+ "flow-error-allowcreation-flow-create-board": "Brukeren har ikke rettigheten «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Du er for tiden ikke i stand til å delta. Du kan prøve å logge inn.",
+ "flow-error-can-not-edit-logged-in": "Du er for tiden ikke i stand til å delta, fordi du ikke har de nødvendige rettighetene.",
"flow-error-http": "Det oppsto en feil ved kontakt med serveren.",
- "flow-error-other": "Det oppsto en ukjent feil.",
- "flow-error-external": "Det oppsto en feil.<br />Feilmeldingen var: $1",
- "flow-error-external-multi": "Feil oppsto under lagring av meldingen.<br />$1",
+ "flow-error-external": "Det oppsto en feil. Feilmeldingen var: $1",
+ "flow-error-topic-is-locked": "Denne saken er markert som løst, så ytterligere aktivitet er ikke mulig.",
+ "flow-error-lock-moderated-post": "Du kan ikke markere et moderert innlegg som løst.",
"flow-error-missing-content": "Innlegget har ikke noe innhold. Innhold kreves for å lagre et innlegg.",
"flow-error-missing-summary": "Du må fylle inn et sammendrag.",
- "flow-error-missing-title": "Meldingen har ingen overskrift. En overskrift kreves for å lagre en diskusjon.",
+ "flow-error-missing-title": "Saken har ingen overskrift. En overskrift kreves for å lagre en sak.",
"flow-error-parsoid-failure": "Innholdet kunne ikke parseres pga. et Parsord-problem.",
+ "flow-error-protected-autoconfirmed-logged-in": "Denne tavla er beskyttet. Bare autobekreftede brukere kan delta. Årsak: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Denne tavla er beskyttet. Bare innloggede brukere som er autobekreftede kan delta. Årsak: $1",
+ "flow-error-protected-sysop-logged-in": "Denne tavla er beskyttet. Bare brukere med administratorrettigheter kan delta. Årsak: $1",
+ "flow-error-protected-sysop-logged-out": "Denne tavla er beskyttet. Bare innloggede brukere med administratorrettigheter kan delta. Årsak: $1",
+ "flow-error-protected-unknown-reason": "Ukjent",
"flow-error-missing-replyto": "Ingen \"replyTo\"-parameter ble sendt inn. Parameteren er påkrevd for \"reply\"-handlingen.",
- "flow-error-invalid-replyto": "Parameteren \"replyTo\" var ugyldig. Det angitte innlegget ble ikke funnet.",
- "flow-error-delete-failure": "Sletting av dette innlegget feilet.",
- "flow-error-hide-failure": "Skjuling av dette innlegget feilet.",
"flow-error-missing-postId": "Ingen \"postId\"-parameter ble sendt inn. Parameteren er påkrevd for å redigere et innlegg.",
"flow-error-invalid-postId": "Parameteren «postId» var ugyldig. Det angitte innlegget ($1) ble ikke funnet.",
- "flow-error-restore-failure": "Gjenoppretting av dette innlegget feilet.",
"flow-error-invalid-moderation-state": "En ugyldig verdi ble gitt for en parameter ('moderationState') ble gitt til Flow-APIet.",
"flow-error-invalid-moderation-reason": "Vennligst oppgi en grunn for modereringen",
"flow-error-not-allowed": "Manglende rettigheter til å utføre denne handlingen",
- "flow-error-title-too-long": "Diskusjonstitler er begrenset til {{PLURAL:$1|én byte|$1 bytes}}.",
- "flow-error-no-existing-workflow": "Denne arbeidsflyten finnes ikke enda.",
- "flow-error-not-a-post": "Diskusjonstittel kan ikke bli lagret som et innlegg.",
+ "flow-error-not-allowed-hide": "Denne saken har blitt skjult.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Du kan ikke svare fordi denne saken er skjult.",
+ "flow-error-not-allowed-delete": "Denne saken har blitt slettet.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Du kan ikke svare fordi denne saken har blitt slettet.",
+ "flow-error-not-allowed-suppress": "Denne saken har blitt slettet.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Du kan ikke svare fordi denne saken har blitt slettet.",
+ "flow-error-not-allowed-hide-extract": "Denne saken har blitt skjult. Skjulingsloggen for saken vises under til orientering.",
+ "flow-error-not-allowed-delete-extract": "Denne saken har blitt slettet. Slettingsloggen for saken vises under til orientering.",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "Du kan ikke svare fordi denne saken har blitt slettet. Slettingsloggen for saken vises under til orientering.",
+ "flow-error-not-allowed-suppress-extract": "Saken har blitt slettet. Sletteloggen for saken vises under til orientering.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Du kan ikke svare fordi saken har blitt sensurert Loggoppføringen for sensurering av saken er vist nedenfor.",
+ "flow-error-title-too-long": "Sakstitler er begrenset til {{PLURAL:$1|én byte|$1 bytes}}.",
+ "flow-error-no-existing-workflow": "Denne arbeidsflyten finnes ikke ennå.",
+ "flow-error-not-a-post": "Sakstittel kan ikke bli lagret som et innlegg.",
"flow-error-missing-header-content": "Du må fylle inn en beskrivelse.",
"flow-error-missing-prev-revision-identifier": "Foregående revisjons-identifikator mangler.",
"flow-error-prev-revision-mismatch": "En annen bruker redigerte innlegget for et par sekunder siden. Er {{GENDER:$3|du}} sikker på at du ønsker å overskrive de siste endringene?",
"flow-error-prev-revision-does-not-exist": "Kunne ikke finne foregående revisjon.",
+ "flow-error-core-topic-deletion": "For å slette en sak, bruk ...-menyen på Flow-tavlen eller [$1 sakssiden]. Ikke besøk action=delete for diskusjonen direkte.",
"flow-error-default": "En feil oppsto.",
"flow-error-invalid-input": "Ugyldig verdi ble brukt for å laste Flow-innholdet.",
"flow-error-invalid-title": "Ugyldig sidetittel ble brukt.",
+ "flow-error-invalid-parameter": "Manglende eller ugyldig parameter til metodekall",
"flow-error-fail-load-history": "Innholdet i historikken kunne ikke lastes inn.",
"flow-error-missing-revision": "Kunne ikke finne en revisjon for å laste Flow-innholdet.",
"flow-error-fail-commit": "Feilet under lagring av Flow-innholdet.",
"flow-error-insufficient-permission": "Mangelfulle rettigheter for å aksessere innholdet.",
"flow-error-revision-comparison": "Diff-operasjoner kan bare bli gjort mellom revisjoner som tilhører det samme innlegget.",
- "flow-error-missing-topic-title": "Finner ikke diskusjonstittel i gjeldende arbeidsflyt.",
+ "flow-error-missing-topic-title": "Finner ikke sakstittel i gjeldende arbeidsflyt.",
+ "flow-error-missing-metadata": "Kunne ikke finne de nødvendige metadata for denne revisjonen.",
+ "flow-error-different-page": "Flows arbeidsflyt assosieres ikke med denne siden.",
"flow-error-fail-load-data": "Feilet under lasting av forespurte data.",
"flow-error-invalid-workflow": "Kunne ikke finne forespurt arbeidsflyt.",
"flow-error-process-data": "En feil har oppstått under behandling av data i din forespørsel.",
@@ -147,29 +203,43 @@
"flow-error-no-index": "Feilet å finne en indeks for å utføre datasøk.",
"flow-error-no-render": "Handlingen ble ikke gjenkjent",
"flow-error-no-commit": "Handlingen kunne ikke utføres.",
+ "flow-error-content-too-long": "Innholdet er for stort. Etter ekspansjon er innholdet begrenset til {{PLURAL:$1|én byte|$1 bytes}}.",
+ "flow-error-move-topic": "Flytting av en emneside er foreløpig ikke støttet.",
+ "flow-error-invalid-topic-uuid-title": "Ugyldig tittel",
+ "flow-error-invalid-topic-uuid": "Den forespurte siden var ugyldig. Sider i Saks-navnerommet blir automatisk lagd av Flow.",
+ "flow-error-unknown-workflow-id-title": "Ugyldig sak",
+ "flow-error-unknown-workflow-id": "Saken eksisterer ikke.",
+ "flow-error-search": "Søket kunne ikke fullføres på grunn av et midlertidig problem. Vennligst prøv igjen senere.",
+ "flow-error-invalid-undelete": "Artikkelen kunne ikke bli tilbakeført fordi det er en diskusjonstavle på stedet.",
"flow-edit-header-placeholder": "Beskriv denne diskusjonssiden",
"flow-edit-header-submit": "Lagre beskrivelse",
+ "flow-edit-header-submit-anonymously": "Lagre beskrivelse anonymt",
"flow-edit-title-submit": "Endre overskrift",
+ "flow-edit-title-submit-anonymously": "Endre tittel anonymt",
"flow-edit-post-submit": "Send inn endringer",
+ "flow-edit-post-submit-anonymously": "Lagre endringer anonymt",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|redigerte}} en [$3 kommentar] på «$4».",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Redigerte}} et innlegg",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|kommenterte}}] «$4»(<em>$5</em>).",
"flow-rev-message-reply-bundle": "'''$1 {{PLURAL:$1|innlegg}}''' {{PLURAL:$1|ble}} lagt til",
- "flow-rev-message-new-post": "$1 {{GENDER:$2|startet}} diskusjonen «[$3 $4]».",
- "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Opprettet}} et innlegg",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|endret}} diskusjonstittelen fra «$5» til «[$3 $4]».",
+ "flow-rev-message-new-post": "$1 {{GENDER:$2|startet}} saken «[$3 $4]».",
+ "flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Opprettet}} en sak",
+ "flow-rev-message-edit-title": "$1 {{GENDER:$2|endret}} sakstittelen fra «$5» til «[$3 $4]».",
"flow-rev-message-create-header": "$1 {{GENDER:$2|opprettet}} beskrivelsen",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|redigerte}} beskrivelsen",
- "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|opprettet}} diskusjonssammendrag for $3.",
- "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|redigerte}} diskusjonssammendraget for $3.",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|opprettet}} sakssammendrag for $3.",
+ "flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|redigerte}} sakssammendraget for $3.",
"flow-rev-message-hid-post": "$1 {{GENDER:$2|skjulte}} en [$4 kommentar] til «$6» (<em>$5</em>).",
"flow-rev-message-deleted-post": "$1 {{GENDER:$2|slettet}} en [$4 kommentar] til «$6» (<em>$5</em>).",
"flow-rev-message-suppressed-post": "$1 {{GENDER:$2|sensurerte}} en [$4 kommentar] til «$6» (<em>$5</em>).",
"flow-rev-message-restored-post": "$1 {{GENDER:$2|gjenopprettet}} en [$4 kommentar] til «$6» (<em>$5</em>).",
- "flow-rev-message-hid-topic": "$1 {{GENDER:$2|skjulte}} [$4 diskusjonen] «$6» (<em>$5</em>).",
- "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|slettet}} [$4 diskusjonen] «$6» (<em>$5</em>).",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|sensurerte}} [$4 diskusjonen] «$6» (<em>$5</em>).",
- "flow-rev-message-restored-topic": "$1 {{GENDER:$2|gjenopprettet}} [$4 diskusjonen] «$6» (<em>$5</em>).",
+ "flow-rev-message-hid-topic": "$1 {{GENDER:$2|skjulte}} [$4 saken] «$6» (<em>$5</em>).",
+ "flow-rev-message-deleted-topic": "$1 {{GENDER:$2|slettet}} [$4 saken] «$6» (<em>$5</em>).",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|sensurerte}} [$4 saken] «$6» (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|markerte}} [$4 saken] «$6» som løst (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "markert som løst",
+ "flow-rev-message-restore-topic-reason": "gjenåpnet",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|gjenopprettet}} [$4 saken] «$6» (<em>$5</em>).",
"flow-rc-topic-of-board": "$1 på $2",
"flow-board-history": "Historikk for «$1»",
"flow-board-history-empty": "Dette brettet har for øyeblikket ingen historikk.",
@@ -181,92 +251,140 @@
"flow-history-pages-topic": "Forekommer på [$1 «$2»-brettet]",
"flow-history-pages-post": "Forekommer på [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 innlegg|0={{GENDER:$2|Bli den første}} til å kommentere!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Vis kommentar|Vis kommentarer}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Skjul kommentar|Skjul kommentarer}}",
"flow-comment-restored": "Gjenopprettet kommentar",
"flow-comment-deleted": "Slettet kommentar",
"flow-comment-hidden": "Skjult kommentar",
"flow-comment-moderated": "Moderert melding",
"flow-last-modified": "Sist endret for rundt $1",
"flow-workflow": "arbeidsflyt",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|svarte}} på '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 og $5 {{PLURAL:$6|annen|andre}} {{GENDER:$1|svarte}} på '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|svarte}} på <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 og {{PLURAL:$5|en annen|$5 andre|100=99+ andre}} {{GENDER:$1|svarte}} på <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|redigerte}} <span class=\"plainlinks\">[$5 meldingen]</span> din på [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 og $5 {{PLURAL:$6|annen|andre}} {{GENDER:$1|redigerte}} et <span class=\"plainlinks\">[$4 innlegg]</span> under «$2» på «$3».",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|startet}} en ny diskusjon på '''$3'''.",
+ "flow-notification-edit-bundle": "$1 og {{PLURAL:$5|en annen|$5 andre|100=99+ andre}} {{GENDER:$1|redigerte}} et <span class=\"plainlinks\">[$4 innlegg]</span> under «$2» på «$3».",
+ "notification-header-flow-new-topic-v2": "Ny sak skapt på <strong>$3</strong>: <bdi>«<strong>$4</strong>»</bdi>.",
+ "notification-compact-header-flow-new-topic": "«<strong>$1</strong>»",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|En ny sak|$1 nye saker|100=99+ nye saker}} på <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "En sak ble opprettet på <strong>din diskusjonsside</strong>: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|En ny sak|$1 nye saker|100=99+ nye saker}} på <strong>din diskusjonsside</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|svarte}} i «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Ett nytt svar|$1 nye svar|100=99+ nye svar}} i «<strong>$3</strong>».",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|skrev}} et svar på <strong>din diskusjonsside</strong> i «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Ett nytt svar|$1 nye svar|100=99+ nye svar}} på <strong>din diskusjonsside</strong> i «<strong>$3</strong>».",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Ditt}} innlegg i «<strong>$1</strong>» ble redigert.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Ditt}} innlegg i «<strong>$1</strong>» ble redigert flere ganger.",
+ "notification-header-flow-post-edited-user-talk": "Et innlegg i «<strong>$1</strong>» ble redigert på <strong>{{GENDER:$2|din}} diskusjonsside</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Et innlegg på «<strong>$1</strong>» ble redigert flere ganger på <strong>{{GENDER:$2|din}} diskusjonsside</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Saken «<strong>$1</strong>» fikk ny tittel «<strong>$2</strong>».",
+ "notification-header-flow-topic-renamed-user-talk": "Saken «<strong>$1</strong>» fikk ny tittel «<strong>$2</strong>» på <strong>{{GENDER:$3|din}} diskusjonsside</strong>.",
+ "notification-header-flow-summary-edited": "Sammendraget av «<strong>$1</strong>» ble oppdatert",
+ "notification-header-flow-summary-edited-first": "Saken «<strong>$1</strong>» fikk sammendrag.",
+ "notification-bundle-header-flow-summary-edited": "Sammendraget for «<strong>$1</strong>» ble oppdatert flere ganger.",
+ "notification-header-flow-summary-edited-user-talk": "Sammendraget for «<strong>$1</strong>» ble oppdatert på <strong>{{GENDER:$2|din}} diskusjonsside</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Saken «<strong>$1</strong>» fikk sammendrag på <strong>{{GENDER:$2|din}} diskusjonsside</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Sammendraget til «<strong>$1</strong>\" ble oppdartert flere ganger på <strong>{{GENDER:$2|din}} diskusjonsside</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|oppdaterte}} sammendraget på $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|oppdaterte}} sammendraget på $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 og {{PLURAL:$3|en annen|$3 andre|100=99+ andre}} {{GENDER:$1|oppdaterte}} sammendraget på $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|nevnte}} {{GENDER:$4|deg}} på «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|nevnte}} {{GENDER:$4|deg}} i beskrivelsen av <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|nevnte}} {{GENDER:$4|deg}} i «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Nytt diskusjonssystem er aktivert for brukerdiskusjonssiden {{GENDER:$2|din}}",
+ "notification-header-flow-description-edited": "Beskrivelsen av <strong>$1</strong> ble redigert.",
+ "notification-header-flow-description-edited-user-talk": "Beskrivelsen ble redigert på <strong>{{GENDER:$2|din}} brukerdiskusjonsside</strong>.",
+ "notification-bundle-header-flow-description-edited": "Beskrivelsen av <strong>$1</strong> ble redigert flere ganger.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Beskrivelsen ble redigert flere ganger på <strong>{{GENDER:$2|din}} brukerdiskusjonsside</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Vis}} side",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|redigerte}} beskrivelsen for $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|redigerte}} beskrivelsen for $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 og {{PLURAL:$3|én annen|$3 andre|100=99+ andre}} {{GENDER:$1|redigerte}} beskrivelsen for $2",
+ "notification-header-flow-topic-resolved": "Saken «<strong>$1</strong>» ble markert som løst.",
+ "notification-header-flow-topic-reopened": "Saken «<strong>$1</strong>» ble gjenåpnet.",
+ "notification-header-flow-topic-resolved-user-talk": "Saken «<strong>$1</strong>» ble løst på <strong>din diskusjonsside</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Saken «<strong>$1</strong>» ble gjenåpnet på <strong>din diskusjonsside</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Saken «<strong>$2</strong>» ble løst.",
+ "notification-email-batch-body-flow-topic-resolved": "Saken «<strong>$2</strong>» ble løst.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|startet}} en ny sak på <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Én ny sak|$1 nye saker|100=99+ nye diskusjoner}} på <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|endret}} overskriften på <span class=\"plainlinks\">[$2 $3]</span> til «$4» på [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|nevnte}} {{GENDER:$5|deg}} i <span class=\"plainlinks\">[$2 innlegget]</span> {{GENDER:$1|hans|hennes|sitt}} under «$3» på «$4»",
"flow-notification-link-text-view-post": "Vis innlegg",
- "flow-notification-link-text-view-topic": "Vis diskusjon",
+ "flow-notification-link-text-view-topic": "Vis sak",
+ "flow-notification-link-text-view-topics": "Vis saker",
"flow-notification-reply-email-subject": "$2 på $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|svarte}} på «$2» på $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 og $4 {{PLURAL:$5|annen|andre}} {{GENDER:$1|svarte}} på «$2» på $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 og {{PLURAL:$4|én annen|$4 andre|100=99+andre}} {{GENDER:$1|svarte}} på «$2» på $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|nevnte}} {{GENDER:$3|deg}} på $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|nevnte}} {{GENDER:$4|deg}} i innlegget {{GENDER:$1|hans|hennes|sitt}} i «$2» på $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|redigerte}} et innlegg",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|redigerte}} innlegget i «$2» på $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 og $4 {{PLURAL:$5|annen|andre}} {{GENDER:$1|redigerte}} et innlegg i «$2» på $3",
- "flow-notification-rename-email-subject": "$1 {{GENDER:$1|endret navn}} på diskusjonen din",
- "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|endret navn}} på diskusjonen din «$2» på $4 til «$3»",
- "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|opprettet}} en ny diskusjon på $2",
- "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|opprettet}} en ny diskusjon på «$3» med overskriften «$2»",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Informer meg når handlinger relatert til meg skjer i Flow",
+ "flow-notification-edit-email-batch-bundle-body": "$1 og {{PLURAL:$4|én annen|$4 andre|100=99+ andre}} {{GENDER:$1|redigerte}} et innlegg i «$2» på $3",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|endret navn}} saken din",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|endret navn}} saken din «$2» på $4 til «$3»",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|opprettet}} en ny sak på «$2»",
+ "flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|opprettet}} en ny sak på «$3» med overskriften «$2»",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Én ny sak|$1 nye saker|100=99+ nye saker}} på $2",
+ "echo-category-title-flow-discussion": "Flow-diskusjon",
+ "echo-pref-tooltip-flow-discussion": "Varsle meg om aktivitet i emner eller sider jeg følger.",
"flow-link-post": "innlegg",
- "flow-link-topic": "diskusjon",
+ "flow-link-topic": "sak",
"flow-link-history": "historikk",
- "flow-link-post-revision": "innleggsrevisjon",
- "flow-link-topic-revision": "diskusjonsrevisjon",
- "flow-link-header-revision": "versjon av beskrivelsen",
- "flow-link-summary-revision": "sammendrag revisjon",
+ "flow-link-post-revision": "innleggets revisjon",
+ "flow-link-topic-revision": "sakens revisjon",
+ "flow-link-header-revision": "beskrivelsens revisjon",
+ "flow-link-summary-revision": "sammendragets revisjon",
"flow-moderation-title-suppress-post": "Sensurer innlegg?",
"flow-moderation-title-delete-post": "Slett innlegg?",
"flow-moderation-title-hide-post": "Skjul innlegg?",
- "flow-moderation-title-unsuppress-post": "Avdemp innlegg?",
+ "flow-moderation-title-unsuppress-post": "Avsensurer innlegg?",
"flow-moderation-title-undelete-post": "Gjenopprett innlegg?",
"flow-moderation-title-unhide-post": "Vis innlegg?",
"flow-moderation-placeholder-suppress-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du sensurerer dette innlegget.",
"flow-moderation-placeholder-delete-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du sletter dette innlegget.",
"flow-moderation-placeholder-hide-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du skjuler dette innlegget.",
- "flow-moderation-placeholder-unsuppress-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du avdemper dette innlegget.",
+ "flow-moderation-placeholder-unsuppress-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du avsensurerer dette innlegget.",
"flow-moderation-placeholder-undelete-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du gjenoppretter dette innlegget.",
"flow-moderation-placeholder-unhide-post": "Vennligst {{GENDER:$3|forklar}} hvorfor du viser dette innlegget.",
"flow-moderation-confirm-suppress-post": "Sensurer",
"flow-moderation-confirm-delete-post": "Slett",
"flow-moderation-confirm-hide-post": "Skjul",
- "flow-moderation-confirm-unsuppress-post": "Avdemp",
+ "flow-moderation-confirm-unsuppress-post": "Avsensurer",
"flow-moderation-confirm-undelete-post": "Gjenopprett",
"flow-moderation-confirm-unhide-post": "Vis",
"flow-moderation-confirm-suppress-topic": "Sensurer",
"flow-moderation-confirm-delete-topic": "Slett",
"flow-moderation-confirm-hide-topic": "Skjul",
- "flow-moderation-confirm-unsuppress-topic": "Avdemp",
+ "flow-moderation-confirm-unsuppress-topic": "Avsensurer",
"flow-moderation-confirm-undelete-topic": "Gjenopprett",
"flow-moderation-confirm-unhide-topic": "Vis",
- "flow-moderation-confirmation-suppress-post": "Innlegget ble sensurert.\n{{GENDER:$2|Vurder}} å gi $1 tilbakemelding på innlegget.",
- "flow-moderation-confirmation-delete-post": "Sletting av innlegget er fullført.\n{{GENDER:$2|Vurder}} å gi $1 tilbakemelding på innlegget.",
- "flow-moderation-confirmation-hide-post": "Skjuling av innlegget er fullført.\n{{GENDER:$2|Vurder}} å gi $1 tilbakemelding på dette innlegget.",
- "flow-moderation-confirmation-unsuppress-post": "Du fullførte avdemping av ovenstående innlegg.",
- "flow-moderation-confirmation-undelete-post": "Du fullførte gjenoppretting av ovenstående innlegg.",
- "flow-moderation-confirmation-unhide-post": "Du fullførte fremvisning av ovenstående innlegg.",
+ "flow-moderation-confirmation-suppress-post": "Innlegget ble sensurert.\n{{GENDER:$2|Vurder}} om du vil gi $1 tilbakemelding på dette innlegget.",
+ "flow-moderation-confirmation-delete-post": "Innlegget ble slettet.\n{{GENDER:$2|Vurder}} om du vil gi $1 tilbakemelding på dette innlegget.",
+ "flow-moderation-confirmation-hide-post": "Innlegget ble skjult.\n{{GENDER:$2|Vurder}} om du vil gi $1 tilbakemelding på dette innlegget.",
+ "flow-moderation-confirmation-unsuppress-post": "Du har avsensurert ovenstående innlegg.",
+ "flow-moderation-confirmation-undelete-post": "Du har gjenopprettet ovenstående innlegg.",
+ "flow-moderation-confirmation-unhide-post": "Du har fjernet skjuling av ovenstående innlegg.",
"flow-moderation-confirmation-suppress-topic": "Diskusjonen har blitt sensurert.",
"flow-moderation-confirmation-delete-topic": "Diskusjonen har blitt slettet.",
"flow-moderation-confirmation-hide-topic": "Diskusjonen har blitt skjult.",
- "flow-moderation-confirmation-unsuppress-topic": "Diskusjonen er ikke lenger sensurert.",
- "flow-moderation-confirmation-undelete-topic": "Diskusjonen har blitt gjenopprettet.",
- "flow-moderation-confirmation-unhide-topic": "Diskusjonen er ikke lenger skjult.",
- "flow-moderation-title-suppress-topic": "Sensurer diskusjon?",
- "flow-moderation-title-delete-topic": "Slett diskusjon?",
- "flow-moderation-title-hide-topic": "Skjul diskusjon?",
- "flow-moderation-title-unsuppress-topic": "Avslutt sensurering av diskusjonen?",
- "flow-moderation-title-undelete-topic": "Gjenopprett diskusjonen?",
- "flow-moderation-title-unhide-topic": "Avslutt skjuling av diskusjonen?",
- "flow-moderation-placeholder-suppress-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du sensurerer denne diskusjonen.",
- "flow-moderation-placeholder-delete-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du sletter denne diskusjonen.",
- "flow-moderation-placeholder-hide-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du skjuler denne diskusjonen.",
- "flow-moderation-placeholder-unsuppress-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du avslutter sensurering av denne diskusjonen.",
- "flow-moderation-placeholder-undelete-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du gjenoppretter denne diskusjonen.",
- "flow-moderation-placeholder-unhide-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du avslutter skjuling av denne diskusjonen.",
- "flow-topic-permalink-warning": "Denne diskusjonen startet på [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Denne diskusjonen startet på [$2 {{GENDER:$1|$1}}s diskusjonsside]",
+ "flow-moderation-confirmation-unsuppress-topic": "Du har avsensurert saken.",
+ "flow-moderation-confirmation-undelete-topic": "Du har gjenopprettet saken.",
+ "flow-moderation-confirmation-unhide-topic": "Du har fjernet skjuling av saken.",
+ "flow-moderation-title-suppress-topic": "Sensurer saken?",
+ "flow-moderation-title-delete-topic": "Slett saken?",
+ "flow-moderation-title-hide-topic": "Skjul saken?",
+ "flow-moderation-title-unsuppress-topic": "Avsensurer saken?",
+ "flow-moderation-title-undelete-topic": "Gjenopprett saken?",
+ "flow-moderation-title-unhide-topic": "Avslutt skjuling av saken?",
+ "flow-moderation-placeholder-suppress-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du sensurerer denne saken.",
+ "flow-moderation-placeholder-delete-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du sletter denne saken.",
+ "flow-moderation-placeholder-hide-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du skjuler denne saken.",
+ "flow-moderation-placeholder-unsuppress-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du avsensurerer av denne saken.",
+ "flow-moderation-placeholder-undelete-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du gjenoppretter denne saken.",
+ "flow-moderation-placeholder-unhide-topic": "Vennligst {{GENDER:$3|forklar}} hvorfor du avslutter skjuling av denne saken.",
+ "flow-topic-permalink-warning": "Denne saken startet på [$2 $1]",
+ "flow-topic-permalink-warning-user-board": "Denne diskusjonen startet på [$2 {{GENDER:$1|$1}}s tavle]",
"flow-revision-permalink-warning-post": "Dette er en permanent lenke til en enkelt versjon av dette innlegget.\nDenne versjonen er fra $1.\nDu kan se [$5 forskjellene fra foregående versjon], eller se andre versjoner i [$4 innleggshistorikken].",
"flow-revision-permalink-warning-post-first": "Dette er en permanent lenke til første versjon av dette innlegget.\nDu kan se senere versjoner i [$4 innleggshistorikken].",
"flow-revision-permalink-warning-postsummary": "Dette er en permanent lenke til en enkelt versjon av sammendraget for dette innlegget. Denne versjonen er fra $1. Du kan se [$5 endringer fra forrige versjon], eller vise andre versjoner i [$4 innleggets historikk].",
@@ -274,77 +392,139 @@
"flow-revision-permalink-warning-header": "Dette er en permanent lenke til en enkelt versjon av denne beskrivelsen.\nDenne versjonen er fra $1. Du kan se [$3 forskjellene fra foregående versjon], eller se andre versjoner i [$2 historikken].",
"flow-revision-permalink-warning-header-first": "Dette er en permanent lenke til første versjon av denne beskrivelsen.\nDu kan se senere versjoner i [$2 overskriftshistorikken].",
"flow-compare-revisions-revision-header": "Versjon av {{GENDER:$2|$2}} fra $1",
- "flow-compare-revisions-header-post": "Denne siden viser {{GENDER:$3|endringer}} mellom to versjoner av et innlegg av $3 i diskusjonen «[$5 $2]» på [$4 $1].\nDu kan se andre versjoner av dette innlegget i [$6 innleggshistorikken].",
- "flow-compare-revisions-header-postsummary": "Denne siden viser endringer mellom to versjoner av en sammendraget av innlegget «[$4 $2]» på [$3 $1].\nDu kan vise andre versjoner av innlegget i [$5 historikken].",
+ "flow-compare-revisions-header-post": "Denne siden viser {{GENDER:$3|endringer}} mellom to versjoner av et innlegg av $3 i saken «[$5 $2]» på [$4 $1].\nDu kan se andre versjoner av dette innlegget i [$6 innleggshistorikken].",
+ "flow-compare-revisions-header-postsummary": "Denne siden viser endringer mellom to versjoner av sammendraget av innlegget «[$4 $2]» på [$3 $1].\nDu kan se andre versjoner av innleggssammendraget i emnets [$5 historikk].",
"flow-compare-revisions-header-header": "Denne siden viser {{GENDER:$2|endringer}} mellom to versjoner av beskrivelsen [$3 $1].\nDu kan se andre versjoner av denne beskrivelsen i [$4 historikken].",
- "right-flow-hide": "Skjul Flow-diskusjoner og innlegg",
- "right-flow-lock": "Merk Flow-diskusjoner som løst",
- "right-flow-delete": "Slett Flow-diskusjoner og innlegg",
- "right-flow-edit-post": "Rediger innlegg av andre brukere",
- "right-flow-suppress": "Sensurer revisjoner",
+ "action-flow-create-board": "opprette Flow-tavler hvor som helst",
+ "right-flow-create-board": "Opprette Flow-tavler hvor som helst",
+ "right-flow-hide": "Skjule Flow-saker og innlegg",
+ "right-flow-lock": "Merke Flow-saker som løst",
+ "right-flow-delete": "Slette Flow-saker og -innlegg",
+ "right-flow-edit-post": "Redigere Flow-innlegg av andre brukere",
+ "right-flow-suppress": "Sensurere Flow-revisjoner",
"flow-terms-of-use-new-topic": "Ved å klikke «{{int:flow-newtopic-save}}» aksepterer du bruksbetingelsene for denne wikien.",
"flow-terms-of-use-reply": "Ved å klikke «{{int:flow-reply-link}}» aksepterer du bruksbetingelsene for denne wikien.",
- "flow-terms-of-use-edit": "Ved å lagre endringer dine aksepterer du bruksbetingelsene for denne wikien.",
- "flow-anon-warning": "Du er ikke logget inn. For å bli kreditert med ditt navn istedenfor din IP-adresse, kan du [$1 logge inn] eller [$2 opprette en konto].",
+ "flow-terms-of-use-edit": "Ved å lagre endringene dine aksepterer du bruksbetingelsene for denne wikien.",
+ "flow-anon-warning": "Du er ikke innlogget. [$1 Logg inn] eller [$2 opprett en konto] om du ønsker å bli kreditert med navnet ditt istedenfor IP-adressen din.",
"flow-cancel-warning": "Du har skrevet inn tekst i skjemaet. Er du sikker på at du vil forkaste den?",
- "flow-topic-first-heading": "Diskusjon på $1",
+ "flow-topic-first-heading": "Sak på «$1»",
"flow-topic-html-title": "$1 på $2",
- "flow-topic-count": "Diskusjoner ($1)",
+ "flow-topic-count": "Saker ($1)",
"flow-load-more": "Last inn mer",
- "flow-no-more-fwd": "Det finnes ingen eldre diskusjoner",
- "flow-newest-topics": "Nyeste diskusjoner",
- "flow-recent-topics": "Diskusjoner med nylig aktivitet",
- "flow-sorting-tooltip-newest": "De nyeste diskusjonene vises først. Klikk for flere sorteringsmuligheter.",
- "flow-sorting-tooltip-recent": "{{GENDER:|Du}} leser nå det nyeste aktive emnet. Klikk for flere sorteringsmuligheter.",
- "flow-toggle-small-topics": "Bytt til kompakt visning",
- "flow-toggle-topics": "Bytt til visning av kun emner",
- "flow-toggle-topics-posts": "Bytt til visning av emner og innlegg",
+ "flow-no-more-fwd": "Det finnes ingen eldre saker",
+ "flow-newest-topics": "Nyeste saker",
+ "flow-recent-topics": "Saker med nylig aktivitet",
+ "flow-sorting-tooltip-newest": "De nyeste sakene vises først. Klikk for flere sorteringsmuligheter.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Du}} leser nå den nyeste aktive saken. Klikk for flere sorteringsmuligheter.",
+ "flow-toggle-small-topics": "Bytt til kompakt visning av sakene",
+ "flow-toggle-topics": "Bytt til visning av kun saker",
+ "flow-toggle-topics-posts": "Bytt til visning av saker og innlegg",
"flow-terms-of-use-summarize": "Ved å klikke på \"{{int:flow-topic-action-update-topic-summary}}\" godtar du vilkårene for denne wikien.",
+ "flow-terms-of-use-lock-topic": "Ved å klikke «{{int:flow-topic-action-lock-topic}}» aksepterer du bruksbetingelsene for denne wikien.",
+ "flow-terms-of-use-unlock-topic": "Ved å klikke «{{int:flow-topic-action-unlock-topic}}» aksepterer du bruksbetingelsene for denne wikien.",
"flow-whatlinkshere-post": "fra et [$1 innlegg]",
"flow-whatlinkshere-header": "fra [$1 beskrivelsen]",
"flow-whatlinkshere-post-summary": "fra [$1 sammendraget]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Denne spesialsiden omdirigerer til en Flow-arbeidsflyt eller et Flow-innlegg gitt en UUID.",
"flow-special-type": "Type",
"flow-special-type-post": "Innlegg",
"flow-special-type-workflow": "Arbeidsflyt",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Kunne ikke finne innhold som matchet typen og UUID-en.",
- "flow-spam-confirmedit-form": "Vennligst bekreft at du er et menneske ved å løse captcha-en: $1",
+ "flow-special-enableflow-legend": "Aktiver Flow på en ny side",
+ "flow-special-enableflow-page": "Side som Flow skal aktiveres for",
+ "flow-special-enableflow-header": "Innledende beskrivelse av Flow-tavle (wikitekst)",
+ "flow-special-enableflow-board-already-exists": "Det eksisterer allerede en Flow-tavle på [[$1]].",
+ "flow-special-enableflow-invalid-title": "En ugyldig sidetittel ble angitt.",
+ "flow-special-enableflow-board-creation-not-allowed": "Du har ikke lov til å opprette en Flow-tavle på [[:$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Det finnes en LiquidThreads-side på [[:$1]].",
+ "flow-special-enableflow-confirmation": "Du har opprettet en Flow-tavle på [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Arkiv %d\n%s/Arkiv%d\n%s/arkiv %d\n%s/arkiv%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Flow-arkiv %d\n%s/FlowArkiv%d",
+ "flow-spam-confirmedit-form": "Vennligst bekreft at du er et menneske ved å løse CAPTCHA-en: $1",
+ "flow-spam-confirmedit-using-failure": "Det oppsto en teknisk feil med CAPTCHA-en. Om du ikke får til å lagre endringen din, kopier teksten, last siden på nytt og prøv igjen.",
"flow-embedding-unsupported": "Diskusjoner kan ikke bygges inn enda.",
"mw-ui-unsubmitted-confirm": "Du har ulagrede endringer på denne siden. Er du sikker på at du vil navigere vekk og miste arbeidet ditt?",
"flow-post-undo-hide": "angre skjuling",
"flow-post-undo-delete": "angre sletting",
- "flow-post-undo-suppress": "angre undertrykking",
+ "flow-post-undo-suppress": "angre sensurering",
"flow-topic-undo-hide": "angre skjuling",
"flow-topic-undo-delete": "angre sletting",
- "flow-topic-undo-suppress": "angre undertrykking",
- "apihelp-flow+edit-post-param-postId": "Innleggs-ID.",
- "apihelp-flow+edit-post-param-format": "Format for postens innhold (wikitext|html)",
+ "flow-topic-undo-suppress": "angre sensurering",
+ "flow-importer-lqt-moved-thread-template": "LQT Flyttet trådstubb konvertert til Flow",
+ "flow-importer-lqt-moved-thread-template-content": "Dette innlegget av {{{author}}} ble flyttet den {{{date}}}. Du kan finne det på [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "LQT-side konvertert til Flow",
+ "flow-importer-lqt-converted-template-content": "Eldre sidehistorikk ble arkivert for sikkerhetskopiformål på <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> den {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-lqt-converted-archive-template": "Arkiv for konvertert LQT-side",
+ "flow-importer-lqt-converted-archive-template-content": "Denne siden er en arkivert LiquidThreads-side. <strong>Vennligst ikke endre innholdet på denne siden</strong>. Ytterligere kommentarer henvises til den [[{{{from}}}|nåværende diskusjonssiden]].",
+ "flow-importer-wt-converted-template": "Wikitekst-diskusjonsside konvertert til Flow",
+ "flow-importer-wt-converted-template-content": "Eldre diskusjoner ble arkivert på <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> den {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Arkiv for konvertert wikitekst-diskusjonsside",
+ "flow-importer-wt-converted-archive-template-content": "Denne siden er et arkiv. <strong>Vennligst ikke endre innholdet på denne siden</strong>. Ytterligere kommentarer henvises til den [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|nåværende diskusjonssiden]].",
+ "flow-importer-lqt-suppressed-user-template": "LQT-innlegg importert med sensurert bruker",
+ "flow-importer-lqt-suppressed-user-template-content": "Denne revisjonen ble importert fra LiquidThread med en sensurert bruker. Det har blitt tilordnet til den nåværende brukeren.",
+ "flow-importer-lqt-different-author-signature-template": "LQT-innlegg importert med en annen signatur-bruker",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Dette innlegget ble lagt inn av [[User:{{{authorUser}}}|{{{authorUser}}}]], men signert som [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Redigert",
"flow-edited-by": "Redigert av $1",
+ "flow-edited-by-header": "Tavlebeskrivelse endret av $1",
+ "flow-edited-by-topic-title": "Emnetittel redigert av $1",
+ "flow-lqt-redirect-reason": "Omdirigerer utfaset LiquidThreads-innlegg til konvertert Flow-innlegg",
+ "flow-talk-conversion-move-reason": "Konvertering av wikitekst til Flow fra $1",
+ "flow-talk-conversion-archive-edit-reason": "Konvertering av diskusjon i wikitekst til Flow.",
"flow-previous-diff": "← Eldre redigering",
"flow-next-diff": "Nyere redigering →",
"flow-undo": "angre",
"flow-undo-latest-revision": "Siste revisjon",
"flow-undo-your-text": "Din tekst",
"flow-undo-edit-header": "Redigerer beskrivelsen",
- "flow-undo-edit-topic-summary": "Redigerer sammendraget av diskusjonen",
+ "flow-undo-edit-topic-summary": "Redigerer sakssammendraget",
"flow-undo-edit-post": "Redigerer et innlegg",
+ "flow-undo-edit-content": "Redigeringen kan angres. Bruk sammenligningen under for å kontrollere at resultatet er som forventet, og lagre deretter endringene for å bekrefte at redigeringen skal fjernes.",
+ "flow-undo-edit-failure": "Redigeringen kunne ikke angres på grunn av konflikt med mellomliggende redigeringer.",
+ "group-flow-bot": "Flow-boter",
+ "group-flow-bot-member": "Flow-bot",
+ "grouppage-flow-bot": "Project:Flow-boter",
"flow-ve-mention-context-item-label": "Nevn",
"flow-ve-mention-inspector-title": "Nevn",
"flow-ve-mention-inspector-remove-label": "Fjern",
"flow-ve-mention-placeholder": "Brukernavn",
"flow-ve-mention-tool-title": "Nevn en bruker",
- "flow-wikitext-switch-editor-tooltip": "Bytt til VisualEditor",
+ "flow-ve-mention-template-title": "FlowMention",
+ "flow-ve-mention-inspector-invalid-user": "Brukernavnet «$1» er ikke registrert.",
+ "flow-wikitext-editor-help": "Wikitekst $1.",
+ "flow-wikitext-editor-help-and-preview": "Wikitekst $1 og du kan $2 når som helst.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|støtter markering]]",
+ "flow-wikitext-editor-help-preview-the-result": "forhåndsvise resultatet",
+ "flow-wikitext-switch-editor-tooltip": "Bytt til visuell redigering",
+ "flow-ve-switch-editor-tool-title": "Bytt til Wikitekst-redigering",
+ "flow-mark-revision-patrolled-link-text": "Marker denne siden som patruljert",
+ "flow-mark-revision-patrolled-link-title": "Marker denne siden som patruljert",
+ "flow-mark-diff-patrolled-link-text": "Marker som patruljert",
+ "flow-mark-diff-patrolled-link-title": "Marker som patruljert",
+ "flow-talk-page-beta-feature-message": "Flow på brukerdiskusjonsside",
+ "flow-talk-page-beta-feature-description": "Aktiver et nytt strukturert diskusjonssystem på brukerdiskusjonssiden {{GENDER:|din}}. Flow gjør diskusjonssiden enklere å bruke med klare felt for å skrive og svare, og man kan bli varslet om oppdateringer i enkeltdiskusjoner. Eksisterende wikitekstdiskusjoner flyttes til et arkiv. Systemet aktiveres ikke automatisk; brukere må aktivere det hver for seg. Deaktivering av systemet vil flytte Flow-siden til en underside og gjenopprette den gamle brukerdiskusjonssiden fra arkivet.",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Vis}} brukerdiskusjonsside",
+ "flow-notification-enabled-on-talkpage-title": "Nytt diskusjonssystem aktivert på brukerdiskusjonssiden {{GENDER:$1|din}}<br /><small>Tilgjengelig siden [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nytt diskusjonssystem på $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, det nye diskusjonssystemet, har blitt aktivert på brukerdiskusjonssiden {{GENDER:$1|din}} på {{SITENAME}}. Du kan finne ut mer, gi tilbakemelding eller deaktivere det nye systemet når som helst fra seksjonen Betafunksjoner i innstillingene {{GENDER:$1|dine}}.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Legger til arkivmal",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Fjerner arkivmal",
"flow-dialog-cancelconfirm-title": "Er du sikker?",
"flow-dialog-cancelconfirm-message": "Er du sikker på at du ønsker å avbryte uten å lagre først?",
"flow-dialog-cancelconfirm-keep": "Fortsett å redigere",
"flow-dialog-cancelconfirm-discard": "Forkast endringer",
+ "flow-optin-archive-wikitext": "Flytter wikitekstside for å gjøre plass til diskusjonstavle.",
+ "flow-optin-archive-flow-board": "Flytter diskusjonstavle for å gjøre plass til wikitekstside.",
+ "flow-optin-restore-wikitext": "Gjenopprett arkivert wikitekstside.",
+ "flow-optin-restore-flow-board": "Gjenopprett arkivert diskusjonstavle.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Velkommen}} til {{GENDER:$1|din}} nye brukerdiskusjonsside",
"flow-guidedtour-optin-welcome-description": "Brukerdiskusjonssiden {{GENDER:$1|din}} er stedet der andre bidragsytere kan kontakte {{GENDER:$1|deg}}. Med Flow har det blitt enklere å starte nye diskusjoner og holde oversikten over dem.",
"flow-guidedtour-optin-find-old-conversations": "Finn igjen {{GENDER:$1|dine}} gamle diskusjoner",
"flow-guidedtour-optin-find-old-conversations-description": "Gamle diskusjoner har blitt flyttet til en arkivside.",
"flow-guidedtour-optin-feedback": "Gi oss {{GENDER:$1|din}} tilbakemelding!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kan finne mer informasjon, gi tilbakemelding, eller deaktivere det nye systemet når som helst fra siden for betafunksjoner."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kan finne mer informasjon, gi tilbakemelding, eller deaktivere det nye systemet når som helst fra siden for betafunksjoner.",
+ "flow-action-not-page": "Sideobjektet er en instans av feil klasse",
+ "flow-action-wrong-title-content-model": "Denne siden er håndtert av Flow, men Tittel-klassen indikerer at innholdsmodellen er «$1». Dette er en feilkonfigurasjon eller inkonsistent tilstand. For eksempel så kan dette være en side som ikke er Flow i et navnerom merket for Flow, hvor <code>rev_content_model</code> ikke er angitt."
}
diff --git a/Flow/i18n/nds.json b/Flow/i18n/nds.json
new file mode 100644
index 00000000..0fc3f3b0
--- /dev/null
+++ b/Flow/i18n/nds.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "flow-post-action-hide-post": "Versteken",
+ "flow-moderation-confirm-hide-post": "Versteken",
+ "flow-moderation-confirm-hide-topic": "Versteken"
+}
diff --git a/Flow/i18n/ne.json b/Flow/i18n/ne.json
index 2b630c9e..face3128 100644
--- a/Flow/i18n/ne.json
+++ b/Flow/i18n/ne.json
@@ -6,9 +6,12 @@
"Nirjal stha",
"बिप्लब आनन्द",
"NehalDaveND",
- "राम प्रसाद जोशी"
+ "राम प्रसाद जोशी",
+ "Nirajan pant"
]
},
+ "notification-dynamic-actions-flow-topic-unwatch": "एइ विषय हेर्न बन्द गर",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "तपाईं [$2 this topic] जहिले पनि हेर्न सक्नुहुन्छ।",
"flow-board-header": "छलफलको बारेमा",
"flow-board-collapse-description": "वर्णन लुकाउने",
"flow-board-expand-description": "वर्णन देखाउने",
@@ -21,13 +24,14 @@
"flow-history-action-delete-post": "मेटिएको",
"flow-history-action-hide-post": "लुकाउनुहोस्",
"flow-history-action-restore-post": "पूर्वावस्थामा ल्याउनुहोस्",
- "flow-history-action-lock-topic": "रोक्ने",
- "flow-history-action-unlock-topic": "रोक फुकुवा गर्ने",
+ "flow-history-action-lock-topic": "समाधान",
+ "flow-history-action-unlock-topic": "रोक फुकुवा",
"flow-post-action-post-history": "इतिहास",
"flow-post-action-suppress-post": "दबाउने",
"flow-post-action-delete-post": "हटाउने",
"flow-post-action-hide-post": "लुकाउनुहोस्",
"flow-post-action-edit-post": "सम्पादन",
+ "flow-post-action-edit-post-submit": "परिवर्तन सङ्ग्रह गर्नुहोस्",
"flow-post-action-restore-post": "पूर्वावस्थामा ल्याउनुहोस्",
"flow-topic-action-history": "इतिहास",
"flow-topic-action-undo-moderation": "पूर्ववत गर्ने",
@@ -46,9 +50,8 @@
"flow-load-more": "थप पढ्ने",
"flow-special-uuid": "UUID",
"flow-special-enableflow-invalid-title": "अबैध पृष्ठ शिर्षक राखिएको थियो",
- "flow-special-enableflow-archive-title-format-default-value": "%s/Archive_%d",
"flow-undo": "पूर्ववत गर्ने",
- "flow-undo-your-text": "तपाईँको पाठ",
+ "flow-undo-your-text": "तपाईंको पाठ",
"flow-ve-mention-inspector-remove-label": "हटाउने",
"flow-ve-mention-placeholder": "प्रयोगकर्ता नाम"
}
diff --git a/Flow/i18n/nl.json b/Flow/i18n/nl.json
index eb7d4128..775e1599 100644
--- a/Flow/i18n/nl.json
+++ b/Flow/i18n/nl.json
@@ -18,27 +18,55 @@
"Mirolith",
"MedShot",
"Robin0van0der0vliet",
- "Catrope"
+ "Catrope",
+ "Nnemo",
+ "Robin van der Vliet",
+ "Macofe",
+ "Matiia",
+ "Dinosaur918",
+ "MrLeopold",
+ "McDutchie",
+ "Mainframe98",
+ "Huhbakker"
]
},
- "enableflow": "Flow inschakelen",
- "flow-desc": "Workflowmanagementsysteem",
- "flow-talk-taken-over": "Deze overlegpagina gebruikt [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal Flow].",
+ "enablestructureddiscussions": "Flow inschakelen",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Stop}} met het volgen van nieuwe gebeurtenissen op \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|U}} volgt de pagina \"$1\" niet meer",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Dit heeft geen invloed op individuele onderwerpen die {{GENDER:$3|u}} volgt. U kunt [$2 deze pagina] op elk moment volgen.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Stop}} met het volgen van dit onderwerp",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|U}} volgt \"$1\" niet meer",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|U}} kunt [$2 dit onderwerp] op elk moment volgen.",
+ "flow-desc": "Discussiesysteem",
+ "flow-talk-taken-over-comment": "/* Deze pagina is omgezet naar een Flow-discussiebord */",
"log-name-flow": "Logboek Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|heeft}} een [$4 bericht] verwijderd van [[$3|$5]] op [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|verwijderde}} een reactie over een onderwerp op [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|heeft}} een [$4 bericht] teruggeplaatst op [[$3|$5]] op [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|herstelde}} een reactie over een onderwerp op [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|heeft}} een [$4 bericht] onderdrukt op [[$3|$5]] op [[$6]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|heeft}} een [$4 bericht] verwijderd van [[$3|$5]] op [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|verwijderde}} een reactie op een onderwerp op [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|heeft}} het onderwerp \"[[$3|$5]]\" op [[$6]] verwijderd",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|verwijderde}} een onderwerp op [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|heeft}} het onderwerp \"[[$3|$5]]\" op [[$6]] teruggeplaatst",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|herstelde}} een onderwerp op [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|heeft}} het onderwerp \"[[$3|$5]]\" op [[$6]] onderdrukt",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|heeft}} het onderwerp \"[[$3|$5]]\" op [[$6]] verwijderd",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|verwijderde}} een onderwerp op [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 heeft het onderwerp \"[[$3|$5]]\" op [[$6]] {{GENDER:$2|gemarkeerd}} als opgelost",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|markeerde}} een onderwerp als opgelost op [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 heeft het onderwerp \"[[$3|$5]]\" op [[$6]] {{GENDER:$2|heropend}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|heropende}} een onderwerp op [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] op [[$3]] is van LiquidThreads naar Flow omgezet",
"flow-user-moderated": "Gemodereerde gebruiker",
"flow-board-header-browse-topics-link": "Blader door onderwerpen",
- "flow-board-header": "Over deze discussie",
+ "flow-board-header": "Over dit discussiebord",
+ "flow-board-description-can-not-edit": "Niet bewerkbaar",
"flow-board-collapse-description": "Beschrijving verbergen",
"flow-board-expand-description": "Beschrijving weergeven",
+ "flow-topic-collapse-siderail": "In volledige breedte lezen",
+ "flow-topic-expand-siderail": "In vaste breedte lezen",
"flow-edit-header-link": "Beschrijving bewerken",
"flow-post-moderated-toggle-hide-show": "Reactie {{GENDER:$1|verborgen}} door $2 zichtbaar maken",
"flow-post-moderated-toggle-delete-show": "Reactie {{GENDER:$1|verwijderd}} door $2 zichtbaar maken",
@@ -60,23 +88,25 @@
"flow-post-actions": "Handelingen",
"flow-topic-actions": "Handelingen",
"flow-cancel": "Annuleren",
- "flow-skip-summary": "Sla samenvatting over",
+ "flow-skip-summary": "Overslaan",
"flow-edit-summary-placeholder": "Beschrijf in het kort de uitkomst van deze discussie",
"flow-summary-authored": "Samenvatting door $1",
"flow-summary-edited": "Overzicht het laatst {{GENDER:$1|bewerkt}} door $1",
"flow-show-change": "Laat wijzigingen zien",
"flow-last-modified-by": "Laatst {{GENDER:$1|bewerkt}} door $1",
- "flow-stub-post-content": "''Dit bericht kan niet worden opgehaald door een technische fout.''",
+ "flow-stub-post-content": "<em>Dit bericht kan niet worden opgehaald door een technische fout.</em>",
"flow-newtopic-title-placeholder": "Nieuw onderwerp",
"flow-newtopic-content-placeholder": "Nieuw bericht plaatsen op \"$1\"",
"flow-newtopic-header": "Nieuw onderwerp toevoegen",
"flow-newtopic-save": "Onderwerp toevoegen",
+ "flow-newtopic-save-anonymously": "Onderwerp anoniem toevoegen",
"flow-newtopic-start-placeholder": "Nieuw onderwerp",
"flow-newtopic-first-heading": "Start een nieuw onderwerp over $1",
"flow-summarize-topic-placeholder": "Vat het overleg samen",
"flow-reply-topic-placeholder": "{{GENDER:$1|Reageren}} op \"$2\"",
"flow-reply-topic-title-placeholder": "Reageren op \"$1\"",
"flow-reply-link": "{{GENDER:$1|Reageren}}",
+ "flow-reply-link-anonymously": "Anoniem reageren",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Bedanken}}}}",
"flow-thank-link-title": "De plaatser van dit bericht openbaar {{GENDER:$1|{{GENDER:$2|bedanken}}}}",
"flow-history-action-suppress-post": "onderdrukken",
@@ -96,6 +126,7 @@
"flow-post-action-hide-post": "Verbergen",
"flow-post-action-edit-post": "Bewerken",
"flow-post-action-edit-post-submit": "Wijzigingen opslaan",
+ "flow-post-action-edit-post-submit-anonymously": "Wijzigingen anoniem opslaan",
"flow-post-action-unsuppress-post": "Niet langer onderdrukken",
"flow-post-action-undelete-post": "Terugplaatsen",
"flow-post-action-unhide-post": "Zichtbaar maken",
@@ -107,7 +138,7 @@
"flow-topic-action-history": "Geschiedenis",
"flow-topic-action-hide-topic": "Onderwerp verbergen",
"flow-topic-action-delete-topic": "Onderwerp verwijderen",
- "flow-topic-action-lock-topic": "Onderwerp sluiten",
+ "flow-topic-action-lock-topic": "Als opgelost markeren",
"flow-topic-action-unlock-topic": "Onderwerp heropenen",
"flow-topic-action-summarize-topic": "Samenvatten",
"flow-topic-action-resummarize-topic": "De onderwerpsamenvatting bewerken",
@@ -124,27 +155,26 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|U}} krijgt een melding als er een nieuw onderwerp wordt gemaakt op dit bord.",
"flow-topic-action-watchlist-add": "Op dit onderwerp abonneren",
"flow-topic-action-watchlist-remove": "Uitschrijven",
- "flow-error-allowcreation-no-usedb": "Voor allowCreation moet <var>$wgContentHandlerUseDB</var> <code>true</code> zijn.",
- "flow-error-allowcreation-already-exists": "Pagina bestond al, maar moest niet bestaan",
+ "flow-error-allowcreation-no-usedb": "Om Flow in te schakelen op een specifieke pagina moet <var>$wgContentHandlerUseDB</var> <code>true</code> zijn.",
+ "flow-error-allowcreation-already-exists": "Er bestaat al een pagina op het doel, dus kan een Flow bord hier niet naar toe verplaatst worden.",
"flow-error-allowcreation-flow-create-board": "De gebruiker heeft het \"{{int:right-flow-create-board}}\" recht niet",
+ "flow-error-can-not-edit-logged-out": "U momenteel niet in staat om deel te nemen. U kunt proberen in te loggen.",
"flow-error-http": "Er is een fout opgetreden in het contact met de server.",
- "flow-error-other": "Er is een onverwachte fout opgetreden.",
- "flow-error-external": "Er is een fout opgetreden.<br />De foutmelding is: $1",
- "flow-error-edit-restricted": "U mag dit bericht niet bewerken.",
+ "flow-error-external": "Er is een fout opgetreden. De foutmelding is: $1",
"flow-error-topic-is-locked": "Dit onderwerp is gesloten, verdere activiteit is niet mogelijk.",
"flow-error-lock-moderated-post": "U kunt een gemodereerd bericht niet sluiten.",
- "flow-error-external-multi": "Er zijn fouten opgetreden.<br />$1",
"flow-error-missing-content": "Het bericht heeft geen inhoud. Inhoud is vereist voor het opslaan van een bericht.",
- "flow-error-missing-summary": "De samenvatting is leeg. U moet tekst invoeren om een samenvatting op te kunnen slaan.",
+ "flow-error-missing-summary": "U moet een samenvatting invoeren.",
"flow-error-missing-title": "Onderwerp heeft geen titel. Een titel is vereist voor het opslaan van een onderwerp.",
"flow-error-parsoid-failure": "Verwerken is niet mogelijk vanwege een fout in Parsoid.",
+ "flow-error-protected-autoconfirmed-logged-in": "Deze board wordt beschermd. Alleen autoconfirmed gebruikers kunnen deelnemen. Reden: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Deze board wordt beschermd. Alleen ingelogde gebruikers die autoconfirmed kunnen deelnemen. Reden: $1",
+ "flow-error-protected-sysop-logged-in": "Deze board wordt beschermd. Alleen gebruikers met beheerdersrechten kunnen deelnemen. Reden: $1",
+ "flow-error-protected-sysop-logged-out": "Deze board wordt beschermd. Alleen ingelogde gebruikers met beheerdersrechten kunnen deelnemen. Reden: $1",
+ "flow-error-protected-unknown-reason": "Onbekend",
"flow-error-missing-replyto": "Er is geen parameter \"replyTo\" opgegeven. Deze parameter is verplicht voor de handeling \"reply\".",
- "flow-error-invalid-replyto": "De parameter \"replyTo\" is ongeldig. Het opgegeven bericht kon niet worden gevonden.",
- "flow-error-delete-failure": "Het verwijderen van dit item is mislukt.",
- "flow-error-hide-failure": "Het verbergen van dit item is mislukt.",
"flow-error-missing-postId": "Er is geen parameter \"postId\" opgegeven. Deze parameter is verplicht bij het wijzigingen van een bericht.",
"flow-error-invalid-postId": "De parameter \"postId\" is ongeldig. Het opgegeven bericht ($1) kan niet worden gevonden.",
- "flow-error-restore-failure": "Het terugplaatsen van dit item is mislukt.",
"flow-error-invalid-moderation-state": "Er is een ongeldige waarde opgegeven voor een parameter (\"moderationState\") van de Flow-API.",
"flow-error-invalid-moderation-reason": "Geef een reden op voor de moderatie.",
"flow-error-not-allowed": "Onvoldoende rechten voor het uitvoeren van deze handeling.",
@@ -162,9 +192,9 @@
"flow-error-title-too-long": "Onderwerpen kunnen niet langer zijn dan $1 {{PLURAL:$1|teken|tekens}}.",
"flow-error-no-existing-workflow": "Deze workflow bestaat nog niet.",
"flow-error-not-a-post": "Dit onderwerp kan niet als bericht worden opgeslagen.",
- "flow-error-missing-header-content": "De beschrijving heeft geen inhoud. Inhoud is verplicht voor de beschrijving, anders kunt u niet opslaan.",
+ "flow-error-missing-header-content": "U moet een beschrijving invoeren.",
"flow-error-missing-prev-revision-identifier": "Het ID van de vorige versie ontbreekt.",
- "flow-error-prev-revision-mismatch": "Een andere gebruiker bewerkte deze bijdrage al een paar seconden geleden. Weet u zeker dat u deze recente verandering wilt overschrijven?{{GENDER:$3|}}",
+ "flow-error-prev-revision-mismatch": "Een andere gebruiker bewerkte deze bijdrage net een paar seconden geleden. Weet u zeker dat u deze recente verandering wilt overschrijven?{{GENDER:$3|}}",
"flow-error-prev-revision-does-not-exist": "De vorige versie kon niet gevonden worden.",
"flow-error-core-topic-deletion": "U kunt dit onderwerp niet rechtstreeks met action=delete verwijderen. Gebruik het ... menu op het discussiebord of op de [$1 onderwerppagina].",
"flow-error-default": "Er is een fout opgetreden.",
@@ -186,7 +216,6 @@
"flow-error-no-commit": "De opgegeven handeling kon niet worden uitgevoerd.",
"flow-error-content-too-long": "De inhoud is te lang. Na uitbreiding van sjablonen mag de grootte maximaal $1 {{PLURAL:$1|byte|bytes}} zijn.",
"flow-error-move-topic": "Het hernoemen van een onderwerppagina wordt momenteel niet ondersteund.",
- "flow-error-move-no-create-permissions": "Het \"{{int:right-flow-create-board}}\" recht is nodig om een discussiebord te hernoemen.",
"flow-error-invalid-topic-uuid-title": "Ongeldige paginanaam",
"flow-error-invalid-topic-uuid": "De opgevraagde paginanaam is ongeldig. Pagina's in the Onderwerp-naamruimte worden automatisch aangemaakt.",
"flow-error-unknown-workflow-id-title": "Onbekend onderwerp",
@@ -194,8 +223,11 @@
"flow-error-search": "Als gevolg van een tijdelijk probleem kon uw zoekopdracht niet worden voltooid. Probeer het later opnieuw.",
"flow-edit-header-placeholder": "Beschrijf dit overlegbord",
"flow-edit-header-submit": "Beschrijving opslaan",
+ "flow-edit-header-submit-anonymously": "Beschrijving anoniem opslaan",
"flow-edit-title-submit": "Onderwerp wijzigen",
+ "flow-edit-title-submit-anonymously": "Anoniem titel wijzigen",
"flow-edit-post-submit": "Wijzigingen opslaan",
+ "flow-edit-post-submit-anonymously": "Wijzigingen anoniem opslaan",
"flow-rev-message-edit-post": "[$1|$2] {{GENDER:$2|heeft}} een [$3 reactie] bewerkt op \"$4\"",
"flow-rev-message-edit-post-recentchanges-summary": "Bericht {{GENDER:$2|bewerkt}}",
"flow-rev-message-reply": "$1 {{GENDER:$2|heeft}} een [$3 reactie] toegevoegd op \"$4\" (<em>$5</em>)",
@@ -214,7 +246,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] \"$6\" verborgen (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] \"$6\" verwijderd (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] \"$6\" onderdrukt (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] $6 gesloten (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] \"$6\" gesloten (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "gesloten",
"flow-rev-message-restore-topic-reason": "heropend",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|heeft}} het [$4 onderwerp] \"$6\" teruggeplaatst (<em>$5</em>)",
@@ -237,30 +269,72 @@
"flow-comment-moderated": "Gemodereerde reactie",
"flow-last-modified": "Ongeveer $1 voor het laatst bewerkt",
"flow-workflow": "workflow",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 heeft {{GENDER:$1|gereageerd}} op '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 en $5 {{PLURAL:$6|iemand anders|anderen}} hebben {{GENDER:$1|gereageerd}} op '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 heeft {{GENDER:$1|gereageerd}} op <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 en {{PLURAL:$5|een iemand anders|$5 anderen|100=99+ anderen}} hebben {{GENDER:$1|gereageerd}} op <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks\"[$6 $2]</span><br />$1 {{GENDER:$1|heeft}} een <span class=\"plainlinks\">[$5 bericht]</span> geplaatst op [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 en $5 {{PLURAL:$6|andere gebruiker|anderen}} {{GENDER:$1|hebben}} een <span class=\"plainlinks\">[$4 bericht]</span> geplaatst in \"$2\" op \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|heeft}} een nieuw onderwerp aangemaakt op '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nieuw onderwerp|$1 nieuwe onderwerpen|250=250+ nieuwe onderwerpen}} op '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 en {{PLURAL:$5|een andere gebruiker|$5 anderen|100=99+ anderen}} {{GENDER:$1|hebben}} een <span class=\"plainlinks\">[$4 bericht]</span> geplaatst in \"$2\" op \"$3\".",
+ "notification-header-flow-new-topic-v2": "Nieuw onderwerp aangemaakt op <strong>$3</strong>: <bdi>\"<strong>$4</strong>''</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Een nieuw onderwerp|$1 nieuwe onderwerpen|100=99+ nieuwe onderwerpen}} op <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Er is een nieuw onderwerp aangemaakt op <strong>uw overlegpagina</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Een nieuw onderwerp|$1 nieuwe onderwerpen|100=99+ nieuwe onderwerpen}} op <strong>uw overlegpagina</strong>.",
+ "notification-header-flow-post-reply": "$1 heeft {{GENDER:$2|gereageerd}} in <strong>$4</strong>.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Een nieuwe reactie|$1 nieuwe reacties|100=99+ nieuwe reacties}} in \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 heeft een reactie op <strong>uw overlegpagina</strong> in \"<strong>$4</strong>\" {{GENDER:$2|geplaatst}}.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Een nieuwe reactie|$1 nieuwe reacties|100=99+ nieuwe reacties}} op <strong>uw overlegpagina</strong> in \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Uw}} bericht in <strong>$1</strong> is bewerkt.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Uw}} bericht in <strong>$1</strong> is meerdere keren bewerkt.",
+ "notification-header-flow-post-edited-user-talk": "Een bericht in \"<strong>$1</strong>\" op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is bewerkt.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Een bericht in \"<strong>$1</strong>\" op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is bewerkt.",
+ "notification-header-flow-topic-renamed-v2": "Het onderwerp \"<strong>$1</strong>\" is hernoemd naar \"<strong>$2</strong>\"",
+ "notification-header-flow-topic-renamed-user-talk": "Het onderwerp \"<strong>$1</strong>\" op <strong>{{GENDER:$3|uw}} overlegpagina</strong> is hernoemd naar \"<strong>$2</strong>\".",
+ "notification-header-flow-summary-edited": "De samenvatting voor \"<strong>$1</strong>\" is bijgewerkt.",
+ "notification-header-flow-summary-edited-first": "Er is een samenvatting gemaakt voor het onderwerp \"<strong>$1</strong>\".",
+ "notification-bundle-header-flow-summary-edited": "De samenvatting voor \"<strong>$1</strong>\" is meerdere keren bijgewerkt.",
+ "notification-header-flow-summary-edited-user-talk": "De samenvatting voor \"<strong>$1</strong>\" op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is bijgewerkt.",
+ "notification-header-flow-summary-edited-first-user-talk": "Het onderwerp \"<strong>$1</strong>\" op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is samengevat.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "De samenvatting voor \"<strong>$1</strong>\" op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is meerdere keren bijgewerkt.",
+ "notification-email-subject-flow-summary-edited": "$1 heeft de samenvatting op $2 {{GENDER:$1|bijgewerkt}}.",
+ "notification-email-batch-body-flow-summary-edited": "$1 heeft de samenvatting op $2 {{GENDER:$1|bijgewerkt}}.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 en {{PLURAL:$3|een iemand anders|$3 anderen|100=99+ anderen}} hebben de samenvatting op $2 {{GENDER:$1|bijgewerkt}}",
+ "notification-header-flow-mention-post": "$1 heeft {{GENDER:$4|u}} {{GENDER:$2|genoemd}} in <strong>$5</strong>.",
+ "notification-header-flow-mention-header": "$1 heeft {{GENDER:$4|u}} {{GENDER:$2|genoemd}} in de beschrijving van <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 heeft {{GENDER:$4|u}} {{GENDER:$2|genoemd}} in \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Nieuw overlegsysteem geactiveerd op <strong>{{GENDER:$2|uw}} overlegpagina</strong>.",
+ "notification-header-flow-description-edited": "De beschrijving van <strong>$1</strong> is gewijzigd.",
+ "notification-header-flow-description-edited-user-talk": "De omschrijving op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is bewerkt.",
+ "notification-bundle-header-flow-description-edited": "De omschrijving van <strong>$1</strong> is meerdere keren bewerkt.",
+ "notification-bundle-header-flow-description-edited-user-talk": "De omschrijving op <strong>{{GENDER:$2|uw}} overlegpagina</strong> is meerdere keren bewerkt.",
+ "notification-links-flow-description-edited-view-page": "Pagina {{GENDER:$1|bekijken}}",
+ "notification-email-subject-flow-description-edited": "$1 heeft de omschrijving van $2 {{GENDER:$1|bewerkt}}.",
+ "notification-email-batch-body-flow-description-edited": "$1 heeft de omschrijving van $2 {{GENDER:$1|bewerkt}}.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 en {{PLURAL:$3|een iemand anders|$3 anderen|100=99+ anderen}} hebben de omschrijving op $2 {{GENDER:$1|bewerkt}}",
+ "notification-header-flow-topic-resolved": "Het onderwerp \"<strong>$1</strong>\" is gemarkeerd als opgelost.",
+ "notification-header-flow-topic-reopened": "Het onderwerp \"<strong>$1</strong>\" is heropend.",
+ "notification-header-flow-topic-resolved-user-talk": "Het onderwerp \"<strong>$1</strong>\" op <strong>uw overlegpagina</strong> is gemarkeerd als opgelost.",
+ "notification-header-flow-topic-reopened-user-talk": "Het onderwerp \"<strong>$1</strong>\" op <strong>uw overlegpagina</strong> is heropend.",
+ "notification-email-subject-flow-topic-resolved": "Het onderwerp \"<strong>$2</strong>\" is gemarkeerd als opgelost.",
+ "notification-email-batch-body-flow-topic-resolved": "Het onderwerp \"<strong>$2</strong>\" is gemarkeerd als opgelost.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|heeft}} een nieuw onderwerp aangemaakt op <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Een nieuw onderwerp|$1 nieuwe onderwerpen|100=99+ nieuwe onderwerpen}} op <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|heeft}} het onderwerp <span class=\"plainlinks\">[$2 $3]</span> hernoemd naar \"$4\" op [[$5|$6]].",
"flow-notification-mention": "$1 heeft {{GENDER:$5|u}} genoemd in {{GENDER:$1|zijn|haar|zijn/haar}} <span class=\"plainlinks\">[$2 bericht]</span> in \"$3\" op \"$4\".",
"flow-notification-link-text-view-post": "Bericht bekijken",
"flow-notification-link-text-view-topic": "Onderwerp bekijken",
+ "flow-notification-link-text-view-topics": "Onderwerpen bekijken",
"flow-notification-reply-email-subject": "$2 op $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|heeft}} gereageerd op \"$2\" op $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 en $4 {{PLURAL:$5|andere gebruiker|anderen}} {{GENDER:$1|hebben}} gereageerd op \"$2\" op $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 en {{PLURAL:$4|een iemand anders|$4 anderen|100=99+ anderen}} {{GENDER:$1|hebben}} gereageerd op \"$2\" op $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|heeft}} {{GENDER:$3|u}} genoemd op $2",
"flow-notification-mention-email-batch-body": "$1 heeft {{GENDER:$4|u}} genoemd in {{GENDER:$1|zijn|haar|zijn/haar}} bericht in \"$2\" op $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|heeft}} een bericht bewerkt",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|heeft}} een bericht bewerkt in \"$2\" op $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 en $4 {{PLURAL:$5|andere gebruiker|anderen}} {{GENDER:$1|hebben}} een bericht bewerkt in \"$2\" op $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 en {{PLURAL:$4|een iemand anders|$4 anderen|100=99+ anderen}} {{GENDER:$1|hebben}} een bericht in \"$2\" op $3 {{GENDER:$1|bewerkt}}",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|heeft}} uw onderwerp een andere naam gegeven",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|heeft}} uw onderwerp \"$2\" hernoemd naar \"$3\" op $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|heeft}} een nieuw onderwerp aangemaakt op $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|heeft}} op $3 een nieuw onderwerp aangemaakt met de naam \"$2\"",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nieuw onderwerp|$1 nieuwe onderwerpen|250=250+ nieuwe onderwerpen}} op $2",
- "echo-category-title-flow-discussion": "Flow",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Een nieuw onderwerp|$1 nieuwe onderwerpen|100=99+ nieuwe onderwerpen}} op $2",
+ "echo-category-title-flow-discussion": "Flow overleg",
"echo-pref-tooltip-flow-discussion": "Informeer mij wanneer er aan mij gerelateerde handelingen in Flow plaatsvinden.",
"flow-link-post": "bericht",
"flow-link-topic": "onderwerp",
@@ -294,17 +368,17 @@
"flow-moderation-confirm-undelete-topic": "Terugplaatsen",
"flow-moderation-confirm-unhide-topic": "Zichtbaar maken",
"flow-moderation-confirmation-suppress-post": "Het bericht is onderdrukt.\n{{GENDER:$2|Overweeg}} $1 terugkoppeling te geven over dit bericht.",
- "flow-moderation-confirmation-delete-post": "Het bericht is verwijderd.\n{{GENDER:$2|Overweeg}} {{GENDER:$1|$1}} terugkoppeling te geven over dit bericht.",
- "flow-moderation-confirmation-hide-post": "Het bericht is verborgen.\n{{GENDER:$2|Overweeg}} {{GENDER:$1|$1}} terugkoppeling te geven over dit bericht.",
+ "flow-moderation-confirmation-delete-post": "Het bericht is verwijderd.\n{{GENDER:$2|Overweeg}} $1 terugkoppeling te geven over dit bericht.",
+ "flow-moderation-confirmation-hide-post": "Het bericht is verborgen.\n{{GENDER:$2|Overweeg}} $1 terugkoppeling te geven over dit bericht.",
"flow-moderation-confirmation-unsuppress-post": "Het bovenstaande bericht wordt niet langer onderdrukt.",
- "flow-moderation-confirmation-undelete-post": "Het bovenstaande bericht is teruggeplaatst.",
- "flow-moderation-confirmation-unhide-post": "Het bovenstaande bericht is weer zichtbaar.",
+ "flow-moderation-confirmation-undelete-post": "U heeft de verwijdering van het bovenstaande bericht ongedaan gemaakt.",
+ "flow-moderation-confirmation-unhide-post": "U heeft het bovenstaande bericht weer zichtbaar gemaakt.",
"flow-moderation-confirmation-suppress-topic": "Dit onderwerp is onderdrukt.",
"flow-moderation-confirmation-delete-topic": "Dit onderwerp is verwijderd.",
"flow-moderation-confirmation-hide-topic": "Dit onderwerp is verborgen.",
"flow-moderation-confirmation-unsuppress-topic": "Dit onderwerp wordt niet langer onderdrukt.",
- "flow-moderation-confirmation-undelete-topic": "Dit onderwerp is teruggeplaatst.",
- "flow-moderation-confirmation-unhide-topic": "Dit onderwerp is weer zichtbaar.",
+ "flow-moderation-confirmation-undelete-topic": "U heeft de verwijdering van dit onderwerp ongedaan gemaakt.",
+ "flow-moderation-confirmation-unhide-topic": "U heeft dit onderwerp weer zichtbaar gemaakt.",
"flow-moderation-title-suppress-topic": "Onderwerp onderdrukken?",
"flow-moderation-title-delete-topic": "Onderwerp verwijderen?",
"flow-moderation-title-hide-topic": "Onderwerp verbergen?",
@@ -327,7 +401,7 @@
"flow-revision-permalink-warning-header-first": "Dit is een permanente koppeling naar de eerste versie van deze koptekst.\nU kunt nieuwere versies bekijken op de [$2 geschiedenispagina van dit discussiebord].",
"flow-compare-revisions-revision-header": "Version van $1 door {{GENDER:$2|$2}}",
"flow-compare-revisions-header-post": "Op deze pagina worden de verschillen tussen twee versies weergegeven van een bericht van {{GENDER:$3|$3}} in het onderwerp \"[$5 $2]\" op [$4 $1].\nU kunt de andere versie van dit bericht bekijken op de [$6 geschiedenispagina].",
- "flow-compare-revisions-header-postsummary": "Op deze pagina worden de verschillen tussen twee versies weergegeven van de samenvatting van een bericht in het onderwerp \"[$4 $2]\" op [$3 $1].\nU kunt de andere versie van dit bericht bekijken op de [$5 geschiedenispagina].",
+ "flow-compare-revisions-header-postsummary": "Op deze pagina worden worden de verschillen tussen twee versies van de samenvatting van het onderwerp getoond \"[$4 $2]\" op [$3 $1]. U kan andere versies van dit onderwerpsoverzicht bekijken op de [$5 geschiedenispagina] van het onderwerp.",
"flow-compare-revisions-header-header": "Op deze pagina worden de {{GENDER:$2|verschillen}} tussen twee versies weergegeven van de koptekst op [$3 $1].\nU kunt de andere versie van de kop bekijken op de [$4 geschiedenispagina].",
"action-flow-create-board": "Flow-discussieborden aanmaken op alle pagina's",
"right-flow-create-board": "Flow-discussieborden aanmaken op alle pagina's",
@@ -359,7 +433,7 @@
"flow-whatlinkshere-post": "van een [$1 bericht]",
"flow-whatlinkshere-header": "van de [$1 beschrijving]",
"flow-whatlinkshere-post-summary": "van de [$1 samenvatting]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Deze speciale pagina verwijst door naar een workflow van Flow of een bericht van Flow op basis van een UUID.",
"flow-special-type": "Type",
"flow-special-type-post": "Bericht",
@@ -373,9 +447,10 @@
"flow-special-enableflow-invalid-title": "Er is een ongeldige paginanaam opgegeven.",
"flow-special-enableflow-board-creation-not-allowed": "Het is u niet toegestaan een Flow-discussiebord aan te maken op [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Er is een LiquidThreads-pagina op [[:$1]].",
- "flow-special-enableflow-confirmation": "U hebt met succes een Flow-discussiebord aangemaakt op [[$1]].",
+ "flow-special-enableflow-confirmation": "U heeft een Flow-discussiebord aangemaakt op [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archief %d\n%s/archief %d\n%s/Archief-%d\n%s/archief-%d",
"flow-spam-confirmedit-form": "Bevestig alstublieft dat u een mens bent door onderstaande captcha op te lossen: $1",
+ "flow-spam-confirmedit-using-failure": "Er was een technische fout met de CAPTCHA. Als u niet in staat bent om uw verandering in te dienen, kopieer dan uw tekst, ververs en probeer opnieuw.",
"flow-embedding-unsupported": "Overleg kan nog niet ingebed worden.",
"mw-ui-unsubmitted-confirm": "U hebt nog niet opgeslagen wijzigingen op deze pagina. Weet u zeker dat u door weg te gaan van deze pagina uw wijzigingen wilt verliezen?",
"flow-post-undo-hide": "verbergen ongedaan maken",
@@ -387,17 +462,18 @@
"flow-importer-lqt-moved-thread-template": "LQT-doorverwijzing omgezet naar Flow",
"flow-importer-lqt-converted-template": "LQT-pagina omgezet naar Flow",
"flow-importer-lqt-converted-archive-template": "Archief voor omgezette LQT-pagina",
+ "flow-importer-lqt-converted-archive-template-content": "Deze pagina is een gearchiveerde LiquidThreads pagina. <strong>Bewerk de inhoud van deze pagina niet</strong>. Plaats alle aanvullende opmerkingen op de [[{{{from}}}|huidige overlegpagina]].",
"flow-importer-wt-converted-template": "Wikitext-overlegpagina omgezet naar Flow",
+ "flow-importer-wt-converted-template-content": "Het vorige gesprek is gearchiveerd op <span class=\"flow-link-to-archive\">[[{{{archive}}}]]</span> op {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Archief voor omgezette wikitext-overlegpagina",
+ "flow-importer-wt-converted-archive-template-content": "Deze pagina is een archief. <strong>Bewerk de inhoud van deze pagina niet</strong>. Plaats alle aanvullende opmerkingen op de [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|huidige overlegpagina]].",
"flow-importer-lqt-suppressed-user-template": "Omgezet LQT-bericht met onderdrukte auteur",
+ "flow-importer-lqt-suppressed-user-template-content": "Deze versie werd geïmporteerd uit LiquidThreads met een verborgen gebruiker. Het is toegewezen aan de huidige gebruiker.",
"flow-importer-lqt-different-author-signature-template": "Omgezet LQT-bericht met andere ondertekenaar",
- "apihelp-flow+edit-header-example-1": "De beschrijving van [[Talk:Sandbox]] bewerken",
- "apihelp-flow+edit-post-param-postId": "Berichtnummer.",
- "apihelp-flow+edit-post-param-content": "Inhoud voor bericht",
- "apihelp-flow+edit-title-param-content": "Inhoud voor titel.",
- "apihelp-flow+lock-topic-example-1": "[[Topic:S2tycnas4hcucw8w]] sluiten",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Dit bericht werd geplaatst door [[User:{{{authorUser}}}|{{{authorUser}}}]], maar ondertekend als [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Bewerkt",
"flow-edited-by": "Bewerkt door $1",
+ "flow-edited-by-topic-title": "Onderwerptitel bewerkt door $1",
"flow-lqt-redirect-reason": "Oud LiquidThreads-bericht doorverwezen naar nieuw Flow-bericht",
"flow-talk-conversion-move-reason": "$1 wordt omgezet van wikitext-discussiepagina naar Flow",
"flow-talk-conversion-archive-edit-reason": "Omzetten van wikitext-discussiepagina naar Flow",
@@ -411,6 +487,9 @@
"flow-undo-edit-post": "Het bewerken van een bericht",
"flow-undo-edit-content": "Deze bewerking kan ongedaan gemaakt worden.\nHieronder staat de tekst waarin de wijziging ongedaan is gemaakt.\nControleer voor het opslaan of het resultaat gewenst is.",
"flow-undo-edit-failure": "De wijziging kan niet ongedaan gemaakt worden vanwege andere strijdige wijzigingen.",
+ "group-flow-bot": "Flowbots",
+ "group-flow-bot-member": "Flowbot",
+ "grouppage-flow-bot": "Project:Flow bots",
"flow-ve-mention-context-item-label": "Noem gebruiker",
"flow-ve-mention-inspector-title": "Noem gebruiker",
"flow-ve-mention-inspector-remove-label": "Verwijderen",
@@ -420,12 +499,28 @@
"flow-ve-mention-inspector-invalid-user": "De gebruiker \"$1\" is niet geregistreerd.",
"flow-wikitext-editor-help": "Wikitekst $1.",
"flow-wikitext-editor-help-and-preview": "Wikitext $1 en u kunt op elk moment uw bewerking $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|maakt gebruik van markup]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|maakt gebruik van markup]]",
"flow-wikitext-editor-help-preview-the-result": "ter controle bekijken",
"flow-wikitext-switch-editor-tooltip": "Overschakelen naar visuele tekstverwerker",
"flow-ve-switch-editor-tool-title": "Overschakelen naar wikitext",
"flow-mark-revision-patrolled-link-text": "Deze pagina als gecontroleerd markeren",
"flow-mark-revision-patrolled-link-title": "Deze pagina als gecontroleerd markeren",
"flow-mark-diff-patrolled-link-text": "Als gecontroleerd markeren",
- "flow-mark-diff-patrolled-link-title": "Als gecontroleerd markeren"
+ "flow-mark-diff-patrolled-link-title": "Als gecontroleerd markeren",
+ "flow-talk-page-beta-feature-message": "Gebruikersoverlegpagina omzetten naar Flow",
+ "flow-notification-link-text-enabled-on-talkpage": "Overlegpagina van gebruiker {{GENDER:|bekijken}}",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nieuw overlegsysteem op $2",
+ "flow-dialog-cancelconfirm-title": "Weet {{GENDER:|u}} het zeker?",
+ "flow-dialog-cancelconfirm-message": "Weet u zeker dat {{GENDER:|u}} wilt annuleren zonder eerst op te slaan?",
+ "flow-dialog-cancelconfirm-keep": "Doorgaan met bewerken",
+ "flow-dialog-cancelconfirm-discard": "Wijzigingen annuleren",
+ "flow-optin-archive-wikitext": "Wikitekst pagina verplaatst om ruimte te maken voor een discussiebord.",
+ "flow-optin-archive-flow-board": "Discussiebord verplaatst om ruimte te maken voor een wikitekst pagina.",
+ "flow-optin-restore-wikitext": "Gearchiveerde wikitekstpagina herstellen.",
+ "flow-optin-restore-flow-board": "Herstel gearchiveerd discussiebord.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Welkom}} op {{GENDER:$1|uw}} nieuwe gebruikersoverlegpagina",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Uw}} overlegpagina is de plaats waar andere bewerkers contact met {{GENDER:$1|u}} kunnen zoeken. Met Flow is het makkelijker om nieuwe onderwerpen te starten en om de gesprekken bij te houden.",
+ "flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|Uw}} oude discussies terugvinden",
+ "flow-guidedtour-optin-find-old-conversations-description": "Eerdere discussies zijn verplaatst naar het archief.",
+ "flow-guidedtour-optin-feedback": "Geef ons {{GENDER:$1|uw}} terugkoppeling!"
}
diff --git a/Flow/i18n/nn.json b/Flow/i18n/nn.json
new file mode 100644
index 00000000..c8969163
--- /dev/null
+++ b/Flow/i18n/nn.json
@@ -0,0 +1,50 @@
+{
+ "@metadata": {
+ "authors": [
+ "Njardarlogar"
+ ]
+ },
+ "flow-board-header-browse-topics-link": "Bla gjennom emne",
+ "flow-board-header": "Om tavla",
+ "flow-board-collapse-description": "Gøym skildring",
+ "flow-topic-collapse-siderail": "Les med full breidd",
+ "flow-edit-header-link": "Endra skildring",
+ "flow-summary-authored": "Samandrag av $1",
+ "flow-summary-edited": "Samandrag sist {{GENDER:$1|endra}} av $1",
+ "flow-last-modified-by": "Sist {{GENDER:$1|endra}} av $1",
+ "flow-newtopic-title-placeholder": "Nytt emne",
+ "flow-newtopic-content-placeholder": "Skriv ei ny melding på «$1»",
+ "flow-newtopic-header": "Legg til eit nytt emne",
+ "flow-newtopic-save": "Legg til emne",
+ "flow-newtopic-start-placeholder": "Start eit nytt emne",
+ "flow-history-action-hide-post": "løyn",
+ "flow-post-action-view": "Fast lenkje",
+ "flow-post-action-hide-post": "Løyn",
+ "flow-post-action-edit-post": "Endra",
+ "flow-post-action-edit-post-submit": "Lagra endringar",
+ "flow-topic-action-view": "Fast lenkje",
+ "flow-topic-action-edit-title": "Endra overskrift",
+ "flow-topic-action-hide-topic": "Løyn emne",
+ "flow-topic-action-lock-topic": "Merk som løyst",
+ "flow-topic-action-summarize-topic": "Lag samandrag",
+ "flow-topic-action-resummarize-topic": "Endra samandraget av emnet",
+ "flow-history-last4": "Siste 4 timane",
+ "flow-history-week": "Siste veka",
+ "flow-last-modified": "Sist endra kring $1",
+ "flow-moderation-placeholder-hide-post": "{{GENDER:$3|Forklår}} kvifor du løyner dette innlegget.",
+ "flow-moderation-placeholder-hide-topic": "{{GENDER:$3|Forklår}} kvifor du løyner dette emnet.",
+ "flow-topic-first-heading": "Emne på «$1»",
+ "flow-newest-topics": "Nyaste emna",
+ "flow-recent-topics": "Nyleg aktive emne",
+ "flow-edited": "Endra",
+ "flow-ve-mention-context-item-label": "Nemn",
+ "flow-ve-mention-inspector-title": "Nemn",
+ "flow-ve-mention-tool-title": "Nemn ein brukar",
+ "flow-wikitext-editor-help-and-preview": "Wikitekst $1 og du kan $2 når som helst.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|stør formateringsmerke]]",
+ "flow-wikitext-editor-help-preview-the-result": "førehandsvisa resultatet",
+ "flow-dialog-cancelconfirm-title": "Er {{GENDER:|du}} sikker?",
+ "flow-dialog-cancelconfirm-message": "Er {{GENDER:|du}} viss på at du ynskjer å avbryta utan å lagra fyrst?",
+ "flow-dialog-cancelconfirm-keep": "Endra vidare",
+ "flow-dialog-cancelconfirm-discard": "Kast endringar"
+}
diff --git a/Flow/i18n/oc.json b/Flow/i18n/oc.json
index ca1b05ca..b50ce2fe 100644
--- a/Flow/i18n/oc.json
+++ b/Flow/i18n/oc.json
@@ -1,11 +1,12 @@
{
"@metadata": {
"authors": [
- "Cedric31"
+ "Cedric31",
+ "Nnemo",
+ "Nicolas Eynaud"
]
},
- "flow-desc": "Sistèma de gestion del flux de trabalh",
- "flow-talk-taken-over": "Aquesta pagina de discussion es estada remplaçada per un [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal ''Flow board''].",
+ "flow-desc": "Sistèma de discussion",
"log-name-flow": "Jornal de flux d’activitat",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|a suprimit}} una [$4 publicacion] sus « [[$3|$5]] » sus [[$6]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|a restablit}} una [$4 nòta] sus \"[[$3|$5]]\" lo [[$6]]",
@@ -13,9 +14,13 @@
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|a suprimit}} una [$4 publicacion] sus « [[$3|$5]] » sus [[$6]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|a suprimit}} lo subjècte « [[$3|$5]] » sus [[$6]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|a restablit}} lo subjècte « [[$3|$5]] » sus [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|a suprimit}} un [$4 subjècte] sus [[$3]]",
- "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|a suprimit}} un [$4 subjècte] sus [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|a amagat}} lo subjècte « [[$3|$5]] » sus [[$6]]",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|a suprimit}} lo subjècte « [[$3|$5]] » sus [[$6]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|a marcat}} lo subjècte « [[$3|$5]] » coma resolgut sus [[$6]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|a reobèrt}} lo subjècte « [[$3|$5]] » sus [[$6]]",
"flow-user-moderated": "Utilizaire moderat",
+ "flow-board-header-browse-topics-link": "Percórrer los subjèctes",
+ "flow-board-header": "A prepaus d'aqueste flux de discussion",
"flow-edit-header-link": "Modificar la descripcion",
"flow-post-moderated-toggle-hide-show": "Afichar lo comentari {{GENDER:$1|amagat}} per $2",
"flow-post-moderated-toggle-delete-show": "Afichar lo comentari {{GENDER:$1|suprimit}} per $2",
@@ -29,7 +34,7 @@
"flow-delete-post-content": "Aqueste comentari es estat {{GENDER:$1|suprimit}} per $1 ([$2 istoric])",
"flow-delete-title-content": "Lo subjècte es estat {{GENDER:$1|suprimit}} per $1",
"flow-delete-header-content": "{{GENDER:$1|Suprimit}} per $2",
- "flow-suppress-post-content": "Aqueste comentari es estat {{GENDER:$1|suprimit}} per $1",
+ "flow-suppress-post-content": "Aqueste comentari es estat {{GENDER:$1|suprimit}} per $1 ([$2 istoric])",
"flow-suppress-title-content": "Lo subjècte es estat {{GENDER:$1|suprimit}} per $1",
"flow-suppress-header-content": "{{GENDER:$1|Suprimit}} per $2",
"flow-suppress-usertext": "<em>Nom d’utilizaire suprimit</em>",
@@ -42,10 +47,17 @@
"flow-newtopic-content-placeholder": "Mandar un messatge novèl sus « $1 »",
"flow-newtopic-header": "Apondre un subjècte novèl",
"flow-newtopic-save": "Apondre un subjècte",
+ "flow-newtopic-save-anonymously": "Apondre un subjècte d'un biais anonim",
"flow-newtopic-start-placeholder": "Començar un subjècte novèl",
"flow-reply-topic-placeholder": "{{GENDER:$1|Comentar}} « $2 »",
"flow-reply-link": "{{GENDER:$1|Respondre}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|mercejar}}}}",
+ "flow-history-action-suppress-post": "suprimir",
+ "flow-history-action-delete-post": "suprimir",
+ "flow-history-action-hide-post": "amagar",
+ "flow-history-action-restore-post": "restablir",
+ "flow-history-action-lock-topic": "resòlvre",
+ "flow-history-action-unlock-topic": "Tornar dobrir",
"flow-post-edited": "Nòta {{GENDER:$1|modificada}} per $1 $2",
"flow-post-action-view": "Ligam permanent",
"flow-post-action-post-history": "Istoric",
@@ -60,24 +72,27 @@
"flow-topic-action-history": "Istoric",
"flow-topic-action-hide-topic": "Amagar lo subjècte",
"flow-topic-action-delete-topic": "Suprimir lo subjècte",
+ "flow-topic-action-lock-topic": "Marcar coma resolgut",
"flow-topic-action-suppress-topic": "Suprimir lo subjècte",
"flow-topic-action-restore-topic": "Restablir lo subjècte",
- "flow-error-http": "Una error s'es producha en comunicant amb lo servidor.",
- "flow-error-other": "Una error imprevista s'es producha.",
- "flow-error-external": "Una error s'es producha.<br />Lo messatge d'error recebut èra :$1",
- "flow-error-edit-restricted": "Sètz pas autorizat(ada) a modificar aquesta nòta",
- "flow-error-external-multi": "D'errors se son produchas.<br /> $1",
+ "flow-error-http": "Una error s'es produita en comunicant amb lo servidor.",
+ "flow-error-external": "Una error s'es produita. Lo messatge d'error recebut èra : $1",
+ "flow-error-lock-moderated-post": "Podètz pas marcar un subjècte moderat coma resolgut.",
"flow-error-missing-content": "Lo messatge a pas cap de contengut. Un contengut es obligatòri per enregistrar un messatge.",
- "flow-error-missing-summary": "Lo resumit a pas cap de contengut. Un contengut es obligatòri per enregistrar un resumit.",
+ "flow-error-missing-summary": "Vos cal sasir un resumit.",
"flow-error-missing-title": "Lo subjècte a pas cap de títol. Un títol es obligatòri per enregistrar un subjècte.",
"flow-error-parsoid-failure": "Impossible d'analisar lo contengut a causa d'una pana de Parsoid.",
+ "flow-error-protected-unknown-reason": "Desconegut",
"flow-error-missing-replyto": "Cap de paramètre « replyTo » es pas estat provesit. Aqueste paramètre es requesit per l'accion « respondre ».",
- "flow-error-invalid-replyto": "Lo paramètre « replyTo » èra pas valid. Lo messatge especificat es pas estat trobat.",
- "flow-error-delete-failure": "Fracàs de la supression d'aquesta entrada.",
- "flow-error-hide-failure": "L'amagatge d'aqueste element a fracassat.",
"flow-error-missing-postId": "Cap de paramètre « postId » es pas estat provesit. Aqueste paramètre es requesit per manipular un messatge.",
"flow-error-invalid-postId": "Lo paramètre « postId » èra pas valid. Lo messatge especificat ($1) es pas estat trobat.",
- "flow-error-restore-failure": "Fracàs del restabliment d'aquesta entrada.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Podètz pas respondre perque aqueste subjècte es estat amagat.",
+ "flow-error-not-allowed-delete": "Aqueste subjècte es estat suprimit.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Podètz pas respondre perque aqueste subjècte es estat suprimit.",
+ "flow-error-not-allowed-suppress": "Aqueste subjècte es estat suprimit.",
+ "flow-error-default": "Una error s'es produita.",
+ "flow-edit-header-placeholder": "Descriure aqueste flux de discussion",
+ "flow-edit-header-submit": "Enregistrar la descripcion",
"flow-edit-title-submit": "Cambiar lo títol",
"flow-edit-post-submit": "Sometre las modificacions",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|a modificat}} un [$3 comentari] sus « $4 ».",
@@ -90,19 +105,32 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|a amagat}} lo [$4 subjècte] « $6 » (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|a suprimit}} lo [$4 subjècte] « $6 » (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|a suprimit}} lo [$4 subjècte] « $6 » (<em>$5</em>).",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|a marcat}} lo [$4 subjècte] « $6 » coma resolgut (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "marcat coma resolgut",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|a restablit}} lo [$4 subjècte] « $6 » (<em>$5</em>).",
"flow-board-history": "Istoric de « $1 »",
"flow-board-history-empty": "Actualament, aqueste conselh a pas cap d'istoric.",
"flow-topic-history": "Istoric del subjècte « $1 »",
+ "flow-history-day": "Uèi",
"flow-comment-restored": "Comentari restablit",
"flow-comment-deleted": "Comentari suprimit",
"flow-comment-hidden": "Comentari amagat",
"flow-last-modified": "Darrièr cambiament $1",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|a respondut}} sus '''$4'''.",
- "flow-notification-edit": "$1 {{GENDER:$1|a modificat}} una <span class=\"plainlinks\">[$5 nòta]</span> sus « $2 » en [[$3|$4]].",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|a creat}} una \n discussion novèla sus '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|a respondut}} sus <strong>$4</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 a {{GENDER:$1|modificat}} vòstre <span class=\"plainlinks\">[$5 messatge]</span> sus [[$3|$4]].",
+ "notification-header-flow-new-topic-user-talk": "Un novèl subjècte es estat creat sus <strong>vòstra pagina de discussion</strong> : « <strong><bdi>$4</bdi></strong> ».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Un novèl subjècte|$1 novèls subjèctes|100=Mai de 100 novèls subjèctes}} sus <strong>vòstra pagina de discussion</strong>.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Una novèla responsa|$1 novèlas responsas|100=Mai de 100 novèlas responsas}} sus <strong>vòstra pagina de discussion</strong> sus « <strong><bdi>$3</bdi></strong> ».",
+ "notification-header-flow-mention-post": "{{GENDER:$2|$1}} {{GENDER:$4|vos a mencionat|vos a mencionada}} dins « <strong><bdi>$5</bdi></strong> ».",
+ "notification-header-flow-mention-header": "{{GENDER:$2|$1}} {{GENDER:$4|vos a mencionat|vos a mencionada}} dins la descripcion de <strong><bdi>$3</bdi></strong>.",
+ "notification-header-flow-mention-post-summary": "{{GENDER:$2|$1}} {{GENDER:$4|vos a mencionat|vos a mencionada}} dins « <strong><bdi>$5</bdi></strong> ».",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 <bdi>$4</bdi>]</span><br /> {{GENDER:$1|$1}} a creat un novèl subjècte sus <strong><bdi>$3</bdi></strong>.",
"flow-notification-rename": "$1 {{GENDER:$1|a modificat}} lo títol de <span class=\"plainlinks\">[$2 $3]</span> en « $4 » sus [[$5|$6]].",
- "echo-category-title-flow-discussion": "Flux",
+ "flow-notification-mention": "$1 vos a {{GENDER:$5|mencionat|mencionada|mencionat(ada)}} dins son <span class=\"plainlinks\">[$2 messatge]</span> sus « $3 », ligat a « $4 »",
+ "flow-notification-link-text-view-topics": "Veire los subjèctes",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$3|vos}} {{GENDER:$3|a mencionat|a mencionada}} sus $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|vos}} a mencion{{GENDER:$4|at|ada}} dins son messatge sus « $2 », ligat a $3",
+ "echo-category-title-flow-discussion": "Discussion de Flow",
"flow-link-post": "nòta",
"flow-link-topic": "subjècte",
"flow-link-history": "istoric",
@@ -115,6 +143,18 @@
"flow-moderation-confirm-suppress-topic": "Suprimir",
"flow-moderation-confirm-delete-topic": "Suprimir",
"flow-moderation-confirm-hide-topic": "Amagar",
+ "flow-moderation-confirmation-suppress-topic": "Aqueste subjècte es estat amagat.",
+ "flow-moderation-confirmation-delete-topic": "Aqueste subjècte es estat suprimit.",
+ "flow-moderation-confirmation-hide-topic": "Aqueste subjècte es estat amagat.",
+ "right-flow-lock": "Marcar de subjèctes de Flow coma resolguts",
+ "structureddiscussions": "Flow",
+ "flow-special-enableflow-confirmation": "Avètz creat un tablèu Flow sus [[$1]].",
"flow-previous-diff": "← Cambiament precedent",
- "flow-next-diff": "Cambiament seguent →"
+ "flow-next-diff": "Cambiament seguent →",
+ "flow-undo": "anullar",
+ "flow-ve-mention-context-item-label": "Mencionar",
+ "flow-ve-mention-inspector-title": "Mencionar",
+ "flow-wikitext-switch-editor-tooltip": "Bascular cap a l’editor visual",
+ "flow-mark-diff-patrolled-link-text": "Marcar coma relegida",
+ "flow-mark-diff-patrolled-link-title": "Marcar coma relegida"
}
diff --git a/Flow/i18n/om.json b/Flow/i18n/om.json
index 9e72788b..fc17dd94 100644
--- a/Flow/i18n/om.json
+++ b/Flow/i18n/om.json
@@ -6,6 +6,7 @@
},
"flow-topic-action-resummarize-topic": "Cuunfaa mataduree gulaali",
"flow-error-not-allowed-suppress": "Matadureen kun haqameera.",
+ "flow-notification-link-text-view-topics": "Matadureewwan ilaali",
"flow-previous-diff": "← Gulaala duraanii",
"flow-next-diff": "Gulaala haaraa →"
}
diff --git a/Flow/i18n/or.json b/Flow/i18n/or.json
index 3a9ad6b6..c581e942 100644
--- a/Flow/i18n/or.json
+++ b/Flow/i18n/or.json
@@ -2,16 +2,39 @@
"@metadata": {
"authors": [
"Nistha.aslp",
- "Psubhashish"
+ "Psubhashish",
+ "MKar",
+ "ଶିତିକଣ୍ଠ ଦାଶ"
]
},
+ "enablestructureddiscussions": "\"ଆଳାପ\" (Flow) କୁ ସକ୍ରିୟ କରନ୍ତୁ",
+ "flow-talk-taken-over-comment": "/* ଏହି ପୃଷ୍ଠାଟି 'ଆଳାପ' ଆଲୋଚନାକୁ ପରିବର୍ତ୍ତନ କରାଗଲା */",
+ "log-name-flow": "'ଆଳାପ' କାର୍ଯ୍ୟକଳାପ ଲଗ",
+ "flow-topic-moderated-reason-prefix": "କାରଣ:",
+ "flow-post-actions": "କାର୍ଯ୍ୟକ୍ରମ",
+ "flow-topic-actions": "କାର୍ଯ୍ୟକ୍ରମ",
+ "flow-cancel": "ନାକଚ",
"flow-skip-summary": "ସାରାଂଶ ବାଦଦିଅନ୍ତୁ",
"flow-edit-summary-placeholder": "ଏହି ଆଲୋଚନାର ଫଳାଫଳ ସଂକ୍ଷେପରେ ଜଣାନ୍ତୁ",
+ "flow-summary-authored": "$1ଙ୍କ ଲିଖିତ ସାରାଂଶ",
+ "flow-newtopic-title-placeholder": "ନୂଆ ବିଷୟ",
+ "flow-newtopic-save": "ନୂଆ ଯୋଡ଼ନ୍ତୁ",
+ "flow-newtopic-start-placeholder": "ଗୋଟିଏ ନୂଆ ବିଷୟ ଆରମ୍ଭ କରନ୍ତୁ",
+ "flow-history-action-delete-post": "ଲିଭାନ୍ତୁ",
+ "flow-history-action-hide-post": "ଲୁଚାନ୍ତୁ",
"flow-history-action-lock-topic": "ସମାଧାନ କରନ୍ତୁ",
"flow-history-action-unlock-topic": "ପୁଣିଥରେ ଖୋଲନ୍ତୁ",
+ "flow-post-action-delete-post": "ଲିଭାଇଦେବେ",
+ "flow-post-action-hide-post": "ଲୁଚାନ୍ତୁ",
+ "flow-post-action-edit-post": "ସମ୍ପାଦନା (Edit)",
+ "flow-post-action-edit-post-submit": "ବଦଳଗୁଡ଼ିକୁ ସାଇତିବେ",
+ "flow-topic-action-history": "ଇତିହାସ",
"flow-topic-action-lock-topic": "ସମାଧାନ ହୋଇଛି ବୋଲି ଚିହ୍ନିତ କରନ୍ତୁ",
"flow-topic-action-unlock-topic": "ପ୍ରସଙ୍ଗଟି ଆଉଥରେ ଖୋଲନ୍ତୁ",
+ "flow-topic-action-summarize-topic": "ସାରକଥା",
"flow-topic-action-update-topic-summary": "ସାରାଂଶ ଅପଡେଟ କରନ୍ତୁ",
+ "flow-topic-action-undo-moderation": "ପଛକୁ ଫେରିବା",
+ "flow-topic-action-watchlist-remove": "ଯୋଗାଯୋଗରୁ ବାହାରିବା",
"flow-rev-message-lock-topic-reason": "ସମାଧାନ ହୋଇଛି ବୋଲି ଚିହ୍ନିତ କରନ୍ତୁ",
"flow-rev-message-restore-topic-reason": "ପୁଣିଥରେ ଖୋଲାହେଲା",
"flow-show-comments-title": "{{PLURAL:$1|ମତାମତ ଦେଖାନ୍ତୁ|ମତାମତସବୁ ଲୁଚାନ୍ତୁ}}",
diff --git a/Flow/i18n/pa.json b/Flow/i18n/pa.json
index 63cc211b..dbf753d6 100644
--- a/Flow/i18n/pa.json
+++ b/Flow/i18n/pa.json
@@ -2,11 +2,19 @@
"@metadata": {
"authors": [
"Babanwalia",
- "Satdeep gill"
+ "Satdeep gill",
+ "ਪ੍ਰਚਾਰਕ",
+ "Jimidar",
+ "Tow"
]
},
- "enableflow": "ਫਲੋ ਲਾਗੂ ਕਰੋ",
+ "enablestructureddiscussions": "ਫਲੋ ਲਾਗੂ ਕਰੋ",
+ "flow-board-description-can-not-edit": "ਸੰਪਾਦਤ ਹੋਣ ਯੋਗ ਨਹੀਂ",
+ "flow-board-collapse-description": "ਵੇਰਵਾ ਲੁਕਾਓ",
+ "flow-board-expand-description": "ਵੇਰਵਾ ਵਿਖਾਓ",
+ "flow-edit-header-link": "ਵੇਰਵਾ ਸੋਧੋ",
"flow-topic-moderated-reason-prefix": "ਕਾਰਨ:",
+ "flow-cancel": "ਰੱਦ ਕਰੋ",
"flow-newtopic-save": "ਵਿਸ਼ਾ ਜੋੜੋ",
"flow-newtopic-start-placeholder": "ਨਵਾਂ ਵਿਸ਼ਾ ਸ਼ੁਰੂ ਕਰੋ",
"flow-newtopic-first-heading": "$1 ਉੱਤੇ ਨਵਾਂ ਵਿਸ਼ਾ ਸ਼ੁਰੂ ਕਰੋ",
@@ -14,11 +22,17 @@
"flow-history-action-delete-post": "ਮਿਟਾਓ",
"flow-history-action-hide-post": "ਓਹਲੇ",
"flow-history-action-restore-post": "ਮੁੜ-ਸਟੋਰ",
+ "flow-post-action-delete-post": "ਮਿਟਾਓ",
+ "flow-post-action-hide-post": "ਲੁਕਾਓ",
"flow-post-action-edit-post": "ਸੋਧੋ",
+ "flow-post-action-edit-post-submit": "ਤਬਦੀਲੀਆਂ ਸਾਂਭੋ",
+ "flow-topic-action-view": "ਪੱਕੀ ਕੜੀ",
+ "flow-topic-action-watchlist": "ਨਿਗਰਾਨ-ਸੂਚੀ",
"flow-topic-action-history": "ਅਤੀਤ",
"flow-topic-action-summarize-topic": "ਸਾਰ ਕੱਢੋ",
"flow-topic-action-undo-moderation": "ਅਣਕੀਤਾ ਕਰੋ",
- "flow-summarize-topic-submit": "ਸਾਰ ਕੱਢੋ",
+ "flow-error-protected-unknown-reason": "ਅਣਪਛਾਤਾ",
+ "flow-notification-link-text-view-topics": "ਵਿਸ਼ੇ ਦੇਖੋ",
"flow-notification-reply-email-subject": "$3 'ਤੇ $2",
"flow-moderation-confirmation-suppress-topic": "ਇਹ ਵਿਸ਼ਾ ਦਬਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।",
"flow-moderation-confirmation-delete-topic": "ਇਹ ਵਿਸ਼ਾ ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।",
@@ -28,7 +42,7 @@
"flow-topic-html-title": "$2 'ਤੇ $1",
"flow-topic-count": "ਵਿਸ਼ਾ ($1)",
"flow-newest-topics": "ਸਭ ਤੋਂ ਨਵੇਂ ਵਿਸ਼ੇ",
- "flow": "ਫਲੋ",
+ "structureddiscussions": "ਫਲੋ",
"flow-special-type": "ਕਿਸਮ",
"flow-undo-your-text": "ਤੁਹਾਡੀ ਲਿਖਤ",
"group-flow-bot": "ਫਲੋ ਬੌਟਸ",
diff --git a/Flow/i18n/pl.json b/Flow/i18n/pl.json
index 4fd0aa4f..50f8ca02 100644
--- a/Flow/i18n/pl.json
+++ b/Flow/i18n/pl.json
@@ -18,24 +18,53 @@
"Devwebtel",
"Mbkgacek",
"Halibutt",
- "The Polish"
+ "The Polish",
+ "Nnemo",
+ "Peter Bowman",
+ "Quiddity",
+ "Macofe",
+ "Sethakill"
]
},
- "enableflow": "Włącz Flow",
- "flow-desc": "System zarządzania cyklem pracy",
+ "enablestructureddiscussions": "Włącz Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Zatrzymaj}} śledzenie nowej aktywności w „$1”",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Nie {{GENDER:$3|obserwujesz}} już strony „$1”",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Nie będzie to miało wpływu na indywidualne tematy, które {{GENDER:$3|obserwujesz}}. Możesz włączyć obserwowanie [$2 tej strony] w dowolnym momencie.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Przestań}} śledzić ten wątek",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Przestałeś|Przestałaś}} śledzić wątek „$1”",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Możesz}} obserwować [$2 ten wątek] w dowolnym momencie.",
+ "flow-desc": "System dyskusji",
+ "flow-talk-taken-over-comment": "/* Ta strona została przekształcona na forum dyskusyjne Flow */",
"log-name-flow": "Rejestr aktywności Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|usunął|usunęła}} [$4 post] z „[[$3|$5]]” na [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|usunął|usunęła}} post w wątku w [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|przywrócił|przywróciła}} [$4 post] w „[[$3|$5]]” na [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|przywrócił|przywróciła}} post w wątku na [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|ukrył|ukryła}} [$4 post] z „[[$3|$5]]” na [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|ukrył|ukryła}} post w wątku w [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|usunął|usunęła}} [$4 post] z „[[$3|$5]]” na [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|usunął|usunęła}} post w temacie w [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|usunął|usunęła}} wątek „[[$3|$5]]” na [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|usunął|usunęła}} temat w [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|przywrócił|przywróciła}} wątek „[[$3|$5]]” na [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|przywrócił|przywróciła}} wątek w [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ukrył|ukryła}} wątek „[[$3|$5]]” na [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|ukrył|ukryła}} temat w [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|usunął|usunęła}} wątek „[[$3|$5]]” na [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|usunął|usunęła}} wątek w [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|zaznaczył|zaznaczyła}} wątek \"[[$3|$5]]\" jako rozwiązany na stronie [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|oznaczył|oznaczyła}} wątek jako rozwiązany w [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 ponownie {{GENDER:$2|otworzył|otworzyła}} wątek \"[[$3|$5]]\" na stronie [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 ponownie {{GENDER:$2|otworzył|otworzyła}} wątek w [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] na [[$3]] zaimportowano z LiquidThreads do Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "ID strony dyskusji z Flow",
+ "abusefilter-edit-builder-vars-board-namespace": "Przestrzeń nazw strony dyskusji z Flow",
+ "abusefilter-edit-builder-vars-board-text": "Tytuł strony dyskusji z Flow",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Pełny tytuł strony dyskusji z Flow",
"flow-user-moderated": "Ukryta nazwa użytkownika",
"flow-board-header-browse-topics-link": "Wyszukaj wątki",
"flow-board-header": "O tej stronie",
+ "flow-board-description-can-not-edit": "Nie można edytować",
"flow-board-collapse-description": "Ukryj opis",
"flow-board-expand-description": "Pokaż opis",
"flow-topic-collapse-siderail": "Czytaj w pełnej szerokości",
@@ -61,17 +90,18 @@
"flow-post-actions": "Akcje",
"flow-topic-actions": "Akcje",
"flow-cancel": "Anuluj",
- "flow-skip-summary": "Pomiń podsumowanie",
+ "flow-skip-summary": "Pomiń",
"flow-edit-summary-placeholder": "Opisz krótko wynik tej dyskusji",
"flow-summary-authored": "Streszczenie autorstwa $1",
"flow-summary-edited": "Streszczenie ostatnio {{GENDER:$1|edytował|edytowała}} $1",
"flow-show-change": "Pokaż zmiany",
"flow-last-modified-by": "Ostatnio {{GENDER:$1|edytowane}} przez $1",
- "flow-stub-post-content": "''Ze względu na błąd techniczny ten post nie mógł zostać przywrócony.''",
+ "flow-stub-post-content": "<em>Ze względu na błąd techniczny ten post nie mógł zostać przywrócony.<em>",
"flow-newtopic-title-placeholder": "Nowy wątek",
"flow-newtopic-content-placeholder": "Napisz nowy post na „$1”",
"flow-newtopic-header": "Dodaj nowy wątek",
"flow-newtopic-save": "Dodaj wątek",
+ "flow-newtopic-save-anonymously": "Dodaj wątek (anonimowo)",
"flow-newtopic-start-placeholder": "Rozpocznij nowy wątek",
"flow-newtopic-first-heading": "Rozpocznij nowy wątek w $1",
"flow-summarize-topic-placeholder": "Streść krótko tę dyskusję",
@@ -98,6 +128,7 @@
"flow-post-action-hide-post": "Ukryj",
"flow-post-action-edit-post": "Edytuj",
"flow-post-action-edit-post-submit": "Zapisz zmiany",
+ "flow-post-action-edit-post-submit-anonymously": "Zapisz zmiany (anonimowo)",
"flow-post-action-unsuppress-post": "Odkryj (oversight)",
"flow-post-action-undelete-post": "Odtwórz",
"flow-post-action-unhide-post": "Nie ukrywaj",
@@ -126,26 +157,27 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1|Otrzymasz}} powiadomienie, kiedy pojawi się nowy wątek na tej stronie.",
"flow-topic-action-watchlist-add": "Obserwuj ten wątek",
"flow-topic-action-watchlist-remove": "Usuń z listy obserwowanych",
- "flow-error-allowcreation-no-usedb": "allowCreation wymaga, żeby <var>$wgContentHandlerUseDB</var> miał wartość <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Strona już istnieje, a nie powinna",
+ "flow-error-allowcreation-no-usedb": "Do włączania Flow na określonych stronach wymagane jest, żeby zmienna <var>$wgContentHandlerUseDB</var> miała wartość <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Istnieje już strona w miejscu docelowym, więc forum dyskusyjne Flow nie może zostać tam przeniesione.",
"flow-error-allowcreation-flow-create-board": "Użytkownik nie posiada uprawnienia „{{int:right-flow-create-board}}”",
+ "flow-error-can-not-edit-logged-out": "Nie masz możliwości uczestnictwa. Możesz spróbować się zalogować.",
+ "flow-error-can-not-edit-logged-in": "Nie masz możliwości uczestnictwa, ponieważ nie posiadasz wymaganych uprawnień.",
"flow-error-http": "Wystąpił błąd w czasie łączenia z serwerem.",
- "flow-error-other": "Wystąpił nieoczekiwany błąd.",
- "flow-error-external": "Wystąpił błąd.<br />Otrzymano następujący komunikat o błędzie: $1",
+ "flow-error-external": "Wystąpił błąd. Otrzymano następujący komunikat o błędzie: $1",
"flow-error-topic-is-locked": "Ten wątek oznaczono jako załatwiony, więc dodawanie komentarzy jest niemożliwe.",
"flow-error-lock-moderated-post": "Nie możesz oznaczyć moderowanego postu jako załatwiony.",
- "flow-error-external-multi": "Wystąpiły błędy.<br />$1",
"flow-error-missing-content": "Post nie ma treści. Aby zapisać wiadomość, wymagana jest treść.",
"flow-error-missing-summary": "Należy wpisać streszczenie.",
"flow-error-missing-title": "Wątek nie ma tytułu. Aby zapisać wątek, wymagany jest tytuł.",
- "flow-error-parsoid-failure": "Nie można wykonać analizy zawartości z powodu awarii Parsoida.",
+ "flow-error-parsoid-failure": "Nie można przesłać zawartości: Błąd kontaktu z serwerem w celu konwersji pomiędzy wikikodem a HTML. Proszę sprawdzić swoje połączenie z Internetem lub spróbować ponownie później jeżeli problem nadal występuje. Jeżeli nadal widzisz ten błąd, proszę zgłosić informację o nim",
+ "flow-error-protected-autoconfirmed-logged-in": "To forum jest zabezpieczone. Mogą w nim uczestniczyć tylko użytkownicy automatycznie zatwierdzeni. Powód: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "To forum jest zabezpieczone. Mogą w nim uczestniczyć tylko zalogowani i automatycznie zatwierdzeni użytkownicy. Powód: $1",
+ "flow-error-protected-sysop-logged-in": "To forum jest zabezpieczone. Tylko użytkownicy z uprawnieniami administratora mogą w nim uczestniczyć. Powód: $1",
+ "flow-error-protected-sysop-logged-out": "To forum jest zabezpieczone. Tylko zalogowani użytkownicy z uprawnieniami administratora mogą w nim uczestniczyć. Powód: $1",
+ "flow-error-protected-unknown-reason": "Nieznany",
"flow-error-missing-replyto": "Nie podano wartości „odpowiedz na”. Ta wartość jest wymagana do wykonania akcji „odpowiedz”.",
- "flow-error-invalid-replyto": "Wartość „odpowiedz na” jest nieprawidłowa. Nie udało się znaleźć podanego posta.",
- "flow-error-delete-failure": "Nie udało się usunąć tego elementu.",
- "flow-error-hide-failure": "Nie udało się ukryć tego elementu.",
"flow-error-missing-postId": "Nie podano wartości „postId”. Ta wartość jest wymagana do zmieniania posta.",
"flow-error-invalid-postId": "Wartość „postId” jest nieprawidłowa. Nie udało się znaleźć podanego ($1) posta.",
- "flow-error-restore-failure": "Nie udało się przywrócić tego elementu.",
"flow-error-invalid-moderation-state": "Podano nieprawidłową wartość parametru 'moderationState' do API Flow.",
"flow-error-invalid-moderation-reason": "Proszę podać powód moderacji.",
"flow-error-not-allowed": "Nie masz uprawnień do wykonania tej akcji.",
@@ -171,6 +203,7 @@
"flow-error-default": "Wystąpił błąd.",
"flow-error-invalid-input": "Podano nieprawidłową wartość w celu załadowania Flow.",
"flow-error-invalid-title": "Podano nieprawidłowy tytuł strony.",
+ "flow-error-invalid-parameter": "Brak lub nieprawidłowy parametr wywołania metody",
"flow-error-fail-load-history": "Nie udało się załadować historii strony.",
"flow-error-missing-revision": "Nie udało się znaleźć wersji w celu załadowania Flow.",
"flow-error-fail-commit": "Nie udało się zapisać zawartości.",
@@ -178,6 +211,7 @@
"flow-error-revision-comparison": "Porównanie wersji można zrobić tylko między dwiema edycjami tego samego postu.",
"flow-error-missing-topic-title": "Nie udało się znaleźć tytułu wątku w tym cyklu pracy.",
"flow-error-missing-metadata": "Nie udało się znaleźć odpowiednich metadanych tej wersji.",
+ "flow-error-different-page": "System dyskusji Flow nie jest powiązany z tę stroną.",
"flow-error-fail-load-data": "Nie udało się pobrać wymaganych danych.",
"flow-error-invalid-workflow": "Nie udało się znaleźć szukanego cyklu pracy.",
"flow-error-process-data": "Wystąpił błąd w czasie przetwarzania danych w zapytaniu.",
@@ -187,17 +221,19 @@
"flow-error-no-commit": "Nie udało się zapisać tej akcji.",
"flow-error-content-too-long": "Treść jest zbyt duża. Po rozbudowie treść jest ograniczona do $1 {{PLURAL:$1|bajta|bajtów}}.",
"flow-error-move-topic": "Przenoszenie wątku nie jest jeszcze obsługiwane.",
- "flow-error-move-no-create-permissions": "Uprawnienie „{{int:right-flow-create-board}}” jest wymagane do przenoszenia stron Flow.",
"flow-error-invalid-topic-uuid-title": "Niepoprawny tytuł",
"flow-error-invalid-topic-uuid": "Podana nazwa strony jest nieprawidłowa. Strony w przestrzeni nazw Wątek są tworzone automatycznie we Flow.",
"flow-error-unknown-workflow-id-title": "Nieznany wątek",
"flow-error-unknown-workflow-id": "Szukany wątek nie istnieje.",
"flow-error-search": "Nie udało nam się zakończyć wyszukiwania z powodu przejściowego problemu. Proszę spróbować później.",
+ "flow-error-invalid-undelete": "Ta strona nie może zostać odtworzona, ponieważ aktualnie w jej miejscu znajduje się forum dyskusyjne.",
"flow-edit-header-placeholder": "Opisz tę stronę dyskusji",
"flow-edit-header-submit": "Zapisz opis",
+ "flow-edit-header-submit-anonymously": "Zapisz opis (anonimowo)",
"flow-edit-title-submit": "Zmień tytuł",
"flow-edit-title-submit-anonymously": "Zmień tytuł anonimowo",
"flow-edit-post-submit": "Zapisz zmiany",
+ "flow-edit-post-submit-anonymously": "Zapisz zmiany (anonimowo)",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|zmienił|zmieniła}} [$3 komentarz] w temacie „$4”",
"flow-rev-message-edit-post-recentchanges-summary": "$2 {{GENDER:$2|edytował|edytowała}} post",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|skomentował|skomentowała}}] „$4” (<em>$5</em>)",
@@ -216,7 +252,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ukrył|ukryła}} [$4 wątek] „$6” (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|usunął|usunęła}} [$4 wątek] „$6” (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|ukrył|ukryła}} [$4 wątek] „$6” (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|oznaczył|oznaczyła}} [$4 wątek] $6 jako załatwiony (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|oznaczył|oznaczyła|oznaczył(a)}} [$4 wątek] „$6” jako załatwiony (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "oznaczone jako załatwione",
"flow-rev-message-restore-topic-reason": "Otworzony na nowo",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|przywrócił|przywróciła}} [$4 wątek] „$6” (<em>$5</em>)",
@@ -239,31 +275,73 @@
"flow-comment-moderated": "Komentarz moderowany",
"flow-last-modified": "Ostatnio zmieniano około $1",
"flow-workflow": "cykl pracy",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|odpowiedział|odpowiedziała}} na '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i $5 {{PLURAL:$6|inny|inni|innych}} {{PLURAL:$6|{{GENDER:$1|odpowiedział|odpowiedziała}}|odpowiedzieli}} na '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|odpowiedział|odpowiedziała|odpowiedział(a)}} na <strong>$4</strong>..",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i {{PLURAL:$5|jeden inny|$5 innych|100=99+ innych}} {{PLURAL:$5|{{GENDER:$1|odpowiedział|odpowiedziała}}|odpowiedzieli}} na '''$3'''.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|edytował|edytowała}} twój <span class=\"plainlinks\">[$5 post]</span> na [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 i $5 {{PLURAL:$6|inny|inni|innych}} {{PLURAL:$5|{{GENDER:$1|edytował|edytowała}}|edytowali}} <span class=\"plainlinks\">[post $4]</span> w „$2” na $3.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|utworzył|utworzyła}} nowy wątek na stronie '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nowy wątek|$1 nowe wątki|$1 nowych wątków|250=250+ nowych wątków}} na '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 i {{PLURAL:$5|jeden inny|$5 innych|100=99+ innych}} {{PLURAL:$5|{{GENDER:$1|edytował|edytowała}}|edytowali}} <span class=\"plainlinks\">[$4 post]</span> w „$2” na $3.",
+ "notification-header-flow-new-topic-v2": "Utworzono nowy wątek w <strong>$3</strong>: <bdi>„<strong>$4</strong>”</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Jeden nowy wątek|$1 nowe wątki|$1 nowych wątków|100=Ponad 99 nowych wątków}} na stronie <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Na <strong>stronie twojej dyskusji</strong> został utworzony nowy wątek: „<strong>$4</strong>”.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Jeden nowy wątek|$1 nowe wątki|$1 nowych wątków|100=Ponad 99 nowych wątków}} na <strong>stronie twojej dyskusji</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|odpowiedział|odpowiedziała|odpowiedział(a)}} w wątku „<strong>$4</strong>”.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Jeden nowa odpowiedź|$1 nowe odpowiedzi|$1 nowych odpowiedzi|100=Ponad 99 nowych odpowiedzi}} w wątku „<strong>$3</strong>”.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|odpowiedział|odpowiedziała}} na <strong>Twojej stronie dyskusji</strong> w wątku \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Jeden nowa odpowiedź|$1 nowe odpowiedzi|$1 nowych odpowiedzi|100=Ponad 99 nowych odpowiedzi}} na <strong>stronie twojej dyskusji</strong> w wątku „<strong>$3</strong>”.",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Twoja}} wiadomość w wątku \"<strong>$1</strong>\" została zmieniona.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Twoja}} wiadomość w wątku \"<strong>$1</strong>\" była kilka razy zmieniana.",
+ "notification-header-flow-post-edited-user-talk": "Wiadomość w wątku „<strong>$1</strong>” została zmieniona na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Wiadomość w wątku „<strong>$1</strong>” była wielokrotnie zmieniana na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Wątek „<strong>$1</strong>” został zmieniony na „<strong>$2</strong>”.",
+ "notification-header-flow-topic-renamed-user-talk": "Na <strong>stronie {{GENDER:$3|twojej}} dyskusji</strong> została zmieniona nazwa wątku z „<strong>$1</strong>” na „<strong>$2</strong>”.",
+ "notification-header-flow-summary-edited": "Podsumowanie wątku „<strong>$1</strong>” zostało zmienione.",
+ "notification-header-flow-summary-edited-first": "Wątek „<strong>$1</strong>” został podsumowany.",
+ "notification-bundle-header-flow-summary-edited": "Podsumowanie wątku „<strong>$1</strong>” zostało zmienione kilka razy.",
+ "notification-header-flow-summary-edited-user-talk": "Podsumowanie wątku „<strong>$1</strong>” zostało zmienione na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Wątek „<strong>$1</strong>” został podsumowany na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Podsumowanie wątku „<strong>$1</strong>” było wielokrotnie zmieniane na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|zmienił|zmieniła|zmienił(a)}} podsumowanie w wątku $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|zmienił|zmieniła|zmienił(a)}} podsumowanie w wątku $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 oraz {{PLURAL:$3|jedne inny|$3 innych|100=99+ innych}} {{PLURAL:$3|{{GENDER:$1|zaktualizował|zaktualizowała}}|zaktualizowało}} streszczenie w $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$4|tobie}} w wątku „<strong>$5</strong>”.",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} {{GENDER:$4|o tobie}} w opisie <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|wspomniał|wspomniała|wspomniał(a)}} o {{GENDER:$4|tobie}} w wątku „<strong>$5</strong>”.",
+ "notification-header-flow-enabled-on-talkpage": "Nowy system dyskusji został włączony dla <strong>{{GENDER:$2|twojej}} strony dyskusji użytkownika</strong>.",
+ "notification-header-flow-description-edited": "Opis <strong>$1</strong> został zmieniony.",
+ "notification-header-flow-description-edited-user-talk": "Został zmieniony opis na <strong>{{GENDER:$2|twojej}} stronie dyskusji</strong>.",
+ "notification-bundle-header-flow-description-edited": "Opis <strong>$1</strong> był edytowany kilka razy.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Edytowano wielokrotnie opis na <strong>{{GENDER:$2|Twojej}} stronie dyskusji</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Zobacz}} stronę",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|zmienił|zmieniła}} opis na stronie $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|zmienił|zmieniła}} opis na stronie $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 i {{PLURAL:$3|jeden inny|$3 innych|100=99+ innych}} {{PLURAL:$3|{{GENDER:$1|edytował|edytowała}}|edytowało}} opis na $2",
+ "notification-header-flow-topic-resolved": "Wątek \"<strong>$1</strong>\" został rozwiązany.",
+ "notification-header-flow-topic-reopened": "Wątek „<strong>$1</strong>” został ponownie otwarty.",
+ "notification-header-flow-topic-resolved-user-talk": "Wątek \"<strong>$1</strong>\" został rozwiązany na <strong>Twojej stronie dyskusji</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Wątek „<strong>$1</strong>” został otwarty ponownie na <strong>Twojej stronie dyskusji</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Wątek „<strong>$2</strong>” został rozwiązany.",
+ "notification-email-batch-body-flow-topic-resolved": "Wątek „<strong>$2</strong>” został rozwiązany.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|utworzył|utworzyła|utworzył(a)}} nowy wątek na stronie <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Jeden nowy wątek|$1 nowe wątki|$1 nowych wątków|100=99+ nowych wątków}} na <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|zmienił|zmieniła}} tytuł <span class=\"plainlinks\">[$2 $3]</span> na „$4” na [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|wspomniał|wspomniała}} o {{GENDER:$5|tobie}} w {{GENDER:$1|swoim}} <span class=\"plainlinks\">[$2 poście]</span> w temacie „$3” na „$4”.",
"flow-notification-link-text-view-post": "Pokaż post",
"flow-notification-link-text-view-topic": "Pokaż wątek",
+ "flow-notification-link-text-view-topics": "Pokaż wątki",
"flow-notification-reply-email-subject": "$2 w $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|odpowiedział|odpowiedziała}} na „$2” na $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 i $4 {{PLURAL:$5|inny|inni|innych}} {{PLURAL:$5|{{GENDER:$1|odpowiedział|odpowiedziała}}|odpowiedzieli}} na „$2” na $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 i {{PLURAL:$4|jeden inny|$4 innych|100=99+ innych}} {{PLURAL:$4|{{GENDER:$1|odpowiedział|odpowiedziała}}|odpowiedzieli}} w wątku „$2” na $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|wspomniał|wspomniała}} o {{GENDER:$3|tobie}} w $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|wspomniał|wspomniała}} o {{GENDER:$4|Tobie}} w {{GENDER:$1|swoim}} poście w wątku „$2” na stronie $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|edytował|edytowała}} post",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|edytował|edytowała}} post w „$2” na $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 i $4 {{PLURAL:$5|inny użytkownik|inni|innych}} {{GENDER:$1|edytował|edytowała|edytowali}} post w „$2” na $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 i {{PLURAL:$4|jedn inny|$4 inni|100=99+ innych}} {{GENDER:$1|edytował|edytowała|edytowali}} post w „$2” na $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|zmienił|zmieniła}} nazwę twojego wątku",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|zmienił|zmieniła}} nazwę twojego wątku na $4 z „$2” na „$3”",
- "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|utworzył|utworzyła}} nowy wątek na $2",
+ "flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|utworzył|utworzyła|utworzył(a)}} nowy wątek na stronie $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|utworzył|utworzyła}} nowy wątek o tytule „$2” na $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nowy wątek|$1 nowe wątki|$1 nowych wątków|250=250+ nowych wątków}} na $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Powiadom mnie, kiedy na Flow nastąpi akcja dotycząca mnie.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Jeden nowy wątek|$1 nowe wątki|$1 nowych wątków|250=Ponad 250 nowych wątków}} na stronie $2",
+ "echo-category-title-flow-discussion": "Dyskusja Flow",
+ "echo-pref-tooltip-flow-discussion": "Powiadom mnie o aktywności w śledzonych przeze mnie wątkach i na stronach.",
"flow-link-post": "wpis",
"flow-link-topic": "wątek",
"flow-link-history": "historia",
@@ -295,18 +373,18 @@
"flow-moderation-confirm-unsuppress-topic": "Odkryj (oversight)",
"flow-moderation-confirm-undelete-topic": "Odtwórz",
"flow-moderation-confirm-unhide-topic": "Nie ukrywaj",
- "flow-moderation-confirmation-suppress-post": "Post został pomyślnie ukryty. {{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
- "flow-moderation-confirmation-delete-post": "Post został pomyślnie usunięty. {{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
- "flow-moderation-confirmation-hide-post": "Post został pomyślnie ukryty. {{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
- "flow-moderation-confirmation-unsuppress-post": "Pomyślnie odkryto powyższy post.",
- "flow-moderation-confirmation-undelete-post": "Pomyślnie odtworzono powyższy post.",
- "flow-moderation-confirmation-unhide-post": "Pomyślnie odkryto powyższy post.",
+ "flow-moderation-confirmation-suppress-post": "Post został ukryty.\n{{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
+ "flow-moderation-confirmation-delete-post": "Post został usunięty.\n{{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
+ "flow-moderation-confirmation-hide-post": "Post został ukryty.\n{{GENDER:$2|Rozważ}} wysłanie wiadomości użytkownikowi $1.",
+ "flow-moderation-confirmation-unsuppress-post": "Odkryto powyższy post.",
+ "flow-moderation-confirmation-undelete-post": "Odtworzono powyższy post.",
+ "flow-moderation-confirmation-unhide-post": "Odkryto powyższy post.",
"flow-moderation-confirmation-suppress-topic": "Ten wątek został ukryty (oversight).",
"flow-moderation-confirmation-delete-topic": "Ten wątek został usunięty.",
"flow-moderation-confirmation-hide-topic": "Ten wątek został ukryty.",
- "flow-moderation-confirmation-unsuppress-topic": "Pomyślnie odkryto ten wątek.",
- "flow-moderation-confirmation-undelete-topic": "Pomyślnie odtworzono ten wątek.",
- "flow-moderation-confirmation-unhide-topic": "Pomyślnie odkryto ten wątek.",
+ "flow-moderation-confirmation-unsuppress-topic": "Odkryto ten wątek.",
+ "flow-moderation-confirmation-undelete-topic": "Odtworzono ten wątek.",
+ "flow-moderation-confirmation-unhide-topic": "Odkryto ten wątek.",
"flow-moderation-title-suppress-topic": "Ukryć wątek? (oversight)",
"flow-moderation-title-delete-topic": "Usunąć wątek?",
"flow-moderation-title-hide-topic": "Ukryć wątek?",
@@ -321,15 +399,15 @@
"flow-moderation-placeholder-unhide-topic": "{{GENDER:$3|Podaj powód}} odkrywania tego wątku.",
"flow-topic-permalink-warning": "Ten wątek rozpoczęto na [$2 $1]",
"flow-topic-permalink-warning-user-board": "Ten wątek rozpoczęto [na stronie $2 {{GENDER:$1|$1}}]",
- "flow-revision-permalink-warning-post": "To jest bezpośredni link do pojedynczej wersji tego posta. Wersja jest z $1. Możesz [$5 porównać różnice z poprzednią wersją] lub zobaczyć inne edycje na [$4 historii strony].",
- "flow-revision-permalink-warning-post-first": "To jest bezpośredni link do pierwszej wersji tego posta. Możesz zobaczyć późniejsze wersje na [$4 historii strony].",
+ "flow-revision-permalink-warning-post": "To jest bezpośredni link do pojedynczej wersji tego postu. Wersja jest z $1. Możesz [$5 porównać różnice z poprzednią wersją] lub zobaczyć inne edycje w [$4 historii strony].",
+ "flow-revision-permalink-warning-post-first": "To jest bezpośredni link do pierwszej wersji tego posta.\nMożesz zobaczyć późniejsze wersje na [$4 stronie historii postu].",
"flow-revision-permalink-warning-postsummary": "To jest bezpośredni link do pojedynczej wersji streszczenia tego posta. Wersja jest z $1. Możesz [$5 porównać różnice z poprzednią wersją] lub zobaczyć inne edycje na [$4 historii strony].",
"flow-revision-permalink-warning-postsummary-first": "To jest bezpośredni link do pierwszej wersji streszczenia tego posta. Możesz zobaczyć późniejsze wersje na [$4 historii strony].",
"flow-revision-permalink-warning-header": "To jest link do pojedynczej wersji opisu.\nTa wersja jest z $1. Możesz zobaczyć [$3 różnice od poprzedniej wersji] lub zobaczyć inne wersje na [$2 stronie historii].",
"flow-revision-permalink-warning-header-first": "To jest link do pierwszej wersji opisu.\nMożesz zobaczyć późniejsze wersje na [$2 stronie historii].",
"flow-compare-revisions-revision-header": "Wersja autorstwa {{GENDER:$2|$2}} • $1",
"flow-compare-revisions-header-post": "Ta strona pokazuje {{GENDER:$3|zmiany}} między dwiema wersjami posta autorstwa $3 w wątku „[$5 $2]” na [$4 $1]. Możesz zobaczyć późniejsze wersje na [$6 historii strony].",
- "flow-compare-revisions-header-postsummary": "Ta strona pokazuje {{GENDER:$3|zmiany}} między dwiema wersjami streszczenia posta w wątku „[$4 $2]” na [$3 $1]. Możesz zobaczyć późniejsze wersje na [$5 historii strony].",
+ "flow-compare-revisions-header-postsummary": "Ta strona pokazuje zmiany między dwiema wersjami streszczenia wątku „[$4 $2]” na [$3 $1].\nMożesz zobaczyć inne wersje streszczeń tego wątku na [$5 stronie historii wątku].",
"flow-compare-revisions-header-header": "Ta strona pokazuje {{GENDER:$2|zmiany}} pomiędzy dwiema wersjami opisu w [$3 $1]. Możesz również zobaczyć inne wersje na [$4 stronie historii].",
"action-flow-create-board": "Twórz dyskusję Flow w dowolnym miejscu",
"right-flow-create-board": "Tworzenie dyskusji Flow w dowolnym miejscu",
@@ -337,7 +415,7 @@
"right-flow-lock": "Oznaczanie wątków Flow jako załatwionych",
"right-flow-delete": "Usuwanie wątków i postów Flow",
"right-flow-edit-post": "Edycja postów innych użytkowników",
- "right-flow-suppress": "Ukryj (oversight) wersje",
+ "right-flow-suppress": "Ukrywanie (oversight) wersji",
"flow-terms-of-use-new-topic": "Klikając na „{{int:flow-newtopic-save}}”, zgadzasz się na warunki użytkowania tej wiki.",
"flow-terms-of-use-reply": "Klikając na „{{int:flow-reply-link}}”, zgadzasz się na warunki użytkowania tej wiki.",
"flow-terms-of-use-edit": "Zapisując zmiany, zgadzasz się na warunki użytkowania tej wiki.",
@@ -350,7 +428,7 @@
"flow-no-more-fwd": "Nie ma starszych wątków",
"flow-newest-topics": "Najnowsze wątki",
"flow-recent-topics": "Wątki ostatnio aktywne",
- "flow-sorting-tooltip-newest": "Teraz {{GENDER:|czytasz}} wątki w kolejności od najnowszego. Kliknij, aby aby wybrać inną kolejność sortowania.",
+ "flow-sorting-tooltip-newest": "Teraz {{GENDER:|czytasz}} wątki w kolejności od najnowszego. Kliknij, aby wybrać inną kolejność sortowania.",
"flow-sorting-tooltip-recent": "Obecnie {{GENDER:|czytasz}} wątki według ostatniej aktywności. Kliknij, aby wybrać inną kolejność sortowania.",
"flow-toggle-small-topics": "Przełącz się na widok małych nagłówków",
"flow-toggle-topics": "Przełącz się na widok samych nagłówków",
@@ -361,7 +439,7 @@
"flow-whatlinkshere-post": "z [$1 postu]",
"flow-whatlinkshere-header": "z [$1 opisu]",
"flow-whatlinkshere-post-summary": "ze [$1 streszczenia]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Ta strona specjalna przekierowuje do cyklu pracy Flow albo do postu Flow o określonym UUID.",
"flow-special-type": "Typ",
"flow-special-type-post": "Post",
@@ -375,9 +453,11 @@
"flow-special-enableflow-invalid-title": "Podano nieprawidłowy tytuł strony",
"flow-special-enableflow-board-creation-not-allowed": "Nie masz uprawnień do tworzenia Flow na [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Na [[:$1]] jest już strona LiquidThreads.",
- "flow-special-enableflow-confirmation": "Tworzenie Flow na [[$1]] powiodło się.",
+ "flow-special-enableflow-confirmation": "Stworzono Flow na [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archiwum %d\n%s/Archiwum%d\n%s/archiwum %d\n%s/archiwum%d",
- "flow-spam-confirmedit-form": "Potwierdź, że nie jesteś programem, rozwiązując poniższą captcha: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Archiwum Flow %d\n%s/ArchiwumFlow%d",
+ "flow-spam-confirmedit-form": "Potwierdź że nie jesteś programem, rozwiązując poniższą CAPTCHA: $1",
+ "flow-spam-confirmedit-using-failure": "Wystąpił techniczny błąd związany z CAPTCHĄ. Jeżeli nie możesz wysłać swojej zmiany, skopiuj tekst, przeładuj stronę i spróbuj ponownie.",
"flow-embedding-unsupported": "W Flow na razie nie działa transkluzja.",
"mw-ui-unsubmitted-confirm": "Masz niezapisane zmiany na tej stronie. Jesteś pewien, że chcesz odejść i stracić zmiany?",
"flow-post-undo-hide": "cofnij rewert",
@@ -387,28 +467,23 @@
"flow-topic-undo-delete": "cofnij usunięcie",
"flow-topic-undo-suppress": "cofnij oversight",
"flow-importer-lqt-moved-thread-template": "Wątek LQT skonwertowany na Flow",
+ "flow-importer-lqt-moved-thread-template-content": "Ten post napisany przez {{{author}}} został przeniesiony {{{date}}}. Możesz go znaleźć pod [[{{{title}}}]].",
"flow-importer-lqt-converted-template": "Strona LQT skonwertowana na Flow",
+ "flow-importer-lqt-converted-template-content": "Poprzednia historia strony została zarchiwizowana jako kopia zapasowa na <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> w {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Archiwum skonwertowanej strony LQT",
- "flow-importer-wt-converted-template": "Strona dyskusji w wikikodzie zmieniona na Flow",
+ "flow-importer-lqt-converted-archive-template-content": "Ta strona jest zarchiwizowaną stroną LiquidThreads. <strong>Nie edytuj zawartości tej strony</strong>. Proszę skierować wszelkie dodatkowe komentarze na [[{{{from}}}|aktualną stronę dyskusji]].",
+ "flow-importer-wt-converted-template": "Strona dyskusji w wikikodzie skonwertowana na Flow",
+ "flow-importer-wt-converted-template-content": "Poprzednia dyskusja została zarchiwizowana na <span class='flow-link-to-archive'>[[{{{archive}}}]]</span>, {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Archiwum skonwertowanej strony dyskusji w wikikodzie",
+ "flow-importer-wt-converted-archive-template-content": "Ta strona jest archiwum. <strong>Nie edytuj zawartości tej strony</strong>. Dodatkowe komentarze należy kierować na [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|bieżącą stronę dyskusji]].",
"flow-importer-lqt-suppressed-user-template": "Zaimportowany post LQT ukrytego użytkownika",
+ "flow-importer-lqt-suppressed-user-template-content": "Ta wersja została zaimportowana z LiquidThreads z ukrytą nazwą użytkownika. Została przypisana ponownie do bieżącego użytkownika.",
"flow-importer-lqt-different-author-signature-template": "Post LQT zaimportowany z innym podpisem użytkownika",
- "apihelp-flow+edit-header-param-format": "Format opisu (wikitekst|html)",
- "apihelp-flow+edit-post-param-postId": "ID wiadomości.",
- "apihelp-flow+lock-topic-description": "Zabezpiecz albo odbezpiecz wątek.",
- "apihelp-flow+lock-topic-param-reason": "Powód zabezpieczenia lub odbezpieczenia wątku. Uwaga, istniejący na wiki program Flow używa opcji „Oznaczony jako załatwiony” oraz nadaje opcjonalne informacje jako jego podsumowanie.",
- "apihelp-flow+moderate-post-param-reason": "Powód moderacji.",
- "apihelp-flow+moderate-post-param-postId": "ID wiadomości do moderacji.",
- "apihelp-flow+moderate-topic-param-reason": "Powód moderacji.",
- "apihelp-flow+new-topic-description": "Tworzy nowy wątek Flow w danym cyklu pracy.",
- "apihelp-flow+reply-description": "Odpowiedzi na post.",
- "apihelp-flow+view-post-description": "Pokaż post",
- "apihelp-flow+view-post-history-description": "Zobacz historię zmian tej wiadomości.",
- "apihelp-flow+view-topic-description": "Pokaż wątek",
- "apihelp-flow+view-topic-example-1": "Zobacz [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topiclist-description": "Wyświetl listę wątków",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Ten post został umieszczony przez [[User:{{{authorUser}}}|{{{authorUser}}}]], ale podpisany jako [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Edytowany",
"flow-edited-by": "Edytowany przez $1",
+ "flow-edited-by-header": "Opis strony dyskusji edytowany przez $1",
+ "flow-edited-by-topic-title": "Tytuł wątku zmieniony przez $1",
"flow-lqt-redirect-reason": "Przekierowanie starych postów LiquidThreads do zmienionej wersji w Flow",
"flow-talk-conversion-move-reason": "Zmiana strony dyskusji $1 w wikikodzie na Flow",
"flow-talk-conversion-archive-edit-reason": "Zmiana strony dyskusji w wikikodzie na Flow",
@@ -434,7 +509,7 @@
"flow-ve-mention-inspector-invalid-user": "Nazwa użytkownika \"$1\" nie jest zarejestrowana.",
"flow-wikitext-editor-help": "Wikitekst $1.",
"flow-wikitext-editor-help-and-preview": "Wikitekst $1. W każdej chwili możesz zobaczyć $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|używa znaczników]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|używa znaczników]]",
"flow-wikitext-editor-help-preview-the-result": "podgląd wyniku",
"flow-wikitext-switch-editor-tooltip": "Przełącz do edytora wizualnego",
"flow-ve-switch-editor-tool-title": "Przełącz do edytora kodu źródłowego",
@@ -442,13 +517,28 @@
"flow-mark-revision-patrolled-link-title": "Oznacz tę stronę jako „sprawdzoną”",
"flow-mark-diff-patrolled-link-text": "Oznacz edycję jako „sprawdzoną”",
"flow-mark-diff-patrolled-link-title": "Oznacz edycję jako „sprawdzoną”",
- "flow-notification-link-text-enabled-on-talkpage": "Zobacz stronę dyskusji użytkownika",
+ "flow-talk-page-beta-feature-message": "Flow na stronie dyskusji użytkownika",
+ "flow-talk-page-beta-feature-description": "Włącza nowy strukturalny system dyskusji na {{GENDER:|Twojej}} stronie dyskusji użytkownika. Flow upraszcza dyskusje na stronach dyskusji z jasno określonymi miejscami, gdzie można pisać i odpowiadać, oraz umożliwia otrzymywanie powiadomień związanych z konwersacjami. Ta funkcja nie jest automatycznie włączana; użytkownicy muszą ją włączyć oddzielnie.<br /><br />Istniejące dyskusje wikitekstowe są przenoszone do archiwum. Wyłączenie tej funkcji spowoduje przeniesienie Flow na podstronę oraz przeniesienie z archiwum z powrotem poprzedniej strony dyskusji. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Dowiedz się więcej na temat aktywacji]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Zobacz}} stronę dyskusji użytkownika",
+ "flow-notification-enabled-on-talkpage-title": "Został włączony nowy system dyskusji dla {{GENDER:$1|Twojej}} strony dyskusji użytkownika<br /><small>Dostępny na [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Nowy system dyskusji na $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, nowy system dyskusji na wiki, został włączony na {{GENDER:$1|Twojej}} stronie dyskusji użytkownika na {{SITENAME}}. Możesz uzyskać więcej informacji, podzielić się opinią lub wyłączyć nowy system w dowolnym czasie w sekcji Funkcje eksperymentalne w {{GENDER:$1|Twoich}} preferencjach.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Dodanie szablonu archiwum",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Usunięcie szablonu archiwum",
"flow-dialog-cancelconfirm-title": "Na pewno?",
"flow-dialog-cancelconfirm-message": "Czy na pewno chcesz przerwać edycję bez jej zapisywania?",
"flow-dialog-cancelconfirm-keep": "Kontynuuj edycję",
"flow-dialog-cancelconfirm-discard": "Porzuć zmiany",
+ "flow-optin-archive-wikitext": "Przeniesienie strony w wikikodzie, aby zrobić miejsce pod forum dyskusyjne.",
+ "flow-optin-archive-flow-board": "Przeniesienie strony z forum dyskusyjnym, aby zrobić miejsce pod stronę w wikikodzie.",
+ "flow-optin-restore-wikitext": "Przywrócenie zarchiwizowanej strony wikitekstowej.",
+ "flow-optin-restore-flow-board": "Przywrócenie zarchiwizowanego forum dyskusyjnego.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Witaj}} na {{GENDER:$1|swojej}} nowej stronie dyskusji",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Twoja}} strona dyskusji jest miejscem, gdzie inni mogą skontaktować się z {{GENDER:$1|Tobą}}. Z Flow łatwiej jest zaczynać nowe tematy i śledzić przebieg rozmowy.",
"flow-guidedtour-optin-find-old-conversations": "Znajdź {{GENDER:$1|swoje}} wcześniejsze rozmowy",
"flow-guidedtour-optin-find-old-conversations-description": "Wcześniejsze rozmowy zostały przeniesione na stronę archiwum.",
- "flow-guidedtour-optin-feedback": "Przekaż nam {{GENDER:$1|swoją}} opinię!"
+ "flow-guidedtour-optin-feedback": "Przekaż nam {{GENDER:$1|swoją}} opinię!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Możesz}} uzyskać więcej informacji, podzielić się opinią lub wyłączyć nowy system w dowolnym czasie w sekcji Funkcje eksperymentalne.",
+ "flow-action-not-page": "Obiekt strony jest instancją niewłaściwej klasy",
+ "flow-action-wrong-title-content-model": "Ta strona jest obsługiwana przez Flow, ale klasa Title wskazuje, że modelem jej zawartości jest '$1'. Jest to skutkiem niewłaściwej konfiguracji lub niespójnego stanu. Na przykład może to być aktualnie strona nie będąca Flow, ale w przestrzeni nazw obsługiwanej przez Flow, gdzie nie jest określana wartość <code>rev_content_model</code>."
}
diff --git a/Flow/i18n/ps.json b/Flow/i18n/ps.json
index dc6808e0..37b4a065 100644
--- a/Flow/i18n/ps.json
+++ b/Flow/i18n/ps.json
@@ -12,24 +12,30 @@
"flow-history-action-delete-post": "ړنگول",
"flow-history-action-unlock-topic": "بيا پرانيستل",
"flow-post-edited": "ليکنه د $1 لخوا په $2 {{GENDER:$1|سمه شوه}}",
+ "flow-post-action-edit-post": "سمول",
"flow-topic-action-watchlist-add": "دا سرليک خپل کتنلړ کې ورگډول",
"flow-topic-action-watchlist-remove": "همدا سرليک خپل کتنلړ څخه لرې کول",
+ "flow-error-protected-unknown-reason": "ناجوت",
"flow-board-history": "\"$1\" پېښليک",
"flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 پر '''$4''' {{GENDER:$1|ځواب ورکړ}}.",
+ "flow-notification-link-text-view-topics": "موضوعگانې کتل",
"flow-notification-reply-email-subject": "$2 پر $3",
"flow-notification-edit-email-subject": "$1 ستاسې ليکنه {{GENDER:$1|سمه کړه}}",
"flow-notification-rename-email-subject": "$1 ستاسې سرليک {{GENDER:$1|نوم بدل کړ}}",
+ "echo-category-title-flow-discussion": "بهاو",
"flow-link-history": "پېښليک",
- "apihelp-flow+new-topic-param-topic": "د نوې موضوع د سرليک متن.",
"flow-previous-diff": "→ زوړ سمون",
"flow-next-diff": "نوی سمون ←",
"flow-undo": "ناکړل",
"flow-undo-your-text": "ستاسې متن",
"flow-ve-mention-inspector-remove-label": "غورځول",
"flow-wikitext-editor-help": "ويکي متن $1.",
+ "flow-wikitext-switch-editor-tooltip": "ليدنيز سمونگر ته ور اړول",
+ "flow-ve-switch-editor-tool-title": "ويکي متن سمونگر ته ور اړول",
"flow-mark-revision-patrolled-link-text": "دا مخ څارل شوی په نخښه کول",
"flow-mark-revision-patrolled-link-title": "دا مخ څارل شوی په نخښه کول",
"flow-mark-diff-patrolled-link-text": "څارل شوی په نخښه کول",
"flow-mark-diff-patrolled-link-title": "څارل شوی په نخښه کول",
+ "flow-notification-link-text-enabled-on-talkpage": "د کار د خبرو اترو مخ {{GENDER:|کتل}}",
"flow-dialog-cancelconfirm-title": "آيا تاسې ډاډه ياست؟"
}
diff --git a/Flow/i18n/pt-br.json b/Flow/i18n/pt-br.json
index 0fc371af..ff6c02a8 100644
--- a/Flow/i18n/pt-br.json
+++ b/Flow/i18n/pt-br.json
@@ -13,30 +13,64 @@
"Diego Queiroz",
"TheEduGobi",
"Araceletorres",
- "Walesson"
+ "Walesson",
+ "Cainamarques",
+ "Nnemo",
+ "Opraco",
+ "Quiddity",
+ "Anderson Costa",
+ "Luk3",
+ "Cristofer Alves",
+ "Felipe L. Ewald"
]
},
- "enableflow": "Ativar Flow",
- "flow-desc": "Sistema de gerenciamento do fluxo de trabalho",
- "log-name-flow": "Registro de atividade do Flow",
- "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|excluiu}} uma [$4 publicação] em [[$3|$5]]\" em [[$6]]",
- "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurou}} uma [$4 publicação] em \"[[$3|$5]]\" em [[$6]]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|suprimiu}} uma [$4 publicação] em \"[[$3|$5]]\" em [[$6]]",
- "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|excluiu}} uma [$4 publicação] em \"[[$3|$5]]\" em [[$6]]",
+ "enablestructureddiscussions": "Ativar o Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Parar}} de vigiar nova atividade em \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Você}} não está mais vigiando a página \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Isso não afetará tópicos individuais que {{GENDER:$3|você}} está vigiando. Você pode vigiar [$2 esta página] a qualquer momento.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Parar}} de vigiar este tópico",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Você}} não está mais vigiando \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Você}} pode vigiar [$2 este tópico] a qualquer momento.",
+ "flow-desc": "Sistema de discussão",
+ "flow-talk-taken-over-comment": "/* Esta página foi convertida em uma discussão do Flow */",
+ "log-name-flow": "Registro de atividades do Flow",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|excluiu}} uma [$4 publicação] sobre \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|excluiu}} uma publicação sobre um tópico em [[$3]]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurou}} uma [$4 publicação] sobre \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} uma publicação sobre um tópico em [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|suprimiu}} uma [$4 publicação] sobre \"[[$3|$5]]\" em [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} uma publicação sobre um tópico em [[$3]]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|excluiu}} uma [$4 publicação] sobre \"[[$3|$5]]\" em [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|excluiu}} uma publicação sobre um tópico em [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|excluiu}} o tópico \"[[$3|$5]]\" em [[$6]]",
- "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restaurou}} tópico \"[[$3|$5]]\" em [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suprimiu}} tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|excluiu}} um tópico em [[$3]]",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restaurou}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} um tópico em [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suprimiu}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} um tópico em [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|excluiu}} o tópico \"[[$3|$5]]\" em [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] em [[$3]] foi importado do LiquidThreads para Flow",
- "flow-user-moderated": "Usuário moderado",
- "flow-board-header-browse-topics-link": "Navegar nos tópicos",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|excluiu}} um tópico em [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marcou}} o tópico \"[[$3|$5]]\" em [[$6]] como resolvido",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|marcou}} um tópico em [[$3]] como resolvido",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reabriu}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|reabriu}} um tópico em [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] em [[$3]] foi importado do LiquidThreads para o Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "ID da página do Flow",
+ "abusefilter-edit-builder-vars-board-namespace": "Namespace do espaço Flow",
+ "abusefilter-edit-builder-vars-board-text": "Título do Espaço de Discussão",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Título completo do Espaço de Discussão",
+ "flow-user-moderated": "Usuário Moderado",
+ "flow-board-header-browse-topics-link": "Navegar pelos tópicos",
"flow-board-header": "Sobre esta discussão",
+ "flow-board-description-can-not-edit": "Não editável",
"flow-board-collapse-description": "Ocultar descrição",
"flow-board-expand-description": "Mostrar descrição",
- "flow-edit-header-link": "Editar cabeçalho",
- "flow-post-moderated-toggle-hide-show": "Mostrar comentário {{GENDER:$1|ocultado}} por $2",
- "flow-post-moderated-toggle-delete-show": "Mostrar comentário {{GENDER:$1|excluído}} por $2",
- "flow-post-moderated-toggle-suppress-show": "Mostrar comentário {{GENDER:$1|suprimido}} por $2",
+ "flow-topic-collapse-siderail": "Ler em largura total",
+ "flow-topic-expand-siderail": "Ler em largura fixa",
+ "flow-edit-header-link": "Editar descrição",
+ "flow-post-moderated-toggle-hide-show": "Exibir comentário {{GENDER:$1|ocultado}} por $2",
+ "flow-post-moderated-toggle-delete-show": "Exibir comentário {{GENDER:$1|excluído}} por $2",
+ "flow-post-moderated-toggle-suppress-show": "Exibir comentário {{GENDER:$1|suprimido}} por $2",
"flow-post-moderated-toggle-hide-hide": "Ocultar comentário {{GENDER:$1|ocultado}} por $2",
"flow-post-moderated-toggle-delete-hide": "Ocultar comentário {{GENDER:$1|excluído}} por $2",
"flow-post-moderated-toggle-suppress-hide": "Ocultar comentário {{GENDER:$1|suprimido}} por $2",
@@ -48,38 +82,43 @@
"flow-delete-title-content": "Este tópico foi {{GENDER:$1|excluído}} por $1",
"flow-delete-header-content": "{{GENDER:$1|Excluído}} por $2",
"flow-suppress-post-content": "Este comentário foi {{GENDER:$1|suprimido}} por $1 ([$2 histórico])",
- "flow-suppress-title-content": "Este comentário foi {{GENDER:$1|suprimido}} por $1",
+ "flow-suppress-title-content": "Este tópico foi {{GENDER:$1|suprimido}} por $1",
"flow-suppress-header-content": "{{GENDER:$1|Suprimido}} por $2",
- "flow-suppress-usertext": "<em>Nome de usuário suprimido</em>",
+ "flow-suppress-usertext": "<em>Nome de usuário(a) suprimido</em>",
"flow-post-actions": "Ações",
"flow-topic-actions": "Ações",
"flow-cancel": "Cancelar",
- "flow-show-change": "Mostrar alterações",
+ "flow-skip-summary": "Pular",
+ "flow-edit-summary-placeholder": "Descreva brevemente o resultado desta discussão",
+ "flow-summary-authored": "Resumo de $1",
+ "flow-summary-edited": "Resumo {{GENDER:$1|editado}} pela última vez por $1",
+ "flow-show-change": "Exibir mudanças",
"flow-last-modified-by": "{{GENDER:$1|Modificado}} pela última vez por $1",
- "flow-stub-post-content": "\"Devido a um erro técnico, esta publicação não pode ser recuperada.\"",
+ "flow-stub-post-content": "<em>Devido a um erro técnico, esta publicação não pode ser recuperada.</em>",
"flow-newtopic-title-placeholder": "Novo tópico",
- "flow-newtopic-content-placeholder": "Publicar nova mensagem para \"$1\"",
+ "flow-newtopic-content-placeholder": "Publicar uma nova mensagem para \"$1\"",
"flow-newtopic-header": "Adicionar um novo tópico",
"flow-newtopic-save": "Adicionar tópico",
"flow-newtopic-save-anonymously": "Adicionar tópico anonimamente",
- "flow-newtopic-start-placeholder": "Comece um novo tópico",
- "flow-newtopic-first-heading": "Iniciar um novo tópico em $1",
+ "flow-newtopic-start-placeholder": "Criar um novo tópico",
+ "flow-newtopic-first-heading": "Criar um novo tópico em $1",
"flow-summarize-topic-placeholder": "Por favor, resuma esta discussão",
- "flow-reply-topic-placeholder": "{{GENDER:$1|Comentou}} em \"$2\"",
+ "flow-reply-topic-placeholder": "{{GENDER:$1|Comentou}} sobre \"$2\"",
"flow-reply-topic-title-placeholder": "Responder a \"$1\"",
"flow-reply-link": "{{GENDER:$1|Responder}}",
"flow-reply-link-anonymously": "Responder anonimamente",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Agradecer}}}}",
- "flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Agradecer}}}} publicamente ao editor",
+ "flow-thank-link-title": "{{GENDER:$1|Agradecer}} publicamente {{GENDER:$2|ao editor|à autora}}",
"flow-history-action-suppress-post": "suprimir",
"flow-history-action-delete-post": "excluir",
"flow-history-action-hide-post": "ocultar",
- "flow-history-action-unsuppress-post": "reativar",
- "flow-history-action-undelete-post": "recuperar",
+ "flow-history-action-unsuppress-post": "cancelar supressão",
+ "flow-history-action-undelete-post": "restaurar",
"flow-history-action-unhide-post": "reexibir",
"flow-history-action-restore-post": "restaurar",
- "flow-history-action-lock-topic": "trancar",
- "flow-history-action-unlock-topic": "destrancar",
+ "flow-history-action-lock-topic": "resolver",
+ "flow-history-action-unlock-topic": "reabrir",
+ "flow-post-interaction-separator": "&#32;•&#32;",
"flow-post-edited": "Publicação {{GENDER:$1|editada}} por $1 $2",
"flow-post-action-view": "Link permanente",
"flow-post-action-post-history": "Histórico",
@@ -91,7 +130,7 @@
"flow-post-action-edit-post-submit-anonymously": "Salvar alterações anonimamente",
"flow-post-action-unsuppress-post": "Cancelar supressão",
"flow-post-action-undelete-post": "Restaurar",
- "flow-post-action-unhide-post": "Mostrar",
+ "flow-post-action-unhide-post": "Reexibir",
"flow-post-action-restore-post": "Restaurar",
"flow-post-action-undo-moderation": "Desfazer",
"flow-topic-action-view": "Link permanente",
@@ -100,50 +139,54 @@
"flow-topic-action-history": "Histórico",
"flow-topic-action-hide-topic": "Ocultar tópico",
"flow-topic-action-delete-topic": "Excluir tópico",
- "flow-topic-action-lock-topic": "Trancar tópico",
- "flow-topic-action-unlock-topic": "Destrancar tópico",
+ "flow-topic-action-lock-topic": "Marcar como resolvido",
+ "flow-topic-action-unlock-topic": "Reabrir tópico",
"flow-topic-action-summarize-topic": "Resumir",
- "flow-topic-action-resummarize-topic": "Editar o sumário do tópico",
+ "flow-topic-action-resummarize-topic": "Editar o resumo do tópico",
+ "flow-topic-action-update-topic-summary": "Atualizar resumo",
"flow-topic-action-suppress-topic": "Suprimir tópico",
- "flow-topic-action-unhide-topic": "Mostrar tópico",
+ "flow-topic-action-unhide-topic": "Reexibir tópico",
"flow-topic-action-undelete-topic": "Restaurar tópico",
- "flow-topic-action-unsuppress-topic": "Cancelar supressão do tópico",
+ "flow-topic-action-unsuppress-topic": "Remover supressão do tópico",
"flow-topic-action-restore-topic": "Restaurar tópico",
"flow-topic-action-undo-moderation": "Desfazer",
- "flow-topic-notification-subscribe-title": "Este tópico foi adicionado à {{GENDER:$1|sua}} lista de vigiados.",
+ "flow-topic-notification-subscribe-title": "Este tópico foi adicionado à {{GENDER:$1|sua}} lista de páginas vigiadas.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Você}} receberá notificações sobre todas as atividades neste tópico.",
- "flow-board-notification-subscribe-title": "{{GENDER:$1|Você}} está inscrito neste quadro de discussão!",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|Você}} receberá uma notificação quando um novo tópico for criado nessa discussão.",
- "flow-error-allowcreation-no-usedb": "allowCreation requer <var>$wgContentHandlerUseDB</var> para ser <code>true</code>.",
- "flow-error-allowcreation-already-exists": "A página já existe, mas não é necessária",
+ "flow-board-notification-subscribe-title": "Você está inscrit{{GENDER:$1|o|a}} nesta discussão!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Você}} receberá uma notificação quando um novo tópico for criado nesta discussão.",
+ "flow-topic-action-watchlist-add": "Inscrever-se neste tópico",
+ "flow-topic-action-watchlist-remove": "Cancelar inscrição",
+ "flow-error-allowcreation-no-usedb": "Ativar o Flow numa página específica requer que <var>$wgContentHandlerUseDB</var> seja <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "A página já existe no destino, uma discussão do Flow não pode ser movida para lá.",
"flow-error-allowcreation-flow-create-board": "O usuário não tem a permissão de \"{{int:right-flow-create-board}}\"",
- "flow-error-http": "Ocorreu um erro ao contactar o servidor.",
- "flow-error-other": "Ocorreu um erro inesperado.",
- "flow-error-external": "Ocorreu um erro.<br />A mensagem de erro recebida foi: $1",
- "flow-error-topic-is-locked": "Este tópico está bloqueado para quaisquer outras atividades.",
- "flow-error-lock-moderated-post": "Você não pode trancar uma publicação moderada.",
- "flow-error-external-multi": "Foram encontrados erros.<br /> $1",
+ "flow-error-can-not-edit-logged-out": "Você ainda não pode participar. Experimente autenticar-se.",
+ "flow-error-can-not-edit-logged-in": "Você ainda não pode participar, por que não tem os direitos necessários.",
+ "flow-error-http": "Ocorreu um erro ao entrar em contato com o servidor.",
+ "flow-error-external": "Ocorreu um erro. A mensagem de erro recebida foi: $1",
+ "flow-error-topic-is-locked": "Este tópico foi resolvido, portanto, atividade adicional não é possível.",
+ "flow-error-lock-moderated-post": "Você não pode marcar uma publicação moderada como resolvida.",
"flow-error-missing-content": "A publicação não tem conteúdo. É necessário haver conteúdo para salvar uma publicação.",
- "flow-error-missing-summary": "O resumo não tem conteúdo. É necessário haver conteúdo para salvar um resumo.",
+ "flow-error-missing-summary": "Você deve entrar com um resumo.",
"flow-error-missing-title": "O tópico não tem título. É necessário definir um título para salvar um tópico.",
- "flow-error-parsoid-failure": "Não foi possível analisar o conteúdo devido a uma falha do Parsoid.",
+ "flow-error-parsoid-failure": "Não é possível transferir conteúdo: Erro ao entrar em contato com o servidor para conversão entre texto wiki e HTML. Por favor, verifique a sua conexão com a internet ou tente novamente mais tarde, se o problema persistir. Se você ainda receber esse erro, por favor, informe o bug",
+ "flow-error-protected-autoconfirmed-logged-in": "Este espaço de discussão está protegido. Somente usuários auto-confirmados podem participar. Razão: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Este espaço de discussão está protegido. Somente usuários logados que são auto-confirmados podem participar. Razão: $1",
+ "flow-error-protected-sysop-logged-in": "Este espaço de discussão está protegido. Somente usuários logados com privilégios administrativos podem participar. Razão: $1",
+ "flow-error-protected-sysop-logged-out": "Este espaço de discussão está protegido. Somente usuários logados com privilégios administrativos podem participar. Razão: $1",
+ "flow-error-protected-unknown-reason": "Desconhecida",
"flow-error-missing-replyto": "Não foi fornecido nenhum parâmetro \"replyTo\". Este parâmetro é necessário para a ação de \"resposta\".",
- "flow-error-invalid-replyto": "Parâmetro \"replyTo\" inválido. A publicação especificada não foi encontrada.",
- "flow-error-delete-failure": "A exclusão deste item falhou.",
- "flow-error-hide-failure": "Falha ao ocultar este item.",
"flow-error-missing-postId": "Não foi fornecido nenhum parâmetro \"postId\". Este parâmetro é necessário para manipular uma publicação.",
"flow-error-invalid-postId": "Parâmetro \"postId\" inválido. A publicação especificada ($1) não pôde ser encontrada.",
- "flow-error-restore-failure": "A restauração deste item falhou.",
"flow-error-invalid-moderation-state": "Foi submetido um valor inválido para o parâmetro ('moderationState') da API Flow.",
"flow-error-invalid-moderation-reason": "Por favor, informe uma razão para a moderação.",
"flow-error-not-allowed": "Permissões insuficientes para executar esta ação.",
- "flow-error-not-allowed-hide": "Este tópico foi oculto.",
- "flow-error-not-allowed-reply-to-hide-topic": "Não é possível responder porque o tópico foi ocultado.",
+ "flow-error-not-allowed-hide": "Este tópico foi ocultado.",
+ "flow-error-not-allowed-reply-to-hide-topic": "Você não pode responder porque este tópico foi ocultado.",
"flow-error-not-allowed-delete": "Este tópico foi excluído.",
- "flow-error-not-allowed-reply-to-delete-topic": "Não é possível responder porque o tópico foi excluído.",
+ "flow-error-not-allowed-reply-to-delete-topic": "Você não pode responder porque este tópico foi excluído.",
"flow-error-not-allowed-suppress": "Este tópico foi excluído.",
- "flow-error-not-allowed-reply-to-suppress-topic": "Não é possível responder porque este tópico foi excluído.",
- "flow-error-not-allowed-hide-extract": "Este tópico foi ocultado. O registro oculto para o tópico é fornecida abaixo para referência.",
+ "flow-error-not-allowed-reply-to-suppress-topic": "Você não pode responder porque este tópico foi excluído.",
+ "flow-error-not-allowed-hide-extract": "Este tópico foi ocultado. O registro de ocultação do tópico é fornecido abaixo para referência.",
"flow-error-not-allowed-delete-extract": "Este tópico foi excluído. O registro de eliminação do tópico é fornecido abaixo como referência.",
"flow-error-not-allowed-reply-to-delete-topic-extract": "Você não pode responder porque esse tópico foi excluído. O registro de eliminação do tópico é fornecido abaixo como referência.",
"flow-error-not-allowed-suppress-extract": "Este tópico foi excluído. O registro de eliminação do tópico é fornecido abaixo como referência.",
@@ -151,45 +194,47 @@
"flow-error-title-too-long": "Os títulos dos tópicos estão restritos a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-no-existing-workflow": "Este fluxo de trabalho ainda não existe.",
"flow-error-not-a-post": "O título do tópico não pode ser salvo como uma publicação.",
- "flow-error-missing-header-content": "A descrição não tem conteúdo. É necessário haver conteúdo para salvar uma descrição.",
+ "flow-error-missing-header-content": "Você deve entrar com uma descrição.",
"flow-error-missing-prev-revision-identifier": "O identificador da revisão anterior está em falta.",
"flow-error-prev-revision-mismatch": "Outro usuário editou esta publicação há poucos segundos. {{GENDER:$3|Você}} tem certeza de que pretende substituir esta alteração recente?",
"flow-error-prev-revision-does-not-exist": "Não foi possível encontrar a revisão anterior.",
- "flow-error-core-topic-deletion": "Para excluir um tópico, use o ... menu na área do Flow ou [$1 página do tópico]. Não visite action=delete para o tópico diretamente.",
+ "flow-error-core-topic-deletion": "Para excluir um tópico, use o menu ... no espaço de discussão do Flow ou a [$1 página do tópico]. Não visite diretamente action=delete para o tópico.",
"flow-error-default": "Ocorreu um erro.",
"flow-error-invalid-input": "Foi fornecido um valor inválido para carregar o conteúdo do Flow.",
"flow-error-invalid-title": "Foi inserido um título de página inválido.",
+ "flow-error-invalid-parameter": "Parâmetro ausente ou inválido para chamada do método",
"flow-error-fail-load-history": "Falha ao carregar o conteúdo do histórico.",
"flow-error-missing-revision": "Não foi possível encontrar uma revisão para carregar o conteúdo do Flow.",
"flow-error-fail-commit": "Falha ao salvar o conteúdo do Flow.",
- "flow-error-insufficient-permission": "Permissões insuficientes para acessar ao conteúdo.",
- "flow-error-revision-comparison": "A operação só pode ser efetuada com duas revisões pertencentes à mesma mensagem.",
+ "flow-error-insufficient-permission": "Permissão insuficiente para acessar ao conteúdo.",
+ "flow-error-revision-comparison": "A operação só pode ser efetuada com duas revisões pertencentes à mesma publicação.",
"flow-error-missing-topic-title": "Não foi possível encontrar o título do tópico no fluxo de trabalho atual.",
"flow-error-missing-metadata": "Não foi possível encontrar os metadados necessários para esta revisão.",
+ "flow-error-different-page": "O fluxo de trabalho Flow não está associado com esta página.",
"flow-error-fail-load-data": "Falha ao carregar os dados solicitados.",
"flow-error-invalid-workflow": "Não foi possível encontrar o fluxo de trabalho solicitado.",
"flow-error-process-data": "Ocorreu um erro ao processar os dados que você solicitou.",
- "flow-error-process-wikitext": "Ocorreu um erro durante o processamento de conversão HTML/wikitexto.",
+ "flow-error-process-wikitext": "Ocorreu um erro durante o processamento de conversão HTML/texto wiki.",
"flow-error-no-index": "Falha ao localizar um índice para executar a busca de dados.",
"flow-error-no-render": "A ação especificada não foi reconhecida.",
"flow-error-no-commit": "A ação especificada não pode ser salva.",
"flow-error-content-too-long": "O conteúdo é muito grande. Após a expansão, o conteúdo é limitado a $1 {{PLURAL:$1|byte|bytes}}.",
- "flow-error-move-topic": "Mover um tópico não é permitido no momento.",
- "flow-error-move-no-create-permissions": "A permissão \"{{int:right-flow-create-board}}\" é requerida para mover uma placa de Flow.",
+ "flow-error-move-topic": "Mover uma página de tópico atualmente não é suportado.",
"flow-error-invalid-topic-uuid-title": "Título inválido",
"flow-error-invalid-topic-uuid": "O título da página fornecido é inválido. Páginas no domínio Tópico são criadas automaticamente pelo Flow.",
"flow-error-unknown-workflow-id-title": "Tópico desconhecido",
"flow-error-unknown-workflow-id": "O tópico solicitado não existe.",
"flow-error-search": "Não foi possível completar a busca devido a um problema temporário. Por favor, tente novamente mais tarde.",
+ "flow-error-invalid-undelete": "A página não pôde ser restaurada porque há atualmente um espaço de discussão no local.",
"flow-edit-header-placeholder": "Descreva este espaço de discussão",
- "flow-edit-header-submit": "Salvar cabeçalho",
+ "flow-edit-header-submit": "Salvar descrição",
"flow-edit-header-submit-anonymously": "Salvar descrição anonimamente",
"flow-edit-title-submit": "Mudar título",
"flow-edit-title-submit-anonymously": "Alterar título anonimamente",
"flow-edit-post-submit": "Enviar alterações",
- "flow-edit-post-submit-anonymously": "Enviar alterações de forma anônima",
+ "flow-edit-post-submit-anonymously": "Enviar alterações anonimamente",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|editou}} um [$3 comentário] em \"$4\"",
- "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Editou}} uma mensagem",
+ "flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Editou}} uma publicação",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|comentou}}] em \"$4\" (<em>$5</em>)",
"flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|comentário|comentários}}</strong> {{PLURAL:$1|foi adicionado|foram adicionados}}",
"flow-rev-message-new-post": "$1 {{GENDER:$2|criou}} o tópico \"[$3 $4]\"",
@@ -200,13 +245,15 @@
"flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|criou}} um resumo de tópico em $3",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|editou}} o resumo do tópico em $3",
"flow-rev-message-hid-post": "$1 {{GENDER:$2|ocultou}} um [$4 comentário] em \"$6\" (<em>$5</em>)",
- "flow-rev-message-deleted-post": "$1 {{GENDER:$2|eliminou}} um [$4 comentário] em \"$6\" (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|excluiu}} um [$4 comentário] em \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-post": "$1 {{GENDER:$2|suprimiu}} um [$4 comentário] em \"$6\" (<em>$5</em>)",
"flow-rev-message-restored-post": "$1 {{GENDER:$2|restaurou}} um [$4 comentário] em \"$6\" (<em>$5</em>)",
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ocultou}} o [$4 tópico] \"$6\" (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|eliminou}} o [$4 tópico] \"$6\" (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suprimiu}} o [$4 tópico] \"$6\" (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|bloqueou}} o [$4 tópico] $6 (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcou}} o [$4 tópico] \"$6\" como resolvido (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "marcado como resolvido",
+ "flow-rev-message-restore-topic-reason": "reaberto",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restaurou}} o [$4 tópico] \"$6\" (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 em $2",
"flow-board-history": "Histórico de \"$1\"",
@@ -215,119 +262,165 @@
"flow-post-history": "Histórico de \"Comentário por {{GENDER:$2|$2}}\"",
"flow-history-last4": "Últimas 4 horas",
"flow-history-day": "Hoje",
- "flow-history-week": "Semana passada",
+ "flow-history-week": "Última semana",
"flow-history-pages-topic": "Aparece no [$1 espaço \"$2\"]",
"flow-history-pages-post": "Aparece em [$1 $2]",
- "flow-topic-comments": "{{PLURAL:$1|$1 comentário|$1 comentários|0=Seja {{GENDER:$2|o primeiro|a primeira}} a comentar!}}",
- "flow-comment-restored": "Comentário recuperado",
+ "flow-topic-comments": "{{PLURAL:$1|Um comentário|$1 comentários|0=Seja {{GENDER:$2|o primeiro|a primeira}} a comentar!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Ver comentário|Ver comentários}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Ocultar comentário|Ocultar comentários}}",
+ "flow-comment-restored": "Comentário restaurado",
"flow-comment-deleted": "Comentário excluído",
"flow-comment-hidden": "Comentário oculto",
"flow-comment-moderated": "Comentário moderado",
"flow-last-modified": "Modificado pela última vez em $1",
"flow-workflow": "fluxo de trabalho",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 \"$2\"]</span><br />$1 {{GENDER:$1|respondeu}} em \"$4\".",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 \"$2\"]</span><br />$1 e $5 {{PLURAL:$6|outro|outros}} {{GENDER:$1|responderam}} em \"$3\".",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|respondeu}} em <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e {{PLURAL:$5|outro usuário|$5 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|responderam}} em <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|editou}} a sua <span class=\"plainlinks\">[$5 publicação]</span> em [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 e $5 {{PLURAL:$6|outro|outros}} {{GENDER:$1|editaram}} uma <span class=\"plainlinks\">[$4 mensagem]</span> em \"$2\", em \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|criou}} um novo tópico em '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 novo tópico|$1 novos tópicos|250=250+ novos tópicos}} em '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 e {{PLURAL:$5|outro usuário|$5 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|editaram}} uma <span class=\"plainlinks\">[$4 publicação]</span> em \"$2\", em \"$3\".",
+ "notification-header-flow-new-topic-v2": "Novo tópico criado em <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-compact-header-flow-new-topic": "\"<strong>$1</strong>\"",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=mais de 99 novos tópicos}} em <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Um novo tópico foi criado na <strong>sua página de discussão</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=mais de 99 novos tópicos}} na <strong>sua página de discussão</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|respondeu}} em \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Uma nova resposta|$1 novas respostas|100=mais de 99 novas respostas}} em \"<strong>$3</strong>\".",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|postou}} uma resposta na <strong>sua página de discussão</strong> em \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Uma nova resposta|$1 novas respostas|100=mais de 99 novas respostas}} na <strong>sua página de discussão</strong> em \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Sua}} publicação em \"<strong>$1</strong>\" foi editada.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Sua}} publicação em \"<strong>$1</strong>\" foi editada várias vezes.",
+ "notification-header-flow-post-edited-user-talk": "Uma publicação em \"<strong>$1</strong>\" foi editada na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Uma publicação em \"<strong>$1</strong>\" foi editada várias vezes na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-header-flow-topic-renamed-v2": "O tópico \"<strong>$1</strong>\" foi renomeado para \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "O tópico \"<strong>$1</strong>\" foi renomeado para \"<strong>$2</strong>\" na <strong>{{GENDER:$3|sua}} página de discussão</strong>.",
+ "notification-header-flow-summary-edited": "A resumo para \"<strong>$1</strong>\" foi editado.",
+ "notification-header-flow-summary-edited-first": "O tópico \"<strong>$1</strong>\" foi resumido.",
+ "notification-bundle-header-flow-summary-edited": "A resumo para \"<strong>$1</strong>\" foi editado várias vezes.",
+ "notification-header-flow-summary-edited-user-talk": "A resumo para \"<strong>$1</strong>\" foi editado na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "O tópico \"<strong>$1</strong>\" foi resumido na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "A resumo para \"<strong>$1</strong>\" foi editado várias vezes na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|atualizou}} o sumário em $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|atualizou}} o sumário em $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 e {{PLURAL:$3|outro usuário|$3 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|atualizaram}} o resumo em $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|mencionou}} {{GENDER:$4|você}} em \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|mencionou}} {{GENDER:$4|você}} na descrição de <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mencionou}} {{GENDER:$4|você}} em \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Novo sistema de discussão ativado para a <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-header-flow-description-edited": "A descrição de <strong>$1</strong> foi editada.",
+ "notification-header-flow-description-edited-user-talk": "A descrição foi editada na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-description-edited": "A descrição de <strong>$1</strong> foi editada várias vezes.",
+ "notification-bundle-header-flow-description-edited-user-talk": "A descrição foi editada várias vezes na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Ver}} página",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|editou}} a descrição em \"$2\".",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|editou}} a descrição em \"$2\".",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 e {{PLURAL:$3|outro usuário|$3 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|editaram}} a descrição em $2",
+ "notification-header-flow-topic-resolved": "O tópico \"<strong>$1</strong>\" foi resolvido.",
+ "notification-header-flow-topic-reopened": "O tópico \"<strong>$1</strong>\" foi reaberto.",
+ "notification-header-flow-topic-resolved-user-talk": "O tópico \"<strong>$1</strong>\" foi resolvido na <strong>sua página de discussão</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "O tópico \"<strong>$1</strong>\" foi reaberto na <strong>sua página de discussão</strong>.",
+ "notification-email-subject-flow-topic-resolved": "O tópico \"<strong>$2</strong>\" foi resolvido.",
+ "notification-email-batch-body-flow-topic-resolved": "O tópico \"<strong>$2</strong>\" foi resolvido.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|criou}} um novo tópico em <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100= mais de 99 novos tópicos}} em <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|modificou}} o título de <span class=\"plainlinks\">[$2 $3]</span> para \"$4\" em [[$5|$6]].",
- "flow-notification-mention": "$1 {{GENDER:$5|mencionou-o|mencionou-a}} {{GENDER:$1|na sua}} <span class=\"plainlinks\">[$2 mensagem]</span> em \"$3\" de \"$4\".",
+ "flow-notification-mention": "$1 {{GENDER:$1|mencionou-o|mencionou-a}} {{GENDER:$5|na sua}} <span class=\"plainlinks\">[$2 publicação]</span> em \"$3\" de \"$4\".",
"flow-notification-link-text-view-post": "Ver publicação",
"flow-notification-link-text-view-topic": "Ver tópico",
+ "flow-notification-link-text-view-topics": "Ver tópicos",
"flow-notification-reply-email-subject": "$2 em $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondeu}} a \"$2\" em $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 e $4 {{PLURAL:$5|outro|outros}} {{GENDER:$1|responderam}} à sua publicação \"$2\" em $3",
- "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mencionou-{{GENDER:$3|o|a|}}}} em \"$2\"",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|mencionou-o|mencionou-a}} {{GENDER:$1|na sua}} publicação em \"$2\" de $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$4|outro usuário|$4 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|responderam}} a \"$2\" em $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mencionou-{{GENDER:$3|o|a|}}}} em $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mencionou-o|mencionou-a}} {{GENDER:$4|na sua}} publicação em \"$2\" de $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|editou}} uma publicação",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|editou}} uma publicação em \"$2\" de $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 e $4 {{PLURAL:$5|outro|outros}} {{GENDER:$1|editaram}} uma publicação em \"$2\" de $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$4|outro usuário|$4 outros usuários|100=mais de 99 usuários}} {{GENDER:$1|editaram}} um publicação sobre \"$2\" em $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|renomeou}} o seu tópico",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renomeou}} o seu tópico \"$2\" para \"$3\" em $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|criou}} um novo tópico em $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|criou}} um novo tópico com o título \"$2\" em $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 novo tópico|$1 novos tópicos|250=250+ novos tópicos}} on $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Notifique-me quando ações relacionadas a mim ocorrer no Flow.",
- "flow-link-post": "publicar",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=mais de 99 novos tópicos}} em $2",
+ "echo-category-title-flow-discussion": "Discussão com o Flow",
+ "echo-pref-tooltip-flow-discussion": "Notificar-me sobre atividades nos tópicos ou nas páginas que eu estiver seguindo.",
+ "flow-link-post": "publicação",
"flow-link-topic": "tópico",
"flow-link-history": "histórico",
"flow-link-post-revision": "revisão da publicação",
"flow-link-topic-revision": "revisão de tópico",
- "flow-link-header-revision": "revisão de descrição",
+ "flow-link-header-revision": "revisão da descrição",
"flow-link-summary-revision": "revisão do resumo",
"flow-moderation-title-suppress-post": "Suprimir publicação?",
"flow-moderation-title-delete-post": "Excluir publicação?",
"flow-moderation-title-hide-post": "Esconder publicação?",
- "flow-moderation-title-unsuppress-post": "Retirar supressão da publicação?",
- "flow-moderation-title-undelete-post": "Restaurar mensagem?",
- "flow-moderation-title-unhide-post": "Mostrar publicação?",
- "flow-moderation-placeholder-suppress-post": "Por favor, {{GENDER:$3|indique}} a razão para a supressão desta mensagem.",
- "flow-moderation-placeholder-delete-post": "Por favor, {{GENDER:$3|indique}} a razão para a eliminação desta mensagem.",
- "flow-moderation-placeholder-hide-post": "Por favor, {{GENDER:$3|indique}} a razão para ocultar esta publicação.",
- "flow-moderation-placeholder-unsuppress-post": "Por favor, {{GENDER:$3|indique}} a razão para reativar esta publicação.",
- "flow-moderation-placeholder-undelete-post": "Por favor, {{GENDER:$3|indique}} a razão para a restauração desta mensagem.",
- "flow-moderation-placeholder-unhide-post": "Por favor, {{GENDER:$3|indique}} a razão para reexibir esta publicação.",
+ "flow-moderation-title-unsuppress-post": "Cancelar supressão da publicação?",
+ "flow-moderation-title-undelete-post": "Restaurar publicação?",
+ "flow-moderation-title-unhide-post": "Reexibir publicação?",
+ "flow-moderation-placeholder-suppress-post": "Por favor, {{GENDER:$3|explique}} por que você está suprimindo esta publicação.",
+ "flow-moderation-placeholder-delete-post": "Por favor, {{GENDER:$3|explique}} por que você está excluindo esta publicação.",
+ "flow-moderation-placeholder-hide-post": "Por favor, {{GENDER:$3|explique}} por que você está ocultando esta publicação.",
+ "flow-moderation-placeholder-unsuppress-post": "Por favor, {{GENDER:$3|explique}} por que você está retirando a supressão desta publicação.",
+ "flow-moderation-placeholder-undelete-post": "Por favor, {{GENDER:$3|explique}} por que você está restaurando esta publicação.",
+ "flow-moderation-placeholder-unhide-post": "Por favor, {{GENDER:$3|explique}} por que você está reexibindo esta publicação.",
"flow-moderation-confirm-suppress-post": "Suprimir",
- "flow-moderation-confirm-delete-post": "Eliminar",
+ "flow-moderation-confirm-delete-post": "Excluir",
"flow-moderation-confirm-hide-post": "Ocultar",
"flow-moderation-confirm-unsuppress-post": "Cancelar supressão",
"flow-moderation-confirm-undelete-post": "Restaurar",
- "flow-moderation-confirm-unhide-post": "Mostrar",
+ "flow-moderation-confirm-unhide-post": "Reexibir",
"flow-moderation-confirm-suppress-topic": "Suprimir",
"flow-moderation-confirm-delete-topic": "Excluir",
"flow-moderation-confirm-hide-topic": "Ocultar",
- "flow-moderation-confirm-unsuppress-topic": "Retirar supressão",
+ "flow-moderation-confirm-unsuppress-topic": "Cancelar supressão",
"flow-moderation-confirm-undelete-topic": "Restaurar",
- "flow-moderation-confirm-unhide-topic": "Mostrar",
- "flow-moderation-confirmation-suppress-post": "A publicação foi suprimida com sucesso.\n{{GENDER:$2|Considere}} falar com $1 sobre esta publicação.",
- "flow-moderation-confirmation-delete-post": "A publicação foi excluída com sucesso.\n{{GENDER:$2|Considere}} falar com $1 sobre esta publicação.",
- "flow-moderation-confirmation-hide-post": "A publicação foi ocultada com sucesso.\n{{GENDER:$2|Considere}} falar com $1 sobre esta publicação.",
- "flow-moderation-confirmation-unsuppress-post": "Você reativou este tópico com sucesso.",
- "flow-moderation-confirmation-undelete-post": "Você restaurou este tópico com sucesso.",
- "flow-moderation-confirmation-unhide-post": "Você reexibiu este tópico com sucesso.",
+ "flow-moderation-confirm-unhide-topic": "Reexibir",
+ "flow-moderation-confirmation-suppress-post": "A publicação foi suprimida.\n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-delete-post": "A publicação foi excluída.\n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-hide-post": "A publicação foi ocultada.\n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-unsuppress-post": "Você removeu a supressão da publicação acima.",
+ "flow-moderation-confirmation-undelete-post": "Você restaurou o tópico acima.",
+ "flow-moderation-confirmation-unhide-post": "Você reexibiu o tópico acima.",
"flow-moderation-confirmation-suppress-topic": "Este tópico foi suprimido.",
"flow-moderation-confirmation-delete-topic": "Este tópico foi excluído.",
- "flow-moderation-confirmation-hide-topic": "Este tópico foi oculto.",
- "flow-moderation-confirmation-unsuppress-topic": "Você reativou este tópico com sucesso.",
- "flow-moderation-confirmation-undelete-topic": "Você restaurou este tópico com sucesso.",
- "flow-moderation-confirmation-unhide-topic": "Você reexibiu este tópico com sucesso.",
+ "flow-moderation-confirmation-hide-topic": "Este tópico foi ocultado.",
+ "flow-moderation-confirmation-unsuppress-topic": "Você removeu a supressão deste tópico.",
+ "flow-moderation-confirmation-undelete-topic": "Você restaurou este tópico.",
+ "flow-moderation-confirmation-unhide-topic": "Você reexibiu este tópico.",
"flow-moderation-title-suppress-topic": "Suprimir tópico?",
"flow-moderation-title-delete-topic": "Excluir tópico?",
"flow-moderation-title-hide-topic": "Ocultar tópico?",
- "flow-moderation-title-unsuppress-topic": "Reativar tópico?",
+ "flow-moderation-title-unsuppress-topic": "Remover supressão do tópico?",
"flow-moderation-title-undelete-topic": "Restaurar tópico?",
"flow-moderation-title-unhide-topic": "Reexibir tópico?",
- "flow-moderation-placeholder-suppress-topic": "Por favor, {{GENDER:$3|explique}} o motivo para a supressão deste tópico.",
- "flow-moderation-placeholder-delete-topic": "Por favor, {{GENDER:$3|explique}} porquê você está excluindo este tópico.",
- "flow-moderation-placeholder-hide-topic": "Por favor, {{GENDER:$3|explique}} porquê você está ocultando este tópico.",
- "flow-moderation-placeholder-unsuppress-topic": "Por favor, {{GENDER:$3|explique}} porquê você está reativando este tópico.",
- "flow-moderation-placeholder-undelete-topic": "Por favor, {{GENDER:$3|explique}} porquê você está recuperando este tópico.",
- "flow-moderation-placeholder-unhide-topic": "Por favor, {{GENDER:$3|explique}} porquê você está reexibindo este tópico.",
+ "flow-moderation-placeholder-suppress-topic": "Por favor, {{GENDER:$3|explique}} por que você está suprimindo este tópico.",
+ "flow-moderation-placeholder-delete-topic": "Por favor, {{GENDER:$3|explique}} por que você está excluindo este tópico.",
+ "flow-moderation-placeholder-hide-topic": "Por favor, {{GENDER:$3|explique}} por que você está ocultando este tópico.",
+ "flow-moderation-placeholder-unsuppress-topic": "Por favor, {{GENDER:$3|explique}} por que você está retirando a supressão deste tópico.",
+ "flow-moderation-placeholder-undelete-topic": "Por favor, {{GENDER:$3|explique}} por que você está restaurando este tópico.",
+ "flow-moderation-placeholder-unhide-topic": "Por favor, {{GENDER:$3|explique}} por que você está reexibindo este tópico.",
"flow-topic-permalink-warning": "Este tópico começou em [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Esse tópico foi iniciado na região de [$2 {{GENDER:$1|$1}}]",
- "flow-revision-permalink-warning-post": "Isto é um link permanente para página singular desta publicação.\nEsta versão é de $1.\nVocê pode ver [$5 diferenças em relação à versão anterior], ou ver outras versões na [$4 página de histórico].",
- "flow-revision-permalink-warning-post-first": "Isto é um link permanente para a primeira versão desta publicação.\nVocê pode ver as versões recentes na [$4 página de histórico da publicação].",
- "flow-revision-permalink-warning-postsummary": "Isto é um link permanente para página singular do sumário desta publicação. Esta versão é de $1.\nVocê pode ver [$5 diferenças em relação à versões anteriores], ou ver outras versões na [$4 página de histórico da publicação].",
- "flow-revision-permalink-warning-postsummary-first": "Isto é um link permanente para a primeira versão do sumário desta publicação.\nVocê pode ver as versões recentes na [$4 página de histórico da publicação].",
- "flow-revision-permalink-warning-header": "Isto é um link permanente para uma versão singular desta descrição.\nEsta versão é de $1. Você pode ver [$3 diferenças em relação à versão anterior], ou ver outras versões sobre na [$2 página de histórico].",
- "flow-revision-permalink-warning-header-first": "Isto é um link permanente para a primeira versão da descrição.\nVocê pode ver outras versões na [$2 página de histórico].",
+ "flow-topic-permalink-warning-user-board": "Esse tópico foi iniciado no espaço [$2 {{GENDER:$1|$1}}]",
+ "flow-revision-permalink-warning-post": "Este é um link permanente para uma versão singular desta publicação.\nEsta versão é de $1.\nVocê pode ver as [$5 diferenças em relação à versão anterior], ou ver outras versões na [$4 página de histórico da publicação].",
+ "flow-revision-permalink-warning-post-first": "Este é um link permanente para a primeira versão desta publicação.\nVocê pode ver as versões posteriores na [$4 página de histórico da publicação].",
+ "flow-revision-permalink-warning-postsummary": "Este é um link permanente para uma versão singular do resumo desta publicação. Esta versão é de $1.\nVocê pode ver as [$5 diferenças em relação à versão anterior], ou ver outras versões na [$4 página de histórico da publicação].",
+ "flow-revision-permalink-warning-postsummary-first": "Este é um link permanente para a primeira versão do resumo desta publicação.\nVocê pode ver as versões posteriores na [$4 página de histórico da publicação].",
+ "flow-revision-permalink-warning-header": "Este é um link permanente para uma versão singular desta descrição.\nEsta versão é de $1. Você pode ver as [$3 diferenças em relação à versão anterior], ou ver outras versões na [$2 página de histórico do espaço de discussão].",
+ "flow-revision-permalink-warning-header-first": "Este é um link permanente para a primeira versão da descrição.\nVocê pode ver as versões posteriores na [$2 página de histórico do espaço de discussão].",
"flow-compare-revisions-revision-header": "Versão por {{GENDER:$2|$2}} de $1",
- "flow-compare-revisions-header-post": "Essa página mostra as {{GENDER:$3|alterações}} entre duas versões de uma publicação de $3 no tópico \"[$5 $2]\" em [$4 $1]. Você pode ver outras versões dessa publicação na sua [$6 página do histórico].",
- "flow-compare-revisions-header-postsummary": "Essa página mostra as alterações entre duas versões de um resumo de publicação na publicação \"[$4 $2]\" em [$3 $1]. Você pode ver outras versões dessa publicação na sua \n[$5 página do histórico].",
- "flow-compare-revisions-header-header": "Esta página mostra as {{GENDER:$2|alterações}} entre duas versões da descrição em [$3 $1].\nVocê pode ver outras versões desta mensagem na sua [$4 página do histórico].",
+ "flow-compare-revisions-header-post": "Essa página mostra as {{GENDER:$3|alterações}} entre duas versões de uma publicação de $3 no tópico \"[$5 $2]\" em [$4 $1].\nVocê pode ver outras versões dessa publicação na sua [$6 página do histórico].",
+ "flow-compare-revisions-header-postsummary": "Essa página mostra as alterações entre duas versões de um resumo da publicação \"[$4 $2]\" em [$3 $1].\nVocê pode ver outras versões do resumo desta publicação na sua [$5 página do histórico].",
+ "flow-compare-revisions-header-header": "Esta página mostra as {{GENDER:$2|alterações}} entre duas versões da descrição em [$3 $1].\nVocê pode ver outras versões da descrição na sua [$4 página do histórico].",
"action-flow-create-board": "criar áreas Flow em qualquer local",
"right-flow-create-board": "Criar áreas Flow em qualquer local",
"right-flow-hide": "Ocultar tópicos e posts do Flow",
- "right-flow-lock": "Fechar tópicos do Flow",
+ "right-flow-lock": "Marcar tópicos do Flow como resolvido",
"right-flow-delete": "Excluir tópicos e posts do Flow",
"right-flow-edit-post": "Editar posts do Flow de outros usuários",
"right-flow-suppress": "Suprimir revisões do Flow",
"flow-terms-of-use-new-topic": "Ao clicar em \"{{int:flow-newtopic-save}}\", você concorda com os termos de uso desta wiki.",
"flow-terms-of-use-reply": "Ao clicar em \"{{int:flow-reply-link}}\", você concorda com os termos de uso desta wiki.",
"flow-terms-of-use-edit": "Ao salvar as suas alterações, você concorda com os termos de uso desta wiki.",
- "flow-anon-warning": "Você não está logado. Para receber atribuição com o seu nome em vez do seu endereço IP, você pode [$1 logar] ou [$2 criar uma conta].",
+ "flow-anon-warning": "Você não está logado. Para receber a atribuição com o seu nome em vez do seu endereço IP, você pode [$1 logar] ou [$2 criar uma conta].",
"flow-cancel-warning": "Você digitou um texto neste formulário. Tem certeza de que deseja descartá-lo?",
"flow-topic-first-heading": "Tópico em $1",
"flow-topic-html-title": "$1 em $2",
@@ -347,7 +440,7 @@
"flow-whatlinkshere-post": "de uma [$1 publicação]",
"flow-whatlinkshere-header": "de uma [$1 descrição]",
"flow-whatlinkshere-post-summary": "do [$1 resumo]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Esta página especial redireciona para um fluxo de trabalho do Flow ou para uma publicação de Flow dado um UUID.",
"flow-special-type": "Tipo",
"flow-special-type-post": "Publicação",
@@ -356,13 +449,16 @@
"flow-special-invalid-uuid": "Não foi possível encontrar o conteúdo correspondente ao tipo e a UUID.",
"flow-special-enableflow-legend": "Ativar Flow em uma nova página",
"flow-special-enableflow-page": "Página na qual ativar o Flow",
- "flow-special-enableflow-header": "Descrição inicial do espaço do Flow (wikitexto)",
- "flow-special-enableflow-board-already-exists": "Já existe um espaço de Flow em [[$1]].",
+ "flow-special-enableflow-header": "Descrição inicial do espaço do Flow (texto wiki)",
+ "flow-special-enableflow-board-already-exists": "Já existe um espaço do Flow em [[$1]].",
"flow-special-enableflow-invalid-title": "Foi fornecido um título de página inválido",
"flow-special-enableflow-board-creation-not-allowed": "Você não possui permissão para criar um espaço de Flow em [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Há uma página LiquidThreads em [[:$1]].",
- "flow-special-enableflow-confirmation": "Você criou com sucesso um espaço de Flow em [[$1]].",
- "flow-spam-confirmedit-form": "Por favor, confirme se você é um ser humano ao resolver o código captcha abaixo: $1",
+ "flow-special-enableflow-confirmation": "Você criou um espaço de Flow em [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Arquivo %d\n%s/Arquivo%d\n%s/arquivo %d\n%s/arquivo%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Flow Archive %d\n%s/FlowArchive%d",
+ "flow-spam-confirmedit-form": "Por favor, confirme que você é um ser humano resolvendo o código CAPTCHA abaixo: $1",
+ "flow-spam-confirmedit-using-failure": "Ocorreu um erro técnico com o CAPTCHA. Se você não conseguir enviar sua alteração, copie seu texto, recarregue a página e tente novamente.",
"flow-embedding-unsupported": "As discussões ainda não podem ser incorporadas.",
"mw-ui-unsubmitted-confirm": "Você possui alterações não salvas nesta página. Tem certeza de que deseja continuar a navegar e perder todo o seu trabalho?",
"flow-post-undo-hide": "desfazer ocultar",
@@ -371,134 +467,79 @@
"flow-topic-undo-hide": "desfazer ocultar",
"flow-topic-undo-delete": "desfazer excluir",
"flow-topic-undo-suppress": "desfazer suprimir",
- "flow-importer-lqt-moved-thread-template": "LQT moveu a discussão convertida para o Flow",
+ "flow-importer-lqt-moved-thread-template": "LQT moveu o esboço do tópico convertido para o Flow",
+ "flow-importer-lqt-moved-thread-template-content": "Esta publicação por {{{author}}} foi movida em {{{date}}}. Você pode encontrá-la em [[{{{title}}}]].",
"flow-importer-lqt-converted-template": "Página LQT convertida para Flow",
+ "flow-importer-lqt-converted-template-content": "As páginas anteriores foram arquivadas em <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> em {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Arquivo para página LQT convertida",
- "flow-importer-wt-converted-template": "Página de discussão em wikitexto convertida para o Flow",
- "flow-importer-wt-converted-archive-template": "Arquivo para a página de discussão em wikitexto convertida",
- "flow-importer-lqt-suppressed-user-template": "Publicação importada do LQT com usuário suprimido",
- "apihelp-flow-description": "Permite que ações sejam realizadas nas páginas Flow.",
- "apihelp-flow-param-submodule": "O submódulo do Flow a ser invocado.",
- "apihelp-flow-param-page": "A página na qual será realizada uma ação",
- "apihelp-flow-example-1": "Editar a descrição de \"[[Talk:Sandbox]]\"",
- "apihelp-flow+close-open-topic-description": "Depreciado em favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Estado em que o tópico será colocado, bloqueado ou desbloqueado.",
- "apihelp-flow+close-open-topic-param-reason": "Motivo para bloquear ou desbloquear o tópico.",
- "apihelp-flow+edit-header-description": "Editar a descrição de um espaço de discussão.",
- "apihelp-flow+edit-header-param-prev_revision": "ID da revisão atual da descrição, para verificar conflitos de edição.",
- "apihelp-flow+edit-header-param-content": "Conteúdo para a descrição.",
- "apihelp-flow+edit-header-param-format": "Formato da descrição (wikitexto|html)",
- "apihelp-flow+edit-header-example-1": "Editar a descrição de \"[[Talk:Sandbox]]\"",
- "apihelp-flow+edit-post-description": "Edita o conteúdo da publicação.",
- "apihelp-flow+edit-post-param-postId": "ID da publicação.",
- "apihelp-flow+edit-post-param-prev_revision": "ID da revisão atual da descrição, para verificar conflitos de edição.",
- "apihelp-flow+edit-post-param-content": "Conteúdo para publicar.",
- "apihelp-flow+edit-post-param-format": "Formato do conteúdo da publicação (wikitexto|html)",
- "apihelp-flow+edit-post-example-1": "Editar uma publicação em [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Edita o título de um tópico.",
- "apihelp-flow+edit-title-param-prev_revision": "ID da revisão atual do título, para verificar conflitos entre edições.",
- "apihelp-flow+edit-title-param-content": "Conteúdo para o título.",
- "apihelp-flow+edit-title-example-1": "Edite o título de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Edita o conteúdo do sumário de uma publicação",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "ID da revisão atual do resumo do tópico, se houver, para verificar conflitos entre edições.",
- "apihelp-flow+edit-topic-summary-param-summary": "Conteúdo para o sumário.",
- "apihelp-flow+edit-topic-summary-param-format": "Formata o sumário (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Editar o sumário de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Tranca ou destranca um tópico do Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Estado para se deixar o tópico, seja trancado ou destrancado.",
- "apihelp-flow+lock-topic-param-reason": "Motivo para trancar ou destrancar o tópico.",
- "apihelp-flow+lock-topic-example-1": "Trancar [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Modera uma publicação do Flow.",
- "apihelp-flow+moderate-post-param-moderationState": "A qual nível moderar.",
- "apihelp-flow+moderate-post-param-reason": "Motivo para moderação.",
- "apihelp-flow+moderate-post-param-postId": "ID da publicação para moderar.",
- "apihelp-flow+moderate-post-example-1": "Excluir uma publicação no tópico [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Modera um tópico do Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "A qual nível moderar.",
- "apihelp-flow+moderate-topic-param-reason": "Motivo para moderação.",
- "apihelp-flow+moderate-topic-example-1": "Excluir o tópico [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Criar um novo tópico do Flow no fluxo de trabalho dado.",
- "apihelp-flow+new-topic-param-topic": "Texto para novo título de tópico.",
- "apihelp-flow+new-topic-param-content": "Conteúdo para a resposta inicial do tópico.",
- "apihelp-flow+new-topic-param-format": "Formato da resposta inicial do novo tópico (wikitexto|html)",
- "apihelp-flow+new-topic-example-1": "Criar um novo tópico em [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Respostas a uma publicação.",
- "apihelp-flow+reply-param-replyTo": "ID da publicação para responder.",
- "apihelp-flow+reply-param-content": "Conteúdo para nova publicação.",
- "apihelp-flow+reply-param-format": "Formato da nova publicação (wikitexto|html)",
- "apihelp-flow+reply-example-1": "Resposta a uma publicação em [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Formato no qual o conteúdo deverá ser retornado.",
- "apihelp-flow+view-header-description": "Ver descrição de um espaço de discussão.",
- "apihelp-flow+view-header-param-revId": "Carregar esta revisão, em vez da mais recente.",
- "apihelp-flow+view-header-example-1": "Obtém a descrição de [[Talk:Sandbox]] como wikitexto",
- "apihelp-flow+view-post-description": "Ver uma publicação",
- "apihelp-flow+view-post-param-postId": "Id da publicação para ver:",
- "apihelp-flow+view-post-param-format": "Formato no qual o conteúdo deverá ser retornado.",
- "apihelp-flow+view-post-example-1": "Obter o conteúdo de uma publicação em [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topic-description": "Ver um tópico.",
- "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-summary-description": "Ver o sumário de um tópico.",
- "apihelp-flow+view-topic-summary-param-format": "Formato no qual o conteúdo deverá ser retornado.",
- "apihelp-flow+view-topic-summary-param-revId": "Carregar esta revisão, em vez da mais recente.",
- "apihelp-flow+view-topic-summary-example-1": "Ver o resumo de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topiclist-description": "Ver uma lista de tópicos.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Direção para ordenar os tópicos.",
- "apihelp-flow+view-topiclist-param-sortby": "Classificando opção dos tópicos, seja <kbd>updated</kbd> (ordenados por tempo de atualização do tópico), ou <kbd>newest</kbd> (ordenados por tempo de criação do tópico).",
- "apihelp-flow+view-topiclist-param-savesortby": "Salve opção de preferências do usuário, se estiver definido.",
- "apihelp-flow+view-topiclist-param-offset-id": "Valor inicial (no formato UUID) para a obtenção de tópicos; usado somente com a ordenação <kbd>newest</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Valor inicial (como um tópico para atualizar data/hora, no formato <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), para obtenção de tópicos; usado somente com a ordenação <kbd>updated</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Número de tópicos para obter.",
- "apihelp-flow+view-topiclist-example-1": "Listar os tópicos em [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Converter texto entre wikitexto e HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Formato no qual o conteúdo deverá ser convertido.",
- "apihelp-flow-parsoid-utils-param-to": "Formato no qual o conteúdo deverá ser convertido.",
- "apihelp-flow-parsoid-utils-param-content": "Conteúdo a ser convertido.",
- "apihelp-flow-parsoid-utils-param-title": "Título da página. Não pode ser usado juntamente com $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID da página. Não pode ser usado juntamente com $1.",
- "apihelp-flow-parsoid-utils-example-1": "Converte wikitexto <nowiki>'''lorem''' ''blah''</nowiki> para HTML",
- "apihelp-query+flowinfo-description": "Obter informações básicas do Flow sobre uma página.",
- "apihelp-query+flowinfo-example-1": "Obter informações do Flow sobre [[Talk:Sandbox]], [[Main Page]], e [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Recuperar informações necessárias para desfazer edições de descrições.",
- "apihelp-flow+undo-edit-header-param-startId": "ID de revisão para começar a desfazer.",
- "apihelp-flow+undo-edit-header-param-endId": "ID de revisão para terminar de desfazer.",
- "apihelp-flow+undo-edit-header-example-1": "Obter informação sobre desfazer uma edição de descrição em [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Recuperar informações necessárias para desfazer edições de uma publicação.",
- "apihelp-flow+undo-edit-post-param-postId": "ID da publicação ser desfeita.",
- "apihelp-flow+undo-edit-post-param-startId": "ID de revisão para começar a desfazer.",
- "apihelp-flow+undo-edit-post-param-endId": "ID de revisão para terminar de desfazer.",
- "apihelp-flow+undo-edit-post-example-1": "Obter informação sobre como desfazer uma edição de uma publicação num tópico específico.",
- "apihelp-flow+undo-edit-topic-summary-description": "Recuperar informações necessárias para desfazer edições do resumo de tópico.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "ID de revisão para começar a desfazer.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "ID de revisão para terminar de desfazer.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Obter informação sobre como desfazer uma edição de um resumo de tópico num tópico específico.",
+ "flow-importer-lqt-converted-archive-template-content": "Esta página é um arquivo de páginas LiquidThreads. <strong>Não edite o conteúdo desta página</strong>. Por favor, quaisquer comentários adicionais devem ser feitos na [[{{{from}}}|na página de discussão]].",
+ "flow-importer-wt-converted-template": "Página de discussão em texto wiki convertida para o Flow",
+ "flow-importer-wt-converted-template-content": "As discussões anteriores foram arquivadas em <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> em {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Arquivo para páginas de discussão em texto wiki convertidas",
+ "flow-importer-wt-converted-archive-template-content": "Esta página é um arquivo. <strong>Não edite o conteúdo desta página</strong>. Por favor, quaisquer comentários adicionais devem ser feitos na [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|página de discussão]].",
+ "flow-importer-lqt-suppressed-user-template": "Publicação LQT importada com usuário suprimido",
+ "flow-importer-lqt-suppressed-user-template-content": "Esta revisão foi importada do LiquidThreads com um usuário suprimido. Ela foi reatribuída ao usuário atual.",
+ "flow-importer-lqt-different-author-signature-template": "Publicação LQT importada com assinatura do usuário diferente",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Esta publicação foi postada por [[User:{{{authorUser}}}|{{{authorUser}}}]], mas assinada como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Editado",
"flow-edited-by": "Editado por $1",
- "flow-lqt-redirect-reason": "Redirecionando uma publicação com LiquidThreads retirada para a publicação convertida com Flow",
- "flow-talk-conversion-move-reason": "Conversão de página de discussão em wikitexto para Flow de $1",
- "flow-talk-conversion-archive-edit-reason": "Conversão de discussão em wikitexto para Flow",
+ "flow-edited-by-header": "Descrição do espaço de discussão editado por $1",
+ "flow-edited-by-topic-title": "Título do tópico editado por $1",
+ "flow-lqt-redirect-reason": "Redirecionando uma publicação LiquidThreads retirada para sua publicação correspondente convertida com Flow",
+ "flow-talk-conversion-move-reason": "Conversão da página de discussão em texto wiki para Flow de $1",
+ "flow-talk-conversion-archive-edit-reason": "Conversão da página de discussão em texto wiki para o Flow",
"flow-previous-diff": "← Edição antiga",
- "flow-next-diff": "Edição recente →",
+ "flow-next-diff": "Edição mais recente →",
"flow-undo": "desfazer",
"flow-undo-latest-revision": "Última revisão",
"flow-undo-your-text": "Seu texto",
"flow-undo-edit-header": "Editando a descrição",
- "flow-undo-edit-topic-summary": "Editando o sumário do tópico",
+ "flow-undo-edit-topic-summary": "Editando o resumo do tópico",
"flow-undo-edit-post": "Editando uma publicação",
"flow-undo-edit-content": "A edição pode ser desfeita. Por favor, verifique o comparativo a seguir para se certificar de que é isto que deseja fazer então salve as modificações abaixo para terminar de desfazer a edição.",
"flow-undo-edit-failure": "A edição não pode ser desfeita devido a modificações intermediárias conflitantes.",
- "group-flow-bot": "Bots para o Flow",
- "group-flow-bot-member": "Bot para o Flow",
+ "group-flow-bot": "Flow bots",
+ "group-flow-bot-member": "Flow bot",
"grouppage-flow-bot": "Project:Flow bots",
"flow-ve-mention-context-item-label": "Menção",
"flow-ve-mention-inspector-title": "Menção",
"flow-ve-mention-inspector-remove-label": "Remover",
"flow-ve-mention-placeholder": "Nome de usuário",
"flow-ve-mention-tool-title": "Mencionar um usuário",
+ "flow-ve-mention-template-title": "FlowMention",
"flow-ve-mention-inspector-invalid-user": "O nome de usuário \"$1\" não está registrado.",
- "flow-wikitext-editor-help": "Wikitexto $1.",
- "flow-wikitext-editor-help-and-preview": "Wikitexto $1 e você pode $2 a qualquer momento.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|usa marcação]]",
+ "flow-wikitext-editor-help": "O texto wiki $1.",
+ "flow-wikitext-editor-help-and-preview": "O texto wiki $1 e você pode $2 a qualquer momento.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|usa marcação]]",
"flow-wikitext-editor-help-preview-the-result": "visualizar resultado",
- "flow-wikitext-switch-editor-tooltip": "Alternar para o VisualEditor",
- "flow-ve-switch-editor-tool-title": "Alternar para o editor wikitexto"
+ "flow-wikitext-switch-editor-tooltip": "Alternar para o Editor Visual",
+ "flow-ve-switch-editor-tool-title": "Alternar para o editor de texto wiki",
+ "flow-mark-revision-patrolled-link-text": "Marcar esta página como patrulhada",
+ "flow-mark-revision-patrolled-link-title": "Marcar esta página como patrulhada",
+ "flow-mark-diff-patrolled-link-text": "Marcar como patrulhada",
+ "flow-mark-diff-patrolled-link-title": "Marcar como patrulhada",
+ "flow-talk-page-beta-feature-message": "Flow na página de discussão",
+ "flow-talk-page-beta-feature-description": "Habilita um novo sistema de discussão estruturado na {{GENDER:|sua}} página de discussão. Flow simplifica discussões em página de discussão com lugares claros para escrever e responder e permite notificações em nível de conversação. Este recurso não é habilitado automaticamente; os usuários terão que habilitá-lo separadamente.<br /><br />As discussões em texto wiki existentes são movidas para um arquivo. Desativar esse recurso moverá o espaço Flow para uma subpágina e desarquivará a página de discussão anterior. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Saiba mais sobre a ativação]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Ver}} página de discussão",
+ "flow-notification-enabled-on-talkpage-title": "Novo sistema de discussão ativado para a {{GENDER:$1|sua}} página de discussão<br /><small>Disponível em [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Novo sistema de discussão em $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, o novo sistema de discussão wiki, foi ativado na {{GENDER:$1|sua}} página de discussão em {{SITENAME}}. Você pode obter mais informações, fornecer comentários ou desativar o novo sistema a qualquer momento na seção Recursos Beta nas {{GENDER:$1|suas}} preferências.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Adicionando predefinição arquivo",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Removendo predefinição de arquivo",
+ "flow-dialog-cancelconfirm-title": "Tem certeza?",
+ "flow-dialog-cancelconfirm-message": "Tem certeza de que deseja cancelar sem salvar primeiro?",
+ "flow-dialog-cancelconfirm-keep": "Continuar editando",
+ "flow-dialog-cancelconfirm-discard": "Descartar alterações",
+ "flow-optin-archive-wikitext": "Página de texto wiki movida para abrir espaço para um espaço de discussão.",
+ "flow-optin-archive-flow-board": "Espaço de discussão movido para abrir espaço para uma página de texto wiki.",
+ "flow-optin-restore-wikitext": "Restaurar página texto wiki arquivada.",
+ "flow-optin-restore-flow-board": "Restaurar o espaço de discussão arquivado.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Bem-vindo|Bem-vinda|Bem-vindo(a)}} à {{GENDER:$1|sua}} nova página de discussão",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|A sua}} página de discussão é o lugar onde outros editores podem entrar em contato com {{GENDER:$1|você}}. Com o Flow, é mais fácil iniciar novos tópicos e acompanhar as conversas.",
+ "flow-guidedtour-optin-find-old-conversations": "Encontrar as {{GENDER:$1|suas}} conversas antigas",
+ "flow-guidedtour-optin-find-old-conversations-description": "As conversas anteriores foram movidas para uma página de arquivo.",
+ "flow-guidedtour-optin-feedback": "Dê-nos o {{GENDER:$1|seu}} feedback!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Você}} pode obter mais informações, fornecer feedback ou desativar o novo sistema a qualquer momento na seção Recursos Beta.",
+ "flow-action-not-page": "O objeto da página é uma instância da classe errada",
+ "flow-action-wrong-title-content-model": "A página está sendo tratada pelo Flow, mas a classe Title indica que o modelo de conteúdo é '$1'. Esta é uma configuração errada ou um estado inconsistente. Por exemplo, isso pode realmente ser uma página não-Flow em um domínio Flow, com <code>rev_content_model</code> não preenchido."
}
diff --git a/Flow/i18n/pt.json b/Flow/i18n/pt.json
index a87d0d47..7bc8387d 100644
--- a/Flow/i18n/pt.json
+++ b/Flow/i18n/pt.json
@@ -13,25 +13,56 @@
"He7d3r",
"Imperadeiro90",
"Opraco",
- "Macofe"
+ "Macofe",
+ "Cainamarques",
+ "Nnemo",
+ "Matiia",
+ "Hamilton Abreu"
]
},
- "enableflow": "Ativar Flow",
- "flow-desc": "Sistema de gestão do fluxo de trabalho",
- "log-name-flow": "Registo de actividade do Flow",
+ "enablestructureddiscussions": "Ativar Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Parar}} de vigiar nova atividade em \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Já não {{GENDER:$3|está}} a vigiar a página \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Isto não afeta os tópicos que {{GENDER:$3|está}} a vigiar. Pode vigiar [$2 esta página] em qualquer altura.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Parar}} de vigiar este tópico",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Já não {{GENDER:$3|está}} a vigiar \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Pode}} vigiar [$2 este tópico] em qualquer altura.",
+ "flow-desc": "Sistema de discussão",
+ "flow-talk-taken-over-comment": "/* Esta página foi convertida num espaço de discussão Flow */",
+ "log-name-flow": "Registo de atividade do Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|eliminou}} uma [$4 mensagem] em \"[[$3|$5]]\" no [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} uma mensagem num tópico em [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|restaurou}} uma [$4 mensagem] em \"[[$3|$5]]\" no [[$6]]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|ocultou}} uma [$4 mensagem] em \"[[$3|$5]]\" no [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} uma mensagem num tópico em [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|suprimiu}} uma [$4 mensagem] em \"[[$3|$5]]\" no [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} uma mensagem num tópico em [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|eliminou}} uma [$4 mensagem] de \"[[$3|$5]]\" em [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} uma mensagem no tópico em [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|eliminou}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} um tópico em [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|restaurou}} o tópico \"[[$3|$5]]\" em [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|ocultou}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|restaurou}} um tópico em [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|suprimiu}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|suprimiu}} um tópico em [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|eliminou}} o tópico \"[[$3|$5]]\" em [[$6]]",
- "flow-user-moderated": "Utilizador em moderação",
- "flow-board-header-browse-topics-link": "Pesquisar tópicos",
- "flow-board-header": "Sobre esta discussão",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|eliminou}} um tópico em [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|marcou}} o tópico \"[[$3|$5]]\" como encerrado em [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|marcou}} um tópico como encerrado em [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|reabriu}} o tópico \"[[$3|$5]]\" em [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|reabriu}} um tópico em [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] em [[$3]] foi importado do LiquidThreads para o Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "Identificador de página do espaço de discussão Flow",
+ "abusefilter-edit-builder-vars-board-namespace": "Espaço nominal do espaço de discussão Flow",
+ "abusefilter-edit-builder-vars-board-text": "Título do espaço de discussão Flow",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Título completo do espaço de discussão Flow",
+ "flow-user-moderated": "Utilizador moderado",
+ "flow-board-header-browse-topics-link": "Navegar tópicos",
+ "flow-board-header": "Sobre este espaço de discussão",
+ "flow-board-description-can-not-edit": "Não editável",
"flow-board-collapse-description": "Ocultar descrição",
"flow-board-expand-description": "Mostrar descrição",
+ "flow-topic-collapse-siderail": "Ler a toda a largura",
+ "flow-topic-expand-siderail": "Ler em largura fixa",
"flow-edit-header-link": "Editar descrição",
"flow-post-moderated-toggle-hide-show": "Mostrar comentário {{GENDER:$1|ocultado}} por $2",
"flow-post-moderated-toggle-delete-show": "Mostrar comentário {{GENDER:$1|eliminado}} por $2",
@@ -53,21 +84,25 @@
"flow-post-actions": "Ações",
"flow-topic-actions": "Ações",
"flow-cancel": "Cancelar",
+ "flow-skip-summary": "Ignorar",
+ "flow-edit-summary-placeholder": "Descreva sucintamente o resultado desta discussão",
"flow-summary-authored": "Resumo por $1",
"flow-summary-edited": "Resumo {{GENDER:$1|editado}} pela última vez por $1",
"flow-show-change": "Mostrar alterações",
"flow-last-modified-by": "Última {{GENDER:$1|modificação}} por $1",
- "flow-stub-post-content": "\"Devido a um erro técnico, esta mensagem não pode ser recuperada.\"",
+ "flow-stub-post-content": "<em>Devido a um erro técnico, esta mensagem não pode ser recuperada.</em>",
"flow-newtopic-title-placeholder": "Novo tópico",
- "flow-newtopic-content-placeholder": "Publicar nova mensagem em \"$1\"",
+ "flow-newtopic-content-placeholder": "Publicar uma nova mensagem em \"$1\"",
"flow-newtopic-header": "Adicionar um novo tópico",
"flow-newtopic-save": "Adicionar tópico",
+ "flow-newtopic-save-anonymously": "Adicionar tópico anonimamente",
"flow-newtopic-start-placeholder": "Começar um novo tópico",
"flow-newtopic-first-heading": "Iniciar um novo tópico em $1",
"flow-summarize-topic-placeholder": "Por favor, resuma esta discussão",
"flow-reply-topic-placeholder": "{{GENDER:$1|Comentário}} em \"$2\"",
- "flow-reply-topic-title-placeholder": "Resposta a \"$1\"",
+ "flow-reply-topic-title-placeholder": "Responder a \"$1\"",
"flow-reply-link": "{{GENDER:$1|Responder}}",
+ "flow-reply-link-anonymously": "Responder anonimamente",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Agradecer}}}}",
"flow-thank-link-title": "{{GENDER:$1|{{GENDER:$2|Agradecer}}}} publicamente a mensagem",
"flow-history-action-suppress-post": "suprimir",
@@ -87,6 +122,7 @@
"flow-post-action-hide-post": "Ocultar",
"flow-post-action-edit-post": "Editar",
"flow-post-action-edit-post-submit": "Gravar alterações",
+ "flow-post-action-edit-post-submit-anonymously": "Gravar alterações anonimamente",
"flow-post-action-unsuppress-post": "Retirar supressão",
"flow-post-action-undelete-post": "Restaurar",
"flow-post-action-unhide-post": "Mostrar",
@@ -98,42 +134,45 @@
"flow-topic-action-history": "Histórico",
"flow-topic-action-hide-topic": "Ocultar tópico",
"flow-topic-action-delete-topic": "Eliminar tópico",
- "flow-topic-action-lock-topic": "Marcar como resolvido",
+ "flow-topic-action-lock-topic": "Marcar como encerrado",
"flow-topic-action-unlock-topic": "Reabrir tópico",
"flow-topic-action-summarize-topic": "Resumir",
"flow-topic-action-resummarize-topic": "Editar resumo do tópico",
- "flow-topic-action-update-topic-summary": "Atualizar sumário",
+ "flow-topic-action-update-topic-summary": "Atualizar resumo",
"flow-topic-action-suppress-topic": "Suprimir tópico",
- "flow-topic-action-unhide-topic": "Exibir tópico",
+ "flow-topic-action-unhide-topic": "Mostrar tópico",
"flow-topic-action-undelete-topic": "Restaurar tópico",
- "flow-topic-action-unsuppress-topic": "Tópico não suprimido",
+ "flow-topic-action-unsuppress-topic": "Retirar supressão do tópico",
"flow-topic-action-restore-topic": "Restaurar tópico",
"flow-topic-action-undo-moderation": "Desfazer",
- "flow-topic-notification-subscribe-title": "Este tópico foi adicionado à {{GENDER:$1|sua}} lista de vigiados.",
+ "flow-topic-notification-subscribe-title": "Este tópico foi adicionado à {{GENDER:$1|sua}} lista de páginas vigiadas.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Irá}} receber notificações sobre todas as atividades neste tópico.",
- "flow-board-notification-subscribe-title": "Está {{GENDER:$1|inscrito|inscrita|inscrito(a)}} neste espaço de discussão!",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|Receberá}} uma notificação quando um novo tópico for adicionado.",
+ "flow-board-notification-subscribe-title": "Está {{GENDER:$1|inscrito|inscrita}} neste espaço de discussão!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Receberá}} uma notificação quando um novo tópico for adicionado neste espaço.",
"flow-topic-action-watchlist-add": "Vigiar este tópico",
"flow-topic-action-watchlist-remove": "Deixar de vigiar",
+ "flow-error-allowcreation-no-usedb": "Ativar o Flow numa página específica requer que <var>$wgContentHandlerUseDB</var> seja <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "A página já existe no destino, por isso não pode ser movido para lá um espaço de discussão Flow.",
"flow-error-allowcreation-flow-create-board": "O utilizador não possui o privilégio \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Neste momento não pode participar. Tente autenticar-se.",
+ "flow-error-can-not-edit-logged-in": "Neste momento não pode participar, porque não tem os privilégios necessários.",
"flow-error-http": "Ocorreu um erro ao contactar o servidor.",
- "flow-error-other": "Ocorreu um erro inesperado.",
- "flow-error-external": "Ocorreu um erro.<br />A mensagem de erro recebida é a seguinte: $1",
- "flow-error-topic-is-locked": "Este tópico está resolvido, portanto não é possível nenhuma atividade.",
- "flow-error-lock-moderated-post": "Não pode marcar uma mensagem como resolvida.",
- "flow-error-external-multi": "Foram encontrados erros.<br /> $1",
+ "flow-error-external": "Ocorreu um erro. A mensagem de erro recebida foi a seguinte: $1",
+ "flow-error-topic-is-locked": "Este tópico está encerrado, portanto não é possível mais nenhuma atividade.",
+ "flow-error-lock-moderated-post": "Não pode marcar uma mensagem moderada como encerrada.",
"flow-error-missing-content": "A mensagem não tem conteúdo. É necessário haver conteúdo para gravar uma mensagem.",
- "flow-error-missing-summary": "Deve apresentar um resumo.",
+ "flow-error-missing-summary": "Tem de enviar um resumo.",
"flow-error-missing-title": "O tópico não tem título. É necessário definir um título para gravar um tópico.",
- "flow-error-parsoid-failure": "Não foi possível analisar o conteúdo devido a uma falha do Parsoid.",
- "flow-error-missing-replyto": "Não foi fornecido nenhum parâmetro \"responderA\". Este parâmetro é necessário para a ação de \"resposta\".",
- "flow-error-invalid-replyto": "Parâmetro \"responderA\" inválido. A mensagem especificada não pôde ser encontrada.",
- "flow-error-delete-failure": "A eliminação deste item falhou.",
- "flow-error-hide-failure": "Falha ao ocultar este item.",
- "flow-error-missing-postId": "Não foi fornecido nenhum parâmetro \"IDpost\". Este parâmetro é necessário para a manutenção da mensagem.",
- "flow-error-invalid-postId": "Parâmetro \"postID\" inválido. A mensagem especificada ($1) não pôde ser encontrada.",
- "flow-error-restore-failure": "A restauração deste item falhou.",
- "flow-error-invalid-moderation-state": "Um valor inválido para o parâmetro ('moderationState') foi fornecido ao API do Flow.",
+ "flow-error-parsoid-failure": "Não foi possível transferir o conteúdo: Erro ao contactar o servidor para a conversão entre texto wiki e HTML. Por favor, verifique a sua ligação à Internet ou tente novamente mais tarde, se o problema persistir. Se continuar a receber este erro reporte-o, por favor",
+ "flow-error-protected-autoconfirmed-logged-in": "Este espaço de discussão está protegido. Só podem participar utilizadores autoconfirmados. Motivo: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Este espaço de discussão está protegido. Só podem participar utilizadores autenticados que estejam autoconfirmados. Motivo: $1",
+ "flow-error-protected-sysop-logged-in": "Este espaço de discussão está protegido. Só podem participar utilizadores com privilégios de administrador. Motivo: $1",
+ "flow-error-protected-sysop-logged-out": "Este espaço de discussão está protegido. Só podem participar utilizadores autenticados que tenham privilégios de administrador. Motivo: $1",
+ "flow-error-protected-unknown-reason": "Desconhecido",
+ "flow-error-missing-replyto": "Não foi fornecido nenhum parâmetro \"replyTo\". Este parâmetro é necessário para a ação \"reply\".",
+ "flow-error-missing-postId": "Não foi fornecido nenhum parâmetro \"postId\". Este parâmetro é necessário para a manutenção da mensagem.",
+ "flow-error-invalid-postId": "O parâmetro \"postId\" era inválido. Não foi possível encontrar a mensagem especificada ($1).",
+ "flow-error-invalid-moderation-state": "Foi enviado à API do Flow um valor inválido para o parâmetro ('moderationState').",
"flow-error-invalid-moderation-reason": "Por favor, indique um motivo para a moderação.",
"flow-error-not-allowed": "Permissões insuficientes para executar esta ação.",
"flow-error-not-allowed-hide": "Este tópico foi ocultado.",
@@ -147,41 +186,48 @@
"flow-error-not-allowed-reply-to-delete-topic-extract": "Não pode responder porque este tópico foi eliminado. O registo de eliminação para o tópico é fornecido abaixo para referência.",
"flow-error-not-allowed-suppress-extract": "Este tópico foi eliminado. O registo de eliminação para o tópico é fornecido abaixo para referência.",
"flow-error-not-allowed-reply-to-suppress-topic-extract": "Não pode responder porque este tópico foi suprimido. O registo de supressão para o tópico é fornecido abaixo para referência.",
- "flow-error-title-too-long": "Os títulos dos tópicos estão restritos a {{PLURAL:$1|byte|bytes}}.",
+ "flow-error-title-too-long": "Os títulos dos tópicos estão restritos a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-no-existing-workflow": "Este fluxo de trabalho não existe ainda.",
"flow-error-not-a-post": "O título do tópico não pode ser gravado como uma mensagem.",
- "flow-error-missing-header-content": "Deve apresentar uma descrição.",
+ "flow-error-missing-header-content": "Tem de enviar uma descrição.",
"flow-error-missing-prev-revision-identifier": "O identificador de revisão anterior está em falta.",
- "flow-error-prev-revision-mismatch": "Outro utilizador editou esta mensagem há alguns segundos. {{GENDER:$3|Tem}} a certeza que pretende substituir esta alteração recente?",
+ "flow-error-prev-revision-mismatch": "Um outro utilizador editou esta mensagem há poucos segundos. {{GENDER:$3|Tem}} a certeza de que pretende substituir esta alteração recente?",
"flow-error-prev-revision-does-not-exist": "Não foi possível encontrar a revisão anterior.",
+ "flow-error-core-topic-deletion": "Para eliminar um tópico, use o menu ... no espaço de discussão Flow ou na [$1 página do tópico]. Não visite diretamente action=delete para o tópico.",
"flow-error-default": "Ocorreu um erro.",
- "flow-error-invalid-input": "Foi fornecido um valor inválido para carregar o conteúdo do fluxo.",
+ "flow-error-invalid-input": "Foi fornecido um valor inválido para carregar o conteúdo do Flow.",
"flow-error-invalid-title": "Foi inserido um título de página inválido.",
+ "flow-error-invalid-parameter": "Parâmetro em falta ou inválido passado na chamada a um método",
"flow-error-fail-load-history": "Falha ao carregar o conteúdo do histórico.",
- "flow-error-missing-revision": "Não foi possível encontrar uma revisão para carregar o conteúdo do fluxo.",
- "flow-error-fail-commit": "Falha ao gravar o conteúdo do fluxo.",
+ "flow-error-missing-revision": "Não foi possível encontrar uma revisão para carregar o conteúdo do Flow.",
+ "flow-error-fail-commit": "Falha ao gravar o conteúdo do Flow.",
"flow-error-insufficient-permission": "Permissões insuficientes para aceder ao conteúdo.",
- "flow-error-revision-comparison": "A operação só pode ser efectuada com duas revisões pertencentes à mesma mensagem.",
- "flow-error-missing-topic-title": "Não foi possível encontrar o título do tópico no fluxo de trabalho actual.",
- "flow-error-missing-metadata": "Não foi possível encontrar os metadados necessários para esta edição.",
+ "flow-error-revision-comparison": "A determinação de diferenças só pode ser feita entre duas revisões da mesma mensagem.",
+ "flow-error-missing-topic-title": "Não foi possível encontrar o título do tópico no fluxo de trabalho atual.",
+ "flow-error-missing-metadata": "Não foi possível encontrar os metadados necessários para esta revisão.",
+ "flow-error-different-page": "O fluxo de trabalho Flow não está associado com esta página.",
"flow-error-fail-load-data": "Falha ao carregar os dados solicitados.",
"flow-error-invalid-workflow": "Não foi possível encontrar o fluxo de trabalho solicitado.",
"flow-error-process-data": "Ocorreu um erro ao processar os dados que foram pedidos por si.",
- "flow-error-process-wikitext": "Ocorreu um erro durante o processamento de conversão HTML/wikitexto.",
+ "flow-error-process-wikitext": "Ocorreu um erro durante o processamento de conversão HTML/texto wiki.",
"flow-error-no-index": "Falha ao localizar um índice para executar a pesquisa de dados.",
"flow-error-no-render": "A ação especificada não foi reconhecida.",
"flow-error-no-commit": "Não foi possível gravar a ação especificada.",
- "flow-error-content-too-long": "O conteúdo é muito grande. Após a expansão, o conteúdo é limitado a $1 {{PLURAL:$1|byte|bytes}}.",
+ "flow-error-content-too-long": "O conteúdo é demasiado grande. O conteúdo após a expansão está limitado a $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-move-topic": "Mover um tópico não é permitido de momento.",
"flow-error-invalid-topic-uuid-title": "Título inválido",
"flow-error-invalid-topic-uuid": "O título da página fornecida é inválido. Páginas no domínio Tópico são criadas automaticamente pelo Flow.",
"flow-error-unknown-workflow-id-title": "Tópico desconhecido",
"flow-error-unknown-workflow-id": "O tópico solicitado não existe.",
"flow-error-search": "Não foi possível concluir a pesquisa devido a um problema temporário. Tente novamente mais tarde, por favor.",
+ "flow-error-invalid-undelete": "Esta página não pode ser restaurada porque contém neste momento um espaço de discussão.",
"flow-edit-header-placeholder": "Descreva este espaço de discussão",
"flow-edit-header-submit": "Gravar descrição",
+ "flow-edit-header-submit-anonymously": "Gravar descrição anonimamente",
"flow-edit-title-submit": "Alterar título",
+ "flow-edit-title-submit-anonymously": "Alterar título anonimamente",
"flow-edit-post-submit": "Enviar alterações",
+ "flow-edit-post-submit-anonymously": "Enviar alterações anonimamente",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|editou}} um [$3 comentário] em \"$4\".",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Editou}} uma mensagem",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|comentou}}] em \"$4\" (<em>$5</em>).",
@@ -200,13 +246,13 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|ocultou}} o [$4 tópico] \"$6\" (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|eliminou}} o [$4 tópico] \"$6\" (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|suprimiu}} o [$4 tópico] \"$6\" (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcou}} o [$4 tópico] $6 como resolvido (<em>$5</em>)",
- "flow-rev-message-lock-topic-reason": "marcar como resolvido",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|marcou}} o [$4 tópico] \"$6\" como encerrado (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "marcado como encerrado",
"flow-rev-message-restore-topic-reason": "reaberto",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|restaurou}} o [$4 tópico] \"$6\" (<em>$5</em>).",
"flow-rc-topic-of-board": "$1 em $2",
"flow-board-history": "Histórico de \"$1\"",
- "flow-board-history-empty": "Atualmente, este espaço não tem histórico.",
+ "flow-board-history-empty": "Este espaço de discussão não tem histórico.",
"flow-topic-history": "Histórico do tópico \"$1\"",
"flow-post-history": "Histórico de \"Comentário por {{GENDER:$2|$2}}\"",
"flow-history-last4": "Últimas 4 horas",
@@ -223,50 +269,92 @@
"flow-comment-moderated": "Comentário moderado",
"flow-last-modified": "Modificado pela última vez em $1",
"flow-workflow": "fluxo de trabalho",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 \"$2\"]</span><br />$1 {{GENDER:$1|respondeu}} em \"$4\".",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 \"$2\"]</span><br />$1 e $5 {{PLURAL:$6|outro|outros}} {{GENDER:$1|responderam}} em \"$3\".",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 \"$2\"]</span><br />$1 {{GENDER:$1|respondeu}} em <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 e {{PLURAL:$5|outro utilizador|$5 outros utilizadores|100=mais de 99 outros utilizadores}} {{GENDER:$1|responderam}} em <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|editou}} a sua <span class=\"plainlinks\">[$5 mensagem]</span> em [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 e $5 {{PLURAL:$6|outro|outros}} {{GENDER:$1|editaram}} uma <span class=\"plainlinks\">[$4 mensagem]</span> em \"$2\", em \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|criou}} um novo tópico em '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 novo tópico|$1 novos tópicos|250=+250 novos tópicos}} em '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 e {{PLURAL:$5|outro utilizador|$5 outros utilizadores|100=mais de 99 outros}} {{GENDER:$1|editaram}} uma <span class=\"plainlinks\">[$4 mensagem]</span> em \"$2\", em \"$3\".",
+ "notification-header-flow-new-topic-v2": "Novo tópico criado em <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=Mais de 99 novos tópicos}} em <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Foi criado um novo tópico na <strong>sua página de discussão</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=Mais de 99 novos tópicos}} na <strong>sua página de discussão</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|respondeu}} em \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Uma nova resposta|$1 novas respostas|100=Mais de 99 novas respostas}} em \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|respondeu}} na <strong>sua página de discussão</strong> em \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Uma nova resposta|$1 novas respostas|100=Mais de 99 novas respostas}} na <strong>sua página de discussão</strong> em \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "A {{GENDER:$2|sua}} mensagem em \"<strong>$1</strong>\" foi editada.",
+ "notification-bundle-header-flow-post-edited-v2": "A {{GENDER:$2|sua}} mensagem em \"<strong>$1</strong>\" foi editada diversas vezes.",
+ "notification-header-flow-post-edited-user-talk": "Uma mensagem em \"<strong>$1</strong>\" foi editada <strong>na {{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Uma mensagem em \"<strong>$1</strong>\" foi editada diversas vezes <strong>na {{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-header-flow-topic-renamed-v2": "O nome do tópico \"<strong>$1</strong>\" foi alterado para \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "O nome do tópico \"<strong>$1</strong>\" foi alterado para \"<strong>$2</strong>\" na <strong>{{GENDER:$3|sua}} página de discussão</strong>.",
+ "notification-header-flow-summary-edited": "O resumo para \"<strong>$1</strong>\" foi atualizado.",
+ "notification-header-flow-summary-edited-first": "O tópico \"<strong>$1</strong>\" foi resumido.",
+ "notification-bundle-header-flow-summary-edited": "O resumo de \"<strong>$1</strong>\" foi atualizado várias vezes.",
+ "notification-header-flow-summary-edited-user-talk": "O resumo de \"<strong>$1</strong>\" foi atualizado na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "O tópico \"<strong>$1</strong>\" foi resumido na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "O resumo de \"<strong>$1</strong>\" foi atualizado várias vezes na <strong>{{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|atualizou}} o resumo de $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|atualizou}} o resumo de $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 e {{PLURAL:$3|outro utilizador|$3 outros utilizadores|100=mais de 99 outros utilizadores}} {{GENDER:$1|atualizaram}} o resumo em $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$4|o|a}} em \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$4|o|a}} na descrição de <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|mencionou-}}{{GENDER:$4|o|a}} em \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Novo sistema de discussão para <strong>{{GENDER:$2|a sua}} página de discussão</strong>.",
+ "notification-header-flow-description-edited": "A descrição de <strong>$1</strong> foi editada.",
+ "notification-header-flow-description-edited-user-talk": "A descrição foi editada <strong>na {{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-bundle-header-flow-description-edited": "A descrição de <strong>$1</strong> foi editada várias vezes.",
+ "notification-bundle-header-flow-description-edited-user-talk": "A descrição foi editada diversas vezes <strong>na {{GENDER:$2|sua}} página de discussão</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Ver}} página",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|editou}} a descrição em $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|editou}} a descrição em $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 e {{PLURAL:$3|outro utilizador|$3 outros utilizadores|100=mais de 99 outros utilizadores}} {{GENDER:$1|editaram}} a descrição em $2",
+ "notification-header-flow-topic-resolved": "O tópico \"<strong>$1</strong>\" foi encerrado.",
+ "notification-header-flow-topic-reopened": "O tópico \"<strong>$1</strong>\" foi reaberto.",
+ "notification-header-flow-topic-resolved-user-talk": "O tópico \"<strong>$1</strong>\" foi encerrado na <strong>sua página de discussão</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "O tópico \"<strong>$1</strong>\" foi reaberto na <strong>sua página de discussão</strong>.",
+ "notification-email-subject-flow-topic-resolved": "O tópico \"<strong>$2</strong>\" foi encerrado.",
+ "notification-email-batch-body-flow-topic-resolved": "O tópico \"<strong>$2</strong>\" foi encerrado.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|criou}} um novo tópico em <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=Mais de 99 novos tópicos}} em <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|modificou}} o título de <span class=\"plainlinks\">[$2 $3]</span> para \"$4\" em [[$5|$6]].",
- "flow-notification-mention": "$1 {{GENDER:$5|mencionou-o|mencionou-a}} {{GENDER:$1|na sua}} <span class=\"plainlinks\">[$2 mensagem]</span> em \"$3\" de \"$4\".",
+ "flow-notification-mention": "$1 {{GENDER:$1|mencionou-}}{{GENDER:$5|o|a}} na <span class=\"plainlinks\">[$2 mensagem]</span> {{GENDER:$1|dele|dela}} em \"$3\" de \"$4\".",
"flow-notification-link-text-view-post": "Ver mensagem",
"flow-notification-link-text-view-topic": "Ver tópico",
+ "flow-notification-link-text-view-topics": "Ver tópicos",
"flow-notification-reply-email-subject": "$2 em $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|respondeu}} a \"$2\" em $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 e $4 {{PLURAL:$5|outro|outros}} {{GENDER:$1|responderam}} à sua mensagem a \"$2\" em $3",
- "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mencionou-{{GENDER:$3|o|a|o(a)}}}} em $2",
- "flow-notification-mention-email-batch-body": "$1 {{GENDER:$4|mencionou-o|mencionou-a}} {{GENDER:$1|na sua}} mensagem em \"$2\" de $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 e {{PLURAL:$4|outro utilizador|$4 outros utilizadores|100=mais de 99 outros utilizadores}} {{GENDER:$1|responderam}} à sua mensagem a \"$2\" em $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$1|mencionou-}}{{GENDER:$3|o|a}} em $2",
+ "flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|mencionou-}}{{GENDER:$4|o|a}} na mensagem {{GENDER:$1|dele|dela}} em \"$2\" de $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|editou}} uma mensagem",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|editou}} uma mensagem em \"$2\" de $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 e $4 {{PLURAL:$5|outro|outros}} {{GENDER:$1|editaram}} uma mensagem em \"$2\" de $3",
- "flow-notification-rename-email-subject": "$1 {{GENDER:$1|renomeou}} o seu tópico",
- "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|renomeou}} o seu tópico \"$2\" para \"$3\" em $4",
+ "flow-notification-edit-email-batch-bundle-body": "$1 e {{PLURAL:$4|outro utilizador|$4 outros utilizadores|100=mais de 99 outros utilizadores}} {{GENDER:$1|editaram}} uma mensagem em \"$2\" de $3",
+ "flow-notification-rename-email-subject": "$1 {{GENDER:$1|alterou}} o nome do seu tópico",
+ "flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|alterou}} o nome do seu tópico \"$2\" para \"$3\" em $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|criou}} um novo tópico em $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|criou}} um novo tópico com o título \"$2\" em $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 novo tópico|$1 novos tópicos|250=+250 novos tópicos}} em $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Notificar-me quando ocorrerem ações relacionadas com o Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Um novo tópico|$1 novos tópicos|100=Mais de 99 novos tópicos}} em $2",
+ "echo-category-title-flow-discussion": "Discussão do Flow",
+ "echo-pref-tooltip-flow-discussion": "Notificar-me acerca da atividade nos tópicos ou nas páginas que estou a seguir.",
"flow-link-post": "mensagem",
"flow-link-topic": "tópico",
"flow-link-history": "histórico",
"flow-link-post-revision": "revisão de mensagem",
"flow-link-topic-revision": "revisão de tópico",
"flow-link-header-revision": "revisão de descrição",
- "flow-link-summary-revision": "resumo da revisão",
+ "flow-link-summary-revision": "revisão de resumo",
"flow-moderation-title-suppress-post": "Suprimir mensagem?",
"flow-moderation-title-delete-post": "Eliminar mensagem?",
"flow-moderation-title-hide-post": "Ocultar mensagem?",
"flow-moderation-title-unsuppress-post": "Retirar supressão da mensagem?",
"flow-moderation-title-undelete-post": "Restaurar mensagem?",
- "flow-moderation-title-unhide-post": "Voltar a exibir mensagem?",
- "flow-moderation-placeholder-suppress-post": "Por favor, {{GENDER:$3|indique}} a razão para a supressão desta mensagem.",
- "flow-moderation-placeholder-delete-post": "Por favor, {{GENDER:$3|indique}} a razão para a eliminação desta mensagem.",
+ "flow-moderation-title-unhide-post": "Voltar a mostrar a mensagem?",
+ "flow-moderation-placeholder-suppress-post": "Por favor, {{GENDER:$3|indique}} a razão para suprimir esta mensagem.",
+ "flow-moderation-placeholder-delete-post": "Por favor, {{GENDER:$3|indique}} a razão para eliminar esta mensagem.",
"flow-moderation-placeholder-hide-post": "Por favor, {{GENDER:$3|indique}} a razão para ocultar esta mensagem.",
- "flow-moderation-placeholder-unsuppress-post": "Por favor, {{GENDER:$3|indique}} a razão para voltar a exibir esta mensagem.",
- "flow-moderation-placeholder-undelete-post": "Por favor, {{GENDER:$3|indique}} a razão a restauração deste tópico.",
- "flow-moderation-placeholder-unhide-post": "Por favor, {{GENDER:$3|indique}} a razão para voltar a exibir esta mensagem.",
+ "flow-moderation-placeholder-unsuppress-post": "Por favor, {{GENDER:$3|indique}} a razão para retirar a supressão desta mensagem.",
+ "flow-moderation-placeholder-undelete-post": "Por favor, {{GENDER:$3|indique}} a razão para restaurar esta mensagem.",
+ "flow-moderation-placeholder-unhide-post": "Por favor, {{GENDER:$3|indique}} a razão para voltar a mostrar esta mensagem.",
"flow-moderation-confirm-suppress-post": "Suprimir",
"flow-moderation-confirm-delete-post": "Eliminar",
"flow-moderation-confirm-hide-post": "Ocultar",
@@ -279,51 +367,53 @@
"flow-moderation-confirm-unsuppress-topic": "Retirar supressão",
"flow-moderation-confirm-undelete-topic": "Restaurar",
"flow-moderation-confirm-unhide-topic": "Mostrar",
- "flow-moderation-confirmation-suppress-post": "A mensagem foi suprimida com sucesso. {{GENDER:$2|Considere}} comentar esta ação com $1.",
- "flow-moderation-confirmation-delete-post": "A mensagem foi eliminada com sucesso. {{GENDER:$2|Considere}} comentar esta ação com $1.",
- "flow-moderation-confirmation-hide-post": "A mensagem foi ocultada com sucesso. {{GENDER:$2|Considere}} comentar esta ação com $1.",
- "flow-moderation-confirmation-unsuppress-post": "Retirou a supressão da mensagem acima com sucesso.",
- "flow-moderation-confirmation-undelete-post": "A mensagem acima foi restaurada com sucesso.",
- "flow-moderation-confirmation-unhide-post": "A mensagem acima está a ser exibida novamente.",
+ "flow-moderation-confirmation-suppress-post": "A mensagem foi suprimida. \n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-delete-post": "A mensagem foi eliminada.\n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-hide-post": "A mensagem foi ocultada. \n{{GENDER:$2|Considere}} comentar esta ação com $1.",
+ "flow-moderation-confirmation-unsuppress-post": "Retirou a supressão da mensagem acima.",
+ "flow-moderation-confirmation-undelete-post": "Restaurou a mensagem acima.",
+ "flow-moderation-confirmation-unhide-post": "Mostrou a mensagem acima.",
"flow-moderation-confirmation-suppress-topic": "Este tópico foi suprimido.",
"flow-moderation-confirmation-delete-topic": "Este tópico foi eliminado.",
"flow-moderation-confirmation-hide-topic": "Este tópico foi ocultado.",
- "flow-moderation-confirmation-unsuppress-topic": "Retirou a supressão deste tópico com sucesso.",
- "flow-moderation-confirmation-undelete-topic": "O tópico foi restaurado com sucesso.",
- "flow-moderation-confirmation-unhide-topic": "O tópico acima está a ser exibido novamente.",
+ "flow-moderation-confirmation-unsuppress-topic": "Retirou a supressão deste tópico.",
+ "flow-moderation-confirmation-undelete-topic": "Restaurou este tópico.",
+ "flow-moderation-confirmation-unhide-topic": "O tópico acima está a ser mostrado novamente.",
"flow-moderation-title-suppress-topic": "Suprimir tópico?",
"flow-moderation-title-delete-topic": "Eliminar tópico?",
"flow-moderation-title-hide-topic": "Ocultar tópico?",
"flow-moderation-title-unsuppress-topic": "Retirar supressão do tópico?",
"flow-moderation-title-undelete-topic": "Restaurar tópico?",
- "flow-moderation-title-unhide-topic": "Exibir novamente o tópico?",
- "flow-moderation-placeholder-suppress-topic": "Por favor, {{GENDER:$3|indique}} o motivo para a supressão deste tópico.",
- "flow-moderation-placeholder-delete-topic": "Por favor, {{GENDER:$3|indique}} o motivo para a eliminação deste tópico.",
+ "flow-moderation-title-unhide-topic": "Voltar a mostrar o tópico?",
+ "flow-moderation-placeholder-suppress-topic": "Por favor, {{GENDER:$3|indique}} o motivo para suprimir este tópico.",
+ "flow-moderation-placeholder-delete-topic": "Por favor, {{GENDER:$3|indique}} o motivo para eliminar este tópico.",
"flow-moderation-placeholder-hide-topic": "Por favor, {{GENDER:$3|indique}} o motivo para ocultar este tópico.",
"flow-moderation-placeholder-unsuppress-topic": "Por favor, {{GENDER:$3|indique}} o motivo para retirar a supressão deste tópico.",
"flow-moderation-placeholder-undelete-topic": "Por favor, {{GENDER:$3|indique}} o motivo para restaurar este tópico.",
- "flow-moderation-placeholder-unhide-topic": "Por favor, {{GENDER:$3|indique}} o motivo para exibir de novo este tópico.",
+ "flow-moderation-placeholder-unhide-topic": "Por favor, {{GENDER:$3|indique}} o motivo para voltar a mostrar este tópico.",
"flow-topic-permalink-warning": "Este tópico foi iniciado em [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Este tópico foi iniciado no [$2 espaço de {{GENDER:$1|$1}}]",
- "flow-revision-permalink-warning-post": "Esta é uma ligação permanente para a versão simples desta mensagem. \nEsta versão é de $1. \nPode ver as [$5 diferenças das outras versões], ou ver outras versões na [$4 página do histórico da mensagem].",
- "flow-revision-permalink-warning-post-first": "Esta é uma ligação permanente para a primeira versão desta mensagem. \nPode ver outras versões na [$4 página de histórico da mensagem].",
- "flow-revision-permalink-warning-postsummary": "Esta é uma ligação permanente para a versão simples do resumo desta mensagem. Esta versão é de $1. \nPode ver as [$5 diferenças das outras versões], ou ver outras versões na [$4 página do histórico da mensagem].",
- "flow-revision-permalink-warning-postsummary-first": "Esta é uma ligação permanente para a primeira versão do resumo desta mensagem.\nPode ver outras versões na [$4 página de histórico da mensagem].",
- "flow-revision-permalink-warning-header": "Esta é uma ligação permanente para a versão simples da descrição. \nEsta versão é de $1. Pode ver as [$3 diferenças das outras versões], ou ver outras versões na [$2 página do histórico da mensagem].",
- "flow-revision-permalink-warning-header-first": "Esta é uma ligação permanente para a primeira versão da descrição.\nPode ver outras versões na [$2 página de histórico do espaço].",
+ "flow-topic-permalink-warning-user-board": "Este tópico foi iniciado no [$2 espaço de discussão de {{GENDER:$1|$1}}]",
+ "flow-revision-permalink-warning-post": "Esta é uma ligação permanente para uma versão desta mensagem. \nEsta versão é de $1. \nPode ver as [$5 diferenças para a versão anterior], ou ver outras versões na [$4 página do histórico da mensagem].",
+ "flow-revision-permalink-warning-post-first": "Esta é uma ligação permanente para a primeira versão desta mensagem. \nPode ver as versões posteriores na [$4 página de histórico da mensagem].",
+ "flow-revision-permalink-warning-postsummary": "Esta é uma ligação permanente para uma versão do resumo desta mensagem. Esta versão é de $1. \nPode ver as [$5 diferenças para a versão anterior], ou ver outras versões na [$4 página do histórico da mensagem].",
+ "flow-revision-permalink-warning-postsummary-first": "Esta é uma ligação permanente para a primeira versão do resumo desta mensagem.\nPode ver as versões posteriores na [$4 página de histórico da mensagem].",
+ "flow-revision-permalink-warning-header": "Esta é uma ligação permanente para uma versão da descrição. \nEsta versão é de $1. Pode ver as [$3 diferenças para a versão anterior], ou ver outras versões na [$2 página de histórico do espaço de discussão].",
+ "flow-revision-permalink-warning-header-first": "Esta é uma ligação permanente para a primeira versão da descrição.\nPode ver as versões posteriores na [$2 página de histórico do espaço de discussão].",
"flow-compare-revisions-revision-header": "Versão por {{GENDER:$2|$2}}, a $1",
- "flow-compare-revisions-header-post": "Esta página mostra as {{GENDER:$3|alterações}} entre duas versões de uma mensagem de $3, no tópico \"[$5 $2]\" em [$4 $1]. Pode ver outras versões desta mensagem no seu [$6 histórico].",
- "flow-compare-revisions-header-postsummary": "Esta página mostra as alterações entre duas versões de resumos da mensagem \"[$4 $2]\" em [$3 $1]. \nPode ver outras versões desta mensagem no seu [$5 histórico].",
- "flow-compare-revisions-header-header": "Esta página mostra as {{GENDER:$2|alterações}} entre duas versões da descrição em [$3 $1].\nPode ver outras versões desta mensagem no seu [$4 histórico].",
+ "flow-compare-revisions-header-post": "Esta página mostra as {{GENDER:$3|alterações}} entre duas versões de uma mensagem de $3, no tópico \"[$5 $2]\" em [$4 $1]. Pode ver outras versões desta mensagem na [$6 página de histórico].",
+ "flow-compare-revisions-header-postsummary": "Esta página mostra as alterações entre duas versões do resumo do tópico \"[$4 $2]\" em [$3 $1]. \nPode ver outras versões deste resumo na [$5 página de histórico] do tópico.",
+ "flow-compare-revisions-header-header": "Esta página mostra as {{GENDER:$2|alterações}} entre duas versões da descrição em [$3 $1].\nPode ver outras versões da descrição na [$4 página de histórico].",
+ "action-flow-create-board": "criar espaços de discussão do Flow em qualquer local",
+ "right-flow-create-board": "Criar espaços de discussão do Flow em qualquer local",
"right-flow-hide": "Ocultar tópicos e mensagens do Flow",
- "right-flow-lock": "Marcar tópicos do Flow como resolvidos",
+ "right-flow-lock": "Marcar tópicos do Flow como encerrados",
"right-flow-delete": "Eliminar tópicos e mensagens do Flow",
"right-flow-edit-post": "Editar mensagens do Flow de outros utilizadores",
"right-flow-suppress": "Suprimir revisões do Flow",
- "flow-terms-of-use-new-topic": "Ao clicar em \"{{int:flow-newtopic-save}}\", concorda com os termos de uso desta wiki.",
- "flow-terms-of-use-reply": "Ao clicar em \"{{int:flow-reply-link}}\", concorda com os termos de uso desta wiki.",
- "flow-terms-of-use-edit": "Ao gravar as suas alterações, concorda com os termos de uso desta wiki.",
- "flow-anon-warning": "Não está autenticado(a). Para receber atribuição com o seu nome em vez do seu endereço IP, pode [$1 iniciar sessão] ou [$2 criar uma conta].",
+ "flow-terms-of-use-new-topic": "Ao clicar em \"{{int:flow-newtopic-save}}\", concorda com as condições de uso desta wiki.",
+ "flow-terms-of-use-reply": "Ao clicar em \"{{int:flow-reply-link}}\", concorda com as condições de uso desta wiki.",
+ "flow-terms-of-use-edit": "Ao gravar as suas alterações, concorda com as condições de uso desta wiki.",
+ "flow-anon-warning": "Não se autenticou. Para receber atribuição com o seu nome em vez do seu endereço IP, pode [$1 iniciar uma sessão] ou [$2 criar uma conta].",
"flow-cancel-warning": "Introduziu texto neste formulário. Tem a certeza de que pretende descartá-lo?",
"flow-topic-first-heading": "Tópico em $1",
"flow-topic-html-title": "$1 em $2",
@@ -332,156 +422,117 @@
"flow-no-more-fwd": "Não existem tópicos antigos",
"flow-newest-topics": "Tópicos mais recentes",
"flow-recent-topics": "Últimos tópicos ativos",
- "flow-sorting-tooltip-newest": "Atualmente, {{GENDER:|está}} a ler os novos tópicos em primeiro lugar. Clique para mais opções de ordenação.",
- "flow-sorting-tooltip-recent": "Atualmente, {{GENDER:|está}} a ler os tópicos ativos mais recentes em primeiro lugar. Clique para mais opções de ordenação.",
+ "flow-sorting-tooltip-newest": "{{GENDER:|Está}} a ler primeiro os novos tópicos. Clique para mais opções de ordenação.",
+ "flow-sorting-tooltip-recent": "{{GENDER:|Está}} a ler primeiro os tópicos ativos mais recentes. Clique para mais opções de ordenação.",
"flow-toggle-small-topics": "Alterar para modo de tópicos pequenos",
"flow-toggle-topics": "Alternar para modo apenas de tópicos",
"flow-toggle-topics-posts": "Alterar para modo de tópicos e mensagens",
- "flow-terms-of-use-summarize": "Ao clicar em \"{{int:flow-topic-action-update-topic-summary}}\", concorda com os termos de uso desta wiki.",
+ "flow-terms-of-use-summarize": "Ao clicar em \"{{int:flow-topic-action-update-topic-summary}}\", concorda com as condições de uso desta wiki.",
"flow-terms-of-use-lock-topic": "Ao clicar em \"{{int:flow-topic-action-lock-topic}}\", concorda com as condições de uso desta wiki.",
"flow-terms-of-use-unlock-topic": "Ao clicar em \"{{int:flow-topic-action-unlock-topic}}\", concorda com as condições de uso desta wiki.",
"flow-whatlinkshere-post": "de uma [$1 mensagem]",
- "flow-whatlinkshere-header": "de uma [$1 descrição]",
+ "flow-whatlinkshere-header": "da [$1 descrição]",
"flow-whatlinkshere-post-summary": "do [$1 resumo]",
- "flow": "Flow",
- "flow-special-desc": "Esta página especial redirecciona para um fluxo de trabalho do Flow ou para uma mensagem de Flow após dado um Identificador Global Único.",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Esta página especial redireciona para um fluxo de trabalho Flow, ou para uma mensagem Flow, dado um Identificador Global Único.",
"flow-special-type": "Tipo",
- "flow-special-type-post": "Publicar",
+ "flow-special-type-post": "Mensagem",
"flow-special-type-workflow": "Fluxo de trabalho",
"flow-special-uuid": "Identificador Global Único",
- "flow-special-invalid-uuid": "Não foi possível encontrar o conteúdo correspondente com o tipo e o UUID.",
+ "flow-special-invalid-uuid": "Não foi possível encontrar o conteúdo correspondente ao tipo e Identificador Global Único.",
"flow-special-enableflow-legend": "Ativar Flow numa página nova",
- "flow-special-enableflow-header": "Descrição inicial do espaço de discussão Flow (wikitexto)",
+ "flow-special-enableflow-page": "Página onde o Flow será ativado",
+ "flow-special-enableflow-header": "Descrição inicial do espaço de discussão Flow (texto wiki)",
"flow-special-enableflow-board-already-exists": "Já existe um espaço de discussão Flow em [[$1]].",
"flow-special-enableflow-invalid-title": "Foi fornecido um título de página inválido",
"flow-special-enableflow-board-creation-not-allowed": "Não possui permissão para criar um espaço de discussão Flow em [[:$1]].",
- "flow-special-enableflow-confirmation": "Criou com sucesso um espaço de discussão Flow em [[$1]].",
+ "flow-special-enableflow-page-is-liquidthreads": "Há uma página LiquidThreads em [[:$1]].",
+ "flow-special-enableflow-confirmation": "Criou um espaço de discussão Flow em [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Arquivo %d\n%s/Arquivo%d\n%s/arquivo %d\n%s/arquivo%d",
- "flow-spam-confirmedit-form": "Por favor, confirme que é um ser humano ao resolver o código CAPTHA abaixo: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Arquivo Flow %d\n%s/ArquivoFlow%d",
+ "flow-spam-confirmedit-form": "Confirme que é um ser humano, por favor, resolvendo o código CAPTHA abaixo: $1",
+ "flow-spam-confirmedit-using-failure": "Ocorreu um erro técnico com o CAPTCHA. Se não consegue enviar a alteração, faça uma cópia do seu texto, recarregue a página e tente novamente.",
"flow-embedding-unsupported": "As discussões ainda não podem ser incorporadas.",
- "mw-ui-unsubmitted-confirm": "Esta página possui alterações que ainda não foram gravadas. Tem a certeza que pretende continuar a navegar e perder todo o seu trabalho?",
- "flow-post-undo-hide": "desfazer ocultar",
+ "mw-ui-unsubmitted-confirm": "Esta página tem alterações que ainda não foram gravadas. Tem a certeza de que pretende continuar a navegar e perder todo o seu trabalho?",
+ "flow-post-undo-hide": "desfazer ocultação",
"flow-post-undo-delete": "desfazer eliminação",
"flow-post-undo-suppress": "desfazer supressão",
- "flow-topic-undo-hide": "desfazer ocultar",
+ "flow-topic-undo-hide": "desfazer ocultação",
"flow-topic-undo-delete": "desfazer eliminação",
"flow-topic-undo-suppress": "desfazer supressão",
+ "flow-importer-lqt-moved-thread-template": "Esboço de tópico movido LQT convertido para Flow",
+ "flow-importer-lqt-moved-thread-template-content": "Esta mensagem de {{{author}}} foi movida a {{{date}}}. Pode encontrá-la em [[{{{title}}}]].",
"flow-importer-lqt-converted-template": "Página LQT convertida para Flow",
+ "flow-importer-lqt-converted-template-content": "O histórico da página anterior foi arquivado, para fins de cópia de segurança, em <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> em {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Arquivo da página LQT convertida",
- "flow-importer-wt-converted-template": "Página de discussão em wikitexto convertida para o Flow",
- "flow-importer-wt-converted-archive-template": "Arquivo para a página de discussão em wikitexto convertida",
- "apihelp-flow-description": "Permite que ações sejam realizadas nas páginas que utilizam o Flow",
- "apihelp-flow-param-submodule": "Submódulo do Flow a ser invocado.",
- "apihelp-flow-param-page": "A página sobre a qual será tomada uma ação",
- "apihelp-flow-example-1": "Editar a descrição de \"[[Talk:Sandbox]]\".",
- "apihelp-flow+close-open-topic-description": "Depreciado em favor de [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Estado em que o tópico será colocado, se \"lock\" (fechado) ou \"unlock\" (aberto).",
- "apihelp-flow+close-open-topic-param-reason": "Motivo para bloquear ou desbloquear o tópico.",
- "apihelp-flow+edit-header-description": "Editar a descrição de um espaço de discussão.",
- "apihelp-flow+edit-header-param-prev_revision": "ID da revisão atual da descrição, para conferir conflitos entre edições.",
- "apihelp-flow+edit-header-param-content": "Conteúdo para a descrição.",
- "apihelp-flow+edit-header-example-1": "Editar a descrição de [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Editar publicação",
- "apihelp-flow+edit-post-param-postId": "ID da publicação.",
- "apihelp-flow+edit-post-param-prev_revision": "ID da revisão atual da publicação, para conferir conflitos entre edições.",
- "apihelp-flow+edit-post-param-content": "Conteúdo para a publicação.",
- "apihelp-flow+edit-post-example-1": "Editar uma publicação em [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Edita o título de um tópico.",
- "apihelp-flow+edit-title-param-prev_revision": "ID da revisão atual do título, para conferir conflitos entre edições.",
- "apihelp-flow+edit-title-param-content": "Conteúdo para o título.",
- "apihelp-flow+edit-title-example-1": "Editar o título de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Editar o conteúdo do sumário de um tópico.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "ID da revisão atual do sumário do tópico, se houver, para conferir conflitos entre edições.",
- "apihelp-flow+edit-topic-summary-param-summary": "Conteúdo para o sumário.",
- "apihelp-flow+edit-topic-summary-example-1": "Editar o sumário de [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Bloquear ou desbloquear um tópico do Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Estado em que o tópico será colocado, se <kbd>lock</kbd> (fechado) ou <kbd>unlock</kbd> (aberto).",
- "apihelp-flow+lock-topic-param-reason": "Motivo para bloquear ou desbloquear o tópico. Note que o cliente Flow da wiki utiliza aqui \"Marcado como resolvido\", e, se desejado, coloca informação adicional no sumário.",
- "apihelp-flow+lock-topic-example-1": "Bloquear [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Moderar uma publicação com Flow",
- "apihelp-flow+moderate-post-param-moderationState": "Nível de moderação",
- "apihelp-flow+moderate-post-param-reason": "Razão para moderação.",
- "apihelp-flow+moderate-post-param-postId": "ID da publicação a moderar.",
- "apihelp-flow+moderate-post-example-1": "Eliminar uma publicação no tópico [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Moderar um tópico do Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "Nível de moderação.",
- "apihelp-flow+moderate-topic-param-reason": "Razão para moderação.",
- "apihelp-flow+moderate-topic-example-1": "Eliminar o tópico [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Criar um novo tópico do Flow no fluxo de trabalho dado.",
- "apihelp-flow+new-topic-param-topic": "Texto para novo título de tópico.",
- "apihelp-flow+new-topic-param-content": "Conteúdo para a resposta inicial do tópico.",
- "apihelp-flow+new-topic-example-1": "Criar um novo tópico em [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Respostas a uma publicação.",
- "apihelp-flow+reply-param-replyTo": "ID da publicação a responder.",
- "apihelp-flow+reply-param-content": "Conteúdo para novo tópico.",
- "apihelp-flow+reply-example-1": "Resposta a uma publicação em [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Formato em que o conteúdo deverá ser retornado.",
- "apihelp-flow+view-header-description": "Ver descrição de um espaço de discussão.",
- "apihelp-flow+view-header-param-revId": "Carregar esta revisão, em vez da mais recente.",
- "apihelp-flow+view-header-example-1": "Obter a descrição de [[Talk:Sandbox]] como wikitexto",
- "apihelp-flow+view-post-description": "Ver uma publicação.",
- "apihelp-flow+view-post-param-postId": "ID da publicação a ser visualizada.",
- "apihelp-flow+view-post-param-format": "Formato em que o conteúdo deverá ser retornado.",
- "apihelp-flow+view-post-example-1": "Obter o conteúdo de uma publicação em [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topic-description": "Ver um tópico.",
- "apihelp-flow+view-topic-example-1": "Ver [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-summary-description": "Ver o sumário de um tópico.",
- "apihelp-flow+view-topic-summary-param-format": "Formato em que o conteúdo deverá ser retornado.",
- "apihelp-flow+view-topic-summary-param-revId": "Carregar esta revisão, em vez da mais recente.",
- "apihelp-flow+view-topic-summary-example-1": "Ver o sumário de [[Topic:S2tycnas4hcucw8w]] como wikitexto",
- "apihelp-flow+view-topiclist-description": "Ver uma lista de tópicos.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Direção para ordenar os tópicos.",
- "apihelp-flow+view-topiclist-param-sortby": "Opções de ordenação dos tópicos, se <kbd>updated</kbd> (ordenados pelo tempo de actualização do tópico) ou <kbd>newest</kbd> (ordenados pelo tempo de criação do tópico).",
- "apihelp-flow+view-topiclist-param-savesortby": "Salvar a opção de ordenação das preferências do utilizador, se estiver definida.",
- "apihelp-flow+view-topiclist-param-offset-id": "Valor inicial (no formato UUID) para a obtenção de tópicos; utilizado somente com a ordenação <kbd>newest</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Valor inicial para a obtenção de tópicos.",
- "apihelp-flow+view-topiclist-param-limit": "Número de tópicos a obter.",
- "apihelp-flow+view-topiclist-example-1": "Listar os tópicos em [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Converter texto entre wikitexto e HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Formato a partir do qual o conteúdo deverá ser convertido.",
- "apihelp-flow-parsoid-utils-param-to": "O formato para o qual o conteúdo deverá ser convertido.",
- "apihelp-flow-parsoid-utils-param-content": "Conteúdo a ser convertido.",
- "apihelp-flow-parsoid-utils-param-title": "Título da página. Não pode ser usado em conjunto com $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID da página. Não pode ser utilizado em conjunto com $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Converter o wikitexto <nowiki>'''lorem''' ''blá''</nowiki> para HTML",
- "apihelp-query+flowinfo-description": "Obter informações básicas do Flow sobre uma página.",
- "apihelp-query+flowinfo-example-1": "Obter informações do Flow sobre [[Talk:Sandbox]], [[Main Page]], e [[Talk:Flow]]",
+ "flow-importer-lqt-converted-archive-template-content": "Esta é uma página LiquidThreads arquivada. <strong>Não edite o conteúdo desta página</strong>. Remeta quaisquer comentários adicionais para a [[{{{from}}}|página de discussão atual]], por favor.",
+ "flow-importer-wt-converted-template": "Página de discussão em texto wiki convertida para o Flow",
+ "flow-importer-wt-converted-template-content": "A discussão anterior foi arquivada em <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> a {{#time: Y-m-d|{{{date}}}}}.",
+ "flow-importer-wt-converted-archive-template": "Arquivo para páginas de discussão em texto wiki convertidas",
+ "flow-importer-wt-converted-archive-template-content": "Esta página é um arquivo. <strong>Não edite o conteúdo desta página</strong>. Remeta quaisquer comentários adicionais para a [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|página de discussão atual]], por favor.",
+ "flow-importer-lqt-suppressed-user-template": "Mensagem LQT importada com utilizador suprimido",
+ "flow-importer-lqt-suppressed-user-template-content": "Esta revisão foi importada do LiquidThreads com um utilizador suprimido. Foi reatribuída ao utilizador atual.",
+ "flow-importer-lqt-different-author-signature-template": "Mensagem LQT importada com assinatura diferente do utilizador",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Esta mensagem foi publicada por [[User:{{{authorUser}}}|{{{authorUser}}}]], mas assinada como [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Editada",
"flow-edited-by": "Editada por $1",
- "flow-lqt-redirect-reason": "Redirecionando uma publicação com LiquidThreads redirecionada para a publicação com Flow correspondente",
- "flow-talk-conversion-move-reason": "Conversão de página de discussão em wikitexto para Flow a partir de $1",
- "flow-talk-conversion-archive-edit-reason": "Conversão de página de discussão em wikitexto para Flow",
+ "flow-edited-by-header": "Descrição do espaço de discussão editada por $1",
+ "flow-edited-by-topic-title": "Título do tópico editado por $1",
+ "flow-lqt-redirect-reason": "A redirecionar uma mensagem LiquidThreads retirada para a correspondente mensagem convertida Flow",
+ "flow-talk-conversion-move-reason": "Conversão de discussão em texto wiki $1 para Flow",
+ "flow-talk-conversion-archive-edit-reason": "Conversão de discussão em texto wiki para Flow",
"flow-previous-diff": "← Edição anterior",
"flow-next-diff": "Edição posterior →",
"flow-undo": "desfazer",
"flow-undo-latest-revision": "Última revisão",
"flow-undo-your-text": "O seu texto",
- "flow-undo-edit-header": "A editar descrição",
+ "flow-undo-edit-header": "A editar a descrição",
"flow-undo-edit-topic-summary": "A editar o resumo do tópico",
- "flow-undo-edit-post": "A editar mensagem",
+ "flow-undo-edit-post": "A editar uma mensagem",
"flow-undo-edit-content": "É possível desfazer a edição. Verifique a comparação abaixo, para se certificar que corresponde ao que pretende fazer. Depois grave as alterações, para finalizar e desfazer a edição.",
"flow-undo-edit-failure": "Não foi possível desfazer a edição por conflito com alterações intermédias.",
- "group-flow-bot": "Flow bots",
- "group-flow-bot-member": "Flow bot",
- "grouppage-flow-bot": "Project:Flow bots",
+ "group-flow-bot": "Robôs para o Flow",
+ "group-flow-bot-member": "robô para o Flow",
+ "grouppage-flow-bot": "Project:Robôs para o Flow",
"flow-ve-mention-context-item-label": "Mencionar",
"flow-ve-mention-inspector-title": "Menção",
"flow-ve-mention-inspector-remove-label": "Remover",
- "flow-ve-mention-placeholder": "Nome de utilizador(a)",
+ "flow-ve-mention-placeholder": "Nome de utilizador",
"flow-ve-mention-tool-title": "Mencionar um utilizador",
- "flow-ve-mention-inspector-invalid-user": "O nome de utilizador(a) \"$1\" não está registado.",
- "flow-wikitext-editor-help-preview-the-result": "pré-visualizar o resultado",
- "flow-wikitext-switch-editor-tooltip": "Mudar para o Editor Visual",
- "flow-ve-switch-editor-tool-title": "Mudar para o editor de wikitexto",
+ "flow-ve-mention-template-title": "FlowMention",
+ "flow-ve-mention-inspector-invalid-user": "O nome de utilizador \"$1\" não está registado.",
+ "flow-wikitext-editor-help": "O texto wiki $1.",
+ "flow-wikitext-editor-help-and-preview": "O texto wiki $1 e pode $2 a qualquer altura.",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|usa elementos de formatação]]",
+ "flow-wikitext-editor-help-preview-the-result": "antever o resultado",
+ "flow-wikitext-switch-editor-tooltip": "Mudar para o editor visual",
+ "flow-ve-switch-editor-tool-title": "Mudar para o editor de texto wiki",
"flow-mark-revision-patrolled-link-text": "Marcar esta página como patrulhada",
"flow-mark-revision-patrolled-link-title": "Marcar esta página como patrulhada",
"flow-mark-diff-patrolled-link-text": "Marcar como patrulhada",
"flow-mark-diff-patrolled-link-title": "Marcar como patrulhada",
- "flow-notification-link-text-enabled-on-talkpage": "Ver página de discussão de utilizador",
- "flow-notification-enabled-on-talkpage-title": "Novo sistema de discussão habilitado na {{GENDER:$1|sua}} página de discussão<br /><small>Disponível em [[$2]]</small>",
+ "flow-talk-page-beta-feature-message": "Flow na página de discussão",
+ "flow-talk-page-beta-feature-description": "Ativa um novo sistema de discussão estruturada na {{GENDER:|sua}} página de discussão. O Flow simplifica as discussões dos utilizadores, fornecendo campos claros onde escrever e responder, e permite notificações para cada tópico. Esta funcionalidade não é ativada automaticamente; os utilizadores terão de ativá-la em separado.<br /><br />As discussões existentes em texto wiki serão movidas para um arquivo. Desativar esta funcionalidade move o espaço de discussão Flow para uma subpágina e restaura a página de discussão anterior. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Mais informação sobre a ativação]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Ver}} página de discussão de utilizador",
+ "flow-notification-enabled-on-talkpage-title": "Novo sistema de discussão ativado na {{GENDER:$1|sua}} página de discussão<br /><small>Disponível em [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Novo sistema de discussão em $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, o novo sistema de discussões wiki, foi ativado na {{GENDER:$1|sua}} página de discussão da wiki {{SITENAME}}. Pode obter mais informação, dar a sua opinião ou desativar o novo sistema a qualquer altura a partir da secção de funcionalidades Beta nas {{GENDER:$1|suas}} preferências.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Predefinição de arquivo adicionada",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Predefinição de arquivo removida",
"flow-dialog-cancelconfirm-title": "Tem a certeza?",
"flow-dialog-cancelconfirm-message": "Tem a certeza de que pretende cancelar sem gravar antes?",
"flow-dialog-cancelconfirm-keep": "Continuar a editar",
- "flow-dialog-cancelconfirm-discard": "Rejeitar alterações"
+ "flow-dialog-cancelconfirm-discard": "Descartar alterações",
+ "flow-optin-archive-wikitext": "Página de texto wiki movida para dar lugar a um espaço de discussão.",
+ "flow-optin-archive-flow-board": "Espaço de discussão movido para dar lugar a uma página de texto wiki.",
+ "flow-optin-restore-wikitext": "Restauro de página de texto wiki arquivada.",
+ "flow-optin-restore-flow-board": "Restauro de espaço de discussão arquivado.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Bem-vindo|Bem-vinda|Bem-vindo(a)}} à {{GENDER:$1|sua}} nova página de discussão",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|A sua}} página de discussão é o local onde outros editores {{GENDER:$1|o|a}} podem contactar. Com o Flow, é fácil iniciar novos tópicos e acompanhar as conversas.",
+ "flow-guidedtour-optin-find-old-conversations": "Encontrar as {{GENDER:$1|suas}} conversas antigas",
+ "flow-guidedtour-optin-find-old-conversations-description": "Conversas mais antigas foram movidas para uma página de arquivo.",
+ "flow-guidedtour-optin-feedback": "Dê-nos {{GENDER:$1|a sua}} opinião!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Pode}} obter mais informação, dar a sua opinião ou desativar o novo sistema a qualquer altura a partir da secção de funcionalidades Beta.",
+ "flow-action-not-page": "O objeto página é uma instância da classe errada",
+ "flow-action-wrong-title-content-model": "A página está a ser tratada pelo Flow, mas a classe \"Title\" indica que o modelo de conteúdo é '$1'. Isto significa que há uma configuração incorreta ou um estado inconsistente. Por exemplo, pode resultar de uma página, que não é do Flow, criada num espaço nominal do Flow sem a propriedade <code>rev_content_model</code> populada."
}
diff --git a/Flow/i18n/qqq.json b/Flow/i18n/qqq.json
index 30fe84f0..f57f5ac5 100644
--- a/Flow/i18n/qqq.json
+++ b/Flow/i18n/qqq.json
@@ -18,25 +18,52 @@
"Metalhead64",
"Matthew Flaschen",
"Wladek92",
- "Tacsipacsi"
+ "Tacsipacsi",
+ "Mhutti1",
+ "Quiddity",
+ "Verdy p",
+ "Thibaut120094"
]
},
- "enableflow": "{{doc-special|EnableFlow}}",
- "flow-desc": "{{desc|name=Flow|url=https://www.mediawiki.org/wiki/Extension:Flow}}",
- "flow-talk-taken-over-comment": "Comment of the new revision that is created when a page turns into a Flow discussion board.",
- "log-name-flow": "{{doc-logpage}}\nName of the Flow log filter on the [[Special:Log]] page.",
- "logentry-delete-flow-delete-post": "Text for a deletion log entry when a post was deleted. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-delete-flow-restore-post": "Text for a deletion log entry when a deleted post was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-suppress-flow-suppress-post": "Text for a deletion log entry when a post was suppressed. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-suppress-flow-restore-post": "Text for a deletion log entry when a suppressed post was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-delete-flow-delete-topic": "Text for a deletion log entry when a topic was deleted. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-delete-flow-restore-topic": "Text for a deletion log entry when a deleted topic was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-suppress-flow-suppress-topic": "Text for a deletion log entry when a topic was suppressed. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-suppress-flow-restore-topic": "Text for a deletion log entry when a suppressed topic was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the moderated topic\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Flow-logentry}}",
- "logentry-import-lqt-to-flow-topic": "Text for an import log entry when a topic has been imported from LiquidThreads to Flow. Parameters:\n* $1 - The page within the topic namespace to which the topic was imported.\n* $2 - The title of the LiquidThreads thread being imported.\n* $3 - The board that was converted from LiquidThreads to Flow.",
+ "enablestructureddiscussions": "{{doc-special|EnableFlow}}",
+ "notification-dynamic-actions-flow-board-unwatch": "Text for the action offering the user to unwatch a board from within a notification.\n\nParameters:\n* $1 - Board name\n* $2 - Board URL\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "Title for the confirmation text for unwatching a board from within a notification.\n\nParameters:\n* $1 - Board name\n* $2 - Board URL\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Description for the confirmation text for unwatching a board from within a notification.\n\nParameters:\n* $1 - Board name\n* $2 - Board URL\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-flow-topic-unwatch": "Text for the action offering the user to unwatch a topic from within a notification.\n\nParameters:\n* $1 - Topic name\n* $2 - Topic URL\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "Title for the confirmation text for unwatching a topic from within a notification.\n\nParameters:\n* $1 - Topic name\n* $2 - Topic URL\n\n{{related|Notification-dynamic}}",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "Description for the confirmation text for unwatching a topic from within a notification.\n\nParameters:\n* $1 - Topic name\n* $2 - Topic URL\n\n{{related|Notification-dynamic}}",
+ "flow-desc": "{{desc|name=Flow|url=https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:StructuredDiscussions}}",
+ "flow-talk-taken-over-comment": "Comment of the new revision that is created when a page turns into a Structured Discussions board.",
+ "log-name-flow": "{{doc-logpage}}\nName of the Structured Discussions log filter on the [[Special:Log]] page.",
+ "logentry-delete-flow-delete-post": "Text for a deletion log entry when a post was deleted. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "Text for a deletion log entry when a post was deleted, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-restore-post": "Text for a deletion log entry when a deleted post was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "Text for a deletion log entry when a deleted post was restored, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-suppress-post": "Text for a deletion log entry when a post was suppressed. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "Text for a deletion log entry when a post was suppressed, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-restore-post": "Text for a deletion log entry when a suppressed post was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the post was moderated\n* $4 - permalink URL to the moderated post\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "Text for a deletion log entry when a suppressed post was restored, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-delete-topic": "Text for a deletion log entry when a topic was deleted. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the topic (unused)\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "Text for a deletion log entry when a topic was deleted, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-restore-topic": "Text for a deletion log entry when a deleted topic was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the topic (unused)\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "Text for a deletion log entry when a deleted topic was restored, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-suppress-topic": "Text for a deletion log entry when a topic was suppressed. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the topic (unused)\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "Text for a deletion log entry when a topic was suppressed, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-restore-topic": "Text for a deletion log entry when a suppressed topic was restored. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the moderated topic\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "Text for a deletion log entry when a suppressed topic was restored, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-lock-flow-lock-topic": "Text for a log entry when a topic was marked as resolved. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the topic (unused)\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "Text for a log entry when a topic was marked as resolved, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-lock-flow-restore-topic": "Text for a log entry when a resolved topic was reopened. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - the page where the topic was moderated\n* $4 - permalink URL to the moderated topic\n* $5 - The topic title text\n* $6 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "Text for a log entry when a resolved topic was reopened, and the topic title is not visible to the current user. Parameters:\n* $1 - the user: link to the user page\n* $2 - the username. Can be used for GENDER.\n* $3 - The board page\n{{Related|Logentry-flow}}",
+ "logentry-import-lqt-to-flow-topic": "Text for an import log entry when a topic has been imported from LiquidThreads to Structured Discussion board. Parameters:\n* $1 - The page within the topic namespace to which the topic was imported.\n* $2 - The title of the LiquidThreads thread being imported.\n* $3 - The board that was converted from LiquidThreads to Structured Discussion board.",
+ "abusefilter-edit-builder-vars-board-articleid": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
+ "abusefilter-edit-builder-vars-board-namespace": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
+ "abusefilter-edit-builder-vars-board-text": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Abuse filter syntax option in a dropdown from the group {{msg-mw|abusefilter-edit-builder-group-vars}}.",
"flow-user-moderated": "Name to display when the current user is not allowed to see the users name due to moderation",
"flow-board-header-browse-topics-link": "Text to show in the board description which links to the topics list.",
"flow-board-header": "Used as title for the board description in the side rail.",
+ "flow-board-description-can-not-edit": "Short message shown when user can not post to the board, e.g. because it is protected or the user is blocked",
"flow-board-collapse-description": "Used as title for the collapse description icon.",
"flow-board-expand-description": "Used as title for the expand description icon.",
"flow-topic-collapse-siderail": "Used as a title for the full width icon.",
@@ -64,7 +91,7 @@
"flow-post-actions": "Used as link text.\n{{Identical|Action}}",
"flow-topic-actions": "Used as link text.\n{{Identical|Action}}",
"flow-cancel": "Used as action link text.\n{{Identical|Cancel}}",
- "flow-skip-summary": "Used as action link text to skip summary.",
+ "flow-skip-summary": "Used as action link text to skip summary.\n{{Identical|Skip}}",
"flow-edit-summary-placeholder": "Used as placeholder text for the edit summary text field.",
"flow-summary-authored": "Used as summary author line when there is only one author or the first and last authors are the same. Parameters:\n* $1 Summary initial author, can be used for GENDER.",
"flow-summary-edited": "Used as summary author line when the summary was last updated by a user that is not the original author. Parameters:\n* $1 Summary last author, can be used for GENDER.",
@@ -83,20 +110,20 @@
"flow-reply-topic-placeholder": "Used as placeholder for the \"reply to this topic\" textarea. Parameters:\n* $1 - username of the logged in user, can be used for GENDER\n* $2 - topic title",
"flow-reply-topic-title-placeholder": "Used as placeholder for the content textarea when replying. Parameters:\n* $1 - When writing a top-level reply, the topic title. When replying to a comment, the first words of the comment to which the reply is being written.\n{{Identical|Reply to}}",
"flow-reply-link": "Text for the link that appears near the post and offers the user to reply to it. Clicking the link will display the reply editor. Also used for the Reply submit button. Parameters:\n* $1 - username, can be used for GENDER\n{{Identical|Reply}}",
- "flow-reply-link-anonymously": "Text for the link that appears near the post and offers an anonymous user to reply to it. Clicking the link will display the reply editor. Also used for the Reply submit button for anonymous users.\n{{Identical|Reply}}",
+ "flow-reply-link-anonymously": "Text for the link that appears near the post and offers an anonymous user to reply to it. Clicking the link will display the reply editor. Also used for the Reply submit button for anonymous users.",
"flow-thank-link": "Link text of the button that will (when clicked) thank the editor of the comment Parameters:\n* $1 - The user that is thanking, for gender\n* $2 - The user that is being thanked, for gender\n{{Identical|Thank}}",
"flow-thank-link-title": "Tooltip text of the button that will (when clicked) thank the editor of the comment. (Poster - one who posts a message, who has written a post)\n\nParameters:\n* $1 - The user that is thanking, for gender\n* $2 - The poster, the user that is being thanked, for gender",
- "flow-history-action-suppress-post": "Text link for suppressing a post or topic from the board history page.\n\nFor meaning of \"suppress\" see [[Thread:Support/About MediaWiki:Flow-post-action-suppress-post/qqq]] and [[Thread:Support/About MediaWiki:Flow-suppress-post-content/sv]].\n\n{{Identical|Suppress}}",
- "flow-history-action-delete-post": "Text link for deleting a post or topic from the board history page.\n{{Identical|Delete}}",
- "flow-history-action-hide-post": "Text link for hiding a post or topic from the board history page.\n{{Identical|Hide}}",
- "flow-history-action-unsuppress-post": "Text link for unsuppressing a post or topic from the board history page.\n{{Identical|Unsuppress}}",
- "flow-history-action-undelete-post": "Text link for undeleting a post or topic from the board history page.\n{{Identical|Undelete}}",
- "flow-history-action-unhide-post": "Text link for unhiding a post or topic from the board history page.\n{{Identical|Unhide}}",
- "flow-history-action-restore-post": "Text link for restoring a post or topic from the board history page.\n{{Identical|Restore}}",
- "flow-history-action-lock-topic": "Text link for resolving a post or topic from the board history page.\n{{Identical|Resolve}}",
- "flow-history-action-unlock-topic": "Text link for reopening a post or topic from the board history page.",
+ "flow-history-action-suppress-post": "Text link for suppressing a post or topic from the board history page.\n\nFor meaning of \"suppress\" see [[Thread:Support/About MediaWiki:Flow-post-action-suppress-post/qqq]] and [[Thread:Support/About MediaWiki:Flow-suppress-post-content/sv]].\n\n{{related|Flow-action}}\n{{Identical|Suppress}}",
+ "flow-history-action-delete-post": "Text link for deleting a post or topic from the board history page.\n{{related|Flow-action}}\n{{Identical|Delete}}",
+ "flow-history-action-hide-post": "Text link for hiding a post or topic from the board history page.\n{{related|Flow-action}}\n{{Identical|Hide}}",
+ "flow-history-action-unsuppress-post": "Text link for unsuppressing a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Unsuppress}}",
+ "flow-history-action-undelete-post": "Text link for undeleting a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Undelete}}",
+ "flow-history-action-unhide-post": "Text link for unhiding a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Unhide}}",
+ "flow-history-action-restore-post": "Text link for restoring a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Restore}}",
+ "flow-history-action-lock-topic": "Text link for resolving a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Resolve}}",
+ "flow-history-action-unlock-topic": "Text link for reopening a post or topic from the board history page.\n{{Related|Flow-action}}\n{{Identical|Reopen}}",
"flow-post-interaction-separator": "{{optional}}",
- "flow-post-edited": "Text displayed to notify the user a post has been modified. Parameters:\n* $1 - username that created the most recent revision of the post\n* $2 - humanized timestamp, relative to now, of when the edit occurred; rendered by MWTimestamp::getHumanTimestamp",
+ "flow-post-edited": "Text displayed to notify the user a post has been modified. Parameters:\n* $1 - username that created the most recent revision of the post\n* $2 - date and timestamp. {{Doc-human-timestamp|12:00|10}}",
"flow-post-action-view": "Used as text for the link which is used to view.\n{{Identical|Permalink}}",
"flow-post-action-post-history": "Used as text for the link which is used to view post-history of the topic.\n{{Identical|History}}",
"flow-post-action-suppress-post": "Used as a link in a dropdown menu to suppress a post.\n\nFor meaning of \"suppress\" see [[Thread:Support/About MediaWiki:Flow-post-action-suppress-post/qqq]] and [[Thread:Support/About MediaWiki:Flow-suppress-post-content/sv]].\n{{Related|Flow-action}}\n{{Identical|Suppress}}",
@@ -109,7 +136,7 @@
"flow-post-action-undelete-post": "Used as a link in a dropdown menu to undelete a post.\n{{Related|Flow-action}}\n{{Identical|Undelete}}",
"flow-post-action-unhide-post": "Used as a link in a dropdown menu to unhide a post.\n{{Related|Flow-action}}\n{{Identical|Unhide}}",
"flow-post-action-restore-post": "Used as a link in a dropdown menu to clear the moderation state of a post.\n{{Related|Flow-action}}\n{{Identical|Restore}}",
- "flow-post-action-undo-moderation": "Used as link text to undo a recently performed moderation action.\n{{Identical|Undo}}",
+ "flow-post-action-undo-moderation": "Used as link text to undo a recently performed moderation action.\n{{related|Flow-action}}\n{{Identical|Undo}}",
"flow-topic-action-view": "Title text for topic's permalink icon.\n{{Identical|Permalink}}",
"flow-topic-action-watchlist": "Title text for topic's watchlist icon.\n{{Identical|Watchlist}}",
"flow-topic-action-edit-title": "Used as title for the link which is used to edit the title.",
@@ -126,34 +153,35 @@
"flow-topic-action-undelete-topic": "Used as a link in a dropdown menu to undelete a topic.\n{{Related|Flow-action}}",
"flow-topic-action-unsuppress-topic": "Used as a link in a dropdown menu to unsuppress a topic.\n{{Related|Flow-action}}",
"flow-topic-action-restore-topic": "Used as a link in a dropdown menu to clear the moderation state of a topic.\n{{Related|Flow-action}}\n{{Identical|Restore}}",
- "flow-topic-action-undo-moderation": "Used as link text to undo a recently performed moderation action.\n{{Identical|Undo}}",
+ "flow-topic-action-undo-moderation": "Used as link text to undo a recently performed moderation action.\n{{related|Flow-action}}\n{{Identical|Undo}}",
"flow-topic-notification-subscribe-title": "Title text for the overlay when a topic is added to watchlist.",
"flow-topic-notification-subscribe-description": "Description text for the overlay when a topic is added to watchlist.",
"flow-board-notification-subscribe-title": "Title text for the overlay when a board is added to watchlist.",
"flow-board-notification-subscribe-description": "Description text for the overlay when a board is added to watchlist.",
"flow-topic-action-watchlist-add": "Title text for the hover state when a individual topic can be added to a watchlist.",
"flow-topic-action-watchlist-remove": "Title text for the hover state when a individual topic can be removed from a watchlist\n{{Identical|Unsubscribe}}",
- "flow-error-allowcreation-no-usedb": "Internal error when allowCreation is used and <var>$wgContentHandlerUseDB</var> is not set to <code>true</code>. Do not translate <code>true</code> as it a boolean value.",
- "flow-error-allowcreation-already-exists": "Internal error when allowCreation is called with $mustNotExist true, but the page does already exist",
- "flow-error-allowcreation-flow-create-board": "Internal error when allowCreation is called and user does not have flow-create-board",
+ "flow-error-allowcreation-no-usedb": "Internal error when attempting to enable Structured Discussion board on a specific page, and <var>$wgContentHandlerUseDB</var> is not set to <code>true</code>. Do not translate <code>true</code> as it’s a boolean value.",
+ "flow-error-allowcreation-already-exists": "Internal error when attempting to enable Structured Discussions on a specific page, and $mustNotExist was set true, but the page does already exist",
+ "flow-error-allowcreation-flow-create-board": "Internal error when attempting to enable Structured Discussions on a specific page, and user does not have flow-create-board",
+ "flow-error-can-not-edit-logged-out": "Used as error message when a logged out user can not edit a Structured Discussions board for a reason other than normal protection. Parameters:\n* $1 - User, for GENDER",
+ "flow-error-can-not-edit-logged-in": "Used as error message when a logged in user can not edit a Structured Discussions board for a reason other than normal protection. Parameters:\n* $1 - User, for GENDER",
"flow-error-http": "Used as error message on HTTP error.",
- "flow-error-other": "Used as generic error message.",
- "flow-error-external": "Uses as error message. Parameters:\n* $1 - error message\nSee also:\n* {{msg-mw|Flow-error-external-multi}}",
+ "flow-error-external": "Used as error message. Parameters:\n* $1 - error message",
"flow-error-topic-is-locked": "Used as error message when a user attempts to moderate/create/edit title/post when a topic is resolved (locked).",
"flow-error-lock-moderated-post": "Used as error message when user attempts to resolve (lock) a moderated topic/post.",
- "flow-error-external-multi": "Used as error message. Parameters:\n* $1 - list of error messages\nSee also:\n* {{msg-mw|Flow-error-external}}",
"flow-error-missing-content": "Used as error message.\n{{Related|Flow-error-missing}}",
"flow-error-missing-summary": "Used as error message when a summary is expected, but is not submitted. Zero-length summaries are allowed.\n{{Related|Flow-error-missing}}",
"flow-error-missing-title": "Used as error message.\n{{Related|Flow-error-missing}}",
"flow-error-parsoid-failure": "Used as error message.\n\nParsoid is a bidirectional wikitext parser and runtime. Converts back and forth between wikitext and HTML/XML DOM with RDFa. See [[mw:Parsoid]].",
+ "flow-error-protected-autoconfirmed-logged-in": "Used as error message when a logged in user can not edit a Structured Discussions board because only users in the 'autoconfirmed' group can do so. Parameters:\n* $1 - Reason given when the page was protected, or {{msg-mw|flow-error-protected-unknown-reason}} if the reason was not specified or can not be fetched.",
+ "flow-error-protected-autoconfirmed-logged-out": "Used as error message when a logged out user can not edit a Structured Discussions board because only users in the 'autoconfirmed' group can do so. Parameters:\n* $1 - Reason given when the page was protected, or {{msg-mw|flow-error-protected-unknown-reason}} if the reason was not specified or can not be fetched.",
+ "flow-error-protected-sysop-logged-in": "Used as error message when a logged in user can not edit a Structured Discussions board because only users in the 'sysop' group can do so. Parameters:\n* $1 - Reason given when the page was protected, or {{msg-mw|flow-error-protected-unknown-reason}} if the reason was not specified or can not be fetched.",
+ "flow-error-protected-sysop-logged-out": "Used as error message when a logged out user can not edit a Structured Discussions board because only users in the 'sysop' group can do so. Parameters:\n* $1 - Reason given when the page was protected, or {{msg-mw|flow-error-protected-unknown-reason}} if the reason was not specified or can not be fetched.",
+ "flow-error-protected-unknown-reason": "Used as placeholder when reason for protection was not specified, or is unknown\n{{Identical|Unknown}}",
"flow-error-missing-replyto": "Used as error message.\n\nThe variable name \"replyTo\" is invisible to users, so \"replyTo\" can be translated.\n{{related|Flow-error-missing}}",
- "flow-error-invalid-replyto": "Used as error message.\n\nThe variable name \"replyTo\" is invisible to users, so \"replyTo\" can be translated.",
- "flow-error-delete-failure": "Used as error message.\n\n\"this item\" refers either \"this topic\" or \"this post\".",
- "flow-error-hide-failure": "Used as error message.\n\n\"this item\" refers either \"this topic\" or \"this post\".",
"flow-error-missing-postId": "Used as error message when deleting/restoring a post.\n\n\"manipulate\" refers either \"delete\" or \"restore\".\n{{related|Flow-error-missing}}",
"flow-error-invalid-postId": "Used as error message when deleting/restoring a post.\n\nThe variable name \"postId\" is invisible to users, so \"postId\" can be translated.\n\nParameters:\n* $1 - contains the postId that was specified",
- "flow-error-restore-failure": "Used as error message when restoring a post.\n\n\"this item\" seems to refer \"this post\".",
- "flow-error-invalid-moderation-state": "Used as error message.\n\nUsually indicates a code bug (possibly in a third-party use of the Flow API), so technical terminology is okay.\n\nValid values for moderationState are: (none), hidden, deleted, suppressed. Do not translate the word 'moderationState'.",
+ "flow-error-invalid-moderation-state": "Used as error message.\n\nUsually indicates a code bug (possibly in a third-party use of the Structured Discussions API), so technical terminology is okay.\n\nValid values for moderationState are: (none), hidden, deleted, suppressed. Do not translate the word 'moderationState'.",
"flow-error-invalid-moderation-reason": "Used as error message when no reason is given for the moderation of a post.",
"flow-error-not-allowed": "Error message when the user has insufficient permissions to execute this action",
"flow-error-not-allowed-hide": "Error message when the user has insufficient permissions to execute this action because the topic is hidden.",
@@ -179,6 +207,7 @@
"flow-error-invalid-input": "Error message when invalid input is provided.",
"flow-error-invalid-title": "Error message when invalid title is provided.",
"flow-error-invalid-action": "Error message when invalid action is provided.\n\nRefers to:\n* {{msg-mw|Nosuchactiontext}}.",
+ "flow-error-invalid-parameter": "Error method when an internal method is called incorrectly.",
"flow-error-fail-load-history": "Error message when load history content is failed to load.",
"flow-error-missing-revision": "Error message when a revision is missing.\n{{related|Flow-error-missing-revision}}",
"flow-error-fail-commit": "Error message when a commit action fails.",
@@ -186,6 +215,7 @@
"flow-error-revision-comparison": "Error message when revision comparison fails.",
"flow-error-missing-topic-title": "Error message when a topic title is missing.\n{{related|Flow-error-missing}}",
"flow-error-missing-metadata": "Error message when a metadata is missing for a revision.\n{{related|Flow-error-missing}}",
+ "flow-error-different-page": "Error message when Structured Discussions workflow is loaded on the wrong page, indicating inconsistent state",
"flow-error-fail-load-data": "General error message when failing to load data.",
"flow-error-invalid-workflow": "Error message when invalid workflow is provided.",
"flow-error-process-data": "General error message when failing to process data.",
@@ -195,13 +225,13 @@
"flow-error-no-commit": "Error message when nothing was able to commit the request (data was submitted but it could not be processed).",
"flow-error-content-too-long": "Error message when the expanded(html) output of a post is too large.\n\nParameters:\n* $1 - post content lengh limit in byte, could be used for plural support.",
"flow-error-move-topic": "Error message when attempting to move a flow topic",
- "flow-error-move-no-create-permissions": "Error message when attempting to move a flow board to a page that the current user is not allowed to.",
"flow-error-invalid-topic-uuid-title": "Title displayed at top of page and in browser title bar when the user requests a page within the Topic namespace that is not a valid UUID",
"flow-error-invalid-topic-uuid": "Body of page displayed when the user requests a page within the Topic namespace that is not a valid UUID",
"flow-error-unknown-workflow-id-title": "Title displayed at top of page and in browser title bar when the user requests a page within the Topic namespace that is not a known topic",
"flow-error-unknown-workflow-id": "Body of page displayed when the user requests a page within the Topic namespace that is not a known topic",
"flow-error-search": "Error message shown to the users when we have an issue communicating with our search backend.",
- "flow-edit-header-placeholder": "Used as placeholder when editing the description of a Flow board",
+ "flow-error-invalid-undelete": "Error message shown to the users when they attempt to restore a revision over an active discussion board.",
+ "flow-edit-header-placeholder": "Used as placeholder when editing the description of a Structured Discussions board",
"flow-edit-header-submit": "Used as label for the Submit button.",
"flow-edit-header-submit-anonymously": "Used as label for the Submit button when submitting as an anonymous user.",
"flow-edit-title-submit": "Used as label for the Submit button.",
@@ -270,32 +300,87 @@
"flow-comment-deleted": "Used as revision comment when the post has been deleted.\n\nSee also:\n* {{msg-mw|Flow-comment-restored}}",
"flow-comment-hidden": "Used as revision comment when the post has been hidden.",
"flow-comment-moderated": "Used as a revision comment when the post has been oversighted.",
- "flow-last-modified": "Followed by the timestamp.\n\nParameters:\n* $1 - most significant unit of time since modification rendered by MWTimestamp::getHumanTimestamp",
+ "flow-last-modified": "Followed by the timestamp.\n\nParameters:\n* $1 - date and timestamp. {{Doc-human-timestamp|12:00|10}}",
"flow-workflow": "Anchor link text for linking to a workflow.\n{{Identical|Workflow}}",
- "flow-notification-reply": "Notification text for when a user receives a reply. Parameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - (Unused) title for the Flow board, this parameter is not used for the message at this moment\n* $4 - title for the page that the Flow board is attached to\n* $5 - permanent URL for the post\n{{Related|Flow-notification}}",
- "flow-notification-reply-bundle": "Notification text for when a user receives replies from multiple users on the same topic.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\n* $4 - permantent URL for the post\n* $5 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $6 - a number used for plural support\nSee also:\n* {{msg-mw|Flow-notification-reply-email-batch-bundle-body}}\n{{Related|Flow-notification}}",
- "flow-notification-edit": "Notification text for when a user's post is edited. Parameters:\n* $1 - username of the person who edited the post\n* $2 - title of the topic\n* $3 - title for the Flow board\n* $4 - title for the page that the Flow board is attached to\n* $5 - permanent URL for the post\n* $6 - permanent URL for the topic\n{{Related|Flow-notification}}",
- "flow-notification-edit-bundle": "Notification text for when a user receives post edits from multiple users on the same topic.\n\nParameters:\n* $1 - username of the person who edited post\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\n* $4 - permantent URL for the topic\n* $5 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $6 - a number used for plural support\nSee also:\n* {{msg-mw|Flow-notification-edit-email-batch-bundle-body}}\n{{Related|Flow-notification}}",
- "flow-notification-newtopic": "Notification text for when a new topic is created. Parameters:\n* $1 - username of the person who created the topic\n* $2 - (Unused) title for the Flow board\n* $3 - title for the page that the Flow board is attached to\n* $4 - title of the topic\n* $5 - Fully qualified url to view the created topic.\n{{Related|Flow-notification}}",
+ "flow-notification-reply": "Notification text for when a user receives a reply. Parameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - (Unused) title for the Structured Discussions board, this parameter is not used for the message at this moment\n* $4 - title for the page that the Structured Discussions board is attached to\n* $5 - permanent URL for the post\n{{Related|Flow-notification}}",
+ "flow-notification-reply-bundle": "Notification text for when a user receives replies from multiple users on the same topic.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\n* $4 - permantent URL for the post\n* $5 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $6 - a number used for plural support\nSee also:\n* {{msg-mw|Flow-notification-reply-email-batch-bundle-body}}\n{{Related|Flow-notification}}",
+ "flow-notification-edit": "Notification text for when a user's post is edited. Parameters:\n* $1 - username of the person who edited the post\n* $2 - title of the topic\n* $3 - title for the Structured Discussions board\n* $4 - title for the page that the Structured Discussions board is attached to\n* $5 - permanent URL for the post\n* $6 - permanent URL for the topic\n{{Related|Flow-notification}}",
+ "flow-notification-edit-bundle": "Notification text for when a user receives post edits from multiple users on the same topic.\n\nParameters:\n* $1 - username of the person who edited post\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\n* $4 - permantent URL for the topic\n* $5 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $6 - a number used for plural support\nSee also:\n* {{msg-mw|Flow-notification-edit-email-batch-bundle-body}}\n{{Related|Flow-notification}}",
+ "notification-header-flow-new-topic-v2": "Notification header text for when a new topic is created. Parameters:\n* $1 - the formatted username of the user who created the topic\n* $2 - the username for gender purposes\n* $3 - title of the Structured Discussions board\n* $4 - title of the topic.\n{{Related|Notification-header-flow}}",
+ "notification-compact-header-flow-new-topic": "{{optional}}\nNotification compact header text for when a new topic is created. Parameters:\n* $1 - title of the topic.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-new-topic": "Notification text for when multiple new topics are created on the same page. Parameters:\n* $1 - The number of topics that were created for display purposes. This can be a number or '99+' if it is 99 or more\n* $2 - The number of new topics created for PLURAL purposes\n* $3 - The title of the page the topics were created on\n{{Related|Notification-bundle}}",
+ "notification-body-flow-new-topic-v2": "Notification body text for when a new topic is created. Parameters:\n$1 - a snippet of the content of the new topic.\n{{Related|Flow-notification}} {{notranslate}}",
+ "notification-header-flow-new-topic-user-talk": "Notification header text for when a new topic is created on a user's talk page. Parameters:\n$1 - the formatted username of the user who created the topic\n* $2 - the username for gender purposes\n* $3 - title of the Structured Discussions board\n* $4 - title of the topic.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-new-topic-user-talk": "Notification text for when multiple new topics are created on a user's talk page. Parameters:\n* $1 - The number of topics that were created for display purposes. This can be a number or '99+' if it is 99 or more\n* $2 - The number of new topics created for PLURAL purposes\n* $3 - The title of the page the topics were created on\n{{Related|Notification-bundle}}",
+ "notification-body-flow-new-topic-user-talk": "Notification body text for when a new topic is created on a user's talk page. Parameters:\n$1 - a snippet of the content of the new topic.\n{{notranslate}}",
+ "notification-header-flow-post-reply": "Notification header text for when there is a reply on a topic. Parameters:\n* $1 - the formatted username of the user who replied to the topic\n* $2 - the username for gender purposes\n* $3 - title of the Structured Discussions board\n* $4 - title of the topic.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-post-reply-v2": "Notification header text for when there is a multiple replies on a topic. Parameters:\n* $1 - the number of replies for display\n* $2 - the raw number of replies, for PLURAL\n* $3 - title of the topic.\n{{Related|Notification-bundle}}",
+ "notification-compact-header-flow-post-reply": "{{optional}}\nNotification compact header text for when there is a reply on a topic. Parameters:\n* $1 - the formatted username of the user who replied to the topic\n* $2 - the username for gender purposes\n* $3 - excerpt of the reply.\n{{Related|Notification-header-flow}}",
+ "notification-body-flow-post-reply-v2": "Notification body text for when there is a reply on a topic. Parameters:\n* $1 - a snippet of the content of the reply.\n{{Related|Flow-notification}} {{notranslate}}",
+ "notification-header-flow-post-reply-user-talk": "Notification header text for when there is a reply on a topic on a user's talk page. Parameters:\n* $1 - the formatted username of the user who replied to the topic\n* $2 - the username for gender purposes\n* $3 - title of the Structured Discussions board\n* $4 - title of the topic.\n{{Related|Notification-header-flow}}\n\nBug: The term \"your\" should have a $5 parameter for the gender of the viewing user as <code><nowiki>{{GENDER:$5|your}}</nowiki></code> in some languages",
+ "notification-bundle-header-flow-post-reply-user-talk": "Notification header text for when there is a multiple replies on a topic on a user's talk page. Parameters:\n* $1 - the number of replies for display\n* $2 - the raw number of replies, for PLURAL\n* $3 - title of the topic.\n{{Related|Notification-bundle}}\n\nBug: \"your\" should have a parameter $4 for the viewing user as <code><nowiki>{{GENDER:$4|your}}</nowiki></code> in some languages",
+ "notification-body-flow-post-reply-user-talk": "Notification body text for when there is a reply on a topic on a user's talk page. Parameters:\n* $1 - a snippet of the content of the reply.\n{{Related|Flow-notification}} {{notranslate}}",
+ "notification-header-flow-post-edited-v2": "Notification header text for when a post is edited. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-post-edited-v2": "Notification bundle header text for when a user receives post edits from multiple users on the same topic. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\nSee also: {{msg-mw|Flow-notification-edit-email-batch-bundle-body}}\n\n{{Related|Notification-bundle}}",
+ "notification-body-flow-post-edited-v2": "Notification body text for when a post is edited. Parameters:\n$1 - snippet of the post\n{{notranslate}}",
+ "notification-header-flow-post-edited-user-talk": "Notification header text for when a post is edited on a user's talk page . Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-post-edited-user-talk": "Notification bundle header text for when a user receives post edits from multiple users on the same topic on a user's talk page .\nParameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-bundle}}",
+ "notification-body-flow-post-edited-user-talk": "Notification body text for when a post on a user's talk page is edited. Parameters:\n$1 - snippet of the post\n{{notranslate}}",
+ "notification-header-flow-topic-renamed-v2": "Notification header text for when a topic is renamed. Parameters:\n$1 - old title of the topic\n* $2 - new title of the topic\n* $3 - username of the person who receives the notification, can be used for GENDER\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-topic-renamed-user-talk": "Notification header text for when a topic is renamed on a user's talk page . Parameters:\n$1 - old title of the topic\n* $2 - new title of the topic\n* $3 - username of the person who receives the notification, can be used for GENDER\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-summary-edited": "Notification header text for when a topic summary is edited. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-summary-edited-first": "Notification header text for when a topic is summarized for the first time. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-summary-edited": "Notification bundle header text for when a topic summary is edited multiple times. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-bundle}}",
+ "notification-body-flow-summary-edited": "Notification body text for when a topic summary is edited. Parameters:\n$1 - snippet of the post\n{{notranslate}}",
+ "notification-header-flow-summary-edited-user-talk": "Notification header text for when a topic summary is edited on a user's talk page. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-summary-edited-first-user-talk": "Notification header text for when a topic is summarized for the first time on a user's talk page. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Notification bundle header text for when a topic summary is edited multiple times on a user's talk page. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-bundle}}",
+ "notification-body-flow-summary-edited-user-talk": "Notification body text for when a topic summary is edited on a user's talk page. Parameters:\n$1 - snippet of the post\n{{notranslate}}",
+ "notification-email-subject-flow-summary-edited": "Subject line of notification email for the topic summary being edited. Parameters:\n* $1 - name of the user that edited the summary\n* $2 - title of the topic",
+ "notification-email-batch-body-flow-summary-edited": "Email notification for the topic summary being edited. Parameters:\n* $1 - name of the user that edited the summary\n* $2 - title of the topic",
+ "notification-email-batch-bundle-body-flow-summary-edited": "Email notification body when a topic summary is edited multiple times, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who edited the summary\n* $2 - title for the topic\n* $3 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $4 - a number used for plural support",
+ "notification-header-flow-mention-post": "Notification header text for when a user is mentioned in a post or topic title. Parameters:\n* $1 - the formatted username of the person who made the post\n* $2 - the username of the user who mentioned the viewing user, can be used for GENDER\n* $3 - title of the Structured Discussions board\n* $4 - username of the person who receives the notification, can be used for GENDER\n* $5 - title of the topic\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-mention-header": "Notification header text for when a user is mentioned in the board description. Parameters:\n* $1 - the formatted username of the person who made the post\n* $2 - the username for gender purposes\n* $3 - title of the Structured Discussions board\n* $4 - username of the person who receives the notification, can be used for GENDER\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-mention-post-summary": "Notification header text for when a user is mentioned in a post summary. Parameters:\n* $1 - the formatted username of the person who made the post\n* $2 - the username of the user who mentioned the viewing user, can be used for GENDER\n* $4 - username of the person who receives the notification, can be used for GENDER\n* $5 - title of the topic\n{{Related|Notification-header-flow}}",
+ "notification-body-flow-mention": "Notification body text for when a user is mentioned in a post. Parameters:\n* $1 - text snippet of the message containing the mention\n{{Related|Flow-notification}}",
+ "notification-header-flow-enabled-on-talkpage": "Notification header text when Structured Discussions is enabled on a user talk page. Parameters:\n* $1 - the formatted username of the user who enabled Structured Discussions on his user talk page\n* $2 - the username for gender purposes\n* $3 - Title where Structured Discussions was enabled.\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-description-edited": "Notification header text for when a board description is edited. Parameters:\n* $1 - title of the board.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-header-flow-description-edited-user-talk": "Notification header text for when a board description is edited on a user's talk page. Parameters:\n* $1 - title of the board.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}",
+ "notification-bundle-header-flow-description-edited": "Notification header text for when a board description is edited multiple times. Parameters:\n* $1 - title of the board.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-bundle}}",
+ "notification-bundle-header-flow-description-edited-user-talk": "Notification header text for when a board description is edited multiple times on a user's talk page. Parameters:\n* $1 - title of the board.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-bundle}}",
+ "notification-body-flow-description-edited": "Notification body text for when a board description is edited. Parameters:\n$1 - snippet of the description\n{{notranslate}}",
+ "notification-body-flow-description-edited-user-talk": "Notification body text for when a board description is edited. Parameters:\n$1 - snippet of the description\n{{notranslate}}",
+ "notification-links-flow-description-edited-view-page": "Text for the link to the board where the description was edited\n{{Identical|View page}}",
+ "notification-email-subject-flow-description-edited": "Subject line of notification email for the description being edited. Parameters:\n* $1 - name of the user that edited the description\n* $2 - title of the page",
+ "notification-email-batch-body-flow-description-edited": "Email notification for the description being edited. Parameters:\n* $1 - name of the user that edited the description\n* $2 - title of the page",
+ "notification-email-batch-bundle-body-flow-description-edited": "Email notification body when a board description is edited multiple times, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who edited the description\n* $2 - title for the page\n* $3 - the count of other action performers, could be number or {{msg-mw|Echo-notification-count}}. e.g. 7 others or 99+ others\n* $4 - a number used for plural support",
+ "notification-header-flow-topic-resolved": "Notification header text for when a topic summary is resolved. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}.",
+ "notification-header-flow-topic-reopened": "Notification header text for when a topic summary is reopened. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}.",
+ "notification-header-flow-topic-resolved-user-talk": "Notification header text for when a topic summary is resolved on a user's talk page. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}.",
+ "notification-header-flow-topic-reopened-user-talk": "Notification header text for when a topic summary is reopened on a user's talk page. Parameters:\n* $1 - title of the topic.\n* $2 - name of the user viewing the notification, can be used for GENDER.\n{{Related|Notification-header-flow}}.",
+ "notification-email-subject-flow-topic-resolved": "Subject line of notification email for the topic being resolved. Parameters:\n* $1 - name of the user that edited the summary\n* $2 - title of the topic",
+ "notification-email-batch-body-flow-topic-resolved": "Subject line of notification email for the topic being reopened. Parameters:\n* $1 - name of the user that edited the summary\n* $2 - title of the topic",
+ "flow-notification-newtopic": "Notification text for when a new topic is created. Parameters:\n* $1 - username of the person who created the topic\n* $2 - (Unused) title for the Structured Discussions board\n* $3 - title for the page that the Structured Discussions board is attached to\n* $4 - title of the topic\n* $5 - Fully qualified url to view the created topic.\n{{Related|Flow-notification}}",
"flow-notification-newtopic-bundle": "Notification text for when multiple new topics are created on the same page. Parameters:\n* $1 - The number of topics that were created. This value is capped to 250. When this value is 250 it means 250 or more topics have been created.\n* $2 - The title of the page the topics were created on\n* $3 - Fully qualified url to view the related board sorted by newest topics.\n{{Related|Flow-notification}}",
- "flow-notification-rename": "Notification text for when the subject of a topic is changed. Parameters:\n* $1 - username of the person who edited the title, can be used for GENDER\n* $2 - permalink to the topic\n* $3 - old topic subject\n* $4 - new topic subject\n* $5 - title for the Flow board\n* $6 - title for the page that the Flow board is attached to\n{{Related|Flow-notification}}",
- "flow-notification-mention": "{{doc-singularthey}}\nNotification text for when a user is mentioned in another conversation. Parameters:\n* $1 - username of the person who made the post, can be used for GENDER\n* $2 - permalink to the post\n* $3 - title of the topic\n* $4 - title for the page that the Flow board is attached to\n* $5 - username of the person who receives the notification, can be used for GENDER\n{{Related|Flow-notification}}",
+ "flow-notification-rename": "Notification text for when the subject of a topic is changed. Parameters:\n* $1 - username of the person who edited the title, can be used for GENDER\n* $2 - permalink to the topic\n* $3 - old topic subject\n* $4 - new topic subject\n* $5 - title for the Structured Discussions board\n* $6 - title for the page that the Structured Discussions board is attached to\n{{Related|Flow-notification}}",
+ "flow-notification-mention": "{{doc-singularthey}}\nNotification text for when a user is mentioned in another conversation. Parameters:\n* $1 - username of the person who made the post, can be used for GENDER\n* $2 - permalink to the post\n* $3 - title of the topic\n* $4 - title for the page that the Structured Discussions board is attached to\n* $5 - username of the person who receives the notification, can be used for GENDER\n{{Related|Flow-notification}}",
"flow-notification-link-text-view-post": "Label for button that links to a flow post.",
- "flow-notification-link-text-view-topic": "Link text in for the view topic button in a notification",
+ "flow-notification-link-text-view-topic": "Link text for the view topic button in a notification",
+ "flow-notification-link-text-view-topics": "Link text for the view topics button in a notification",
"flow-notification-reply-email-subject": "Email notification subject when a user receives a reply. Parameters:\n* $1 - username of the person who replied (Unused now)\n* $2 - the topic title being replied to\n* $3 - title of the page the topic belongs to\n{{Related|Flow-notification-email}}\n{{Identical|On}}",
- "flow-notification-reply-email-batch-body": "Email notification body when a user receives a reply, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\n{{Related|Flow-notification-email}}",
- "flow-notification-reply-email-batch-bundle-body": "Email notification body when a user receives reply from multiple users, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\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\n{{Related|Flow-notification-email}}",
+ "flow-notification-reply-email-batch-body": "Email notification body when a user receives a reply, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\n{{Related|Flow-notification-email}}",
+ "flow-notification-reply-email-batch-bundle-body": "Email notification body when a user receives reply from multiple users, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\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\n{{Related|Flow-notification-email}}",
"flow-notification-mention-email-subject": "Email notification subject when a user is mentioned in a post. Parameters:\n* $1 - username of the person who mentions other users, can be used for GENDER\n* $2 - flow title text\n* $3 - username of the person who receives the notification, can be used for GENDER\n{{Related|Flow-notification-email}}",
- "flow-notification-mention-email-batch-body": "{{doc-singularthey}}\nEmail notification body when a user is mentioned in a post, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who mentions other users, can be used for GENDER\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\n* $4 - username of the person who receives the notification, can be used for GENDER\n{{Related|Flow-notification-email}}",
+ "flow-notification-mention-email-batch-body": "{{doc-singularthey}}\nEmail notification body when a user is mentioned in a post, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who mentions other users, can be used for GENDER\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\n* $4 - username of the person who receives the notification, can be used for GENDER\n{{Related|Flow-notification-email}}",
"flow-notification-edit-email-subject": "Subject line of notification email for post being edited. Parameters:\n* $1 - name of the user that edited the post\n{{Related|Flow-notification-email}}",
"flow-notification-edit-email-batch-body": "Email notification for post being edited. Parameters:\n* $1 - name of the user that edited the post\n* $2 - name of the topic the edited post belongs to\n* $3 - title of the page the topic belongs to\n{{Related|Flow-notification-email}}",
- "flow-notification-edit-email-batch-bundle-body": "Email notification body when a user receives post edits from multiple users, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Flow board is attached to\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\n{{Related|Flow-notification-email}}",
+ "flow-notification-edit-email-batch-bundle-body": "Email notification body when a user receives post edits from multiple users, this message is used in both single email and email digest.\n\nParameters:\n* $1 - username of the person who replied\n* $2 - title of the topic\n* $3 - title for the page that the Structured Discussions board is attached to\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\n{{Related|Flow-notification-email}}",
"flow-notification-rename-email-subject": "Subject line of notification email for topic being renamed. Parameters:\n* $1 - name of the user that renamed the topic\n{{Related|Flow-notification-email}}",
"flow-notification-rename-email-batch-body": "Email notification for topic being renamed. Parameters:\n* $1 - name of the user that renamed the topic\n* $2 - the original topic title\n* $3 - the new topic title\n* $4 - title of the page the topic belongs to\n{{Related|Flow-notification-email}}",
"flow-notification-newtopic-email-subject": "Subject line of notification email for new topic creation. Parameters:\n* $1 - name of the user that created a new topic\n* $2 - title\n{{Related|Flow-notification-email}}",
"flow-notification-newtopic-email-batch-body": "Email notification for new topic creation. Parameters:\n* $1 - name of the user that created a new topic\n* $2 - the title of the new topic\n* $3 - title of the page the topic belongs to\n{{Related|Flow-notification-email}}",
- "flow-notification-newtopic-email-batch-bundle-body": "Email notification for when multiple new topics are created on the same page. Parameters:\n* $1 - The number of topics that were created. This value is capped to 250. When this value is 250 it means 250 or more topics have been created.\n* $2 - The title of the page the topics were created on\n* $3 - Fully qualified url to view the related board sorted by newest topics.\n{{Related|Flow-notification}}",
- "echo-category-title-flow-discussion": "This is a short title for notification category. Parameters:\n* $1 - number of mentions, for PLURAL support\n{{Related|Echo-category-title}}\n{{Identical|Flow}}\nFlow as an extension name : mw:Extension:Flow ,must not be translated.",
+ "flow-notification-newtopic-email-batch-bundle-body": "Email notification for when multiple new topics are created on the same page. Parameters:\n* $1 - The number of topics that were created. This value is capped to 250. When this value is 250 it means 250 or more topics have been created.\n* $2 - The title of the page the topics were created on\n* $3 - Fully qualified url to view the related board sorted by newest topics.\n{{Related|Flow-notification-email}}",
+ "echo-category-title-flow-discussion": "This is a short title for notification category. Parameters:\n* $1 - number of mentions, for PLURAL support\n{{Related|Echo-category-title}}\n{{Identical|Structured Discussion}}",
"echo-pref-tooltip-flow-discussion": "This is a short description of the flow-discussion notification category.\n{{Related|Echo-pref-tooltip}}",
"flow-link-post": "Tooltip text used when linking to a post from recentchanges.\n{{Identical|Post}}",
"flow-link-topic": "Tooltip text used when linking to a topic from recentchanges.\n{{Identical|Topic}}",
@@ -355,16 +440,16 @@
"flow-moderation-placeholder-unhide-topic": "Placeholder for the moderation confirmation dialog when a topic is being unhidden. Parameters:\n* $1 - (Unused) The user whose post is being moderated.\n* $2 - (Unused) The subject.\n* $3 - the user who is moderating the post. GENDER supported.\n{{Related|Flow-moderation-intro}}",
"flow-topic-permalink-warning": "Displayed at the top of a page when a person has clicked on a permanent link to a topic.\n\nParameters:\n* $1 - display text for a link to the board that the topic comes from\n* $2 - URL for a link to the board that the topic comes from\nSee also:\n* {{msg-mw|Flow-topic-permalink-warning-user-board}}",
"flow-topic-permalink-warning-user-board": "Displayed at the top of a page when a person has clicked on a permanent link to a topic from a user's board.\n\nParameters:\n* $1 - the user's name. Supports GENDER.\n* $2 - URL for a link to the board that the topic comes from\nSee also:\n* {{msg-mw|Flow-topic-permalink-warning}}",
- "flow-revision-permalink-warning-post": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-post-first}}).\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - title of the Flow Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n* $5 - URL to the diff from the previous revision to this one\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-post-first}}\n* {{msg-mw|Flow-revision-permalink-warning-header}}",
- "flow-revision-permalink-warning-post-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post.\n\nThis message will only be shown for the first revision.\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - title of the Flow Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-post}}\n* {{msg-mw|Flow-revision-permalink-warning-header-first}}",
- "flow-revision-permalink-warning-postsummary": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of summary for a post.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-postsummary-first}}).\n\nParameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - title of the Flow Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n* $5 - URL to the diff from the previous revision to this one\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-postsummary-first}}\n* {{msg-mw|Flow-revision-permalink-warning-header}}",
- "flow-revision-permalink-warning-postsummary-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post summary.\n\nThis message will only be shown for the first revision.\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - title of the Flow Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-post}}\n* {{msg-mw|Flow-revision-permalink-warning-header-first}}",
- "flow-revision-permalink-warning-header": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of board header.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-header-first}}).\n\nParameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - URL to the history page\n* $3 - URL to the diff from the previous revision to this one\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-header-first}}\n* {{msg-mw|Flow-revision-permalink-warning-post}}",
- "flow-revision-permalink-warning-header-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of board header.\n\nThis message will only be shown for the first revision.\n\nParameters:\n* $1 - (Unused) date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp that changes into an RFC2822 timestamp when hovered over.\n* $2 - URL to the history page\nSee also:\n* {{msg-mw|Flow-revision-permalink-warning-header}}\n* {{msg-mw|Flow-revision-permalink-warning-post-first}}",
- "flow-compare-revisions-revision-header": "Diff column header for a revision. Parameters:\n* $1 - date and timestamp, formatted as most are in Flow. That is, a human-readable timestamp is shown.\n* $2 - user who made this revision",
- "flow-compare-revisions-header-post": "Header for a page showing a \"diff\" between two revisions of a Flow post. Parameters:\n* $1 - the title of the Board on which this post sits. Example: User talk:Andrew\n* $2 - the subject of the Topic in which this post sits\n* $3 - the username of the author of the post\n* $4 - URL to the Board, with the fragment set to the post in question\n* $5 - URL to the Topic, with the fragment set to the post in question\n* $6 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
- "flow-compare-revisions-header-postsummary": "Header for a page showing a \"diff\" between two revisions of a Flow post summary. Parameters:\n* $1 - the title of the Board on which this post sits. Example: User talk:Andrew\n* $2 - the subject of the Topic in which this post sits\n* $3 - URL to the Board, with the fragment set to the post in question\n* $4 - URL to the Topic, with the fragment set to the post in question\n* $5 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
- "flow-compare-revisions-header-header": "Header for a page showing a \"diff\" between two revisions of a Flow board header. Parameters:\n* $1 - the title of the Board on which this header sits. Example: User talk:Andrew\n* $2 - the username of the author of the header\n* $3 - URL to the Board, with the fragment set to the post in question\n* $4 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
+ "flow-revision-permalink-warning-post": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-post-first}}).\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - title of the Structured Discussions Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n* $5 - URL to the diff from the previous revision to this one\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-revision-permalink-warning-post-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post.\n\nThis message will only be shown for the first revision.\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - title of the Structured Discussions Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-revision-permalink-warning-postsummary": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of summary for a post.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-postsummary-first}}).\n\nParameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - title of the Structured Discussions Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n* $5 - URL to the diff from the previous revision to this one\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-revision-permalink-warning-postsummary-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of a post summary.\n\nThis message will only be shown for the first revision.\n\nNote that the \"topic permalink warning\" (see {{msg-mw|Flow-topic-permalink-warning}}) will also be displayed.\n\nParameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - title of the Structured Discussions Board that the post appears on. Example: User talk:Andrew\n* $3 - title of the topic that this post appears in\n* $4 - URL to the history page\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-revision-permalink-warning-header": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of board header.\n\nThis message will not appear for the first revision, which has its own message ({{msg-mw|Flow-revision-permalink-warning-header-first}}).\n\nParameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - URL to the history page\n* $3 - URL to the diff from the previous revision to this one\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-revision-permalink-warning-header-first": "Header displayed at the top of a page when somebody is viewing a single-revision permalink of board header.\n\nThis message will only be shown for the first revision.\n\nParameters:\n* $1 - (Unused) date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - URL to the history page\n{{Related|Flow-revision-permalink-warning}}",
+ "flow-compare-revisions-revision-header": "Diff column header for a revision. Parameters:\n* $1 - date and timestamp: {{Doc-human-timestamp|12:00|10}}\n* $2 - user who made this revision",
+ "flow-compare-revisions-header-post": "Header for a page showing a \"diff\" between two revisions of a Structured Discussions post. Parameters:\n* $1 - the title of the Board on which this post sits. Example: User talk:Andrew\n* $2 - the subject of the Topic in which this post sits\n* $3 - the username of the author of the post\n* $4 - URL to the Board, with the fragment set to the post in question\n* $5 - URL to the Topic, with the fragment set to the post in question\n* $6 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
+ "flow-compare-revisions-header-postsummary": "Header for a page showing a \"diff\" between two revisions of a Structured Discussions post summary. Parameters:\n* $1 - the title of the Board on which this post sits. Example: User talk:Andrew\n* $2 - the subject of the Topic in which this post sits\n* $3 - URL to the Board, with the fragment set to the post in question\n* $4 - URL to the Topic, with the fragment set to the post in question\n* $5 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
+ "flow-compare-revisions-header-header": "Header for a page showing a \"diff\" between two revisions of a Structured Discussions board header. Parameters:\n* $1 - the title of the Board on which this header sits. Example: User talk:Andrew\n* $2 - the username of the author of the header\n* $3 - URL to the Board, with the fragment set to the post in question\n* $4 - URL to the history page for this post\n{{Related|Flow-compare-revisions-header}}",
"action-flow-create-board": "{{doc-action|flow-create-board}}",
"right-flow-create-board": "{{doc-right|flow-create-board}}",
"right-flow-hide": "{{doc-right|flow-hide}}",
@@ -392,10 +477,10 @@
"flow-terms-of-use-summarize": "Terms of use for summarizing a description/topic/post.\n\nRefers to {{msg-mw|flow-topic-action-update-topic-summary}}.\n{{Related|Flow-terms-of-use}}",
"flow-terms-of-use-lock-topic": "Terms of use for resolving a topic.\n\nRefers to {{msg-mw|Flow-topic-action-lock-topic}}.\n{{Related|Flow-terms-of-use}}",
"flow-terms-of-use-unlock-topic": "Terms of use for reopening a topic.\n\nRefers to {{msg-mw|flow-topic-action-unlock-topic}}.\n{{Related|Flow-terms-of-use}}",
- "flow-whatlinkshere-post": "Displayed in parentheses on [[Special:WhatLinksHere]] for an entry that relates to a Flow post.\n\nParameters:\n* $1 - a URL to the post\nSee also:\n* {{msg-mw|Flow-whatlinkshere-header}}",
- "flow-whatlinkshere-header": "Displayed in parentheses on [[Special:WhatLinksHere]] for an entry that relates to a Flow Board description.\n\nParameters:\n* $1 - a URL to the description\n\nSee also:\n* {{msg-mw|Flow-whatlinkshere-post}}",
+ "flow-whatlinkshere-post": "Displayed in parentheses on [[Special:WhatLinksHere]] for an entry that relates to a Structured Discussions post.\n\nParameters:\n* $1 - a URL to the post\nSee also:\n* {{msg-mw|Flow-whatlinkshere-header}}",
+ "flow-whatlinkshere-header": "Displayed in parentheses on [[Special:WhatLinksHere]] for an entry that relates to a Structured Discussions Board description.\n\nParameters:\n* $1 - a URL to the description\n\nSee also:\n* {{msg-mw|Flow-whatlinkshere-post}}",
"flow-whatlinkshere-post-summary": "Displayed in parentheses on [[Special:WhatLinksHere]] for an entry that relates to a topic summary.\n\nParameters:\n* $1 - a URL to the topic that has the summary\nSee also:\n* {{msg-mw|Flow-whatlinkshere-post}}",
- "flow": "{{doc-special|Flow}}\n{{Identical|Flow}}",
+ "structureddiscussions": "{{doc-special|Flow}}\n{{Identical|Structured Discussion}}",
"flow-special-desc": "Description at the top of the redirector special page",
"flow-special-type": "Label for the type (Workflow or PostRevision) dropdown on the redirector special page.\n{{Identical|Type}}",
"flow-special-type-post": "Label for PostRevision in the type dropdown.\n{{Identical|Post}}",
@@ -405,15 +490,16 @@
"flow-special-enableflow-legend": "Legend for Special:EnableFlow form",
"flow-special-enableflow-page": "Label for the page field of Special:EnableFlow",
"flow-special-enableflow-header": "Label for the header field of Special:EnableFlow",
- "flow-special-enableflow-board-already-exists": "Error given on Special:EnableFlow if board already exists at requested page name. Parameters:\n$1 - Page name where user requested to put Flow board",
+ "flow-special-enableflow-board-already-exists": "Error given on Special:EnableFlow if board already exists at requested page name. Parameters:\n$1 - Page name where user requested to put Structured Discussions board",
"flow-special-enableflow-invalid-title": "Error given on Special:EnableFlow if the provided page is not a valid page name.",
- "flow-special-enableflow-board-creation-not-allowed": "Error given on Special:EnableFlow if the current user is not allowed to create a Flow board. Parameters:\n$1 - Page name where user requested to put Flow board",
- "flow-special-enableflow-page-is-liquidthreads": "Error given on Special:EnableFlow if the page to enable Flow on is a LiquidThreads page. Parameters:\n$1 - Page name where user requested to put Flow board",
- "flow-special-enableflow-confirmation": "Confirmation message on Special:EnableFlow saying that you have successfully created a board Parameters:\n$1 - Page name of new Flow board",
- "flow-conversion-archive-page-name-format": "Archive format used when enabling Flow on existing pages. This is a format string. %s and %d should be present. %s represents the title of the page where Flow is being enabled. %d represents a number that will be incremented if an archive page with the same name already exist. Multiple formats can be specified separated by the new line character (\\n).",
- "flow-conversion-archive-flow-page-name-format": "Archive format used when archiving a Flow page. This is a format string. %s and %d should be present. %s represents the title of the Flow page being archived. %d represents a number that will be incremented if an archive page with the same name already exist. Multiple formats can be specified separated by the new line character (\\n).",
+ "flow-special-enableflow-board-creation-not-allowed": "Error given on Special:EnableFlow if the current user is not allowed to create a Structured Discussions board. Parameters:\n$1 - Page name where user requested to put Structured Discussions board",
+ "flow-special-enableflow-page-is-liquidthreads": "Error given on Special:EnableFlow if the page to enable Structured Discussions on is a LiquidThreads page. Parameters:\n$1 - Page name where user requested to put Structured Discussions board",
+ "flow-special-enableflow-confirmation": "Confirmation message on Special:EnableFlow saying that you have successfully created a board Parameters:\n$1 - Page name of new Structured Discussions board",
+ "flow-conversion-archive-page-name-format": "Archive format used when enabling Structured Discussions on existing pages. This is a format string. %s and %d should be present. %s represents the title of the page where Structured Discussions is being enabled. %d represents a number that will be incremented if an archive page with the same name already exist. Multiple formats can be specified separated by the new line character (\\n).",
+ "flow-conversion-archive-flow-page-name-format": "Archive format used when archiving a Structured Discussions page. This is a format string. %s and %d should be present. %s represents the title of the Structured Discussions page being archived. %d represents a number that will be incremented if an archive page with the same name already exist. Multiple formats can be specified separated by the new line character (\\n).",
"flow-spam-confirmedit-form": "Error message when ConfirmEdit flagged the submitted content (because an anonymous user submitted external links, possibly spam). A captcha will be displayed after this error message. Parameters:\n* $1 - the HTML for the captcha form.",
- "flow-embedding-unsupported": "Error message displayed if a user tries to transclude a Flow page.",
+ "flow-spam-confirmedit-using-failure": "Error message when mw.loader.using fails on the CAPTCHA resources.",
+ "flow-embedding-unsupported": "Error message displayed if a user tries to transclude a Structured Discussions page.",
"mw-ui-unsubmitted-confirm": "You have unsubmitted changes on this page. Are you sure you want to navigate away and lose your work?",
"flow-post-undo-hide": "Automatic moderation summary when undoing a post hide that was just performed.",
"flow-post-undo-delete": "Automatic moderation summary when undoing a post deletion that was just performed.",
@@ -421,126 +507,27 @@
"flow-topic-undo-hide": "Automatic moderation summary when undoing a topic hide that was just performed.",
"flow-topic-undo-delete": "Automatic moderation summary when undoing a topic deletion that was just performed.",
"flow-topic-undo-suppress": "Automatic moderation summary when undoing a topic suppression that was just performed.",
- "flow-importer-lqt-moved-thread-template": "Name of a wikitext template that is used as the content of LQT moved thread stubs when they are imported to Flow.",
+ "flow-importer-lqt-moved-thread-template": "Name of a wikitext template that is used as the content of LQT moved thread stubs when they are imported to Structured Discussions.",
"flow-importer-lqt-moved-thread-template-content": "Content of the Template:{{msg-mw|flow-importer-lqt-moved-thread-template}} page, informing people the LiquidThreads post was moved. Available template params: {{{author}}}, {{{date}}}, {{{title}}}.",
- "flow-importer-lqt-converted-template": "Name of a wikitext template that is added to the description of Flow boards that were converted from LiquidThreads",
+ "flow-importer-lqt-converted-template": "Name of a wikitext template that is added to the description of Structured Discussions boards that were converted from LiquidThreads",
"flow-importer-lqt-converted-template-content": "Content of the Template:{{msg-mw|flow-importer-lqt-converted-template}} page, informing people where to find the LiquidThreads history. Available template params: {{{archive}}}, {{{date}}}.",
- "flow-importer-lqt-converted-archive-template": "Name of a wikitext template that is added to the archived copy of a LiquidThreads page converted to Flow.",
+ "flow-importer-lqt-converted-archive-template": "Name of a wikitext template that is added to the archived copy of a LiquidThreads page converted to Structured Discussions.",
"flow-importer-lqt-converted-archive-template-content": "Content of the Template:{{msg-mw|flow-importer-lqt-converted-archive-template}} page, informing people this is an archived LiquidThreads page. Available template params: {{{from}}}.",
- "flow-importer-wt-converted-template": "Name of a wikitext template that is added to the description of a Flow boards that were converted from Wikitext",
+ "flow-importer-wt-converted-template": "Name of a wikitext template that is added to the description of a Structured Discussions boards that were converted from Wikitext",
"flow-importer-wt-converted-template-content": "Content of the Template:{{msg-mw|flow-importer-wt-converted-template}} page, informing people this wikitext discussion is archived. Available template params: {{{archive}}}, {{{date}}}.",
- "flow-importer-wt-converted-archive-template": "Name of a wikitext template that is added to the archived copy of a wikitext talk page converted to Flow.",
+ "flow-importer-wt-converted-archive-template": "Name of a wikitext template that is added to the archived copy of a wikitext talk page converted to Structured Discussions.",
"flow-importer-wt-converted-archive-template-content": "Content of the Template:{{msg-mw|flow-importer-wt-converted-archive-template}} page, informing people this is an archived wikitext discussion. Available template params: {{{from}}}.",
"flow-importer-lqt-suppressed-user-template": "Name of a wikitext template that is added to a revision imported from liquidthreads that is owned by a suppressed user.",
"flow-importer-lqt-suppressed-user-template-content": "Content of the Template:{{msg-mw|flow-importer-lqt-suppressed-user-template}} page, informing people this revision was imported from LiquidThreads with a suppressed user and has been reassigned to the current user.",
"flow-importer-lqt-different-author-signature-template": "Name of a wikitext template used when the post author and post signature differ. The template takes two parameters:\nauthorUser - Username (or IP) that posted the post.\nsignatureUser- Username (or IP) that the post is signed as",
"flow-importer-lqt-different-author-signature-template-content": "Content of the Template:{{msg-mw|flow-importer-lqt-different-author-signature-template}} page, informing people this LiquidThreads post was posted by a different user than it was signed as. Available template params: {{{authorUser}}}, {{{signatureUser}}}.",
- "apihelp-flow-description": "{{doc-apihelp-description|flow}}",
- "apihelp-flow-param-submodule": "{{doc-apihelp-param|flow|submodule}}",
- "apihelp-flow-param-page": "{{doc-apihelp-param|flow|page}}",
- "apihelp-flow-example-1": "{{doc-apihelp-example|flow}} (don't translate the [[Talk:Sandbox]] part, that's the name of the page for the API example)",
- "apihelp-flow+close-open-topic-description": "{{doc-apihelp-description|flow+close-open-topic}}",
- "apihelp-flow+close-open-topic-param-moderationState": "{{doc-apihelp-param|flow+close-open-topic|moderationState}}",
- "apihelp-flow+close-open-topic-param-reason": "{{doc-apihelp-param|flow+close-open-topic|reason}}",
- "apihelp-flow+edit-header-description": "{{doc-apihelp-description|flow+edit-header}}",
- "apihelp-flow+edit-header-param-prev_revision": "{{doc-apihelp-param|flow+edit-header|prev_revision}}",
- "apihelp-flow+edit-header-param-content": "{{doc-apihelp-param|flow+edit-header|content}}",
- "apihelp-flow+edit-header-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+edit-header|format}}",
- "apihelp-flow+edit-header-example-1": "{{doc-apihelp-example|flow+edit-header}}",
- "apihelp-flow+edit-post-description": "{{doc-apihelp-description|flow+edit-post}}",
- "apihelp-flow+edit-post-param-postId": "{{doc-apihelp-param|flow+edit-post|postId}}",
- "apihelp-flow+edit-post-param-prev_revision": "{{doc-apihelp-param|flow+edit-post|prev_revision}}",
- "apihelp-flow+edit-post-param-content": "{{doc-apihelp-param|flow+edit-post|content}}",
- "apihelp-flow+edit-post-param-format": "{{doc-apihelp-param|flow+edit-post|format}}",
- "apihelp-flow+edit-post-example-1": "{{doc-apihelp-example|flow+edit-post}}",
- "apihelp-flow+edit-title-description": "{{doc-apihelp-description|flow+edit-title}}",
- "apihelp-flow+edit-title-param-prev_revision": "{{doc-apihelp-param|flow+edit-title|prev_revision}}",
- "apihelp-flow+edit-title-param-content": "{{doc-apihelp-param|flow+edit-title|content}}",
- "apihelp-flow+edit-title-example-1": "{{doc-apihelp-example|flow+edit-title}}",
- "apihelp-flow+edit-topic-summary-description": "{{doc-apihelp-description|flow+edit-topic-summary}}",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "{{doc-apihelp-param|flow+edit-topic-summary|prev_revision}}",
- "apihelp-flow+edit-topic-summary-param-summary": "{{doc-apihelp-param|flow+edit-topic-summary|summary}}",
- "apihelp-flow+edit-topic-summary-param-format": "{{doc-apihelp-param|flow+edit-topic-summary|format}}",
- "apihelp-flow+edit-topic-summary-example-1": "{{doc-apihelp-example|flow+edit-topic-summary}}",
- "apihelp-flow+lock-topic-description": "{{doc-apihelp-description|flow+lock-topic}}",
- "apihelp-flow+lock-topic-param-moderationState": "{{doc-apihelp-param|flow+lock-topic|moderationState}}",
- "apihelp-flow+lock-topic-param-reason": "{{doc-apihelp-param|flow+lock-topic|reason}}",
- "apihelp-flow+lock-topic-example-1": "{{doc-apihelp-example|flow+lock-topic}}",
- "apihelp-flow+moderate-post-description": "{{doc-apihelp-description|flow+moderate-post}}",
- "apihelp-flow+moderate-post-param-moderationState": "{{doc-apihelp-param|flow+moderate-post|moderationState}}",
- "apihelp-flow+moderate-post-param-reason": "{{doc-apihelp-param|flow+moderate-post|reason}}",
- "apihelp-flow+moderate-post-param-postId": "{{doc-apihelp-param|flow+moderate-post|postId}}",
- "apihelp-flow+moderate-post-example-1": "{{doc-apihelp-example|flow+moderate-post}}",
- "apihelp-flow+moderate-topic-description": "{{doc-apihelp-description|flow+moderate-topic}}",
- "apihelp-flow+moderate-topic-param-moderationState": "{{doc-apihelp-param|flow+moderate-topic|moderationState}}",
- "apihelp-flow+moderate-topic-param-reason": "{{doc-apihelp-param|flow+moderate-topic|reason}}",
- "apihelp-flow+moderate-topic-example-1": "{{doc-apihelp-example|flow+moderate-topic}}",
- "apihelp-flow+new-topic-description": "{{doc-apihelp-description|flow+new-topic}}",
- "apihelp-flow+new-topic-param-topic": "{{doc-apihelp-param|flow+new-topic|topic}}",
- "apihelp-flow+new-topic-param-content": "{{doc-apihelp-param|flow+new-topic|content}}",
- "apihelp-flow+new-topic-param-format": "Do not alter the string \"(wikitext|html)\" in your translation.\n----\n{{doc-apihelp-param|flow+new-topic|format}}",
- "apihelp-flow+new-topic-example-1": "{{doc-apihelp-example|flow+new-topic}}",
- "apihelp-flow+reply-description": "{{doc-apihelp-description|flow+reply}}",
- "apihelp-flow+reply-param-replyTo": "{{doc-apihelp-param|flow+reply|replyTo}}",
- "apihelp-flow+reply-param-content": "{{doc-apihelp-param|flow+reply|content}}",
- "apihelp-flow+reply-param-format": "{{doc-apihelp-param|flow+reply|format}}",
- "apihelp-flow+reply-example-1": "{{doc-apihelp-example|flow+reply}}",
- "apihelp-flow+view-header-param-format": "{{doc-apihelp-param|flow+view-header|format}}",
- "apihelp-flow+view-header-description": "{{doc-apihelp-description|flow+view-header}}",
- "apihelp-flow+view-header-param-revId": "{{doc-apihelp-param|flow+view-header|revId}}",
- "apihelp-flow+view-header-example-1": "{{doc-apihelp-example|flow+view-header}}",
- "apihelp-flow+view-post-description": "{{doc-apihelp-description|flow+view-post}}",
- "apihelp-flow+view-post-param-postId": "{{doc-apihelp-param|flow+view-post|postId}}",
- "apihelp-flow+view-post-param-format": "{{doc-apihelp-param|flow+view-post|format}}",
- "apihelp-flow+view-post-example-1": "{{doc-apihelp-example|flow+view-post}}",
- "apihelp-flow+view-post-history-description": "{{doc-apihelp-description|flow+view-post-history}}",
- "apihelp-flow+view-post-history-param-postId": "{{doc-apihelp-param|flow+view-post-history|postId}}",
- "apihelp-flow+view-post-history-param-format": "{{doc-apihelp-param|flow+view-post-history|format}}",
- "apihelp-flow+view-post-history-example-1": "{{doc-apihelp-example|flow+view-post-history}}",
- "apihelp-flow+view-topic-description": "{{doc-apihelp-description|flow+view-topic}}",
- "apihelp-flow+view-topic-example-1": "{{doc-apihelp-example|flow+view-topic}}",
- "apihelp-flow+view-topic-history-description": "{{doc-apihelp-description|flow+view-topic-history}}",
- "apihelp-flow+view-topic-history-param-format": "{{doc-apihelp-param|flow+view-topic-history|format}}",
- "apihelp-flow+view-topic-history-example-1": "{{doc-apihelp-example|flow+view-topic-history}}",
- "apihelp-flow+view-topic-summary-description": "{{doc-apihelp-description|flow+view-topic-summary}}",
- "apihelp-flow+view-topic-summary-param-format": "{{doc-apihelp-param|flow+view-topic-summary|format}}",
- "apihelp-flow+view-topic-summary-param-revId": "{{doc-apihelp-param|flow+view-topic-summary|revId}}",
- "apihelp-flow+view-topic-summary-example-1": "{{doc-apihelp-example|flow+view-topic-summary}}",
- "apihelp-flow+view-topiclist-description": "{{doc-apihelp-description|flow+view-topiclist}}",
- "apihelp-flow+view-topiclist-param-offset-dir": "{{doc-apihelp-param|flow+view-topiclist|offset-dir}}",
- "apihelp-flow+view-topiclist-param-sortby": "{{doc-apihelp-param|flow+view-topiclist|sortby}}",
- "apihelp-flow+view-topiclist-param-savesortby": "{{doc-apihelp-param|flow+view-topiclist|savesortby}}",
- "apihelp-flow+view-topiclist-param-offset-id": "{{doc-apihelp-param|flow+view-topiclist|offset-id}}",
- "apihelp-flow+view-topiclist-param-offset": "{{doc-apihelp-param|flow+view-topiclist|offset}}",
- "apihelp-flow+view-topiclist-param-limit": "{{doc-apihelp-param|flow+view-topiclist|limit}}",
- "apihelp-flow+view-topiclist-example-1": "{{doc-apihelp-example|flow+view-topiclist}}",
- "apihelp-flow-parsoid-utils-description": "{{doc-apihelp-description|flow-parsoid-utils}}",
- "apihelp-flow-parsoid-utils-param-from": "{{doc-apihelp-param|flow-parsoid-utils|from}}",
- "apihelp-flow-parsoid-utils-param-to": "{{doc-apihelp-param|flow-parsoid-utils|to}}",
- "apihelp-flow-parsoid-utils-param-content": "{{doc-apihelp-param|flow-parsoid-utils|content}}",
- "apihelp-flow-parsoid-utils-param-title": "{{doc-apihelp-param|flow-parsoid-utils|title}}",
- "apihelp-flow-parsoid-utils-param-pageid": "{{doc-apihelp-param|flow-parsoid-utils|pageid}}",
- "apihelp-flow-parsoid-utils-example-1": "{{doc-apihelp-example|flow-parsoid-utils}}",
- "apihelp-query+flowinfo-description": "{{doc-apihelp-description|query+flowinfo}}",
- "apihelp-query+flowinfo-example-1": "{{doc-apihelp-example|query+flowinfo}}",
- "apihelp-flow+undo-edit-header-description": "{{doc-apihelp-description|flow+undo-edit-header}}",
- "apihelp-flow+undo-edit-header-param-startId": "{{doc-apihelp-param|flow+undo-edit-header|startId}}",
- "apihelp-flow+undo-edit-header-param-endId": "{{doc-apihelp-param|flow+undo-edit-header|endId}}",
- "apihelp-flow+undo-edit-header-example-1": "{{doc-apihelp-example|flow+undo-edit-header}}",
- "apihelp-flow+undo-edit-post-description": "{{doc-apihelp-description|flow+undo-edit-post}}",
- "apihelp-flow+undo-edit-post-param-postId": "{{doc-apihelp-param|flow+undo-edit-post|postId}}",
- "apihelp-flow+undo-edit-post-param-startId": "{{doc-apihelp-param|flow+undo-edit-post|startId}}",
- "apihelp-flow+undo-edit-post-param-endId": "{{doc-apihelp-param|flow+undo-edit-post|endId}}",
- "apihelp-flow+undo-edit-post-example-1": "{{doc-apihelp-example|flow+undo-edit-post}}",
- "apihelp-flow+undo-edit-topic-summary-description": "{{doc-apihelp-description|flow+undo-edit-topic-summary}}",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "{{doc-apihelp-param|flow+undo-edit-topic-summary|startId}}",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "{{doc-apihelp-param|flow+undo-edit-topic-summary|endId}}",
- "apihelp-flow+undo-edit-topic-summary-example-1": "{{doc-apihelp-example|flow+undo-edit-topic-summary}}",
"flow-edited": "Message displayed below a post to indicate it has last been edited by the original author\n{{Identical|Edited}}",
"flow-edited-by": "Message displayed below a post to indicate it has last been edited by a user other than the original author",
- "flow-lqt-redirect-reason": "Edit summary used to redirect old LQT thread pages to Flow topics",
+ "flow-edited-by-header": "Message added to the wikitext export of a board description to indicate it has been edited by users other than the original author.",
+ "flow-edited-by-topic-title": "Message added to the wikitext export of a topic title to indicate it has been edited by users other than the original author.",
+ "flow-lqt-redirect-reason": "Edit summary used to redirect old LQT thread pages to Structured Discussions topics",
"flow-talk-conversion-move-reason": "Message used as an edit summary when moving an existing talk page to an archive location in preparation for enabling flow on that page.\nParameters:\n* $1 - Title the page was moved from",
- "flow-talk-conversion-archive-edit-reason": "Message used as an edit summary when appending a template to a wikitext talk page after archiving it in preparation for conversion to Flow.",
+ "flow-talk-conversion-archive-edit-reason": "Message used as an edit summary when appending a template to a wikitext talk page after archiving it in preparation for conversion to Structured Discussions.",
"flow-previous-diff": "Text used on diff pages to link to the previous diff. For right-to-left languages use →.\n\nSee also:\n* {{msg-mw|Flow-next-diff}}",
"flow-next-diff": "Text used on diff pages to link to the next diff. For right-to-left languages use ←.\n\nSee also:\n* {{msg-mw|Flow-previous-diff}}",
"flow-undo": "Used as link text to go to the page to undo a revision\n{{Identical|Undo}}",
@@ -554,11 +541,11 @@
"group-flow-bot": "{{doc-group|flow-bot}}",
"group-flow-bot-member": "{{doc-group|flow-bot|member}}",
"grouppage-flow-bot": "{{doc-group|flow-bot|page}}",
- "flow-ve-mention-context-item-label": "Label of a button for mentioning users in Flow's VisualEditor.",
- "flow-ve-mention-inspector-title": "Title for the user mention panel (inspector) in Flow's VisualEditor.",
- "flow-ve-mention-inspector-remove-label": "Text of remove button on Flow's user mention panel (inspector) in the VisualEditor.",
+ "flow-ve-mention-context-item-label": "Label of a button for mentioning users in Structured Discussions's VisualEditor.",
+ "flow-ve-mention-inspector-title": "Title for the user mention panel (inspector) in Structured Discussions's VisualEditor.",
+ "flow-ve-mention-inspector-remove-label": "Text of remove button on Structured Discussions's user mention panel (inspector) in the VisualEditor.",
"flow-ve-mention-placeholder": "Placeholder text for the input field in the user mention tool where the user can type a user name.\n{{Identical|Username}}",
- "flow-ve-mention-tool-title": "Title text for the user mention tool on Flow's VisualEditor toolbar.",
+ "flow-ve-mention-tool-title": "Title text for the user mention tool on Structured Discussions's VisualEditor toolbar.",
"flow-ve-mention-template-title": "Name of on-wiki template used for user mentions. The template should accept a call in the form <nowiki>{{templatename|Username}}</nowiki> and <nowiki>{{templatename|Username|Displayname}}</nowiki>, to mention the username Username. It uses the content language.",
"flow-ve-mention-inspector-invalid-user": "Error shown when the poster attempts to mention a user that does not exist. Parameters:\n$1: Username. The username is not registered; thus, gender is unknown.",
"flow-wikitext-editor-help": "Text shown at the bottom of a wikitext editing box when visualeditor is not available to switch to.\n\n$1 is {{msg-mw|Flow-wikitext-editor-help-uses-wikitext}}.",
@@ -571,22 +558,28 @@
"flow-mark-revision-patrolled-link-title": "Title of the link to mark a revision as patrolled on a revision page.",
"flow-mark-diff-patrolled-link-text": "Text of the link to mark a revision as patrolled on a diff page.\n{{Identical|Mark as patrolled}}",
"flow-mark-diff-patrolled-link-title": "Title of the link to mark a revision as patrolled on a diff page.\n{{Identical|Mark as patrolled}}",
- "flow-talk-page-beta-feature-message": "Title of the beta feature to enable Flow on the user's talk page.",
- "flow-talk-page-beta-feature-description": "Description of the beta feature to enable Flow on the user's talk page.",
- "flow-notification-link-text-enabled-on-talkpage": "Primary link text in email for notification when Flow was enabled on your talk page.",
- "flow-notification-enabled-on-talkpage-title": "Text of the web notification when Flow was enabled on your talk page. Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Flow was enabled.",
- "flow-notification-enabled-on-talkpage-email-subject-message": "Email subject for notification when Flow was enabled on your talk page. Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Flow was enabled.",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Email body for notification when Flow was enabled on your talk page.\n Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Flow was enabled.",
+ "flow-talk-page-beta-feature-message": "Title of the beta feature to enable Structured Discussions on the user's talk page.",
+ "flow-talk-page-beta-feature-description": "Description of the beta feature to enable Structured Discussions on the user's talk page.",
+ "flow-notification-link-text-enabled-on-talkpage": "Primary link text in email for notification when Structured Discussions was enabled on your talk page.",
+ "flow-notification-enabled-on-talkpage-title": "Text of the web notification when Structured Discussions was enabled on your talk page. Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Structured Discussions was enabled.",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Email subject for notification when Structured Discussions was enabled on your talk page. Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Structured Discussions was enabled.",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Email body for notification when Structured Discussions was enabled on your talk page.\n Parameters:\n* $1 - the username. Can be used for GENDER.\n* $2 - Title where Structured Discussions was enabled.",
"flow-beta-feature-add-archive-template-edit-summary": "Edit summary message for the revision adding the archive template to an archived talk page.",
"flow-beta-feature-remove-archive-template-edit-summary": "Edit summary message for the revision removing the archive template to an archived talk page.",
"flow-dialog-cancelconfirm-title": "Title of the dialog that appears when the user cancels an edit and verifies whether the user wants to discard their edits or continue editing.\n{{Identical|Are you sure?}}",
"flow-dialog-cancelconfirm-message": "Title of the dialog that appears when the user cancels an edit, asking the user if they are sure they wants to discard their edits or continue editing.",
"flow-dialog-cancelconfirm-keep": "Title for the keep option in the dialog that appears when the user cancels an edit.",
"flow-dialog-cancelconfirm-discard": "Title for the discard option in the dialog that appears when the user cancels an edit.",
- "flow-guidedtour-optin-welcome": "Title of the 'welcome' step in the Flow opt-in guided tour. This message is the first to appear in the guided tour after a user chose to convert their talk page to a Flow board.",
- "flow-guidedtour-optin-welcome-description": "Description of the 'welcome' step in the flow opt-in guided tour. This message is the first to appear in the guided tour after a user chose to convert their talk page to a Flow board.",
- "flow-guidedtour-optin-find-old-conversations": "Title of the 'find old conversations' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Flow board. This message appears next to the board description, where a link is visible to the user's old talk page.",
- "flow-guidedtour-optin-find-old-conversations-description": "Description of the 'find old conversations' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Flow board. This message appears next to the board description, where a link is visible to the user's old talk page.",
- "flow-guidedtour-optin-feedback": "Title of the 'feedback' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Flow board. It appears under the 'beta' personal tool link, suggesting to the users that they can send the Flow developers feedback on their experience.",
- "flow-guidedtour-optin-feedback-description": "Description of the 'feedback' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Flow board. It appears under the 'beta' personal tool link, suggesting to the users that they can send the Flow developers feedback on their experience."
+ "flow-optin-archive-wikitext": "Move reason when wikitext page is being moved to make room for the discussion board.",
+ "flow-optin-archive-flow-board": "Move reason when discussion board is being moved to make room for the wikitext page.",
+ "flow-optin-restore-wikitext": "Move reason when the archived wikitext page is being moved back, to replace the (now archived) discussion board.",
+ "flow-optin-restore-flow-board": "Move reason when the archived discussion board is being moved back, to replace the (now archived) wikitext page.",
+ "flow-guidedtour-optin-welcome": "Title of the 'welcome' step in the Structured Discussions opt-in guided tour. This message is the first to appear in the guided tour after a user chose to convert their talk page to a Structured Discussions board.",
+ "flow-guidedtour-optin-welcome-description": "Description of the 'welcome' step in the flow opt-in guided tour. This message is the first to appear in the guided tour after a user chose to convert their talk page to a Structured Discussions board.",
+ "flow-guidedtour-optin-find-old-conversations": "Title of the 'find old conversations' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Structured Discussions board. This message appears next to the board description, where a link is visible to the user's old talk page.",
+ "flow-guidedtour-optin-find-old-conversations-description": "Description of the 'find old conversations' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Structured Discussions board. This message appears next to the board description, where a link is visible to the user's old talk page.",
+ "flow-guidedtour-optin-feedback": "Title of the 'feedback' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Structured Discussions board. It appears under the 'beta' personal tool link, suggesting to the users that they can send the Structured Discussions developers feedback on their experience.",
+ "flow-guidedtour-optin-feedback-description": "Description of the 'feedback' step in the flow opt-in guided tour that launches after the user chose to convert their talk page to a Structured Discussions board. It appears under the 'beta' personal tool link, suggesting to the users that they can send the Structured Discussions developers feedback on their experience.",
+ "flow-action-not-page": "Error displayed in the main page area if a bug or misconfiguration causes an inconsistent state.",
+ "flow-action-wrong-title-content-model": "Error displayed if the page has the wrong content model. Parameters:\n* $1 - The actual content model as reported by the Title class"
}
diff --git a/Flow/i18n/ro.json b/Flow/i18n/ro.json
index 6cc80554..01020d65 100644
--- a/Flow/i18n/ro.json
+++ b/Flow/i18n/ro.json
@@ -2,7 +2,9 @@
"@metadata": {
"authors": [
"Minisarm",
- "Tuxilina"
+ "Tuxilina",
+ "Nnemo",
+ "Strainu"
]
},
"flow-user-moderated": "Utilizator moderat",
@@ -10,7 +12,6 @@
"flow-post-actions": "Acțiuni",
"flow-topic-actions": "Acțiuni",
"flow-cancel": "Revocare",
- "flow-preview": "Previzualizare",
"flow-show-change": "Arată modificările",
"flow-stub-post-content": "''Din cauza unei erori de natură tehnică, acest mesaj nu a putut fi obținut.''",
"flow-newtopic-title-placeholder": "Subiect nou",
@@ -19,8 +20,8 @@
"flow-summarize-topic-placeholder": "Vă rugăm să faceți un rezumat al acestei discuții",
"flow-history-action-delete-post": "șterge",
"flow-history-action-hide-post": "ascunde",
- "flow-history-action-lock-topic": "blochează",
- "flow-history-action-unlock-topic": "deblochează",
+ "flow-history-action-lock-topic": "rezolvă",
+ "flow-history-action-unlock-topic": "redeschide",
"flow-post-action-view": "Legătură permanentă",
"flow-post-action-post-history": "Istoric",
"flow-post-action-delete-post": "Șterge",
@@ -31,11 +32,9 @@
"flow-topic-action-history": "Istoric",
"flow-topic-action-hide-topic": "Ascunde subiectul",
"flow-topic-action-summarize-topic": "Rezumare",
- "flow-topic-action-resummarize-topic": "Modifică rezumatul",
+ "flow-topic-action-resummarize-topic": "Modifică rezumatul subiectului",
"flow-error-http": "A apărut o eroare în momentul accesării serverului.",
- "flow-error-other": "A intervenit o eroare neașteptată.",
- "flow-error-external": "A intervenit o eroare.<br />Mesajul de eroare primit a fost: $1.",
- "flow-error-edit-restricted": "Nu aveți permisiunea de a modifica acest mesaj.",
+ "flow-error-external": "A intervenit o eroare. <br />Mesajul de eroare primit a fost: $1.",
"flow-error-topic-is-locked": "Acest subiect este blocat pentru orice acțiuni suplimentare.",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|a redenumit}} subiectul dv."
}
diff --git a/Flow/i18n/roa-tara.json b/Flow/i18n/roa-tara.json
index 84507267..9c26412b 100644
--- a/Flow/i18n/roa-tara.json
+++ b/Flow/i18n/roa-tara.json
@@ -4,9 +4,9 @@
"Joetaras"
]
},
- "enableflow": "Abbilite Flow",
- "flow-desc": "Sisteme de Gestione de le Flusse de fatìe",
- "log-name-flow": "Arcihvije de le attività d'u flusse",
+ "enablestructureddiscussions": "Abbilite 'Ngazzainde strutturate",
+ "flow-desc": "Sisteme de le 'ngazzaminde",
+ "log-name-flow": "Arcihvije de le attività sus a le 'ngazzaminde strutturate",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|scangellate}} 'nu [$4 messàgge] 'u \"[[$3|$5]]\" sus a [[$6]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|repristinate}} 'nu [$4 messàgge] 'u \"[[$3|$5]]\" sus a [[$6]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|luate}} 'nu [$4 messàgge] 'u \"[[$3|$5]]\" sus a [[$6]]",
@@ -32,6 +32,7 @@
"flow-post-actions": "Aziune",
"flow-topic-actions": "Aziune",
"flow-cancel": "Annulle",
+ "flow-skip-summary": "Zumbe",
"flow-show-change": "Fa vedè le cangiaminde",
"flow-last-modified-by": "Urteme {{GENDER:$1|cangiate}} da $1",
"flow-newtopic-title-placeholder": "Argomende nuève",
@@ -85,15 +86,16 @@
"flow-topic-action-restore-topic": "Repristine l'argomende",
"flow-topic-action-undo-moderation": "Annulle",
"flow-error-http": "Ha assute 'n'errore condattanne 'u server.",
- "flow-error-other": "Ha assute 'n'errore inaspettate.",
"flow-error-missing-summary": "Tu a confermà 'nu riepiloghe.",
+ "flow-error-protected-unknown-reason": "Scanusciute",
"flow-error-missing-header-content": "Tu a confermà 'na descrizione.",
"flow-edit-title-submit": "Cange 'u titole",
"flow-moderation-confirmation-suppress-topic": "St'argomende ha state luate.",
"flow-moderation-confirmation-delete-topic": "St'argomende ha state scangellate.",
"flow-moderation-confirmation-hide-topic": "St'argomende ha state scunnute.",
"flow-topic-html-title": "$1 sus a $2",
- "flow-dialog-cancelconfirm-title": "Sì secure?",
+ "group-flow-bot": "Bot de le 'ngazzaminde strutturate",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|Sì}} secure?",
"flow-dialog-cancelconfirm-keep": "Condinue a cangià",
"flow-dialog-cancelconfirm-discard": "Scitte le cangiaminde"
}
diff --git a/Flow/i18n/ru.json b/Flow/i18n/ru.json
index dc08a8f6..22810247 100644
--- a/Flow/i18n/ru.json
+++ b/Flow/i18n/ru.json
@@ -18,27 +18,55 @@
"Batumski brodyaga",
"Dicto23456",
"Дмитрий",
- "Amire80"
+ "Amire80",
+ "INS Pirat",
+ "Nnemo",
+ "Metastasis",
+ "Ядерный Трамвай",
+ "Mailman",
+ "Jack who built the house",
+ "Туллук",
+ "Kareyac",
+ "Alex Great",
+ "Redredsonia"
]
},
- "enableflow": "Включить Поток",
- "flow-desc": "Система управления потоками работ",
- "flow-talk-taken-over-comment": "/* Эта страница была преобразована в доску обсуждений Потока */",
- "log-name-flow": "Журнал активности Потока",
+ "enablestructureddiscussions": "Включить структурированные обсуждения",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Прекратить}} отслеживание новых изменений страницы «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Вы}} больше не искать страницу с именем «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Это не будет затрагивать отдельные темы {{пол:$3|вы}} для поиска. Вы можете смотреть [$2 страница] в любое время.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Перестать}} следить за этой темой",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Вы}} больше не следите за «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Вы}} можете возобновить отслеживание [$2 этой страницы] в любой момент.",
+ "flow-desc": "Система обсуждения",
+ "flow-talk-taken-over-comment": "/* Эта страница была преобразована в стену обсуждений Flow */",
+ "log-name-flow": "Журнал активности Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|удалил|удалила}} [$4 сообщение] в «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 удалил{{GENDER:$2||а}} сообщение в теме на [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|восстановил|восстановила}} [$4 сообщение] в «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 восстановил{{GENDER:$2||а}} сообщение в теме на [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|подавил|подавила}} [$4 сообщение] в «[[$3|$5]]» на [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|подавил|подавила}} сообщение темы на [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|удалил|удалила}} [$4 сообщение] в «[[$3|$5]]» на [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 удалил{{GENDER:$2||а}} сообщение в теме на [[$3]]",
"logentry-delete-flow-delete-topic": "$1 удалил{{GENDER:$2||а}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 удалил{{GENDER:$2||а}} тему на [[$3]]",
"logentry-delete-flow-restore-topic": "$1 восстановил{{GENDER:$2||а}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 восстановил{{GENDER:$2||а}} тему на [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|подавил|подавила}} тему «[[$3|$5]]» на [[$6]]",
"logentry-suppress-flow-restore-topic": "$1 удалил{{GENDER:$2||а}} тему «[[$3|$5]]» на [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] в [[$3]] была импортирована из LiquidThreads в Поток",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 удалил {{GENDER:$2||а}} тему на [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 переоткрыл{{GENDER:$2||а}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 переоткрыл{{GENDER:$2||а}} тему на [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] в [[$3]] была импортирована из LiquidThreads в Flow",
"flow-user-moderated": "Участник промодерирован",
"flow-board-header-browse-topics-link": "Обзор тем",
- "flow-board-header": "Об этой доске",
+ "flow-board-header": "Об этой стене",
+ "flow-board-description-can-not-edit": "Нельзя редактировать",
"flow-board-collapse-description": "скрыть описание",
"flow-board-expand-description": "Показать описание",
+ "flow-topic-collapse-siderail": "Читать на всю ширину",
+ "flow-topic-expand-siderail": "Читать на фиксированную ширину",
"flow-edit-header-link": "Править описание",
"flow-post-moderated-toggle-hide-show": "Показать комментарий, скрытый {{GENDER:$1|участником|участницей}} $2",
"flow-post-moderated-toggle-delete-show": "Показать комментарий, {{GENDER:$1|удалённый}} $2",
@@ -60,34 +88,36 @@
"flow-post-actions": "Действия",
"flow-topic-actions": "Действия",
"flow-cancel": "Отменить",
- "flow-skip-summary": "Пропустить краткое описание",
+ "flow-skip-summary": "Пропустить",
"flow-edit-summary-placeholder": "Кратко опишите исход обсуждения",
- "flow-summary-authored": "Краткое содержание написано $1",
+ "flow-summary-authored": "Резюме написано $1",
"flow-summary-edited": "Краткое содержание было в последний раз {{GENDER:$1|написано}} $1",
"flow-show-change": "Показать изменения",
"flow-last-modified-by": "Последний раз изменено {{GENDER:$1|участником|участницей}} $1",
- "flow-stub-post-content": "«Из-за технической ошибки это сообщение не удалось получить.»",
+ "flow-stub-post-content": "<em>Из-за технической ошибки это сообщение не удалось получить.</em>",
"flow-newtopic-title-placeholder": "Новая тема",
"flow-newtopic-content-placeholder": "Разместите новое сообщение на «$1»",
"flow-newtopic-header": "Добавить новую тему",
"flow-newtopic-save": "Добавить тему",
+ "flow-newtopic-save-anonymously": "Добавить тему анонимно",
"flow-newtopic-start-placeholder": "Начать новую тему",
"flow-newtopic-first-heading": "Начать новую тему на странице $1",
- "flow-summarize-topic-placeholder": "Пожалуйста, кратко опишите содержание этого обсуждения",
+ "flow-summarize-topic-placeholder": "Пожалуйста, резюмируйте это обсуждение",
"flow-reply-topic-placeholder": "{{GENDER:$1|Комментарий}} в «$2»",
"flow-reply-topic-title-placeholder": "Ответ на «$1»",
"flow-reply-link": "{{GENDER:$1|Ответить}}",
+ "flow-reply-link-anonymously": "Ответить анонимно",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Поблагодарить}}}}",
"flow-thank-link-title": "Публично {{GENDER:$1|{{GENDER:$2|поблагодарить}}}} автора сообщения",
"flow-history-action-suppress-post": "подавить",
"flow-history-action-delete-post": "удалить",
"flow-history-action-hide-post": "скрыть",
"flow-history-action-unsuppress-post": "отменить подавление",
- "flow-history-action-undelete-post": "отменить удаление",
- "flow-history-action-unhide-post": "отменить скрытие",
+ "flow-history-action-undelete-post": "восстановить",
+ "flow-history-action-unhide-post": "показать",
"flow-history-action-restore-post": "восстановить",
- "flow-history-action-lock-topic": "решить",
- "flow-history-action-unlock-topic": "открыть заново",
+ "flow-history-action-lock-topic": "завершить",
+ "flow-history-action-unlock-topic": "открыть",
"flow-post-edited": "Сообщение отредактировал{{GENDER:$1||а}} $1 $2",
"flow-post-action-view": "Постоянная ссылка",
"flow-post-action-post-history": "История",
@@ -96,9 +126,10 @@
"flow-post-action-hide-post": "Скрыть",
"flow-post-action-edit-post": "Править",
"flow-post-action-edit-post-submit": "Сохранить изменения",
+ "flow-post-action-edit-post-submit-anonymously": "Сохранить изменения анонимно",
"flow-post-action-unsuppress-post": "Отменить подавление",
- "flow-post-action-undelete-post": "Отменить удаление",
- "flow-post-action-unhide-post": "Отменить скрытие",
+ "flow-post-action-undelete-post": "Восстановить",
+ "flow-post-action-unhide-post": "Показать",
"flow-post-action-restore-post": "Восстановить",
"flow-post-action-undo-moderation": "Отменить",
"flow-topic-action-view": "Постоянная ссылка",
@@ -107,10 +138,10 @@
"flow-topic-action-history": "История",
"flow-topic-action-hide-topic": "Скрыть тему",
"flow-topic-action-delete-topic": "Удалить тему",
- "flow-topic-action-lock-topic": "Отметить, как решённую",
+ "flow-topic-action-lock-topic": "Завершить",
"flow-topic-action-unlock-topic": "Раскрыть тему заново",
- "flow-topic-action-summarize-topic": "Кратко описать содержание",
- "flow-topic-action-resummarize-topic": "Править краткое содержание темы",
+ "flow-topic-action-summarize-topic": "Резюмировать",
+ "flow-topic-action-resummarize-topic": "Править резюме темы",
"flow-topic-action-update-topic-summary": "Обновить краткое описание",
"flow-topic-action-suppress-topic": "Подавить тему",
"flow-topic-action-unhide-topic": "Отменить скрытие темы",
@@ -120,28 +151,31 @@
"flow-topic-action-undo-moderation": "Отменить",
"flow-topic-notification-subscribe-title": "Эта тема добавлена в {{GENDER:$1|ваш}} список наблюдения.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Вы}} будете получать уведомления обо всех действиях в этой теме.",
- "flow-board-notification-subscribe-title": "{{GENDER:$1|Вы}} подписались на эту доску обсуждений!",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|Вы}} получите уведомление, когда на этой доске появится новая тема.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Вы}} подписались на эту стену обсуждений!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Вы}} получите уведомление, когда на этой стене появится новая тема.",
"flow-topic-action-watchlist-add": "Подписаться на эту тему",
"flow-topic-action-watchlist-remove": "Отписаться",
- "flow-error-allowcreation-flow-create-board": "У пользователя нет права «{{int:right-flow-create-board}}»",
+ "flow-error-allowcreation-no-usedb": "Включение Flow на конкретной странице требует, чтобы значение параметра <var>$wgContentHandlerUseDB</var> было <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Целевая страница уже существует, поэтому стена Flow не может перемещена.",
+ "flow-error-allowcreation-flow-create-board": "У участника нет права «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Вы не можете участвовать в обсуждении. Попробуйте выполнить вход на вики.",
+ "flow-error-can-not-edit-logged-in": "Вы не можете участвовать в обсуждении, потому что у вас нет необходимых для этого прав.",
"flow-error-http": "Произошла ошибка при обращении к серверу.",
- "flow-error-other": "Произошла непредвиденная ошибка.",
- "flow-error-external": "Произошла ошибка.<br />Было получено следующее сообщение об ошибке: $1",
- "flow-error-topic-is-locked": "Эта тема решена, дальнейшие действия невозможны.",
- "flow-error-lock-moderated-post": "Вы не можете отметить промодерированное сообщение, как решённое.",
- "flow-error-external-multi": "Были обнаружены ошибки.<br />$1",
+ "flow-error-external": "Произошла ошибка. Было получено следующее сообщение об ошибке: $1",
+ "flow-error-topic-is-locked": "Эта тема завершена, дальнейшие действия невозможны.",
+ "flow-error-lock-moderated-post": "Вы не можете отметить промодерированное сообщение, как завершенное.",
"flow-error-missing-content": "Сообщение не имеет содержимого. Для сохранения сообщения требуется содержимое.",
- "flow-error-missing-summary": "Вам необходимо оставить краткое содержание.",
+ "flow-error-missing-summary": "Вам необходимо оставить резюме.",
"flow-error-missing-title": "Тема не имеет заголовка. Заголовок необходим для сохранения темы.",
- "flow-error-parsoid-failure": "Не удаётся выполнить разбор содержимого из-за сбоя Parsoid.",
- "flow-error-missing-replyto": "Параметр «ответить на» не был предоставлен. Этот параметр является обязательным для действия «ответить».",
- "flow-error-invalid-replyto": "Недопустимый параметр «ответить на». Не удалось найти указанное сообщение.",
- "flow-error-delete-failure": "Не удалось удалить этот элемент.",
- "flow-error-hide-failure": "Не удалось скрыть этот элемент.",
- "flow-error-missing-postId": "Параметр «идентификатор сообщения» не был предоставлен. Этот параметр является обязательным для управления сообщением.",
+ "flow-error-parsoid-failure": "Не удаётся выполнить перенос содержимого: Ошибка соединения с сервером в целях преобразования вики-текста и HTML. Пожалуйста, проверьте ваше подключение к интернету или повторите попытку позже, если проблема не исчезнет. Если вы по-прежнему будете получать эту ошибку, отправьте сообщение об ошибке.",
+ "flow-error-protected-autoconfirmed-logged-in": "Эта стена защищена по причине: $1\nТолько автоподтверждённые участники могут участвовать в обсуждении.",
+ "flow-error-protected-autoconfirmed-logged-out": "Эта стена защищена по причине: $1\nТолько зарегистрированные участники могут участвовать в обсуждении.",
+ "flow-error-protected-sysop-logged-in": "Эта стена защищена по причине: $1\nТолько администраторы могут участвовать в обсуждении.",
+ "flow-error-protected-sysop-logged-out": "Эта стена защищена по причине: $1\nТолько администраторы могут участвовать в обсуждении.",
+ "flow-error-protected-unknown-reason": "Неизвестно",
+ "flow-error-missing-replyto": "Параметр «ответить на» не был предоставлен. Этот параметр — обязательный для действия «ответить».",
+ "flow-error-missing-postId": "Не был предоставлен параметр «идентификатор сообщения» (\"postId\"). Этот параметр обязателен для управления сообщением.",
"flow-error-invalid-postId": "Недопустимый параметр «идентификатор сообщения». Указанное сообщение ($1) не удается найти.",
- "flow-error-restore-failure": "Не удалось восстановить этот элемент.",
"flow-error-invalid-moderation-state": "Для Flow API было представлено недопустимое значение параметра ('moderationState').",
"flow-error-invalid-moderation-reason": "Пожалуйста, введите причину модерации.",
"flow-error-not-allowed": "Недостаточно прав для выполнения этого действия.",
@@ -157,40 +191,43 @@
"flow-error-not-allowed-suppress-extract": "Эта тема была удалена. Журнала удалений для этой темы приводится ниже для справки.",
"flow-error-not-allowed-reply-to-suppress-topic-extract": "Вы не можете ответить, потому что эта тема была подавлена. Журнал подавлений для этой темы приводится ниже для справки.",
"flow-error-title-too-long": "Заголовки тем ограничены $1 {{PLURAL:$1|байтом|байтами}}.",
- "flow-error-no-existing-workflow": "Этот поток работ ещё не существует.",
+ "flow-error-no-existing-workflow": "Эта страница не существует.",
"flow-error-not-a-post": "Название темы не может быть сохранено как сообщение.",
"flow-error-missing-header-content": "Вам необходимо оставить описание.",
"flow-error-missing-prev-revision-identifier": "Отсутствует идентификатор предыдущей версии.",
"flow-error-prev-revision-mismatch": "Другой участник отредактировал это сообщение несколько секунд назад. {{GENDER:$3|Вы}} уверены, что хотите перезаписать недавние изменения?",
"flow-error-prev-revision-does-not-exist": "Не удалось найти предыдущую версию.",
- "flow-error-core-topic-deletion": "Чтобы удалить тему, используйте меню ... на доске Потока или [$1 на странице темы]. Не посещайте с action=delete в url для темы напрямую.",
+ "flow-error-core-topic-deletion": "Чтобы удалить тему, используйте меню ... на стене Flow или [$1 на странице темы]. Не используйте action=delete в URL напрямую.",
"flow-error-default": "Произошла ошибка.",
- "flow-error-invalid-input": "Было предоставлено недопустимое значение для загрузки содержимого Потока.",
+ "flow-error-invalid-input": "Было предоставлено недопустимое значение для загрузки содержимого Flow.",
"flow-error-invalid-title": "Было предоставлено недопустимое название страницы.",
"flow-error-fail-load-history": "Не удалось загрузить содержимое истории.",
- "flow-error-missing-revision": "Не удалось найти версию для загрузки содержимого Потока.",
- "flow-error-fail-commit": "Не удалось сохранить содержимое Потока.",
+ "flow-error-missing-revision": "Не удалось найти версию для загрузки содержимого Flow.",
+ "flow-error-fail-commit": "Не удалось сохранить содержимое Flow.",
"flow-error-insufficient-permission": "Недостаточно прав для доступа к содержимому.",
"flow-error-revision-comparison": "Операция сравнения может быть сделана только для двух версий, принадлежащих одному и тому же сообщению.",
- "flow-error-missing-topic-title": "Не удалось найти название темы для текущего потока работ.",
+ "flow-error-missing-topic-title": "Не удалось найти название темы для текущего потока.",
"flow-error-missing-metadata": "Не удалось найти необходимые метаданные для этой версии.",
"flow-error-fail-load-data": "Не удалось загрузить запрошенные данные.",
- "flow-error-invalid-workflow": "Не удалось найти запрошенный поток работ.",
+ "flow-error-invalid-workflow": "Не удалось найти запрошенный поток.",
"flow-error-process-data": "Произошла ошибка при обработке данных в вашем запросе.",
"flow-error-process-wikitext": "Произошла ошибка при обработке преобразования HTML/викитекста.",
"flow-error-no-index": "Не удалось найти индекс для выполнения поиска данных.",
"flow-error-no-render": "Указанное действие не было распознано.",
"flow-error-no-commit": "Указанное действие не может быть сохранено.",
- "flow-error-content-too-long": "Содержимое является слишком большим. После расширения, содержимое ограничено {{PLURAL:$1|1=байтом|$1 байтами}}.",
- "flow-error-move-no-create-permissions": "Для перемещения доски Потока требуется право «{{int:right-flow-create-board}}».",
+ "flow-error-content-too-long": "Содержимое слишком велико. После расширения содержимое ограничено $1 {{PLURAL:$1|байтом|байтами}}.",
"flow-error-invalid-topic-uuid-title": "Недопустимое название",
- "flow-error-invalid-topic-uuid": "Запрашиваемое название страницы является недопустимым. Страницы в пространстве имен Тема создаются Потоком автоматически.",
+ "flow-error-invalid-topic-uuid": "Запрошено недопустимое название страницы. Страницы в пространстве имён \"Topic:\" создаются расширением автоматически.",
"flow-error-unknown-workflow-id-title": "Неизвестная тема",
"flow-error-unknown-workflow-id": "Запрошенная тема не существует.",
- "flow-edit-header-placeholder": "Опишите эту доску обсуждений",
+ "flow-error-search": "Нам не удалось завершить поиск из-за временной проблемы. Пожалуйста, повторите попытку позже.",
+ "flow-edit-header-placeholder": "Опишите эту стену обсуждений",
"flow-edit-header-submit": "Сохранить описание",
+ "flow-edit-header-submit-anonymously": "Сохранить описание анонимно",
"flow-edit-title-submit": "Изменить заголовок",
+ "flow-edit-title-submit-anonymously": "Изменить заголовок анонимно",
"flow-edit-post-submit": "Подтвердить изменения",
+ "flow-edit-post-submit-anonymously": "Сохранить изменения анонимно",
"flow-rev-message-edit-post": "$1 отредактировал{{GENDER:$2||а}} [$3 комментарий] в «$4»",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Отредактировал|Отредактировала}} сообщение",
"flow-rev-message-reply": "$1 [$3 прокомментировал{{GENDER:$2||а}}] «$4» (<em>$5</em>)",
@@ -200,7 +237,7 @@
"flow-rev-message-edit-title": "$1 изменил{{GENDER:$2||а}} название темы с «$5» на «[$3 $4]»",
"flow-rev-message-create-header": "$1 создал{{GENDER:$2||а}} описание",
"flow-rev-message-edit-header": "$1 отредактировал{{GENDER:$2||а}} описание",
- "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|создал|создала}} краткое описание темы «$3»",
+ "flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|создал|создала}} резюме темы «$3»",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|отредактировал|отредактировала}} краткое содержание темы «$3»",
"flow-rev-message-hid-post": "$1 {{GENDER:$2|скрыл|скрыла}} [$4 комментарий] в «$6» (<em>$5</em>)",
"flow-rev-message-deleted-post": "$1 удалил{{GENDER:$2||а}} [$4 комментарий] в «$6» (<em>$5</em>)",
@@ -209,58 +246,87 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|скрыл|скрыла}} [$4 тему] «$6» (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|удалил|удалила}} [$4 тему] «$6» (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|подавил|подавила}} [$4 тему] «$6» (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 отметил{{GENDER:$2||а}} [$4 тему] $6 как разрешённую (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 отметил{{GENDER:$2||а}} [$4 тему] «$6» как завершенную (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "отмечен как закрытый",
+ "flow-rev-message-restore-topic-reason": "открыто заново",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|восстановил|восстановила}} [$4 тему] «$6» (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 на $2",
"flow-board-history": "История «$1»",
- "flow-board-history-empty": "У этой доски в настоящее время нет истории.",
+ "flow-board-history-empty": "У этой стены в настоящее время нет истории.",
"flow-topic-history": "История темы «$1»",
"flow-post-history": "«Комментарий {{GENDER:$2|$2}}» история сообщения",
"flow-history-last4": "За последние 4 часа",
"flow-history-day": "Сегодня",
"flow-history-week": "На прошлой неделе",
- "flow-history-pages-topic": "Показывается на [$1 доске «$2»]",
+ "flow-history-pages-topic": "Показывается на [$1 стене «$2»]",
"flow-history-pages-post": "Показывается в [$1 $2]",
"flow-topic-comments": "{{PLURAL:$1|$1 комментарий|$1 комментария|$1 комментариев|0={{GENDER:$2|Оставь первым|Оставь первой}} комментарий!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Посмотреть комментарий|Посмотреть комментарии}}",
"flow-hide-comments-title": "{{PLURAL:$1|Скрыть комментарий|Скрыть комментарии}}",
"flow-comment-restored": "Восстановленный комментарий",
"flow-comment-deleted": "Удалённый комментарий",
"flow-comment-hidden": "Скрытый комментарий",
"flow-comment-moderated": "Промодерированный комментарий",
"flow-last-modified": "Последнее изменение около $1",
- "flow-workflow": "поток работ",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1| ответил|ответила}} на '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и $5 {{PLURAL:$6|другой|других}} {{GENDER:$1|ответил|ответила}} на странице '''$3'''.",
+ "flow-workflow": "поток",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|ответил|ответила}} на <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и {{PLURAL:$5|$5 другой ответил{{GENDER:$1||а}}|$5 других ответило|100=99+ других ответило}} на странице <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 отредактировал{{GENDER:$1||а}} ваше <span class=\"plainlinks\">[$5 сообщение]</span> на [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 и $5 {{PLURAL:$6|другой|других}} {{GENDER:$1|отредактировал|отредактировала}} <span class=\"plainlinks\">[$4 сообщение]</span> в «$2» на «$3».",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|создал|создала}} новую тему на '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1 новая тема|$1 новых тем|$1 новые темы|250=250+ новых тем}} в '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 и {{PLURAL:$5|$5 другой участников отредактировал{{GENDER:$1||а}}|$5 других участников отредактировало|100=99+ других участников отредактировало}} <span class=\"plainlinks\">[$4 сообщение]</span> в «$2» на «$3».",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|$1 новая тема|$1 новых тем|100=99+ новых тем}} на <strong>$3</strong>",
+ "notification-header-flow-new-topic-user-talk": "На <strong>вашей странице обсуждения</strong> была создана новая тема: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|$1 новая тема|$1 новых тем|100=99+ новых тем}} на вашей странице обсуждений",
+ "notification-header-flow-post-reply": "$1 ответил{{GENDER:$2||а}} в «<strong>$4</strong>».",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Ваше}} сообщение в «<strong>$1</strong>» было отредактировано.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Ваше}} сообщение в «<strong>$1</strong>» было несколько раз отредактировано.",
+ "notification-header-flow-summary-edited": "Резюме для «<strong>$1</strong>» было обновлено.",
+ "notification-email-subject-flow-summary-edited": "$1 обновил{{GENDER:$2||а}} резюме в $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 обновил{{GENDER:$2||а}} краткое описание $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 {{PLURAL:$3|ещё один участник|$3 других участников|100=99+ других участников}} {{PLURAL:$3|обновил{{GENDER:$2||а}}|и}} резюме в $2",
+ "notification-header-flow-mention-post": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$4|вас}} в «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$4|вас}} в описании «<strong>$3</strong>».",
+ "notification-header-flow-mention-post-summary": "$1 упомянул{{GENDER:$2||а}} {{GENDER:$4|вас}} в «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Новая система обсуждений подключена для <strong>{{GENDER:$2|вашей}} страницы обсуждений</strong>.",
+ "notification-header-flow-description-edited": "Описание <strong>$1</strong> было отредактировано.",
+ "notification-header-flow-description-edited-user-talk": "Описание на <strong>{{GENDER:$2|вашей}} странице обсуждения</strong> было отредактировано.",
+ "notification-bundle-header-flow-description-edited": "Описание <strong>$1</strong> было несколько раз отредактировано.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Описание на <strong>{{GENDER:$2|вашей}} странице обсуждения</strong> было отредактировано несколько раз.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Посмотреть}} страницу",
+ "notification-email-subject-flow-description-edited": "$1 отредактировал{{GENDER:$1||а}} описание на странице $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|отредактировал|отредактировала}} описание страницы $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 и {{PLURAL:$3|$3 {{GENDER:$1|другой отредактировал|другая отредактировала}}|$3 других отредактировали|100=99+ других отредактировали}} описание на странице $2",
+ "notification-header-flow-topic-resolved": "Тема «<strong>$1</strong>» была завершена.",
+ "notification-header-flow-topic-reopened": "Тема «<strong>$1</strong>» была переоткрыта.",
+ "notification-email-subject-flow-topic-resolved": "Тема «<strong>$2</strong>» была завершена.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|создал|создала}} новую тему на <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1 новая тема|$1 новых тем|$1 новые темы|100=99+ новых тем}} в <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|изменил|изменила}} заголовок темы <span class=\"plainlinks\">[$2 $3]</span> на «$4» на странице [[$5|$6]].",
"flow-notification-mention": "$1 упомянул{{GENDER:$1||а}} {{GENDER:$5|вас}} в {{GENDER:$1|своём}} <span class=\"plainlinks\">[$2 сообщении]</span> в «$3» на «$4».",
"flow-notification-link-text-view-post": "Посмотреть сообщение",
"flow-notification-link-text-view-topic": "Посмотреть тему",
+ "flow-notification-link-text-view-topics": "Посмотреть темы",
"flow-notification-reply-email-subject": "$2 на $3",
"flow-notification-reply-email-batch-body": "$1 ответил{{GENDER:$1||а}} в «$2» на $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 и $4 {{PLURAL:$5|другой|других}} {{GENDER:$1|ответил|ответила}} в «$2» на $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 и {{PLURAL:$4|$4 {{GENDER:$1|другой ответил|другая ответила}}|$4 других ответили|100=99+ других ответили}} в «$2» на $3",
"flow-notification-mention-email-subject": "$1 упомянул{{GENDER:$1||а}} {{GENDER:$3|вас}} в $2",
"flow-notification-mention-email-batch-body": "$1 упомянул{{GENDER:$1||а}} {{GENDER:$4|вас}} в {{GENDER:$1|своём}} сообщении в «$2» на $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|отредактировал|отредактировала}} сообщение",
"flow-notification-edit-email-batch-body": "$1 отредактировал{{GENDER:$2||а}} сообщение в «$2» на $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 и $4 {{PLURAL:$5|другой|других}} {{GENDER:$1|отредактировал|отредактировала}} сообщение в «$2» на $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 и {{PLURAL:$4|$4 {{GENDER:$1|другой отредактировал|другая отредактировала}}|$4 других отредактировали|100=99+ других отредактировали}} в «$2» на $3",
"flow-notification-rename-email-subject": "$1 переименовал{{GENDER:$1||а}} вашу тему",
"flow-notification-rename-email-batch-body": "$1 переименовал{{GENDER:$1||а}} вашу тему с «$2» на «$3» на странице $4",
"flow-notification-newtopic-email-subject": "$1 создал{{GENDER:$1||а}} новую тему на странице $2",
"flow-notification-newtopic-email-batch-body": "$1 создал{{GENDER:$1||а}} новую тему с названием «$2» на странице $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 новая тема|$1 новых темы|$1 новых тем|250=250+ новых тем}} на $2",
- "echo-category-title-flow-discussion": "Поток",
- "echo-pref-tooltip-flow-discussion": "Уведомить меня, когда связанные со мной действия происходят в Потоке.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 новая тема|$1 новых тем|$1 новых темы|100=99+ новых тем}} на $2",
+ "echo-category-title-flow-discussion": "Структурированное обсуждение",
+ "echo-pref-tooltip-flow-discussion": "Уведомить меня об активности в темах или на страницах, которые я отслеживаю.",
"flow-link-post": "сообщение",
"flow-link-topic": "тема",
"flow-link-history": "история",
"flow-link-post-revision": "версия сообщения",
"flow-link-topic-revision": "версия темы",
"flow-link-header-revision": "версия описания",
- "flow-link-summary-revision": "версия краткого содержания",
+ "flow-link-summary-revision": "версия резюме",
"flow-moderation-title-suppress-post": "Подавить сообщение?",
"flow-moderation-title-delete-post": "Удалить сообщение?",
"flow-moderation-title-hide-post": "Скрыть сообщение?",
@@ -285,18 +351,18 @@
"flow-moderation-confirm-unsuppress-topic": "Отменить подавление",
"flow-moderation-confirm-undelete-topic": "Отменить удаление",
"flow-moderation-confirm-unhide-topic": "Отменить скрытие",
- "flow-moderation-confirmation-suppress-post": "Сообщение было успешно подавлено.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
- "flow-moderation-confirmation-delete-post": "Сообщение было успешно удалено.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
- "flow-moderation-confirmation-hide-post": "Сообщение было успешно скрыто.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
- "flow-moderation-confirmation-unsuppress-post": "Вы успешно отменили подавление вышеуказанного сообщения.",
- "flow-moderation-confirmation-undelete-post": "Вы успешно отменили удаление вышеуказанного сообщения.",
- "flow-moderation-confirmation-unhide-post": "Вы успешно отменили скрытие вышеуказанного сообщения.",
+ "flow-moderation-confirmation-suppress-post": "Сообщение было подавлено.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
+ "flow-moderation-confirmation-delete-post": "Сообщение было удалено.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
+ "flow-moderation-confirmation-hide-post": "Сообщение было скрыто.\n{{GENDER:$2|Рассмотрите}} возможность предоставления для $1 отзыва на это сообщение.",
+ "flow-moderation-confirmation-unsuppress-post": "Вы отменили подавление вышеуказанного сообщения.",
+ "flow-moderation-confirmation-undelete-post": "Вы отменили удаление вышеуказанного сообщения.",
+ "flow-moderation-confirmation-unhide-post": "Вы отменили скрытие вышеуказанного сообщения.",
"flow-moderation-confirmation-suppress-topic": "Эта тема была подавлена.",
"flow-moderation-confirmation-delete-topic": "Эта тема была удалена.",
"flow-moderation-confirmation-hide-topic": "Эта тема была скрыта.",
- "flow-moderation-confirmation-unsuppress-topic": "Вы успешно отменили подавление этой темы.",
- "flow-moderation-confirmation-undelete-topic": "Вы успешно отменили удаление этой темы.",
- "flow-moderation-confirmation-unhide-topic": "Вы успешно отменили скрытие этой темы.",
+ "flow-moderation-confirmation-unsuppress-topic": "Вы отменили подавление этой темы.",
+ "flow-moderation-confirmation-undelete-topic": "Вы отменили удаление этой темы.",
+ "flow-moderation-confirmation-unhide-topic": "Вы отменили скрытие этой темы.",
"flow-moderation-title-suppress-topic": "Подавить тему?",
"flow-moderation-title-delete-topic": "Удалить тему?",
"flow-moderation-title-hide-topic": "Скрыть тему?",
@@ -310,24 +376,24 @@
"flow-moderation-placeholder-undelete-topic": "Пожалуйста, {{GENDER:$3|поясните}} почему вы отменяете удаление этой темы.",
"flow-moderation-placeholder-unhide-topic": "Пожалуйста, {{GENDER:$3|поясните}} почему вы отменяете скрытие этой темы.",
"flow-topic-permalink-warning": "Эта тема была начата на [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Эта тема была начата на [$2 доске {{GENDER:$1|участника|участницы}} $1]",
+ "flow-topic-permalink-warning-user-board": "Эта тема была начата на [$2 стене {{GENDER:$1|участника|участницы}} $1]",
"flow-revision-permalink-warning-post": "Это постоянная ссылка на одну версию этого сообщения.\nЭта версия от $1.\nВы можете увидеть [$5 отличия от предыдущей версии], или просмотреть другие версии на [$4 на странице истории этого сообщения].",
"flow-revision-permalink-warning-post-first": "Это постоянная ссылка на первую версию этого сообщения.\nВы можете посмотреть более поздние версии на [$4 странице истории этого сообщения].",
- "flow-revision-permalink-warning-postsummary": "Это постоянная ссылка на одну версию краткого содержания этого сообщения. Эта версия от $1.\nВы можете увидеть [$5 отличия от предыдущей версии], или просмотреть другие версии на [$4 странице истории этого сообщения].",
- "flow-revision-permalink-warning-postsummary-first": "Это постоянная ссылка на первую версию краткого содержания этого сообщения.\nВы можете посмотреть более поздние версии на [$4 странице истории этого сообщения].",
- "flow-revision-permalink-warning-header": "Это постоянная ссылка на одну версию описания.\nЭта версия от $1. Вы можете увидеть [$3 отличия от предыдущей версии], или просмотреть другие версии на [$2 странице истории этой доски].",
- "flow-revision-permalink-warning-header-first": "Это постоянная ссылка на первую версию этого описания.\nВы можете посмотреть более поздние версии на [$2 странице истории этой доски].",
+ "flow-revision-permalink-warning-postsummary": "Это постоянная ссылка на одну версию резюме этого сообщения. Эта версия от $1.\nВы можете увидеть [$5 отличия от предыдущей версии], или просмотреть другие версии на [$4 странице истории этого сообщения].",
+ "flow-revision-permalink-warning-postsummary-first": "Это постоянная ссылка на первую версию резюме этого сообщения.\nВы можете посмотреть более поздние версии на [$4 странице истории этого сообщения].",
+ "flow-revision-permalink-warning-header": "Это постоянная ссылка на одну версию описания.\nЭта версия от $1. Вы можете увидеть [$3 отличия от предыдущей версии], или просмотреть другие версии на [$2 странице истории этой стены].",
+ "flow-revision-permalink-warning-header-first": "Это постоянная ссылка на первую версию этого описания.\nВы можете посмотреть более поздние версии на [$2 странице истории этой стены].",
"flow-compare-revisions-revision-header": "Версия {{GENDER:$2|участника|участницы}} $2 от $1",
"flow-compare-revisions-header-post": "На этой странице показаны {{GENDER:$3|изменения}} между двумя версиями сообщения от участника $3 в теме «[$5 $2]» на [$4 $1].\nВы можете посмотреть другие версии этого сообщения на его [$6 странице истории].",
- "flow-compare-revisions-header-postsummary": "Эта страница показывает изменения между двумя версиями краткого содержания в сообщении «[$4 $2]» на [$3 $1].\nВы можете увидеть другие версии этого сообщения на его [$5 странице истории].",
+ "flow-compare-revisions-header-postsummary": "Эта страница показывает изменения между двумя версиями резюме темы «[$4 $2]» на [$3 $1].\nВы можете увидеть другие версии резюме этой темы на [$5 странице истории] темы.",
"flow-compare-revisions-header-header": "Эта страница показывает {{GENDER:$2|изменения}} между двумя версиями описания на [$3 $1].\nВы можете увидеть другие версии описания на её [$4 странице истории].",
- "action-flow-create-board": "создание досок Потока в любом месте",
- "right-flow-create-board": "создание досок Потока в любом месте",
- "right-flow-hide": "скрытие тем и сообщений Потока",
- "right-flow-lock": "пометка тем Потока как завершённых",
- "right-flow-delete": "Удалять темы и сообщения Потока",
- "right-flow-edit-post": "правка сообщений Потока других участников",
- "right-flow-suppress": "подавление версий Потока",
+ "action-flow-create-board": "создание стен Flow в любом месте",
+ "right-flow-create-board": "создание стен Flow в любом месте",
+ "right-flow-hide": "скрытие тем и сообщений Flow",
+ "right-flow-lock": "завершение тем Flow",
+ "right-flow-delete": "удаление тем и сообщений Flow",
+ "right-flow-edit-post": "правка всех сообщений Flow",
+ "right-flow-suppress": "подавление сообщений и тем Flow",
"flow-terms-of-use-new-topic": "Нажимая «{{int:flow-newtopic-save}}», вы соглашаетесь с условиями использования этой вики.",
"flow-terms-of-use-reply": "Нажимая «{{int:flow-reply-link}}», вы соглашаетесь с условиями использования этой вики.",
"flow-terms-of-use-edit": "Сохраняя изменения, вы соглашаетесь с условиями использования этой вики.",
@@ -350,22 +416,23 @@
"flow-terms-of-use-unlock-topic": "Нажимая «{{int:flow-topic-action-unlock-topic}}», вы соглашаетесь с условиями использования этой вики.",
"flow-whatlinkshere-post": "из [$1 сообщения]",
"flow-whatlinkshere-header": "из [$1 описания]",
- "flow": "Поток",
- "flow-special-desc": "Эта специальная страница перенаправляет на workflow Потока или на сообщение Потока по UUID.",
+ "structureddiscussions": "Структурированные обсуждения",
+ "flow-special-desc": "Эта специальная страница перенаправляет на поток Flow или на сообщение Flow по UUID.",
"flow-special-type": "Тип",
"flow-special-type-post": "Сообщение",
- "flow-special-type-workflow": "Поток работ",
+ "flow-special-type-workflow": "Поток",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Не удалось найти содержимое, соответствующее типу и UUID.",
- "flow-special-enableflow-legend": "Включить Поток на новой странице",
- "flow-special-enableflow-page": "Страница для включения Потока",
- "flow-special-enableflow-header": "Начальное описание доски Потока (викитекст)",
- "flow-special-enableflow-board-already-exists": "Там уже есть доска Потока на [[$1]].",
+ "flow-special-enableflow-legend": "Включить Flow на новой странице",
+ "flow-special-enableflow-page": "Страница для включения Flow",
+ "flow-special-enableflow-header": "Начальное описание стены Flow (викитекст)",
+ "flow-special-enableflow-board-already-exists": "Стена Flow уже существует на странице [[$1]].",
"flow-special-enableflow-invalid-title": "Было предоставлено недопустимое название страницы",
- "flow-special-enableflow-board-creation-not-allowed": "Вам не разрешено создание доски Потока на [[:$1]].",
- "flow-special-enableflow-confirmation": "Вы успешно создали доску Потока на [[$1]].",
- "flow-conversion-archive-flow-page-name-format": "%s/Архив Потока %d\n%s/АрхивПотока%d",
- "flow-spam-confirmedit-form": "Пожалуйста, введите текст с картинки ниже, если вы не робот: $1",
+ "flow-special-enableflow-board-creation-not-allowed": "Вам не разрешено создание стены Flow на [[:$1]].",
+ "flow-special-enableflow-confirmation": "Вы создали стену Flow на [[$1]].",
+ "flow-conversion-archive-page-name-format": "%s/Архив %d\n%s/Архив%d\n%s/архив %d\n%s/архив%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Архив Flow %d\n%s/АрхивFlow%d",
+ "flow-spam-confirmedit-form": "Пожалуйста, подтвердите, что вы человек, решив капчу ниже: $1",
"flow-embedding-unsupported": "Обсуждения пока не могут быть вставленным куда-либо ещё.",
"mw-ui-unsubmitted-confirm": "У вас есть неприменённые изменения на этой странице. Вы уверены, что хотите уйти и потерять изменения?",
"flow-post-undo-hide": "отмена скрытия",
@@ -374,125 +441,34 @@
"flow-topic-undo-hide": "отмена скрытия",
"flow-topic-undo-delete": "отменить удаление",
"flow-topic-undo-suppress": "отмена подавления",
- "flow-importer-lqt-moved-thread-template": "LQT Moved thread stub преобразован в Поток",
- "flow-importer-lqt-converted-template": "LQT-страница преобразована в Поток",
+ "flow-importer-lqt-moved-thread-template": "LQT Moved thread stub преобразован в Flow",
+ "flow-importer-lqt-converted-template": "LQT-страница преобразована в Flow",
"flow-importer-lqt-converted-template-content": "Предыдущая страница истории была архивирования в целях резервного копирования в <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Архив преобразованной LQT-страницы",
- "flow-importer-wt-converted-template": "Вики-текст страницы обсуждения преобразован в Поток",
+ "flow-importer-wt-converted-template": "Вики-текст страницы обсуждения преобразован в Flow",
"flow-importer-wt-converted-template-content": "Предыдущее обсуждение было архивировано в <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> on {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Архив преобразованного вики-текста страницы обсуждения",
+ "flow-importer-wt-converted-archive-template-content": "Эта страница является архивом. <strong>Не редактируйте ее содержимое</strong>. Вы можете оставить комментарий на [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|текущей странице обсуждений]].",
"flow-importer-lqt-suppressed-user-template": "LQT-публикация, импортированная с подавленным пользователем",
- "apihelp-flow-description": "Позволяет применять действия к страницам Потока.",
- "apihelp-flow-param-submodule": "Вызываемый подмодуль Потока",
- "apihelp-flow-param-page": "Страница, к которой применяются действия.",
- "apihelp-flow-example-1": "Править описание у «[[Talk:Sandbox]]»",
- "apihelp-flow+close-open-topic-description": "Устарело в пользу [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Состояние, задаваемое теме: «закрыта» или «открыта».",
- "apihelp-flow+close-open-topic-param-reason": "Основание для закрытия или отмены закрытия темы.",
- "apihelp-flow+edit-header-description": "Редактирование описания доски.",
- "apihelp-flow+edit-header-param-prev_revision": "Идентификатор версии текущей версии описания, для проверки на конфликты редактирования.",
- "apihelp-flow+edit-header-param-content": "Содержимое для описания.",
- "apihelp-flow+edit-header-param-format": "Формат описания (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "Править описание у [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Правки содержимого сообщения.",
- "apihelp-flow+edit-post-param-postId": "ID сообщения.",
- "apihelp-flow+edit-post-param-prev_revision": "Revision ID текущей версии сообщения, для проверки на конфликты редактирования.",
- "apihelp-flow+edit-post-param-content": "Содержимое для сообщения.",
- "apihelp-flow+edit-post-param-format": "Формат содержимого сообщения (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "Править сообщение в [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Правки заголовка темы.",
- "apihelp-flow+edit-title-param-prev_revision": "Revision ID текущей версии заголовка, для проверки на конфликты редактирования.",
- "apihelp-flow+edit-title-param-content": "Содержимое для заголовка.",
- "apihelp-flow+edit-title-example-1": "Править заголовок у [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Правки содержимого краткого содержания темы.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Revision ID текущей версии краткого содержания темы, для проверки на конфликты редактирования.",
- "apihelp-flow+edit-topic-summary-param-summary": "Содержимое для краткого содержания.",
- "apihelp-flow+edit-topic-summary-param-format": "Формат краткого содержания (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Править краткое содержание в [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Закрыть или отменить закрытие темы Потока.",
- "apihelp-flow+lock-topic-param-moderationState": "Состояние, задаваемое теме: <kbd>закрыта</kbd> или <kbd>открыта</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Причина для закрытия или открытия темы. Обратите внимание, клиент Потока в вики использует здесь \"Помечено как улаженное\" и добавляет на необязательные дополнительные сведения в краткое содержание.",
- "apihelp-flow+lock-topic-example-1": "Закрыть [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Модерирования сообщения Потока.",
- "apihelp-flow+moderate-post-param-moderationState": "Какой уровень модерации.",
- "apihelp-flow+moderate-post-param-reason": "Причина модерации.",
- "apihelp-flow+moderate-post-param-postId": "ID сообщения для модерации.",
- "apihelp-flow+moderate-post-example-1": "Удалить сообщение в теме [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Модерирования темы Потока.",
- "apihelp-flow+moderate-topic-param-moderationState": "Какой уровень модерации.",
- "apihelp-flow+moderate-topic-param-reason": "Причина модерации.",
- "apihelp-flow+moderate-topic-example-1": "Удалить тему [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Создает новую тему Потока в данном потоке работ.",
- "apihelp-flow+new-topic-param-topic": "Текст для нового заголовка темы.",
- "apihelp-flow+new-topic-param-content": "Содержимое для начального ответа в теме.",
- "apihelp-flow+new-topic-param-format": "Формат начального ответа в новой теме (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "Создать новую тему в [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Ответы на сообшение.",
- "apihelp-flow+reply-param-replyTo": "ID сообщения для ответа.",
- "apihelp-flow+reply-param-content": "Содержимое для нового сообщения.",
- "apihelp-flow+reply-param-format": "Формат нового сообщения (wikitext|html)",
- "apihelp-flow+reply-example-1": "Ответить на сообщение в [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Формат, в котором вернуть содержимое",
- "apihelp-flow+view-header-description": "Посмотреть описание доски.",
- "apihelp-flow+view-header-param-revId": "Загрузить эту версию, вместо текущей.",
- "apihelp-flow+view-header-example-1": "Извлечь описание у [[Talk:Sandbox]] как вики-текст",
- "apihelp-flow+view-post-description": "Посмотреть сообщение.",
- "apihelp-flow+view-post-param-postId": "ID сообщения для просмотра.",
- "apihelp-flow+view-post-param-format": "Формат, в котором вернуть содержимое",
- "apihelp-flow+view-post-example-1": "Извлечь содержимое сообщения у [[Topic:S2tycnas4hcucw8w]] как вики-текст",
- "apihelp-flow+view-topic-description": "Посмотреть тему.",
- "apihelp-flow+view-topic-example-1": "Просмотреть [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-summary-description": "Посмотреть краткое содержание темы.",
- "apihelp-flow+view-topic-summary-param-format": "Формат, в котором вернуть содержимое",
- "apihelp-flow+view-topic-summary-param-revId": "Загрузить эту версию, вместо текущей.",
- "apihelp-flow+view-topic-summary-example-1": "Посмотреть краткое содержание у [[Topic:S2tycnas4hcucw8w]] как вики-текст",
- "apihelp-flow+view-topiclist-description": "Посмотреть список тем.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Направление порядка тем.",
- "apihelp-flow+view-topiclist-param-sortby": "Вариант сортировки тем, как обновлённых (отсортированных по времени обновления), так и новых (отсортированных по времени создания).",
- "apihelp-flow+view-topiclist-param-savesortby": "Сохранить способ сортировки в настройках пользователя (если установлен).",
- "apihelp-flow+view-topiclist-param-offset-id": "Значение смещения (в формате UUID), чтобы начать выборку тем.",
- "apihelp-flow+view-topiclist-param-offset": "Значение смещения, чтобы начать выборку тем.",
- "apihelp-flow+view-topiclist-param-limit": "Количество тем для извлечения.",
- "apihelp-flow+view-topiclist-example-1": "Список тем в [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Преобразовать текст между вики-текстом и HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Формат из которого преобразуется содержимое.",
- "apihelp-flow-parsoid-utils-param-to": "Формат в который преобразуется содержимое.",
- "apihelp-flow-parsoid-utils-param-content": "Содержимое которое нежно преобразовать",
- "apihelp-flow-parsoid-utils-param-title": "Заголовок страницы. Не может использоваться вместе с $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID страницы. Не может использоваться вместе с $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Преобразование вики-текста <nowiki>'''lorem''' ''blah''</nowiki> в HTML",
- "apihelp-query+flowinfo-description": "Получить основную информацию Потока о странице.",
- "apihelp-query+flowinfo-example-1": "Извлечь информацию Потока о [[Talk:Sandbox]], [[Main Page]] и [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Получить информацию, необходимую для отмены правок описания.",
- "apihelp-flow+undo-edit-header-param-startId": "Id версии начала отмены.",
- "apihelp-flow+undo-edit-header-param-endId": "Id версии конца отмены.",
- "apihelp-flow+undo-edit-header-example-1": "Извлечь информацию об отмене правки описания у [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Получить информацию, необходимую для отмены правки сообщения.",
- "apihelp-flow+undo-edit-post-param-postId": "ID сообщения, которое будет отменено.",
- "apihelp-flow+undo-edit-post-param-startId": "Id версии начала отмены.",
- "apihelp-flow+undo-edit-post-param-endId": "Id версии конца отмены.",
- "apihelp-flow+undo-edit-post-example-1": "Извлечь информацию об отмене правок сообщения в отдельной теме.",
- "apihelp-flow+undo-edit-topic-summary-description": "Получать информацию, необходимую для отмены правок краткого содердания темы.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Id версии начала отмены.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Id версии конца отмены.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Извлечь сведения об отмене правок краткого содержания темы в отдельной теме",
"flow-edited": "Отредактировано",
"flow-edited-by": "Отредактировано $1",
- "flow-lqt-redirect-reason": "Перенаправление устаревшего сообщения LiquidThreads на преобразованное в сообщение Потока",
- "flow-talk-conversion-move-reason": "Преобразование обсуждения из вики-текста в Поток со страницы $1",
- "flow-talk-conversion-archive-edit-reason": "Преобразование обсуждения из вики-текста в Поток",
+ "flow-edited-by-header": "Описание стены было отредактировано $1",
+ "flow-edited-by-topic-title": "Название темы было отредактировано $1",
+ "flow-lqt-redirect-reason": "Перенаправление устаревшего сообщения LiquidThreads на преобразованное в сообщение Flow",
+ "flow-talk-conversion-move-reason": "Преобразование обсуждения из вики-текста в Flow со страницы $1",
+ "flow-talk-conversion-archive-edit-reason": "Преобразование обсуждения из вики-текста в Flow",
"flow-previous-diff": "← Предыдущая правка",
"flow-next-diff": "Следующая правка →",
"flow-undo": "отменить",
"flow-undo-latest-revision": "Текущая версия",
"flow-undo-your-text": "Ваш текст",
"flow-undo-edit-header": "Редактирование описания",
- "flow-undo-edit-topic-summary": "Редактирование краткого содержания темы",
+ "flow-undo-edit-topic-summary": "Правка резюме темы",
"flow-undo-edit-post": "Редактировании сообщения",
"flow-undo-edit-content": "Правка может быть отменена. Пожалуйста, проверьте сравнение версий, чтобы убедиться, что это именно то, что вы хотели, и сохраните изменения чтобы закончить отмену правки.",
"flow-undo-edit-failure": "Правка не может быть отменена из-за несовместимости промежуточных изменений.",
- "group-flow-bot": "боты Потока",
- "group-flow-bot-member": "бот Потока",
+ "group-flow-bot": "Flow",
+ "group-flow-bot-member": "Flow",
"grouppage-flow-bot": "Project:Flow bots",
"flow-ve-mention-context-item-label": "Упоминание",
"flow-ve-mention-inspector-title": "Упоминание",
@@ -503,12 +479,34 @@
"flow-ve-mention-inspector-invalid-user": "Участник «$1» не зарегистрирован.",
"flow-wikitext-editor-help": "Вики-текст $1.",
"flow-wikitext-editor-help-and-preview": "Вики-текст $1 и вы можете $2 в любое время.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|использует разметку]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|использует разметку]]",
"flow-wikitext-editor-help-preview-the-result": "предварительно просмотреть результат",
- "flow-wikitext-switch-editor-tooltip": "Переключить на Визуальный редактор",
+ "flow-wikitext-switch-editor-tooltip": "Переключить на визуальный редактор",
"flow-ve-switch-editor-tool-title": "Переключить на редактор вики-текста",
- "flow-talk-page-beta-feature-message": "Поток на странице обсуждения участни{{GENDER:|ка|цы}}",
- "flow-talk-page-beta-feature-description": "Включает новую систему структурированного обсуждения на вашей странице обсуждения участни{{GENDER:|ка|цы}}. Поток упрощает дискуссии на страницe обсуждения, добавляет понятные места где писать и где отвечать, и обеспечивает уведомления для каждого разговора. Существующие обсуждения на вики-тексте будут перемещены в архив. Эта функция не включается автоматически; участники должны будут самостоятельно включить его отдельно. Отключение этой функции переименует доску Потока в подстраницу и разархивирует предыдущую страницу обсуждения.",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Поток, новая система обсуждений в вики, была включена на вашей странице обсуждения участни{{GENDER:$1|ка|цы}} в {{SITENAME}}. Вы можете получить более подробную информацию, оставить отзыв или отключить новую систему в любое время из бета-функций в разделе ваших настроек.",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Ваша}} страница обсуждения - это место, где другие редакторы могут связаться с {{GENDER:$1|вами}}. С Потоком легче начинать новые темы и продолжать отслеживать разговоры."
+ "flow-mark-revision-patrolled-link-text": "Отметить эту страницу как проверенную",
+ "flow-mark-revision-patrolled-link-title": "Отметить эту страницу как проверенную",
+ "flow-mark-diff-patrolled-link-text": "Отметить как проверенную",
+ "flow-mark-diff-patrolled-link-title": "Отметить как проверенную",
+ "flow-talk-page-beta-feature-message": "Flow на странице обсуждения участника",
+ "flow-talk-page-beta-feature-description": "Включает новую систему структурированного обсуждения на {{GENDER:|вашей}} странице обсуждения участника. Flow упрощает дискуссии на страницe обсуждения, добавляет понятные места для написания и ответа, и обеспечивает уведомления для каждого разговора. Эта функция не включается автоматически, участники должны будут самостоятельно включить её отдельно.<br /><br />Существующие обсуждения на вики-тексте будут перемещены в архив. Отключение этой функции переименует стену Flow в подстраницу и разархивирует предыдущую страницу обсуждения. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Узнать подробнее об активации]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Посмотреть}} страницу обсуждения участника",
+ "flow-notification-enabled-on-talkpage-title": "Для {{GENDER:$1|вашей}} странице обсуждения участни{{GENDER:$1|ка|цы}} включена новая система обсуждений<br /><small>Доступно на [[$2]]</small>",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "Новая система обсуждений на $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Flow, новая система обсуждений в вики, была включена на {{GENDER:$1|вашей}} странице обсуждения в {{SITENAME}}. Вы можете получить более подробную информацию, оставить отзыв или отключить новую систему в любое время из бета-функций в разделе {{GENDER:$1|ваших}} настроек.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Добавление шаблона архива",
+ "flow-beta-feature-remove-archive-template-edit-summary": "Удаление шаблона архива",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|Вы}} уверены?",
+ "flow-dialog-cancelconfirm-message": "{{GENDER:|Вы}} уверены, что хотите отменить без сохранения?",
+ "flow-dialog-cancelconfirm-keep": "Продолжить редактирование",
+ "flow-dialog-cancelconfirm-discard": "Отменить изменения",
+ "flow-optin-archive-wikitext": "Переименовывание страницы с вики-текстом, чтобы освободить место для стены обсуждений.",
+ "flow-optin-archive-flow-board": "Переименовывание страницы со стеной обсуждений для освобождения места.",
+ "flow-optin-restore-wikitext": "Восстановление архивированной страницы с викитекстом.",
+ "flow-optin-restore-flow-board": "Восстановление архивированной стены обсуждений.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Добро пожаловать}} на {{GENDER:$1|вашу}} новую страницу обсуждения участни{{GENDER:$1|ка|цы}}",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Ваша}} страница обсуждения - это место, где другие редакторы могут связаться с {{GENDER:$1|вами}}. С Flow легче начинать новые темы и продолжать отслеживать разговоры.",
+ "flow-guidedtour-optin-find-old-conversations": "Найти {{GENDER:$1|ваш}} старые разговоры",
+ "flow-guidedtour-optin-find-old-conversations-description": "Предыдущие разговоры были перемещены на архивную страницу.",
+ "flow-guidedtour-optin-feedback": "Оправьте нам {{GENDER:$1|ваши}} отзывы и предложения!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Вы}} можете получить более подробную информацию, отправить отзыв и предложение или отключить эту новую систему в любое время в разделе настроек «бета-функции»."
}
diff --git a/Flow/i18n/sa.json b/Flow/i18n/sa.json
index eac19a1b..98b2e1ed 100644
--- a/Flow/i18n/sa.json
+++ b/Flow/i18n/sa.json
@@ -50,5 +50,5 @@
"flow-undo-latest-revision": "नूतनतमं संस्करणम्",
"flow-undo-your-text": "भवतः/भवत्याः पाठः",
"flow-ve-mention-inspector-remove-label": "निष्कास्यताम्",
- "flow-ve-mention-placeholder": "प्रयोक्तृनाम"
+ "flow-ve-mention-placeholder": "सदस्यनाम"
}
diff --git a/Flow/i18n/sc.json b/Flow/i18n/sc.json
index 5c719851..d1797b84 100644
--- a/Flow/i18n/sc.json
+++ b/Flow/i18n/sc.json
@@ -3,7 +3,5 @@
"authors": [
"Taxandru"
]
- },
- "flow-edited-ago-minute": "Cambiadu $1 {{PLURAL:$1|minutu|minutos}} a como",
- "flow-time-ago-minute": "$1 {{PLURAL:$1|minutu|minutos}} a como"
+ }
}
diff --git a/Flow/i18n/scn.json b/Flow/i18n/scn.json
index eefca329..9afb26ea 100644
--- a/Flow/i18n/scn.json
+++ b/Flow/i18n/scn.json
@@ -6,5 +6,6 @@
"Sarvaturi"
]
},
- "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|ringrazzia}}}}"
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|ringrazzia}}}}",
+ "structureddiscussions": "Flussu"
}
diff --git a/Flow/i18n/sd.json b/Flow/i18n/sd.json
index 47ce06b4..a92c9477 100644
--- a/Flow/i18n/sd.json
+++ b/Flow/i18n/sd.json
@@ -2,10 +2,15 @@
"@metadata": {
"authors": [
"Sindhu",
- "Mehtab ahmed"
+ "Mehtab ahmed",
+ "Aursani",
+ "Indus Asia"
]
},
- "flow-topic-action-watchlist-add": "هيءَ ٽاپڪ پنهنجي واچ اڪثر ڏسجندڙ لسٽ ۾ جوڙيو",
- "flow-topic-action-watchlist-remove": "پنهنجي واچ لسٽ تان هيءَ ٽاپڪ ڊليٽ ڪريو",
- "flow-notification-enabled-on-talkpage-email-subject-message": "$2 تي نئون بحص جو نظام"
+ "flow-topic-collapse-siderail": "پوري ويڪر تي پڙھو",
+ "flow-topic-expand-siderail": "مقرر ڪيل ويڪر تي پڙھو",
+ "flow-last-modified-by": "$1 پاران آخري ڀيرو {{GENDER:$1|سنواريل}}",
+ "flow-topic-action-watchlist-add": "هن موضوع کي سبسڪرائب ڪريو",
+ "flow-topic-action-watchlist-remove": "اڻ سبسڪرائب ڪريو",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "$2 تي نئون مباحثي سرشتو"
}
diff --git a/Flow/i18n/sh.json b/Flow/i18n/sh.json
new file mode 100644
index 00000000..7b5a7c48
--- /dev/null
+++ b/Flow/i18n/sh.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Conquistador"
+ ]
+ },
+ "flow-cancel": "Otkaži",
+ "flow-topic-action-watchlist": "Lista praćenja"
+}
diff --git a/Flow/i18n/si.json b/Flow/i18n/si.json
index 95e15780..4b4a3249 100644
--- a/Flow/i18n/si.json
+++ b/Flow/i18n/si.json
@@ -4,7 +4,8 @@
"Sahan.ssw",
"Thirsty",
"Sandaru",
- "Susith Chandira Gts"
+ "Susith Chandira Gts",
+ "SusithCM"
]
},
"flow-board-header-browse-topics-link": "ගවේෂණ මාතෘකා",
@@ -14,5 +15,8 @@
"flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\"ක්ලික් කිරීමෙන්, මෙම විකිය භාවිතාකිරීමට ඇති නීතිවලට ඔබ එකඟ වේ.",
"flow-terms-of-use-reply": "\"{{int:flow-reply-link}}\"click කිරීමෙන්, මෙම විකිය භාවිතාකිරීමට ඇති නීතිවලට ඔබ එකඟ වේ.",
"flow-terms-of-use-edit": "ඔබගේ වෙනස්කම් සුරැකීමෙන්,ඔබ විකිය භාවිතා කිරීමට ඇති කොන්දේසි වලට එකඟ වේ.",
- "flow-special-enableflow-invalid-title": "වැරදි පිටු ශීර්ෂයක් ලබා දෙන ලදී"
+ "flow-special-enableflow-invalid-title": "වැරදි පිටු ශීර්ෂයක් ලබා දෙන ලදී",
+ "flow-ve-mention-placeholder": "පරිශීලක නාමය",
+ "flow-notification-link-text-enabled-on-talkpage": "පරිශීලක සාකච්ඡා පිටුව {{GENDER:|පෙන්වන්න}}",
+ "flow-notification-enabled-on-talkpage-title": "{{GENDER:$1| ඔබගේ}} සාකච්ඡා පිටුව සදහා නව සාකච්ඡා පද්ධතියක් සක්‍රීය කර ඇත<br /><small>[[$2]] හි ඇත</small>"
}
diff --git a/Flow/i18n/sk.json b/Flow/i18n/sk.json
new file mode 100644
index 00000000..86eb889b
--- /dev/null
+++ b/Flow/i18n/sk.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Teslaton"
+ ]
+ },
+ "echo-category-title-flow-discussion": "diskusiu vo Flow",
+ "echo-pref-tooltip-flow-discussion": "Upozornite ma na aktivitu vo Flow vláknach a diskusných stránkách, ktoré sledujem."
+}
diff --git a/Flow/i18n/skr-arab.json b/Flow/i18n/skr-arab.json
new file mode 100644
index 00000000..0cdde54d
--- /dev/null
+++ b/Flow/i18n/skr-arab.json
@@ -0,0 +1,155 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saraiki"
+ ]
+ },
+ "flow-desc": "بحث دا نظام",
+ "flow-board-header-browse-topics-link": "عنوان ݙیکھو",
+ "flow-board-description-can-not-edit": "نافابل تبدیل",
+ "flow-board-collapse-description": "وضاحت لکاؤ",
+ "flow-board-expand-description": "وضاحت ݙکھاؤ",
+ "flow-edit-header-link": "وضاحت وچ تبدیلی کرو",
+ "flow-topic-moderated-reason-prefix": "سبب:",
+ "flow-post-actions": "کم",
+ "flow-topic-actions": "کم",
+ "flow-cancel": "منسوخ",
+ "flow-skip-summary": "چھوڑو",
+ "flow-summary-authored": "خلاصہ $1 کنوں",
+ "flow-show-change": "تبدیلیاں ݙکھاؤ",
+ "flow-newtopic-title-placeholder": "نواں عنوان",
+ "flow-newtopic-header": "نواں عنوان شروع کرو",
+ "flow-newtopic-save": "عنوان شروع کرو",
+ "flow-newtopic-start-placeholder": "نواں عنوان شروع کرو",
+ "flow-newtopic-first-heading": "$1 تے نواں عنواں شروع کرو",
+ "flow-summarize-topic-placeholder": "بحث دا خلاصہ لکھو",
+ "flow-reply-topic-title-placeholder": "$1 کوں جواب ݙیوو",
+ "flow-reply-link": "{{GENDER:$1|جواب ݙیوو}}",
+ "flow-history-action-suppress-post": "دباؤ",
+ "flow-history-action-delete-post": "مٹاؤ",
+ "flow-history-action-hide-post": "لُکاؤ",
+ "flow-history-action-unsuppress-post": "دباؤ ہٹاؤ",
+ "flow-history-action-undelete-post": "بحال",
+ "flow-history-action-unhide-post": "ݙکھاؤ",
+ "flow-history-action-restore-post": "بحال",
+ "flow-history-action-lock-topic": "برطرف کرو",
+ "flow-history-action-unlock-topic": "ولدا کھولو",
+ "flow-post-action-view": "مستقل ربط",
+ "flow-post-action-post-history": "تاریخچہ",
+ "flow-post-action-suppress-post": "دباؤ",
+ "flow-post-action-delete-post": "مٹاؤ",
+ "flow-post-action-hide-post": "لُکاؤ",
+ "flow-post-action-edit-post": "لکھو",
+ "flow-post-action-edit-post-submit": "تبدیلیاں محفوظ کرو",
+ "flow-post-action-unsuppress-post": "دباؤ ہٹاؤ",
+ "flow-post-action-undelete-post": "بحال",
+ "flow-post-action-unhide-post": "ݙکھاؤ",
+ "flow-post-action-restore-post": "بحال",
+ "flow-post-action-undo-moderation": "واپس",
+ "flow-topic-action-view": "مستقل ربط",
+ "flow-topic-action-watchlist": "نظریں ہیٹھ فہرست",
+ "flow-topic-action-edit-title": "عنوان تبدیل کرو",
+ "flow-topic-action-history": "تاریخچہ",
+ "flow-topic-action-hide-topic": "موضوع لکاؤ",
+ "flow-topic-action-delete-topic": "عنوان مٹاؤ",
+ "flow-topic-action-unlock-topic": "موضوع ولدا کھولو",
+ "flow-topic-action-summarize-topic": "خلاصہ کرو",
+ "flow-topic-action-update-topic-summary": "خلاصہ تازہ کرو",
+ "flow-topic-action-suppress-topic": "موضوع دباؤ",
+ "flow-topic-action-unhide-topic": "موضوع ݙکھاؤ",
+ "flow-topic-action-undelete-topic": "موضوع بحال کرو",
+ "flow-topic-action-unsuppress-topic": "موضوع توں دباؤ ہٹاؤ",
+ "flow-topic-action-restore-topic": "موضوع بحال کرو",
+ "flow-topic-action-undo-moderation": "واپس",
+ "flow-error-missing-summary": "تہاکوں خلاصہ لکھݨاں پوسی۔",
+ "flow-error-protected-unknown-reason": "اݨ سونہاں",
+ "flow-error-not-allowed-hide": "ایہ موضوع لکا ہویا ہے۔",
+ "flow-error-not-allowed-delete": "ایہ عنوان مٹ ڳئے",
+ "flow-error-not-allowed-reply-to-delete-topic": "تساں ایں عنوان دا جواب نہوے ݙے سڳدے کیوں جو ایہ مٹ ڳئے۔",
+ "flow-error-not-allowed-suppress": "ایہ عنوان مٹ ڳئے",
+ "flow-error-not-allowed-reply-to-suppress-topic": "تساں ایں عنوان دا جواب نہوے ݙے سڳدے کیوں جو ایہ مٹ ڳئے۔",
+ "flow-error-unknown-workflow-id-title": "نامعلوم موضوع",
+ "flow-edit-header-submit": "تفصیل محفوظ کرو",
+ "flow-edit-title-submit": "عنوان تبدیل کرو",
+ "flow-edit-post-submit": "تبدیلیاں روانہ کرو",
+ "flow-rev-message-restore-topic-reason": "ولدا کھل ڳیا",
+ "flow-rc-topic-of-board": "$1 $2 تے",
+ "flow-board-history": "\"$1\" تاریخچہ",
+ "flow-board-history-empty": "ہݨ ایں بورڈ تے تاریخ کائنی۔",
+ "flow-topic-history": "\"$1\" تاریچہ موضوع",
+ "flow-history-last4": "آخری 4 گھنٹے",
+ "flow-history-day": "اڄ",
+ "flow-history-week": "پچھلا ہفتہ",
+ "flow-comment-deleted": "مٹائی ہوئی رائے",
+ "flow-comment-hidden": "لکے ہوئے تبصرے",
+ "flow-notification-link-text-view-post": "پوسٹ ݙیکھو",
+ "flow-notification-link-text-view-topic": "موضوع ݙیکھو",
+ "flow-notification-link-text-view-topics": "موضوع ݙیکھو",
+ "flow-notification-reply-email-subject": "$2 $3 اتے",
+ "flow-link-post": "پوسٹ",
+ "flow-link-topic": "موضوع",
+ "flow-link-history": "تاریخچہ",
+ "flow-link-post-revision": "پوسٹ دی دہرائی",
+ "flow-link-topic-revision": "موضوع دی نظرثانی",
+ "flow-link-header-revision": "وضاحت نظرثانی",
+ "flow-link-summary-revision": "خلاصہ نظرثانی",
+ "flow-moderation-title-suppress-post": "پوسٹ دباؤں؟",
+ "flow-moderation-title-delete-post": "پوسٹ مٹاؤں؟",
+ "flow-moderation-title-hide-post": "پوسٹ لکاؤں",
+ "flow-moderation-title-unsuppress-post": "پوسٹ دباؤ ہٹاؤں؟",
+ "flow-moderation-title-undelete-post": "پوسٹ بحال کرو؟",
+ "flow-moderation-title-unhide-post": "پوسٹ ݙکھاؤ؟",
+ "flow-moderation-confirm-suppress-post": "دباؤ",
+ "flow-moderation-confirm-delete-post": "مٹاؤ",
+ "flow-moderation-confirm-hide-post": "لُکاؤ",
+ "flow-moderation-confirm-unsuppress-post": "دباؤ ہٹاؤ",
+ "flow-moderation-confirm-undelete-post": "بحال",
+ "flow-moderation-confirm-unhide-post": "ݙکھاؤ",
+ "flow-moderation-confirm-suppress-topic": "دباؤ",
+ "flow-moderation-confirm-delete-topic": "مٹاؤ",
+ "flow-moderation-confirm-hide-topic": "لُکاؤ",
+ "flow-moderation-confirm-unsuppress-topic": "دباؤ ہٹاؤ",
+ "flow-moderation-confirm-undelete-topic": "بحال",
+ "flow-moderation-confirm-unhide-topic": "ݙکھاؤ",
+ "flow-moderation-confirmation-delete-topic": "ایہ عنوان مٹ ڳئے",
+ "flow-moderation-confirmation-hide-topic": "ایہ موضوع لکا ہویا ہے۔",
+ "flow-moderation-title-suppress-topic": "موضوع دباؤ؟",
+ "flow-moderation-title-delete-topic": "عنوان مٹاؤ؟",
+ "flow-moderation-title-hide-topic": "موضوع لکاؤ؟",
+ "flow-moderation-title-unsuppress-topic": "موضوع توں دباؤ ہٹاؤ؟",
+ "flow-moderation-title-undelete-topic": "موضوع بحال کرو؟",
+ "flow-moderation-title-unhide-topic": "موضوع ݙکھاؤ؟",
+ "flow-topic-first-heading": "$1 تے موضوع",
+ "flow-topic-html-title": "$1 $2 تے",
+ "flow-topic-count": "موضوعات ($1)",
+ "flow-load-more": "ٻئے لوݙ کرو",
+ "flow-newest-topics": "تازہ ترین موضوعات",
+ "structureddiscussions": "فلو",
+ "flow-special-type": "قسم",
+ "flow-special-type-post": "پوسٹ",
+ "flow-special-type-workflow": "کم دی چال",
+ "flow-special-uuid": "یو یو آئی ڈی",
+ "flow-post-undo-hide": "ݙکھاؤ",
+ "flow-post-undo-delete": "بحال",
+ "flow-post-undo-suppress": "دباؤ ہٹاؤ",
+ "flow-topic-undo-hide": "ݙکھاؤ",
+ "flow-topic-undo-delete": "بحال",
+ "flow-topic-undo-suppress": "دباؤ ہٹاؤ",
+ "flow-edited": "ترمیم شدہ",
+ "flow-edited-by": "ترمیم شدہ از $1",
+ "flow-undo": "واپس",
+ "flow-undo-latest-revision": "موجودہ حالت",
+ "flow-undo-your-text": "تہاݙی لکھائی",
+ "flow-undo-edit-header": "وضاحت تبدیل کرݨ",
+ "flow-undo-edit-topic-summary": "موضوئ دے خلاصے وچ تبدیلی کرݨ",
+ "flow-undo-edit-post": "پوسٹ تبدیل کرݨ",
+ "group-flow-bot": "بݨی بݨائی بحثاں دا بوٹ",
+ "group-flow-bot-member": "بݨی بݨائی بحثاں دا بوٹ",
+ "flow-ve-mention-context-item-label": "ذکر کرݨ",
+ "flow-ve-mention-inspector-title": "ذکر کرݨ",
+ "flow-ve-mention-inspector-remove-label": "ہٹاؤ",
+ "flow-ve-mention-placeholder": "ورتݨ آلا ناں",
+ "flow-ve-mention-tool-title": "ورتݨ آلے دا ذکر کرو",
+ "flow-dialog-cancelconfirm-keep": "لکھݨ جاری رکھو",
+ "flow-dialog-cancelconfirm-discard": "تبدیلیاں مسترد کرو"
+}
diff --git a/Flow/i18n/sl.json b/Flow/i18n/sl.json
index b60fc43d..49fb802f 100644
--- a/Flow/i18n/sl.json
+++ b/Flow/i18n/sl.json
@@ -3,29 +3,35 @@
"authors": [
"Dbc334",
"Eleassar",
- "Yerpo"
+ "Yerpo",
+ "Janezdrilc"
]
},
"flow-error-missing-replyto": "Podan ni bil noben parameter »odgovori na«. Ta parameter je za dejanje »odgovorite« obvezen.",
- "flow-error-invalid-replyto": "Parameter »odgovori« je bil neveljaven. Navedene objave ni bilo mogoče najti.",
"flow-error-missing-postId": "Podan ni bil noben parameter »postId«. Ta parameter je za upravljanje z objavo obvezen.",
"flow-error-invalid-postId": "Parameter »postId« ni veljaven. Navedene objave ($1) ni bilo mogoče najti.",
"flow-error-search": "Zaradi začasne težave nam ni uspelo izvesti vašega iskanja. Prosimo, poskusite kasneje.",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 se je {{GENDER:$1|odzval|odzvala|odzval(-a)}} na <span class=\"plainlinks\">[$5 $2]</span> na strani '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 in $5 {{PLURAL:$6|drug|druga|drugi|drugih}} so se odzvali na <span class=\"plainlinks\">[$4 $2]</span> na strani '''$3'''.",
- "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 je {{GENDER:$1|urejal|urejala}} vašo <span class=\"plainlinks\">[$5 objavo]</span> v razdelku »$2« na [[$3|$4]].",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|je ustvaril|je ustvarila}} novo temo na '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 se je {{GENDER:$1|odzval|odzvala}} na <span class=\"plainlinks\">[$5 $2]</span> na strani <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 in {{PLURAL:$5|en drug se je odzval|dva druga sta se odzvala|$5 drugi so se odzvali|$5 drugih se je odzvalo|100=99+ drugih se je odzvalo}} na <span class=\"plainlinks\">[$4 $2]</span> na strani <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 je {{GENDER:$1|urejal|urejala}} tvojo <span class=\"plainlinks\">[$5 objavo]</span> v razdelku »$2« na [[$3|$4]].",
+ "notification-header-flow-post-edited-user-talk": "Na <strong>{{GENDER:$2|vaši pogovorni strani}}</strong> je bila urejana objava v »<strong>$1</strong>«.",
+ "notification-header-flow-summary-edited-user-talk": "Na <strong>{{GENDER:$2|vaši pogovorni strani}}</strong> je bil posodobljen povzetek »<strong>$1</strong>«.",
+ "notification-header-flow-summary-edited-first-user-talk": "Na <strong>{{GENDER:$2|vaši pogovorni strani}}</strong> je bila povzeta tema »<strong>$1</strong>«.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|je ustvaril|je ustvarila}} novo temo na <strong>$3</strong>.",
"flow-notification-rename": "$1 {{GENDER:$1|je spremenil|je spremenila}} naslov <span class=\"plainlinks\">[$2 $3]</span> v »$4« na [[$5|$6]].",
"flow-notification-link-text-view-post": "Ogled objave",
"flow-notification-reply-email-subject": "$2 na $3",
- "flow-notification-reply-email-batch-body": "$1 se je {{GENDER:$1|odzval|odzvala|odzval(-a)}} na »$2« na strani $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 in $4 {{PLURAL:$5|drugi|druga|drugi|drugih}} {{PLURAL:$5|sta se {{GENDER:$1|odzvala}}|so se odzvali}} na »$2« na strani $3",
- "echo-category-title-flow-discussion": "Tok",
- "echo-pref-tooltip-flow-discussion": "Obvesti me, ko se v Toku pojavijo dejanja v zvezi z mano.",
+ "flow-notification-reply-email-batch-body": "$1 se je {{GENDER:$1|odzval|odzvala}} na »$2« na strani $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 in {{PLURAL:$4|en drug|dva druga|$4 drugi|$4 drugih|100=99+ drugih}} {{PLURAL:$4|sta se {{GENDER:$1|odzvala}}|so se odzvali|so se odzvali|se je odzvalo}} na »$2« na strani $3",
+ "flow-notification-mention-email-subject": "$1 {{GENDER:$3|te}} je {{GENDER:$1|omenil|omenila}} na $2",
+ "echo-category-title-flow-discussion": "Strukturirana razprava",
+ "echo-pref-tooltip-flow-discussion": "Obvesti me o dejavnostih v temah ali na straneh, ki jim sledim.",
"flow-link-post": "objava",
"flow-link-topic": "tema",
"flow-link-history": "zgodovina",
"flow-moderation-title-suppress-post": "Cenzoriraj objavo",
"flow-moderation-title-delete-post": "Izbriši objavo",
- "flow-moderation-title-hide-post": "Skrij objavo"
+ "flow-moderation-title-hide-post": "Skrij objavo",
+ "group-flow-bot": "Boti Strukturiranih razprav",
+ "group-flow-bot-member": "Bot Strukturiranih razprav"
}
diff --git a/Flow/i18n/so.json b/Flow/i18n/so.json
new file mode 100644
index 00000000..03e5bee2
--- /dev/null
+++ b/Flow/i18n/so.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Abshirdheere"
+ ]
+ },
+ "flow-wikitext-switch-editor-tooltip": "U gudub wax bedeleha muuqada"
+}
diff --git a/Flow/i18n/sq.json b/Flow/i18n/sq.json
index d55ab7ce..8ad830c3 100644
--- a/Flow/i18n/sq.json
+++ b/Flow/i18n/sq.json
@@ -7,5 +7,5 @@
},
"flow-topic-moderated-reason-prefix": "Arsyeja:",
"flow-error-no-commit": "veprimi specifik nuk mund te ruhet",
- "flow-spam-confirmedit-form": "Ju lutem konfirmoni se ju jeni njeri duke zgjidhur në captcha më poshtë: <span class=\"notranslate\" translate=\"asnjë\">$1</span>"
+ "flow-spam-confirmedit-form": "Ju lutem konfirmoni se ju jeni njeri duke zgjidhur në captcha më poshtë: $1"
}
diff --git a/Flow/i18n/sr-ec.json b/Flow/i18n/sr-ec.json
index d96be56c..554c5b72 100644
--- a/Flow/i18n/sr-ec.json
+++ b/Flow/i18n/sr-ec.json
@@ -2,10 +2,18 @@
"@metadata": {
"authors": [
"Milicevic01",
- "Rancher"
+ "Rancher",
+ "Macofe",
+ "Сербијана",
+ "Zoranzoki21",
+ "Obsuser"
]
},
- "enableflow": "Омогући Flow",
+ "enablestructureddiscussions": "Омогући Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "ID странице Форума за дискусију",
+ "abusefilter-edit-builder-vars-board-namespace": "Именски простор Форума за дискусију",
+ "abusefilter-edit-builder-vars-board-text": "Назив Форума за дискусију",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Пуни назив Форума за дискусију",
"flow-board-header-browse-topics-link": "Списак тема",
"flow-board-header": "О овој дискусији",
"flow-board-collapse-description": "Сакриј опис",
@@ -14,6 +22,7 @@
"flow-topic-moderated-reason-prefix": "Разлог:",
"flow-hide-post-content": "Овај коментар је {{GENDER:$1|сакрио|сакрила}} $1 ([$2 историја])",
"flow-hide-title-content": "Ову тему је {{GENDER:$1|сакрио|сакрила}} $1",
+ "flow-hide-header-content": "{{GENDER:$1|Сакрио|Сакрила}} $2",
"flow-delete-post-content": "$1 је {{GENDER:$1|обрисао|обрисала}} овај коментар ([$2 историја])",
"flow-delete-title-content": "$1 је {{GENDER:$1|обрисао|обрисала}} ову тему",
"flow-delete-header-content": "{{GENDER:$1|Обрисао|Обрисала}} $2",
@@ -28,6 +37,7 @@
"flow-newtopic-content-placeholder": "Напишите нову поруку на „$1“",
"flow-newtopic-save": "Додај тему",
"flow-newtopic-start-placeholder": "Направи нову тему",
+ "flow-reply-topic-title-placeholder": "Одговори на „$1“",
"flow-reply-link": "{{GENDER:$1|Одговори}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Захвали}}}} се",
"flow-history-action-delete-post": "обриши",
@@ -48,44 +58,79 @@
"flow-topic-action-delete-topic": "Обриши тему",
"flow-topic-action-lock-topic": "Означи као решено",
"flow-topic-action-unlock-topic": "Поново отвори тему",
+ "flow-topic-action-summarize-topic": "Сумирај",
+ "flow-topic-action-undo-moderation": "Опозови",
"flow-topic-notification-subscribe-title": "Ова тема је додата на {{GENDER:$1|Ваш}} списак надгледања.",
"flow-error-not-allowed-delete": "Ова тема је обрисана.",
"flow-error-not-allowed-suppress": "Ова тема је обрисана.",
"flow-error-no-commit": "Наведену радњу није могуће сачувати.",
+ "flow-error-invalid-topic-uuid-title": "Неисправан наслов",
+ "flow-error-invalid-topic-uuid": "Наведени наслов није ваљан. Странице у именском простору Тема аутоматски прави Flow.",
+ "flow-error-unknown-workflow-id-title": "Непозната тема",
+ "flow-error-unknown-workflow-id": "Тражена тема не постоји.",
"flow-edit-header-submit": "Сачувај опис",
"flow-edit-post-submit": "Сачувај",
+ "flow-edit-post-submit-anonymously": "Сачувај измене анонимно",
+ "flow-rev-message-edit-post": "$1 је {{GENDER:$2|уредио|уредила}} [$3 коментар] на „$4“.",
+ "flow-rev-message-reply": "$1 је {{GENDER:$2|оставио|оставила}} [$3 коментар] на „$4“ (<em>$5</em>)",
"flow-rev-message-new-post": "$1 је {{GENDER:$2|направио|направила}} тему „[$3 $4]“",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Направљена}} нова тема",
+ "flow-rev-message-edit-title": "$1 је {{GENDER:$2|променио|променила}} наслов теме „$5“ у „[$3 $4]“",
"flow-rev-message-create-header": "$1 је {{GENDER:$2|направио|направила}} опис",
- "flow-rev-message-edit-header": "$1 је {{GENDER:$2|изменио|изменила}} опис",
+ "flow-rev-message-edit-header": "$1 је {{GENDER:$2|уредио|уредила}} опис",
+ "flow-rev-message-create-topic-summary": "$1 је {{GENDER:$2|сумирао|сумирала}} тему $3",
+ "flow-rev-message-deleted-topic": "$1 је {{GENDER:$2|обрисао|обрисала}} [$4 тему] „$6“ (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 је {{GENDER:$2|означио|означила}} [$4 тему] „$6“ решеном (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 је поново {{GENDER:$2|отворио|отворила}} [$4 тему] „$6“ (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 на $2",
"flow-history-last4": "Претходна 4 сата",
"flow-history-day": "Данас",
"flow-history-week": "Прошле недеље",
"flow-topic-comments": "{{PLURAL:$1|$1 коментар|$1 коментара|0={{GENDER:$2|Први|Прва}} прокоментариши!}}",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 је {{GENDER:$1|оставио|оставила}} коментар на '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и још $5 {{PLURAL:$6|корисник|корисника}} су {{GENDER:$1|оставили}} коментаре на '''$3'''.",
- "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 је {{GENDER:$1|изменио|изменила}} Ваш <span class=\"plainlinks\">[$5 коментар]</span> на [[$3|$4]].",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 је {{GENDER:$1|направио|направила}} нову тему на '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 нова тема|$1 нове теме|$1 нових тема|250=Преко 250 нових тема}} на '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-show-comments-title": "{{PLURAL:$1|Погледај коментаре}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Сакриј коментаре}}",
+ "flow-comment-deleted": "Обрисани коментар",
+ "flow-comment-hidden": "Сакривени коментар",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 је {{GENDER:$1|оставио|оставила}} коментар на <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 и још {{PLURAL:$5|један корисник|$5 корисника|100=99+ корисника}} су {{GENDER:$1|оставили}} коментаре на <strong>$3</strong>.",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 је {{GENDER:$1|уредио|уредила}} Ваш <span class=\"plainlinks\">[$5 коментар]</span> на [[$3|$4]].",
+ "notification-header-flow-mention-post": "$1 Вас је {{GENDER:$2|поменуо|поменула}} {{GENDER:$4|у}} „<strong>$5</strong>“.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 је {{GENDER:$1|направио|направила}} нову тему на <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Једна нова тема|$1 нове теме|$1 нових тема|100=99+ нових тема}} на <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "echo-category-title-flow-discussion": "Flow дискусије",
+ "echo-pref-tooltip-flow-discussion": "Обавештава вас о активностима у темама или на страницама које пратите.",
"flow-link-topic": "тема",
"flow-link-history": "историја",
"flow-moderation-confirm-delete-topic": "Обриши",
"flow-moderation-confirm-hide-topic": "Сакриј",
"flow-moderation-confirm-undelete-topic": "Врати",
"flow-moderation-confirm-unhide-topic": "Откриј",
+ "flow-moderation-confirmation-delete-topic": "Ова тема је обрисана.",
+ "flow-moderation-confirmation-hide-topic": "Ова тема је сакривена.",
+ "right-flow-create-board": "прављење Flow табли било где",
+ "right-flow-hide": "скривање тема и коментара у Flow-у",
+ "right-flow-lock": "означавање тема решеним у Flow-у",
+ "right-flow-edit-post": "уређивање туђих коментара у Flow-у",
"flow-terms-of-use-new-topic": "Кликом на „{{int:flow-newtopic-save}}“, прихватате услове коришћења на овом викију.",
"flow-terms-of-use-reply": "Кликом на „{{int:flow-reply-link}}“, прихватате услове коришћења на овом викију.",
"flow-terms-of-use-edit": "Чувањем измена, прихватате услове коришћења на овом викију.",
"flow-cancel-warning": "Унели сте текст у овај оквир. Да ли сигурно желите да га одбаците?",
"flow-load-more": "Учитај још",
+ "flow-no-more-fwd": "Нема старих тема",
"flow-newest-topics": "Најновије теме",
"flow-recent-topics": "Недавно активне теме",
+ "flow-terms-of-use-summarize": "Кликом на „{{int:flow-topic-action-update-topic-summary}}“, прихватате услове коришћења овог викија.",
+ "flow-terms-of-use-lock-topic": "Кликом на „{{int:flow-topic-action-lock-topic}}“, прихватате услове коришћења овог викија.",
+ "flow-terms-of-use-unlock-topic": "Кликом на „{{int:flow-topic-action-unlock-topic}}“, прихватате услове коришћења овог викија.",
+ "flow-special-type": "Тип",
"flow-previous-diff": "← Старија измена",
"flow-next-diff": "Новија измена →",
"flow-ve-mention-placeholder": "Корисничко име",
"flow-ve-mention-tool-title": "Спомени корисника",
"flow-wikitext-switch-editor-tooltip": "Пребаци ме на Визуелни уређивач",
"flow-ve-switch-editor-tool-title": "Пребаци ме на уређивач викитекста",
- "flow-dialog-cancelconfirm-title": "Јесте ли сигурни?"
+ "flow-dialog-cancelconfirm-title": "Јесте ли сигурни?",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Добро дошли}} на {{GENDER:$1|Вашу}} нову страницу за разговор",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Ваша}} страница за разговор је место где вас други уредници контактирају. Са Flow-ом, једноставније је направити нову тему и пратити дискусију.",
+ "flow-guidedtour-optin-feedback": "Дајте нам {{GENDER:$1|Ваше}} мишљење!"
}
diff --git a/Flow/i18n/sr-el.json b/Flow/i18n/sr-el.json
index efe707b3..c7a400a3 100644
--- a/Flow/i18n/sr-el.json
+++ b/Flow/i18n/sr-el.json
@@ -1,9 +1,12 @@
{
"@metadata": {
"authors": [
- "Milicevic01"
+ "Milicevic01",
+ "Macofe",
+ "Obsuser"
]
},
+ "enablestructureddiscussions": "Omogući Flow",
"flow-board-header-browse-topics-link": "Spisak tema",
"flow-board-header": "O ovoj diskusiji",
"flow-board-collapse-description": "Sakrij opis",
@@ -11,12 +14,16 @@
"flow-topic-moderated-reason-prefix": "Razlog:",
"flow-hide-post-content": "Ovaj komentar je {{GENDER:$1|sakrio|sakrila}} $1",
"flow-hide-title-content": "Ovu temu je {{GENDER:$1|sakrio|sakrila}} $1",
+ "flow-hide-header-content": "{{GENDER:$1|Sakrio|Sakrila}} $2",
"flow-delete-post-content": "Ovaj komentar je {{GENDER:$1|obrisao|obrisala}} $1",
"flow-delete-title-content": "$1 je {{GENDER:$1|obrisao|obrisala}} ovu temu",
"flow-delete-header-content": "{{GENDER:$1|Obrisao|Obrisala}} $2",
+ "flow-edit-summary-placeholder": "Kratko opišite ishod diskusije",
+ "flow-summary-authored": "Opis {{GENDER:$1|napisao|napisala}} $1",
"flow-show-change": "Prikaži izmene",
"flow-newtopic-content-placeholder": "Napišite novu poruku na „$1“",
"flow-newtopic-start-placeholder": "Napravi novu temu",
+ "flow-reply-topic-title-placeholder": "Odgovori na „$1“",
"flow-reply-link": "{{GENDER:$1|Odgovori}}",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Zahvali se}}}}",
"flow-history-action-delete-post": "obriši",
@@ -31,37 +38,72 @@
"flow-topic-action-delete-topic": "Obriši temu",
"flow-topic-action-lock-topic": "Označi kao rešeno",
"flow-topic-action-unlock-topic": "Ponovo otvori temu",
+ "flow-topic-action-summarize-topic": "Sumiraj",
+ "flow-topic-action-undo-moderation": "Opozovi",
"flow-topic-notification-subscribe-title": "Ova tema je dodata na {{GENDER:$1|Vaš}} spisak nadgledanja.",
"flow-error-not-allowed-delete": "Ova tema je obrisana.",
"flow-error-not-allowed-suppress": "Ova tema je obrisana.",
"flow-error-no-commit": "Navedenu radnju nije moguće sačuvati.",
+ "flow-error-invalid-topic-uuid-title": "Neispravan naslov",
+ "flow-error-invalid-topic-uuid": "Navedeni naslov nije valjan. Stranice u imenskom prostoru Tema automatski pravi Flow.",
+ "flow-error-unknown-workflow-id-title": "Nepoznata tema",
"flow-edit-header-submit": "Sačuvaj opis",
+ "flow-edit-post-submit-anonymously": "Sačuvaj izmene anonimno",
+ "flow-rev-message-edit-post": "$1 je {{GENDER:$2|uredio|uredila}} [$3 komentar] na „$4“.",
+ "flow-rev-message-reply": "$1 je {{GENDER:$2|ostavio|ostavila}} [$3 komentar] na „$4“ (<em>$5</em>)",
"flow-rev-message-new-post": "$1 je {{GENDER:$2|napravio|napravila}} temu „[$3 $4]“",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|Napravljena}} nova tema",
+ "flow-rev-message-edit-title": "$1 je {{GENDER:$2|promenio|promenila}} naslov teme „$5“ u „[$3 $4]“",
"flow-rev-message-create-header": "$1 je {{GENDER:$2|napravio|napravila}} opis",
- "flow-rev-message-edit-header": "$1 je {{GENDER:$2|izmenio|izmenila}} opis",
+ "flow-rev-message-edit-header": "$1 je {{GENDER:$2|uredio|uredila}} opis",
+ "flow-rev-message-create-topic-summary": "$1 je {{GENDER:$2|sumirao|sumirala}} temu $3",
+ "flow-rev-message-deleted-topic": "$1 je {{GENDER:$2|obrisao|obrisala}} [$4 temu] „$6“ (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 je {{GENDER:$2|označio|označila}} [$4 temu] „$6“ rešenom (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 je ponovo {{GENDER:$2|otvorio|otvorila}} [$4 temu] „$6“ (<em>$5</em>)",
"flow-rc-topic-of-board": "$1 na $2",
"flow-history-last4": "Prethodna 4 sata",
"flow-history-week": "Prošle nedelje",
"flow-topic-comments": "{{PLURAL:$1|$1 komentar|$1 komentara|0={{GENDER:$2|Prvi|Prva}} prokomentariši!}}",
+ "flow-show-comments-title": "{{PLURAL:$1|Pogledaj komentare}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|Sakrij komentare}}",
+ "flow-comment-deleted": "Obrisani komentar",
+ "flow-comment-hidden": "Sakriveni komentar",
"flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 je {{GENDER:$1|ostavio|ostavila}} komentar na '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i još $5 {{PLURAL:$6|korisnik|korisnika}} su {{GENDER:$1|ostavili}} komentare na '''$3'''.",
- "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 je {{GENDER:$1|izmenio|izmenila}} Vaš <span class=\"plainlinks\">[$5 komentar]</span> na [[$3|$4]].",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 i još {{PLURAL:$5|jedan korisnik|$5 korisnika|100=99+ korisnika}} su {{GENDER:$1|ostavili}} komentare na '''$3",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 je {{GENDER:$1|uredio|uredila}} Vaš <span class=\"plainlinks\">[$5 komentar]</span> na [[$3|$4]].",
+ "notification-header-flow-mention-post": "$1 Vas je {{GENDER:$2|pomenuo|pomenula}} {{GENDER:$4|u}} „'''$5'''“.",
"flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 je {{GENDER:$1|napravio|napravila}} novu temu na '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nova tema|$1 nove teme|$1 novih tema|250=Preko 250 novih tema}} na '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Jedna nova tema|$1 nove teme|$1 novih tema|100=99+ novih tema}} na <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
+ "echo-category-title-flow-discussion": "Flow diskusije",
+ "echo-pref-tooltip-flow-discussion": "Obaveštava vas o aktivnostima u temama ili na stranicama koje pratite.",
"flow-link-history": "istorija",
"flow-moderation-confirm-delete-topic": "Obriši",
"flow-moderation-confirm-hide-topic": "Sakrij",
"flow-moderation-confirm-undelete-topic": "Vrati",
"flow-moderation-confirm-unhide-topic": "Otkrij",
+ "flow-moderation-confirmation-delete-topic": "Ova tema je obrisana.",
+ "flow-moderation-confirmation-hide-topic": "Ova tema je sakrivena.",
+ "right-flow-create-board": "pravljenje Flow tabli bilo gde",
+ "right-flow-hide": "skrivanje tema i komentara u Flow-u",
+ "right-flow-lock": "označavanje tema rešenim u Flow-u",
+ "right-flow-edit-post": "uređivanje tuđih komentara u Flow-u",
"flow-cancel-warning": "Uneli ste tekst u ovaj okvir. Da li sigurno želite da ga odbacite?",
"flow-load-more": "Učitaj još",
+ "flow-no-more-fwd": "Nema starih tema",
"flow-newest-topics": "Najnovije teme",
"flow-recent-topics": "Nedavno aktivne teme",
+ "flow-terms-of-use-summarize": "Klikom na „{{int:flow-topic-action-update-topic-summary}}“, prihvatate uslove korišćenja ovog vikija.",
+ "flow-terms-of-use-lock-topic": "Klikom na „{{int:flow-topic-action-lock-topic}}“, prihvatate uslove korišćenja ovog vikija.",
+ "flow-terms-of-use-unlock-topic": "Klikom na „{{int:flow-topic-action-unlock-topic}}“, prihvatate uslove korišćenja ovog vikija.",
+ "flow-special-type": "Tip",
"flow-previous-diff": "← Starija izmena",
"flow-next-diff": "Novija izmena →",
"flow-ve-mention-placeholder": "Korisničko ime",
"flow-ve-mention-tool-title": "Spomeni korisnika",
"flow-wikitext-switch-editor-tooltip": "Prebaci me na Vizuelni uređivač",
- "flow-ve-switch-editor-tool-title": "Prebaci me na uređivač vikiteksta"
+ "flow-ve-switch-editor-tool-title": "Prebaci me na uređivač vikiteksta",
+ "flow-dialog-cancelconfirm-title": "Jeste li sigurni?",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Dobro došli}} na {{GENDER:$1|Vašu}} novu stranicu za razgovor",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Vaša}} stranica za razgovor je mesto gde vas drugi urednici kontaktiraju. Sa Flow-om, jednostavnije je napraviti novu temu i pratiti diskusiju.",
+ "flow-guidedtour-optin-feedback": "Dajte nam {{GENDER:$1|Vaše}} mišljenje!"
}
diff --git a/Flow/i18n/su.json b/Flow/i18n/su.json
new file mode 100644
index 00000000..f9f87f71
--- /dev/null
+++ b/Flow/i18n/su.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Uchup19"
+ ]
+ },
+ "flow-topic-moderated-reason-prefix": "Alesan:",
+ "flow-cancel": "Bolay",
+ "flow-ve-mention-inspector-remove-label": "Pupus"
+}
diff --git a/Flow/i18n/sv.json b/Flow/i18n/sv.json
index f5b10965..8d9e5759 100644
--- a/Flow/i18n/sv.json
+++ b/Flow/i18n/sv.json
@@ -14,26 +14,54 @@
"Josve05a",
"Lejonel",
"Hangsna",
- "Macofe"
+ "Macofe",
+ "Nnemo",
+ "Rockyfelle"
]
},
- "enableflow": "Aktivera Flow",
- "flow-desc": "Arbetsflödeshanteringssystem",
- "log-name-flow": "Aktivitetslogg för Flow",
+ "enablestructureddiscussions": "Aktivera Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Sluta}} bevaka ny aktivitet på \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Du}} bevakar inte längre sidan \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Detta kommer inte att påverka de individuella ämnen {{GENDER:$3|du}} bevakar. Du kan bevaka [$2 denna sida] när som helst.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Sluta}} bevaka detta ämne",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Du}} bevakar inte längre \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Du}} kan bevaka [$2 detta ämne] när som helst.",
+ "flow-desc": "Diskussionssystem",
+ "flow-talk-taken-over-comment": "/* Denna sida har omvandlats till ett strukturerat diskussionsforum */",
+ "log-name-flow": "Aktivitetslogg för strukturerade diskussioner",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|raderade}} ett [$4 inlägg] i \"[[$3|$5]]\" på [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|raderade}} ett inlägg i ett ämne på [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|återställde}} ett [$4 inlägg] i \"[[$3|$5]]\" på [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|återställde}} ett inlägg i ett ämne på [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|censurerade}} ett [$4 inlägg] i \"[[$3|$5]]\" på [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|censurerade}} ett inlägg i ett ämne på [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|raderade}} ett [$4 inlägg] i \"[[$3|$5]]\" på [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|raderade}} ett inlägg i ett ämne på [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|raderade}} ämne \"[[$3|$5]]\" på [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|raderade}} ett ämne på [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|återställde}} ämne \"[[$3|$5]]\" på [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|återställde}} ett ämne på [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|censurerade}} ämne \"[[$3|$5]]\" på [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|censurerade}} ett ämne på [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|raderade}} ämne \"[[$3|$5]]\" på [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] på [[$3]] importerade från LiquidThreads till Flow",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|raderade}} ett ämne på [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|markerade}} ämnet \"[[$3|$5]]\" som löst på [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|markerade}} ett ämne som löst på [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|återställde}} ämnet \"[[$3|$5]]\" på [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|återöppnade}} ett ämne på [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] på [[$3]] importerade från LiquidThreads till strukturerade diskussioner",
+ "abusefilter-edit-builder-vars-board-articleid": "Sid-ID för strukturerade diskussionsforum",
+ "abusefilter-edit-builder-vars-board-namespace": "Namnrymd för strukturerade diskussionsforum",
+ "abusefilter-edit-builder-vars-board-text": "Titel för strukturerade diskussionsforum",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Full titel för strukturerade diskussionsforum",
"flow-user-moderated": "Modererad användare",
"flow-board-header-browse-topics-link": "Bläddra bland ämnen",
"flow-board-header": "Om denna diskussion",
+ "flow-board-description-can-not-edit": "Inte redigerbar",
"flow-board-collapse-description": "Dölj beskrivning",
"flow-board-expand-description": "Visa beskrivning",
+ "flow-topic-collapse-siderail": "Läs i full bredd",
+ "flow-topic-expand-siderail": "Läs med fast bredd",
"flow-edit-header-link": "Redigera beskrivning",
"flow-post-moderated-toggle-hide-show": "Visa kommentar {{GENDER:$1|dold}} av $2",
"flow-post-moderated-toggle-delete-show": "Visa kommentar {{GENDER:$1|raderad}} av $2",
@@ -55,13 +83,13 @@
"flow-post-actions": "Åtgärder",
"flow-topic-actions": "Åtgärder",
"flow-cancel": "Avbryt",
- "flow-skip-summary": "Skippa sammanfattning",
+ "flow-skip-summary": "Hoppa över",
"flow-edit-summary-placeholder": "Beskriv kortfattat resultatet av denna diskussion",
"flow-summary-authored": "Sammanfattning av $1",
"flow-summary-edited": "Sammanfattningen {{KÖN:$1|redigerades}} senast av $1",
"flow-show-change": "Visa ändringar",
"flow-last-modified-by": "Senast {{GENDER:$1|ändrad}} av $1",
- "flow-stub-post-content": "\"På grund av ett tekniskt fel, kunde detta inlägg inte hämtas.\"",
+ "flow-stub-post-content": "<em>På grund av ett tekniskt fel, kunde detta innehåll inte hämtas.</em>",
"flow-newtopic-title-placeholder": "Nytt ämne",
"flow-newtopic-content-placeholder": "Skicka ett nytt meddelande till \"$1\"",
"flow-newtopic-header": "Lägg till ett nytt ämne",
@@ -121,28 +149,29 @@
"flow-board-notification-subscribe-title": "{{GENDER:$1|Du}} prenumererar på detta diskussionsforum!",
"flow-board-notification-subscribe-description": "{{GENDER:$1|Du}} kommer att få ett meddelande när ett nytt ämne skapas på detta forum.",
"flow-topic-action-watchlist-add": "Bevaka det här ämnet",
- "flow-topic-action-watchlist-remove": "Obevaka",
- "flow-error-allowcreation-no-usedb": "allowCreation kräver att <var>$wgContentHandlerUseDB</var> är <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Sidan finns redan, men borde inte",
+ "flow-topic-action-watchlist-remove": "Avbevaka",
+ "flow-error-allowcreation-no-usedb": "<var>$wgContentHandlerUseDB</var> måste vara <code>true</code> för att aktivera strukturerade diskussioner på vissa ställen.",
+ "flow-error-allowcreation-already-exists": "Sidan finns redan på destinationen, så ett strukturerat diskussionsforum kan inte flyttas dit.",
"flow-error-allowcreation-flow-create-board": "Användaren har inte behörigheten \"{{int:right-flow-create-board}}\"",
+ "flow-error-can-not-edit-logged-out": "Du kan för tillfället inte delta. Du kan prova att logga in.",
+ "flow-error-can-not-edit-logged-in": "Du kan för tillfället inte delta, eftersom du inte har de nödvändiga rättigheterna.",
"flow-error-http": "Ett fel uppstod när servern kontaktades.",
- "flow-error-other": "Ett oväntat fel uppstod.",
- "flow-error-external": "Ett fel uppstod.<br />Felmeddelandet var: $1",
+ "flow-error-external": "Ett fel uppstod. Felmeddelandet var: $1",
"flow-error-topic-is-locked": "Detta ämne är löst, så ytterligare aktivitet är inte möjlig.",
"flow-error-lock-moderated-post": "Du kan inte markera ett modererat inlägg som löst.",
- "flow-error-external-multi": "Fel uppstod.<br />$1",
"flow-error-missing-content": "Inlägget har inget innehåll. Innehåll krävs för att spara ett inlägg.",
"flow-error-missing-summary": "Du måste skicka in en sammanfattning.",
"flow-error-missing-title": "Ämnet har ingen rubrik. En rubrik krävs för att spara ett ämne.",
- "flow-error-parsoid-failure": "Det gick inte att parsa innehållet på grund av ett Parsoid-fel.",
+ "flow-error-parsoid-failure": "Det gick inte att överföra innehållet: Ett fel uppstod när servern kontaktas för att konvertera mellan wikitext och HTML. Kontrollera din Internetanslutning eller försök igen senare om problemet kvarstår. Rapportera detta om du fortfarande får detta fel",
+ "flow-error-protected-autoconfirmed-logged-in": "Detta forum är skyddat. Endast automatiskt bekräftade användare får delta. Anledning: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Detta forum är skyddat. Endast inloggade användare får delta. Anledning: $1",
+ "flow-error-protected-sysop-logged-in": "Detta forum är skyddat. Endast användare med administratörsrättigheter får delta. Anledning: $1",
+ "flow-error-protected-sysop-logged-out": "Detta forum är skyddat. Endast inloggade användare med administratörsrättigheter får delta. Anledning: $1",
+ "flow-error-protected-unknown-reason": "Okänd",
"flow-error-missing-replyto": "Ingen \"replyTo\"-parameter tillhandahölls. Denna parameter krävs för åtgärden \"svara\".",
- "flow-error-invalid-replyto": "\"replyTo\"-parametern var ogiltig. Det angivna inlägget kunde inte hittas.",
- "flow-error-delete-failure": "Radering av detta objekt misslyckades.",
- "flow-error-hide-failure": "Döljandet av detta objekt misslyckades.",
"flow-error-missing-postId": "Ingen \"postId\"-parameter tillhandahölls. Denna parameter krävs för att påverka ett inlägg.",
"flow-error-invalid-postId": "Parametern \"postId\" var ogiltig. Det angivna inlägget ($1) kunde inte hittas.",
- "flow-error-restore-failure": "Det gick inte att återställa objektet.",
- "flow-error-invalid-moderation-state": "Ett ogiltigt värde för parametern ('moderationState') lämnades till Flow API:et.",
+ "flow-error-invalid-moderation-state": "Ett ogiltigt värde för parametern ('moderationState') lämnades till API:et för strukturerade diskussioner.",
"flow-error-invalid-moderation-reason": "Vänligen ange en orsak för moderationen",
"flow-error-not-allowed": "Otillräcklig behörighet att utföra denna åtgärd",
"flow-error-not-allowed-hide": "Detta ämne har dolts.",
@@ -163,17 +192,19 @@
"flow-error-missing-prev-revision-identifier": "Identifieraren för den tidigare versionen saknas.",
"flow-error-prev-revision-mismatch": "En annan användare redigerade just inlägget för några sekunder sedan. Är {{GENDER:$3|du}} säker på att du vill skriva över de senaste ändringarna?",
"flow-error-prev-revision-does-not-exist": "Kunde inte hitta den tidigare versionen.",
- "flow-error-core-topic-deletion": "För att radera ett ämne, använd menyn ... på Flow-forumet eller [$1 ämnessidan]. Gå inte direkt till action=delete för ämnet.",
+ "flow-error-core-topic-deletion": "För att radera ett ämne, använd menyn ... på strukturerade diskussionsforumet eller [$1 ämnessidan]. Gå inte direkt till action=delete för ämnet.",
"flow-error-default": "Ett fel har uppstått.",
- "flow-error-invalid-input": "Ett ogiltigt värde angavs för att läsa in Flow-innehåll.",
+ "flow-error-invalid-input": "Ett ogiltigt värde angavs för att läsa in strukturerat diskussionsinnehåll.",
"flow-error-invalid-title": "Ogiltig sidrubrik angavs.",
+ "flow-error-invalid-parameter": "Saknad eller ogiltig parameter till metodanropet",
"flow-error-fail-load-history": "Innehållet i historiken kunde inte läsas in.",
- "flow-error-missing-revision": "Det gick inte att hitta en version för att ladda Flow-innehåll.",
- "flow-error-fail-commit": "Flow-innehållet kunde inte sparas.",
+ "flow-error-missing-revision": "Det gick inte att hitta en version för att läsa in strukturerat diskussionsinnehåll.",
+ "flow-error-fail-commit": "Strukturerade diskussionsinnehållet kunde inte sparas.",
"flow-error-insufficient-permission": "Otillräcklig behörighet för att komma åt innehållet.",
"flow-error-revision-comparison": "Diff-funktionen kan endast användas för två revideringar som hör till samma post.",
"flow-error-missing-topic-title": "Kunde inte hitta ämnesrubriken för det aktuella arbetsflödet.",
"flow-error-missing-metadata": "Kunde inte hitta den metadata som krävs för den här versionen.",
+ "flow-error-different-page": "Arbetsflödet Strukturerade diskussioner associeras inte med denna sida.",
"flow-error-fail-load-data": "Det gick inte att läsa in de begärda uppgifterna.",
"flow-error-invalid-workflow": "Kunde inte hitta det önskade arbetsflödet.",
"flow-error-process-data": "Ett fel uppstod under bearbetning av uppgifterna i din begäran.",
@@ -183,18 +214,19 @@
"flow-error-no-commit": "Den angivna åtgärden kunde inte sparas.",
"flow-error-content-too-long": "Innehållet är för stort. Innehåll, efter expansion, är begränsad till $1 {{PLURAL:$1|byte|bytes}}.",
"flow-error-move-topic": "Flyttning av ett ämne stöds för närvarande inte.",
- "flow-error-move-no-create-permissions": "Behörigheten \"{{int:right-flow-create-board}}\" krävs för att flytta ett Flow-forum.",
"flow-error-invalid-topic-uuid-title": "Ogiltig titel",
- "flow-error-invalid-topic-uuid": "Den begärda sidatiteln var ogiltig. Sidor i ämnesnamnrymden skapas automatiskt av Flow.",
+ "flow-error-invalid-topic-uuid": "Den begärda sidtiteln var ogiltig. Sidor i ämnesnamnrymden skapas automatiskt av Strukturerade diskussioner.",
"flow-error-unknown-workflow-id-title": "Okänt ämne",
"flow-error-unknown-workflow-id": "Det begärda ämnet finns inte.",
"flow-error-search": "Vi kunde inte slutföra din sökning på grund av ett tillfälligt problem. Försök igen senare.",
+ "flow-error-invalid-undelete": "Sidan kunde inte återställas eftersom det finns för tillfället ett diskussionsforum där.",
"flow-edit-header-placeholder": "Beskriva detta diskussionsforum",
"flow-edit-header-submit": "Spara beskrivning",
"flow-edit-header-submit-anonymously": "Spara beskrivning anonymt",
"flow-edit-title-submit": "Ändra rubrik",
"flow-edit-title-submit-anonymously": "Ändra titel anonymt",
"flow-edit-post-submit": "Skicka ändringar",
+ "flow-edit-post-submit-anonymously": "Spara ändringar anonymt",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|redigerade}} en [$3 kommentar] på \"$4\".",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Redigerade}} ett inlägg",
"flow-rev-message-reply": "$1 [$3 {{GENDER:$2|kommenterade}}] på \"$4\" (<em>$5</em>).",
@@ -213,7 +245,7 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|dolde}} [$4 ämnet] på \"$6\" (<em>$5</em>).",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|tog bort}} [$4 ämnet] på \"$6\" (<em>$5</em>).",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|censurerade}} [$4 ämnet] på \"$6\" (<em>$5</em>).",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|märkte}} [$4 ämnet] $6 som löst (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|märkte}} [$4 ämnet] \"$6\" som löst (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "Märk som löst",
"flow-rev-message-restore-topic-reason": "återöppnad",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|återställde}} [$4 ämnet] på \"$6\" (<em>$5</em>).",
@@ -236,31 +268,73 @@
"flow-comment-moderated": "Modererad kommentar",
"flow-last-modified": "Senast ändrad $1",
"flow-workflow": "arbetsflöde",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|svarade}} på '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 och $5 {{PLURAL:$6|annan|andra}} {{GENDER:$1|svarade}} på '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|svarade}} på <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 och {{PLURAL:$5|en annan|$5 andra|100=99+ andra}} {{GENDER:$1|svarade}} på <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 har {{GENDER:$1|redigerat}} ditt <span class=\"plainlinks\">[$5 inlägg]</span> på [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 och $5 {{PLURAL:$6|annan|andra}} {{GENDER:$1|redigerade}} ett <span class=\"plainlinks\">[$4 inlägg]</span> i \"$2\" på \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|skapade}} ett nytt ämne på '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 nytt ämne|$1 nya ämnen}} {{PLURAL:$1|nytt ämne|nya ämnen}} på '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 och {{PLURAL:$5|en annan|$5 andra|100=99+ andra}} {{GENDER:$1|redigerade}} ett <span class=\"plainlinks\">[$4 inlägg]</span> i \"$2\" på \"$3\".",
+ "notification-header-flow-new-topic-v2": "Nytt ämne skapades på <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Ett nytt ämne|$1 nya ämnen|100=99+ nya ämnen}} på <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Ett nytt ämne skapades på <strong>din diskussionssida</strong>: \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Ett nytt ämne|$1 nya ämnen|100=99+ nya ämnen}} på <strong>din diskussionssida</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|svarade}} på \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Ett nytt|$1 nya|100=99+ nya}} svar på \"<strong>$3</strong>\".",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|svarade}} på <strong>din diskussionssida</strong> i \"<strong>$4</strong>\".",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Ett nytt|$1 nya|100=99+ nya}} svar på <strong>din diskussionssida</strong> i \"<strong>$3</strong>\".",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Ditt}} inlägg på \"<strong>$1</strong>\" redigerades.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Ditt}} inlägg på \"<strong>$1</strong>\" redigerades flera gånger.",
+ "notification-header-flow-post-edited-user-talk": "Ett inlägg på \"<strong>$1</strong>\" redigerades på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Ett inlägg på \"<strong>$1</strong>\" redigerades flera gånger på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Ämnet \"<strong>$1</strong>\" bytte namn till \"<strong>$2</strong>\".",
+ "notification-header-flow-topic-renamed-user-talk": "Ämnet \"<strong>$1</strong>\" bytte namn till \"<strong>$2</strong>\" på <strong>{{GENDER:$3|din}} diskussionssida</strong>.",
+ "notification-header-flow-summary-edited": "Sammanfattningen för \"<strong>$1</strong>\" uppdaterades.",
+ "notification-header-flow-summary-edited-first": "Ämnet \"<strong>$1</strong>\" sammanfattas.",
+ "notification-bundle-header-flow-summary-edited": "Sammanfattningen för \"<strong>$1</strong>\" uppdaterades flera gånger.",
+ "notification-header-flow-summary-edited-user-talk": "Sammanfattningen för \"<strong>$1</strong>\" uppdaterades på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Ämnet \"<strong>$1</strong>\" sammanfattades på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Sammanfattningen för \"<strong>$1</strong>\" uppdaterades flera gånger på <strong>{{GENDER:$2|din}} diskussionssidan</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|uppdaterade}} sammanfattningen på $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|uppdaterade}} sammanfattningen på $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 och {{PLURAL:$3|en annan|$3 andra|100=99+ andra}} {{GENDER:$1|uppdaterade}} sammanfattningen på $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|nämnde}} {{GENDER:$4|dig}} i \"<strong>$5</strong>\".",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|nämnde}} {{GENDER:$4|dig}} i beskrivningen för <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|nämnde}} {{GENDER:$4|dig}} i \"<strong>$5</strong>\".",
+ "notification-header-flow-enabled-on-talkpage": "Nytt diskussionssystem har aktiverats för <strong>{{GENDER:$2|din}} användardiskussionssida</strong>.",
+ "notification-header-flow-description-edited": "Beskrivningen för <strong>$1</strong> redigerades.",
+ "notification-header-flow-description-edited-user-talk": "Beskrivningen redigerades på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-bundle-header-flow-description-edited": "Beskrivningen för <strong>$1</strong> redigerades flera gånger.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Beskrivningen redigerades flera gånger på <strong>{{GENDER:$2|din}} diskussionssida</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Visa}} sidan",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|redigerade}} beskrivningen på $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|redigerade}} beskrivningen på $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 och {{PLURAL:$3|en annan|$3 andra|100=99+ andra}} {{GENDER:$1|redigerade}} beskrivningen på $2",
+ "notification-header-flow-topic-resolved": "Ämnet \"<strong>$1</strong>\" löstes.",
+ "notification-header-flow-topic-reopened": "Ämnet \"<strong>$1</strong>\" återöppnades.",
+ "notification-header-flow-topic-resolved-user-talk": "Ämnet \"<strong>$1</strong>\" löstes på <strong>din diskussionssida</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Ämnet \"<strong>$1</strong>\" återöppnades på <strong>din diskussionssida</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Ämnet \"<strong>$2</strong>\" löstes.",
+ "notification-email-batch-body-flow-topic-resolved": "Ämnet \"<strong>$2</strong>\" löstes.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|skapade}} ett nytt ämne på <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Ett nytt ämne|$1 nya ämnen|100=99+ nya ämnen}} på <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|ändrade}} rubriken för <span class=\"plainlinks\">[$2 $3]</span> till \"$4\" på [[$5|$6]].",
"flow-notification-mention": "$1 {{GENDER:$1|nämnde}} {{GENDER:$5|dig}} i {{GENDER:$1|hans|hennes|sitt}} <span class=\"plainlinks\">[$2 inlägg]</span> i \"$3\" på \"$4\".",
"flow-notification-link-text-view-post": "Visa inlägg",
"flow-notification-link-text-view-topic": "Visa ämne",
+ "flow-notification-link-text-view-topics": "Visa ämnen",
"flow-notification-reply-email-subject": "$2 på $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|svarade}} på \"$2\" på $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 och $4 {{PLURAL:$5|annan|andra}} {{GENDER:$1|svarade}} på \"$2\" på $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 och {{PLURAL:$4|en annan|$4 andra|100=99+ andra}} {{GENDER:$1|svarade}} på \"$2\" på $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|omnämnde}} {{GENDER:$3|dig}} på $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|omnämnde}} {{GENDER:$4|dig}} i {{GENDER:$1|hans|hennes|sitt}} inlägg i \"$2\" på $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|redigerade}} ett inlägg",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|redigerade}} ett inlägg i \"$2\" på $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 och $4 {{PLURAL:$5|annan|andra}} {{GENDER:$1|redigerade}} ett inlägg i \"$2\" på $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 och {{PLURAL:$4|en annan|$4 andra|100=99+ andra}} {{GENDER:$1|redigerade}} ett inlägg i \"$2\" på $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|byt namn på}} ditt ämne",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|byt namn på}} ditt ämne \"$2\" till \"$3\" på $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|skapade}} ett nytt ämne på $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|skapade}} ett ny ämne med rubriken \"$2\" på $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 nytt ämne|$1 nya ämnen|250=250+ nya ämnen}} på $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Meddela mig när åtgärder som rör mig förekommer i Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Ett nytt ämne|$1 nya ämnen|100=99+ nya ämnen}} på $2",
+ "echo-category-title-flow-discussion": "Strukturerad diskussion",
+ "echo-pref-tooltip-flow-discussion": "Meddela mig om aktivitet i ämnen eller på sidor jag följer.",
"flow-link-post": "inlägg",
"flow-link-topic": "ämne",
"flow-link-history": "historik",
@@ -292,18 +366,18 @@
"flow-moderation-confirm-unsuppress-topic": "Avcensurera",
"flow-moderation-confirm-undelete-topic": "Återställ",
"flow-moderation-confirm-unhide-topic": "Sluta dölja",
- "flow-moderation-confirmation-suppress-post": "Inlägget censurerades framgångsrikt.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
- "flow-moderation-confirmation-delete-post": "Inlägget raderades framgångsrikt.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
- "flow-moderation-confirmation-hide-post": "Inlägget doldes framgångsrikt.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
- "flow-moderation-confirmation-unsuppress-post": "Du har framgångsrikt avcensurerat ovanstående inlägg.",
- "flow-moderation-confirmation-undelete-post": "Du har framgångsrikt återställt ovanstående inlägg.",
- "flow-moderation-confirmation-unhide-post": "Du har framgångsrikt slutat dölja ovanstående inlägg.",
+ "flow-moderation-confirmation-suppress-post": "Inlägget har censurerats.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
+ "flow-moderation-confirmation-delete-post": "Inlägget har raderats.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
+ "flow-moderation-confirmation-hide-post": "Inlägget har dolts.\n{{GENDER:$2|Överväg}} att ge feedback åt $1 gällande detta inlägg.",
+ "flow-moderation-confirmation-unsuppress-post": "Du har avcensurerat ovanstående inlägg.",
+ "flow-moderation-confirmation-undelete-post": "Du har återställt ovanstående inlägg.",
+ "flow-moderation-confirmation-unhide-post": "Du har slutat dölja ovanstående inlägg.",
"flow-moderation-confirmation-suppress-topic": "Detta ämne har censurerats.",
"flow-moderation-confirmation-delete-topic": "Detta ämne har raderats.",
"flow-moderation-confirmation-hide-topic": "Detta ämne har dolts.",
- "flow-moderation-confirmation-unsuppress-topic": "Du har framgångsrikt avcensurerat detta ämne.",
- "flow-moderation-confirmation-undelete-topic": "Du har framgångsrikt återställt detta ämne.",
- "flow-moderation-confirmation-unhide-topic": "Du har framgångsrikt slutat dölja detta ämne.",
+ "flow-moderation-confirmation-unsuppress-topic": "Du har avcensurerat detta ämne.",
+ "flow-moderation-confirmation-undelete-topic": "Du har återställt detta ämne.",
+ "flow-moderation-confirmation-unhide-topic": "Du har slutat dölja detta ämne.",
"flow-moderation-title-suppress-topic": "Censurera ämnet?",
"flow-moderation-title-delete-topic": "Radera ämnet?",
"flow-moderation-title-hide-topic": "Dölja ämnet?",
@@ -326,15 +400,15 @@
"flow-revision-permalink-warning-header-first": "Detta är en permanent länk till den första versionen av beskrivningen.\nDu kan se senare versioner på [$2 forumets historiksida].",
"flow-compare-revisions-revision-header": "Version av {{GENDER:$2|$2}} från $1",
"flow-compare-revisions-header-post": "Denna sida visar {{GENDER:$3|förändringar}} mellan två versioner av ett inlägg av $3 i ämnet \"[$5 $2]\" på [$4 $1].\nDu kan se andra versioner av detta inlägg genom dess [$6 historiksida].",
- "flow-compare-revisions-header-postsummary": "Denna sida visar förändringarna mellan två versioner av en inläggssammanfattning i inlägget \"[$4 $2]\" på [$3 $1].\nDu kan se andra versioner av detta inlägg genom dess [$5 historiksida].",
+ "flow-compare-revisions-header-postsummary": "Denna sida visar förändringarna mellan två versioner av sammanfattningen i ämnet \"[$4 $2]\" på [$3 $1].\nDu kan se andra versioner av denna ämnessammanfattning på ämnets [$5 historiksida].",
"flow-compare-revisions-header-header": "Denna sida visar {{GENDER:$2|ändringarna}} mellan två versioner av beskrivningen på [$3 $1].\nDu kan se andra versioner av beskrivningen på dess [$4 sidhistorik].",
- "action-flow-create-board": "skapa Flow-forum på alla platser",
- "right-flow-create-board": "Skapa Flow-forum var som helst",
- "right-flow-hide": "Dölj ämnen och inlägg i Flow",
- "right-flow-lock": "Märk ämnen i Flow som lösta",
- "right-flow-delete": "Radera ämnen och inlägg i Flow",
- "right-flow-edit-post": "Redigera andras inlägg i Flow",
- "right-flow-suppress": "Censurera versioner i Flow",
+ "action-flow-create-board": "skapa strukturerade diskussionsforum på alla platser",
+ "right-flow-create-board": "Skapa strukturerade diskussionsforum var som helst",
+ "right-flow-hide": "Dölj ämnen och inlägg i strukturerade diskussioner",
+ "right-flow-lock": "Märk ämnen i strukturerade diskussioner som lösta",
+ "right-flow-delete": "Radera ämnen och inlägg i strukturerade diskussioner",
+ "right-flow-edit-post": "Redigera andras inlägg i strukturerade diskussioner",
+ "right-flow-suppress": "Censurera versioner i strukturerade diskussioner",
"flow-terms-of-use-new-topic": "Genom att klicka på \"{{int:flow-newtopic-save}}\" godkänner du användarvillkoren för denna wiki.",
"flow-terms-of-use-reply": "Genom att klicka på \"{{int:flow-reply-link}}\" godkänner du användarvillkoren för denna wiki.",
"flow-terms-of-use-edit": "Genom att spara dina ändringar godkänner du användarvillkoren för denna wiki.",
@@ -358,23 +432,25 @@
"flow-whatlinkshere-post": "från ett [$1 inlägg]",
"flow-whatlinkshere-header": "från [$1 beskrivningen]",
"flow-whatlinkshere-post-summary": "från [$1 sammanfattningen]",
- "flow": "Flow",
- "flow-special-desc": "Denna specialsida omdirigerar till ett Flow-arbetsflöde eller ett Flow-inlägg för ett angivet UUID.",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Denna specialsida omdirigerar till ett strukturerat diskussionsflöde eller ett strukturerat diskussionsinlägg för ett angivet UUID.",
"flow-special-type": "Typ",
"flow-special-type-post": "Inlägg",
"flow-special-type-workflow": "Arbetsflöde",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Kunde inte hitta innehåll som matchar typen och UUID:et.",
- "flow-special-enableflow-legend": "Aktivera Flow på en ny sida",
- "flow-special-enableflow-page": "Sida att aktivera Flow på",
- "flow-special-enableflow-header": "Inledande beskrivning av Flow-forumet (wikitext)",
- "flow-special-enableflow-board-already-exists": "Det finns redan ett Flow-forum på [[$1]].",
+ "flow-special-enableflow-legend": "Aktivera strukturerade diskussioner på en ny sida",
+ "flow-special-enableflow-page": "Sida att aktivera strukturerade diskussioner på",
+ "flow-special-enableflow-header": "Inledande beskrivning av strukturerat diskussionsforum (wikitext)",
+ "flow-special-enableflow-board-already-exists": "Det finns redan ett strukturerat diskussionsforum på [[$1]].",
"flow-special-enableflow-invalid-title": "En ogiltig sidtitel angavs",
- "flow-special-enableflow-board-creation-not-allowed": "Du får inte skapa ett Flow-forum på [[:$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "Du får inte skapa ett strukturerat diskussionsforum på [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Det finns redan en LiquidThreads-sida på [[:$1]].",
- "flow-special-enableflow-confirmation": "Du har skapat ett Flow-forum på [[$1]].",
+ "flow-special-enableflow-confirmation": "Du har skapat ett strukturerat diskussionsforum på [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Archive %d\n%s/Archive%d\n%s/archive %d\n%s/archive%d",
- "flow-spam-confirmedit-form": "Vänligen bekräfta att du är en människa genom att lösa nedanstående captcha: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Strukturerat diskussionsarkiv %d\n%s/Strukturerat diskussionsarkiv%d",
+ "flow-spam-confirmedit-form": "Vänligen bekräfta att du är en människa genom att lösa nedanstående CAPTCHA: $1",
+ "flow-spam-confirmedit-using-failure": "Ett tekniskt fel uppstod med CAPTCHA. Om du inte kan skicka dina ändringar kan du kopiera din text, uppdatera sidan och försöka igen.",
"flow-embedding-unsupported": "Diskussioner kan ännu inte bäddas in.",
"mw-ui-unsubmitted-confirm": "Du har osparade ändringar på denna sida. Är du säker du vill lämna sidan och förlora ändringarna?",
"flow-post-undo-hide": "ångra dölj",
@@ -383,113 +459,27 @@
"flow-topic-undo-hide": "ångra dölj",
"flow-topic-undo-delete": "ångra radera",
"flow-topic-undo-suppress": "ångra censurering",
- "flow-importer-lqt-moved-thread-template": "LQT Flyttad tråd-stubb konverterad till Flow",
+ "flow-importer-lqt-moved-thread-template": "Flyttad LQT-trådstubb konverterades till strukturerad diskussion",
"flow-importer-lqt-moved-thread-template-content": "Detta inlägg av {{{author}}} flyttades den {{{date}}}. Du kan hitta det på [[{{{title}}}]].",
- "flow-importer-lqt-converted-template": "LQT-sida konverterad till Flow",
+ "flow-importer-lqt-converted-template": "LQT-sida konverterades till strukturerad diskussion",
+ "flow-importer-lqt-converted-template-content": "Den tidigare sidhistoriken arkiverades för att säkerhetskopiera den på <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> den {{#time: d F Y|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Arkiv för konverterad LQT-sida",
- "flow-importer-wt-converted-template": "Wikitextdiskussionssida konverterad till Flow",
+ "flow-importer-lqt-converted-archive-template-content": "Denna sida är en arkiverad LiquidThreads-sida. <strong>Redigera inte innehållet i denna sida</strong>. Ytterligare kommentarer hänvisas till [[{{{from}}}|den aktuella diskussionssidan]].",
+ "flow-importer-wt-converted-template": "Wikitextdiskussionssida konverterades till strukturerad diskussion",
+ "flow-importer-wt-converted-template-content": "Föregående diskussioner arkiverades på <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> den {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Arkiv för konverterade wikitextdiskussionssidor",
+ "flow-importer-wt-converted-archive-template-content": "Denna sida är ett arkiv. <strong>Redigera inte innehållet i denna sida</strong>. Ytterligare kommentarer hänvisas till [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|den aktuella diskussionssidan]].",
"flow-importer-lqt-suppressed-user-template": "LQT inlägg importerat med dold användare",
+ "flow-importer-lqt-suppressed-user-template-content": "Denna sidversion importerades från LiquidThreads med en censurerad användare. Den har tilldelats till den aktuella användaren.",
"flow-importer-lqt-different-author-signature-template": "LQT inlägg importera med användare med annan signatur",
- "apihelp-flow-description": "GÖr det möjligt att utföra åtgärder på Flow-sidor.",
- "apihelp-flow-param-submodule": "Den Flow-undermodul som ska anropas.",
- "apihelp-flow-param-page": "Sidan som åtgärden ska utföras på.",
- "apihelp-flow-example-1": "Redigera beskrivningen för \"[[Talk:Sandbox]]\"",
- "apihelp-flow+close-open-topic-description": "Utfasad i förmån för [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Tillstånd att försätta ämnet i, antingen \"lås\" eller \"lås upp\".",
- "apihelp-flow+close-open-topic-param-reason": "Skäl för att låsa eller låsa upp ämnet.",
- "apihelp-flow+edit-header-description": "Redigera beskrivningen för ett forum.",
- "apihelp-flow+edit-header-param-prev_revision": "Versions-ID för den aktuella beskrivningsversionen, för att hantera redigeringskonflikter.",
- "apihelp-flow+edit-header-param-content": "Innehåll för beskrivningen.",
- "apihelp-flow+edit-header-param-format": "Beskrivningens format (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "Redigera beskrivningen för [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Redigerar ett inläggs innehåll.",
- "apihelp-flow+edit-post-param-postId": "Inläggs-ID.",
- "apihelp-flow+edit-post-param-prev_revision": "Versions-ID för den aktuella inläggsversionen, för att hantera redigeringskonflikter.",
- "apihelp-flow+edit-post-param-content": "Innehåll för inlägg.",
- "apihelp-flow+edit-post-param-format": "Formatet för inläggets innehåll (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "Redigera ett inlägg i [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Redigeringar en ämnesrubrik.",
- "apihelp-flow+edit-title-param-prev_revision": "Versions-ID för den aktuella titelversionen, för att hantera redigeringskonflikter.",
- "apihelp-flow+edit-title-param-content": "Innehåll för rubrik.",
- "apihelp-flow+edit-title-example-1": "Redigera rubriken på [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Redigera innehållet för en ämnessammanfattning.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Versions-ID för den aktuella ämnessammanfattningsversionen, för att hantera redigeringskonflikter.",
- "apihelp-flow+edit-topic-summary-param-summary": "Innehåll för sammanfattningen.",
- "apihelp-flow+edit-topic-summary-param-format": "Sammanfattningens format (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Redigera sammanfattningen av [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Lås eller lås upp ett Flow-ämne.",
- "apihelp-flow+lock-topic-param-moderationState": "Tillstånd att försätta ämnet i, antingen <kbd>lås</kbd> eller <kbd>lås upp</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Skäl för att låsa eller låsa upp ämnet. Notera att Flow-klienten på wikin använder \"Markerad som löst\" här vilket lägger till ytterligare information i sammanfattningen.",
- "apihelp-flow+lock-topic-example-1": "Lås [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Modererar ett Flow-inlägg.",
- "apihelp-flow+moderate-post-param-moderationState": "Vilken nivå att moderera på.",
- "apihelp-flow+moderate-post-param-reason": "Skäl för moderering.",
- "apihelp-flow+moderate-post-param-postId": "ID för inlägget som ska modereras.",
- "apihelp-flow+moderate-post-example-1": "Radera ett inlägg i ämne [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Moderera ett Flow-ämne.",
- "apihelp-flow+moderate-topic-param-moderationState": "Vilken nivå att moderera på.",
- "apihelp-flow+moderate-topic-param-reason": "Skäl för moderering.",
- "apihelp-flow+moderate-topic-example-1": "Radera ämnet [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Skapa ett nytt Flow-ämne på det angivna arbetsflödet.",
- "apihelp-flow+new-topic-param-topic": "Text för ny ämnestitel.",
- "apihelp-flow+new-topic-param-content": "Innehåll för ämnets första svar.",
- "apihelp-flow+new-topic-param-format": "Format på det nya ämnets första svar (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "Skapa ett nytt ämne på [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Svar på ett inlägg.",
- "apihelp-flow+reply-param-replyTo": "Inläggs-ID att svara på.",
- "apihelp-flow+reply-param-content": "Innehåll för nytt inlägg.",
- "apihelp-flow+reply-param-format": "Formatet för det nya inlägget (wikitext|html)",
- "apihelp-flow+reply-example-1": "Svara på ett inlägg på [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Format att returnera innehållet i.",
- "apihelp-flow+view-header-description": "Visa beskrivning för ett forum.",
- "apihelp-flow+view-header-param-revId": "Ladda denna version, istället för den senaste.",
- "apihelp-flow+view-header-example-1": "Hämta beskrivningen för [[Talk:Sandbox]] som wikitext",
- "apihelp-flow+view-post-description": "Visa ett inlägg",
- "apihelp-flow+view-post-param-postId": "ID för inlägget som ska visas.",
- "apihelp-flow+view-post-param-format": "Format att returnera innehållet i.",
- "apihelp-flow+view-post-example-1": "Hämta innehållet i ett inlägg på [[Topic:S2tycnas4hcucw8w]] som wikitext",
- "apihelp-flow+view-topic-description": "Visa ett ämne.",
- "apihelp-flow+view-topic-example-1": "Visa [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-summary-description": "Visa en ämnessammanfattning.",
- "apihelp-flow+view-topic-summary-param-format": "Format att returnera innehållet i.",
- "apihelp-flow+view-topic-summary-param-revId": "Ladda denna version, istället för den senaste.",
- "apihelp-flow+view-topic-summary-example-1": "Visa sammanfattningen för [[Topic:S2tycnas4hcucw8w]] som wikitext",
- "apihelp-flow+view-topiclist-description": "Visa en lista av ämnen.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Riktning för sortering av ämnen.",
- "apihelp-flow+view-topiclist-param-sortby": "Sorteringsalternativ för ämnena, anringen <kbd>uppdaterad</kbd> (sorterat på ämnets uppdateringstid), eller <kbd>nyast</kbd> (sorterat på ämnets tid för skapande).",
- "apihelp-flow+view-topiclist-param-savesortby": "Spara sorteringsalternativ i användarintällningarna, om angivet.",
- "apihelp-flow+view-topiclist-param-offset-id": "Förskjutningsvärde (i UUID-format) från vilket ämnen ska börja hämtas; används bara i sorteringen <kbd>nyaste</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Förskjutningsvärde (som ämnets tidsstämpel, i <code>TS_MW</code> formatet (<code>ÅÅÅÅMMDDTTMMSS</code>)), från vilket ämnen ska börja hämtas; används bara vid sorteringen <kbd>uppdaterad</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Antal ämnen att hämta.",
- "apihelp-flow+view-topiclist-example-1": "Lista ämnen på [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Konvertera text mellan wikitext och HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Format att konvertera innehållet från.",
- "apihelp-flow-parsoid-utils-param-to": "Format att konvertera innehållet till.",
- "apihelp-flow-parsoid-utils-param-content": "Innehåll att konvertera.",
- "apihelp-flow-parsoid-utils-param-title": "Titel för sidan. Kan inte användas tillsammans med $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID för sidan. Kan inte användas tillsammans med $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Konvertera wikitext <nowiki>'''lorem''' ''blah''</nowiki> till HTML",
- "apihelp-query+flowinfo-description": "Hämta grundläggande Flow-information för en sida.",
- "apihelp-query+flowinfo-example-1": "Hämta Flow-information om [[Talk:Sandbox]], [[Main Page]], och [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Hämta information som är nödvändig för att göra beskrivningsredigeringar ogjorda.",
- "apihelp-flow+undo-edit-header-param-startId": "Sidversionens ID att börja ångra från.",
- "apihelp-flow+undo-edit-header-param-endId": "Sidversionens ID att sluta ångra på.",
- "apihelp-flow+undo-edit-header-example-1": "Hämta information om att ångra en beskrivningsredigering på [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Hämta information som är nödvändig för att göra inläggsredigering ogjord.",
- "apihelp-flow+undo-edit-post-param-postId": "Inläggs-ID att ångra.",
- "apihelp-flow+undo-edit-post-param-startId": "Sidversionens ID att börja ångra från.",
- "apihelp-flow+undo-edit-post-param-endId": "Sidversionens ID att sluta ångra på.",
- "apihelp-flow+undo-edit-post-example-1": "Hämta information om att ångra en inläggsredigering inom ett specifikt ämne.",
- "apihelp-flow+undo-edit-topic-summary-description": "Hämta information som är nödvändig för att göra ämnessammanfattningsredigeringar ogjorda.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Sidversionens ID att börja ångra från.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Sidversionens ID att sluta ångra på.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Hämta information om att göra en ämnessammanfattningsredigering ogjord i ett specifikt ämne.",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Detta inlägg skapades av [[User:{{{authorUser}}}|{{{authorUser}}}]], men signerades som [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Redigerad",
"flow-edited-by": "Redigerad av $1",
- "flow-lqt-redirect-reason": "Omdirigerar utfasad LiquidThreads-inlägg till dess konverterade Flow-inlägg",
- "flow-talk-conversion-move-reason": "Konvertering av wikitext till Flow från $1",
- "flow-talk-conversion-archive-edit-reason": "Konvertering av diskussion i wikitext till Flow",
+ "flow-edited-by-header": "Forumbeskrivningen redigerades av $1",
+ "flow-edited-by-topic-title": "Ämnesrubriken redigerades av $1",
+ "flow-lqt-redirect-reason": "Omdirigerar utfasad LiquidThreads-inlägg till dess konverterade strukturerade diskussionsinlägg",
+ "flow-talk-conversion-move-reason": "Konvertering av wikitext till strukturerad diskussion från $1",
+ "flow-talk-conversion-archive-edit-reason": "Konvertering av diskussion i wikitext till strukturerad diskussion",
"flow-previous-diff": "← Äldre redigering",
"flow-next-diff": "Nyare redigering →",
"flow-undo": "gör ogjord",
@@ -500,9 +490,9 @@
"flow-undo-edit-post": "Redigerar ett inlägg",
"flow-undo-edit-content": "Redigeringen kan göras ogjord. Var god och kontrollera jämförelsen nedan för att bekräfta att detta är vad du avser att göra, och spara sedan ändringarna nedan för att göra redigeringen ogjord.",
"flow-undo-edit-failure": "Redigeringen kunde inte göras ogjord på grund av konflikt med mellanliggande redigeringar.",
- "group-flow-bot": "Flow-botar",
- "group-flow-bot-member": "Flow-Bot",
- "grouppage-flow-bot": "Project:Flow-botar",
+ "group-flow-bot": "Strukturerad diskussion-botar",
+ "group-flow-bot-member": "Strukturerad diskussion-bot",
+ "grouppage-flow-bot": "Project:Strukturerade diskussion-botar",
"flow-ve-mention-context-item-label": "Nämn",
"flow-ve-mention-inspector-title": "Nämn",
"flow-ve-mention-inspector-remove-label": "Ta bort",
@@ -512,25 +502,36 @@
"flow-ve-mention-inspector-invalid-user": "Användarnamnet \"$1\" är inte registrerat.",
"flow-wikitext-editor-help": "Wikitext $1.",
"flow-wikitext-editor-help-and-preview": "Wikitexten $1 och du kan $2 när som helst.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|använder kodläge]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|använder kodläge]]",
"flow-wikitext-editor-help-preview-the-result": "förhandsgranska resultatet",
- "flow-wikitext-switch-editor-tooltip": "Byt till VisualEditor",
+ "flow-wikitext-switch-editor-tooltip": "Byt till den visuella redigeraren",
"flow-ve-switch-editor-tool-title": "Byt till wikitext-redigeraren",
"flow-mark-revision-patrolled-link-text": "Märk den här sidan som patrullerad",
"flow-mark-revision-patrolled-link-title": "Märk den här sidan som patrullerad",
"flow-mark-diff-patrolled-link-text": "Märk som patrullerad",
"flow-mark-diff-patrolled-link-title": "Märk som patrullerad",
- "flow-notification-link-text-enabled-on-talkpage": "Visa användardiskussionssida",
+ "flow-talk-page-beta-feature-message": "Strukturerade diskussioner på användardiskussioner",
+ "flow-talk-page-beta-feature-description": "Möjliggör ett nytt strukturerat diskussionssystem på {{GENUS:|din}} användardiskussionssida. Strukturerade diskussioner förenklar diskussioner genom tydliga platser för att skriva och svara, och tillåter notifieringar på konversationsnivå. Befintliga wikitext-diskussioner flyttas till ett arkiv. Den här funktionen är inte automatiskt aktiverad, användare måste aktivera den separat. Inaktivering av den här funktionen kommer att flytta strukturerade diskussionerna till en undersida och oarkivera föregående diskussionssida. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Läs mer om aktivering]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Visa}} användardiskussionssida",
+ "flow-notification-enabled-on-talkpage-title": "Nytt diskussionssystem aktiverat för {{GENDER:$1|din}} användardiksussionssida<br /><small>Finns på [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Nytt diskussionssystem på $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "Strukturerade diskussioner, det nya diskussionssystemet, har aktiverats på {{GENDER:$1|din}} användardiskussionssida på {{SITENAME}}. Du kan hitta mer information, ge återkoppling eller avaktivera det nya systemet när som helst från sektionen med beta-funktioner i {{GENDER:$1|dina}} inställningar.",
+ "flow-beta-feature-add-archive-template-edit-summary": "Lägger till arkivmall",
"flow-beta-feature-remove-archive-template-edit-summary": "Tar bort arkivmall",
- "flow-dialog-cancelconfirm-title": "Är du säker?",
- "flow-dialog-cancelconfirm-message": "Är du säker på att du vill avbryta utan att spara först?",
+ "flow-dialog-cancelconfirm-title": "Är {{GENDER:|du}} säker?",
+ "flow-dialog-cancelconfirm-message": "Är {{GENDER:|du}} säker på att du vill avbryta utan att spara först?",
"flow-dialog-cancelconfirm-keep": "Fortsätt redigera",
"flow-dialog-cancelconfirm-discard": "Ignorera ändringar",
+ "flow-optin-archive-wikitext": "Flyttar wikitext-sidan för att göra plats för ett diskussionsforum.",
+ "flow-optin-archive-flow-board": "Flyttar diskussionsforumssidan för att göra plats för en wikitext-sida.",
+ "flow-optin-restore-wikitext": "Återställ arkiverad wikitext-sida.",
+ "flow-optin-restore-flow-board": "Återställ arkiverat diskussionsforum.",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|Välkommen}} till {{GENDER:$1|din}} nya användardiskussionsida",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Din}} diskussionssida är platsen där andra redigerare kan kontakta {{GENDER:$1|dig}}. Med Flow är det enklare att starta nya ämnen och hålla reda på konversationer.",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Din}} diskussionssida är platsen där andra redigerare kan kontakta {{GENDER:$1|dig}}. Med strukturerade diskussioner är det enklare att starta nya ämnen och hålla reda på konversationer.",
"flow-guidedtour-optin-find-old-conversations": "Hitta {{GENDER:$1|dina}} gamla konversationer",
"flow-guidedtour-optin-find-old-conversations-description": "Tidigare konversationer har flyttas till en arkivsida.",
"flow-guidedtour-optin-feedback": "Ge oss {{GENDER:$1|din}} återkoppling!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kan skaffa mer information, ge återkoppling eller inaktivera det nya systemet när som helst från avsnittet Betafunktioner."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Du}} kan skaffa mer information, ge återkoppling eller inaktivera det nya systemet när som helst från avsnittet Betafunktioner.",
+ "flow-action-not-page": "Sidobjektet är en instans av fel klass",
+ "flow-action-wrong-title-content-model": "Sidan hanteras av strukturerade diskussioner, men Titelklassen indikerar att innehållsmodellen är '$1'. Detta är en felkonfiguration eller ett inkonsistent tillstånd. Detta kan t.ex. vara en sida som inte är strukturerade diskussioner i en namnrymd av typen strukturerad diskussion där <code>rev_content_model</code> inte har specificerats."
}
diff --git a/Flow/i18n/ta.json b/Flow/i18n/ta.json
index 316af98c..02f6054e 100644
--- a/Flow/i18n/ta.json
+++ b/Flow/i18n/ta.json
@@ -2,13 +2,18 @@
"@metadata": {
"authors": [
"ElangoRamanujam",
- "கலைவாணன்"
+ "கலைவாணன்",
+ "Rakeshonwiki"
]
},
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|You}} இந்த பக்கத்தை பார்ப்பதில்லை \"$1\"",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "இவை {{GENDER:$3|you}} பார்க்கும் தனிப்பட்ட தலைப்புகளை பாதிப்பதில்லை. நீங்கள் [$2 this page] ஐ எப்போது வேண்டுமானாலும் பார்க்கலாம்",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Stop}} இந்த தலைப்பை பார்க்கிரார்",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|You}} இந்த பக்கத்தை பார்ப்பதில்லை \"$1\"",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|You}}, [$2 this page] ஐ எப்போது வேண்டுமானாலும் பார்க்கலாம்.",
+ "flow-skip-summary": "தவிர்",
"flow-history-action-delete-post": "நீக்கவும்",
"flow-history-action-hide-post": "மறைக்க",
- "flow-lock-topic-submit": "தலைப்பைப் பூட்டுக",
- "flow-unlock-topic-submit": "தலைப்பைத் திறக்கவும்",
"flow-topic-html-title": "$2ல் $1",
"flow-edited": "தொகுக்கப்பட்டது",
"flow-edited-by": "$1ஆல் தொகுக்கப்பட்டது",
diff --git a/Flow/i18n/tay.json b/Flow/i18n/tay.json
new file mode 100644
index 00000000..6fb401d4
--- /dev/null
+++ b/Flow/i18n/tay.json
@@ -0,0 +1,66 @@
+{
+ "@metadata": {
+ "authors": [
+ "Akamycoco",
+ "Translatealcd",
+ "Hitaypayan"
+ ]
+ },
+ "flow-topic-moderated-reason-prefix": "’ringan:",
+ "flow-post-actions": "Mmtzyuwaw",
+ "flow-topic-actions": "Mtzyuwaw",
+ "flow-cancel": "Laxan",
+ "flow-skip-summary": "Siy laxiy kya",
+ "flow-newtopic-title-placeholder": "Qiqas na kkayal",
+ "flow-newtopic-save": "Misan tnwang kkayal",
+ "flow-history-action-suppress-post": "qmhut",
+ "flow-history-action-delete-post": "’muyut",
+ "flow-history-action-hide-post": "smbbaq",
+ "flow-history-action-unhide-post": "laxiy lqingiy",
+ "flow-history-action-restore-post": "psbzih",
+ "flow-history-action-lock-topic": "kbalay",
+ "flow-post-action-suppress-post": "Qmhut",
+ "flow-post-action-delete-post": "’muyut",
+ "flow-post-action-hide-post": "Smbbaq",
+ "flow-post-action-edit-post": "smr’zyut miru’",
+ "flow-post-action-unhide-post": "Laxiy lqingiy",
+ "flow-post-action-restore-post": "Psbzih",
+ "flow-post-action-undo-moderation": "Psbzih",
+ "flow-topic-action-unlock-topic": "Gyahiy lawziy kkayal",
+ "flow-topic-action-summarize-topic": "Gnaygay lalu’",
+ "flow-topic-action-resummarize-topic": "Sr’zyut miru’ quw pinsr’tung sa kkayal",
+ "flow-topic-action-unhide-topic": "Lzxiy quw lnqing na kkayal",
+ "flow-topic-action-undelete-topic": "Laxiy quw aki’ llaxan na kkayal",
+ "flow-topic-action-unsuppress-topic": "Laxiy lquw qnihut sa kkayal",
+ "flow-topic-action-undo-moderation": "Psbzih",
+ "flow-topic-action-watchlist-add": "Pcyumung sa spzyang balay kktan qaniy",
+ "flow-error-protected-unknown-reason": "Ini’ bqbaqiy ginlaylwan",
+ "flow-rev-message-lock-topic-reason": "sinbbaq sa wayal sblazyun",
+ "flow-history-week": "Rihay wayal",
+ "flow-comment-restored": "Wal pbaynahun sa knayal sraral",
+ "flow-comment-deleted": "Inzyutan na knayal kay’",
+ "flow-comment-moderated": "Klhangan sa iyat niya’ kkhmut na knayal",
+ "flow-link-post": "skayal kwara’ squliq",
+ "flow-link-topic": "kkayal",
+ "flow-moderation-confirm-suppress-post": "Qmhut",
+ "flow-moderation-confirm-delete-post": "’muyut",
+ "flow-moderation-confirm-hide-post": "Smbbaq",
+ "flow-moderation-confirm-unhide-post": "Laxiy lqingiy",
+ "flow-moderation-confirm-suppress-topic": "Qmhut",
+ "flow-moderation-confirm-delete-topic": "’muyut",
+ "flow-moderation-confirm-hide-topic": "Smbbaq",
+ "flow-moderation-confirm-unhide-topic": "Laxiy lqingiy",
+ "flow-moderation-title-unsuppress-topic": "Laxiy lquw qnihut sa kkayal?",
+ "flow-moderation-title-undelete-topic": "Laxiy quw aki’ llaxan na kkayal?",
+ "flow-moderation-title-unhide-topic": "Lzxiy quw lnqing na kkayal?",
+ "flow-topic-count": "Kkayal ($1)",
+ "flow-special-type": "Gluw na mmntnaq",
+ "flow-previous-diff": "← Smural sinr’zyut miru’",
+ "flow-next-diff": "Giqas hazi’ na sinr’zyut miru’→",
+ "flow-undo": "Psbzih",
+ "flow-undo-edit-header": "Cyuw tmrang smr’zyut miru’ sa pinqzyuwan na’",
+ "flow-undo-edit-post": "Cyuw tmrang smr’zyut miru’ sa biru’ qnlah",
+ "flow-ve-mention-context-item-label": "Skayal",
+ "flow-ve-mention-inspector-remove-label": "Laxan",
+ "flow-mark-diff-patrolled-link-text": "Sinbbaq sa wayal gawzyagan mita’"
+}
diff --git a/Flow/i18n/te.json b/Flow/i18n/te.json
index cd0d18d0..756516bd 100644
--- a/Flow/i18n/te.json
+++ b/Flow/i18n/te.json
@@ -5,12 +5,11 @@
"Ravichandra",
"రహ్మానుద్దీన్",
"వైజాసత్య",
- "Praveen Illa"
+ "Praveen Illa",
+ "Veeven"
]
},
"flow-desc": "కార్యధార నిర్వహణా వ్యవస్థ",
- "flow-talk-taken-over": "ఈ పుట [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal Flow] ను వాడుతోంది.",
- "flow-talk-username": "ఫ్లో చర్చ పుట నిర్వాహకి",
"log-name-flow": "ఫ్లో చర్య లాగ్",
"logentry-delete-flow-delete-post": "$1 [[$6]] లో [[$3|$5]] లోని [$4 టపాను] {{GENDER:$2|తొలగించారు}}",
"flow-board-header-browse-topics-link": "అంశాలను చూడండి",
@@ -19,7 +18,7 @@
"flow-post-actions": "చర్యలు",
"flow-topic-actions": "చర్యలు",
"flow-cancel": "రద్దుచేయి",
- "flow-skip-summary": "సారాంశాన్ని దాటవేయి",
+ "flow-skip-summary": "దాటవేయి",
"flow-show-change": "తేడాలను చూపించు",
"flow-newtopic-title-placeholder": "కొత్త అంశం",
"flow-newtopic-header": "కొత్త అంశాన్ని చేర్చు",
@@ -84,5 +83,6 @@
"flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\" నొక్కడం ద్వారా, మీరు ఈ వికీ నియమాలను అంగీకరిస్తున్నారు.",
"flow-terms-of-use-reply": "\"{{int:flow-reply-link}}\" నొక్కడం ద్వారా, మీరు ఈ వికీ విధివిధానాలను అంగీకరిస్తున్నట్లు.",
"flow-terms-of-use-edit": "మీ మార్పులను భద్రపరచడం ద్వారా, మీరు ఈ వికీ విధివిధానాలను అంగీకరిస్తున్నట్లు.",
- "apihelp-flow+close-open-topic-param-moderationState": "విషయాన్ని ఉంచాల్సిన స్థితి, \"తాళంవేయి\" లేదా \"తాళంతీయి\"."
+ "flow-wikitext-switch-editor-tooltip": "విజువల్ ఎడిటర్ కు మారండి",
+ "flow-ve-switch-editor-tool-title": "సాధారణ వికీపాఠ్య ఎడిటర్ కు మారండి"
}
diff --git a/Flow/i18n/tg-cyrl.json b/Flow/i18n/tg-cyrl.json
new file mode 100644
index 00000000..2f283626
--- /dev/null
+++ b/Flow/i18n/tg-cyrl.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "AryanSogd",
+ "ToJack"
+ ]
+ },
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{ГЕНДЕР:$2|пок}} мавзӯъ оид ба [[$3]]",
+ "flow-show-change": "Намоиши тағйирот",
+ "flow-thank-link": "Ташаккур",
+ "flow-ve-mention-placeholder": "Номи корбар"
+}
diff --git a/Flow/i18n/tl.json b/Flow/i18n/tl.json
index 58220a31..94d37595 100644
--- a/Flow/i18n/tl.json
+++ b/Flow/i18n/tl.json
@@ -2,7 +2,8 @@
"@metadata": {
"authors": [
"Jewel457",
- "Leeheonjin"
+ "Leeheonjin",
+ "Emem.calist"
]
},
"flow-post-moderated-toggle-hide-show": "Ipakita ang pagpuna.",
@@ -12,6 +13,9 @@
"flow-post-moderated-toggle-suppress-hide": "Itago ang mungkahi",
"flow-post-action-post-history": "Kasaysayan",
"flow-post-action-edit-post": "Baguhin",
+ "flow-error-invalid-undelete": "Mukhang nagkakagulo, 'Wag ka munang umepal'. Balik ka na lang kapag tapos na ang mga diskusyon ng mga bossing.",
+ "notification-header-flow-enabled-on-talkpage": "Pinayagan ang bagong sistemang pantalakayan sa {{GENDER:$2|iyong}} usapang pahina",
+ "echo-pref-tooltip-flow-discussion": "Ipaalala sa akin ang mga kaganapan ng pinaguusapan o mga pahinang aking sinusundan.",
"flow-previous-diff": "← Mas lumang pagbabago",
"flow-next-diff": "Mas bagong pagbabago →"
}
diff --git a/Flow/i18n/tr.json b/Flow/i18n/tr.json
index c42921fd..857e061c 100644
--- a/Flow/i18n/tr.json
+++ b/Flow/i18n/tr.json
@@ -7,22 +7,51 @@
"Violetanka",
"Meelo",
"KorkmazO",
- "McAang"
+ "McAang",
+ "HakanIST",
+ "JackUKElliott",
+ "Macofe",
+ "Hbseren",
+ "Sadrettin",
+ "Vito Genovese",
+ "Bulgu"
]
},
"flow-board-header-browse-topics-link": "Konulara göz at",
"flow-topic-moderated-reason-prefix": "Sebep:",
+ "flow-stub-post-content": "<em>Teknik bir hata nedeniyle, bu yazı alınamadı.</em>",
"flow-newtopic-start-placeholder": "Yeni bir konu başlat",
- "flow-topic-action-lock-topic": "Konuyu kilitle",
+ "flow-post-action-edit-post": "Düzenle",
+ "flow-topic-action-lock-topic": "Çözümlendi olarak işaretle",
"flow-topic-action-unlock-topic": "Konunun kilidini aç",
"flow-topic-action-undo-moderation": "Geri alın",
"flow-board-notification-subscribe-description": "Bu tahtada yeni bir konu oluşturulduğunda bildirim alacaksınız.",
+ "flow-error-external": "Bir hata oluştu. Hata iletisi: $1",
"flow-error-lock-moderated-post": "Denetlenen bir yazıyı kilitleyemezsiniz.",
"flow-error-content-too-long": "İçerik çok büyük. Genişlemeden sonraki içerik $1 {{PLURAL:$1|byte|byte}}'la sınırlanmıştır.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 '''$3'başlığında yeni bir konu'{{GENDER:$1|oluşturdu}}'.",
+ "notification-header-flow-new-topic-v2": "<strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi> konusunda yeni bir başlık yaratıldı.",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> konusunda $1 yeni {{PLURAL:$1|topic|topics}}.",
+ "notification-header-flow-new-topic-user-talk": "<strong>sizin tartışma sayfanızda</strong>: \"<strong>$4</strong>\" konusunda yeni bir başlık yaratıldı.",
+ "notification-bundle-header-flow-new-topic-user-talk": "<strong>Sizin tartışma sayfanızda</strong> $1 yeni {{PLURAL:$1|başlık|başlıklar}}.",
+ "notification-header-flow-post-reply": "\"<strong>$4</strong>\" konusunda $1 {{GENDER:$2|kişisi cevapladı}}.",
+ "notification-bundle-header-flow-post-reply-v2": "\"<strong>$3</strong>\" tanımında $1 yeni {{ÇOĞUL:$1|cevap|cevaplar}}.",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2 tartışma sayfasında|senin tartışma sayfanda}} </strong> \"<strong>$1</strong>\" konusunda bir mesaj düzenlendi.",
+ "notification-bundle-header-flow-post-edited-user-talk": "\"<strong>$1</strong>\" konusunda bir başlık <strong>{{GENDER:$2|senin}} tartışma sayfanda</strong> bir çok defa değiştirildi.",
+ "notification-header-flow-summary-edited": "\"<strong>$1</strong>\" konusunun özeti güncellendi.",
+ "notification-header-flow-summary-edited-first": "\"<strong>$1</strong>\" konusu özetlenmiştir.",
+ "notification-bundle-header-flow-summary-edited": "\"<strong>$1</strong>\" konusunun özeti birden çok defa güncellendi.",
+ "notification-header-flow-mention-post": "<strong>$5</strong> tanımında, $1 {{GENDER:$2|kişisi}} {{GENDER:$4|sizden}} bahsetti.",
+ "notification-header-flow-mention-header": "<strong>$3</strong> tanımında, $1 {{GENDER:$2|kişisi}} {{GENDER:$4|sizden}} bahsetti.",
+ "notification-header-flow-mention-post-summary": "$1, \"<strong>$5</strong>\" içinde {{GENDER:$4|sizden}} {{GENDER:$2|bahsetti}}.",
+ "notification-header-flow-enabled-on-talkpage": "Yeni konuşma sistemi, <strong>{{GENDER:$2|Kullanıcı}} mesaj sayfanız</strong> için etkinleştirildi.",
+ "notification-header-flow-description-edited": "<strong>$1</strong> tanımı düzenlendi.",
+ "notification-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|sizin}} tartışma sayfanızdaki</strong> tanım değiştirildi.",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong> tanımı birden fazla defa düzenlendi.",
+ "notification-bundle-header-flow-description-edited-user-talk": "<strong>{{GENDER:$2|sizin}} tartışma sayfanızdaki</strong> tanım birden çok defa değiştirildi.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 <strong>$3</strong> başlığında yeni bir konu'{{GENDER:$1|oluşturdu}}'.",
"flow-notification-mention": "$1, \"$4\" sayfasındaki \"$3\" başlığındaki [$2 değişikliğinde] sizden {{GENDER:$1|bahsetti}}",
"flow-notification-mention-email-subject": "$1, $2 sayfasında sizden {{GENDER:$1|bahsetti}}",
- "flow-notification-mention-email-batch-body": "$1, \"$3\" sayfasındaki \"$2\" başlığında sizden {{GENDER:$1|bahsetti}}",
+ "flow-notification-mention-email-batch-body": "$1, \"$3\" sayfasındaki \"$2\" başlığında {{GENDER:$4|sizden}} {{GENDER:$1|bahsetti}}",
"flow-link-history": "geçmiş",
"flow-moderation-confirmation-suppress-topic": "Bu konu askıya alınmıştır.",
"flow-moderation-confirmation-delete-topic": "Bu konu silindi.",
@@ -30,6 +59,13 @@
"flow-anon-warning": "Oturum açmadınız.",
"flow-topic-html-title": "$1 sayfa $2",
"flow-special-enableflow-invalid-title": "Geçersiz bir sayfa başlığı girildi",
+ "flow-importer-lqt-converted-archive-template-content": "Bu sayfa arşivlenmiş LiquidThreads sayfasıdır. <strong>Bu sayfanın içeriğini düzenlemeyiniz</strong>. Lütfen başka bir yorumunuz varsa [[{{{from}}}|güncel tartışma sayfası]] ile iletişime geçiniz.",
+ "flow-importer-wt-converted-archive-template-content": "Bu sayfa arşivlenmiş bir sayfadır. <strong>Bu sayfanın içeriğini düzenlemeyiniz</strong>. Lütfen başka bir yorumunuz varsa [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|güncel tartışma sayfası]] ile iletişime geçiniz.",
+ "group-flow-bot-member": "Flow botu",
"flow-ve-mention-placeholder": "Kullanıcı adı",
+ "flow-wikitext-switch-editor-tooltip": "Görsel düzenleyiciye geç",
+ "flow-ve-switch-editor-tool-title": "Wikimetin editörüne geç",
+ "flow-notification-link-text-enabled-on-talkpage": "Kullanıcı mesaj sayfasını {{GENDER:|görüntüle}}",
+ "flow-beta-feature-add-archive-template-edit-summary": "Arşiv şablonu ekleme",
"flow-dialog-cancelconfirm-message": "Kaydetmeden iptal etmek istediğinizden emin misiniz?"
}
diff --git a/Flow/i18n/tt-cyrl.json b/Flow/i18n/tt-cyrl.json
new file mode 100644
index 00000000..e6261214
--- /dev/null
+++ b/Flow/i18n/tt-cyrl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ильнар"
+ ]
+ },
+ "echo-category-title-flow-discussion": "Агым",
+ "structureddiscussions": "Структуралы бәхәс",
+ "group-flow-bot": "Агым ботлары",
+ "flow-dialog-cancelconfirm-keep": "Үзгәртүне дәвам итү"
+}
diff --git a/Flow/i18n/udm.json b/Flow/i18n/udm.json
new file mode 100644
index 00000000..a76eab9a
--- /dev/null
+++ b/Flow/i18n/udm.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaganer"
+ ]
+ },
+ "flow-dialog-cancelconfirm-keep": "Тупатъянэз азьланьтоно"
+}
diff --git a/Flow/i18n/uk.json b/Flow/i18n/uk.json
index 025f1d51..771b81e8 100644
--- a/Flow/i18n/uk.json
+++ b/Flow/i18n/uk.json
@@ -10,24 +10,53 @@
"Капитан Джон Шепард",
"Piramidion",
"Lxlalexlxl",
- "Dars"
+ "Dars",
+ "Nnemo",
+ "Quiddity",
+ "Green Zero",
+ "Visem",
+ "Macofe"
]
},
- "enableflow": "Увімкнути Flow",
- "flow-desc": "Система управління робочими процесами",
- "log-name-flow": "Журнал активності потоку",
+ "enablestructureddiscussions": "Увімкнути Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|Припинити}} спостерігати за новою діяльністю на «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|Ви}} більше не спостерігаєте за сторінкою «$1»",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Це не вплине на окремі теми, за якими {{GENDER:$3|Ви}} спостерігаєте. Ви можете додати [$2 цю сторінку] до списку спостереження будь-коли.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|Припинити}} спостерігати за цією темою",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|Ви}} більше не спостерігаєте за «$1»",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|Ви}} можете додати [$2 цю тему] до списку спостереження будь-коли.",
+ "flow-desc": "Система обговорення",
+ "flow-talk-taken-over-comment": "/* Ця сторінка була перетворена на стіну структурованих обговорень */",
+ "log-name-flow": "Журнал активності структурованих обговорень",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2|вилучив|вилучила}} [$4 допис] у «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2|вилучив|вилучила}} допис у темі на сторінці [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2|відновив|відновила}} [$4 допис] у «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|відновив|відновила}} допис у темі на сторінці [[$3]]",
"logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|прибрав|прибрала}} [$4 допис] у «[[$3|$5]]» на [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2|приховав|приховала}} допис у темі на сторінці [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|вилучив|вилучила}} [$4 допис] у «[[$3|$5]]» на [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2|вилучив|вилучила}} допис у темі на сторінці [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|вилучив|вилучила}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2|вилучив|вилучила}} тему на сторінці [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|відновив|відновила}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|відновив|відновила}} тему на сторінці [[$3]]",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|прибрав|прибрала}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2|приховав|приховала}} тему на сторінці [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|вилучив|вилучила}} тему «[[$3|$5]]» на [[$6]]",
- "logentry-import-lqt-to-flow-topic": "[[$1|$2]] на [[$3]] було імпортовано з LiquidThreads у Flow",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|вилучив|вилучила}} тему на сторінці [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|позначив|позначила}} тему «[[$3|$5]]» як вирішену на [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2|позначив|позначила}} тему як вирішену на сторінці [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 повторно {{GENDER:$2|відкрив|відкрила}} тему «[[$3|$5]]» на [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2|відкрив|відкрила}} повторно тему на сторінці [[$3]]",
+ "logentry-import-lqt-to-flow-topic": "[[$1|$2]] на [[$3]] було імпортовано з LiquidThreads у структуровані обговорення",
+ "abusefilter-edit-builder-vars-board-articleid": "Ідентифікатор сторінки зі стіною структурованих обговорень",
+ "abusefilter-edit-builder-vars-board-namespace": "Простір назв стіни структурованих обговорень",
+ "abusefilter-edit-builder-vars-board-text": "Назва стіни структурованих обговорень",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Повна назва стіни структурованих обговорень",
"flow-user-moderated": "Обмежений користувач",
"flow-board-header-browse-topics-link": "Огляд тем",
- "flow-board-header": "Про цю дошку",
+ "flow-board-header": "Про цю стіну",
+ "flow-board-description-can-not-edit": "Не можна редагувати",
"flow-board-collapse-description": "Приховати опис",
"flow-board-expand-description": "Показати опис",
"flow-topic-collapse-siderail": "Читати у повну ширину",
@@ -53,23 +82,25 @@
"flow-post-actions": "Дії",
"flow-topic-actions": "Дії",
"flow-cancel": "Скасувати",
- "flow-skip-summary": "Пропустити короткий опис",
- "flow-edit-summary-placeholder": "Коротко опишіть підсумок цього обговорення",
- "flow-summary-authored": "Короткий опис зроблений $1",
+ "flow-skip-summary": "Пропустити",
+ "flow-edit-summary-placeholder": "Коротко опишіть результати цього обговорення",
+ "flow-summary-authored": "Підсумок підбитий $1",
"flow-summary-edited": "Підсумок востаннє {{GENDER:$1|редагував|редагувала}} $1",
"flow-show-change": "Показати зміни",
"flow-last-modified-by": "Востаннє {{GENDER:$1|змінив|змінила}} $1",
- "flow-stub-post-content": "''Через технічну помилку цей допис не міг бути отриманим.''",
+ "flow-stub-post-content": "<em>Через технічну помилку цей контент не вдалося отримати.</em>",
"flow-newtopic-title-placeholder": "Нова тема",
"flow-newtopic-content-placeholder": "Розмістити нове повідомлення на «$1»",
"flow-newtopic-header": "Додати нову тему",
"flow-newtopic-save": "Додати тему",
+ "flow-newtopic-save-anonymously": "Додати тему анонімно",
"flow-newtopic-start-placeholder": "Почати нову тему",
"flow-newtopic-first-heading": "Почати нову тему на $1",
"flow-summarize-topic-placeholder": "Будь ласка, підсумуйте це обговорення",
"flow-reply-topic-placeholder": "{{GENDER:$1|Коментувати}} на \"$2\"",
"flow-reply-topic-title-placeholder": "Відповісти на «$1»",
"flow-reply-link": "{{GENDER:$1|Відповісти}}",
+ "flow-reply-link-anonymously": "Відповісти анонімно",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|Подякувати}}}}",
"flow-thank-link-title": "Публічно {{GENDER:$1|{{GENDER:$2|подякувати}}}} авторові допису",
"flow-history-action-suppress-post": "прибрати",
@@ -80,7 +111,7 @@
"flow-history-action-unhide-post": "скасувати приховування",
"flow-history-action-restore-post": "відновити",
"flow-history-action-lock-topic": "позначити вирішеним",
- "flow-history-action-unlock-topic": "відновити",
+ "flow-history-action-unlock-topic": "відкрити повторно",
"flow-post-edited": "Допис {{GENDER:$1|відредагував|відредагувала}} $1 $2",
"flow-post-action-view": "Постійне посилання",
"flow-post-action-post-history": "Історія",
@@ -89,6 +120,7 @@
"flow-post-action-hide-post": "Приховати",
"flow-post-action-edit-post": "Редагувати",
"flow-post-action-edit-post-submit": "Зберегти зміни",
+ "flow-post-action-edit-post-submit-anonymously": "Зберегти зміни анонімно",
"flow-post-action-unsuppress-post": "Висвітити",
"flow-post-action-undelete-post": "Відновити",
"flow-post-action-unhide-post": "Відобразити",
@@ -100,11 +132,11 @@
"flow-topic-action-history": "Історія",
"flow-topic-action-hide-topic": "Приховати тему",
"flow-topic-action-delete-topic": "Видалити тему",
- "flow-topic-action-lock-topic": "Позначити як вирішене",
+ "flow-topic-action-lock-topic": "Позначити як вирішену",
"flow-topic-action-unlock-topic": "Відкрити тему знову",
"flow-topic-action-summarize-topic": "Підсумувати",
"flow-topic-action-resummarize-topic": "Редагувати підсумок теми",
- "flow-topic-action-update-topic-summary": "Оновити опис",
+ "flow-topic-action-update-topic-summary": "Оновити підсумок",
"flow-topic-action-suppress-topic": "Прибрати тему",
"flow-topic-action-unhide-topic": "Відобразити тему",
"flow-topic-action-undelete-topic": "Відновити тему",
@@ -113,31 +145,32 @@
"flow-topic-action-undo-moderation": "Повернути",
"flow-topic-notification-subscribe-title": "Ця тема була додана у {{GENDER:$1|Ваш}} список спостереження.",
"flow-topic-notification-subscribe-description": "{{GENDER:$1|Ви}} будете отримувати сповіщення про будь-яку активність у цій темі.",
- "flow-board-notification-subscribe-title": "{{GENDER:$1|Ви}} підписалися на цю дошку обговорень!",
- "flow-board-notification-subscribe-description": "{{GENDER:$1|Ви}} отримаєте сповіщення при створенні нової теми на цій дошці.",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|Ви}} підписалися на цю стіну обговорень!",
+ "flow-board-notification-subscribe-description": "{{GENDER:$1|Ви}} отримаєте сповіщення при створенні нової теми на цій стіні.",
"flow-topic-action-watchlist-add": "Підписатися на цю тему",
"flow-topic-action-watchlist-remove": "Відписатися",
- "flow-error-allowcreation-no-usedb": "allowCreation вимагає <var>$wgContentHandlerUseDB</var> зі значенням <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Сторінка вже існує, хоча не має",
+ "flow-error-allowcreation-no-usedb": "Увімкнення структурованих обговорень на конкретній сторінці вимагає <var>$wgContentHandlerUseDB</var> зі значенням <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Сторінка вже існує у вказаному місці, тож стіну структурованих обговорень не можна перемістити туди.",
"flow-error-allowcreation-flow-create-board": "Користувач не має права «{{int:right-flow-create-board}}»",
+ "flow-error-can-not-edit-logged-out": "Наразі Ви не можете брати участь. Ви можете спробувати ввійти до системи.",
+ "flow-error-can-not-edit-logged-in": "Ви наразі не можете брати участь, бо Ви не маєте необхідних прав.",
"flow-error-http": "Сталася помилка при зверненні до сервера.",
- "flow-error-other": "Трапилася неочікувана помилка.",
- "flow-error-external": "Сталася помилка.<br />Отримане повідомлення було:$1",
+ "flow-error-external": "Сталася помилка. Отримане повідомлення було:$1",
"flow-error-topic-is-locked": "Ця тема позначена як вирішена, тож подальші дії неможливі.",
"flow-error-lock-moderated-post": "Ви не можете позначити модерований допис як вирішений.",
- "flow-error-external-multi": "Виявлені помилки.<br /> $1",
"flow-error-missing-content": "Публікація не має ніякого вмісту. Необхідний вміст, щоб зберегти публікацію.",
- "flow-error-missing-summary": "Ви маєте надати резюме.",
+ "flow-error-missing-summary": "Ви маєте написати підсумок.",
"flow-error-missing-title": "Тема не має назви. Потрібна назва, щоб зберегти тему.",
- "flow-error-parsoid-failure": "Не вдалося проаналізувати вміст через помилку Parsoid.",
- "flow-error-missing-replyto": "Параметр „reply-to“ не був наданий. Цей параметр є обов'язковим для дії \"відповідь\".",
- "flow-error-invalid-replyto": "Параметр „replyTo“ неприпустимий. Не вдалося знайти вказану публікацію.",
- "flow-error-delete-failure": "Не вдалося видалити цей елемент.",
- "flow-error-hide-failure": "Приховання цього елементу не вдалося.",
+ "flow-error-parsoid-failure": "Не вдалося перенести вміст: помилка з'єднання з сервером для конвертації між вікірозміткою та HTML. Будь ласка, перевірте своє з'єднання з інтернетом або спробуйте пізніше, якщо проблема все ще існуватиме. Якщо Ви й надалі отримуватимете це повідомлення про помилку, будь ласка, повідомте про баг",
+ "flow-error-protected-autoconfirmed-logged-in": "Ця стіна є захищеною. Лише автопідтверджені користувачі можуть брати участь. Причина: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Ця стіна є захищеною. Лише користувачі, що ввійшли до системи та є автопідтвердженими можуть брати участь. Причина: $1",
+ "flow-error-protected-sysop-logged-in": "Ця стіна є захищеною. Лише користувачі з правами адміністратора можуть брати участь. Причина: $1",
+ "flow-error-protected-sysop-logged-out": "Ця стіна є захищеною. Лише користувачі, що ввійшли до системи, які мають права адміністратора, можуть брати участь. Причина: $1",
+ "flow-error-protected-unknown-reason": "Невідома",
+ "flow-error-missing-replyto": "Параметр «відповісти на» не був наданий. Цей параметр є обов'язковим для дії «відповісти».",
"flow-error-missing-postId": "Параметр „postId“ не був наданий. Цей параметр вимагає, щоб маніпулювати публікацією.",
"flow-error-invalid-postId": "Параметр „postId“ неприпустимий. Не вдалося знайти вказану публікацію ($1).",
- "flow-error-restore-failure": "Не вдалося виконати відновлення цього елемента.",
- "flow-error-invalid-moderation-state": "Для Flow API було подано неприпустиме значення параметра ('moderationState').",
+ "flow-error-invalid-moderation-state": "Для API структурованих обговорень було подано неприпустиме значення параметра ('moderationState').",
"flow-error-invalid-moderation-reason": "Будь ласка, вкажіть причину для модерації",
"flow-error-not-allowed": "Недостатні дозволи для виконання цієї дії",
"flow-error-not-allowed-hide": "Цю тему приховано.",
@@ -158,17 +191,19 @@
"flow-error-missing-prev-revision-identifier": "Ідентифікатор попередньої ревізії відсутній.",
"flow-error-prev-revision-mismatch": "Цей допис саме кілька секунд тому був відредагований іншим користувачем. {{GENDER:$3|Ви}} справді бажаєте перезаписати останні зміни?",
"flow-error-prev-revision-does-not-exist": "Не вдалося знайти попередню ревізію.",
- "flow-error-core-topic-deletion": "Аби вилучити тему, використовуйте меню ... на дошці Flow або на [$1 сторінці теми]. Не переходьте безпосередньо на action=delete для цієї теми.",
+ "flow-error-core-topic-deletion": "Аби вилучити тему, використовуйте меню ... на стіні структурованих обговорень або на [$1 сторінці теми]. Не переходьте безпосередньо на action=delete для цієї теми.",
"flow-error-default": "Сталася помилка.",
- "flow-error-invalid-input": "Неприпустиме значення було надано для завантаження потоку даних.",
+ "flow-error-invalid-input": "Для завантаження контенту структурованих обговорень було надано недійсне значення.",
"flow-error-invalid-title": "Надана невірна сторінка заголовку.",
+ "flow-error-invalid-parameter": "Відсутній або недійсний параметр для виклику методу",
"flow-error-fail-load-history": "Не вдалося завантажити зміст історії.",
- "flow-error-missing-revision": "Не вдалося знайти редакцію для завантаження вмісту потоку.",
- "flow-error-fail-commit": "Не вдалося зберегти вміст потоку.",
+ "flow-error-missing-revision": "Не вдалося знайти редакцію для завантаження вмісту структурованих обговорень.",
+ "flow-error-fail-commit": "Не вдалося зберегти вміст структурованих обговорень.",
"flow-error-insufficient-permission": "Недостатньо прав для доступу до вмісту.",
"flow-error-revision-comparison": "Операції порівняння може бути зроблена лише для двох ревізій, що належать й того ж допису.",
"flow-error-missing-topic-title": "Не вдалося знайти назву теми для поточного робочого циклу.",
"flow-error-missing-metadata": "Не вдалось знайти необхідні метадані для цієї версії.",
+ "flow-error-different-page": "Робочий процес структурованих обговорень не пов'язаний із цією сторінкою.",
"flow-error-fail-load-data": "Не вдалося завантажити запитані дані.",
"flow-error-invalid-workflow": "Не вдалося знайти запитаний робочий процес.",
"flow-error-process-data": "Сталася помилка під час обробки даних у вашому запиті.",
@@ -178,16 +213,19 @@
"flow-error-no-commit": "Зазначену дію не вдалося зберегти.",
"flow-error-content-too-long": "Вміст завеликий. Довжина після маркування обмежена $1 {{PLURAL:$1|байтом|байтами}}.",
"flow-error-move-topic": "Перейменування сторінки теми наразі не підтримується.",
- "flow-error-move-no-create-permissions": "Необхідне право «{{int:right-flow-create-board}}» для перейменування Flow-дошки.",
"flow-error-invalid-topic-uuid-title": "Неприпустима назва",
- "flow-error-invalid-topic-uuid": "Запитувана назва сторінки є неприпустимою. Сторінки в просторі назв ''Topic'' створюються автоматично через Flow.",
+ "flow-error-invalid-topic-uuid": "Запитувана назва сторінки є неприпустимою. Сторінки в просторі назв ''Topic'' створюються автоматично через Структуровані обговорення.",
"flow-error-unknown-workflow-id-title": "Невідома тема",
"flow-error-unknown-workflow-id": "Запитувана тема не існує.",
"flow-error-search": "Нам не вдалося завершити ваш пошук через тимчасову проблему. Спробуйте ще раз пізніше.",
- "flow-edit-header-placeholder": "Опишіть цю дошку обговорень",
+ "flow-error-invalid-undelete": "Сторінку не вдалося відновити, оскільки на її місці перебуває стіна обговорення.",
+ "flow-edit-header-placeholder": "Опишіть цю стіну обговорень",
"flow-edit-header-submit": "Зберегти опис",
+ "flow-edit-header-submit-anonymously": "Зберегти опис анонімно",
"flow-edit-title-submit": "Змінити заголовок",
+ "flow-edit-title-submit-anonymously": "Змінити заголовок анонімно",
"flow-edit-post-submit": "Подати зміни",
+ "flow-edit-post-submit-anonymously": "Зберегти зміни анонімно",
"flow-rev-message-edit-post": "$1 {{GENDER:$2|відредагував|відредагувала}} [$3 коментар] у темі «$4»",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|Відредагував|Відредагувала}} допис",
"flow-rev-message-reply": "$1 [$3 прокоментува{{GENDER:$2|в|ла}}] тему «$4» (<em>$5</em>)",
@@ -206,14 +244,14 @@
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|приховав|приховала}} [$4 тему] «$6» (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|вилучив|вилучила}} [$4 тему] «$6» (<em>$5</em>)",
"flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|прибрав|прибрала}} [$4 тему] «$6» (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|позначив|позначила}} [$4 тему] $6 як вирішену (<em>$5</em>)",
- "flow-rev-message-lock-topic-reason": "позначено як вирішене",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|позначив|позначила}} [$4 тему] \"$6\" як вирішену (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "позначено як вирішену",
"flow-rev-message-restore-topic-reason": "відкрито повторно",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2|відновив|відновила}} [$4 тему] «$6»(<em>$5</em>)",
"flow-rc-topic-of-board": "$1 на $2",
"flow-board-history": "Історія \"$1\"",
- "flow-board-history-empty": "Ця дошка в даний час не має історії.",
- "flow-topic-history": "Історія теми \"$1\"",
+ "flow-board-history-empty": "Ця стіна наразі не має історії.",
+ "flow-topic-history": "Історія теми «$1»",
"flow-post-history": "Історія дописів «Коментар {{GENDER:$2|$2}}»",
"flow-history-last4": "Останні 4 години",
"flow-history-day": "Сьогодні",
@@ -229,31 +267,73 @@
"flow-comment-moderated": "Модерований коментар",
"flow-last-modified": "Остання зміна про $1",
"flow-workflow": "робочий процес",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|відповів|відповіла}} на '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 та $5 {{PLURAL:$6|інший|інші|інших}} {{GENDER:$1|відповіли}} на '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1|відповів|відповіла}} на <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 та {{PLURAL:$5|$5 інший|$5 інші|$5 інших|1=один інший|100=99+ інших}} {{GENDER:$1|відповіли}} на <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|відредагував|відредагувала}} Ваш <span class=\"plainlinks\">[$5 допис]</span> на [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 та $5 {{PLURAL:$6|інший|інші|інших}} {{GENDER:$1|відредагував|відредагувала}} <span class=\"plainlinks\">[$4 допис]</span> у $2 на \"$3\".",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|створив|створила}} нову тему на '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 нова тема|$1 нові теми|$1 нових тем|250=250+ нових тем}} на '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 та {{PLURAL:$5|$5 інший|$5 інші|$5 інших|1=один інший|100=99+ інших}} {{GENDER:$1|відредагував|відредагувала}} <span class=\"plainlinks\">[$4 допис]</span> у $2 на «$3».",
+ "notification-header-flow-new-topic-v2": "Створена нова тема на '''$3''': <bdi>«'''$4'''»</bdi>.",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Одна нова тема|$1 нові теми|$1 нових тем|100=99+ нових тем}} на <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Створена нова тема на <strong>Вашій сторінці обговорення</strong>: «<strong>$4</strong>».",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Одна нова тема|$1 нові теми|$1 нових тем|100=99+ нових тем}} на <strong>Вашій сторінці обговорення</strong>.",
+ "notification-header-flow-post-reply": "$1 {{GENDER:$2|відповів|відповіла}} у «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Одна нова відповідь|$1 нові відповіді|$1 нових відповідей|100=99+ нових відповідей}} у «<strong>$3</strong>».",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2|опублікував|опублікувала}} відповідь на <strong>Вашій сторінці обговорення</strong> у «<strong>$4</strong>».",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Одна нова відповідь|$1 нові відповіді|$1 нових відповідей|100=99+ новий відповідей}} на <strong>Вашій сторінці обговорення</strong> у «<strong>$3</strong>».",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|Ваше}} повідомлення у «<strong>$1</strong>» було відредаговано.",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|Ваше}} повідомлення у «<strong>$1</strong>» було відредаговано кілька разів.",
+ "notification-header-flow-post-edited-user-talk": "Повідомлення у «<strong>$1</strong>» було відредаговане на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Повідомлення у «<strong>$1</strong>» було відредаговане кілька разів на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Тему «<strong>$1</strong>» було перейменовано на «<strong>$2</strong>».",
+ "notification-header-flow-topic-renamed-user-talk": "На <strong>{{GENDER:$3|Вашій}} сторінці обговорення</strong> тему «<strong>$1</strong>» було перейменовано на «<strong>$2</strong>».",
+ "notification-header-flow-summary-edited": "Підсумок до «<strong>$1</strong>» було оновлено.",
+ "notification-header-flow-summary-edited-first": "Тему «<strong>$1</strong>» було підсумовано.",
+ "notification-bundle-header-flow-summary-edited": "Підсумок до «<strong>$1</strong>» було оновлено декілька разів.",
+ "notification-header-flow-summary-edited-user-talk": "Підсумок до «<strong>$1</strong>» було оновлено на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Тему «<strong>$1</strong>» було підсумовано на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Підсумок до «<strong>$1</strong>» було оновлено декілька разів на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 {{GENDER:$1|оновив|оновила}} підсумок теми $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 {{GENDER:$1|оновив|оновила}} підсумок теми $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 і {{PLURAL:$3|$3 інший|$3 інші|$3 інших|1=один інший|100=99+ інших}} {{GENDER:$1|оновили}} підсумок теми $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2|згадав|згадала}} {{GENDER:$4|Вас}} у «<strong>$5</strong>».",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2|згадав|згадала}} {{GENDER:$4|Вас}} в описі <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|згадав|згадала}} {{GENDER:$4|Вас}} у «<strong>$5</strong>».",
+ "notification-header-flow-enabled-on-talkpage": "Нова система обговорень увімкнена для <strong>{{GENDER:$2|Вашої}} сторінки обговорення користувача</strong>.",
+ "notification-header-flow-description-edited": "Опис <strong>$1</strong> було відредаговано.",
+ "notification-header-flow-description-edited-user-talk": "Опис було відредаговано на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-bundle-header-flow-description-edited": "Опис <strong>$1</strong> був відредагований кілька разів.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Опис було відредаговано кілька разів на <strong>{{GENDER:$2|Вашій}} сторінці обговорення</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|Переглянути}} сторінку",
+ "notification-email-subject-flow-description-edited": "$1 {{GENDER:$1|відредагував|відредагувала}} опис на $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 {{GENDER:$1|відредагував|відредагувала}} опис на $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 та {{PLURAL:$3|$3 інший|$3 інші|$3 інших|1=один інший|100=99+ інших}} {{GENDER:$1|відредагували}} опис на $2",
+ "notification-header-flow-topic-resolved": "Тему «<strong>$1</strong>» було вирішено.",
+ "notification-header-flow-topic-reopened": "Тему «<strong>$1</strong>» було повторно відкрито.",
+ "notification-header-flow-topic-resolved-user-talk": "Тему «<strong>$1</strong>» було вирішено на <strong>Вашій сторінці обговорення</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Тему «<strong>$1</strong>» було повторно відкрито на <strong>Вашій сторінці обговорення</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Тему «<strong>$2</strong>» було вирішено.",
+ "notification-email-batch-body-flow-topic-resolved": "Тему «<strong>$2</strong>» було вирішено.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|створив|створила}} нову тему на <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1 нова тема|$1 нові теми|$1 нових тем|1=Одна нова тема|100=99+ нових тем}} на <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 {{GENDER:$1|змінив|змінила}} назву <span class=\"plainlinks\">[$2 $3]</span> на \"$4\" у [[$5|$6]]",
"flow-notification-mention": "$1 {{GENDER:$1|згадав|згадала}} {{GENDER:$5|вас}} у {{GENDER:$1|своєму}} <span class=\"plainlinks\">[$2 дописі]</span> у \"$3\" на \"$4\".",
"flow-notification-link-text-view-post": "Переглянути допис",
- "flow-notification-link-text-view-topic": "Перегляд теми",
+ "flow-notification-link-text-view-topic": "Переглянути тему",
+ "flow-notification-link-text-view-topics": "Переглянути теми",
"flow-notification-reply-email-subject": "$2 на $3",
"flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|відповів|відповіла}} у «$2» на $3.",
- "flow-notification-reply-email-batch-bundle-body": "$1 та $4 {{PLURAL:$5|інший|інші|інших}} {{GENDER:$1|відповіли}} у «$2» на $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 та {{PLURAL:$4|$4 інший|$4 інші|$4 інших|1=один інший|100=99+інших}} {{GENDER:$1|відповіли}} у «$2» на $3",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|згадав|згадала}} {{GENDER:$3|Вас}} на $2",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|згадав|згадала}} {{GENDER:$4|Вас}} у {{GENDER:$1|своєму}} дописі у «$2» на $3",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|відредагував|відредагувала}} допис",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|відредагував|відредагувала}} допис у «$2» на $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 та $4 {{PLURAL:$5|інший|інші|інших}} {{GENDER:$1|відредагував|відредагувала}} допис у «$2» на $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 та {{PLURAL:$4|$4 інший|$4 інші|$4 інших|1=один інший|100=99+ інших}} {{GENDER:$1|відредагували}} допис у «$2» на $3",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|перейменував|перейменувала}} Вашу тему",
"flow-notification-rename-email-batch-body": "$1 {{GENDER:$1|перейменував|перейменувала}} Вашу тему з «$2» на «$3» у $4",
"flow-notification-newtopic-email-subject": "$1 {{GENDER:$1|створив|створила}} нову тему на $2",
"flow-notification-newtopic-email-batch-body": "$1 {{GENDER:$1|створив|створила}} нову тему під назвою «$2» на $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 нова тема|$1 нові теми|$1 нових тем|250=250+ нових тем}} на $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Повідомляти, коли у Flow відбуваються дії, пов'язані зі мною.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1 нова тема|$1 нові теми|$1 нових тем|1=Одна нова тема|100=99+ нових тем}} на $2",
+ "echo-category-title-flow-discussion": "Структуроване обговорення",
+ "echo-pref-tooltip-flow-discussion": "Повідомляти мене про активність у темах чи на сторінках, за якими я спостерігаю.",
"flow-link-post": "допис",
"flow-link-topic": "тема",
"flow-link-history": "історія",
@@ -285,18 +365,18 @@
"flow-moderation-confirm-unsuppress-topic": "Висвітити",
"flow-moderation-confirm-undelete-topic": "Відновити",
"flow-moderation-confirm-unhide-topic": "Відобразити",
- "flow-moderation-confirmation-suppress-post": "Допис успішно усунено.\nРозгляньте відгук {{GENDER:$2|наданий}} $1 на цей допис.",
- "flow-moderation-confirmation-delete-post": "Цей допис успішно вилучено.\nРозгляньте відгук, {{GENDER:$2|наданий}} $1, на цей допис.",
- "flow-moderation-confirmation-hide-post": "Цей допис успішно приховано.\nРозгляньте відгук, {{GENDER:$2|наданий}} $1, на цей допис.",
- "flow-moderation-confirmation-unsuppress-post": "Ви успішно відновили допис вище.",
- "flow-moderation-confirmation-undelete-post": "Ви успішно відновили публікацію вище.",
- "flow-moderation-confirmation-unhide-post": "Ви успішно показали публікацію вище.",
+ "flow-moderation-confirmation-suppress-post": "Допис усунено.\nРозгляньте відгук, {{GENDER:$2|наданий}} $1 на цей допис.",
+ "flow-moderation-confirmation-delete-post": "Цей допис вилучено.\nРозгляньте відгук, {{GENDER:$2|наданий}} $1, на цей допис.",
+ "flow-moderation-confirmation-hide-post": "Цей допис приховано.\nРозгляньте відгук, {{GENDER:$2|наданий}} $1, на цей допис.",
+ "flow-moderation-confirmation-unsuppress-post": "Ви відновили допис вище.",
+ "flow-moderation-confirmation-undelete-post": "Ви відновили публікацію вище.",
+ "flow-moderation-confirmation-unhide-post": "Ви показали публікацію вище.",
"flow-moderation-confirmation-suppress-topic": "Ця тема успішно усунена.",
"flow-moderation-confirmation-delete-topic": "Тему успішно вилучено.",
"flow-moderation-confirmation-hide-topic": "Тему успішно приховано.",
- "flow-moderation-confirmation-unsuppress-topic": "Ви успішно відновили цю тему.",
- "flow-moderation-confirmation-undelete-topic": "Ви успішно відновили цю тему.",
- "flow-moderation-confirmation-unhide-topic": "Ви успішно показали цю тему.",
+ "flow-moderation-confirmation-unsuppress-topic": "Ви відновили цю тему.",
+ "flow-moderation-confirmation-undelete-topic": "Ви відновили цю тему.",
+ "flow-moderation-confirmation-unhide-topic": "Ви показали цю тему.",
"flow-moderation-title-suppress-topic": "Прибрати тему?",
"flow-moderation-title-delete-topic": "Видалити тему?",
"flow-moderation-title-hide-topic": "Приховати тему?",
@@ -310,7 +390,7 @@
"flow-moderation-placeholder-undelete-topic": "Будь ласка, {{GENDER:$3|поясніть}}, чому Ви скасовуєте вилучення цієї теми.",
"flow-moderation-placeholder-unhide-topic": "Будь ласка, {{GENDER:$3|поясніть}}, чому Ви скасовуєте приховування цієї теми.",
"flow-topic-permalink-warning": "Ця тема розпочата [$2 $1]",
- "flow-topic-permalink-warning-user-board": "Ця тема розпочата на [$2 дошці {{GENDER:$1|користувача|користувачки}} $1]",
+ "flow-topic-permalink-warning-user-board": "Ця тема розпочата на [$2 стіні {{GENDER:$1|користувача|користувачки}} $1]",
"flow-revision-permalink-warning-post": "Це постійне посилання на окрему версію цього допису.\nЦе версія за $1.\nВи можете подивитися [відмінності від попередньої версії $5] або переглянути інші версії на [сторінці історії допису $4].",
"flow-revision-permalink-warning-post-first": "Це постійне посилання на першу версію цього допису.\nВи можете переглядати пізніші версії на [сторінці історії допису $4].",
"flow-revision-permalink-warning-postsummary": "Це постійне посилання на окрему версію підсумку цього допису. Це версія за $1.\nВи можете подивитися [$5 відмінності від попередньої версії] або переглянути інші версії на [$4 сторінці історії допису].",
@@ -319,15 +399,15 @@
"flow-revision-permalink-warning-header-first": "Це постійне посилання на першу версію цього опису.\nВи можете переглядати пізніші версії на [$2 сторінці історії стіни].",
"flow-compare-revisions-revision-header": "Версія від {{GENDER:$2|$2}} за $1",
"flow-compare-revisions-header-post": "Ця сторінка відображає зміни між двома версіями допису від $3 у розділі \"[$5 $2]\" на [$4 $1].\nВи можете побачити інші версії цього допису на його [сторінці історії $6].",
- "flow-compare-revisions-header-postsummary": "Ця сторінка відображає зміни між двома версіями підсумку допису у дописі «[$4 $2]» на [$3 $1].\nВи можете побачити інші версії цього допису на його [$5 сторінці історії].",
+ "flow-compare-revisions-header-postsummary": "Ця сторінка відображає зміни між двома версіями підсумку теми «[$4 $2]» на [$3 $1].\nВи можете побачити інші версії цього підсумку теми на її [$5 сторінці історії].",
"flow-compare-revisions-header-header": "На цій сторінці відображаються {{GENDER:$2|зміни}} між двома версіями опису на [$3 $1].\nВи можете побачити інші версії опису на його [$4 сторінці історії].",
- "action-flow-create-board": "створення дощок Flow у будь-якому місці",
- "right-flow-create-board": "Створення дощок Flow у будь-якому місці",
- "right-flow-hide": "Приховування тем і дописів Flow",
- "right-flow-lock": "Позначити теми Flow як вирішені",
- "right-flow-delete": "Вилучення тем і дописів Flow",
- "right-flow-edit-post": "Редагування дописів інших користувачів у Flow",
- "right-flow-suppress": "Приховування версій Flow",
+ "action-flow-create-board": "створення стін структурованих обговорень у будь-якому місці",
+ "right-flow-create-board": "створення стін структурованих обговорень у будь-якому місці",
+ "right-flow-hide": "приховування тем і дописів у структурованих обговореннях",
+ "right-flow-lock": "позначення тем структурованих обговорень як вирішених",
+ "right-flow-delete": "вилучення тем і дописів у структурованих обговореннях",
+ "right-flow-edit-post": "редагування дописів інших користувачів у структурованих обговореннях",
+ "right-flow-suppress": "приховування версій структурованих обговорень",
"flow-terms-of-use-new-topic": "Натискаючи кнопку «{{int:flow-newtopic-save}}», Ви погоджуєтеся з умовами використання цієї вікі.",
"flow-terms-of-use-reply": "Натискаючи кнопку «{{int:flow-reply-link}}», Ви погоджуєтеся з умовами використання цієї вікі.",
"flow-terms-of-use-edit": "Зберігаючи зміни, ви погоджуєтесь з умовами використання для цього вікі.",
@@ -345,29 +425,31 @@
"flow-toggle-small-topics": "Перемкнути на зменшений вигляд тем",
"flow-toggle-topics": "Перемкнути на вигляд заголовків",
"flow-toggle-topics-posts": "Перемкнути на відображення тем і дописів",
- "flow-terms-of-use-summarize": "Натиснувши кнопку «{{int:flow-topic-action-update-topic-summary}}», ви погоджуєтеся з умовами використання цієї вікі.",
- "flow-terms-of-use-lock-topic": "Натиснувши кнопку \"{{int:flow-topic-action-lock-topic}}\", ви погоджуєтеся з умовами використання цієї вікі.",
+ "flow-terms-of-use-summarize": "Натискаючи кнопку «{{int:flow-topic-action-update-topic-summary}}», Ви погоджуєтеся з умовами використання цієї вікі.",
+ "flow-terms-of-use-lock-topic": "Натискаючи кнопку «{{int:flow-topic-action-lock-topic}}», Ви погоджуєтеся з умовами використання цієї вікі.",
"flow-terms-of-use-unlock-topic": "Натискаючи кнопку «{{int:flow-topic-action-unlock-topic}}», Ви погоджуєтеся з умовами використання цієї вікі.",
"flow-whatlinkshere-post": "із [$1 допису]",
"flow-whatlinkshere-header": "із [$1 опису]",
"flow-whatlinkshere-post-summary": "з [$1 підсумку]",
- "flow": "Flow",
- "flow-special-desc": "Ця спеціальна сторінка перенаправляє на робочий процес Flow або допис Flow, згідно з UUID.",
+ "structureddiscussions": "Flow",
+ "flow-special-desc": "Ця спеціальна сторінка перенаправляє на робочий процес структурованого обговорення або допис у структурованому обговоренні, згідно з UUID.",
"flow-special-type": "Тип",
"flow-special-type-post": "Допис",
"flow-special-type-workflow": "Робочий процес",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "Не вдалося знайти вміст, що відповідає типу та UUID.",
- "flow-special-enableflow-legend": "Увімкнути Flow на новій сторінці",
- "flow-special-enableflow-page": "Сторінка, на якій має бути увімкнений Flow",
- "flow-special-enableflow-header": "Вихідний опис Flow-стіни (вікітекст)",
- "flow-special-enableflow-board-already-exists": "Уже є стіна Flow на [[$1]].",
+ "flow-special-enableflow-legend": "Увімкнути структуровані обговорення на новій сторінці",
+ "flow-special-enableflow-page": "Сторінка, на якій слід увімкнути структуровані обговорення",
+ "flow-special-enableflow-header": "Початковий опис стіни структурованого обговорення (вікірозмітка)",
+ "flow-special-enableflow-board-already-exists": "На [[$1]] вже є стіна структурованого обговорення.",
"flow-special-enableflow-invalid-title": "Вказана неприпустима назва сторінки",
- "flow-special-enableflow-board-creation-not-allowed": "У Вас немає прав на створення стіни Flow на [[:$1]].",
+ "flow-special-enableflow-board-creation-not-allowed": "У Вас немає прав на створення стіни структурованого обговорення на [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Існує сторінка LiquidThreads на [[:$1]].",
- "flow-special-enableflow-confirmation": "Ви успішно створили стіну Flow на [[$1]].",
+ "flow-special-enableflow-confirmation": "Ви створили стіну структурованого обговорення на [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Архів %d\n%s/Архів%d\n%s/архів %d\n%s/архів%d",
- "flow-spam-confirmedit-form": "Будь ласка, підтвердіть, що Ви людина, ввівши каптчу нижче: $1",
+ "flow-conversion-archive-flow-page-name-format": "%s/Архів структурованих обговорень %d\n%s/АрхівСтруктурованихОбговорень%d",
+ "flow-spam-confirmedit-form": "Будь ласка, підтвердіть, що Ви людина, ввівши CAPTCHA нижче: $1",
+ "flow-spam-confirmedit-using-failure": "Сталася технічна помилка з CAPTCHA. Якщо Ви не можете зберегти своє редагування, будь ласка, скопіюйте текст, перезавантажте сторінку і спробуйте ще раз.",
"flow-embedding-unsupported": "Обговорення іще не можна вставити.",
"mw-ui-unsubmitted-confirm": "У вас є невідправлені зміни на цій сторінці. Ви впевнені, що хочете піти і втратити роботу?",
"flow-post-undo-hide": "скасування приховування",
@@ -376,120 +458,27 @@
"flow-topic-undo-hide": "скасування приховування",
"flow-topic-undo-delete": "скасування вилучення",
"flow-topic-undo-suppress": "скасування пригнічення",
- "flow-importer-lqt-moved-thread-template": "Перейменовану заготовку теми LQT перетворено на Flow",
- "flow-importer-lqt-converted-template": "Сторінку LQT перетворено на Flow",
+ "flow-importer-lqt-moved-thread-template": "Перейменовану заготовку теми LQT перетворено на структуроване обговорення",
+ "flow-importer-lqt-moved-thread-template-content": "Цей допис від {{{author}}} було переміщено {{{date}}}. Ви можете знайти його на [[{{{title}}}]].",
+ "flow-importer-lqt-converted-template": "Сторінку LQT перетворено на структуроване обговорення",
+ "flow-importer-lqt-converted-template-content": "Попередня історія сторінки була резервно заархівована на <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-lqt-converted-archive-template": "Архів конвертованої LQT-сторінки",
- "flow-importer-wt-converted-template": "Вікітекстова сторінка обговорення перетворена на Flow",
- "flow-importer-wt-converted-template-content": "Попередня дискусія була заархівованою <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> {{#час: Р-М-д|{{{дата}}}}}.",
+ "flow-importer-lqt-converted-archive-template-content": "Ця сторінка є архівом сторінки LiquidThreads. <strong>Не змінюйте вміст даної сторінки</strong>. Будь ласка, пишіть будь-які додаткові коментарі на [[{{{from}}}|поточну сторінку обговорення]].",
+ "flow-importer-wt-converted-template": "Вікітекстова сторінка обговорення перетворена на структуроване обговорення",
+ "flow-importer-wt-converted-template-content": "Попередня дискусія була заархівованою <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> {{#time: Y-m-d|{{{date}}}}}.",
"flow-importer-wt-converted-archive-template": "Архів перетвореної вікітекстової сторінки обговорення",
+ "flow-importer-wt-converted-archive-template-content": "Ця сторінка є архівом. <strong>Не змінюйте вміст даної сторінки</strong>. Будь ласка, пишіть будь-які додаткові коментарі на [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|поточну сторінку обговорення]].",
"flow-importer-lqt-suppressed-user-template": "Допис LQT імпортовано з пригніченим користувачем",
+ "flow-importer-lqt-suppressed-user-template-content": "Цю версію було імпортовано з LiquidThreads з пригніченим користувачем. Вона була перепризначена для поточного користувача.",
"flow-importer-lqt-different-author-signature-template": "LQT-пост імпортовано з іншим підписом користувача",
- "apihelp-flow-description": "Дозволяє застосовувати дії до сторінок Flow.",
- "apihelp-flow-param-submodule": "Підмодуль Flow, що викликається.",
- "apihelp-flow-param-page": "Сторінка, до якої застосовуються дії.",
- "apihelp-flow-example-1": "Додати опис «[[Talk:Sandbox]]»",
- "apihelp-flow+close-open-topic-description": "Застаріло на користь [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Статус, що надається темі, «закрити» або «відкрити».",
- "apihelp-flow+close-open-topic-param-reason": "Причина закриття чи відкриття теми.",
- "apihelp-flow+edit-header-description": "Редагування опису стіни.",
- "apihelp-flow+edit-header-param-prev_revision": "ID версії поточної версії опису, який перевіряється на конфлікти редагувань.",
- "apihelp-flow+edit-header-param-content": "Вміст для опису.",
- "apihelp-flow+edit-header-param-format": "Формат опису (вікітекст|html)",
- "apihelp-flow+edit-header-example-1": "Редагувати опис «[[Talk:Sandbox]]»",
- "apihelp-flow+edit-post-description": "Редагування вмісту допису.",
- "apihelp-flow+edit-post-param-postId": "ID допису.",
- "apihelp-flow+edit-post-param-prev_revision": "ID поточної версії допису, яка перевіряється на конфлікти редагувань.",
- "apihelp-flow+edit-post-param-content": "Вміст для допису.",
- "apihelp-flow+edit-post-param-format": "Формат вмісту допису (вікітекст|html)",
- "apihelp-flow+edit-post-example-1": "Редагувати допис у [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Редагування назви теми.",
- "apihelp-flow+edit-title-param-prev_revision": "ID поточної версії назви, яка перевіряється на конфлікти редагувань.",
- "apihelp-flow+edit-title-param-content": "Вміст для заголовка.",
- "apihelp-flow+edit-title-example-1": "Редагувати назву у [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Редагування вмісту підсумку теми.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "ID поточної версії підсумку теми, яка перевіряється на конфлікти редагувань.",
- "apihelp-flow+edit-topic-summary-param-summary": "Вміст для підсумку.",
- "apihelp-flow+edit-topic-summary-param-format": "Формат підсумку (вікітекст|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Редагувати підсумок у [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Закрити чи відкрити тему Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Статус, що надається темі, <kbd>закрити</kbd> або <kbd>відкрити</kbd>.",
- "apihelp-flow+lock-topic-param-reason": "Причина закриття чи відкриття теми. Зауважте, що клієнт Flow у вікі використовує позначку «Позначено як вирішене» і додає необов'язкову додаткову інформацію в описі.",
- "apihelp-flow+lock-topic-example-1": "Закрити [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Модерування допису Flow.",
- "apihelp-flow+moderate-post-param-moderationState": "Який рівень модерації.",
- "apihelp-flow+moderate-post-param-reason": "Причина для модерації.",
- "apihelp-flow+moderate-post-param-postId": "ID допису для модерації.",
- "apihelp-flow+moderate-post-example-1": "Вилучити допис у темі [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Модерування теми Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "Який рівень модерації.",
- "apihelp-flow+moderate-topic-param-reason": "Причина для модерації.",
- "apihelp-flow+moderate-topic-example-1": "Вилучити тему [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Створює нову тему Flow у даному робочому полі.",
- "apihelp-flow+new-topic-param-topic": "Текст для нової назви теми.",
- "apihelp-flow+new-topic-param-content": "Вміст для початкової відповіді в темі.",
- "apihelp-flow+new-topic-param-format": "Формат початкової відповіді в темі (вікітекст|html)",
- "apihelp-flow+new-topic-example-1": "Створити нову тему у [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Відповіді на допис.",
- "apihelp-flow+reply-param-replyTo": "ID допису для відповіді.",
- "apihelp-flow+reply-param-content": "Вміст для нового допису.",
- "apihelp-flow+reply-param-format": "Формат нового допису (вікітекст|html)",
- "apihelp-flow+reply-example-1": "Відповідь на допис у [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Формат виведення вмісту.",
- "apihelp-flow+view-header-description": "Переглянути опис стіни.",
- "apihelp-flow+view-header-param-revId": "Завантажити цю версію замість останньої.",
- "apihelp-flow+view-header-example-1": "Вибірка опису [[Talk:Sandbox]] у вигляді вікітексту",
- "apihelp-flow+view-post-description": "Переглянути допис.",
- "apihelp-flow+view-post-param-postId": "ID допису для перегляду.",
- "apihelp-flow+view-post-param-format": "Формат виведення вмісту.",
- "apihelp-flow+view-post-example-1": "Вибірка вмісту допису у [[Topic:S2tycnas4hcucw8w]] у вигляді вікітексту",
- "apihelp-flow+view-post-history-description": "Переглянути історію змін цього допису.",
- "apihelp-flow+view-post-history-param-postId": "ID запису, для якого необхідно переглянути історію змін.",
- "apihelp-flow+view-post-history-param-format": "Формат, у якому повернути вміст.",
- "apihelp-flow+view-post-history-example-1": "Отримати версії допису у [[Topic:S2tycnas4hcucw8w]] як вікітекст",
- "apihelp-flow+view-topic-description": "Переглянути тему.",
- "apihelp-flow+view-topic-example-1": "Переглянути [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Переглянути історію змін цієї теми.",
- "apihelp-flow+view-topic-history-param-format": "Формат, у якому повернути вміст.",
- "apihelp-flow+view-topic-history-example-1": "Переглянути версії допису в [[Topic:S2tycnas4hcucw8w]] як вікітекст",
- "apihelp-flow+view-topic-summary-description": "Переглянути підсумок теми.",
- "apihelp-flow+view-topic-summary-param-format": "Формат виведення вмісту.",
- "apihelp-flow+view-topic-summary-param-revId": "Завантажити цю версію замість останньої.",
- "apihelp-flow+view-topic-summary-example-1": "Переглянути підсумок для [[Topic:S2tycnas4hcucw8w]] як вікітекст",
- "apihelp-flow+view-topiclist-description": "Переглянути список тем.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Порядок сортування тем.",
- "apihelp-flow+view-topiclist-param-sortby": "Варіант сортування тем: або <kbd>updated</kbd> (сортування за часом оновлення теми), або <kbd>newest</kbd> (сортування за часом створення теми).",
- "apihelp-flow+view-topiclist-param-savesortby": "Зберегти опцію сортування у налаштуваннях користувача, якщо вказана.",
- "apihelp-flow+view-topiclist-param-offset-id": "Значення зміщення (у форматі UUID) для початку вибірки тем; використовується лише для сортування <kbd>newest</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Значення зміщення (у вигляді часової мітки оновлення теми, у форматі <code>TS_MW</code> (<code>YYYYMMDDHHMMSS</code>)), з якого почати вибірку тем; використовується лише з сортуванням <kbd>updated</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Кількість тем для вибірки.",
- "apihelp-flow+view-topiclist-example-1": "Список тем у [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Конвертувати текст між вікітекстом і HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Формат, з якого конвертувати вміст.",
- "apihelp-flow-parsoid-utils-param-to": "Формат, у який конвертувати вміст.",
- "apihelp-flow-parsoid-utils-param-content": "Вміст для конвертування.",
- "apihelp-flow-parsoid-utils-param-title": "Заголовок сторінки. Не може використовуватися разом із $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "ID сторінки. Не може використовуватися разом з $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Конвертувати вікітекст <nowiki>'''lorem''' ''blah''</nowiki> у HTML",
- "apihelp-query+flowinfo-description": "Отримати базову Flow-інформацію про сторінку.",
- "apihelp-query+flowinfo-example-1": "Вибрати Flow-інформацію про [[Talk:Sandbox]], [[Main Page]], та [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Отримати інформацію, необхідну для скасування редагувань опису.",
- "apihelp-flow+undo-edit-header-param-startId": "Ідентифікатор версії для початку скасування.",
- "apihelp-flow+undo-edit-header-param-endId": "Ідентифікатор версії для закінчення скасування.",
- "apihelp-flow+undo-edit-header-example-1": "Вибрати інформацію про скасування редагування опису на [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Отримати інформацію, необхідну для скасування редагування допису.",
- "apihelp-flow+undo-edit-post-param-postId": "ID допису, який буде скасовано.",
- "apihelp-flow+undo-edit-post-param-startId": "Ідентифікатор версії для початку скасування.",
- "apihelp-flow+undo-edit-post-param-endId": "Ідентифікатор версії для закінчення скасування.",
- "apihelp-flow+undo-edit-post-example-1": "Вибрати інформацію про скасування редагування допису у певній темі.",
- "apihelp-flow+undo-edit-topic-summary-description": "Отримати інформацію, необхідну для скасування редагувань опису теми.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Ідентифікатор версії для початку скасування.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Ідентифікатор версії для закінчення скасування.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Вибрати інформацію про скасування редагування опису теми у певній темі",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Це повідомлення було опубліковано [[User:{{{authorUser}}}|{{{authorUser}}}]], але підписано як [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Відредаговано",
"flow-edited-by": "Відредаговано $1",
- "flow-lqt-redirect-reason": "Перенаправлення застарілого допису LiquidThreads на допис, конвертований у Flow",
- "flow-talk-conversion-move-reason": "Перетворення розмови у вікітексті на Flow з $1",
- "flow-talk-conversion-archive-edit-reason": "Перетворення обговорення у вікітексті на Flow",
+ "flow-edited-by-header": "Опис стіни відредаговано $1",
+ "flow-edited-by-topic-title": "Назву теми відредаговано $1",
+ "flow-lqt-redirect-reason": "Перенаправлення застарілого допису LiquidThreads на допис, конвертований у структуроване обговорення",
+ "flow-talk-conversion-move-reason": "Перетворення обговорення у форматі вікірозмітки на структуроване обговорення з $1",
+ "flow-talk-conversion-archive-edit-reason": "Перетворення обговорення у форматі вікірозмітки на структуроване обговорення",
"flow-previous-diff": "← Старіше редагування",
"flow-next-diff": "Новіше редагування →",
"flow-undo": "скасувати",
@@ -500,9 +489,9 @@
"flow-undo-edit-post": "Редагування допису",
"flow-undo-edit-content": "Редагування може бути скасовано. Будь ласка, перевірте порівняння нижче, щоб впевнитись, що це те, що Ви хочете зробити, а потім збережіть зміни нижче, щоб закінчити скасування редагування.",
"flow-undo-edit-failure": "Редагування не може бути скасовано через конфліктні проміжні редагування.",
- "group-flow-bot": "Flow-боти",
- "group-flow-bot-member": "Flow-бот",
- "grouppage-flow-bot": "Project:Flow bots",
+ "group-flow-bot": "Боти для структурованих обговорень",
+ "group-flow-bot-member": "Бот для структурованих обговорень",
+ "grouppage-flow-bot": "Project:Structured Discussions bots",
"flow-ve-mention-context-item-label": "Згадування",
"flow-ve-mention-inspector-title": "Згадка",
"flow-ve-mention-inspector-remove-label": "Прибрати",
@@ -512,7 +501,7 @@
"flow-ve-mention-inspector-invalid-user": "Користувач «$1» не зареєстрований.",
"flow-wikitext-editor-help": "Вікірозмітка $1.",
"flow-wikitext-editor-help-and-preview": "Цей редактор $1 і Ви можете $2 в будь-який момент.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|використовує вікірозмітку]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|використовує вікірозмітку]]",
"flow-wikitext-editor-help-preview-the-result": "попередньо переглянути результат",
"flow-wikitext-switch-editor-tooltip": "Перемкнути на Візуальний редактор",
"flow-ve-switch-editor-tool-title": "Перемкнути на редактор вікірозмітки",
@@ -520,11 +509,28 @@
"flow-mark-revision-patrolled-link-title": "Позначити цю сторінку як патрульовану",
"flow-mark-diff-patrolled-link-text": "Позначити як патрульовану",
"flow-mark-diff-patrolled-link-title": "Позначити як патрульовану",
+ "flow-talk-page-beta-feature-message": "Структуроване обговорення на сторінці обговорення користувача",
+ "flow-talk-page-beta-feature-description": "Вмикає нову структуровану систему дискусій на {{GENDER:|Вашій}} сторінці обговорення користувача. Структуроване обговорення спрощує дискусії на сторінці обговорення, даючи чіткі місця, де писати й відповідати, і має можливість сповіщення за рівнями розмови. Ця функція не увімкнена автоматично; користувачі матимуть увімкнути її окремо.<br /><br />Наявні обговорення у вікірозмітці переносяться в архів. Вимкнення цієї функції перемістить стіну структурованого обговорення на підсторінку і розархівує попередню сторінку обговорення. [[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|Дізнайтесь більше про активацію]].",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|Подивитися}} сторінку обговорення користувача",
"flow-notification-enabled-on-talkpage-title": "На {{GENDER:$1|вашій}} сторінці обговорення задіяна нова дискусійна система<br /><small>Доступно від [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Нова система обговорення на $2",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "На {{GENDER:$1|Вашій}} сторінці обговорення користувача на сайті {{SITENAME}} було увімкнено структуроване обговорення — нову систему обговорень у вікі. Ви можете дізнатися більше, залишити відгук або вимкнути нову систему у будь-який час у розділі Бета-функції у {{GENDER:$1|своїх}} налаштуваннях.",
"flow-beta-feature-add-archive-template-edit-summary": "Додавання архівного шаблону",
"flow-beta-feature-remove-archive-template-edit-summary": "Видалення архівного шаблону",
- "flow-dialog-cancelconfirm-title": "Ви впевнені?",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|Ви}} впевнені?",
+ "flow-dialog-cancelconfirm-message": "{{GENDER:|Ви}} впевнені, що хочете скасувати, не зберігши спершу?",
"flow-dialog-cancelconfirm-keep": "Продовжити редагування",
- "flow-dialog-cancelconfirm-discard": "Відкинути зміни"
+ "flow-dialog-cancelconfirm-discard": "Відкинути зміни",
+ "flow-optin-archive-wikitext": "Перемістити сторінку вікірозмітки, щоб звільнити місце для стіни обговорення.",
+ "flow-optin-archive-flow-board": "Перемістити сторінку стіни обговорення, щоб звільнити місце для сторінки у форматі вікірозмітки.",
+ "flow-optin-restore-wikitext": "Відновити заархівовану сторінку у форматі вікірозмітки.",
+ "flow-optin-restore-flow-board": "Відновити заархівовану стіну обговорень.",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|Ласкаво просимо}} на {{GENDER:$1|Вашу}} нову сторінку обговорення користувача",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|Ваша}} сторінка обговорення є місцем, де інші редактори можуть зв'язатися з {{GENDER:$1|Вами}}. Завдяки структурованому обговоренню легше почати нову тему і слідкувати за розмовами.",
+ "flow-guidedtour-optin-find-old-conversations": "Знайти {{GENDER:$1|свої}} старі обговорення",
+ "flow-guidedtour-optin-find-old-conversations-description": "Попередні обговорення було переміщено на архівну сторінку.",
+ "flow-guidedtour-optin-feedback": "Залиште нам {{GENDER:$1|свій}} відгук!",
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|Ви}} можете отримати більш детальну інформацію, залишити відгук або вимкнути нову систему в будь-який час у розділі «Бета-функції».",
+ "flow-action-not-page": "Об'єкт сторінки є екземпляром хибного класу",
+ "flow-action-wrong-title-content-model": "Сторінка опрацьовується Структурованим обговоренням, але клас назви свідчить про те, що контентною моделлю є «$1». Це — неправильне налаштування, або неузгоджений стан. Наприклад, ця сторінка може бути сторінкою, що не опрацьовується Структурованим обговоренням, але перебуває в просторі назв структурованих обговорень із незаповненим <code>rev_content_model</code>."
}
diff --git a/Flow/i18n/ur.json b/Flow/i18n/ur.json
index d2ff34f8..36d5a1a8 100644
--- a/Flow/i18n/ur.json
+++ b/Flow/i18n/ur.json
@@ -3,40 +3,381 @@
"authors": [
"Muhammad Shuaib",
"عثمان خان شاہ",
- "FarhanDanish"
+ "FarhanDanish",
+ "Obaid Raza",
+ "Macofe"
]
},
- "enableflow": "فلو فعال کریں",
+ "enablestructureddiscussions": "فلو فعال کریں",
"flow-desc": "ورک فلو مینیجمنٹ سسٹم",
- "flow-talk-taken-over": "یہ تبادلۂ خیال صفحہ [https://www.mediawiki.org/wiki/Special:MyLanguage/Flow_Portal Flow] استعمال کررہا ہے.",
+ "flow-talk-taken-over-comment": "/* پیش نظر صفحہ کو فلو تبادلۂ خیال نظام کی جانب منتقل کر دیا گیا ہے */",
"log-name-flow": "نوشتہ فعالیت فلو",
"logentry-delete-flow-delete-post": "$1 نے [[$6]] پر [[$3|$5]] سے ایک [$4 مراسلہ] {{GENDER:$2|حذف کیا}}",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 نے [[$3]] موضوع پر ایک مراسلہ کو {{GENDER:$2|حذف کیا}}",
"logentry-delete-flow-restore-post": "$1 نے [[$6]] پر [[$3|$5]] سے ایک [$4 مراسلہ] {{GENDER:$2|بحال کیا}}",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 نے [[$3]] موضوع پر ایک مراسلہ کو {{GENDER:$2|بحال کیا}}",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 نے [[$3]] موضوع پر ایک مراسلہ کو {{GENDER:$2|دبایا}}",
"logentry-suppress-flow-restore-post": "$1 نے [[$6]] پر [[$3|$5]] سے ایک [$4 مراسلہ] {{GENDER:$2|حذف کیا}}",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 نے [[$3]] موضوع پر ایک مراسلہ کو {{GENDER:$2|حذف کیا}}",
"logentry-delete-flow-delete-topic": "$1 نے [[$6]] پر موضوع [[$3|$5]] {{GENDER:$2|حذف کیا}}",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 نے [[$3]] پر ایک موضوع کو {{GENDER:$2|حذف کیا}}",
"logentry-delete-flow-restore-topic": "$1 نے [[$6]] پر موضوع [[$3|$5]] {{GENDER:$2|بحال کیا}}",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 نے [[$3]] پر ایک موضوع کو {{GENDER:$2|بحال کیا}}",
+ "logentry-suppress-flow-suppress-topic": "$1 نے [[$6]] پر \"[[$3|$5]]\" موضوع کو {{GENDER:$2|دبایا}}",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 نے [[$3]] پر ایک موضوع کو {{GENDER:$2|دبایا}}",
+ "logentry-suppress-flow-restore-topic": "$1 نے [[$6]] پر موضوع [[$3|$5]] {{GENDER:$2|حذف کیا}}",
"flow-user-moderated": "تدوین شدہ صارف",
"flow-board-header-browse-topics-link": "موضوعات دیکھیں",
- "flow-board-header": "اس بورڈ کے بارے میں",
- "flow-board-collapse-description": "تفصیل چھپائیں",
- "flow-board-expand-description": "تفصیل دکھائیں",
- "flow-edit-header-link": "تفصیل میں ترمیم کریں",
+ "flow-board-header": "اس صفحہ کے بارے میں",
+ "flow-board-description-can-not-edit": "ناقابل ترمیم",
+ "flow-board-collapse-description": "وضاحت چھپائیں",
+ "flow-board-expand-description": "وضاحت دکھائیں",
+ "flow-topic-collapse-siderail": "مکمل چوڑائی کا احاطہ کریں",
+ "flow-topic-expand-siderail": "متعین چوڑائی میں پڑھیں",
+ "flow-edit-header-link": "وضاحت میں ترمیم کریں",
"flow-post-moderated-toggle-hide-show": "تبصرہ {{GENDER:$1|پوشیدہ کردہ}} از $2 دکھائیں",
"flow-post-moderated-toggle-delete-show": "$2 کا {{GENDER:$1|حذف کردہ}} تبصرہ دکھائیں",
+ "flow-post-moderated-toggle-hide-hide": "$2 کا {{GENDER:$1|پوشیدہ کردہ}} تبصرہ چھپائیں",
+ "flow-post-moderated-toggle-delete-hide": "$2 کا {{GENDER:$1|حذف کردہ}} تبصرہ چھپائیں",
"flow-topic-moderated-reason-prefix": "وجہ:",
"flow-hide-post-content": "اس تبصرے کو $1 نے {{GENDER:$1|پوشیدہ کردیا ہے}} ([$2 تاریخچہ])",
+ "flow-hide-title-content": "اس موضوع کو $1 نے {{GENDER:$1|پوشیدہ کر دیا}} ہے",
+ "flow-hide-header-content": "{{GENDER:$1|پوشیدہ کردہ}} از $2",
+ "flow-delete-post-content": "اس تبصرے کو $1 نے {{GENDER:$1|حذف کردیا ہے}} ([$2 تاریخچہ])",
+ "flow-delete-title-content": "اس موضوع کو $1 نے {{GENDER:$1|حذف کر دیا}} ہے",
+ "flow-delete-header-content": "{{GENDER:$1|حذف کردہ}} از $2",
+ "flow-suppress-usertext": "<em>صارف نام کو دبا دیا گیا</em>",
"flow-post-actions": "اقدامات",
"flow-topic-actions": "اقدامات",
- "flow-cancel": "منسوخ کریں",
+ "flow-cancel": "منسوخ",
"flow-skip-summary": "خلاصہ نظر انداز کریں",
- "flow-edit-summary-placeholder": "مختصر طور پر اس گفتگو کا نتیجہ تحریر کریں",
+ "flow-edit-summary-placeholder": "مختصراً اس گفتگو کا نتیجہ تحریر کریں",
"flow-summary-authored": "خلاصہ از $1",
+ "flow-summary-edited": "آخری بار خلاصہ میں $1 نے {{GENDER:$1|ترمیم کی}}",
"flow-show-change": "تبدیلیاں دکھائیں",
- "flow-newtopic-save": "نیا موضوع شامل کریں",
+ "flow-last-modified-by": "$1 نے آخری مرتبہ {{GENDER:$1|ترمیم کیا}}",
+ "flow-stub-post-content": "<em>کسی تکنیکی غلطی کی وجہ سے یہ مراسلہ بازیاب نہیں ہو سکا۔</em>",
+ "flow-newtopic-title-placeholder": "نیا موضوع",
+ "flow-newtopic-content-placeholder": "\"$1\" میں نیا مراسلہ ارسال کریں",
+ "flow-newtopic-header": "نیا موضوع شروع کریں",
+ "flow-newtopic-save": "موضوع شروع کریں",
+ "flow-newtopic-save-anonymously": "بطور نامعلوم صارف موضوع شروع کریں",
"flow-newtopic-start-placeholder": "نیا موضوع شروع کریں",
"flow-newtopic-first-heading": "$1 پر نیا موضوع شروع کریں",
- "flow-reply-topic-title-placeholder": "\"$1\" کو جواب دیں",
+ "flow-summarize-topic-placeholder": "براہ کرم گفتگو کا خلاصہ تحریر کریں",
+ "flow-reply-topic-placeholder": "$2 پر {{GENDER:$1|تبصرہ}}",
+ "flow-reply-topic-title-placeholder": "\"$1\" کا جواب دیں",
+ "flow-reply-link": "{{GENDER:$1|جواب دیں}}",
+ "flow-reply-link-anonymously": "بطور نامعلوم صارف جواب دیں",
+ "flow-thank-link": "{{GENDER:$1|{{GENDER:$2|شکریہ}}}}",
+ "flow-thank-link-title": "عوامی طور پر ارسال کنندہ کا {{GENDER:$1|{{GENDER:$2|شکریہ ادا کیا}}}}",
+ "flow-history-action-suppress-post": "دبائیں",
"flow-history-action-delete-post": "حذف کریں",
"flow-history-action-hide-post": "چھپائیں",
- "flow-history-action-undelete-post": "بحال کریں"
+ "flow-history-action-undelete-post": "بحال کریں",
+ "flow-history-action-unhide-post": "دکھائیں",
+ "flow-history-action-restore-post": "بحال",
+ "flow-history-action-lock-topic": "برطرف کریں",
+ "flow-history-action-unlock-topic": "دوبارہ کھولیں",
+ "flow-post-edited": "مراسلہ ترمیم شدہ از $1 $2",
+ "flow-post-action-view": "مستقل ربط",
+ "flow-post-action-post-history": "تاریخچہ",
+ "flow-post-action-suppress-post": "دبائیں",
+ "flow-post-action-delete-post": "حذف",
+ "flow-post-action-hide-post": "چھپائیں",
+ "flow-post-action-edit-post": "ترمیم",
+ "flow-post-action-edit-post-submit": "تبدیلیاں محفوظ کریں",
+ "flow-post-action-edit-post-submit-anonymously": "بطور نامعلوم صارف تبدیلیاں محفوظ کریں",
+ "flow-post-action-undelete-post": "بحال کریں",
+ "flow-post-action-unhide-post": "دکھائیں",
+ "flow-post-action-restore-post": "بحال",
+ "flow-post-action-undo-moderation": "استرجع",
+ "flow-topic-action-view": "مستقل ربط",
+ "flow-topic-action-watchlist": "زیر نظر فہرست",
+ "flow-topic-action-edit-title": "عنوان تبدیل کریں",
+ "flow-topic-action-history": "تاریخچہ",
+ "flow-topic-action-hide-topic": "موضوع چھپائیں",
+ "flow-topic-action-delete-topic": "موضوع حذف کریں",
+ "flow-topic-action-lock-topic": "بطور برطرف شدہ نشان زد کریں",
+ "flow-topic-action-unlock-topic": "موضوع دوبارہ کھولیں",
+ "flow-topic-action-summarize-topic": "خلاصہ کریں",
+ "flow-topic-action-resummarize-topic": "خلاصہ موضوع تبدیل کریں",
+ "flow-topic-action-update-topic-summary": "خلاصہ تازہ کریں",
+ "flow-topic-action-unhide-topic": "موضوع دکھائیں",
+ "flow-topic-action-undelete-topic": "موضوع بحال کریں",
+ "flow-topic-action-restore-topic": "موضوع بحال کریں",
+ "flow-topic-action-undo-moderation": "استرجع",
+ "flow-topic-notification-subscribe-title": "یہ موضوع {{GENDER:$1|آپ}} کی زیر نظر فہرست میں شامل کر دیا گیا ہے۔",
+ "flow-topic-notification-subscribe-description": "اب {{GENDER:$1|آپ}} کو اس موضوع پر ہونے والی جملہ سرگرمیوں کی اطلاعات موصول ہوگی۔",
+ "flow-board-notification-subscribe-title": "{{GENDER:$1|آپ نے}} اس گفتگو کو سبسکرائب کر لیا ہے!",
+ "flow-board-notification-subscribe-description": "اس صفحہ میں نیا موضوع شروع ہونے پر {{GENDER:$1|آپ}} کو اطلاع موصول ہوگی۔",
+ "flow-topic-action-watchlist-add": "اس گفتگو کو سبسکرائب کریں",
+ "flow-topic-action-watchlist-remove": "شمولیت ختم",
+ "flow-error-allowcreation-flow-create-board": "صارف کے پاس \"{{int:right-flow-create-board}}\" اختیار نہیں ہے۔",
+ "flow-error-http": "سرور سے رابطہ کے دوران کوئی نقص واقع ہوگیا ہے۔",
+ "flow-error-external": "نقص! موصول شدہ پیغام: $1",
+ "flow-error-topic-is-locked": "اس موضوع کو برطرف کر دیا ہے، لہذا مزید کارروائی ناممکن ہے۔",
+ "flow-error-lock-moderated-post": "آپ زیر نگرانی مراسلہ کو بطور برطرف شدہ نشان زد نہیں کر سکتے۔",
+ "flow-error-missing-content": "اس مراسلہ میں کوئی مواد موجود نہیں، اسے محفوظ کرنے کے لیے کسی قسم کے مواد کی موجودگی ضروری ہے۔",
+ "flow-error-missing-summary": "آپ کو خلاصہ درج کرنا پڑے گا۔",
+ "flow-error-missing-title": "اس موضوع کا کوئی عنوان موجود نہی، اسے محفوظ کرنے کے لیے عنوان کا اندراج ناگزیر ہے۔",
+ "flow-error-protected-unknown-reason": "نامعلوم",
+ "flow-error-invalid-moderation-reason": "براہ کرم نگرانی کی وجہ درج کریں۔",
+ "flow-error-not-allowed": "اس اقدام کی تکمیل کے لیے ناکافی اختیارات ہیں۔",
+ "flow-error-not-allowed-hide": "یہ موضوع پوشیدہ کر دیا گیا ہے۔",
+ "flow-error-not-allowed-reply-to-hide-topic": "اس موضوع کے پوشیدہ ہو جانے کی وجہ سے آپ اپنا جواب نہیں ارسال کر سکتے ہیں۔",
+ "flow-error-not-allowed-delete": "یہ موضوع حذف کر دیا گیا ہے۔",
+ "flow-error-not-allowed-reply-to-delete-topic": "اس موضوع کے حذف ہو جانے کی وجہ سے آپ اپنا جواب نہیں ارسال کر سکتے ہیں۔",
+ "flow-error-not-allowed-suppress": "یہ موضوع حذف کر دیا گیا ہے۔",
+ "flow-error-not-allowed-reply-to-suppress-topic": "اس موضوع کے حذف ہو جانے کی وجہ سے آپ اپنا جواب نہیں ارسال کر سکتے ہیں۔",
+ "flow-error-not-allowed-hide-extract": "یہ موضوع پوشیدہ کر دیا گیا ہے۔ حوالہ کے لیے ذیل میں نوشتۂ پوشیدگی درج ہے۔",
+ "flow-error-not-allowed-delete-extract": "یہ موضوع حذف کر دیا گیا ہے۔ حوالہ کے لیے ذیل میں نوشتۂ حذف شدگی درج ہے۔",
+ "flow-error-not-allowed-reply-to-delete-topic-extract": "اس موضوع کے حذف ہو جانے کی وجہ سے آپ اپنا جواب نہیں ارسال کر سکتے ہیں۔ حوالہ کے لیے ذیل میں نوشتہ حذف شدگی دیا گیا ہے۔",
+ "flow-error-not-allowed-suppress-extract": "یہ موضوع حذف کر دیا گیا ہے۔ حوالہ کے لیے ذیل میں نوشتۂ حذف شدگی درج ہے۔",
+ "flow-error-title-too-long": "موضوع کے عنوانات $1 {{PLURAL:$1|بائٹ}} تک محدود ہیں۔",
+ "flow-error-no-existing-workflow": "یہ ورک فلو ابھی موجود نہیں ہے۔",
+ "flow-error-not-a-post": "عنوان کو بطور مراسلہ نہیں محفوظ کیا جا سکتا ہے۔",
+ "flow-error-missing-header-content": "آپ کو وضاحت لازماً درج کرنا ہوگا۔",
+ "flow-error-prev-revision-mismatch": "کسی دوسرے صارف نے چند سیکنڈ قبل اس مراسلہ میں ترمیم کی ہے۔ کیا {{GENDER:$3|آپ}} واقعی اس حالیہ تبدیلی کو برتحریر (overwrite) کرنا چاہتے ہیں؟",
+ "flow-error-prev-revision-does-not-exist": "گزشتہ نظرثانی نہیں مل سکی۔",
+ "flow-error-core-topic-deletion": "موضوع کو حذف کرنے کے لیے براہ راست action=delete استعمال کرنے کے بجائے ... فلو صفحہ پر موجود مینیو یا [$1 صفحۂ موضوع] استعمال کریں۔",
+ "flow-error-default": "ایک غلطی واقع ہوئی ہے۔",
+ "flow-error-invalid-input": "فلو مواد کی لوڈنگ کے لیے غلط قدر دی گئی۔",
+ "flow-error-invalid-title": "صفحہ کا عنوان غلط درج کیا گیا ہے۔",
+ "flow-error-fail-load-history": "تاریخچہ کا مواد لوڈ ہونے میں ناکام رہا۔",
+ "flow-error-fail-commit": "فلو مواد محفوظ ہونے میں ناکام رہا۔",
+ "flow-error-insufficient-permission": "مواد تک رسائی کے لیے ناکافی اختیار ہے۔",
+ "flow-error-revision-comparison": "فرق دیکھنا اسی وقت ممکن ہے جب دو اعادے ایک ہی مراسلہ سے تعلق رکھتے ہوں۔",
+ "flow-error-missing-topic-title": "موجودہ ورک فلو کے لیے عنوان موضوع نہیں مل سکا۔",
+ "flow-error-missing-metadata": "اس نظرثانی کے لیے درکار میٹاڈیٹا نہیں مل سکا۔",
+ "flow-error-fail-load-data": "درخواست شدہ ڈیٹا لوڈ ہونے میں ناکام رہا۔",
+ "flow-error-invalid-workflow": "درخواست شدہ ورک فلو نہیں مل سکا۔",
+ "flow-error-process-data": "آپ کی درخواست میں موجود ڈیٹا پراسیسنگ کے دوران کوئی نقص واقع ہوگیا ہے۔",
+ "flow-error-process-wikitext": "ایچ ٹی ایم ایل/ویکی متن تبدیلی کے دوران کوئی نقص واقع ہو گیا ہے۔",
+ "flow-error-no-render": "متعینہ اقدام کی شناخت نہیں ہو سکی۔",
+ "flow-error-no-commit": "متعینہ اقدام محفوظ نہیں کیا جا سکا۔",
+ "flow-error-content-too-long": "مواد انتہائی زیادہ ہے۔ مواد میں اضافے کے بعد یہ $1 {{PLURAL:$1|بائٹ}} تک محدود ہے۔",
+ "flow-error-move-topic": "فی الحال موضوع صفحہ کی منتقلی کی معاونت شامل نہیں کی گئی ہے۔",
+ "flow-error-invalid-topic-uuid-title": "غلط عنوان",
+ "flow-error-invalid-topic-uuid": "درخواست شدہ عنوان صفحہ غلط ہے۔ موضوع نام فضا میں صفحات فلو کے ذریعہ خودکار طور پر بنتے ہیں۔",
+ "flow-error-unknown-workflow-id-title": "نامعلوم موضوع",
+ "flow-error-unknown-workflow-id": "مطلوبہ موضوع موجود نہیں ہے۔",
+ "flow-error-search": "ایک عارضی مسئلہ کی وجہ سے ہم آپ کی تلاش مکمل نہیں کر سکے۔ براہ کرم کچھ دیر بعد دوبارہ کوشش کریں۔",
+ "flow-edit-header-placeholder": "اس گفتگو کی وضاحت کریں",
+ "flow-edit-header-submit": "وضاحت محفوظ کریں",
+ "flow-edit-header-submit-anonymously": "بطور نامعلوم صارف وضاحت محفوظ کریں",
+ "flow-edit-title-submit": "عنوان تبدیل کریں",
+ "flow-edit-title-submit-anonymously": "بطور نامعلوم صارف عنوان تبدیل کریں",
+ "flow-edit-post-submit": "تبدیلیاں روانہ کریں",
+ "flow-edit-post-submit-anonymously": "بطور نامعلوم صارف تبدیلیاں روانہ کریں",
+ "flow-rev-message-edit-post": "\"$4\" پر $1 نے ایک [$3 تبصرہ] میں {{GENDER:$2|ترمیم کی}}",
+ "flow-rev-message-edit-post-recentchanges-summary": "مراسلہ میں {{GENDER:$2|ترمیم کی}}",
+ "flow-rev-message-reply": "$1 نے \"$4\" پر [$3 {{GENDER:$2|تبصرہ کیا}}] (<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 {{PLURAL:$1|تبصرہ|تبصرے}}</strong> شامل {{PLURAL:$1|کیا گیا|کئے گئے}}",
+ "flow-rev-message-new-post": "$1 نے موضوع \"[$3 $4]\" {{GENDER:$2|شروع کیا}}",
+ "flow-rev-message-new-post-recentchanges-summary": "نیا موضوع {{GENDER:$2|شروع کیا}}",
+ "flow-rev-message-edit-title": "$1 نے عنوان موضوع کو \"$5\" سے \"[$3 $4] {{GENDER:$2|کر دیا}}",
+ "flow-rev-message-create-header": "$1 نے وضاحت {{GENDER:$2|تحریر کی}}",
+ "flow-rev-message-edit-header": "$1 نے وضاحت میں {{GENDER:$2|ترمیم کی}}",
+ "flow-rev-message-create-topic-summary": "$1 نے $3 میں خلاصہ موضوع {{GENDER:$2|تحریر کیا}}",
+ "flow-rev-message-edit-topic-summary": "$1 نے $3 میں خلاصہ موضوع {{GENDER:$2|تبدیل کیا}}",
+ "flow-rev-message-hid-post": "$1 نے \"$6\" پر [$4 تبصرہ] {{GENDER:$2|پوشیدہ کیا}} (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 نے \"$6\" پر [$4 تبصرہ] {{GENDER:$2|حذف کیا}} (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 نے \"$6\" پر [$4 تبصرہ] {{GENDER:$2|بحال کیا}} (<em>$5</em>)",
+ "flow-rev-message-hid-topic": "$1 نے \"$6\" پر [$4 موضوع] کو {{GENDER:$2|پوشیدہ کیا}} (<em>$5</em>)",
+ "flow-rev-message-deleted-topic": "$1 نے \"$6\" پر [$4 موضوع] {{GENDER:$2|حذف کیا}} (<em>$5</em>)",
+ "flow-rev-message-lock-topic-reason": "بطور برطرف شدہ نشان زد کیا",
+ "flow-rev-message-restore-topic-reason": "دوبارہ کھولیں",
+ "flow-rev-message-restored-topic": "$1 نے \"$6\" پر [$4 موضوع] {{GENDER:$2|بحال کیا}} (<em>$5</em>)",
+ "flow-rc-topic-of-board": "$1 $2 پر",
+ "flow-board-history": "\"$1\" تاریخچہ",
+ "flow-board-history-empty": "فی الوقت اس صفحہ کا تاریخچہ موجود نہیں ہے۔",
+ "flow-topic-history": "\"$1\" تاریچہ موضوع",
+ "flow-history-last4": "آخری 4 گھنٹے",
+ "flow-history-day": "آج",
+ "flow-history-week": "گزشتہ ہفتہ",
+ "flow-topic-comments": "{{PLURAL:$1|$1 تبصرہ|$1 تبصرے|0=پہلا تبصرہ {{GENDER:$2|کریں}}}}",
+ "flow-show-comments-title": "{{PLURAL:$1|تبصرہ دیکھیں|تبصرے دیکھیں}}",
+ "flow-hide-comments-title": "{{PLURAL:$1|تبصرہ چھپائیں|تبصرے چھپائیں}}",
+ "flow-comment-restored": "بحال شدہ تبصرہ",
+ "flow-comment-deleted": "حذف شدہ تبصرہ",
+ "flow-comment-hidden": "پوشیدہ تبصرہ",
+ "flow-comment-moderated": "زیر نگرانی تبصرہ",
+ "flow-last-modified": "$1 کے متعلق آخری مرتبہ ترمیم ہوئی",
+ "flow-workflow": "ورک فلو",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 نے '''$4''' پر {{GENDER:$1|جواب دیا}}۔",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 اور {{PLURAL:$5|دیگر}} نے <strong>$3</strong> پر {{GENDER:$1|تبصرہ کیا}}۔",
+ "flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 نے [[$3|$4]] پر آپ کے <span class=\"plainlinks\">[$5 مراسلہ]</span> میں {{GENDER:$1|ترمیم کی}}۔",
+ "flow-notification-edit-bundle": "$1 اور {{PLURAL:$5|دیگر|دیگر افراد}} نے $3 پر \"$2\" میں موجود ایک <span class=\"plainlinks\">[$4 مراسلہ]</span> میں {{GENDER:$1|ترمیم کی}}۔",
+ "notification-header-flow-new-topic-v2": "<strong>$3</strong> پر نیا موضوع <bdi> \"<strong>$4</strong>\"</bdi> تخلیق کیا گیا۔",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> پر $1 {{PLURAL:$1|نیا موضوع|نئے موضوعات}}",
+ "notification-header-flow-new-topic-user-talk": "<strong>آپ کے تبادلہ خیال صفحہ</strong> پر نیا موضوع شروع کیا گیا ہے: \"<strong>$4</strong>\"۔",
+ "notification-header-flow-post-reply": "$1 نے \"<strong>$4</strong>\" میں {{GENDER:$2|جواب دیا}}۔",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|ایک تازہ جواب|$1 نئے جواب|100=99+ نئے جواب}} \"<strong>$3</strong>\" میں۔",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|ایک تازہ جواب|$1 نئے جواب|100=99+ نئے جواب}} موضوع \"<strong>$3</strong>\" <strong> میں آپ کے تبادلۂ خیال صفحہ پر</strong>۔",
+ "notification-header-flow-post-edited-v2": "موضوع \"<strong>$1</strong>\" میں {{GENDER:$2|آپ }} کے تبصرے میں ترمیم کی گئی ہے۔",
+ "notification-header-flow-description-edited": "<strong>$1</strong> کی تفصیل میں ترمیم کی گئی ہے۔",
+ "notification-links-flow-description-edited-view-page": "صفحہ {{GENDER:$1|دیکھیں}}",
+ "notification-header-flow-topic-resolved": "موضوع \"<strong>$1</strong>\" حل کر لیا گیا۔",
+ "notification-header-flow-topic-reopened": "موضوع \"<strong>$1</strong>\" دوبارہ کھول دیا گیا۔",
+ "notification-email-subject-flow-topic-resolved": "موضوع \"<strong>$2</strong>\" کو حل کر دیا گیا۔",
+ "notification-email-batch-body-flow-topic-resolved": "موضوع \"<strong>$2</strong>\" کو حل کر دیا گیا۔",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 نے <strong>$3</strong> پر نیا موضوع {{GENDER:$1|شروع کیا}}۔",
+ "flow-notification-newtopic-bundle": "<strong><span class=\"plainlinks\">[$3 $2]</span></strong> پر {{PLURAL:$1|$1 نیا موضوع|$1 نئے موضوعات|250=250+ نئے موضوعات}}",
+ "flow-notification-rename": "$1 نے <span class=\"plainlinks\">[$2 $3]</span> کے عنوان کو [[$5|$6]] پر \"$4\" کی جانب {{GENDER:$1|منتقل کیا}}۔",
+ "flow-notification-mention": "$1 نے \"$4\" پر \"$3\" میں {{GENDER:$1|اپنے}} <span class=\"plainlinks\">[$2 post]</span> میں {{GENDER:$5|آپ کا}} {{GENDER:$1|تذکرہ کیا}}۔",
+ "flow-notification-link-text-view-post": "مراسلہ دیکھیں",
+ "flow-notification-link-text-view-topic": "موضوع دیکھیں",
+ "flow-notification-link-text-view-topics": "موضوعات دیکھیں",
+ "flow-notification-reply-email-subject": "$2 $3 پر",
+ "flow-notification-reply-email-batch-body": "$1 نے $3 پر \"$2\" کا {{GENDER:$1|جواب دیا}}",
+ "flow-notification-reply-email-batch-bundle-body": "$1 اور {{PLURAL:$4|دیگر|دیگر افراد}} نے $3 پر \"$2\" میں موجود ایک مراسلہ میں {{GENDER:$1|جواب دیا}}",
+ "flow-notification-mention-email-subject": "$1 نے $2 پر {{GENDER:$3|آپ کا}} {{GENDER:$1|جواب دیا}}",
+ "flow-notification-edit-email-subject": "$1 نے ایک مراسلہ میں {{GENDER:$1|ترمیم کی}}",
+ "flow-notification-edit-email-batch-bundle-body": "$1 اور {{PLURAL:$4|دیگر|دیگر افراد}} نے $3 پر \"$2\" میں موجود ایک مراسلہ میں {{GENDER:$1|ترمیم کی}}",
+ "flow-notification-rename-email-subject": "$1 نے آپ کے موضوع کا {{GENDER:$1|نام تبدیل کیا}}",
+ "flow-notification-rename-email-batch-body": "$1 نے $4 میں موجود آپ کے موضوع «$2» کا {{GENDER:$1|نام تبدیل کرکے}} «$3» {{GENDER:$1|کر دیا}}",
+ "flow-notification-newtopic-email-subject": "$1 نے $2 پر نیا موضوع {{GENDER:$1|شروع کیا}}",
+ "echo-category-title-flow-discussion": "فلو",
+ "echo-pref-tooltip-flow-discussion": "فلو میں مجھ سے متعلق پیش آمدہ اقدامات سے مجھے آگاہ کریں۔",
+ "flow-link-post": "مراسلہ",
+ "flow-link-topic": "موضوع",
+ "flow-link-history": "تاریخچہ",
+ "flow-link-post-revision": "مراسلہ نظرثانی",
+ "flow-link-topic-revision": "موضوع نظرثانی",
+ "flow-link-header-revision": "وضاحت نظرثانی",
+ "flow-link-summary-revision": "خلاصہ نظرثانی",
+ "flow-moderation-title-delete-post": "حذف مراسلہ؟",
+ "flow-moderation-title-hide-post": "مراسلہ چھپائیں؟",
+ "flow-moderation-title-undelete-post": "مراسلہ بحال کریں؟",
+ "flow-moderation-title-unhide-post": "مراسلہ دکھائیں؟",
+ "flow-moderation-placeholder-hide-post": "براہ کرم مراسلہ کی پوشیدگی کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-placeholder-undelete-post": "براہ کرم مراسلہ کی بحالی کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-placeholder-unhide-post": "براہ کرم مراسلہ کی پوشیدگی ختم کرنے کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-confirm-delete-post": "حذف",
+ "flow-moderation-confirm-hide-post": "چھپائیں",
+ "flow-moderation-confirm-undelete-post": "بحال",
+ "flow-moderation-confirm-unhide-post": "دکھائیں",
+ "flow-moderation-confirm-delete-topic": "حذف",
+ "flow-moderation-confirm-hide-topic": "چھپائیں",
+ "flow-moderation-confirm-undelete-topic": "بحال",
+ "flow-moderation-confirm-unhide-topic": "دکھائیں",
+ "flow-moderation-confirmation-delete-post": "مراسلہ حذف کر دیا گیا۔\nاس مراسلہ کے متعلق $1 کو اطلاع دینا {{GENDER:$2|نہ بھولیں}}۔",
+ "flow-moderation-confirmation-hide-post": "مراسلہ پوشیدہ کر دیا گیا۔\nاس مراسلہ کے متعلق $1 کو اطلاع دینا {{GENDER:$2|نہ بھولیں}}۔",
+ "flow-moderation-confirmation-undelete-post": "آپ نے اوپر موجود مراسلہ کو بحال کر دیا ہے۔",
+ "flow-moderation-confirmation-unhide-post": "آپ نے اوپر موجود مراسلہ کی پوشیدگی ختم کر دی ہے۔",
+ "flow-moderation-confirmation-delete-topic": "یہ موضوع حذف کر دیا گیا ہے۔",
+ "flow-moderation-confirmation-hide-topic": "یہ موضوع پوشیدہ کر دیا گیا ہے۔",
+ "flow-moderation-confirmation-undelete-topic": "آپ نے اس موضوع کو بحال کر دیا ہے۔",
+ "flow-moderation-confirmation-unhide-topic": "آپ نے اس موضوع کی پوشیدگی کو ختم کر دیا ہے۔",
+ "flow-moderation-title-delete-topic": "حذف موضوع؟",
+ "flow-moderation-title-hide-topic": "موضوع چھپاییں؟",
+ "flow-moderation-title-undelete-topic": "موضوع بحال کریں؟",
+ "flow-moderation-title-unhide-topic": "موضوع دکھائیں؟",
+ "flow-moderation-placeholder-delete-topic": "براہ کرم اس موضوع کی حذف شدگی کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-placeholder-hide-topic": "براہ کرم اس موضوع کی پوشیدگی کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-placeholder-undelete-topic": "براہ کرم اس موضوع کی بحالی کی وجہ {{GENDER:$3|تحریر کریں}}۔",
+ "flow-moderation-placeholder-unhide-topic": "براہ کرم اس موضوع کی پوشیدگی ختم کرنے کی وجہ {{GENDER:$3|تحریر کریں}}",
+ "flow-topic-permalink-warning": "یہ موضوع [$2 $1] کو شروع کیا گیا تھا",
+ "flow-topic-permalink-warning-user-board": "یہ موضوع [$2 {{GENDER:$1|$1}} کے صفحہ] پر شروع کیا گیا تھا",
+ "flow-compare-revisions-revision-header": "{{GENDER:$2|$2}} کا ترمیم کردہ نسخہ از $1",
+ "action-flow-create-board": "کسی بھی جگہ پر فلو تختے تخلیق کرنے کا",
+ "right-flow-create-board": "تمام جگہوں پر فلو تختے کی تخلیق",
+ "right-flow-hide": "فلو کے موضوعات اور مراسلوں کی پوشیدگی",
+ "right-flow-lock": "فلو موضوعات کو بطور برطرف شدہ نشان زد کریں",
+ "right-flow-delete": "فلو کے موضوعات اور مراسلوں کو حذف کریں",
+ "right-flow-edit-post": "دیگر صارفین کے فلو مراسلوں کی ترمیم",
+ "right-flow-suppress": "فلو نسخوں کی پوشیدگی",
+ "flow-terms-of-use-new-topic": "\"{{int:flow-newtopic-save}}\" کلک کرنے پر آپ کو اس ویکی کے شرائط استعمال سے متفق تصور کیا جائے گا۔",
+ "flow-terms-of-use-reply": "\"{{int:flow-reply-link}}\" کلک کرنے پر آپ کو اس ویکی کے شرائط استعمال سے متفق تصور کیا جائے گا۔",
+ "flow-terms-of-use-edit": "تبدیلیاں محفوظ کرنے پر آپ کو اس ویکی کے شرائط استعمال سے متفق تصور کیا جائے گا۔",
+ "flow-anon-warning": "آپ لاگ ان نہیں ہیں۔ آئی پی پتہ کے بجائے اپنے نام سے منسوب کرنے کے لیے آپ [$1 لاگ ان] یا [$2 کھاتہ بنا سکتے ہیں]۔",
+ "flow-cancel-warning": "آپ نے اس شکل میں متن درج کیا ہے۔ کیا آپ واقعی اسے مسترد کرنا چاہتے ہیں؟",
+ "flow-topic-first-heading": "$1 پر موضوع",
+ "flow-topic-html-title": "$1 $2 پر",
+ "flow-topic-count": "موضوعات ($1)",
+ "flow-load-more": "مزید لوڈ کریں",
+ "flow-no-more-fwd": "گزشتہ موضوعات موجود نہیں ہیں",
+ "flow-newest-topics": "تازہ ترین موضوعات",
+ "flow-recent-topics": "موجودہ زیر بحث موضوعات",
+ "flow-sorting-tooltip-newest": "ابھی {{GENDER:|آپ}} تازہ ترین موضوعات پڑھ رہے ہیں۔ مزید اختیارات کے لیے کلک کریں۔",
+ "flow-sorting-tooltip-recent": "ابھی {{GENDER:|آپ}} حال ہی میں فعال رہنے والے موضوعات پڑھ رہے ہیں۔ مزید اختیارات کے لیے کلک کریں۔",
+ "flow-toggle-small-topics": "مختصر موضوعات ملاحظہ کریں",
+ "flow-toggle-topics": "محض موضوعات ملاحظہ کریں",
+ "flow-toggle-topics-posts": "موضوعات و مراسلات دونوں ملاحظہ کریں",
+ "flow-terms-of-use-summarize": "\"{{int:flow-topic-action-update-topic-summary}}\" کلک کرنے پر آپ کو اس کے شرائط استعمال سے متفق تصور کیا جائے گا۔",
+ "flow-whatlinkshere-post": "از [$1 مراسلہ]",
+ "flow-whatlinkshere-header": "از [$1 وضاحت]",
+ "flow-whatlinkshere-post-summary": "از [$1 وضاحت]",
+ "structureddiscussions": "فلو",
+ "flow-special-type": "طرز",
+ "flow-special-type-post": "مراسلہ",
+ "flow-special-type-workflow": "ورک فلو",
+ "flow-special-uuid": "UUID",
+ "flow-special-enableflow-legend": "نئے صفحہ پر فلو فعال کریں",
+ "flow-special-enableflow-page": "صفحہ کا عنوان جس پر فلو کو فعال کرنا ہے",
+ "flow-special-enableflow-header": "تختۂ فلو کی ابتدائی وضاحت (ویکی متن)",
+ "flow-special-enableflow-board-already-exists": "[[$1]] پر پہلے ہی سے تختۂ فلو موجود ہے۔",
+ "flow-special-enableflow-invalid-title": "درج کردہ عنوان نادرست ہے",
+ "flow-special-enableflow-board-creation-not-allowed": "آپ کو [[:$1]] پر فلو صفحہ بنانے کی اجازت نہیں ہے۔",
+ "flow-special-enableflow-confirmation": "آپ نے [[$1]] پر تختۂ فلو کو تخلیق کیا۔",
+ "flow-conversion-archive-page-name-format": "%s/وثق %d\n%s/وثق%d\n%s/وثق %d\n%s/وثق%d",
+ "flow-spam-confirmedit-using-failure": "کیپچا میں ایک تکنیکی خرابی تھی۔ اگر تبدیلی نہیں کر پا رہے ہیں تو براہ کرم اپنے متن کو نقل کریں، صفحہ تازہ کریں اور دوبارہ کوشش کریں۔",
+ "flow-embedding-unsupported": "ابھی گفتگو کو شامل نہیں کیا جا سکتا۔",
+ "mw-ui-unsubmitted-confirm": "اس صفحہ میں آپ کی غیر محفوظ کردہ تبدیلیاں موجود ہیں۔ کیا آپ واقعی اسے چھوڑنا چاہتے ہیں؟",
+ "flow-post-undo-hide": "استرجع پوشیدگی",
+ "flow-post-undo-delete": "استرجع حذف شدگی",
+ "flow-topic-undo-hide": "استرجع پوشیدگی",
+ "flow-topic-undo-delete": "استرجع حذف شدگی",
+ "flow-importer-wt-converted-template": "ویکی متن تبادلہ خیال صفحہ فلو میں منتقل",
+ "flow-importer-wt-converted-template-content": "سابقہ گفتگو مورخہ {{#time: dF،Yء|{{{date}}}}} کو <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> پر وثق میں منتقل کر دی گئی۔",
+ "flow-importer-wt-converted-archive-template": "منتقل شدہ ویکی متن تبادلہ خیال صفحہ کا وثق",
+ "flow-edited": "ترمیم شدہ",
+ "flow-edited-by": "ترمیم شدہ از $1",
+ "flow-previous-diff": "→ پُرانی ترمیم",
+ "flow-next-diff": "نئی ترمیم ←",
+ "flow-undo": "استرجع",
+ "flow-undo-latest-revision": "حالیہ نسخہ",
+ "flow-undo-your-text": "آپ کی تحریر",
+ "flow-undo-edit-header": "ترمیم وضاحت",
+ "flow-undo-edit-topic-summary": "ترمیم خلاصہ موضوع",
+ "flow-undo-edit-post": "ترمیم مراسلہ",
+ "group-flow-bot": "فلو روبہ جات",
+ "group-flow-bot-member": "فلو روبہ",
+ "grouppage-flow-bot": "Project:فلو روبہ جات",
+ "flow-ve-mention-context-item-label": "تذکرہ",
+ "flow-ve-mention-inspector-title": "تذکرہ",
+ "flow-ve-mention-inspector-remove-label": "حذف",
+ "flow-ve-mention-placeholder": "صارف نام",
+ "flow-ve-mention-tool-title": "صارف کا تذکرہ کریں",
+ "flow-ve-mention-template-title": "فلو میں آپ کا ذکر",
+ "flow-ve-mention-inspector-invalid-user": "صارف نام \"$1\" مندرج نہیں ہے۔",
+ "flow-wikitext-editor-help": "ویکی متن $1۔",
+ "flow-wikitext-editor-help-and-preview": "ویکی متن میں $1 ہے اور آپ کسی بھی وقت $2 دیکھ سکتے ہیں۔",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|مارک اپ زیر استعمال]]",
+ "flow-wikitext-editor-help-preview-the-result": "نتیجہ کی نمائش",
+ "flow-wikitext-switch-editor-tooltip": "بصری خانہ ترمیم شروع کریں",
+ "flow-ve-switch-editor-tool-title": "ویکی متن خانہ ترمیم شروع کریں",
+ "flow-mark-revision-patrolled-link-text": "اس صفحہ کو بطور مراجعت شدہ نشان زد کریں",
+ "flow-mark-revision-patrolled-link-title": "اس صفحہ کو بطور مراجعت شدہ نشان زد کریں",
+ "flow-mark-diff-patrolled-link-text": "بطور مراجعت شدہ نشان زد کریں",
+ "flow-mark-diff-patrolled-link-title": "بطور مراجعت شدہ نشان زد کریں",
+ "flow-talk-page-beta-feature-message": "تبادلۂ خیال صارف پر فلو",
+ "flow-talk-page-beta-feature-description": "{{GENDER:|آپ}} کے تبادلہ خیال صفحہ پر نیا نظام گفتگو فعال کرتا ہے۔ اس نظام کے ذریعہ گفتگو اور تبادلہ خیال میں انتہائی سہولت ہو جاتی ہے نیز گفتگو کی اطلاعات بھی موصول ہوتی رہتی ہیں۔ بعد ازاں پہلے سے موجود ویکی متن والی گفتگو وثق میں منتقل ہو جائے گی۔ چونکہ یہ سہولت از خود فعال نہیں ہوتی، لہذا صارفین کو دستی طور پر اسے فعال کرنا لازمی ہے۔ اس سہولت کو غیر فعال کرنے کے بعد گزشتہ تبادلہ خیال صفحہ وثق سے ختم ہو کر واپس اصل صفحہ پر آجائے گا اور نیا نظام گفتگو فلو غیر فعال ہو جائے گا۔",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|صارف کا تبادلۂ خیال صفحہ دیکھیے}}",
+ "flow-notification-enabled-on-talkpage-email-subject-message": "$2 پر نیا نظام گفتگو",
+ "flow-beta-feature-add-archive-template-edit-summary": "اضافہ سانچہ وثق",
+ "flow-beta-feature-remove-archive-template-edit-summary": "حذف سانچہ وثق",
+ "flow-dialog-cancelconfirm-title": "واقعی؟",
+ "flow-dialog-cancelconfirm-message": "کیا آپ واقعی محفوظ کیے بغیر منسوخ کرنا چاہتے ہیں؟",
+ "flow-dialog-cancelconfirm-keep": "ترمیم جاری رکھیں",
+ "flow-dialog-cancelconfirm-discard": "تبدیلیاں مسترد کریں",
+ "flow-optin-restore-wikitext": "وثق شدہ ویکی متن صفحہ بحال کریں۔",
+ "flow-optin-restore-flow-board": "وثق شدہ صفحہ گفتگو بحال کریں۔",
+ "flow-guidedtour-optin-welcome": "{{GENDER:$1|آپ کے}} نئے تبادلۂ خیال صفحہ پر {{GENDER:$1|خوش آمدید}}!",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|آپ}} کا تبادلۂ خیال صفحہ ایسی جگہ ہے جہاں دوسرے صارفین {{GENDER:$1|آپ}} سے رابطہ کرتے ہیں۔ فلو کے اس نئے نظام کے ذریعہ نئے موضوعات کو شروع کرنا اور گفتگو کو یکجا رکھنا نسبتاً زیادہ سہل ہے۔",
+ "flow-guidedtour-optin-find-old-conversations": "{{GENDER:$1|اپنی}} پرانی گفتگو تلاش کریں",
+ "flow-guidedtour-optin-find-old-conversations-description": "گزشتہ گفتگو کو صفحۂ وثق میں منتقل کر دیا گیا ہے۔",
+ "flow-guidedtour-optin-feedback": "ہمیں {{GENDER:$1|اپنا}} تبصرہ ارسال کریں!",
+ "flow-guidedtour-optin-feedback-description": "تجرباتی خصوصیات کے خانہ سے {{GENDER:$1|آپ}} کسی بھی وقت نئے نظام کو غیر فعال کر سکتے ہیں۔"
}
diff --git a/Flow/i18n/vi.json b/Flow/i18n/vi.json
index 8db3e8ec..070f3286 100644
--- a/Flow/i18n/vi.json
+++ b/Flow/i18n/vi.json
@@ -8,25 +8,51 @@
"Max20091",
"Dinhxuanduyet",
"KhangND",
- "Darcy Le"
+ "Darcy Le",
+ "Nnemo",
+ "Nguyên Lê",
+ "Macofe"
]
},
- "enableflow": "Kích hoạt Flow",
- "flow-desc": "Hệ thống quản lý luồng làm việc",
+ "enablestructureddiscussions": "Kích hoạt Flow",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3}}Ngừng theo dõi hoạt động mới tại “$1”",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3}}Bạn không còn theo dõi trang “$1”",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "Điều này sẽ không ảnh hưởng đến các đề tài riêng mà {{GENDER:$3}}bạn đang theo dõi. Bạn có thể theo dõi [$2 trang này] bất cứ lúc nào.",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3}}Ngừng theo dõi đề tài này",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3}}Bạn không còn theo dõi “$1”",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3}}Bạn có thể theo dõi [$2 đề tài này] bất cứ lúc nào.",
+ "flow-desc": "Hệ thống thảo luận",
"flow-talk-taken-over-comment": "/* Trang này đã được chuyển đổi thành bảng tin Flow */",
"log-name-flow": "Nhật trình hoạt động Flow",
"logentry-delete-flow-delete-post": "$1 {{GENDER:$2}}đã xóa một [$4 bài đăng] về “[[$3|$5]]” tại [[$6]]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa bài đăng khỏi một đề tài tại [[$3]]",
"logentry-delete-flow-restore-post": "$1 {{GENDER:$2}}đã phục hồi một [$4 bài đăng] về “[[$3|$5]]” tại [[$6]]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2}}đã đàn áp một [$4 đề tài] về “[[$3|$5]]” tại [[$6]]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2}}đã phục hồi bài đăng tại một đề tài tại [[$3]]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2}}đã xóa hẳn một [$4 đề tài] về “[[$3|$5]]” tại [[$6]]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa hẳn bài đăng khỏi một đề tài tại [[$3]]",
"logentry-suppress-flow-restore-post": "$1 {{GENDER:$2}}đã xóa một [$4 bài đăng] về “[[$3|$5]]” tại [[$6]]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa bài đăng khỏi một đề tài tại [[$3]]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2}}đã xóa đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa một đề tài tại [[$3]]",
"logentry-delete-flow-restore-topic": "$1 {{GENDER:$2}}đã phục hồi đề tài “[[$3|$5]]” tại [[$6]]",
- "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2}}đã đàn áp đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã phục hồi một bài đăng tại [[$3]]",
+ "logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2}}đã xóa hẳn đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa hẳn một đề tài tại [[$3]]",
"logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2}}đã xóa đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã xóa một đề tài tại [[$3]]",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2}}đã đánh dấu giải quyết đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã đánh dấu giải quyết một đề tài tại [[$3]]",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2}}đã mở lại đề tài “[[$3|$5]]” tại [[$6]]",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1 {{GENDER:$2}}đã mở lại một đề tài tại [[$3]]",
"logentry-import-lqt-to-flow-topic": "[[$1|$2]] trên [[$3]] được nhập từ LiquidThreads sang Flow",
+ "abusefilter-edit-builder-vars-board-articleid": "Số trang của bảng tin Flow",
+ "abusefilter-edit-builder-vars-board-namespace": "Không gian tên của bảng tin Flow",
+ "abusefilter-edit-builder-vars-board-text": "Tên của bảng tin Flow",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "Tên đầy đủ của bảng tin Flow",
"flow-user-moderated": "Người dùng bị kiểm duyệt",
"flow-board-header-browse-topics-link": "Xem các đề tài",
"flow-board-header": "Thông tin về bảng tin này",
+ "flow-board-description-can-not-edit": "Không sửa đổi được",
"flow-board-collapse-description": "Ẩn miêu tả",
"flow-board-expand-description": "Hiện miêu tả",
"flow-topic-collapse-siderail": "Đọc ở chế độ rộng",
@@ -34,10 +60,10 @@
"flow-edit-header-link": "Sửa miêu tả",
"flow-post-moderated-toggle-hide-show": "Hiển thị bình luận đã bị $2 {{GENDER:$1}}ẩn",
"flow-post-moderated-toggle-delete-show": "Hiển thị bình luận đã bị $2 {{GENDER:$1}}xóa",
- "flow-post-moderated-toggle-suppress-show": "Hiển thị bình luận đã bị $2 {{GENDER:$1}}đàn áp",
+ "flow-post-moderated-toggle-suppress-show": "Hiển thị bình luận đã bị $2 {{GENDER:$1}}xóa hẳn",
"flow-post-moderated-toggle-hide-hide": "Ẩn bình luận đã bị $2 {{GENDER:$1}}ẩn",
"flow-post-moderated-toggle-delete-hide": "Ẩn bình luận đã bị $2 {{GENDER:$1}}xóa",
- "flow-post-moderated-toggle-suppress-hide": "Ẩn bình luận đã bị $2 {{GENDER:$1}}đàn áp",
+ "flow-post-moderated-toggle-suppress-hide": "Ẩn bình luận đã bị $2 {{GENDER:$1}}xóa hẳn",
"flow-topic-moderated-reason-prefix": "Lý do:",
"flow-hide-post-content": "Bình luận này đã bị {{GENDER:$1}}ẩn bởi $1 ([$2 lịch sử])",
"flow-hide-title-content": "Đề tài này đã bị {{GENDER:$1}}ẩn bởi $1",
@@ -45,20 +71,20 @@
"flow-delete-post-content": "Bình luận này đã bị {{GENDER:$1}}xóa bởi $1 ([$2 lịch sử])",
"flow-delete-title-content": "Đề tài này đã bị {{GENDER:$1}}xóa bởi $1",
"flow-delete-header-content": "{{GENDER:$1}}Xóa bởi $2",
- "flow-suppress-post-content": "Bình luận này đã bị {{GENDER:$1}}đàn áp bởi $1 ([$2 lịch sử])",
- "flow-suppress-title-content": "Đề tài này đã bị {{GENDER:$1}}đàn áp bởi $1",
- "flow-suppress-header-content": "{{GENDER:$1}}Đàn áp bởi $2",
- "flow-suppress-usertext": "<em>Tên người dùng bị đàn áp</em>",
+ "flow-suppress-post-content": "Bình luận này đã bị {{GENDER:$1}}xóa hẳn bởi $1 ([$2 lịch sử])",
+ "flow-suppress-title-content": "Đề tài này đã bị {{GENDER:$1}}xóa hẳn bởi $1",
+ "flow-suppress-header-content": "{{GENDER:$1}}Xóa hẳn bởi $2",
+ "flow-suppress-usertext": "<em>Tên người dùng bị xóa hẳn</em>",
"flow-post-actions": "Tác vụ",
"flow-topic-actions": "Tác vụ",
"flow-cancel": "Hủy bỏ",
- "flow-skip-summary": "Bỏ qua tóm lược",
+ "flow-skip-summary": "Bỏ qua",
"flow-edit-summary-placeholder": "Tóm lược kết quả cuộc thảo luận này",
"flow-summary-authored": "Tóm lược của $1",
"flow-summary-edited": "Tóm lược được {{GENDER:$1}}sửa đổi lần cuối bởi $1",
"flow-show-change": "Xem thay đổi",
"flow-last-modified-by": "Sửa đổi lần cuối cùng bởi $1",
- "flow-stub-post-content": "''Không thể lấy bài đăng này do một lỗi kỹ thuật.''",
+ "flow-stub-post-content": "<em>Không thể tải bài đăng này do một lỗi kỹ thuật.</em>",
"flow-newtopic-title-placeholder": "Đề tài mới",
"flow-newtopic-content-placeholder": "Nhắn tin mới tại “$1”",
"flow-newtopic-header": "Thêm đề tài mới",
@@ -73,10 +99,10 @@
"flow-reply-link-anonymously": "Trả lời vô danh",
"flow-thank-link": "{{GENDER:$1}}{{GENDER:$2}}Cảm ơn",
"flow-thank-link-title": "{{GENDER:$1}}{{GENDER:$2}}Cảm ơn người đăng bài một cách công khai",
- "flow-history-action-suppress-post": "đàn áp",
+ "flow-history-action-suppress-post": "xóa hẳn",
"flow-history-action-delete-post": "xóa",
"flow-history-action-hide-post": "ẩn",
- "flow-history-action-unsuppress-post": "ngừng đàn áp",
+ "flow-history-action-unsuppress-post": "phục hồi",
"flow-history-action-undelete-post": "phục hồi",
"flow-history-action-unhide-post": "bỏ ẩn",
"flow-history-action-restore-post": "phục hồi",
@@ -85,13 +111,13 @@
"flow-post-edited": "Bài đăng được sửa đổi bởi $1 $2",
"flow-post-action-view": "Liên kết thường trực",
"flow-post-action-post-history": "Lịch sử",
- "flow-post-action-suppress-post": "Đàn áp",
+ "flow-post-action-suppress-post": "Xóa hẳn",
"flow-post-action-delete-post": "Xóa",
"flow-post-action-hide-post": "Ẩn",
"flow-post-action-edit-post": "Sửa đổi",
"flow-post-action-edit-post-submit": "Lưu các thay đổi",
"flow-post-action-edit-post-submit-anonymously": "Lưu thay đổi vô danh",
- "flow-post-action-unsuppress-post": "Ngừng đàn áp",
+ "flow-post-action-unsuppress-post": "Phục hồi",
"flow-post-action-undelete-post": "Phục hồi",
"flow-post-action-unhide-post": "Ngừng ẩn",
"flow-post-action-restore-post": "Phục hồi",
@@ -107,10 +133,10 @@
"flow-topic-action-summarize-topic": "Tóm lược",
"flow-topic-action-resummarize-topic": "Sửa đề tài đề tài",
"flow-topic-action-update-topic-summary": "Cập nhật tóm lược",
- "flow-topic-action-suppress-topic": "Đàn áp đề tài",
+ "flow-topic-action-suppress-topic": "Xóa hẳn đề tài",
"flow-topic-action-unhide-topic": "Ngừng ẩn đề tài",
"flow-topic-action-undelete-topic": "Phục hồi đề tài",
- "flow-topic-action-unsuppress-topic": "Ngừng đàn áp đề tài",
+ "flow-topic-action-unsuppress-topic": "Phục hồi đề tài bị xóa hẳn",
"flow-topic-action-restore-topic": "Phục hồi đề tài",
"flow-topic-action-undo-moderation": "Lùi lại",
"flow-topic-notification-subscribe-title": "Đề tài này đã được thêm vào danh sách theo dõi của {{GENDER:$1}}bạn.",
@@ -119,26 +145,27 @@
"flow-board-notification-subscribe-description": "{{GENDER:$1}}Bạn sẽ được thông báo khi nào một đề tài mới được tạo ra trên bảng tin này.",
"flow-topic-action-watchlist-add": "Theo dõi đề tài này",
"flow-topic-action-watchlist-remove": "Ngừng theo dõi",
- "flow-error-allowcreation-no-usedb": "allowCreation cần <var>$wgContentHandlerUseDB</var> phải là <code>true</code>.",
- "flow-error-allowcreation-already-exists": "Trang đã tồn tại nhưng không được phép tồn tại",
+ "flow-error-allowcreation-no-usedb": "Kích hoạt Flow trên một trang cụ thể cần <var>$wgContentHandlerUseDB</var> phải là <code>true</code>.",
+ "flow-error-allowcreation-already-exists": "Không thể di chuyển bảng tin Flow vì trang đích đã tồn tại.",
"flow-error-allowcreation-flow-create-board": "Người dùng không có quyền “{{int:right-flow-create-board}}”",
+ "flow-error-can-not-edit-logged-out": "Hiện tại bạn không có thể tham gia. Hãy thử đăng nhập.",
+ "flow-error-can-not-edit-logged-in": "Hiện tại bạn không có quyền tham gia.",
"flow-error-http": "Đã xuất hiện lỗi khi liên lạc với máy chủ.",
- "flow-error-other": "Đã xuất hiện lỗi bất ngờ.",
- "flow-error-external": "Đã xuất hiện lỗi.<br />Lỗi nhận được là: $1",
+ "flow-error-external": "Đã xuất hiện lỗi. Lỗi nhận được là: $1",
"flow-error-topic-is-locked": "Đề tài này đã được giải quyết nên không thể tác động tiếp.",
"flow-error-lock-moderated-post": "Bạn không thể đánh dấu giải quyết một bài đăng được điều phối.",
- "flow-error-external-multi": "Đã xuất hiện lỗi.<br />$1",
"flow-error-missing-content": "Bài đăng không có nội dung. Bài đăng phải có nội dung để lưu.",
"flow-error-missing-summary": "Bạn phải gửi một bản tóm tắt.",
"flow-error-missing-title": "Đề tài không có tiêu đề. Đề tài phải có tiêu đề để lưu.",
- "flow-error-parsoid-failure": "Không thể phân tích nội dung vì Parsoid bị thất bại.",
+ "flow-error-parsoid-failure": "Không thể truyền nội dung: Lỗi kết nối với máy chủ để chuyển đổi giữa mã wiki và HTML. Xin vui lòng kiểm tra kết nối Internet của bạn hoặc thử lại sau nếu vẫn gặp vấn đề này. Nếu vẫn gặp lỗi này, xin vui lòng báo cáo lỗi.",
+ "flow-error-protected-autoconfirmed-logged-in": "Bảng tin này bị khóa. Chỉ có những người dùng tự xác nhận có thể tham gia. Lý do: $1",
+ "flow-error-protected-autoconfirmed-logged-out": "Bảng tin này bị khóa. Chỉ có những người dùng tự xác nhận đã đăng nhập có thể tham gia. Lý do: $1",
+ "flow-error-protected-sysop-logged-in": "Bảng tin này bị khóa. Chỉ có những người dùng có quyền bảo quản viên có thể tham gia. Lý do: $1",
+ "flow-error-protected-sysop-logged-out": "Bảng tin này bị khóa. Chỉ có những người dùng có quyền bảo quản viên đã đăng nhập có thể tham gia. Lý do: $1",
+ "flow-error-protected-unknown-reason": "Không rõ",
"flow-error-missing-replyto": "Tham số “replyTo” không được cung cấp. Tham số này cần để thực hiện tác vụ “trả lời”.",
- "flow-error-invalid-replyto": "Tham số “replyTo” có giá trị không hợp lệ. Không tìm thấy bài đăng.",
- "flow-error-delete-failure": "Thất bại khi xóa mục này.",
- "flow-error-hide-failure": "Thất bại khi ẩn mục này.",
"flow-error-missing-postId": "Tham số “postId” không được cung cấp. Tham số này cần để xóa hoặc phục hồi bài đăng.",
"flow-error-invalid-postId": "Tham số “postId” có giá trị không hợp lệ. Không tìm thấy bài đăng được chỉ định ($1).",
- "flow-error-restore-failure": "Thất bại khi phục hồi mục này.",
"flow-error-invalid-moderation-state": "Một giá trị không hợp lệ cho một tham số (“moderationState”) đã được gửi vào API Flow",
"flow-error-invalid-moderation-reason": "Xin vui lòng cung cấp một lý do kiểm duyệt",
"flow-error-not-allowed": "Không có đủ quyền để thực hiện tác vụ này",
@@ -152,7 +179,7 @@
"flow-error-not-allowed-delete-extract": "Đề tài này đã bị xóa. Mục nhật trình xóa của đề tài được đưa ra dưới đây để tiện theo dõi.",
"flow-error-not-allowed-reply-to-delete-topic-extract": "Bạn không thể trả lời vì đề tài này đã bị xóa. Mục nhật trình xóa của đề tài được đưa ra dưới đây để tiện theo dõi.",
"flow-error-not-allowed-suppress-extract": "Đề tài này đã bị xóa. Mục nhật trình xóa của đề tài được đưa ra dưới đây để tiện theo dõi.",
- "flow-error-not-allowed-reply-to-suppress-topic-extract": "Bạn không thể trả lời vì đề tài này đã bị đàn áp. Mục nhật trình đàn áp của đề tài được đưa ra dưới đây để tiện theo dõi.",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "Bạn không thể trả lời vì đề tài này đã bị xóa hẳn. Mục nhật trình xóa hẳn của đề tài được đưa ra dưới đây để tiện theo dõi.",
"flow-error-title-too-long": "Tên đề tài không được dài hơn $1 byte.",
"flow-error-no-existing-workflow": "Luồng làm việc này chưa tồn tại.",
"flow-error-not-a-post": "Không thể lưu tên đề tài thành nội dung của bài đăng.",
@@ -164,6 +191,7 @@
"flow-error-default": "Đã xuất hiện lỗi.",
"flow-error-invalid-input": "Đã cung cấp một giá trị không hợp lệ khi tải nội dung luồng.",
"flow-error-invalid-title": "Đã cung cấp tên trang không hợp lệ.",
+ "flow-error-invalid-parameter": "Tham số bị thiếu hoặc không hợp lệ khi gọi hàm",
"flow-error-fail-load-history": "Thất bại khi tải nội dung lịch sử.",
"flow-error-missing-revision": "Không tìm thấy phiên bản để tải nội dung luồng.",
"flow-error-fail-commit": "Thất bại khi lưu nội dung luồng.",
@@ -171,6 +199,7 @@
"flow-error-revision-comparison": "Chỉ có thể so sánh hai phiên bản của cùng bài đăng.",
"flow-error-missing-topic-title": "Không tìm thấy tên đề tài cho luồng làm việc hiện tại.",
"flow-error-missing-metadata": "Không tìm thấy siêu dữ liệu cần thiết cho thay đổi này.",
+ "flow-error-different-page": "Luồng làm việc Flow không có liên quan đến trang này.",
"flow-error-fail-load-data": "Thất bại khi tải dữ liệu được yêu cầu.",
"flow-error-invalid-workflow": "Không tìm thấy luồng làm việc.",
"flow-error-process-data": "Đã xuất hiện lỗi khi xử lý dữ liệu trong yêu cầu của bạn.",
@@ -180,12 +209,12 @@
"flow-error-no-commit": "Không thể lưu tác vụ được chỉ định.",
"flow-error-content-too-long": "Nội dung quá lớn. Nội dung không được quá $1 byte sau khi được bung.",
"flow-error-move-topic": "Chưa hỗ trợ việc di chuyển một trang đề tài.",
- "flow-error-move-no-create-permissions": "Cần có quyền “{{int:right-flow-create-board}}” để di chuyển một bảng tin Flow.",
"flow-error-invalid-topic-uuid-title": "Tựa trang sai",
"flow-error-invalid-topic-uuid": "Tên trang yêu cầu là không hợp lệ. Các trang trong không gian tên Topic được Flow tự động tạo ra.",
"flow-error-unknown-workflow-id-title": "Đề tài không rõ",
"flow-error-unknown-workflow-id": "Đề tài yêu cầu không tồn tại.",
"flow-error-search": "Không thể hoàn tất truy vấn của bạn vì một vấn đề tạm thời. Xin vui lòng thử lại sau.",
+ "flow-error-invalid-undelete": "Không thể phục hồi trang vì hiện có bảng tin chiếm đoạt tên trang.",
"flow-edit-header-placeholder": "Miêu tả bảng tin này",
"flow-edit-header-submit": "Lưu miêu tả",
"flow-edit-header-submit-anonymously": "Lưu miêu tả vô danh",
@@ -206,12 +235,12 @@
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2}}đã sửa tóm lược đề tài $3",
"flow-rev-message-hid-post": "$1 {{GENDER:$2}}đã ẩn một [$4 bình luận] về “$6” (<em>$5</em>).",
"flow-rev-message-deleted-post": "$1 {{GENDER:$2}}đã xóa một [$4 bình luận] về “$6” (<em>$5</em>).",
- "flow-rev-message-suppressed-post": "$1 {{GENDER:$2}}đã đàn áp một [$4 bình luận] về “$6” (<em>$5</em>).",
+ "flow-rev-message-suppressed-post": "$1 {{GENDER:$2}}đã xóa hẳn một [$4 bình luận] về “$6” (<em>$5</em>).",
"flow-rev-message-restored-post": "$1 {{GENDER:$2}}đã phục hồi một [$4 bình luận] về “$6” (<em>$5</em>).",
"flow-rev-message-hid-topic": "$1 {{GENDER:$2}}đã ẩn [$4 đề tài] “$6” (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2}}đã xóa [$4 đề tài] “$6” (<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2}}đã đàn áp [$4 đề tài] “$6” (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2}}đã đánh dấu giải quyết [$4 đề tài] $6 (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2}}đã xóa hẳn [$4 đề tài] “$6” (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2}}đã đánh dấu giải quyết [$4 đề tài] “$6” (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "đã giải quyết",
"flow-rev-message-restore-topic-reason": "đã mở lại",
"flow-rev-message-restored-topic": "$1 {{GENDER:$2}}đã phục hồi [$4 đề tài] “$6” (<em>$5</em>)",
@@ -234,31 +263,75 @@
"flow-comment-moderated": "Bài đăng kiểm duyệt",
"flow-last-modified": "Thay đổi lần cuối cùng vào khoảng $1",
"flow-workflow": "luồng làm việc",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1}}đã trả lời tại '''$4'''.",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 và $5 {{PLURAL:$6}}người khác đã trả lời tại '''$3'''.",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 {{GENDER:$1}}đã trả lời tại <strong>$4</strong>.",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 và {{PLURAL:$5|một người nữa|$5 người khác|100=99+ người khác}} {{GENDER:$1}}đã trả lời tại <strong>$3</strong>.",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 đã sửa đổi <span class=\"plainlinks\">[$5 bài đăng]</span> của bạn tại [[$3|$4]].",
- "flow-notification-edit-bundle": "$1 và $5 {{PLURAL:$6}}người khác đã {{GENDER:$1}}sửa đổi một <span class=\"plainlinks\">[$4 bài đăng]</span> về “$2” tại “$3”.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 đã tạo ra đề tài mới tại '''$3'''.",
- "flow-notification-newtopic-bundle": "{{PLURAL:$1|$1|250=250+}} đề tài mới trên '''<span class=\"plainlinks\">[$3 $2]</span>'''",
+ "flow-notification-edit-bundle": "$1 và {{PLURAL:$5|một người|$5 người|100=99+ người}} khác đã {{GENDER:$1}}sửa đổi một <span class=\"plainlinks\">[$4 bài đăng]</span> về “$2” tại “$3”.",
+ "notification-header-flow-new-topic-v2": "Đã tạo đề tài mới tại <strong>$3</strong>: <bdi>“<strong>$4</strong>”</bdi>.",
+ "notification-compact-header-flow-new-topic": "“<strong>$1</strong>”",
+ "notification-bundle-header-flow-new-topic": "{{PLURAL:$1|Một đề tài|$1 đề tài|100=99+ đề tài}} mới tại <strong>$3</strong>.",
+ "notification-header-flow-new-topic-user-talk": "Đề tài mới được tạo trên <strong>trang thảo luận của bạn</strong>: “<strong>$4</strong>”.",
+ "notification-bundle-header-flow-new-topic-user-talk": "{{PLURAL:$1|Một đề tài|$1 đề tài|100=99+ đề tài}} mới tại <strong>trang thảo luận của bạn</strong>.",
+ "notification-header-flow-post-reply": "$1 đã {{GENDER:$2}}trả lời trong “<strong>$4</strong>”.",
+ "notification-bundle-header-flow-post-reply-v2": "{{PLURAL:$1|Một trả lời|$1 trả lời|100=99+ trả lời}} mới trong “<strong>$3</strong>”.",
+ "notification-compact-header-flow-post-reply": "$1: <em>$3</em>.",
+ "notification-header-flow-post-reply-user-talk": "$1 {{GENDER:$2}}đã đăng trả lời tại <strong>trang thảo luận của bạn</strong> trong “<strong>$4</strong>”.",
+ "notification-bundle-header-flow-post-reply-user-talk": "{{PLURAL:$1|Một trả lời|$1 trả lời|100=99+ trả lời}} mới tại <strong>trang thảo luận của bạn</strong> trong “<strong>$3</strong>”.",
+ "notification-header-flow-post-edited-v2": "Bài đăng của {{GENDER:$2}}bạn trong “<strong>$1</strong>” đã được sửa đổi.",
+ "notification-bundle-header-flow-post-edited-v2": "Bài đăng của {{GENDER:$2}}bạn trong “<strong>$1</strong>” đã được sửa đổi nhiều lần.",
+ "notification-header-flow-post-edited-user-talk": "Bài đăng trong “<strong>$1</strong>” đã được sửa đổi tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-bundle-header-flow-post-edited-user-talk": "Bài đăng trong “<strong>$1</strong>” đã được sửa đổi nhiều lần tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-header-flow-topic-renamed-v2": "Đề tài “<strong>$1</strong>” đã được đổi tên thành “<strong>$2</strong>”.",
+ "notification-header-flow-topic-renamed-user-talk": "Đề tài “<strong>$1</strong>” đã được đổi tên thành “<strong>$2</strong>” tại <strong>trang thảo luận của {{GENDER:$3}}bạn</strong>.",
+ "notification-header-flow-summary-edited": "Tóm lược của “<strong>$1</strong>” đã được cập nhật.",
+ "notification-header-flow-summary-edited-first": "Đề tài “<strong>$1</strong>” đã được tóm lược.",
+ "notification-bundle-header-flow-summary-edited": "Tóm lược của “<strong>$1</strong>” đã được cập nhật nhiều lần.",
+ "notification-header-flow-summary-edited-user-talk": "Tóm lược của “<strong>$1</strong>” đã được cập nhật tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-header-flow-summary-edited-first-user-talk": "Đề tài “<strong>$1</strong>” đã được tóm lược tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-bundle-header-flow-summary-edited-user-talk": "Tóm lược của “<strong>$1</strong>” đã được cập nhật nhiều lần tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-email-subject-flow-summary-edited": "$1 đã cập nhật tóm lược của $2.",
+ "notification-email-batch-body-flow-summary-edited": "$1 đã cập nhật tóm lược của $2.",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1 và {{PLURAL:$3|một người|$3 người|100=99+ người}} khác đã cập nhật tóm lược của $2",
+ "notification-header-flow-mention-post": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$4}}bạn trong “<strong>$5</strong>”.",
+ "notification-header-flow-mention-header": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$4}}bạn trong lời miêu tả <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2}}đã nhắc đến {{GENDER:$4}}bạn trong “<strong>$5</strong>”.",
+ "notification-header-flow-enabled-on-talkpage": "Hệ thống thảo luận mới được kích hoạt tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-header-flow-description-edited": "Lời miêu tả <strong>$1</strong> đã được sửa đổi.",
+ "notification-header-flow-description-edited-user-talk": "Lời miêu tả đã được sửa đổi tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-bundle-header-flow-description-edited": "Lời miêu tả <strong>$1</strong> đã được sửa đổi nhiều lần.",
+ "notification-bundle-header-flow-description-edited-user-talk": "Lời miêu tả đã được sửa đổi nhiều lần tại <strong>trang thảo luận của {{GENDER:$2}}bạn</strong>.",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1}}Xem trang",
+ "notification-email-subject-flow-description-edited": "$1 đã sửa đổi lời miêu tả $2.",
+ "notification-email-batch-body-flow-description-edited": "$1 đã sửa đổi lời miêu tả $2.",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1 và {{PLURAL:$3|một người|$3 người|100=99+ người}} khác đã sửa đổi lời miêu tả $2",
+ "notification-header-flow-topic-resolved": "Đề tài “<strong>$1</strong>” đã được giải quyết.",
+ "notification-header-flow-topic-reopened": "Đề tài “<strong>$1</strong>” đã được mở lại.",
+ "notification-header-flow-topic-resolved-user-talk": "Đề tài “<strong>$1</strong>” đã được giải quyết tại <strong>trang thảo luận của bạn</strong>.",
+ "notification-header-flow-topic-reopened-user-talk": "Đề tài “<strong>$1</strong>” đã được mở lại tại <strong>trang thảo luận của bạn</strong>.",
+ "notification-email-subject-flow-topic-resolved": "Đề tài “<strong>$2</strong>” đã được giải quyết.",
+ "notification-email-batch-body-flow-topic-resolved": "Đề tài “<strong>$2</strong>” đã được giải quyết.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 đã tạo ra đề tài mới tại <strong>$3</strong>.",
+ "flow-notification-newtopic-bundle": "{{PLURAL:$1|Một đề tài|$1 đề tài|100=99+ đề tài}} mới trên <strong><span class=\"plainlinks\">[$3 $2]</span></strong>",
"flow-notification-rename": "$1 đã thay đổi tiêu đề của <span class=\"plainlinks\">[$2 $3]</span> thành “$4” tại [[$5|$6]].",
"flow-notification-mention": "$1 đã nói đến {{GENDER:$5}}bạn trong <span class=\"plainlinks\">[$2 bài đăng]</span> của họ về “$3” tại “$4”.",
"flow-notification-link-text-view-post": "Xem bài đăng",
"flow-notification-link-text-view-topic": "Xem đề tài",
+ "flow-notification-link-text-view-topics": "Xem đề tài",
"flow-notification-reply-email-subject": "$2 tại $3",
"flow-notification-reply-email-batch-body": "$1 đã trả lời “$2” tại $3",
- "flow-notification-reply-email-batch-bundle-body": "$1 và $4 {{PLURAL:$5}}người khác đã trả lời “$2” tại $3",
+ "flow-notification-reply-email-batch-bundle-body": "$1 và {{PLURAL:$4|một người|$4 người|100=99+ người}} khác đã trả lời “$2” tại $3",
"flow-notification-mention-email-subject": "$1 đã nói đến {{GENDER:$3}}bạn tại $2",
"flow-notification-mention-email-batch-body": "$1 đã nói đến {{GENDER:$4}}bạn trong bài đăng của họ về “$2” tại $3.",
"flow-notification-edit-email-subject": "$1 đã sửa đổi một bài đăng",
"flow-notification-edit-email-batch-body": "$1 đã sửa đổi một bài đăng về “$2” tại $3",
- "flow-notification-edit-email-batch-bundle-body": "$1 và $4 {{PLURAL:$5}}người khác đã sửa đổi một bài đăng về “$2” tại $3",
+ "flow-notification-edit-email-batch-bundle-body": "$1 và {{PLURAL:$4|một người|$4 người|100=99+ người}} khác đã sửa đổi một bài đăng về “$2” tại $3",
"flow-notification-rename-email-subject": "$1 đã đổi tên đề tài của bạn",
"flow-notification-rename-email-batch-body": "$1 đã đổi tên đề tài của bạn từ “$2” thành “$3” tại $4",
"flow-notification-newtopic-email-subject": "$1 đã bắt đầu một đề tài mới tại $2",
"flow-notification-newtopic-email-batch-body": "$1 đã bắt đầu một đề tài mới với tiêu đề “$2” tại $3",
- "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|$1|$1|250=250+}} đề tài mới trên $2",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "Thông báo cho tôi khi các hành động có liên quan đến tôi xảy ra trên Flow.",
+ "flow-notification-newtopic-email-batch-bundle-body": "{{PLURAL:$1|Một đề tài|$1 đề tài|100=99+ đề tài}} mới trên $2",
+ "echo-category-title-flow-discussion": "Thảo luận Flow",
+ "echo-pref-tooltip-flow-discussion": "Thông báo cho tôi về các hành động trong đề tài hoặc trang tôi theo dõi.",
"flow-link-post": "bài đăng",
"flow-link-topic": "đề tài",
"flow-link-history": "lịch sử",
@@ -266,52 +339,52 @@
"flow-link-topic-revision": "phiên bản đề tài",
"flow-link-header-revision": "phiên bản miêu tả",
"flow-link-summary-revision": "phiên bản tóm lược",
- "flow-moderation-title-suppress-post": "Đàn áp bài đăng?",
+ "flow-moderation-title-suppress-post": "Xóa hẳn bài đăng?",
"flow-moderation-title-delete-post": "Xóa bài đăng?",
"flow-moderation-title-hide-post": "Ẩn bài đăng?",
- "flow-moderation-title-unsuppress-post": "Ngừng đàn áp bài đăng?",
+ "flow-moderation-title-unsuppress-post": "Phục hồi bài đăng đã từng bị xóa hẳn?",
"flow-moderation-title-undelete-post": "Phục hồi bài đăng?",
"flow-moderation-title-unhide-post": "Ngừng ẩn bài đăng?",
- "flow-moderation-placeholder-suppress-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn đàn áp bài đăng này.",
+ "flow-moderation-placeholder-suppress-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn xóa hẳn bài đăng này.",
"flow-moderation-placeholder-delete-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn xóa bài đăng này.",
"flow-moderation-placeholder-hide-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn ẩn bài đăng này.",
- "flow-moderation-placeholder-unsuppress-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn ngừng đàn áp bài đăng này.",
+ "flow-moderation-placeholder-unsuppress-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn phục hồi bài đăng này đã từng bị xóa hẳn.",
"flow-moderation-placeholder-undelete-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn phục hồi bài đăng này.",
"flow-moderation-placeholder-unhide-post": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn ngừng ẩn bài đăng này.",
- "flow-moderation-confirm-suppress-post": "Đàn áp",
+ "flow-moderation-confirm-suppress-post": "Xóa hẳn",
"flow-moderation-confirm-delete-post": "Xóa",
"flow-moderation-confirm-hide-post": "Ẩn",
- "flow-moderation-confirm-unsuppress-post": "Ngừng đàn áp",
+ "flow-moderation-confirm-unsuppress-post": "Phục hồi",
"flow-moderation-confirm-undelete-post": "Phục hồi",
"flow-moderation-confirm-unhide-post": "Ngừng ẩn",
- "flow-moderation-confirm-suppress-topic": "Đàn áp",
+ "flow-moderation-confirm-suppress-topic": "Xóa hẳn",
"flow-moderation-confirm-delete-topic": "Xóa",
"flow-moderation-confirm-hide-topic": "Ẩn",
- "flow-moderation-confirm-unsuppress-topic": "Ngừng đàn áp",
+ "flow-moderation-confirm-unsuppress-topic": "Phục hồi",
"flow-moderation-confirm-undelete-topic": "Phục hồi",
"flow-moderation-confirm-unhide-topic": "Ngừng ẩn",
- "flow-moderation-confirmation-suppress-post": "Bài đăng đã được đàn áp thành công. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
- "flow-moderation-confirmation-delete-post": "Bài đăng đã được xóa thành công. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
- "flow-moderation-confirmation-hide-post": "Bài đăng đã được ẩn thành công. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
- "flow-moderation-confirmation-unsuppress-post": "Bạn đã ngừng đàn áp bài đăng ở trên thành công.",
- "flow-moderation-confirmation-undelete-post": "Bạn đã phục hồi bài đăng ở trên thành công.",
- "flow-moderation-confirmation-unhide-post": "Bạn đã ngừng ẩn bài đăng ở trên thành công.",
- "flow-moderation-confirmation-suppress-topic": "Đề tài này đã được đàn áp.",
+ "flow-moderation-confirmation-suppress-post": "Bài đăng đã được xóa hẳn. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
+ "flow-moderation-confirmation-delete-post": "Bài đăng đã được xóa. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
+ "flow-moderation-confirmation-hide-post": "Bài đăng đã được ẩn. Xin hãy {{GENDER:$2}}nghĩ đến việc gửi phản hồi cho $1 về bài đăng này.",
+ "flow-moderation-confirmation-unsuppress-post": "Bạn đã phục hồi bài đăng ở trên đã từng bị xóa hẳn.",
+ "flow-moderation-confirmation-undelete-post": "Bạn đã phục hồi bài đăng ở trên.",
+ "flow-moderation-confirmation-unhide-post": "Bạn đã ngừng ẩn bài đăng ở trên.",
+ "flow-moderation-confirmation-suppress-topic": "Đề tài này đã được xóa hẳn.",
"flow-moderation-confirmation-delete-topic": "Đề tài này đã được xóa.",
"flow-moderation-confirmation-hide-topic": "Đề tài này đã được ẩn.",
- "flow-moderation-confirmation-unsuppress-topic": "Bạn đã ngừng đàn áp đề tài này thành công.",
- "flow-moderation-confirmation-undelete-topic": "Bạn đã phục hồi đề tài này thành công.",
- "flow-moderation-confirmation-unhide-topic": "Bạn đã ngừng ẩn đề tài này thành công.",
- "flow-moderation-title-suppress-topic": "Đàn áp đề tài?",
+ "flow-moderation-confirmation-unsuppress-topic": "Bạn đã phục hồi đề tài này đã từng bị xóa hẳn.",
+ "flow-moderation-confirmation-undelete-topic": "Bạn đã phục hồi đề tài này.",
+ "flow-moderation-confirmation-unhide-topic": "Bạn đã ngừng ẩn đề tài này.",
+ "flow-moderation-title-suppress-topic": "Xóa hẳn đề tài?",
"flow-moderation-title-delete-topic": "Xóa đề tài?",
"flow-moderation-title-hide-topic": "Ẩn đề tài?",
- "flow-moderation-title-unsuppress-topic": "Ngừng đàn áp đề tài?",
+ "flow-moderation-title-unsuppress-topic": "Phục hồi đề tài đã từng bị xóa hẳn?",
"flow-moderation-title-undelete-topic": "Phục hồi đề tài?",
"flow-moderation-title-unhide-topic": "Ngừng ẩn đề tài?",
- "flow-moderation-placeholder-suppress-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn đàn áp đề tài này.",
+ "flow-moderation-placeholder-suppress-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn xóa hẳn đề tài này.",
"flow-moderation-placeholder-delete-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn xóa đề tài này.",
"flow-moderation-placeholder-hide-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn ẩn đề tài này.",
- "flow-moderation-placeholder-unsuppress-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn ngừng đàn áp đề tài này.",
+ "flow-moderation-placeholder-unsuppress-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn phục hồi đề tài này đã từng bị xóa hẳn.",
"flow-moderation-placeholder-undelete-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn phục hồi đề tài này.",
"flow-moderation-placeholder-unhide-topic": "Xin vui lòng {{GENDER:$3}}giải thích tại sao bạn muốn ngừng ẩn đề tài này.",
"flow-topic-permalink-warning": "Đề tài này được bắt đầu tại [$2 $1]",
@@ -324,7 +397,7 @@
"flow-revision-permalink-warning-header-first": "Đây là liên kết thường trực đến phiên bản đầu tiên của miêu tả này.\nBạn có thể xem các phiên bản sau tại [$2 trang lịch sử bảng tin].",
"flow-compare-revisions-revision-header": "Phiên bản của $2 vào $1",
"flow-compare-revisions-header-post": "Trang này có các khác biệt giữa hai phiên bản của một bài đăng của $3 trong đề tài “[$5 $2]” tại [$4 $1].\nBạn có thể xem các phiên bản khác của bài đăng này tại [$6 trang lịch sử] của nó.",
- "flow-compare-revisions-header-postsummary": "Trang này có các khác biệt giữa hai phiên bản của một tóm lược bài đăng “[$4 $2]” tại [$3 $1].\nBạn có thể xem các phiên bản khác của bài đăng này tại [$5 trang lịch sử] của nó.",
+ "flow-compare-revisions-header-postsummary": "Trang này có các khác biệt giữa hai phiên bản của tóm lược đề tài “[$4 $2]” tại [$3 $1].\nBạn có thể xem các phiên bản khác của tóm lược đề tài này tại [$5 trang lịch sử] của đề tài.",
"flow-compare-revisions-header-header": "{{GENDER:$2}}Trang này có các khác biệt giữa hai phiên bản của lời miêu tả trên [$3 $1].\nBạn có thể xem các phiên bản khác của miêu tả này tại [$4 trang lịch sử] của nó.",
"action-flow-create-board": "tạo bảng tin Flow tại mọi nơi",
"right-flow-create-board": "Tạo bảng tin Flow tại mọi nơi",
@@ -332,7 +405,7 @@
"right-flow-lock": "Đánh dấu đề tài Flow là đã giải quyết",
"right-flow-delete": "Xóa đề tài và bài đăng Flow",
"right-flow-edit-post": "Sửa bài đăng Flow của người dùng khác",
- "right-flow-suppress": "Đàn áp phiên bản Flow",
+ "right-flow-suppress": "Xóa hẳn phiên bản Flow",
"flow-terms-of-use-new-topic": "Với việc bấm “{{int:flow-newtopic-save}}”, bạn chấp nhận các điều khoản sử dụng của wiki này.",
"flow-terms-of-use-reply": "Với việc bấm “{{int:flow-reply-link}}”, bạn chấp nhận các điều khoản sử dụng của wiki này.",
"flow-terms-of-use-edit": "Với việc lưu các thay đổi của bạn, bạn chấp nhận các điều khoản sử dụng của wiki này.",
@@ -356,7 +429,7 @@
"flow-whatlinkshere-post": "từ một [$1 bài đăng]",
"flow-whatlinkshere-header": "từ [$1 miêu tả]",
"flow-whatlinkshere-post-summary": "từ [$1 tóm lược]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "Trang đặc biệt này đổi hướng đến luồng làm việc hoặc bài đăng Flow ứng với UUID.",
"flow-special-type": "Kiểu",
"flow-special-type-post": "Bài đăng",
@@ -370,10 +443,11 @@
"flow-special-enableflow-invalid-title": "Tên trang đã cung cấp không hợp lệ.",
"flow-special-enableflow-board-creation-not-allowed": "Bạn không được phép tạo bảng tin Flow tại [[:$1]].",
"flow-special-enableflow-page-is-liquidthreads": "Có trang LiquidThreads tại [[:$1]].",
- "flow-special-enableflow-confirmation": "Bạn đã tạo bảng tin Flow thành công tại [[$1]].",
+ "flow-special-enableflow-confirmation": "Bạn đã tạo bảng tin Flow tại [[$1]].",
"flow-conversion-archive-page-name-format": "%s/Lưu %d\n%s/Lưu%d\n%s/lưu %d\n%s/lưu%d\n%s/Lưu trữ %d\n%s/lưu trữ %d",
"flow-conversion-archive-flow-page-name-format": "%s/Lưu Flow %d\n%s/LưuFlow%d",
"flow-spam-confirmedit-form": "Xin vui lòng giải hình CAPTCHA bên dưới để xác nhận rằng bạn là con người: $1",
+ "flow-spam-confirmedit-using-failure": "Đã xuất hiện lỗi kỹ thuật về hình CAPTCHA. Nếu bạn không thể lưu thay đổi của mình, xin hãy sao chép văn bản của bạn, tải lại trang, và thử lại.",
"flow-embedding-unsupported": "Chưa có thể nhúng thảo luận vào trang khác.",
"mw-ui-unsubmitted-confirm": "Bạn có thay đổi chưa được lưu trên trang này. Bạn có chắc chắn muốn rời trang và mất các thay đổi của bạn?",
"flow-post-undo-hide": "hoàn ẩn",
@@ -387,118 +461,19 @@
"flow-importer-lqt-converted-template": "Trang LQT chuyển đổi qua Flow",
"flow-importer-lqt-converted-template-content": "Lịch sử cũ của trang được lưu trữ tại <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> vào {{#time: \"ngày\" j M \"năm\" Y | {{{date}}} }}.",
"flow-importer-lqt-converted-archive-template": "Lưu trữ trang LQT chuyển đổi",
- "flow-importer-lqt-converted-archive-template-content": "Đây là một trang LiquidThreads được lưu trữ. '''Xin đừng sửa đổi nội dung của trang này.''' Xin hãy đưa các ý kiến mới vào [[{{{from}}}|trang thảo luận hiện tại]].",
+ "flow-importer-lqt-converted-archive-template-content": "Đây là một trang LiquidThreads được lưu trữ. <strong>Xin đừng sửa đổi nội dung của trang này.</strong> Xin hãy đưa các ý kiến mới vào [[{{{from}}}|trang thảo luận hiện tại]].",
"flow-importer-wt-converted-template": "Trang thảo luận mã wiki chuyển đổi qua Flow",
"flow-importer-wt-converted-template-content": "Thảo luận cũ được lưu trữ tại <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> vào {{#time: \"ngày\" j M \"năm\" Y | {{{date}}} }}.",
"flow-importer-wt-converted-archive-template": "Lưu trữ trang thảo luận mã wiki chuyển đổi",
- "flow-importer-wt-converted-archive-template-content": "Trang này là một bản lưu trữ. '''Xin đừng sửa đổi nội dung của trang này.''' Xin hãy đưa các ý kiến mới vào [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|trang thảo luận hiện tại]].",
- "flow-importer-lqt-suppressed-user-template": "Bài đăng LQT được nhập của người dùng đàn áp",
- "flow-importer-lqt-suppressed-user-template-content": "Phiên bản này được nhập từ LiquidThreads trong khi tác giả là một người dùng đã bị đàn áp. Tác giả được đổi thành người dùng hiện tại.",
+ "flow-importer-wt-converted-archive-template-content": "Trang này là một bản lưu trữ. <strong>Xin đừng sửa đổi nội dung của trang này.</strong> Xin hãy đưa các ý kiến mới vào [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|trang thảo luận hiện tại]].",
+ "flow-importer-lqt-suppressed-user-template": "Bài đăng LQT được nhập của người dùng bị xóa hẳn",
+ "flow-importer-lqt-suppressed-user-template-content": "Phiên bản này được nhập từ LiquidThreads trong khi tác giả là một người dùng đã bị xóa hẳn. Tác giả được đổi thành người dùng hiện tại.",
"flow-importer-lqt-different-author-signature-template": "Bài đăng LQT được nhập có người ký tên khác",
- "flow-importer-lqt-different-author-signature-template-content": "''Bài này do [[User:{{{authorUser}}}|{{{authorUser}}}]] đăng nhưng có chữ ký của [[User:{{{signatureUser}}}|{{{signatureUser}}}]].''",
- "apihelp-flow-description": "Cho phép thực hiện các tác vụ trên các trang Flow.",
- "apihelp-flow-param-submodule": "Bộ phận con Flow để gọi.",
- "apihelp-flow-param-page": "Trang để thực hiện tác vụ.",
- "apihelp-flow-example-1": "Sửa đổi lời miêu tả của “[[Talk:Sandbox]]”",
- "apihelp-flow+close-open-topic-description": "Bị phản đối; hãy sử dụng [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]].",
- "apihelp-flow+close-open-topic-param-moderationState": "Trạng thái mới của đề tài, hoặc “lock” (khóa) hoặc “unlock” (mở khóa).",
- "apihelp-flow+close-open-topic-param-reason": "Lý do khóa hoặc mở khóa đề tài.",
- "apihelp-flow+edit-header-description": "Sửa đổi lời miêu tả bảng tin.",
- "apihelp-flow+edit-header-param-prev_revision": "Số phiên bản của tóm lược hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
- "apihelp-flow+edit-header-param-content": "Nội dung miêu tả.",
- "apihelp-flow+edit-header-param-format": "Định dạng của miêu tả (wikitext|html)",
- "apihelp-flow+edit-header-example-1": "Sửa đổi lời miêu tả của [[Talk:Sandbox]]",
- "apihelp-flow+edit-post-description": "Sửa đổi nội dung của một bài đăng.",
- "apihelp-flow+edit-post-param-postId": "Mã số bài đăng.",
- "apihelp-flow+edit-post-param-prev_revision": "Số phiên bản bài đăng hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
- "apihelp-flow+edit-post-param-content": "Nội dung bài đăng.",
- "apihelp-flow+edit-post-param-format": "Định dạng của nội dung bài đăng (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "Sửa đổi một bài đăng trong [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-title-description": "Sửa đổi tiêu đề của đề tài.",
- "apihelp-flow+edit-title-param-prev_revision": "Số phiên bản tiêu đề hiện tại để kiểm tra có mâu thuẫn sửa đổi hay không.",
- "apihelp-flow+edit-title-param-content": "Nội dung tiêu đề.",
- "apihelp-flow+edit-title-example-1": "Sửa đổi tiêu đề của [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+edit-topic-summary-description": "Sửa đổi nội dung của tóm lược đề tài.",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "Số phiên bản tóm lược đề tài hiện tại, nếu có, để kiểm tra có mâu thuẫn sửa đổi hay không.",
- "apihelp-flow+edit-topic-summary-param-summary": "Nội dung tóm lược.",
- "apihelp-flow+edit-topic-summary-param-format": "Định dạng của tóm lược (wikitext|html)",
- "apihelp-flow+edit-topic-summary-example-1": "Sửa đổi tóm lược của [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+lock-topic-description": "Khóa hoặc mở khóa một đề tài Flow.",
- "apihelp-flow+lock-topic-param-moderationState": "Trạng thái mới của đề tài, hoặc <kbd>lock</kbd> (khóa) hoặc <kbd>unlock</kbd> (mở khóa).",
- "apihelp-flow+lock-topic-param-reason": "Lý do khóa hoặc mở khóa đề tài. Lưu ý rằng trình khác Flow trên wiki sẽ đề “Đã giải quyết” tại đây và đưa thêm thông tin vào tóm lược.",
- "apihelp-flow+lock-topic-example-1": "Khóa [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "Giữ lại một bài đăng Flow.",
- "apihelp-flow+moderate-post-param-moderationState": "Mức để giữ lại.",
- "apihelp-flow+moderate-post-param-reason": "Lý do giữ lại.",
- "apihelp-flow+moderate-post-param-postId": "Mã số bài đăng để giữ lại.",
- "apihelp-flow+moderate-post-example-1": "Xóa một bài đăng trong đề tài [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-topic-description": "Giữ lại một đề tài Flow.",
- "apihelp-flow+moderate-topic-param-moderationState": "Mức để giữ lại.",
- "apihelp-flow+moderate-topic-param-reason": "Lý do giữ lại.",
- "apihelp-flow+moderate-topic-example-1": "Xóa đề tài [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "Tạo một đề tài Flow mới theo luồng làm việc được đề tài.",
- "apihelp-flow+new-topic-param-topic": "Văn bản tiêu đề mới của đề tài.",
- "apihelp-flow+new-topic-param-content": "Nội dung của lời trả lời đầu tiên trong đề tài.",
- "apihelp-flow+new-topic-param-format": "Định dạng của lời trả lời đầu tiên của đề tài mới (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "Tạo đề tài mới trên [[Talk:Sandbox]]",
- "apihelp-flow+reply-description": "Trả lời một bài đăng.",
- "apihelp-flow+reply-param-replyTo": "Mã số bài đăng để trả lời.",
- "apihelp-flow+reply-param-content": "Nội dung bài đăng mới.",
- "apihelp-flow+reply-param-format": "Định dạng của bài đăng mới (wikitext|html)",
- "apihelp-flow+reply-example-1": "Trả lời một bài đăng trên [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-header-param-format": "Định dạng để trả về nội dung.",
- "apihelp-flow+view-header-description": "Xem miêu tả bảng tin.",
- "apihelp-flow+view-header-param-revId": "Tải phiên bản này thay vì phiên bản mới nhất.",
- "apihelp-flow+view-header-example-1": "Lấy miêu tả của [[Talk:Sandbox]] dưới dạng mã wiki",
- "apihelp-flow+view-post-description": "Xem một bài đăng.",
- "apihelp-flow+view-post-param-postId": "Mã số bài đăng để xem.",
- "apihelp-flow+view-post-param-format": "Định dạng để trả về nội dung.",
- "apihelp-flow+view-post-example-1": "Lấy nội dung của một bài đăng trên [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
- "apihelp-flow+view-post-history-description": "Xem lịch sử thay đổi của một bài đăng.",
- "apihelp-flow+view-post-history-param-postId": "ID của bài đăng để xem lịch sử thay đổi.",
- "apihelp-flow+view-post-history-param-format": "Định dạng để trả về nội dung.",
- "apihelp-flow+view-post-history-example-1": "Lấy các phiên bản của một bài đăng trên [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
- "apihelp-flow+view-topic-description": "Xem một đề tài.",
- "apihelp-flow+view-topic-example-1": "Xem [[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "Xem lịch sử thay đổi của một đề tài.",
- "apihelp-flow+view-topic-history-param-format": "Định dạng để trả về nội dung.",
- "apihelp-flow+view-topic-history-example-1": "Lấy các phiên bản của các bài đăng trên [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
- "apihelp-flow+view-topic-summary-description": "Xem một tóm lược đề tài.",
- "apihelp-flow+view-topic-summary-param-format": "Định dạng để trả về nội dung.",
- "apihelp-flow+view-topic-summary-param-revId": "Tải phiên bản này thay vì phiên bản mới nhất.",
- "apihelp-flow+view-topic-summary-example-1": "Xem tóm lược của [[Topic:S2tycnas4hcucw8w]] dưới dạng mã wiki",
- "apihelp-flow+view-topiclist-description": "Xem danh sách đề tài.",
- "apihelp-flow+view-topiclist-param-offset-dir": "Hướng để sắp xếp các đề tài.",
- "apihelp-flow+view-topiclist-param-sortby": "Thứ tự để sắp xếp các đề tài, hoặc <kbd>updated</kbd> (theo lúc cập nhật đề tài) hoặc <kbd>newest</kbd> (theo lúc tạo ra đề tài).",
- "apihelp-flow+view-topiclist-param-savesortby": "Lưu tùy chọn sắp xếp, nếu được đặt.",
- "apihelp-flow+view-topiclist-param-offset-id": "Giá trị chệch (dưới dạng UUID) để bắt đầu lấy đề tài; chỉ sử dụng khi sắp xếp theo thứ tự <kbd>newest</kbd>",
- "apihelp-flow+view-topiclist-param-offset": "Giá trị chệch (dưới dạng dấu thời gian cập nhật đề tài, dạng <code>TS_MW</code>, tức <code>YYYYMMDDHHMMSS</code>), để bắt đầu lấy đề tài; chỉ sử dụng khi sắp xếp theo thứ tự <kbd>updated</kbd>",
- "apihelp-flow+view-topiclist-param-limit": "Số đề tài để lấy.",
- "apihelp-flow+view-topiclist-example-1": "Liệt kê các đề tài trên [[Talk:Sandbox]]",
- "apihelp-flow-parsoid-utils-description": "Chuyển đổi văn bản giữa mã wiki và HTML.",
- "apihelp-flow-parsoid-utils-param-from": "Định dạng gốc để chuyển đổi nội dung.",
- "apihelp-flow-parsoid-utils-param-to": "Định dạng đích để chuyển đổi nội dung.",
- "apihelp-flow-parsoid-utils-param-content": "Nội dung để chuyển đổi.",
- "apihelp-flow-parsoid-utils-param-title": "Tên trang. Không thể sử dụng với $1pageid.",
- "apihelp-flow-parsoid-utils-param-pageid": "Mã số của trang. Không thể sử dụng với $1title.",
- "apihelp-flow-parsoid-utils-example-1": "Chuyển đổi mã wiki <nowiki>'''ví''' ''dụ''</nowiki> sang HTML",
- "apihelp-query+flowinfo-description": "Lấy thông tin cơ bản Flow về một trang.",
- "apihelp-query+flowinfo-example-1": "Lấy thông tin Flow về [[Talk:Sandbox]], [[Main Page]], và [[Talk:Flow]]",
- "apihelp-flow+undo-edit-header-description": "Lấy thông tin cần thiết để lùi lại sửa đổi miêu tả.",
- "apihelp-flow+undo-edit-header-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
- "apihelp-flow+undo-edit-header-param-endId": "Số phiên bản để ngừng lùi sửa.",
- "apihelp-flow+undo-edit-header-example-1": "Lấy thông tin về việc lùi lại một sửa đổi miêu tả tại [[Talk:Sandbox]]",
- "apihelp-flow+undo-edit-post-description": "Lấy thông tin cần thiết để lùi lại sửa đổi bài đăng.",
- "apihelp-flow+undo-edit-post-param-postId": "Mã số bài đăng để lùi lại.",
- "apihelp-flow+undo-edit-post-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
- "apihelp-flow+undo-edit-post-param-endId": "Số phiên bản để ngừng lùi sửa.",
- "apihelp-flow+undo-edit-post-example-1": "Lấy thông tin về việc lùi lại một sửa đổi bài đăng trong một đề tài cụ thể.",
- "apihelp-flow+undo-edit-topic-summary-description": "Lấy lại thông tin cần thiết để hoàn tác chỉnh sửa tóm tắt bài viết.",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "Số phiên bản để bắt đầu lùi sửa.",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "Số phiên bản để ngừng lùi sửa.",
- "apihelp-flow+undo-edit-topic-summary-example-1": "Lấy thông tin về việc lùi lại một sửa đổi tóm lược của một đề tài cụ thể.",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>Bài này do [[User:{{{authorUser}}}|{{{authorUser}}}]] đăng nhưng có chữ ký của [[User:{{{signatureUser}}}|{{{signatureUser}}}]].</em>",
"flow-edited": "Đã sửa đổi",
"flow-edited-by": "Sửa đổi bởi $1",
+ "flow-edited-by-header": "Miêu tả bảng tin được sửa đổi bởi $1",
+ "flow-edited-by-topic-title": "Tên đề tài được sửa đổi bởi $1",
"flow-lqt-redirect-reason": "Đang đổi hướng bài đăng LiquidThreads cũ đến bài đăng Flow đã được chuyển đổi",
"flow-talk-conversion-move-reason": "Chuyển đổi thảo luận dưới dạng mã wiki đến Flow từ $1",
"flow-talk-conversion-archive-edit-reason": "Chuyển đổi thảo luận dưới dạng mã wiki đến Flow",
@@ -524,16 +499,16 @@
"flow-ve-mention-inspector-invalid-user": "Chưa có tài khoản với tên “$1”.",
"flow-wikitext-editor-help": "Mã wiki $1.",
"flow-wikitext-editor-help-and-preview": "Mã wiki $1 và bạn có thể lúc nào $2.",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|có cú pháp dịnh dạng]]",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|có cú pháp dịnh dạng]]",
"flow-wikitext-editor-help-preview-the-result": "xem trước kết quả",
- "flow-wikitext-switch-editor-tooltip": "Chuyển sang Trình soạn thảo trực quan",
+ "flow-wikitext-switch-editor-tooltip": "Chuyển sang trình soạn thảo trực quan",
"flow-ve-switch-editor-tool-title": "Chuyển sang hộp sửa đổi mã wiki",
"flow-mark-revision-patrolled-link-text": "Đánh dấu tuần tra trang này",
"flow-mark-revision-patrolled-link-title": "Đánh dấu tuần tra trang này",
"flow-mark-diff-patrolled-link-text": "Đánh dấu tuần tra",
"flow-mark-diff-patrolled-link-title": "Đánh dấu tuần tra",
"flow-talk-page-beta-feature-message": "Flow trên trang thảo luận cá nhân",
- "flow-talk-page-beta-feature-description": "Kích hoạt một hệ thống thảo luận có cấu trúc mới trên trang thảo luận cá nhân của bạn. Flow làm các trang thảo luận đơn giản hơn, với các chức năng đăng bài và trả lời, và nó tự động gửi thông báo cho những người tham gia một cuộc thảo luận cụ thể. Các thảo luận đã tồn tại ở dạng mã wiki được lưu trữ. Tính năng này không được kích hoạt tự động; mỗi người phải kích hoạt thủ công. Nếu tắt tính năng này, bảng tin Flow sẽ được di chuyển đến một trang con và trang thảo luận cũ sẽ được khôi phục từ trang lưu trữ.",
+ "flow-talk-page-beta-feature-description": "Kích hoạt một hệ thống thảo luận có cấu trúc mới trên trang thảo luận cá nhân của bạn. Flow làm các trang thảo luận đơn giản hơn, với các chức năng đăng bài và trả lời, và nó tự động gửi thông báo cho những người tham gia một cuộc thảo luận cụ thể.<br /><br />Các thảo luận đã tồn tại ở dạng mã wiki được lưu trữ. Tính năng này không được kích hoạt tự động; mỗi người phải kích hoạt thủ công. Nếu tắt tính năng này, bảng tin Flow sẽ được di chuyển đến một trang con và trang thảo luận cũ sẽ được khôi phục từ trang lưu trữ. [[mw:Special:MyLanguage/Help:Flow/Activation#Activate|Tìm hiểu thêm về việc kích hoạt]].",
"flow-notification-link-text-enabled-on-talkpage": "Xem trang thảo luận cá nhân",
"flow-notification-enabled-on-talkpage-title": "Hệ thống thảo luận mới được kích hoạt trên trang thảo luận cá nhân của {{GENDER:$1}}bạn<br /><small>Có sẵn tại [[$2]]</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "Hệ thống thảo luận mới tại $2",
@@ -544,10 +519,16 @@
"flow-dialog-cancelconfirm-message": "Bạn có chắc chắn muốn hủy bỏ mà không lưu các sửa đổi?",
"flow-dialog-cancelconfirm-keep": "Sửa tiếp",
"flow-dialog-cancelconfirm-discard": "Bỏ các thay đổi",
+ "flow-optin-archive-wikitext": "Di chuyển trang mã wiki để có chỗ tạo bảng tin.",
+ "flow-optin-archive-flow-board": "Di chuyển trang bảng tin để có chỗ tạo trang mã wiki.",
+ "flow-optin-restore-wikitext": "Phục hồi trang mã wiki đã được lưu trữ.",
+ "flow-optin-restore-flow-board": "Phục hồi bảng tin đã được lưu trữ.",
"flow-guidedtour-optin-welcome": "Chào mừng {{GENDER:$1}}bạn đến với trang thảo luận cá nhân mới của bạn",
"flow-guidedtour-optin-welcome-description": "Trang thảo luận của {{GENDER:$1}}bạn là nơi để những thành viên khác có thể liên lạc với bạn. Nhờ Flow, mọi người có thể bắt đầu đề tài mới và theo dõi các cuộc thảo luận càng dễ dàng.",
"flow-guidedtour-optin-find-old-conversations": "Tìm các cuộc thảo luận cũ của {{GENDER:$1}}bạn",
"flow-guidedtour-optin-find-old-conversations-description": "Các cuộc thảo luận cũ đã được di chuyển đến một trang lưu trữ.",
"flow-guidedtour-optin-feedback": "{{GENDER:$1}}Gửi phản hồi cho chúng tôi!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1}}Bạn có thể lúc nào tìm hiểu thêm, cung cấp phản hồi, hoặc tắt hệ thống mới ở phần “Tính năng beta” trong Tùy chọn."
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1}}Bạn có thể lúc nào tìm hiểu thêm, cung cấp phản hồi, hoặc tắt hệ thống mới ở phần “Tính năng beta” trong Tùy chọn.",
+ "flow-action-not-page": "Đối tượng trang là thực thể của lớp sai",
+ "flow-action-wrong-title-content-model": "Trang do Flow xử lý, nhưng lớp Title cho biết rằng kiểu nội dung là “$1”, có nghĩa là cấu hình sai hoặc trạng thái mâu thuẫn. Ví dụ trang này có thể là một trang không thuộc về Flow nằm trong không gian tên Flow, và <code>rev_content_model</code> không được định rõ."
}
diff --git a/Flow/i18n/wuu.json b/Flow/i18n/wuu.json
new file mode 100644
index 00000000..37d837fc
--- /dev/null
+++ b/Flow/i18n/wuu.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "飞舞回堂前"
+ ]
+ },
+ "flow-wikitext-switch-editor-tooltip": "换成可视化编辑器"
+}
diff --git a/Flow/i18n/xmf.json b/Flow/i18n/xmf.json
index fd3fa8d1..b11b9187 100644
--- a/Flow/i18n/xmf.json
+++ b/Flow/i18n/xmf.json
@@ -5,6 +5,7 @@
]
},
"flow-topic-action-watchlist-remove": "გიშაჭარუაშ გოუქვაფა",
+ "notification-header-flow-post-edited-v2": "\"$1\"-ს თქვან პოსტი რედაქტირაფილი რე.",
"flow-mark-revision-patrolled-link-text": "დოშანე თე სტატია მუჭოთ პატრულირაფილი",
"flow-mark-revision-patrolled-link-title": "დოშანე თე სტატია მუჭოთ პატრულირაფილი",
"flow-mark-diff-patrolled-link-text": "დოშანე მუჭოთ პატრულირაფილი",
diff --git a/Flow/i18n/yi.json b/Flow/i18n/yi.json
index 63afc3f4..f1698e03 100644
--- a/Flow/i18n/yi.json
+++ b/Flow/i18n/yi.json
@@ -11,6 +11,7 @@
"flow-topic-actions": "אַקציעס",
"flow-cancel": "אַנולירן",
"flow-summary-authored": "רעזומע פון $1",
+ "flow-summary-edited": "רעזומע לעצט {{GENDER:$1|רעדאקטירט}} דורך $1",
"flow-newtopic-title-placeholder": "נײַע טעמע",
"flow-newtopic-content-placeholder": "אײַנגעבן א נײַע מעלדונג צו \"$1\"",
"flow-newtopic-header": "צולייגן א נײַע טעמע",
@@ -28,9 +29,6 @@
"flow-topic-action-watchlist": "אויפֿפאַסונג ליסטע",
"flow-topic-action-edit-title": "רעדאקטירן טיטל",
"flow-topic-action-history": "היסטאריע",
- "flow-error-delete-failure": "אויסמעקן דעם אביעקט אדורכגעפאלן.",
- "flow-error-hide-failure": "באהאלטן דעם אביעקט אדורכגעפאלן.",
- "flow-error-restore-failure": "צוריקשטעלן דעם אביעקט אדורכגעפאלן.",
"flow-edit-header-submit": "אויפהיטן באַשרײַבונג",
"flow-edit-title-submit": "ענדערן טיטל",
"flow-edit-post-submit": "איינגעבן ענדערונגען",
@@ -47,13 +45,16 @@
"flow-comment-deleted": "אויסגעמעקט הערה",
"flow-comment-hidden": "באהאלטענע הערה",
"flow-comment-moderated": "מאדערירטע הערה",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 און $5 {{PLURAL:$6|אן אנדערער|אנדערע}} {{GENDER:$1|האבן זיך אנגערופֿן}} דעם '''$3'''.",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|האט געשאפן}} א נײַע טעמע </span> אויף '''$3'''.",
- "echo-category-title-flow-discussion": "פֿלוסן",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 און {{PLURAL:$5|איין אנדערער|$5 אנדערע|100=מער ווי 99 אנדערע}} {{GENDER:$1|האבן געענטפערט}} ביי <strong>$3</strong>.",
+ "notification-header-flow-mention-post-summary": "$1 {{GENDER:$2|האט דערמאנט}} {{GENDER:$4|אייך}} אויף <strong>$5</strong>.",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 {{GENDER:$1|האט געשאפן}} א נײַע טעמע </span> אויף <strong>$3</strong>.",
+ "flow-notification-link-text-view-topics": "באקוקן טעמעס",
+ "echo-category-title-flow-discussion": "פֿלוס־שמועס",
"flow-link-topic": "טעמע",
"flow-link-history": "היסטאריע",
"flow-moderation-confirm-undelete-post": "מבטל זיין אויסמעקן",
"flow-moderation-confirm-undelete-topic": "מבטל זיין אויסמעקן",
+ "flow-importer-wt-converted-archive-template": "ארכיוו פאר פארוואנדלטע וויקיטעקסט רעדן־בלאט",
"flow-undo-your-text": "אייער טעקסט",
"flow-ve-mention-placeholder": "באניצער־נאמען"
}
diff --git a/Flow/i18n/zh-hans.json b/Flow/i18n/zh-hans.json
index ee367d3b..9a3ad1fa 100644
--- a/Flow/i18n/zh-hans.json
+++ b/Flow/i18n/zh-hans.json
@@ -18,25 +18,58 @@
"Duolaimi",
"御坂美琴",
"Shizhao",
- "LNDDYL"
+ "LNDDYL",
+ "Nnemo",
+ "EagerLin",
+ "范",
+ "Apflu",
+ "Quiddity",
+ "Cwek",
+ "飞舞回堂前",
+ "Chiefwei",
+ "Myy730",
+ "Arthur2e5"
]
},
- "enableflow": "启用Flow",
- "flow-desc": "工作流管理系统",
- "flow-talk-taken-over-comment": "/* 此页面已被转换至一个Flow讨论版 */",
- "log-name-flow": "Flow活动日志",
- "logentry-delete-flow-delete-post": "$1{{GENDER:$2|删除}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
- "logentry-delete-flow-restore-post": "$1{{GENDER:$2|还原}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
- "logentry-suppress-flow-suppress-post": "$1{{GENDER:$2|禁止}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
- "logentry-suppress-flow-restore-post": "$1{{GENDER:$2|删除}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
- "logentry-delete-flow-delete-topic": "$1{{GENDER:$2|删除}}在[[$6]]中的话题“[[$3|$5]]”",
- "logentry-delete-flow-restore-topic": "$1{{GENDER:$2|还原}}在[[$6]]中的话题“[[$3|$5]]”",
- "logentry-suppress-flow-suppress-topic": "$1{{GENDER:$2|禁止}}在[[$6]]中的话题“[[$3|$5]]”",
- "logentry-suppress-flow-restore-topic": "$1{{GENDER:$2|删除}}在[[$6]]中的话题“[[$3|$5]]”",
- "logentry-import-lqt-to-flow-topic": "在[[$3]]上的[[$1|$2]]已从LiquidThreads导入至Flow",
+ "enablestructureddiscussions": "启用结构化讨论",
+ "notification-dynamic-actions-flow-board-unwatch": "{{GENDER:$3|停止}}关注“$1”上新活动",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation": "{{GENDER:$3|您}}已不再监视页面“$1”",
+ "notification-dynamic-actions-flow-board-unwatch-confirmation-description": "这将不会影响{{GENDER:$3|您}}监视的单个话题。您可以随时监视[$2 此页面]。",
+ "notification-dynamic-actions-flow-topic-unwatch": "{{GENDER:$3|停止}}监视此话题",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation": "{{GENDER:$3|您}}已不再监视“$1”",
+ "notification-dynamic-actions-flow-topic-unwatch-confirmation-description": "{{GENDER:$3|您}}可以随时监视[$2 此话题]。",
+ "flow-desc": "讨论系统",
+ "flow-talk-taken-over-comment": "/* 此页面已转换为一个结构化讨论版块 */",
+ "log-name-flow": "结构化讨论活动日志",
+ "logentry-delete-flow-delete-post": "$1{{GENDER:$2|删除了}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
+ "logentry-delete-flow-delete-post-topic-title-not-visible": "$1{{GENDER:$2|删除}}了[[$3]]上一个话题的帖子",
+ "logentry-delete-flow-restore-post": "$1{{GENDER:$2|还原了}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
+ "logentry-delete-flow-restore-post-topic-title-not-visible": "$1{{GENDER:$2|还原}}了[[$3]]上一个话题的帖子",
+ "logentry-suppress-flow-suppress-post": "$1{{GENDER:$2|屏蔽了}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
+ "logentry-suppress-flow-suppress-post-topic-title-not-visible": "$1{{GENDER:$2|屏蔽}}了[[$3]]上一个话题的帖子",
+ "logentry-suppress-flow-restore-post": "$1{{GENDER:$2|解除屏蔽了}}在[[$6]]中“[[$3|$5]]”的一个[$4 帖子]",
+ "logentry-suppress-flow-restore-post-topic-title-not-visible": "$1{{GENDER:$2|删除}}了[[$3]]上一个话题的帖子",
+ "logentry-delete-flow-delete-topic": "$1{{GENDER:$2|删除了}}在[[$6]]中的话题“[[$3|$5]]”",
+ "logentry-delete-flow-delete-topic-topic-title-not-visible": "$1{{GENDER:$2|删除}}了[[$3]]上的话题",
+ "logentry-delete-flow-restore-topic": "$1{{GENDER:$2|还原了}}在[[$6]]中的话题“[[$3|$5]]”",
+ "logentry-delete-flow-restore-topic-topic-title-not-visible": "$1{{GENDER:$2|还原}}了[[$3]]上的话题",
+ "logentry-suppress-flow-suppress-topic": "$1{{GENDER:$2|屏蔽了}}在[[$6]]中的话题“[[$3|$5]]”",
+ "logentry-suppress-flow-suppress-topic-topic-title-not-visible": "$1{{GENDER:$2|屏蔽}}了[[$3]]上的话题",
+ "logentry-suppress-flow-restore-topic": "$1{{GENDER:$2|解除屏蔽了}}在[[$6]]中的话题“[[$3|$5]]”",
+ "logentry-suppress-flow-restore-topic-topic-title-not-visible": "$1{{GENDER:$2|删除}}了[[$3]]上的话题",
+ "logentry-lock-flow-lock-topic": "$1将位于[[$6]]的主题“[[$3|$5]]”{{GENDER:$2|标记}}为已解决",
+ "logentry-lock-flow-lock-topic-topic-title-not-visible": "$1将位于[[$3]]的话题{{GENDER:$2|标记}}为已解决",
+ "logentry-lock-flow-restore-topic": "$1已{{GENDER:$2|重启了}}位于[[$6]]的主题“[[$3|$5]]”",
+ "logentry-lock-flow-restore-topic-topic-title-not-visible": "$1{{GENDER:$2|重启}}了[[$3]]上的话题",
+ "logentry-import-lqt-to-flow-topic": "在[[$3]]上的[[$1|$2]]已从LiquidThreads导入至结构化讨论",
+ "abusefilter-edit-builder-vars-board-articleid": "结构化讨论版块的页面ID",
+ "abusefilter-edit-builder-vars-board-namespace": "结构化讨论版块的名字空间",
+ "abusefilter-edit-builder-vars-board-text": "结构化讨论版块的标题",
+ "abusefilter-edit-builder-vars-board-prefixedtext": "结构化讨论版块的完整标题",
"flow-user-moderated": "限制用户",
"flow-board-header-browse-topics-link": "浏览话题",
"flow-board-header": "关于此版块",
+ "flow-board-description-can-not-edit": "不可编辑",
"flow-board-collapse-description": "隐藏描述",
"flow-board-expand-description": "显示描述",
"flow-topic-collapse-siderail": "全宽阅读",
@@ -44,10 +77,10 @@
"flow-edit-header-link": "编辑描述",
"flow-post-moderated-toggle-hide-show": "显示被$2{{GENDER:$1|隐藏}}的评论",
"flow-post-moderated-toggle-delete-show": "显示被$2{{GENDER:$1|删除}}的评论",
- "flow-post-moderated-toggle-suppress-show": "显示被$2{{GENDER:$1|禁止}}的评论",
+ "flow-post-moderated-toggle-suppress-show": "显示被$2{{GENDER:$1|屏蔽}}的评论",
"flow-post-moderated-toggle-hide-hide": "隐藏被$2{{GENDER:$1|隐藏}}的评论",
"flow-post-moderated-toggle-delete-hide": "隐藏被$2{{GENDER:$1|删除}}的评论",
- "flow-post-moderated-toggle-suppress-hide": "隐藏被$2{{GENDER:$1|禁止}}的评论",
+ "flow-post-moderated-toggle-suppress-hide": "隐藏被$2{{GENDER:$1|屏蔽}}的评论",
"flow-topic-moderated-reason-prefix": "原因:",
"flow-hide-post-content": "此评论已被$1{{GENDER:$1|隐藏}}([$2 历史])",
"flow-hide-title-content": "此话题已被$1{{GENDER:$1|隐藏}}",
@@ -55,20 +88,20 @@
"flow-delete-post-content": "此评论已被$1{{GENDER:$1|删除}}([$2 历史])",
"flow-delete-title-content": "此话题已被$1{{GENDER:$1|删除}}",
"flow-delete-header-content": "被$2{{GENDER:$1|删除}}",
- "flow-suppress-post-content": "此评论已被$1{{GENDER:$1|禁止}}([$2 历史])",
- "flow-suppress-title-content": "此话题已被$1{{GENDER:$1|禁止}}",
- "flow-suppress-header-content": "被$2{{GENDER:$1|禁止}}",
- "flow-suppress-usertext": "<em>用户名已被禁止</em>",
+ "flow-suppress-post-content": "此评论已被$1{{GENDER:$1|屏蔽}}([$2 历史])",
+ "flow-suppress-title-content": "此话题已被$1{{GENDER:$1|屏蔽}}",
+ "flow-suppress-header-content": "被$2{{GENDER:$1|屏蔽}}",
+ "flow-suppress-usertext": "<em>用户名已被屏蔽</em>",
"flow-post-actions": "操作",
"flow-topic-actions": "操作",
"flow-cancel": "取消",
- "flow-skip-summary": "跳过摘要",
+ "flow-skip-summary": "跳过",
"flow-edit-summary-placeholder": "简单描述此次讨论的结果",
"flow-summary-authored": "由$1做出的摘要",
"flow-summary-edited": "摘要最近由$1{{GENDER:$1|编辑}}",
"flow-show-change": "显示更改",
"flow-last-modified-by": "$1最后{{GENDER:$1|修改}}",
- "flow-stub-post-content": "''由于一个技术错误,此帖子无法被恢复。''",
+ "flow-stub-post-content": "<em>由于一个技术错误,此内容无法被恢复。</em>",
"flow-newtopic-title-placeholder": "新话题",
"flow-newtopic-content-placeholder": "发布新消息至“$1”",
"flow-newtopic-header": "添加新话题",
@@ -83,10 +116,10 @@
"flow-reply-link-anonymously": "匿名回复",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|感谢}}}}",
"flow-thank-link-title": "公开{{GENDER:$1|{{GENDER:$2|感谢}}}}发帖人",
- "flow-history-action-suppress-post": "禁止",
+ "flow-history-action-suppress-post": "屏蔽",
"flow-history-action-delete-post": "删除",
"flow-history-action-hide-post": "隐藏",
- "flow-history-action-unsuppress-post": "解禁",
+ "flow-history-action-unsuppress-post": "解除屏蔽",
"flow-history-action-undelete-post": "还原",
"flow-history-action-unhide-post": "显示",
"flow-history-action-restore-post": "恢复",
@@ -95,13 +128,13 @@
"flow-post-edited": "帖子被$1于$2{{GENDER:$1|编辑}}",
"flow-post-action-view": "固定链接",
"flow-post-action-post-history": "历史",
- "flow-post-action-suppress-post": "禁止",
+ "flow-post-action-suppress-post": "屏蔽",
"flow-post-action-delete-post": "删除",
"flow-post-action-hide-post": "隐藏",
"flow-post-action-edit-post": "编辑",
"flow-post-action-edit-post-submit": "保存更改",
"flow-post-action-edit-post-submit-anonymously": "匿名保存更改",
- "flow-post-action-unsuppress-post": "解禁",
+ "flow-post-action-unsuppress-post": "解除屏蔽",
"flow-post-action-undelete-post": "还原",
"flow-post-action-unhide-post": "显示",
"flow-post-action-restore-post": "恢复",
@@ -117,10 +150,10 @@
"flow-topic-action-summarize-topic": "摘要",
"flow-topic-action-resummarize-topic": "编辑话题摘要",
"flow-topic-action-update-topic-summary": "更新摘要",
- "flow-topic-action-suppress-topic": "禁止话题",
+ "flow-topic-action-suppress-topic": "屏蔽话题",
"flow-topic-action-unhide-topic": "显示话题",
"flow-topic-action-undelete-topic": "还原话题",
- "flow-topic-action-unsuppress-topic": "解禁话题",
+ "flow-topic-action-unsuppress-topic": "解除屏蔽话题",
"flow-topic-action-restore-topic": "恢复话题",
"flow-topic-action-undo-moderation": "撤销",
"flow-topic-notification-subscribe-title": "此话题已加入了{{GENDER:$1|您}}的监视列表。",
@@ -129,27 +162,28 @@
"flow-board-notification-subscribe-description": "当此版发起新话题时,{{GENDER:$1|您}}将收到通知。",
"flow-topic-action-watchlist-add": "订阅这个主题",
"flow-topic-action-watchlist-remove": "取消订阅",
- "flow-error-allowcreation-no-usedb": "允许创建需要<var>$wgContentHandlerUseDB</var>设置为<code>true</code>。",
- "flow-error-allowcreation-already-exists": "页面已存在,但不需要存在",
+ "flow-error-allowcreation-no-usedb": "在特定页面启用结构化讨论需要<var>$wgContentHandlerUseDB</var>设置为<code>true</code>。",
+ "flow-error-allowcreation-already-exists": "页面已存在于目标中,因此结构化讨论版块不能移动至此。",
"flow-error-allowcreation-flow-create-board": "用户没有“{{int:right-flow-create-board}}”权限",
+ "flow-error-can-not-edit-logged-out": "您当前无法参与讨论。您可以尝试登录。",
+ "flow-error-can-not-edit-logged-in": "您当前无法参与讨论,因为您没有所需权限。",
"flow-error-http": "与服务器联系时出错。",
- "flow-error-other": "出现意外的错误。",
- "flow-error-external": "出现一个错误。<br />收到的错误信息:$1",
+ "flow-error-external": "出现一个错误。收到的错误信息:$1",
"flow-error-topic-is-locked": "此话题已解决,因此不再接受更多回复。",
"flow-error-lock-moderated-post": "您不能将被限制的帖子标记为已解决。",
- "flow-error-external-multi": "出错。<br />$1",
"flow-error-missing-content": "帖子无内容。只能保存有内容的帖子。",
"flow-error-missing-summary": "您必须提交一段摘要。",
"flow-error-missing-title": "此话题没有标题。必须有标题才能保存一个话题。",
- "flow-error-parsoid-failure": "由于Parsoid故障无法解析内容。",
+ "flow-error-parsoid-failure": "无法转移内容:连接用于wiki文本与HTML之间转换的服务器时出错。请检查您的互联网连接,或如果问题持续,请稍后尝试。如果您仍然看到该错误,请提交错误报告",
+ "flow-error-protected-autoconfirmed-logged-in": "此版块已被保护。只有自动确认用户可以参与讨论。原因:$1",
+ "flow-error-protected-autoconfirmed-logged-out": "此版块已被保护。只有已自动确认的登录用户可以参与讨论。原因:$1",
+ "flow-error-protected-sysop-logged-in": "此版块已被保护。只有拥有管理员特权的用户可以参与讨论。原因:$1",
+ "flow-error-protected-sysop-logged-out": "此版块已被保护。只有拥有管理员特权的登录用户可以参与讨论。原因:$1",
+ "flow-error-protected-unknown-reason": "未知",
"flow-error-missing-replyto": "没有提供“回复至”参数。此参数在“回复”操作中是必须的。",
- "flow-error-invalid-replyto": "“回复至”参数无效。找不到指定的帖子。",
- "flow-error-delete-failure": "删除此项失败。",
- "flow-error-hide-failure": "隐藏此项失败。",
- "flow-error-missing-postId": "没有指定“回复至”参数。需要此参数才能操控一个帖子。",
- "flow-error-invalid-postId": "“回复至”参数无效。找不到指定帖子($1)。",
- "flow-error-restore-failure": "恢复此项失败。",
- "flow-error-invalid-moderation-state": "用于参数“moderationState”的无效值被提交到了Flow API。",
+ "flow-error-missing-postId": "没有指定“贴子ID”参数。需要此参数才能操控一个帖子。",
+ "flow-error-invalid-postId": "“帖子ID”参数无效。找不到指定帖子($1)。",
+ "flow-error-invalid-moderation-state": "用于参数“moderationState”的无效值被提交到了结构化讨论API。",
"flow-error-invalid-moderation-reason": "请提供限制操作的原因。",
"flow-error-not-allowed": "没有足够权限执行此操作。",
"flow-error-not-allowed-hide": "此话题已被隐藏。",
@@ -162,7 +196,7 @@
"flow-error-not-allowed-delete-extract": "此话题已被删除。以下是该话题的删除日志以供参考。",
"flow-error-not-allowed-reply-to-delete-topic-extract": "您不能回复,因为此话题已被删除。下面提供该话题的删除日志以便参考。",
"flow-error-not-allowed-suppress-extract": "此话题已被删除。下面提供该话题的删除日志以便参考。",
- "flow-error-not-allowed-reply-to-suppress-topic-extract": "您不能回复,因为此话题已被禁止。下面提供该话题的监督日志以便参考。",
+ "flow-error-not-allowed-reply-to-suppress-topic-extract": "您不能回复,因为此话题已被屏蔽。下面提供该话题的监督日志以便参考。",
"flow-error-title-too-long": "话题标题需小于$1字节。",
"flow-error-no-existing-workflow": "该工作流尚未存在。",
"flow-error-not-a-post": "话题标题无法保存为帖子。",
@@ -170,32 +204,34 @@
"flow-error-missing-prev-revision-identifier": "上一版本标识符丢失。",
"flow-error-prev-revision-mismatch": "另一位用户已于几秒钟前编辑了此帖子。{{GENDER:$3|您}}确信继续重写最近更新?",
"flow-error-prev-revision-does-not-exist": "无法找到上一版本。",
- "flow-error-core-topic-deletion": "要删除一个话题,在Flow板块或[$1 话题页]上使用...菜单。不要直接访问话题的action=delete。",
+ "flow-error-core-topic-deletion": "要删除一个话题,在结构化讨论版块或[$1 话题页]上使用...菜单。不要在话题中直接访问action=delete。",
"flow-error-default": "出现错误。",
- "flow-error-invalid-input": "提供了无效的正在载入的flow内容的值。",
+ "flow-error-invalid-input": "加载结构化讨论内容时,加载的值无效。",
"flow-error-invalid-title": "提供了无效的页面标题。",
+ "flow-error-invalid-parameter": "丢失或无效的方法调用参数",
"flow-error-fail-load-history": "载入历史内容失败。",
- "flow-error-missing-revision": "无法找到需要加载Flow内容的版本。",
- "flow-error-fail-commit": "未能保存Flow内容。",
+ "flow-error-missing-revision": "无法找到需要加载结构化讨论内容的版本。",
+ "flow-error-fail-commit": "未能保存结构化讨论内容。",
"flow-error-insufficient-permission": "没有足够的权限访问内容。",
"flow-error-revision-comparison": "版本差异操作只能在同一帖子中的两个版本中进行。",
"flow-error-missing-topic-title": "找不到当前工作流的话题标题。",
"flow-error-missing-metadata": "无法找到此修订所需的元数据。",
+ "flow-error-different-page": "结构化讨论工作流未与此页面相关联。",
"flow-error-fail-load-data": "未能加载所请求的数据。",
"flow-error-invalid-workflow": "找不到请求的工作流。",
"flow-error-process-data": "处理您的请求中的数据时出错。",
- "flow-error-process-wikitext": "处理 HTML/维基文本 转换时出错。",
+ "flow-error-process-wikitext": "处理HTML/维基文本转换时出错。",
"flow-error-no-index": "未能找到索引来执行数据搜索。",
"flow-error-no-render": "无法识别指定操作。",
"flow-error-no-commit": "无法保存指定操作。",
"flow-error-content-too-long": "内容太长。扩张后内容限于$1字节。",
"flow-error-move-topic": "目前暂不支持移动话题页面。",
- "flow-error-move-no-create-permissions": "移动flow板块需要“{{int:right-flow-create-board}}”权限。",
"flow-error-invalid-topic-uuid-title": "错误标题",
- "flow-error-invalid-topic-uuid": "请求的页面标题无效。Topic名字空间的页面由Flow自动创建。",
+ "flow-error-invalid-topic-uuid": "请求的页面标题无效。Topic名字空间的页面由结构化讨论自动创建。",
"flow-error-unknown-workflow-id-title": "未知话题",
"flow-error-unknown-workflow-id": "请求的话题不存在。",
"flow-error-search": "由于出现暂时性的问题,我们未能完成您的搜索。请稍后再试。",
+ "flow-error-invalid-undelete": "页面不能恢复,因为目前在此有讨论版块。",
"flow-edit-header-placeholder": "描述此讨论板块",
"flow-edit-header-submit": "保存描述",
"flow-edit-header-submit-anonymously": "匿名保存描述",
@@ -203,25 +239,25 @@
"flow-edit-title-submit-anonymously": "匿名更改标题",
"flow-edit-post-submit": "提交更改",
"flow-edit-post-submit-anonymously": "匿名提交更改",
- "flow-rev-message-edit-post": "$1{{GENDER:$2|编辑}}“$4”的一个[$3 评论]。",
+ "flow-rev-message-edit-post": "$1{{GENDER:$2|已编辑}}于“$4”的[$3 评论]",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|编辑了}}一个帖子",
- "flow-rev-message-reply": "$1[$3 {{GENDER:$2|评论}}]“$4”(<em>$5</em>)",
- "flow-rev-message-reply-bundle": "<strong>$1个评论</strong>被添加",
+ "flow-rev-message-reply": "$1[$3 {{GENDER:$2|已评论}}]\"$4\"的话题(<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1个{{PLURAL:$1|评论}}</strong>被{{PLURAL:$1|添加}}",
"flow-rev-message-new-post": "$1{{GENDER:$2|已创建}}话题“[$3 $4]”",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|已创建}}新话题",
- "flow-rev-message-edit-title": "$1{{GENDER:$2|已修改}}话题标题自“$5”至“[$3 $4]”",
+ "flow-rev-message-edit-title": "$1已将话题的标题从“$5”{{GENDER:$2|更改}}为“[$3 $4]”",
"flow-rev-message-create-header": "$1{{GENDER:$2|已创建}}描述",
"flow-rev-message-edit-header": "$1{{GENDER:$2|已编辑}}描述",
"flow-rev-message-create-topic-summary": "$1{{GENDER:$2|已创建}}$3的话题摘要",
"flow-rev-message-edit-topic-summary": "$1{{GENDER:$2|已编辑}}$3的话题摘要",
"flow-rev-message-hid-post": "$1{{GENDER:$2|已隐藏}}“$6”的一个[$4 评论](<em>$5</em>)",
"flow-rev-message-deleted-post": "$1{{GENDER:$2|已删除}}“$6”的一个[$4 评论](<em>$5</em>)",
- "flow-rev-message-suppressed-post": "$1在“$6”{{GENDER:$2|已禁止}}一个[$4 评论](<em>$5</em>)。",
+ "flow-rev-message-suppressed-post": "$1在“$6”{{GENDER:$2|已屏蔽}}一个[$4 评论](<em>$5</em>)。",
"flow-rev-message-restored-post": "$1{{GENDER:$2|已还原}}“$6”的一个[$4 评论](<em>$5</em>)",
"flow-rev-message-hid-topic": "$1{{GENDER:$2|已隐藏}}“$6”的一个[$4 话题](<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1{{GENDER:$2|已删除}}“$6”的一个[$4 话题](<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1{{GENDER:$2|已禁止}}[$4 话题]“$6”(<em>$5</em>)。",
- "flow-rev-message-locked-topic": "$1已将[$4 话题]$6{{GENDER:$2|标记}}为已解决(<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1{{GENDER:$2|已屏蔽}}[$4 话题]“$6”(<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1已将[$4 话题]“$6”{{GENDER:$2|标记}}为已解决(<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "标记为已解决",
"flow-rev-message-restore-topic-reason": "已重启",
"flow-rev-message-restored-topic": "$1{{GENDER:$2|已还原}}“$6”的一个[$4 话题](<em>$5</em>)",
@@ -235,7 +271,7 @@
"flow-history-week": "上周",
"flow-history-pages-topic": "显示于[$1 “$2”板]",
"flow-history-pages-post": "出现在[$1 $2]",
- "flow-topic-comments": "{{PLURAL:$1|$1个评论|0={{GENDER:$2|抢沙发}}!}}",
+ "flow-topic-comments": "{{PLURAL:$1|$1个评论|0={{GENDER:$2|第一个}}发表评论!}}",
"flow-show-comments-title": "{{PLURAL:$1|查看评论}}",
"flow-hide-comments-title": "{{PLURAL:$1|隐藏评论}}",
"flow-comment-restored": "已还原的评论",
@@ -244,31 +280,73 @@
"flow-comment-moderated": "已限制的评论",
"flow-last-modified": "有关$1的最后修改时间",
"flow-workflow": "工作流",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1回答了'''$4'''。",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1和$5位{{PLURAL:$6|其他}}用户回答了'''$3'''。",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1回答了<strong>$4</strong>。",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1和{{PLURAL:$5|其他|$5位其他|100=超过99位其他}}用户{{GENDER:$1|回答}}了<strong>$3</strong>。",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1{{GENDER:$1|编辑了}}您在[[$3|$4]]的<span class=\"plainlinks\">[$5 帖子]</span>。",
- "flow-notification-edit-bundle": "$1和$5名{{PLURAL:$6|其他}}用户于“$2”在“$3”{{GENDER:$1|编辑了}}一个<span class=\"plainlinks\">[$4 帖子]</span>。",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1在'''$3'''{{GENDER:$1|创建了}}一个新话题。",
- "flow-notification-newtopic-bundle": "'''<span class=\"plainlinks\">[$3 $2]</span>'''上的{{PLURAL:$1|$1|250=超过250}}个新话题",
+ "flow-notification-edit-bundle": "$1和{{PLURAL:$5|其他|$5位其他|100=超过99位其他}}用户在“$3”上的“$2”{{GENDER:$1|编辑了}}一个<span class=\"plainlinks\">[$4 帖子]</span>。",
+ "notification-header-flow-new-topic-v2": "已在<strong>$3</strong>上创建新话题:<bdi>“<strong>$4</strong>”</bdi>。",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong>上有{{PLURAL:$1|$1个新话题|100=超过99个新话题}}。",
+ "notification-header-flow-new-topic-user-talk": "<strong>您的讨论页</strong>上创建的新话题:“<strong>$4</strong>”。",
+ "notification-bundle-header-flow-new-topic-user-talk": "<strong>您的讨论页</strong>上有{{PLURAL:$1|$1个新话题|100=超过99个新话题}}。",
+ "notification-header-flow-post-reply": "$1在“<strong>$4</strong>”{{GENDER:$2|做出}}了回应。",
+ "notification-bundle-header-flow-post-reply-v2": "“<strong>$3</strong>”上的{{PLURAL:$1|$1条新回复|100=超过99条新回复}}。",
+ "notification-header-flow-post-reply-user-talk": "$1在<strong>您的讨论页</strong>上的“<strong>$4</strong>”中{{GENDER:$2|留言}}了。",
+ "notification-bundle-header-flow-post-reply-user-talk": "在<strong>您的讨论页</strong>上“<strong>$3</strong>”的{{PLURAL:$1|$1条新回复|100=超过99条新回复}}。",
+ "notification-header-flow-post-edited-v2": "{{GENDER:$2|您}}的帖子“<strong>$1</strong>”已编辑。",
+ "notification-bundle-header-flow-post-edited-v2": "{{GENDER:$2|您}}的帖子“<strong>$1</strong>”编辑了太多次。",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|您}}的讨论页</strong>上的帖子“<strong>$1</strong>”已被编辑。",
+ "notification-bundle-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|您}}的讨论页</strong>上的帖子“<strong>$1</strong>”被编辑了多次。",
+ "notification-header-flow-topic-renamed-v2": "话题“<strong>$1</strong>”已重命名为“<strong>$2</strong>”。",
+ "notification-header-flow-topic-renamed-user-talk": "在<strong>{{GENDER:$3|您}}的讨论页</strong>上的话题“<strong>$1</strong>”已重命名为“<strong>$2</strong>”。",
+ "notification-header-flow-summary-edited": "“<strong>$1</strong>”的摘要已更新。",
+ "notification-header-flow-summary-edited-first": "话题“<strong>$1</strong>”已总结。",
+ "notification-bundle-header-flow-summary-edited": "“<strong>$1</strong>”的摘要已更新太多次。",
+ "notification-header-flow-summary-edited-user-talk": "“<strong>$1</strong>”的摘要已在<strong>{{GENDER:$2|您}}的讨论页</strong>上更新。",
+ "notification-header-flow-summary-edited-first-user-talk": "话题“<strong>$1</strong>”已在<strong>{{GENDER:$2|您}}的讨论页</strong>上总结。",
+ "notification-bundle-header-flow-summary-edited-user-talk": "“<strong>$1</strong>”的摘要已在<strong>{{GENDER:$2|您}}的讨论页</strong>上更新太多次。",
+ "notification-email-subject-flow-summary-edited": "$1{{GENDER:$1|更新了}}$2上的摘要。",
+ "notification-email-batch-body-flow-summary-edited": "$1{{GENDER:$1|更新了}}$2上的摘要。",
+ "notification-email-batch-bundle-body-flow-summary-edited": "$1和{{PLURAL:$3|其他|$3位其他|100=超过99位其他}}用户{{GENDER:$1|更新了}}$2上的摘要",
+ "notification-header-flow-mention-post": "$1在“<strong>$5</strong>”里{{GENDER:$2|提到}}了{{GENDER:$4|您}}。",
+ "notification-header-flow-mention-header": "$1在<strong>$3</strong>的描述中{{GENDER:$2|提到}}了{{GENDER:$4|您}}。",
+ "notification-header-flow-mention-post-summary": "$1在“<strong>$5</strong>”里{{GENDER:$2|提到}}了{{GENDER:$4|您}}。",
+ "notification-header-flow-enabled-on-talkpage": "已为<strong>{{GENDER:$2|您}}的用户讨论页</strong>启用新的讨论系统。",
+ "notification-header-flow-description-edited": "<strong>$1</strong>的描述已编辑。",
+ "notification-header-flow-description-edited-user-talk": "描述已在<strong>{{GENDER:$2|您}}的讨论页</strong>上编辑。",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong>的描述已被编辑太多次。",
+ "notification-bundle-header-flow-description-edited-user-talk": "描述已在<strong>{{GENDER:$2|您}}的讨论页</strong>上编辑了太多次。",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|查看}}页面",
+ "notification-email-subject-flow-description-edited": "$1{{GENDER:$2|已编辑}}$2上的描述。",
+ "notification-email-batch-body-flow-description-edited": "$1{{GENDER:$2|已编辑}}$2上的描述。",
+ "notification-email-batch-bundle-body-flow-description-edited": "$1和{{PLURAL:$3|其他|$3位其他|100=超过99位其他}}用户{{GENDER:$1|编辑了}}$2上的描述",
+ "notification-header-flow-topic-resolved": "话题“<strong>$1</strong>”已解决。",
+ "notification-header-flow-topic-reopened": "话题“<strong>$1</strong>”已重启。",
+ "notification-header-flow-topic-resolved-user-talk": "话题“<strong>$1</strong>”已在<strong>您的讨论页</strong>上解决。",
+ "notification-header-flow-topic-reopened-user-talk": "话题“<strong>$1</strong>”已在<strong>您的讨论页</strong>上重启。",
+ "notification-email-subject-flow-topic-resolved": "话题“<strong>$2</strong>”已解决。",
+ "notification-email-batch-body-flow-topic-resolved": "话题“<strong>$2</strong>”已解决。",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1在<strong>$3</strong>{{GENDER:$1|创建了}}一个新话题。",
+ "flow-notification-newtopic-bundle": "<strong><span class=\"plainlinks\">[$3 $2]</span></strong>上的{{PLURAL:$1|$1个|100=超过99个}}新话题",
"flow-notification-rename": "<span class=\"plainlinks\">[$2 $3]</span>的标题已被$1在[[$5|$6]]{{GENDER:$1|更改}}为“$4”。",
- "flow-notification-mention": "$1于“$4”在{{GENDER:$1|他|她|他们}}的“$3”的<span class=\"plainlinks\">[$2 帖子]</span>中提到了{{GENDER:$5|您}}。",
+ "flow-notification-mention": "$1在“$4”上的“$3”中{{GENDER:$1|他|她|他}}的<span class=\"plainlinks\">[$2 帖子]</span>里提到了{{GENDER:$5|您}}。",
"flow-notification-link-text-view-post": "浏览帖子",
"flow-notification-link-text-view-topic": "查看话题",
+ "flow-notification-link-text-view-topics": "查看话题",
"flow-notification-reply-email-subject": "$3上的$2",
"flow-notification-reply-email-batch-body": "$1在$3{{GENDER:$1|回复了}}“$2”",
- "flow-notification-reply-email-batch-bundle-body": "$1和$4名{{PLURAL:$5|其他}}用户在$3{{GENDER:$1|回答了}}“$2”",
+ "flow-notification-reply-email-batch-bundle-body": "$1和{{PLURAL:$4|其他|$4位其他|100=超过99位其他}}用户在$3{{GENDER:$1|回答了}}“$2”",
"flow-notification-mention-email-subject": "$1在$2{{GENDER:$1|提及}}了{{GENDER:$3|您}}",
- "flow-notification-mention-email-batch-body": "$1于“$2”在$3在{{GENDER:$1|他|她|他们}}的帖子里{{GENDER:$1|提及}}了{{GENDER:$4|您}}",
+ "flow-notification-mention-email-batch-body": "$1于“$2”在$3在{{GENDER:$1|他|她|他}}的帖子里{{GENDER:$1|提及}}了{{GENDER:$4|您}}",
"flow-notification-edit-email-subject": "$1编辑了一个帖子",
"flow-notification-edit-email-batch-body": "$1{{GENDER:$1|编辑}}了$3上话题“$2”中的一个帖子",
- "flow-notification-edit-email-batch-bundle-body": "$1和{{PLURAL:$5|其他}}$4位用户于$3在“$2”{{GENDER:$1|编辑}}了一个帖子",
+ "flow-notification-edit-email-batch-bundle-body": "$1和{{PLURAL:$4|其他|$4位其他|100=超过99位其他}}用户在$3上的“$2”{{GENDER:$1|编辑}}了一个帖子",
"flow-notification-rename-email-subject": "$1重命名了您的话题",
"flow-notification-rename-email-batch-body": "$1将您在$4的话题“$2”{{GENDER:$1|重命名}}为“$3”",
"flow-notification-newtopic-email-subject": "$1在$2{{GENDER:$1|创建了}}新话题",
"flow-notification-newtopic-email-batch-body": "$1在$3创建了一个新话题,标题为“$2”",
- "flow-notification-newtopic-email-batch-bundle-body": "$2上的{{PLURAL:$1|$1个新话题|250=250多个新话题}}",
- "echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "在讨论版发生有关我的动作时通知我。",
+ "flow-notification-newtopic-email-batch-bundle-body": "$2上的{{PLURAL:$1|$1个|100=超过99个}}新话题",
+ "echo-category-title-flow-discussion": "结构化讨论",
+ "echo-pref-tooltip-flow-discussion": "通知我有关我正在关注的话题中或页面上的活动。",
"flow-link-post": "帖子",
"flow-link-topic": "话题",
"flow-link-history": "历史",
@@ -276,52 +354,52 @@
"flow-link-topic-revision": "话题版本",
"flow-link-header-revision": "描述版本",
"flow-link-summary-revision": "摘要版本",
- "flow-moderation-title-suppress-post": "禁止帖子么?",
+ "flow-moderation-title-suppress-post": "屏蔽帖子么?",
"flow-moderation-title-delete-post": "删除帖子吗?",
"flow-moderation-title-hide-post": "隐藏帖子吗?",
- "flow-moderation-title-unsuppress-post": "解禁帖子么?",
+ "flow-moderation-title-unsuppress-post": "解除屏蔽帖子么?",
"flow-moderation-title-undelete-post": "还原帖子么?",
"flow-moderation-title-unhide-post": "显示帖子么?",
- "flow-moderation-placeholder-suppress-post": "请{{GENDER:$3|说明}}您为何禁止这个帖子。",
+ "flow-moderation-placeholder-suppress-post": "请{{GENDER:$3|说明}}您为何屏蔽这个帖子。",
"flow-moderation-placeholder-delete-post": "请{{GENDER:$3|说明}}您为何删除这个帖子。",
"flow-moderation-placeholder-hide-post": "请{{GENDER:$3|说明}}您为何隐藏这个帖子。",
- "flow-moderation-placeholder-unsuppress-post": "请{{GENDER:$3|说明}}您为何解禁这个帖子。",
+ "flow-moderation-placeholder-unsuppress-post": "请{{GENDER:$3|说明}}您为何解除屏蔽这个帖子。",
"flow-moderation-placeholder-undelete-post": "请{{GENDER:$3|说明}}您为还原这个帖子。",
"flow-moderation-placeholder-unhide-post": "请{{GENDER:$3|说明}}您为何显示这个帖子。",
- "flow-moderation-confirm-suppress-post": "禁止",
+ "flow-moderation-confirm-suppress-post": "屏蔽",
"flow-moderation-confirm-delete-post": "删除",
"flow-moderation-confirm-hide-post": "隐藏",
- "flow-moderation-confirm-unsuppress-post": "解禁",
+ "flow-moderation-confirm-unsuppress-post": "解除屏蔽",
"flow-moderation-confirm-undelete-post": "还原",
"flow-moderation-confirm-unhide-post": "显示",
- "flow-moderation-confirm-suppress-topic": "禁止",
+ "flow-moderation-confirm-suppress-topic": "屏蔽",
"flow-moderation-confirm-delete-topic": "删除",
"flow-moderation-confirm-hide-topic": "隐藏",
- "flow-moderation-confirm-unsuppress-topic": "解禁",
+ "flow-moderation-confirm-unsuppress-topic": "解除屏蔽",
"flow-moderation-confirm-undelete-topic": "还原",
"flow-moderation-confirm-unhide-topic": "显示",
- "flow-moderation-confirmation-suppress-post": "此帖子已被禁止。{{GENDER:$2|考虑}}让$1为此帖子提供反馈。",
+ "flow-moderation-confirmation-suppress-post": "此帖子已被屏蔽。{{GENDER:$2|考虑}}让$1为此帖子提供反馈。",
"flow-moderation-confirmation-delete-post": "此帖子已删除。{{GENDER:$2|考虑}}为此帖子提供$1反馈。",
"flow-moderation-confirmation-hide-post": "此帖子已隐藏。{{GENDER:$2|考虑}}为此帖子提供$1反馈。",
- "flow-moderation-confirmation-unsuppress-post": "您已解禁上述帖子。",
+ "flow-moderation-confirmation-unsuppress-post": "您已解除对上述帖子的屏蔽。",
"flow-moderation-confirmation-undelete-post": "您已还原上述帖子。",
"flow-moderation-confirmation-unhide-post": "您已显示上述帖子。",
- "flow-moderation-confirmation-suppress-topic": "此话题已被禁止。",
+ "flow-moderation-confirmation-suppress-topic": "此话题已被屏蔽。",
"flow-moderation-confirmation-delete-topic": "此话题已被删除。",
"flow-moderation-confirmation-hide-topic": "此话题已被隐藏。",
- "flow-moderation-confirmation-unsuppress-topic": "您已解禁此话题。",
+ "flow-moderation-confirmation-unsuppress-topic": "您已解除对此话题的屏蔽。",
"flow-moderation-confirmation-undelete-topic": "您已还原此话题。",
"flow-moderation-confirmation-unhide-topic": "您已显示此话题。",
- "flow-moderation-title-suppress-topic": "要禁止话题吗?",
+ "flow-moderation-title-suppress-topic": "屏蔽话题吗?",
"flow-moderation-title-delete-topic": "要删除话题吗?",
"flow-moderation-title-hide-topic": "要隐藏话题吗?",
- "flow-moderation-title-unsuppress-topic": "要解禁话题吗?",
+ "flow-moderation-title-unsuppress-topic": "解除屏蔽话题吗?",
"flow-moderation-title-undelete-topic": "要还原话题吗?",
"flow-moderation-title-unhide-topic": "要显示话题吗?",
- "flow-moderation-placeholder-suppress-topic": "请{{GENDER:$3|说明}}您为何要禁止此话题。",
+ "flow-moderation-placeholder-suppress-topic": "请{{GENDER:$3|说明}}您为何要屏蔽此话题。",
"flow-moderation-placeholder-delete-topic": "请{{GENDER:$3|说明}}您为何要删除此话题。",
"flow-moderation-placeholder-hide-topic": "请{{GENDER:$3|说明}}您为何要隐藏此话题。",
- "flow-moderation-placeholder-unsuppress-topic": "请{{GENDER:$3|说明}}您为何要解禁此话题。",
+ "flow-moderation-placeholder-unsuppress-topic": "请{{GENDER:$3|说明}}您为何要解除屏蔽此话题。",
"flow-moderation-placeholder-undelete-topic": "请{{GENDER:$3|说明}}您为何还原此话题。",
"flow-moderation-placeholder-unhide-topic": "请{{GENDER:$3|说明}}您为何显示此话题。",
"flow-topic-permalink-warning": "本话题发起于[$2 $1]",
@@ -334,15 +412,15 @@
"flow-revision-permalink-warning-header-first": "这是此描述的第一个版本的固定链接。您可通过[$2 历史页面]查看其他版本。",
"flow-compare-revisions-revision-header": "版本由{{GENDER:$2|$2}}从$1生成",
"flow-compare-revisions-header-post": "此页面显示由$3于[$4 $1]在话题“[$5 $2]”发布帖子的两个版本之间的{{GENDER:$3|更改}}。您可在它的[$6 历史页面]查看此帖子的其它版本。",
- "flow-compare-revisions-header-postsummary": "本页面显示在[$3 $1]的帖子“[$4 $2]”摘要两个版本之间的更改。您可点击[$5 历史页面]查看此帖子的其他版本。",
+ "flow-compare-revisions-header-postsummary": "本页面显示在[$3 $1]的话题“[$4 $2]”摘要两个版本之间的更改。您可以在话题的[$5 历史页面]查看此话题摘要的其他版本。",
"flow-compare-revisions-header-header": "此页面显示[$3 $1]上两个描述版本间的{{GENDER:$2|更改}}。您可通过它的[$4 历史页面]查看其它版本。",
- "action-flow-create-board": "在任意位置创建Flow版块",
- "right-flow-create-board": "在任意位置创建Flow版块",
- "right-flow-hide": "隐藏Flow话题和帖子",
- "right-flow-lock": "将Flow话题标记为已解决",
- "right-flow-delete": "删除Flow话题和帖子",
- "right-flow-edit-post": "编辑其它用户的Flow帖子",
- "right-flow-suppress": "禁止Flow修订",
+ "action-flow-create-board": "在任意位置创建结构化讨论版块",
+ "right-flow-create-board": "在任意位置创建结构化讨论版块",
+ "right-flow-hide": "隐藏结构化讨论话题和帖子",
+ "right-flow-lock": "将结构化讨论话题标记为已解决",
+ "right-flow-delete": "删除结构化讨论话题和帖子",
+ "right-flow-edit-post": "编辑其它用户的结构化讨论帖子",
+ "right-flow-suppress": "屏蔽结构化讨论修订版本",
"flow-terms-of-use-new-topic": "点击“{{int:flow-newtopic-save}}”,即表示您认同本wiki的使用条款。",
"flow-terms-of-use-reply": "点击“{{int:flow-reply-link}}”,即表示您认同本wiki的使用条款。",
"flow-terms-of-use-edit": "保存您的更改,即表示您认同本wiki的使用条款。",
@@ -366,152 +444,54 @@
"flow-whatlinkshere-post": "来自一个[$1 帖子]",
"flow-whatlinkshere-header": "来自[$1 描述]",
"flow-whatlinkshere-post-summary": "来自[$1 摘要]",
- "flow": "Flow",
- "flow-special-desc": "此特殊页面重定向至Flow工作流或指定UUID的Flow帖子。",
+ "structureddiscussions": "结构化讨论",
+ "flow-special-desc": "此特殊页面重定向至结构化讨论工作流或指定UUID的结构化讨论帖子。",
"flow-special-type": "类型",
"flow-special-type-post": "帖子",
"flow-special-type-workflow": "工作流",
"flow-special-uuid": "UUID",
"flow-special-invalid-uuid": "无法找到与指定类型和UUID匹配的内容。",
- "flow-special-enableflow-legend": "在一个新页面启用Flow",
- "flow-special-enableflow-page": "要启用Flow的页面",
- "flow-special-enableflow-header": "Flow板块的最初描述(wiki文本)",
- "flow-special-enableflow-board-already-exists": "在[[$1]]已存在Flow板块。",
+ "flow-special-enableflow-legend": "在一个新页面启用结构化讨论",
+ "flow-special-enableflow-page": "要启用结构化讨论的页面",
+ "flow-special-enableflow-header": "结构化讨论版块的最初描述(wiki文本)",
+ "flow-special-enableflow-board-already-exists": "在[[$1]]已存在结构化讨论板块。",
"flow-special-enableflow-invalid-title": "提供了一个无效的页面标题",
- "flow-special-enableflow-board-creation-not-allowed": "您不被允许在[[:$1]]创建一个Flow板块。",
+ "flow-special-enableflow-board-creation-not-allowed": "您不被允许在[[:$1]]创建一个结构化讨论版块。",
"flow-special-enableflow-page-is-liquidthreads": "在[[:$1]]有一个LiquidThreads页面。",
- "flow-special-enableflow-confirmation": "您已成功在[[$1]]创建一个Flow板块。",
+ "flow-special-enableflow-confirmation": "您已在[[$1]]创建一个结构化讨论版块。",
"flow-conversion-archive-page-name-format": "%s/存档 %d\n%s/存档%d\n%s/存档 %d\n%s/存档%d",
- "flow-conversion-archive-flow-page-name-format": "%s/Flow 存档 %d\n%s/Flow存档%d",
- "flow-spam-confirmedit-form": "请输入下面的验证码已确认您是真人:$1",
+ "flow-conversion-archive-flow-page-name-format": "%s/结构化讨论 存档 %d\n%s/结构化讨论存档%d",
+ "flow-spam-confirmedit-form": "请输入下面的验证码以确认您是真人:$1",
+ "flow-spam-confirmedit-using-failure": "存在与验证码相关的技术错误。如果您无法提交您的更改,请复制您的文本、重新加载并重试。",
"flow-embedding-unsupported": "讨论尚不能嵌入。",
"mw-ui-unsubmitted-confirm": "您在此页有未提交的更新。您确信不保存您的更改离开?",
"flow-post-undo-hide": "撤销隐藏",
"flow-post-undo-delete": "撤销删除",
- "flow-post-undo-suppress": "撤销禁止",
+ "flow-post-undo-suppress": "撤销屏蔽",
"flow-topic-undo-hide": "撤销隐藏",
"flow-topic-undo-delete": "撤销删除",
- "flow-topic-undo-suppress": "撤销禁止",
- "flow-importer-lqt-moved-thread-template": "LQT移动了帖子存档,并转换成Flow",
+ "flow-topic-undo-suppress": "撤销屏蔽",
+ "flow-importer-lqt-moved-thread-template": "LQT移动了帖子存档,并转换成结构化讨论",
"flow-importer-lqt-moved-thread-template-content": "这个由{{{author}}}发表的帖子已于{{{date}}}移动。您可以在[[{{{title}}}]]找到。",
- "flow-importer-lqt-converted-template": "LQT页面已转换为Flow",
+ "flow-importer-lqt-converted-template": "LQT页面已转换为结构化讨论",
"flow-importer-lqt-converted-template-content": "既往的页面历史已于{{#time: Y-m-d|{{{date}}}}}基于备份目的存档在<span class='flow-link-to-archive'>[[{{{archive}}}]]</span>。",
"flow-importer-lqt-converted-archive-template": "已转换的LQT页面的存档",
- "flow-importer-lqt-converted-archive-template-content": "此页面是已存档的LiquidThreads页面。'''请不要编辑此页面内容'''。请直接在[[{{{from}}}|当前讨论页]]发表额外评论。",
- "flow-importer-wt-converted-template": "从Wiki文本讨论页转换为Flow页面",
+ "flow-importer-lqt-converted-archive-template-content": "此页面是已存档的LiquidThreads页面。<strong>请不要编辑此页面内容</strong>。请直接在[[{{{from}}}|当前讨论页]]发表额外评论。",
+ "flow-importer-wt-converted-template": "从Wiki文本讨论页转换为结构化讨论页面",
"flow-importer-wt-converted-template-content": "既往讨论已于{{#time: Y-m-d|{{{date}}}}}存档在<span class='flow-link-to-archive'>[[{{{archive}}}]]</span>。",
"flow-importer-wt-converted-archive-template": "来自已转换的wiki文本讨论页的存档",
- "flow-importer-wt-converted-archive-template-content": "此页面是存档页面。'''请不要编辑此页面内容'''。请直接在[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|当前讨论页]]发表额外评论。",
- "flow-importer-lqt-suppressed-user-template": "LQT帖子被一名已禁止的用户导入",
- "flow-importer-lqt-suppressed-user-template-content": "此修订是从一位被禁止的用户的LiquidThreads导入的。它现已重新分配至当前用户。",
+ "flow-importer-wt-converted-archive-template-content": "此页面是存档页面。<strong>请不要编辑此页面内容</strong>。请直接在[[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|当前讨论页]]发表额外评论。",
+ "flow-importer-lqt-suppressed-user-template": "LQT帖子被一名已屏蔽的用户导入",
+ "flow-importer-lqt-suppressed-user-template-content": "此修订是从一位被屏蔽的用户的LiquidThreads导入的。它现已重新分配至当前用户。",
"flow-importer-lqt-different-author-signature-template": "LQT帖子已连带不同签名的用户导入",
- "flow-importer-lqt-different-author-signature-template-content": "''此帖子曾由[[User:{{{authorUser}}}|{{{authorUser}}}]]发布,但被表示为[[User:{{{signatureUser}}}|{{{signatureUser}}}]]。''",
- "apihelp-flow-description": "允许对Flow页面的操作。",
- "apihelp-flow-param-submodule": "要调用的Flow子模块。",
- "apihelp-flow-param-page": "要进行操作的页面。",
- "apihelp-flow-example-1": "编辑“[[Talk:Sandbox]]”的描述",
- "apihelp-flow+close-open-topic-description": "由于[[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]]而弃用。",
- "apihelp-flow+close-open-topic-param-moderationState": "提交话题的情形,要么“lock”要么“unlock”。",
- "apihelp-flow+close-open-topic-param-reason": "锁定或解锁话题的原因。",
- "apihelp-flow+edit-header-description": "编辑板块的描述。",
- "apihelp-flow+edit-header-param-prev_revision": "当前描述修订的版本ID,以检查编辑冲突。",
- "apihelp-flow+edit-header-param-content": "用于描述的内容。",
- "apihelp-flow+edit-header-param-format": "描述的格式(wikitext|html)",
- "apihelp-flow+edit-header-example-1": "编辑[[Talk:Sandbox]]的描述",
- "apihelp-flow+edit-post-description": "编辑帖子的内容。",
- "apihelp-flow+edit-post-param-postId": "帖子ID。",
- "apihelp-flow+edit-post-param-prev_revision": "当前帖子修订的版本ID,以检查编辑冲突。",
- "apihelp-flow+edit-post-param-content": "帖子的内容。",
- "apihelp-flow+edit-post-param-format": "贴子内容的格式(wiki文本|html)",
- "apihelp-flow+edit-post-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的帖子",
- "apihelp-flow+edit-title-description": "编辑话题的标题。",
- "apihelp-flow+edit-title-param-prev_revision": "当前标题修订的版本ID,以检查编辑冲突。",
- "apihelp-flow+edit-title-param-content": "标题的内容。",
- "apihelp-flow+edit-title-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的标题",
- "apihelp-flow+edit-topic-summary-description": "编辑一个话题的摘要内容。",
- "apihelp-flow+edit-topic-summary-param-prev_revision": "当前话题摘要修订的版本ID(如果有),以检查编辑冲突。",
- "apihelp-flow+edit-topic-summary-param-summary": "编辑摘要的内容。",
- "apihelp-flow+edit-topic-summary-param-format": "摘要格式(wiki文本|html)",
- "apihelp-flow+edit-topic-summary-example-1": "编辑[[Topic:S2tycnas4hcucw8w]]的摘要",
- "apihelp-flow+lock-topic-description": "锁定或解锁一个Flow话题。",
- "apihelp-flow+lock-topic-param-moderationState": "提交话题的情形,要么<kbd>lock</kbd>要么<kbd>unlock</kbd>。",
- "apihelp-flow+lock-topic-param-reason": "锁定或解锁此话题的原因。注意wiki上的Flow客户端在此使用“Marked as resolved”,并将可选的额外信息放置在摘要中。",
- "apihelp-flow+lock-topic-example-1": "锁定[[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+moderate-post-description": "限制一个Flow帖子。",
- "apihelp-flow+moderate-post-param-moderationState": "限制等级。",
- "apihelp-flow+moderate-post-param-reason": "限制的原因。",
- "apihelp-flow+moderate-post-param-postId": "要限制的帖子ID。",
- "apihelp-flow+moderate-post-example-1": "删除话题[[Topic:S2tycnas4hcucw8w]]的帖子",
- "apihelp-flow+moderate-topic-description": "限制一个Flow帖子。",
- "apihelp-flow+moderate-topic-param-moderationState": "限制等级。",
- "apihelp-flow+moderate-topic-param-reason": "限制的原因。",
- "apihelp-flow+moderate-topic-example-1": "删除话题[[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+new-topic-description": "在指定的工作流中创建一个新的Flow话题。",
- "apihelp-flow+new-topic-param-topic": "用于新话题标题的文字。",
- "apihelp-flow+new-topic-param-content": "用于话题的最初回复的内容。",
- "apihelp-flow+new-topic-param-format": "新话题首次回复的格式 (wikitext|html)",
- "apihelp-flow+new-topic-example-1": "在[[Talk:Sandbox]]创建一个新话题",
- "apihelp-flow+reply-description": "回复一个帖子。",
- "apihelp-flow+reply-param-replyTo": "要回复的ID。",
- "apihelp-flow+reply-param-content": "新帖子的内容。",
- "apihelp-flow+reply-param-format": "新贴子的格式(wiki文本|html)",
- "apihelp-flow+reply-example-1": "回复[[Topic:S2tycnas4hcucw8w]]的帖子",
- "apihelp-flow+view-header-param-format": "返回内容的格式。",
- "apihelp-flow+view-header-description": "查看板块描述。",
- "apihelp-flow+view-header-param-revId": "加载此修订版本,而不是最新的。",
- "apihelp-flow+view-header-example-1": "获取[[Talk:Sandbox]]的描述作为wiki文本",
- "apihelp-flow+view-post-description": "查看帖子。",
- "apihelp-flow+view-post-param-postId": "要查看的帖子ID。",
- "apihelp-flow+view-post-param-format": "返回内容的格式。",
- "apihelp-flow+view-post-example-1": "获取[[Topic:S2tycnas4hcucw8w]]上帖子的内容作为wiki文本",
- "apihelp-flow+view-post-history-description": "浏览一个帖子的修订历史。",
- "apihelp-flow+view-post-history-param-postId": "要查看修订历史的帖子ID。",
- "apihelp-flow+view-post-history-param-format": "返回内容的格式。",
- "apihelp-flow+view-post-history-example-1": "检索在[[Topic:S2tycnas4hcucw8w]]的帖子修订作为wiki文本",
- "apihelp-flow+view-topic-description": "查看话题。",
- "apihelp-flow+view-topic-example-1": "查看[[Topic:S2tycnas4hcucw8w]]",
- "apihelp-flow+view-topic-history-description": "浏览一个话题的修订历史。",
- "apihelp-flow+view-topic-history-param-format": "返回内容的格式。",
- "apihelp-flow+view-topic-history-example-1": "查看在[[Topic:S2tycnas4hcucw8w]]的帖子修订作为wiki文本",
- "apihelp-flow+view-topic-summary-description": "查看话题摘要。",
- "apihelp-flow+view-topic-summary-param-format": "返回内容的格式。",
- "apihelp-flow+view-topic-summary-param-revId": "加载此修订版本,而不是最新的。",
- "apihelp-flow+view-topic-summary-example-1": "查看[[Topic:S2tycnas4hcucw8w]]的摘要作为wiki文本",
- "apihelp-flow+view-topiclist-description": "查看话题列表。",
- "apihelp-flow+view-topiclist-param-offset-dir": "排序话题的方向。",
- "apihelp-flow+view-topiclist-param-sortby": "话题的排序选项,既可以是<kbd>updated</kbd>(按话题更新时间排序),又可以是<kbd>newest</kbd>(按话题创建时间排序)。",
- "apihelp-flow+view-topiclist-param-savesortby": "保存排序方式选项至用户设置,如果设置。",
- "apihelp-flow+view-topiclist-param-offset-id": "开始取得话题的抵消值(UUID格式),只与<kbd>newest</kbd>一起用于排序",
- "apihelp-flow+view-topiclist-param-offset": "偏移值(作为一个<code>TS_MW</code>格式的话题更新时间戳(<code>YYYYMMDDHHMMSS</code>)),以开始取得话题;只与<kbd>updated</kbd>一起排序",
- "apihelp-flow+view-topiclist-param-limit": "要取得的话题数量。",
- "apihelp-flow+view-topiclist-example-1": "[[Talk:Sandbox]]的话题列表",
- "apihelp-flow-parsoid-utils-description": "在wiki文本和HTML之间互相转换文本。",
- "apihelp-flow-parsoid-utils-param-from": "要转换格式的内容。",
- "apihelp-flow-parsoid-utils-param-to": "格式转换的目标内容。",
- "apihelp-flow-parsoid-utils-param-content": "要转换的内容。",
- "apihelp-flow-parsoid-utils-param-title": "页面标题。不能与$1pageid一起使用。",
- "apihelp-flow-parsoid-utils-param-pageid": "页面ID。不能与$1title一起使用。",
- "apihelp-flow-parsoid-utils-example-1": "将wiki文本<nowiki>'''lorem''' ''blah''</nowiki>转换为HTML",
- "apihelp-query+flowinfo-description": "获取有关页面的基本Flow信息。",
- "apihelp-query+flowinfo-example-1": "获取有关[[Talk:Sandbox]]、[[Main Page]]和[[Talk:Flow]]的Flow信息",
- "apihelp-flow+undo-edit-header-description": "检索撤销描述编辑必需要的信息。",
- "apihelp-flow+undo-edit-header-param-startId": "要开始撤销的修订ID。",
- "apihelp-flow+undo-edit-header-param-endId": "要结束撤销的修订ID。",
- "apihelp-flow+undo-edit-header-example-1": "检索有关在[[Talk:Sandbox]]撤销一次描述编辑的信息",
- "apihelp-flow+undo-edit-post-description": "检索撤销帖子编辑必需要的信息。",
- "apihelp-flow+undo-edit-post-param-postId": "要回退的帖子ID。",
- "apihelp-flow+undo-edit-post-param-startId": "要开始撤销的修订ID。",
- "apihelp-flow+undo-edit-post-param-endId": "要结束撤销的修订ID。",
- "apihelp-flow+undo-edit-post-example-1": "取得有关在一次话题中撤销一次帖子编辑的信息。",
- "apihelp-flow+undo-edit-topic-summary-description": "检索撤销话题摘要编辑必需要的信息。",
- "apihelp-flow+undo-edit-topic-summary-param-startId": "要开始撤销的修订ID。",
- "apihelp-flow+undo-edit-topic-summary-param-endId": "要结束撤销的修订ID。",
- "apihelp-flow+undo-edit-topic-summary-example-1": "取得有关撤销在特定话题中一次话题摘要的编辑的信息",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>此帖子曾由[[User:{{{authorUser}}}|{{{authorUser}}}]]发布,但被表示为[[User:{{{signatureUser}}}|{{{signatureUser}}}]]。</em>",
"flow-edited": "编辑于",
"flow-edited-by": "由$1编辑",
- "flow-lqt-redirect-reason": "重定向停用的LiquidThreads帖子至转换的Flow帖子",
- "flow-talk-conversion-move-reason": "将$1从wiki文本讨论页转换为Flow页面",
- "flow-talk-conversion-archive-edit-reason": "Wiki文本讨论页至Flow转换",
+ "flow-edited-by-header": "板块描述已由$1编辑",
+ "flow-edited-by-topic-title": "话题标题已由$1编辑",
+ "flow-lqt-redirect-reason": "将过时的LiquidThreads帖子重定向至转换的结构化讨论帖子",
+ "flow-talk-conversion-move-reason": "将$1从wiki文本讨论页转换为结构化讨论页面",
+ "flow-talk-conversion-archive-edit-reason": "Wiki文本讨论页至结构化讨论转换",
"flow-previous-diff": "←上一编辑",
"flow-next-diff": "下一编辑→",
"flow-undo": "撤销",
@@ -522,9 +502,9 @@
"flow-undo-edit-post": "编辑帖子",
"flow-undo-edit-content": "该编辑可以被撤销。请检查下面的对比以核实你想要撤销的内容,然后保存下面的更改以完成撤销。",
"flow-undo-edit-failure": "因存在冲突的中间编辑,本编辑不能撤销。",
- "group-flow-bot": "Flow机器人",
- "group-flow-bot-member": "Flow机器人",
- "grouppage-flow-bot": "Project:Flow机器人",
+ "group-flow-bot": "结构化讨论机器人",
+ "group-flow-bot-member": "结构化讨论机器人",
+ "grouppage-flow-bot": "Project:结构化讨论机器人",
"flow-ve-mention-context-item-label": "提及",
"flow-ve-mention-inspector-title": "提及",
"flow-ve-mention-inspector-remove-label": "移除",
@@ -533,8 +513,8 @@
"flow-ve-mention-template-title": "Flow提及",
"flow-ve-mention-inspector-invalid-user": "用户名“$1”未注册。",
"flow-wikitext-editor-help": "Wiki文本$1。",
- "flow-wikitext-editor-help-and-preview": "Wiki文本$1并且您随时都可以$2。",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|使用标记]]",
+ "flow-wikitext-editor-help-and-preview": "Wiki文本$1;您随时都可以$2。",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|标记用法]]",
"flow-wikitext-editor-help-preview-the-result": "预览结果",
"flow-wikitext-switch-editor-tooltip": "切换为可视化编辑器",
"flow-ve-switch-editor-tool-title": "切换为Wiki文本编辑器",
@@ -542,22 +522,28 @@
"flow-mark-revision-patrolled-link-title": "标记此页面为已巡查",
"flow-mark-diff-patrolled-link-text": "标记为已巡查",
"flow-mark-diff-patrolled-link-title": "标记为已巡查",
- "flow-talk-page-beta-feature-message": "用户讨论页上的Flow",
- "flow-talk-page-beta-feature-description": "在{{GENDER:|您}}的用户讨论页启用新的结构化讨论系统。Flow通过清晰的书写和回复的地方简化讨论页的讨论,并允许会话级的通知。现有的wiki文本讨论已移动至存档。此功能不会自动启用;用户需要手动启用它。禁用此功能将会把Flow版块移动至一个子页面,并从存档中抽回之前的讨论页。",
- "flow-notification-link-text-enabled-on-talkpage": "查看用户讨论页",
+ "flow-talk-page-beta-feature-message": "用户讨论页上的结构化讨论",
+ "flow-talk-page-beta-feature-description": "在{{GENDER:|您}}的用户讨论页启用新的结构化讨论系统。结构化讨论通过清晰的书写和回复的地方简化讨论页的讨论,并允许会话级的通知。此功能不会自动启用;用户需要手动启用它。<br /><br />现有的wiki文本讨论已移动到存档中。禁用此功能将会把结构化讨论版块移动至一个子页面,并从存档中抽回之前的讨论页。[[mw:Special:MyLanguage/Help:Structured Discussions/Activation#Activate|了解更多有关激活的信息]]。",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|查看}}用户讨论页",
"flow-notification-enabled-on-talkpage-title": "新讨论系统已在{{GENDER:$1|您}}的用户讨论页启用<br /><small>在[[$2]]可用</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "$2上的新讨论系统",
- "flow-notification-enabled-on-talkpage-email-batch-body": "Flow,新的wiki讨论系统,已在{{GENDER:$1|您}}{{SITENAME}}上的用户讨论页上启用。您可以随时从{{GENDER:$1|您}}的参数设置的测试功能选项中获取更多信息、提供反馈或禁用新系统。",
+ "flow-notification-enabled-on-talkpage-email-batch-body": "结构化讨论,新的wiki讨论系统,已在{{GENDER:$1|您}}{{SITENAME}}上的用户讨论页上启用。您可以随时从{{GENDER:$1|您}}的参数设置的测试功能选项中获取更多信息、提供反馈或禁用新系统。",
"flow-beta-feature-add-archive-template-edit-summary": "正在添加存档模板",
"flow-beta-feature-remove-archive-template-edit-summary": "正在移除存档模板",
- "flow-dialog-cancelconfirm-title": "您确定吗?",
- "flow-dialog-cancelconfirm-message": "您确定要取消而不先保存么?",
+ "flow-dialog-cancelconfirm-title": "{{GENDER:|您}}确定吗?",
+ "flow-dialog-cancelconfirm-message": "{{GENDER:|您}}确定要取消而不先保存吗?",
"flow-dialog-cancelconfirm-keep": "继续编辑",
"flow-dialog-cancelconfirm-discard": "放弃更改",
+ "flow-optin-archive-wikitext": "移动wiki文本页面以为讨论版块腾出地方。",
+ "flow-optin-archive-flow-board": "移动讨论版块页面以为wiki文本页面腾出地方。",
+ "flow-optin-restore-wikitext": "恢复已存档的wiki文本页面。",
+ "flow-optin-restore-flow-board": "恢复已存档的讨论版块。",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|欢迎}}来到{{GENDER:$1|您}}的新用户讨论页",
- "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|您}}的讨论页是其他编辑者可以联络{{GENDER:$1|您}}的地方。通过使用Flow,您将更容易地开启新话题,并保持对谈话的追踪。",
+ "flow-guidedtour-optin-welcome-description": "{{GENDER:$1|您}}的讨论页是其他编辑者可以联络{{GENDER:$1|您}}的地方。通过使用结构化讨论,您将更容易地开启新话题,并保持对谈话的追踪。",
"flow-guidedtour-optin-find-old-conversations": "找到{{GENDER:$1|您}}的旧谈话",
"flow-guidedtour-optin-find-old-conversations-description": "之前的谈话已移动至一个存档页面。",
"flow-guidedtour-optin-feedback": "向我们提供{{GENDER:$1|您}}的反馈!",
- "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|您}}可以随时从测试功能选项中获取更多信息、提供反馈、或禁用新系统。"
+ "flow-guidedtour-optin-feedback-description": "{{GENDER:$1|您}}可以随时从测试功能选项中获取更多信息、提供反馈、或禁用新系统。",
+ "flow-action-not-page": "页面对象是错误类的实例",
+ "flow-action-wrong-title-content-model": "页面正在由结构化讨论处理,但标题类指出内容模型是“$1”。这是配置错误或不一致的状态。例如,这可能确实是在结构化讨论名字空间中的非结构化讨论页面,而<code>rev_content_model</code>未被填充。"
}
diff --git a/Flow/i18n/zh-hant.json b/Flow/i18n/zh-hant.json
index 903be975..44d56656 100644
--- a/Flow/i18n/zh-hant.json
+++ b/Flow/i18n/zh-hant.json
@@ -8,21 +8,28 @@
"Impersonator 1",
"LNDDYL",
"MoonYaksha",
- "Macofe"
+ "Macofe",
+ "Nnemo",
+ "Bowleerin",
+ "Shizhao",
+ "飞舞回堂前",
+ "Arthur2e5"
]
},
- "enableflow": "開啟 Flow",
- "flow-desc": "工作流程管理系統",
+ "enablestructureddiscussions": "開啟 Flow",
+ "flow-desc": "對話系統",
"flow-talk-taken-over-comment": "/* 此頁面已被轉換為 Flow 討論板 */",
- "log-name-flow": "Flow 活動日誌",
- "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|已刪除}}位於 [[$6]] 中 \"[[$3|$5]]\" 的一篇 [$4 貼文]",
- "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|已還原}} 位於 [[$6]] 中 \"[[$3|$5]]\" 的一篇 [$4 貼文]",
- "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|已封鎖}}位於 [[$6]] 中 \"[[$3|$5]]\" 的一篇 [$4 貼文]",
- "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|已刪除}} 位於 [[$6]] 中 \"[[$3|$5]]\" 的一篇 [$4 貼文]",
+ "log-name-flow": "Flow 活躍日誌",
+ "logentry-delete-flow-delete-post": "$1 {{GENDER:$2|已刪除}}位於 [[$6]] 中 「[[$3|$5]]」 的一篇 [$4 貼文]",
+ "logentry-delete-flow-restore-post": "$1 {{GENDER:$2|已還原}} 位於 [[$6]] 中 「[[$3|$5]]」 的一篇 [$4 貼文]",
+ "logentry-suppress-flow-suppress-post": "$1 {{GENDER:$2|已封鎖}}位於 [[$6]] 中 「[[$3|$5]]」 的一篇 [$4 貼文]",
+ "logentry-suppress-flow-restore-post": "$1 {{GENDER:$2|已刪除}} 位於 [[$6]] 中 「[[$3|$5]]」 的一篇 [$4 貼文]",
"logentry-delete-flow-delete-topic": "$1 {{GENDER:$2|已刪除}}位於 [[$6]] 中的話題 \"[[$3|$5]]\"",
- "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|已還原}}位於 [[$6]] 中的 \"[[$3|$5]]\" 話題",
+ "logentry-delete-flow-restore-topic": "$1 {{GENDER:$2|已還原}}位於 [[$6]] 中的 「[[$3|$5]]」 話題",
"logentry-suppress-flow-suppress-topic": "$1 {{GENDER:$2|已封鎖}}位於 [[$6]] 中的 \"[[$3|$5]]\" 話題",
- "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|已刪除}}位於 [[$6]] 中的話題 \"[[$3|$5]]\"",
+ "logentry-suppress-flow-restore-topic": "$1 {{GENDER:$2|已刪除}}位於 [[$6]] 中的話題 「[[$3|$5]]」",
+ "logentry-lock-flow-lock-topic": "$1 {{GENDER:$2|已標記}}位於[[$6]]的話題「[[$3|$5]]」為已解決",
+ "logentry-lock-flow-restore-topic": "$1 {{GENDER:$2|已重新開啟}}位於[[$6]]的話題「[[$3|$5]]」",
"logentry-import-lqt-to-flow-topic": "位於 [[$3]] 上的 [[$1|$2]] 已從 LiquidThreads 匯入至 Flow",
"flow-user-moderated": "受管制的使用者",
"flow-board-header-browse-topics-link": "瀏覽話題",
@@ -52,23 +59,25 @@
"flow-post-actions": "操作",
"flow-topic-actions": "操作",
"flow-cancel": "取消",
- "flow-skip-summary": "跳過摘要",
+ "flow-skip-summary": "跳過",
"flow-edit-summary-placeholder": "簡單的描述此次討論的結果",
"flow-summary-authored": "由 $1 摘要",
"flow-summary-edited": "摘要最後由 $1 {{GENDER:$1|編輯}}",
"flow-show-change": "顯示變更",
"flow-last-modified-by": "最後由 $1 {{GENDER:$1|修改}}",
- "flow-stub-post-content": "''由於技術問題,無法檢索這篇貼文。''",
+ "flow-stub-post-content": "<em>由於技術問題,無法檢索這篇貼文。</em>",
"flow-newtopic-title-placeholder": "新話題",
"flow-newtopic-content-placeholder": "發佈一則新訊息至 \"$1\"",
"flow-newtopic-header": "新增新話題",
"flow-newtopic-save": "新增話題",
+ "flow-newtopic-save-anonymously": "匿名使用者新增話題",
"flow-newtopic-start-placeholder": "發起新話題",
"flow-newtopic-first-heading": "發起新話題於 $1",
"flow-summarize-topic-placeholder": "請為為此討論摘要說明",
"flow-reply-topic-placeholder": "於 \"$2\" 的{{GENDER:$1|評論}}",
"flow-reply-topic-title-placeholder": "回覆至 \"$1\"",
"flow-reply-link": "{{GENDER:$1|回覆}}",
+ "flow-reply-link-anonymously": "匿名使用者回覆",
"flow-thank-link": "{{GENDER:$1|{{GENDER:$2|感謝}}}}",
"flow-thank-link-title": "公開{{GENDER:$1|{{GENDER:$2|感謝}}}}發佈者",
"flow-history-action-suppress-post": "封鎖",
@@ -88,6 +97,7 @@
"flow-post-action-hide-post": "隱藏",
"flow-post-action-edit-post": "編輯",
"flow-post-action-edit-post-submit": "儲存變更",
+ "flow-post-action-edit-post-submit-anonymously": "匿名使用者儲存變更",
"flow-post-action-unsuppress-post": "解除封鎖",
"flow-post-action-undelete-post": "取消刪除",
"flow-post-action-unhide-post": "取消隱藏",
@@ -120,22 +130,17 @@
"flow-error-allowcreation-already-exists": "頁面已存在,但是須為不存在。",
"flow-error-allowcreation-flow-create-board": "使用者沒有 \"{{int:right-flow-create-board}}\" 權限",
"flow-error-http": "與伺服器連線時發生錯誤。",
- "flow-error-other": "發生未預期的錯誤。",
- "flow-error-external": "發生錯誤。<br />錯誤訊息為:$1",
+ "flow-error-external": "發生錯誤。錯誤訊息為:$1",
"flow-error-topic-is-locked": "此話題已被解決,不能進行進一步的活動。",
"flow-error-lock-moderated-post": "您無法標記受管制的貼文已解決。",
- "flow-error-external-multi": "發生錯誤。<br />$1",
"flow-error-missing-content": "貼文沒有內容。 您需要填寫內容以儲存貼文。",
"flow-error-missing-summary": "您必須填寫摘要。",
"flow-error-missing-title": "話題沒有標題。 您需要填寫標題以儲存話題。",
"flow-error-parsoid-failure": "因 Parsoid 錯誤,無法解析內容。",
+ "flow-error-protected-unknown-reason": "不明",
"flow-error-missing-replyto": "未提供「回覆至」參數。「回覆」動作需要使用此參數。",
- "flow-error-invalid-replyto": "「回覆至」參數無效。 查無指定的貼文。",
- "flow-error-delete-failure": "此項目刪除失敗。",
- "flow-error-hide-failure": "此項目隱藏失敗。",
"flow-error-missing-postId": "未提供 \"postId\" 參數。 處理貼文需要使用此參數。",
"flow-error-invalid-postId": "\"postId\" 參數無效。 查無指定的貼文 ($1)。",
- "flow-error-restore-failure": "此項目還原失敗。",
"flow-error-invalid-moderation-state": "提供給 Flow API 的 ('moderationState') 參數值無效。",
"flow-error-invalid-moderation-reason": "請說明限制操作的原因。",
"flow-error-not-allowed": "無足夠的權限執行此操作。",
@@ -177,7 +182,6 @@
"flow-error-no-commit": "無法儲存指定的動作。",
"flow-error-content-too-long": "內容過大,內容展開後的限制為 $1 {{PLURAL:$1|位元組|位元組}}。",
"flow-error-move-topic": "目前不支援移動話題頁面。",
- "flow-error-move-no-create-permissions": "移動 Flow 留言板需要 \"{{int:right-flow-create-board}}\" 權限。",
"flow-error-invalid-topic-uuid-title": "無效的標題",
"flow-error-invalid-topic-uuid": "請求的頁面標題無效。 在話題命名空間中的頁面會由 Flow 自動建立。",
"flow-error-unknown-workflow-id-title": "不明話題",
@@ -185,30 +189,33 @@
"flow-error-search": "因暫時性的問題,我們無法完成您的搜尋。請稍候再試。",
"flow-edit-header-placeholder": "請描述此討論板",
"flow-edit-header-submit": "儲存描述",
- "flow-edit-title-submit": "更改標題",
+ "flow-edit-header-submit-anonymously": "匿名使用者儲存描述",
+ "flow-edit-title-submit": "變更標題",
+ "flow-edit-title-submit-anonymously": "匿名使用者修改標題",
"flow-edit-post-submit": "送出變更",
- "flow-rev-message-edit-post": "$1{{GENDER:$2|編輯}}於 \"$4\" 之[$3 評論]",
+ "flow-edit-post-submit-anonymously": "匿名使用者提交變更",
+ "flow-rev-message-edit-post": "$1{{GENDER:$2|已編輯}}於 「$4」 之[$3 評論]",
"flow-rev-message-edit-post-recentchanges-summary": "{{GENDER:$2|已編輯}}一篇貼文",
- "flow-rev-message-reply": "$1 [$3 {{GENDER:$2|已評論}}] 於 \"$4\" (<em>$5</em>)",
- "flow-rev-message-reply-bundle": "<strong>$1 筆{{PLURAL:$1|評論|評論}}</strong> {{PLURAL:$1|已新增|已新增}}",
+ "flow-rev-message-reply": "$1[$3 {{GENDER:$2|已評論}}]「$4」的話題(<em>$5</em>)",
+ "flow-rev-message-reply-bundle": "<strong>$1 筆{{PLURAL:$1|評論}}</strong> {{PLURAL:$1|已新增}}",
"flow-rev-message-new-post": "$1 {{GENDER:$2|已建立}}話題 \"[$3 $4]\"",
"flow-rev-message-new-post-recentchanges-summary": "{{GENDER:$2|已建立}}新話題",
- "flow-rev-message-edit-title": "$1 {{GENDER:$2|已更改}}話題標題自 \"$5\" 至 \"[$3 $4]\"",
- "flow-rev-message-create-header": "$1 {{GENDER:$2|己建立}}描述",
+ "flow-rev-message-edit-title": "$1 原話題標題 「$5」{{GENDER:$2|已變更}}為 「[$3 $4]」",
+ "flow-rev-message-create-header": "$1 {{GENDER:$2|已建立}}描述",
"flow-rev-message-edit-header": "$1 {{GENDER:$2|已編輯}}描述",
"flow-rev-message-create-topic-summary": "$1 {{GENDER:$2|已建立}}於 $3 的話題摘要",
"flow-rev-message-edit-topic-summary": "$1 {{GENDER:$2|已編輯}} $3 的話題摘要",
- "flow-rev-message-hid-post": "$1 {{GENDER:$2|已隱藏}}於 \"$6\" 的一筆 [$4 評論] (<em>$5</em>)",
- "flow-rev-message-deleted-post": "$1 {{GENDER:$2|已刪除}}於 \"$6\" 的一筆 [$4 評論] (<em>$5</em>)",
+ "flow-rev-message-hid-post": "$1 {{GENDER:$2|已隱藏}}於 「$6」 的一筆 [$4 評論] (<em>$5</em>)",
+ "flow-rev-message-deleted-post": "$1 {{GENDER:$2|已刪除}}於 「$6」 的一筆 [$4 評論] (<em>$5</em>)",
"flow-rev-message-suppressed-post": "$1 {{GENDER:$2|已封鎖}}於 \"$6\" 的一筆 [$4 評論] (<em>$5</em>)",
- "flow-rev-message-restored-post": "$1 {{GENDER:$2|已還原}}於 \"$6\" 的一筆 [$4 評論] (<em>$5</em>)",
+ "flow-rev-message-restored-post": "$1 {{GENDER:$2|已還原}}於 「$6」 的一筆 [$4 評論] (<em>$5</em>)",
"flow-rev-message-hid-topic": "$1 {{GENDER:$2|已隱藏}}於 \"$6\" 的 [$4 話題] (<em>$5</em>)",
"flow-rev-message-deleted-topic": "$1 {{GENDER:$2|已刪除}}於 \"$6\" 的 [$4 話題] (<em>$5</em>)",
- "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|已封鎖}}於 \"$6\" 的 [$4 話題] (<em>$5</em>)",
- "flow-rev-message-locked-topic": "$1 {{GENDER:$2|已標記}}於 \"$6\" 的 [$4 話題] 為已解決 (<em>$5</em>)",
+ "flow-rev-message-suppressed-topic": "$1 {{GENDER:$2|已封鎖}}於 「$6」 的 [$4 話題] (<em>$5</em>)",
+ "flow-rev-message-locked-topic": "$1 {{GENDER:$2|已標記}}於“$6”的 [$4 話題] 為已解決 (<em>$5</em>)",
"flow-rev-message-lock-topic-reason": "標記為已解決",
"flow-rev-message-restore-topic-reason": "重新開啟",
- "flow-rev-message-restored-topic": "$1 {{GENDER:$2|已還原}}於 \"$6\" 的 [$4 話題] (<em>$5</em>)",
+ "flow-rev-message-restored-topic": "$1 {{GENDER:$2|已還原}}於 「$6」 的 [$4 話題] (<em>$5</em>)",
"flow-rc-topic-of-board": "於 $2 之 $1",
"flow-board-history": "\"$1\" 歷史",
"flow-board-history-empty": "此討論板目前沒有歷史記錄。",
@@ -219,7 +226,7 @@
"flow-history-week": "上週",
"flow-history-pages-topic": "於 [$1 \"$2\" 討論板] 中顯示",
"flow-history-pages-post": "於 [$1 $2] 中顯示",
- "flow-topic-comments": "{{PLURAL:$1|$1 則評論|0={{GENDER:$2|發表第一則}}評論!}}",
+ "flow-topic-comments": "{{PLURAL:$1|$1則評論|0={{GENDER:$2|發表第一筆}}評論!}}",
"flow-show-comments-title": "{{PLURAL:$1|檢視評論|檢視評論}}",
"flow-hide-comments-title": "{{PLURAL:$1|隱藏評論|隱藏評論}}",
"flow-comment-restored": "已還原的評論",
@@ -228,31 +235,48 @@
"flow-comment-moderated": "受管制的評論",
"flow-last-modified": "上次修改於 $1",
"flow-workflow": "工作流程",
- "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 已於 '''$4''' {{GENDER:$1|回應}}。",
- "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 與{{PLURAL:$6|其他}} $5 個人已於 '''$3''' {{GENDER:$1|回應}}。",
+ "flow-notification-reply": "<span class=\"plainlinks mw-echo-title-heading\">[$5 $2]</span><br />$1 已於 <strong>$4</strong> {{GENDER:$1|回應}}。",
+ "flow-notification-reply-bundle": "<span class=\"plainlinks mw-echo-title-heading\">[$4 $2]</span><br />$1 與{{PLURAL:$5|其他人|其他 $5 個人|100=其他 99+ 個人}}已於 <strong>$3</strong> {{GENDER:$1|回應}}。",
"flow-notification-edit": "<span class=\"plainlinks mw-echo-title-heading\">[$6 $2]</span><br />$1 {{GENDER:$1|已編輯}}您在 [[$3|$4]] 的 <span class=\"plainlinks\">[$5 貼文]</span>。",
- "flow-notification-edit-bundle": "$1 與{{PLURAL:$6|其他}} $5 個人{{GENDER:$1|已編輯}}於 \"$3\" 中 \"$2\" 的 <span class=\"plainlinks\">[$4 貼文]</span>。",
- "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 於 '''$3''' {{GENDER:$1|建立了}}一個新話題。",
- "flow-notification-newtopic-bundle": "於 '''<span class=\"plainlinks\">[$3 $2]</span>''' 中有 {{PLURAL:$1|$1 則新話題|$1 則新話題|250=250+ 則新話題}}",
+ "flow-notification-edit-bundle": "$1 與{{PLURAL:$5|其他人|其他 $5 個人|100=其他 99+ 個人}}{{GENDER:$1|已編輯}}於 \"$3\" 中 \"$2\" 的 <span class=\"plainlinks\">[$4 貼文]</span>。",
+ "notification-header-flow-new-topic-v2": "新話題已建於 <strong>$3</strong>: <bdi>\"<strong>$4</strong>\"</bdi>。",
+ "notification-bundle-header-flow-new-topic": "<strong>$3</strong> 上有 {{PLURAL:$1|1 則新話題|$1 則新話題|100=99+ 則新話題}}。",
+ "notification-header-flow-new-topic-user-talk": "已在<strong>您的對話頁面</strong>建立了新話題: \"<strong>$4</strong>\"。",
+ "notification-bundle-header-flow-new-topic-user-talk": "<strong>您的對話頁面</strong>有 {{PLURAL:$1|1 個新話題|$1 個新話題|100=99+ 個新話題}}。",
+ "notification-header-flow-post-reply": "$1 於 \"<strong>$4</strong>\" {{GENDER:$2|回覆了}}。",
+ "notification-header-flow-post-reply-user-talk": "$1 在<strong>您的對話頁面</strong>裡的 \"<strong>$4</strong>\" {{GENDER:$2|發佈了}} 一則回覆。",
+ "notification-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|您}}的對話頁面</strong>裡的貼文 \"<strong>$1</strong>\" 已被編輯。",
+ "notification-bundle-header-flow-post-edited-user-talk": "<strong>{{GENDER:$2|您}}的對話頁面</strong>裡的貼文 \"<strong>$1</strong>\" 已被編輯了多次。",
+ "notification-header-flow-topic-renamed-user-talk": "<strong>{{GENDER:$3|您的}}對話頁面</strong>裡面的話題 \"<strong>$1</strong>\" 已被重新命名為 \"<strong>$2</strong>\"。",
+ "notification-header-flow-enabled-on-talkpage": "已在<strong>{{GENDER:$2|您}}的使用者討論頁</strong>開啟了新的討論系統。",
+ "notification-bundle-header-flow-description-edited": "<strong>$1</strong> 的描述已被編輯了多次。",
+ "notification-links-flow-description-edited-view-page": "{{GENDER:$1|檢視}}頁面",
+ "notification-header-flow-topic-resolved": "話題 \"<strong>$1</strong>\" 已解決。",
+ "notification-header-flow-topic-reopened": "話題 \"<strong>$1</strong>\" 已重新開啟。",
+ "notification-email-subject-flow-topic-resolved": "話題 \"<strong>$2</strong>\" 已解決。",
+ "notification-email-batch-body-flow-topic-resolved": "話題 \"<strong>$2</strong>\" 已解決。",
+ "flow-notification-newtopic": "<span class=\"mw-echo-title-heading plainlinks\">[$5 $4]</span><br />$1 於 <strong>$3</strong> {{GENDER:$1|建立了}}一個新話題。",
+ "flow-notification-newtopic-bundle": "於 <strong><span class=\"plainlinks\">[$3 $2]</span></strong> 中有 {{PLURAL:$1|一則新話題|$1 則新話題|100=99+ 則新話題}}",
"flow-notification-rename": "$1 {{GENDER:$1|已更改}}於 [[$5|$6]] 中 <span class=\"plainlinks\">[$2 $3]</span> 的標題為 \"$4\"。",
- "flow-notification-mention": "$1 {{GENDER:$1|已提到}}{{GENDER:$5|您}}於 \"$4\" 中 \"$3\" {{GENDER:$1|他|她|他們}}的 <span class=\"plainlinks\">[$2 貼文]</span>。",
+ "flow-notification-mention": "$1 {{GENDER:$1|已提到}}{{GENDER:$5|您}}於 「$4」 中 「$3」 {{GENDER:$1|他|她|他}}的 <span class=\"plainlinks\">[$2 貼文]</span>。",
"flow-notification-link-text-view-post": "檢視貼文",
"flow-notification-link-text-view-topic": "檢視話題",
+ "flow-notification-link-text-view-topics": "檢視話題",
"flow-notification-reply-email-subject": "$2 於 $3",
- "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|已回覆}}位於 $3 中的 \"$2\" 話題",
- "flow-notification-reply-email-batch-bundle-body": "$1 與其他 $4 {{PLURAL:$5|個人}}{{GENDER:$1|回覆了}}位於 $3 中的 \"$2\" 話題",
+ "flow-notification-reply-email-batch-body": "$1 {{GENDER:$1|已回覆}}位於 $3 中的 「$2」 話題",
+ "flow-notification-reply-email-batch-bundle-body": "$1 與{{PLURAL:$4|其他人|其他 $4 個人|100=其他 99+ 個人}}{{GENDER:$1|回覆了}}位於 $3 中的 \"$2\" 話題",
"flow-notification-mention-email-subject": "$1 {{GENDER:$1|已提到}}{{GENDER:$3|您}},在 $2 中",
"flow-notification-mention-email-batch-body": "$1 {{GENDER:$1|已提到}}{{GENDER:$4|您}},在 $3 中 \"$2\" {{GENDER:$1|他|她|他們}}的貼文",
"flow-notification-edit-email-subject": "$1 {{GENDER:$1|已編輯}}一篇留言",
"flow-notification-edit-email-batch-body": "$1 {{GENDER:$1|已編輯}}在 $3 中 \"$2\" 的一篇貼文",
- "flow-notification-edit-email-batch-bundle-body": "$1 與其他 $4 {{PLURAL:$5|個人}} {{GENDER:$1|已編輯}}在 $3 中 \"$2\" 的一篇貼文",
+ "flow-notification-edit-email-batch-bundle-body": "$1 與{{PLURAL:$4|其他人|其他 $4 個人|100=其他 99+ 個人}}{{GENDER:$1|已編輯}}在 $3 中 \"$2\" 的一篇貼文",
"flow-notification-rename-email-subject": "$1 {{GENDER:$1|已重新命名}}您的話題",
"flow-notification-rename-email-batch-body": "您在 $4 的 \"$2\" 話題被{{GENDER:$1|重新命名}}為 \"$3\"",
"flow-notification-newtopic-email-subject": "$1 在 $2 {{GENDER:$1|建立}}了新話題",
"flow-notification-newtopic-email-batch-body": "$1 在 $3 {{GENDER:$1|建立}}了一則新話題,標題為 \"$2\"",
- "flow-notification-newtopic-email-batch-bundle-body": "$2 有 {{PLURAL:$1|$1 則新話題|$1 則新話題|250=250+ 則新話題}}",
+ "flow-notification-newtopic-email-batch-bundle-body": "$2 有 {{PLURAL:$1|一則新話題|$1 則新話題|100=99+ 則新話題}}",
"echo-category-title-flow-discussion": "Flow",
- "echo-pref-tooltip-flow-discussion": "通知我,當有與我相關的動作發生在 Flow 時。",
+ "echo-pref-tooltip-flow-discussion": "當有與我相關的動作發生在 Flow 時,通知我。",
"flow-link-post": "發佈",
"flow-link-topic": "話題",
"flow-link-history": "歷史",
@@ -284,18 +308,18 @@
"flow-moderation-confirm-unsuppress-topic": "解除封鎖",
"flow-moderation-confirm-undelete-topic": "取消刪除",
"flow-moderation-confirm-unhide-topic": "取消隱藏",
- "flow-moderation-confirmation-suppress-post": "已成功封鎖貼文。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
- "flow-moderation-confirmation-delete-post": "已成功刪除貼文。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
- "flow-moderation-confirmation-hide-post": "已成功隱藏留言。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
- "flow-moderation-confirmation-unsuppress-post": "您已成功解除封鎖以上貼文。",
- "flow-moderation-confirmation-undelete-post": "您已成功取消刪除以上留言。",
- "flow-moderation-confirmation-unhide-post": "您已成功取消隱藏以上貼文。",
+ "flow-moderation-confirmation-suppress-post": "已封鎖貼文。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
+ "flow-moderation-confirmation-delete-post": "已刪除貼文。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
+ "flow-moderation-confirmation-hide-post": "已隱藏留言。\n{{GENDER:$2|請考慮}}讓 $1 對此話題提供意見回饋。",
+ "flow-moderation-confirmation-unsuppress-post": "您已解除封鎖以上貼文。",
+ "flow-moderation-confirmation-undelete-post": "您已取消刪除以上留言。",
+ "flow-moderation-confirmation-unhide-post": "您已取消隱藏以上貼文。",
"flow-moderation-confirmation-suppress-topic": "已成功封鎖此話題。",
"flow-moderation-confirmation-delete-topic": "已成功刪除此話題。",
"flow-moderation-confirmation-hide-topic": "已成功隱藏此話題。",
- "flow-moderation-confirmation-unsuppress-topic": "您已成功解除封鎖此話題。",
- "flow-moderation-confirmation-undelete-topic": "您已成功取消刪除此話題。",
- "flow-moderation-confirmation-unhide-topic": "您已成功取消隱藏此話題。",
+ "flow-moderation-confirmation-unsuppress-topic": "您已解除封鎖此話題。",
+ "flow-moderation-confirmation-undelete-topic": "您已取消刪除此話題。",
+ "flow-moderation-confirmation-unhide-topic": "您已取消隱藏此話題。",
"flow-moderation-title-suppress-topic": "封鎖話題?",
"flow-moderation-title-delete-topic": "刪除話題?",
"flow-moderation-title-hide-topic": "隱藏話題?",
@@ -332,7 +356,7 @@
"flow-terms-of-use-edit": "透過儲存您的更改,您同意此 wiki 之使用條款。",
"flow-anon-warning": "您尚未登入。 要收到使用您的名字的署名而非 IP 位址,您可以 [$1 登入] 或 [$2 建立帳號]。",
"flow-cancel-warning": "您已於此表單輸入內容,您確定要放棄內容?",
- "flow-topic-first-heading": "於 $1 的話題",
+ "flow-topic-first-heading": "位於 $1 的話題",
"flow-topic-html-title": "$1 於 $2",
"flow-topic-count": "話題 ($1)",
"flow-load-more": "讀取更多",
@@ -350,7 +374,7 @@
"flow-whatlinkshere-post": "來自一筆 [$1 貼文]",
"flow-whatlinkshere-header": "來自 [$1 描述]",
"flow-whatlinkshere-post-summary": "來自 [$1 摘要]",
- "flow": "Flow",
+ "structureddiscussions": "Flow",
"flow-special-desc": "此特殊頁面會重新導向至指定 UUID 的 Flow 工作流程或 Flow 貼文。",
"flow-special-type": "類型",
"flow-special-type-post": "發佈",
@@ -364,7 +388,9 @@
"flow-special-enableflow-invalid-title": "提供了無效的頁面標題。",
"flow-special-enableflow-board-creation-not-allowed": "您不被允許建立 Flow 留言板於 [[:$1]]。",
"flow-special-enableflow-page-is-liquidthreads": "[[:$1]] 己使用 LiquidThreads 頁面。",
- "flow-special-enableflow-confirmation": "您已成功建立了 Flow 留言板於 [[$1]]。",
+ "flow-special-enableflow-confirmation": "您已建立了 Flow 留言板於 [[$1]]。",
+ "flow-conversion-archive-page-name-format": "%s/存檔 %d\n%s/存檔%d\n%s/存檔 %d\n%s/存檔%d",
+ "flow-conversion-archive-flow-page-name-format": "%s/Flow 存檔 %d\n%s/Flow存檔%d",
"flow-spam-confirmedit-form": "請回答以下驗証碼來確認您不是機器人:$1",
"flow-embedding-unsupported": "無法嵌入討論。",
"mw-ui-unsubmitted-confirm": "您在此頁面有未送出的變更,您確定要離開此頁面並放棄您的修改?",
@@ -374,45 +400,24 @@
"flow-topic-undo-hide": "還原隱藏",
"flow-topic-undo-delete": "還原刪除",
"flow-topic-undo-suppress": "還原封鎖",
+ "flow-importer-lqt-moved-thread-template": "LQT移動了頁面存檔,並轉換成Flow",
"flow-importer-lqt-moved-thread-template-content": "此貼文已於 {{{date}}} 由 {{{author}}} 移動至它處。 您可以在 [[{{{title}}}]] 找到該貼文。",
"flow-importer-lqt-converted-template": "LQT 頁面已轉換為 Flow",
"flow-importer-lqt-converted-template-content": "先前的頁面歷史已於 {{#time: Y-m-d|{{{date}}}}} 存檔至 <span class='flow-link-to-archive'>[[{{{archive}}}]]</span> 做為備份。",
"flow-importer-lqt-converted-archive-template": "已轉換的 LQT 頁面備份",
- "flow-importer-lqt-converted-archive-template-content": "此頁面為存檔的 LiquidThreads 頁面,'''請勿編輯此頁面內容'''。 請在 [[{{{from}}}|目前對話頁面]] 發表補充評論。",
+ "flow-importer-lqt-converted-archive-template-content": "此頁面為存檔的 LiquidThreads 頁面,<strong>請勿編輯此頁面內容</strong>。 請在 [[{{{from}}}|目前對話頁面]] 發表補充評論。",
"flow-importer-wt-converted-template": "Wikitext 對話頁面已轉換為 Flow",
"flow-importer-wt-converted-template-content": "先前的討論已於 {{#time: Y-m-d|{{{date}}}}} 存檔至 <span class='flow-link-to-archive'>[[{{{archive}}}]]</span>。",
"flow-importer-wt-converted-archive-template": "已轉換的 wikitext 對話頁面備份",
- "flow-importer-wt-converted-archive-template-content": "此頁面為存檔頁面,'''請勿編輯此頁面內容'''。 請在 [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|目前對話頁面]] 發表補充評論。",
+ "flow-importer-wt-converted-archive-template-content": "此頁面為存檔頁面,<strong>請勿編輯此頁面內容</strong>。 請在 [[{{{from|{{TALKSPACE}}:{{BASEPAGENAME}}}}}|目前對話頁面]] 發表補充評論。",
"flow-importer-lqt-suppressed-user-template": "由被封鎖的使用者所匯入的 LQT 貼文",
"flow-importer-lqt-suppressed-user-template-content": "此修訂由被封鎖的使用者自 LiquidThreads 匯入。 目前已重新指派為目前的使用者。",
"flow-importer-lqt-different-author-signature-template": "由不同簽名的使用者所匯入的 LQT 貼文",
- "flow-importer-lqt-different-author-signature-template-content": "''此貼文由 [[User:{{{authorUser}}}|{{{authorUser}}}]] 所發表,但卻以 [[User:{{{signatureUser}}}|{{{signatureUser}}}]] 簽名。''",
- "apihelp-flow-description": "允許對 Flow 頁面執行操作。",
- "apihelp-flow-param-submodule": "要使用的 Flow 子模組。",
- "apihelp-flow-param-page": "要執行操作的頁面。",
- "apihelp-flow-example-1": "編輯 \"[[Talk:Sandbox]]\" 的描述",
- "apihelp-flow+close-open-topic-description": "已不建議使用 [[Special:ApiHelp/flow+lock-topic|action=flow&submodule=lock-topic]] 用法。",
- "apihelp-flow+close-open-topic-param-moderationState": "話題要設定的狀態,可為 \"lock\" 或 \"unlock\"。",
- "apihelp-flow+close-open-topic-param-reason": "鎖定或解除鎖定話題的原因。",
- "apihelp-flow+edit-header-description": "編輯討論板的描述。",
- "apihelp-flow+edit-header-param-prev_revision": "目前描述修訂的修訂 ID,以用來檢查編輯衝突。",
- "apihelp-flow+edit-header-param-content": "內容描述。",
- "apihelp-flow+edit-header-param-format": "描述格式 (wikitext|html)。",
- "apihelp-flow+edit-header-example-1": "編輯 [[Talk:Sandbox]] 的描述",
- "apihelp-flow+edit-post-description": "編輯一篇貼文的內容。",
- "apihelp-flow+edit-post-param-postId": "貼文 ID。",
- "apihelp-flow+edit-post-param-prev_revision": "目前貼文修訂的修訂 ID,以用來檢查編輯衝突。",
- "apihelp-flow+edit-post-param-content": "貼文的內容。",
- "apihelp-flow+edit-post-param-format": "貼文內容格式 (wikitext|html)",
- "apihelp-flow+edit-post-example-1": "編輯於 [[Topic:S2tycnas4hcucw8w]] 的貼文",
- "apihelp-flow+edit-title-description": "編輯話題的標題。",
- "apihelp-flow+reply-description": "回覆一篇貼文。",
- "apihelp-flow+reply-param-content": "新貼文的內容。",
- "apihelp-flow+reply-example-1": "於 [[Topic:S2tycnas4hcucw8w]] 回覆一篇貼文",
- "apihelp-flow+view-header-description": "檢視討論板的描述。",
- "apihelp-flow+view-post-description": "檢視一篇貼文。",
+ "flow-importer-lqt-different-author-signature-template-content": "<em>此貼文由 [[User:{{{authorUser}}}|{{{authorUser}}}]] 所發表,但卻以 [[User:{{{signatureUser}}}|{{{signatureUser}}}]] 簽名。</em>",
"flow-edited": "已編輯於",
"flow-edited-by": "已編輯由 $1",
+ "flow-talk-conversion-move-reason": "$1的wikitext討論頁轉換成Flow頁面",
+ "flow-talk-conversion-archive-edit-reason": "Wikitext討論頁至Flow轉換",
"flow-previous-diff": "← 較舊編輯",
"flow-next-diff": "較新編輯 →",
"flow-undo": "還原",
@@ -421,9 +426,11 @@
"flow-undo-edit-header": "正在編輯描述",
"flow-undo-edit-topic-summary": "正在編輯話題摘要",
"flow-undo-edit-post": "正在編輯貼文",
+ "flow-undo-edit-content": "此編輯可以被還原。請檢查下列差異,確認您是否要還原,然後儲存以下變更以完成編輯還原。",
+ "flow-undo-edit-failure": "由於編輯的修訂間有衝突,此編輯不能還原。",
"group-flow-bot": "Flow 機器人",
- "group-flow-bot-member": "Flow 機器人",
- "grouppage-flow-bot": "Project:Flow bots",
+ "group-flow-bot-member": "Flow機器人",
+ "grouppage-flow-bot": "Project:Flow机器人",
"flow-ve-mention-context-item-label": "提到",
"flow-ve-mention-inspector-title": "提到",
"flow-ve-mention-inspector-remove-label": "移除",
@@ -432,8 +439,8 @@
"flow-ve-mention-template-title": "FlowMention",
"flow-ve-mention-inspector-invalid-user": "使用者名稱 \"$1\" 未註冊。",
"flow-wikitext-editor-help": "Wikitext $1。",
- "flow-wikitext-editor-help-and-preview": "Wikitext $1 且您可以隨時 $2。",
- "flow-wikitext-editor-help-uses-wikitext": "[[mw:Help:Formatting|使用標籤]]",
+ "flow-wikitext-editor-help-and-preview": "Wikitext $1;您可以隨時 $2。",
+ "flow-wikitext-editor-help-uses-wikitext": "[[mw:Special:MyLanguage/Help:Formatting|標籤用法]]",
"flow-wikitext-editor-help-preview-the-result": "預覽結果",
"flow-wikitext-switch-editor-tooltip": "切換至視覺化編輯器",
"flow-ve-switch-editor-tool-title": "切換至 Wikitext 編輯器",
@@ -443,7 +450,7 @@
"flow-mark-diff-patrolled-link-title": "標記為已巡查",
"flow-talk-page-beta-feature-message": "於使用者對話上使用 Flow",
"flow-talk-page-beta-feature-description": "於{{GENDER:|您的}}使用者對話頁面開啟新結構化討論系統。 Flow 透過簡潔的方式提供發表與回覆的功能來簡化對話頁面的討論方式,並允許對話層級的通知。 已存在的 wikitext 討論內容將會移動至存檔頁面。 此功能不會自動開啟,使用者需要手動開啟。 關閉此功能將會移動 Flow 討論板至子頁面並且還原先前對話頁面的存檔。",
- "flow-notification-link-text-enabled-on-talkpage": "檢視使用者對話頁面",
+ "flow-notification-link-text-enabled-on-talkpage": "{{GENDER:|檢視}}使用者對話頁面",
"flow-notification-enabled-on-talkpage-title": "{{GENDER:$1|您的}}使用者對話頁面已開啟新討論系統<br /><small>於 [[$2]] 可用</small>",
"flow-notification-enabled-on-talkpage-email-subject-message": "於 $2 的新討論系統",
"flow-notification-enabled-on-talkpage-email-batch-body": "已在 {{SITENAME}} 於{{GENDER:$1|您的}}使用者對話頁面開啟新 wiki 討論系統 Flow。 您可以隨時於{{GENDER:$1|您的}}偏好設定中的試用版功能區取得更多資訊,提供意見回饋或者關閉新的系統。",
@@ -453,6 +460,8 @@
"flow-dialog-cancelconfirm-message": "您確定要取消而不儲存嗎?",
"flow-dialog-cancelconfirm-keep": "繼續編輯",
"flow-dialog-cancelconfirm-discard": "放棄變更",
+ "flow-optin-restore-wikitext": "恢復已存檔的wikitext頁面。",
+ "flow-optin-restore-flow-board": "恢復已存檔的討論版塊。",
"flow-guidedtour-optin-welcome": "{{GENDER:$1|歡迎光臨}}來到{{GENDER:$1|您的}}新使用者對話頁面",
"flow-guidedtour-optin-welcome-description": "{{GENDER:$1|您的}}對話頁面提供其他編輯人員可聯絡{{GENDER:$1|您}}的地方。 使用 Flow 可更簡單的發起新的話題並追蹤對話的狀況。",
"flow-guidedtour-optin-find-old-conversations": "尋找{{GENDER:$1|您}}的舊談話",
diff --git a/Flow/images/betafeature-flow-ltr.svg b/Flow/images/betafeature-flow-ltr.svg
index 9fb14a61..eb0ccaf1 100644
--- a/Flow/images/betafeature-flow-ltr.svg
+++ b/Flow/images/betafeature-flow-ltr.svg
@@ -1,23 +1,22 @@
<?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">
- <g id="g4">
- <path d="M13.366 161.357L.5 151.75V.5h263v151.75l-9 6.704V42.5h-39v112.6l-4.393-3.73-7.607 5.33V42.5h-155v110.85l-9.75 8.03-13.917-10.02z" id="path6" fill="#fff"/>
- <path d="M263 1v150.998l-8 5.96V42h-40v112.02l-3.274-2.78-.59-.5-.632.442-6.504 4.556V42H48v111.1l-9.257 7.66-13.295-9.57-.645-.463-.598.52-10.864 9.47L1 151.5V1h262m1-1H0v152l13.39 10 11.475-10 13.89 10L49 153.6V43h154v114.66l8.078-5.66 4.922 4.18V43h38v116.95l10-7.45V0z" id="path8" fill="#e5e5e5"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162">
+ <defs>
+ <clipPath id="a">
+ <path 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 clip-path="url(#a)">
+ <path d="M263.5 162.25l-263-.5V.5h263z" fill="#fff"/>
+ <path d="M252 162.496V29H48v133.496zM11 22c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14zM38 163.807V58H13v105.807h25z" fill="#e5e5e5"/>
+ <g fill="#e5e5e5">
+ <path d="M233 5h26v6h-26V5zM209 5h22v6h-22zM185 5h22v6h-22zM162 5h13v6h-13zM177 5h6v6h-6zM154 5h6v6h-6z"/>
+ </g>
+ <g fill="#e5e5e5">
+ <path d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z"/>
+ <path d="M168 17h2v2h-2z"/>
+ </g>
+ <path d="M38 45v-5H13v5h25z" fill="#e5e5e5"/>
+ <path 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.167z" fill="#e5e5e5"/>
+ <path d="M191.047 81.46v39.226l8.717 8.717h-61.02V81.46h52.303zm-74.094-21.792h52.302v17.434h-34.868v30.51h-26.15l8.716-8.718V59.668z" fill="#36c"/>
</g>
- <path d="M203 157.66V43H49v110.6l2.145-1.6L63.7 162l13.81-10 14.228 10 12.972-10 12.973 10 13.81-10 12.137 10 13.39-10 14.23 10 12.972-10 12.974 10 5.804-4.34z" id="path10" fill="#e5e5e5"/>
- <path d="M11 36c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14z" id="path12" fill="#e5e5e5"/>
- <path d="M254 159.95V43h-38v113.18l7.55 5.82 13.812-10 13.89 10 2.748-2.05z" id="path14" fill="#e5e5e5"/>
- <path d="M38 132.354V72H13v60.354h25z" id="path16" fill="#e5e5e5"/>
- <path d="M232.51 5h26v6h-26V5z" id="path18" fill="#e5e5e5"/>
- <path d="M208.51 5h22v6h-22z" id="path20" fill="#e5e5e5"/>
- <path d="M142 6v4H50V6h92m1-1H49v6h94V5z" id="path22" fill="#e5e5e5"/>
- <path d="M184.51 5h22v6h-22z" id="path24" fill="#e5e5e5"/>
- <path d="M161.51 5h13v6h-13z" id="path26" fill="#e5e5e5"/>
- <path d="M176.51 5h6v6h-6z" id="path28" fill="#e5e5e5"/>
- <path d="M153.51 5h6v6h-6z" id="path30" fill="#e5e5e5"/>
- <path d="M9 5h32v6H9z" id="path32" fill="#e5e5e5"/>
- <path d="M2 14.5h260" id="path34" fill="#e5e5e5" stroke="#e5e5e5"/>
- <path d="M52 7h2v2h-2z" id="path36" fill="#e5e5e5"/>
- <path d="M38 59v-5H13v5h25z" id="path38" fill="#e5e5e5"/>
- <path d="M163.047 85.46v39.226l8.717 8.717h-61.02V85.46h52.303zM88.953 63.668h52.302v17.434h-34.868v30.51h-26.15l8.716-8.718V63.668z" id="path4059" fill="#347bff"/>
</svg>
diff --git a/Flow/images/betafeature-flow-rtl.svg b/Flow/images/betafeature-flow-rtl.svg
index a0de77b2..ff2ad211 100644
--- a/Flow/images/betafeature-flow-rtl.svg
+++ b/Flow/images/betafeature-flow-rtl.svg
@@ -1,23 +1,22 @@
<?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">
- <g id="g4">
- <path d="M250.634 161.357l12.866-9.608V.5H.5v151.75l9 6.704V42.5h39v112.6l4.393-3.73 7.607 5.33V42.5h155v110.85l9.75 8.03 13.917-10.02z" id="path6" fill="#fff"/>
- <path d="M1 1v150.998l8 5.96V42h40v112.02l3.274-2.78.59-.5.632.442L60 155.738V42h156v111.1l9.257 7.66 13.295-9.57.645-.463.598.52 10.864 9.47L263 151.5V1H1M0 0h264v152l-13.39 10-11.475-10-13.89 10L215 153.6V43H61v114.66L52.922 152 48 156.18V43H10v116.95L0 152.5V0z" id="path8" fill="#e5e5e5"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162">
+ <defs>
+ <clipPath id="a">
+ <path 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)" clip-path="url(#a)">
+ <path d="M263.5 162.25l-263-.5V.5h263z" fill="#fff"/>
+ <path d="M252 162.496V29H48v133.496zM11 22c0-7.732 6.268-14 14-14s14 6.268 14 14-6.268 14-14 14-14-6.268-14-14zM38 163.807V58H13v105.807h25z" fill="#e5e5e5"/>
+ <g fill="#e5e5e5">
+ <path d="M233 5h26v6h-26V5zM209 5h22v6h-22zM185 5h22v6h-22zM162 5h13v6h-13zM177 5h6v6h-6zM154 5h6v6h-6z"/>
+ </g>
+ <g fill="#e5e5e5">
+ <path d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z"/>
+ <path d="M168 17h2v2h-2z"/>
+ </g>
+ <path d="M38 45v-5H13v5h25z" fill="#e5e5e5"/>
+ <path 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.167z" fill="#e5e5e5"/>
+ <path d="M191.047 81.46v39.226l8.717 8.717h-61.02V81.46h52.303zm-74.094-21.792h52.302v17.434h-34.868v30.51h-26.15l8.716-8.718V59.668z" fill="#36c"/>
</g>
- <path d="M61 157.66V43h154v110.6l-2.145-1.6-12.555 10-13.81-10-14.228 10-12.972-10-12.973 10-13.81-10-12.137 10-13.39-10-14.23 10-12.972-10-12.974 10L61 157.66z" id="path10" fill="#e5e5e5"/>
- <path d="M253 36c0-7.732-6.268-14-14-14s-14 6.268-14 14 6.268 14 14 14 14-6.268 14-14z" id="path12" fill="#e5e5e5"/>
- <path d="M10 159.95V43h38v113.18L40.45 162l-13.812-10-13.89 10L10 159.95z" id="path14" fill="#e5e5e5"/>
- <path d="M226 132.354V72h25v60.354h-25z" id="path16" fill="#e5e5e5"/>
- <path d="M31.49 5h-26v6h26V5z" id="path18" fill="#e5e5e5"/>
- <path d="M55.49 5h-22v6h22z" id="path20" fill="#e5e5e5"/>
- <path d="M122 6v4h92V6h-92m-1-1h94v6h-94V5z" id="path22" fill="#e5e5e5"/>
- <path d="M79.49 5h-22v6h22z" id="path24" fill="#e5e5e5"/>
- <path d="M102.49 5h-13v6h13z" id="path26" fill="#e5e5e5"/>
- <path d="M87.49 5h-6v6h6z" id="path28" fill="#e5e5e5"/>
- <path d="M110.49 5h-6v6h6z" id="path30" fill="#e5e5e5"/>
- <path d="M255 5h-32v6h32z" id="path32" fill="#e5e5e5"/>
- <path d="M262 14.5H2" id="path34" fill="#e5e5e5" stroke="#e5e5e5"/>
- <path d="M212 7h-2v2h2z" id="path36" fill="#e5e5e5"/>
- <path d="M226 59v-5h25v5h-25z" id="path38" fill="#e5e5e5"/>
- <path d="M100.953 85.46v39.226l-8.717 8.717h61.02V85.46h-52.303zm74.094-21.792h-52.302v17.434h34.868v30.51h26.15l-8.716-8.718V63.668z" id="path4059" fill="#347bff"/>
</svg>
diff --git a/Flow/includes/Actions/Action.php b/Flow/includes/Actions/Action.php
index 95625d46..6213826b 100644
--- a/Flow/includes/Actions/Action.php
+++ b/Flow/includes/Actions/Action.php
@@ -35,6 +35,10 @@ class FlowAction extends Action {
$this->actionName = $actionName;
}
+ public function doesWrites() {
+ return true;
+ }
+
/**
* @return string
*/
@@ -59,14 +63,22 @@ class FlowAction extends Action {
$output = $this->context->getOutput();
}
- // Check if this is actually a Flow page.
- if ( ! $this->page instanceof WikiPage && ! $this->page instanceof Article ) {
- throw new ErrorPageError( 'nosuchaction', 'flow-action-unsupported' );
+ // Check if this is actually the right type of page.
+ if ( !$this->page instanceof WikiPage && !$this->page instanceof Article ) {
+ throw new ErrorPageError( 'nosuchaction', 'flow-action-not-page' );
}
$title = $this->page->getTitle();
- if ( $title->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
- throw new ErrorPageError( 'nosuchaction', 'flow-action-unsupported' );
+
+ $titleContentModel = $title->getContentModel();
+ if ( $titleContentModel !== CONTENT_MODEL_FLOW_BOARD ) {
+ // If we make it to this method, something thinks it's Flow.
+ // However, if we get here the Title class thinks otherwise.
+
+ // This may mean it is a non-Flow page in a Flow namespace, if
+ // page_content_model is populated but rev_content_model is not.
+
+ throw new ErrorPageError( 'nosuchaction', 'flow-action-wrong-title-content-model', $titleContentModel );
}
// @todo much of this seems to duplicate BoardContent::getParserOutput
@@ -98,7 +110,7 @@ class FlowAction extends Action {
}
$view->show( $loader, $action );
- } catch( FlowException $e ) {
+ } catch ( FlowException $e ) {
$e->setOutput( $output );
throw $e;
}
@@ -137,6 +149,8 @@ class FlowAction extends Action {
}
// We need to redirect
- return $redirTitle->getLinkURL();
+ return $redirTitle->getLinkURL(
+ array_diff_key( $request->getValues(), [ 'title' => '', 'workflow' => '' ] )
+ );
}
}
diff --git a/Flow/includes/Actions/EditAction.php b/Flow/includes/Actions/EditAction.php
index 0ec9ece5..6eb96be1 100644
--- a/Flow/includes/Actions/EditAction.php
+++ b/Flow/includes/Actions/EditAction.php
@@ -28,4 +28,7 @@ class EditAction extends FlowAction {
$this->context->getOutput()->redirect( $title->getFullURL() );
}
+ public function doesWrites() {
+ return false;
+ }
}
diff --git a/Flow/includes/Actions/PurgeAction.php b/Flow/includes/Actions/PurgeAction.php
index d6ceeb94..097698b7 100644
--- a/Flow/includes/Actions/PurgeAction.php
+++ b/Flow/includes/Actions/PurgeAction.php
@@ -41,14 +41,14 @@ class PurgeAction extends \PurgeAction {
// will initialize memcache before this is run when UseSquid is enabled.
Container::reset();
$container = Container::getContainer();
- $container->extend( 'memcache', function( $memcache, $c ) {
+ $container->extend( 'memcache', function ( $memcache, $c ) {
$c['memcache.purge_backup'] = $memcache;
return new HashBagOStuff;
} );
$this->hashBag = $container['memcache'];
$this->realMemcache = $container['memcache.purge_backup'];
- if ( !parent::onSubmit( array() ) ) {
+ if ( !parent::onSubmit( [] ) ) {
return false;
}
@@ -58,13 +58,13 @@ class PurgeAction extends \PurgeAction {
->createWorkflowLoader( $this->page->getTitle() )
->getWorkflow();
- switch( $workflow->getType() ) {
+ switch ( $workflow->getType() ) {
case 'discussion':
$this->fetchDiscussion( $workflow );
break;
case 'topic':
- $this->fetchTopics( array( $workflow->getId()->getAlphadecimal() => $workflow->getId() ) );
+ $this->fetchTopics( [ $workflow->getId()->getAlphadecimal() => $workflow->getId() ] );
break;
default:
@@ -84,34 +84,34 @@ class PurgeAction extends \PurgeAction {
* @param Workflow $workflow
*/
protected function fetchDiscussion( Workflow $workflow ) {
- $results = array();
- $pagers = array();
+ $results = [];
+ $pagers = [];
/** @var ManagerGroup $storage */
$storage = Container::get( 'storage' );
// 'newest' sort order
$pagers[] = new Pager(
$storage->getStorage( 'TopicListEntry' ),
- array( 'topic_list_id' => $workflow->getId() ),
- array( 'pager-limit' => 499 )
+ [ 'topic_list_id' => $workflow->getId() ],
+ [ 'pager-limit' => 499 ]
);
// 'updated' sort order
$pagers[] = new Pager(
$storage->getStorage( 'TopicListEntry' ),
- array( 'topic_list_id' => $workflow->getId() ),
- array(
+ [ 'topic_list_id' => $workflow->getId() ],
+ [
'pager-limit' => 499,
'sort' => 'workflow_last_update_timestamp',
'order' => 'desc',
- )
+ ]
);
// Based on Header::init.
$storage->find(
'Header',
- array( 'rev_type_id' => $workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $workflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
foreach ( $pagers as $pager ) {
@@ -124,14 +124,10 @@ class PurgeAction extends \PurgeAction {
$this->fetchTopics( $results );
// purge the board history
- $storage->find(
- 'BoardHistoryEntry',
- array( 'topic_list_id' => $workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 499 )
- );
+ $boardHistoryQuery = Container::get( 'query.board.history' );
+ $boardHistoryQuery->getResults( $workflow->getId(), 499 );
}
-
/**
* Load the requested topics. Does not return anything, the goal
* here is to populate $this->hashBag.
@@ -140,20 +136,16 @@ class PurgeAction extends \PurgeAction {
*/
protected function fetchTopics( array $results ) {
// purge the revisions that make up the topic
- /** @var TopicListQuery $query */
- $query = Container::get( 'query.topiclist' );
- $query->getResults( $results );
+ /** @var TopicListQuery $topicListQuery */
+ $topicListQuery = Container::get( 'query.topiclist' );
+ $topicListQuery->getResults( $results );
+
+ $topicHistoryQuery = Container::get( 'query.topic.history' );
- // Purge the history
- $queries = array();
foreach ( $results as $id ) {
- $queries[] = array( 'topic_root_id' => $id );
+ // purge the topic history
+ $topicHistoryQuery->getResults( $id, 499 );
}
- Container::get( 'storage' )->findMulti(
- 'TopicHistoryEntry',
- $queries,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 499 )
- );
}
/**
@@ -167,7 +159,7 @@ class PurgeAction extends \PurgeAction {
// that contain our prefix.
$keys = array_filter(
array_keys( $reflProp->getValue( $this->hashBag ) ),
- function( $key ) use( $prefix ) {
+ function ( $key ) use( $prefix ) {
if ( strpos( $key, $prefix ) === 0 ) {
return true;
} else {
@@ -189,7 +181,7 @@ class PurgeAction extends \PurgeAction {
protected function cacheKeyPrefix() {
global $wgFlowDefaultWikiDb;
if ( $wgFlowDefaultWikiDb === false ) {
- return wfWikiId();
+ return wfWikiID();
} else {
return $wgFlowDefaultWikiDb;
}
diff --git a/Flow/includes/Actions/ViewAction.php b/Flow/includes/Actions/ViewAction.php
index f4188178..e63e8b4b 100644
--- a/Flow/includes/Actions/ViewAction.php
+++ b/Flow/includes/Actions/ViewAction.php
@@ -12,6 +12,10 @@ class ViewAction extends FlowAction {
parent::__construct( $page, $context, 'view' );
}
+ public function doesWrites() {
+ return false;
+ }
+
public function showForAction( $action, OutputPage $output = null ) {
parent::showForAction( $action, $output );
@@ -22,24 +26,23 @@ class ViewAction extends FlowAction {
$output = $this->context->getOutput();
}
$output->addCategoryLinks( $this->getCategories( $title ) );
-
}
protected function getCategories( Title $title ) {
$id = $title->getArticleId();
if ( !$id ) {
- return array();
+ return [];
}
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select(
/* from */ 'categorylinks',
- /* select */ array( 'cl_to', 'cl_sortkey' ),
- /* conditions */ array( 'cl_from' => $id ),
+ /* select */ [ 'cl_to', 'cl_sortkey' ],
+ /* conditions */ [ 'cl_from' => $id ],
__METHOD__
);
- $categories = array();
+ $categories = [];
foreach ( $res as $row ) {
$categories[$row->cl_to] = $row->cl_sortkey;
}
diff --git a/Flow/includes/Api/ApiFlow.php b/Flow/includes/Api/ApiFlow.php
index b8b6afb4..4863cc9c 100644
--- a/Flow/includes/Api/ApiFlow.php
+++ b/Flow/includes/Api/ApiFlow.php
@@ -11,10 +11,12 @@ use Title;
class ApiFlow extends ApiBase {
- /** @var ApiModuleManager $moduleManager */
+ /**
+ * @var ApiModuleManager
+ */
private $moduleManager;
- private static $alwaysEnabledModules = array(
+ private static $alwaysEnabledModules = [
// POST
'new-topic' => 'Flow\Api\ApiFlowNewTopic',
'edit-header' => 'Flow\Api\ApiFlowEditHeader',
@@ -40,11 +42,11 @@ class ApiFlow extends ApiBase {
'view-topic-history' => 'Flow\Api\ApiFlowViewTopicHistory',
'view-header' => 'Flow\Api\ApiFlowViewHeader',
'view-topic-summary' => 'Flow\Api\ApiFlowViewTopicSummary',
- );
+ ];
- private static $searchModules = array(
+ private static $searchModules = [
'search' => 'Flow\Api\ApiFlowSearch',
- );
+ ];
public function __construct( $main, $action ) {
global $wgFlowSearchEnabled;
@@ -75,26 +77,18 @@ class ApiFlow extends ApiBase {
// The checks for POST and tokens are the same as ApiMain.php
$wasPosted = $this->getRequest()->wasPosted();
if ( !$wasPosted && $module->mustBePosted() ) {
- $this->dieUsageMsg( array( 'mustbeposted', $params['submodule'] ) );
+ $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $params['submodule'] ] );
}
if ( $module->needsToken() ) {
if ( !isset( $params['token'] ) ) {
- $this->dieUsageMsg( array( 'missingparam', 'token' ) );
+ $this->dieWithError( [ 'apierror-missingparam', 'token' ] );
}
- if ( is_callable( array( $module, 'validateToken' ) ) ) {
- if ( !$module->validateToken( $params['token'], $params ) ) {
- $this->dieUsageMsg( 'sessionfailure' );
- }
- } else {
- if ( !$this->getUser()->matchEditToken(
- $params['token'],
- $module->getTokenSalt(),
- $this->getRequest() )
- ) {
- $this->dieUsageMsg( 'sessionfailure' );
- }
+ $module->requirePostedParameters( [ 'token' ] );
+
+ if ( !$module->validateToken( $params['token'], $params ) ) {
+ $this->dieWithError( 'apierror-badtoken' );
}
}
@@ -104,7 +98,7 @@ class ApiFlow extends ApiBase {
$module->setPage( $this->getPage( $params ) );
}
$module->execute();
- Hooks::run( 'APIFlowAfterExecute', array( $module ) );
+ Hooks::run( 'APIFlowAfterExecute', [ $module ] );
$module->profileOut();
}
@@ -115,17 +109,27 @@ class ApiFlow extends ApiBase {
protected function getPage( $params ) {
$page = Title::newFromText( $params['page'] );
if ( !$page ) {
- $this->dieUsage( 'Invalid page provided', 'invalid-page' );
+ $this->dieWithError(
+ [ 'apierror-invalidtitle', wfEscapeWikiText( $params['page'] ) ], 'invalid-page'
+ );
+ }
+
+ if ( $page->getNamespace() < 0 ) {
+ $this->dieWithError(
+ [ 'apierror-invalidtitle', wfEscapeWikiText( $params['page'] ) ], 'invalid-page-negative-namespace'
+ );
}
+
/** @var \Flow\TalkpageManager $controller */
$controller = Container::get( 'occupation_controller' );
if ( $page->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
// Just check for permissions, nothing else to do. The Flow board
// will be put in place right before the rest of the data is stored
// (in SubmissionHandler::commit), after everything's been validated.
- $status = $controller->allowCreation( $page, $this->getUser() );
+ $status = $controller->safeAllowCreation( $page, $this->getUser(),
+ /* $mustNotExist = */ true, /* $forWrite = */ false );
if ( !$status->isGood() ) {
- $this->dieUsage( "Page provided does not have Flow enabled and allowCreation failed with: " . $status->getMessage()->parse(), 'invalid-page' );
+ $this->dieWithError( [ 'apierror-flow-safeallowcreationfailed', $status->getMessage() ], 'invalid-page' );
}
}
@@ -133,114 +137,42 @@ class ApiFlow extends ApiBase {
}
public function getAllowedParams() {
- $mainParams = $this->getMain()->getAllowedParams();
- if ( $mainParams['action'][ApiBase::PARAM_TYPE] === 'submodule' ) {
- $submodulesType = 'submodule';
- } else {
- /** @todo Remove this case once support for older MediaWiki is dropped */
- $submodulesType = $this->moduleManager->getNames( 'submodule' );
- }
-
- return array(
- 'submodule' => array(
+ return [
+ 'submodule' => [
ApiBase::PARAM_REQUIRED => true,
- ApiBase::PARAM_TYPE => $submodulesType,
- ),
- 'page' => array(
+ ApiBase::PARAM_TYPE => 'submodule',
+ ],
+ 'page' => [
ApiBase::PARAM_REQUIRED => true,
// supply bogus default - not every action may *need* ?page=
ApiBase::PARAM_DFLT => Title::newFromText( 'Flow-enabled page', NS_TOPIC )->getPrefixedDBkey(),
- ),
+ ],
'token' => '',
- );
+ ];
}
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Allows actions to be taken on Flow pages.';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'submodule' => 'The Flow submodule to invoke',
- 'page' => 'The page to take the action on',
- 'token' => 'An edit token',
- );
- }
-
- /**
- * Override the parent to generate help messages for all available query modules.
- * @return string
- */
- public function makeHelpMsg() {
-
- // Use parent to make default message for the query module
- $msg = parent::makeHelpMsg();
-
- $querySeparator = str_repeat( '--- ', 12 );
- $moduleSeparator = str_repeat( '*** ', 14 );
- $msg .= "\n$querySeparator Flow: Submodules $querySeparator\n\n";
- $msg .= $this->makeHelpMsgHelper( 'submodule' );
- $msg .= "\n\n$moduleSeparator Modules: continuation $moduleSeparator\n\n";
-
- return $msg;
- }
-
- /**
- * For all modules of a given group, generate help messages and join them together
- * @param string $group Module group
- * @return string
- */
- private function makeHelpMsgHelper( $group ) {
- $moduleDescriptions = array();
-
- $moduleNames = $this->moduleManager->getNames( $group );
- sort( $moduleNames );
- foreach ( $moduleNames as $name ) {
- /**
- * @var $module ApiFlowBase
- */
- $module = $this->moduleManager->getModule( $name );
-
- $msg = ApiMain::makeHelpMsgHeader( $module, $group );
- $msg2 = $module->makeHelpMsg();
- if ( $msg2 !== false ) {
- $msg .= $msg2;
- }
- $moduleDescriptions[] = $msg;
- }
-
- return implode( "\n", $moduleDescriptions );
+ public function isWriteMode() {
+ // We can't use extractRequestParams() here because getHelpFlags() calls this function,
+ // and we'd error out because the submodule parameter isn't set.
+ $moduleName = $this->getMain()->getVal( 'submodule' );
+ $module = $this->moduleManager->getModule( $moduleName, 'submodule' );
+ return $module ? $module->isWriteMode() : false;
}
public function getHelpUrls() {
- return array(
+ return [
'https://www.mediawiki.org/wiki/Extension:Flow/API',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=edit-header&page=Talk:Sandbox&ehprev_revision=???&ehcontent=Nice%20to&20meet%20you',
- );
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=edit-header&page=Talk:Sandbox&ehprev_revision=???&ehcontent=Nice%20to&20meet%20you'
=> 'apihelp-flow-example-1',
- );
+ ];
}
public function mustBePosted() {
@@ -250,8 +182,4 @@ class ApiFlow extends ApiBase {
public function needsToken() {
return false;
}
-
- public function getTokenSalt() {
- return false;
- }
}
diff --git a/Flow/includes/Api/ApiFlowBase.php b/Flow/includes/Api/ApiFlowBase.php
index 61435d73..a7c22cb7 100644
--- a/Flow/includes/Api/ApiFlowBase.php
+++ b/Flow/includes/Api/ApiFlowBase.php
@@ -3,23 +3,30 @@
namespace Flow\Api;
use ApiBase;
+use ApiMessage;
use Flow\Block\Block;
use Flow\Container;
use Flow\Model\AbstractRevision;
-use Flow\TalkpageManager;
use Flow\WorkflowLoader;
use Flow\WorkflowLoaderFactory;
+use Status;
use Title;
abstract class ApiFlowBase extends ApiBase {
- /** @var WorkflowLoader $loader */
+ /**
+ * @var WorkflowLoader
+ */
protected $loader;
- /** @var Title $page */
+ /**
+ * @var Title
+ */
protected $page;
- /** @var ApiFlow $apiFlow */
+ /**
+ * @var ApiFlow
+ */
protected $apiFlow;
/**
@@ -55,7 +62,7 @@ abstract class ApiFlowBase extends ApiBase {
$this->page = $page;
}
- /*
+ /**
* Return the name of the flow action
* @return string
*/
@@ -66,7 +73,7 @@ abstract class ApiFlowBase extends ApiBase {
*/
protected function getLoader() {
if ( $this->loader === null ) {
- /** @var WorkflowLoaderFactory $factory */
+ /** @var WorkflowLoaderFactory $factory */
$factory = Container::get( 'factory.loader.workflow' );
$this->loader = $factory->createWorkflowLoader( $this->page );
}
@@ -79,18 +86,18 @@ abstract class ApiFlowBase extends ApiBase {
* @return string[]
*/
protected function getModerationStates( $addAliases = true ) {
- $states = array(
+ $states = [
AbstractRevision::MODERATED_NONE,
AbstractRevision::MODERATED_DELETED,
AbstractRevision::MODERATED_HIDDEN,
AbstractRevision::MODERATED_SUPPRESSED,
- );
+ ];
if ( $addAliases ) {
// aliases for AbstractRevision::MODERATED_NONE
- $states = array_merge( $states, array(
+ $states = array_merge( $states, [
'restore', 'unhide', 'undelete', 'unsuppress',
- ) );
+ ] );
}
return $states;
@@ -98,34 +105,23 @@ abstract class ApiFlowBase extends ApiBase {
/**
* Kill the request if errors were encountered.
- * Only the first error will be output:
- * * dieUsage only outputs one error - we could add more as $extraData, but
- * that would mean we'd have to check for flow-specific errors differently
- * * most of our code just quits on the first error that's encountered, so
- * outputting all encountered errors might still not cover everything
- * that's wrong with the request
*
* @param Block[] $blocks
*/
protected function processError( $blocks ) {
- foreach( $blocks as $block ) {
+ $status = Status::newGood();
+ foreach ( $blocks as $block ) {
if ( $block->hasErrors() ) {
- $errors = $block->getErrors();
-
- foreach( $errors as $key ) {
- $this->dieUsage(
- $block->getErrorMessage( $key )->parse(),
- $key,
- 200,
- // additional info for this message (e.g. to be used to
- // enable recovery from error, like returning the most
- // recent revision ID to re-submit content in the case
- // of edit conflict)
- array( $key => $block->getErrorExtra( $key ) )
- );
+ foreach ( $block->getErrors() as $key ) {
+ $status->fatal( ApiMessage::create(
+ $block->getErrorMessage( $key ), $key, [ $key => $block->getErrorExtra( $key ) ]
+ ) );
}
}
}
+ if ( !$status->isGood() ) {
+ $this->dieStatus( $status );
+ }
}
/**
@@ -146,9 +142,9 @@ abstract class ApiFlowBase extends ApiBase {
* {@inheritDoc}
*/
public function getHelpUrls() {
- return array(
+ return [
'https://www.mediawiki.org/wiki/Extension:Flow/API#' . $this->getAction(),
- );
+ ];
}
/**
@@ -161,13 +157,6 @@ abstract class ApiFlowBase extends ApiBase {
/**
* {@inheritDoc}
*/
- public function getTokenSalt() {
- return '';
- }
-
- /**
- * {@inheritDoc}
- */
public function getParent() {
return $this->apiFlow;
}
diff --git a/Flow/includes/Api/ApiFlowBaseGet.php b/Flow/includes/Api/ApiFlowBaseGet.php
index 8b7651dc..e87b3a17 100644
--- a/Flow/includes/Api/ApiFlowBaseGet.php
+++ b/Flow/includes/Api/ApiFlowBaseGet.php
@@ -15,17 +15,17 @@ abstract class ApiFlowBaseGet extends ApiFlowBase {
$action = $this->getAction();
$passedParams = $this->getBlockParams();
- $output = array( $action => array(
- 'result' => array(),
+ $output = [ $action => [
+ 'result' => [],
'status' => 'ok',
- ) );
+ ] ];
/** @var Block $block */
- foreach( $blocks as $block ) {
+ foreach ( $blocks as $block ) {
$block->init( $context, $action );
if ( $block->canRender( $action ) ) {
- $blockParams = array();
+ $blockParams = [];
if ( isset( $passedParams[$block->getName()] ) ) {
$blockParams = $passedParams[$block->getName()];
}
@@ -41,19 +41,14 @@ abstract class ApiFlowBaseGet extends ApiFlowBase {
// If nothing could render, we'll consider that an error (at least some
// block should've been able to render a GET request)
if ( !$output[$action]['result'] ) {
- $this->dieUsage(
- wfMessage( 'flow-error-no-render' )->parse(),
- 'no-render',
- 200,
- array()
- );
+ $this->dieWithError( 'flow-error-no-render', 'no-render' );
}
- $blocks = array_keys($output[$action]['result']);
+ $blocks = array_keys( $output[$action]['result'] );
$this->getResult()->setIndexedTagName( $blocks, 'block' );
// Required until php5.4 which has the JsonSerializable interface
- array_walk_recursive( $output, function( &$value ) {
+ array_walk_recursive( $output, function ( &$value ) {
if ( $value instanceof Anchor ) {
$value = $value->toArray();
} elseif ( $value instanceof Message ) {
@@ -79,11 +74,4 @@ abstract class ApiFlowBaseGet extends ApiFlowBase {
public function needsToken() {
return false;
}
-
- /**
- * {@inheritDoc}
- */
- public function getTokenSalt() {
- return false;
- }
}
diff --git a/Flow/includes/Api/ApiFlowBasePost.php b/Flow/includes/Api/ApiFlowBasePost.php
index 1c796ad7..3d9ffb77 100644
--- a/Flow/includes/Api/ApiFlowBasePost.php
+++ b/Flow/includes/Api/ApiFlowBasePost.php
@@ -2,7 +2,6 @@
namespace Flow\Api;
-use ApiBase;
use Flow\Model\Anchor;
use Flow\Model\UUID;
use Message;
@@ -30,30 +29,25 @@ abstract class ApiFlowBasePost extends ApiFlowBase {
// If nothing is ready to be committed, we'll consider that an error (at least some
// block should've been able to process the POST request)
if ( !count( $blocksToCommit ) ) {
- $this->dieUsage(
- wfMessage( 'flow-error-no-commit' )->parse(),
- 'no-commit',
- 200,
- array()
- );
+ $this->dieWithError( 'flow-error-no-commit', 'no-commit' );
}
$commitMetadata = $loader->commit( $blocksToCommit );
- $savedBlocks = array();
+ $savedBlocks = [];
$result->setIndexedTagName( $savedBlocks, 'block' );
- foreach( $blocksToCommit as $block ) {
+ foreach ( $blocksToCommit as $block ) {
$savedBlocks[] = $block->getName();
}
- $output = array( $action => array(
+ $output = [ $action => [
'status' => 'ok',
'workflow' => $workflow->isNew() ? '' : $workflow->getId()->getAlphadecimal(),
'committed' => $commitMetadata,
- ) );
+ ] ];
// required until php5.4 which has the JsonSerializable interface
- array_walk_recursive( $output, function( &$value ) {
+ array_walk_recursive( $output, function ( &$value ) {
if ( $value instanceof Anchor ) {
$value = $value->toArray();
} elseif ( $value instanceof Message ) {
@@ -86,11 +80,4 @@ abstract class ApiFlowBasePost extends ApiFlowBase {
public function needsToken() {
return 'csrf';
}
-
- /**
- * {@inheritDoc}
- */
- public function getTokenSalt() {
- return '';
- }
}
diff --git a/Flow/includes/Api/ApiFlowEditHeader.php b/Flow/includes/Api/ApiFlowEditHeader.php
index 36db50c2..083b89f9 100644
--- a/Flow/includes/Api/ApiFlowEditHeader.php
+++ b/Flow/includes/Api/ApiFlowEditHeader.php
@@ -15,7 +15,7 @@ class ApiFlowEditHeader extends ApiFlowBasePost {
* @return array
*/
protected function getBlockParams() {
- return array( 'header' => $this->extractRequestParams() );
+ return [ 'header' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -23,54 +23,27 @@ class ApiFlowEditHeader extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'prev_revision' => array(
- ),
- 'content' => array(
+ return [
+ 'prev_revision' => [
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
+ ],
+ 'format' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 'wikitext',
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'prev_revision' => 'Revision id of the current header revision to check for edit conflicts',
- 'content' => 'Content for header',
- 'format' => 'Format of the content (wikitext|html)',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Edits a topic\'s header';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=edit-header&page=Talk:Sandbox&ehprev_revision=???&ehcontent=Nice%20to&20meet%20you&ehformat=wikitext',
- );
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=edit-header&page=Talk:Sandbox&ehprev_revision=???&ehcontent=Nice%20to&20meet%20you&ehformat=wikitext'
=> 'apihelp-flow+edit-header-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowEditPost.php b/Flow/includes/Api/ApiFlowEditPost.php
index ff8982ff..4a8278ee 100644
--- a/Flow/includes/Api/ApiFlowEditPost.php
+++ b/Flow/includes/Api/ApiFlowEditPost.php
@@ -15,63 +15,35 @@ class ApiFlowEditPost extends ApiFlowBasePost {
}
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
public function getAllowedParams() {
- return array(
- 'postId' => array(
+ return [
+ 'postId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'prev_revision' => array(
+ ],
+ 'prev_revision' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'content' => array(
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
+ ],
+ 'format' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 'wikitext',
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'postId' => 'Post ID',
- 'prev_revision' => 'Revision id of the current post revision to check for edit conflicts',
- 'content' => 'Content for post',
- 'format' => 'Format of the content (wikitext|html)',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Edits a post\'s content';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=edit-post&page=Topic:S2tycnas4hcucw8w&eppostId=???&epprev_revision=???&epcontent=Nice%20to&20meet%20you&epformat=wikitext',
- );
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=edit-post&page=Topic:S2tycnas4hcucw8w&eppostId=???&epprev_revision=???&epcontent=Nice%20to&20meet%20you&epformat=wikitext'
=> 'apihelp-flow+edit-post-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowEditTitle.php b/Flow/includes/Api/ApiFlowEditTitle.php
index 0c1c3527..dcc6db65 100644
--- a/Flow/includes/Api/ApiFlowEditTitle.php
+++ b/Flow/includes/Api/ApiFlowEditTitle.php
@@ -15,7 +15,7 @@ class ApiFlowEditTitle extends ApiFlowBasePost {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -23,49 +23,23 @@ class ApiFlowEditTitle extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'prev_revision' => array(
+ return [
+ 'prev_revision' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'content' => array(
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'prev_revision' => 'Revision id of the current title revision to check for edit conflicts',
- 'content' => 'Content for title',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Edits a topic\'s title';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=edit-title&page=Topic:S2tycnas4hcucw8w&etprev_revision=???&etcontent=Nice%20to&20meet%20you',
- );
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=edit-title&page=Topic:S2tycnas4hcucw8w&etprev_revision=???&ehtcontent=Nice%20to&20meet%20you'
=> 'apihelp-flow+edit-title-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowEditTopicSummary.php b/Flow/includes/Api/ApiFlowEditTopicSummary.php
index ca8d6a67..b214cf8c 100644
--- a/Flow/includes/Api/ApiFlowEditTopicSummary.php
+++ b/Flow/includes/Api/ApiFlowEditTopicSummary.php
@@ -15,60 +15,33 @@ class ApiFlowEditTopicSummary extends ApiFlowBasePost {
}
protected function getBlockParams() {
- return array(
+ return [
'topicsummary' => $this->extractRequestParams(),
- 'topic' => array(),
- );
+ 'topic' => [],
+ ];
}
public function getAllowedParams() {
- return array(
+ return [
'prev_revision' => null,
- 'summary' => array(
+ 'summary' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
+ ],
+ 'format' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 'wikitext',
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'prev_revision' => 'Revision id of the current topic summary revision to check for edit conflicts. Null for a new topic summary revision',
- 'summary' => 'Content for the summary',
- 'format' => 'Format of the summary (wikitext|html)',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Edits a topic summary\'s content';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=edit-topic-summary&page=Topic:S2tycnas4hcucw8w&wetsprev_revision=???&etssummary=Nice%20to&20meet%20you&etsformat=wikitext',
- );
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=edit-topic-summary&page=Topic:S2tycnas4hcucw8w&wetsprev_revision=???&etssummary=Nice%20to&20meet%20you&etsformat=wikitext'
=> 'apihelp-flow+edit-topic-summary-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowLockTopic.php b/Flow/includes/Api/ApiFlowLockTopic.php
index fa1b73c4..b6ce825e 100644
--- a/Flow/includes/Api/ApiFlowLockTopic.php
+++ b/Flow/includes/Api/ApiFlowLockTopic.php
@@ -13,9 +13,9 @@ class ApiFlowLockTopic extends ApiFlowBasePost {
protected function getBlockParams() {
$params = $this->extractRequestParams();
- return array(
+ return [
'topic' => $params,
- );
+ ];
}
protected function getAction() {
@@ -27,54 +27,28 @@ class ApiFlowLockTopic extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'moderationState' => array(
+ return [
+ 'moderationState' => [
ApiBase::PARAM_REQUIRED => true,
- ApiBase::PARAM_TYPE => array(
+ ApiBase::PARAM_TYPE => [
AbstractRevision::MODERATED_LOCKED, 'unlock',
'close', 'reopen' // BC: now replaced by lock & unlock
- ),
- ),
- 'reason' => array(
+ ],
+ ],
+ 'reason' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_TYPE => 'string',
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'moderationState' => "State to put topic in, either locked or unlocked",
- 'reason' => 'Reason for locking or unlocking the topic',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Lock or unlock a Flow topic';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=lock-topic&page=Topic:S2tycnas4hcucw8w&cotmoderationState=lock&cotreason=Ahhhh',
- );
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=lock-topic&page=Topic:S2tycnas4hcucw8w&cotmoderationState=lock&cotreason=Ahhhh'
=> 'apihelp-flow+lock-topic-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowModeratePost.php b/Flow/includes/Api/ApiFlowModeratePost.php
index 89e9acf2..1c492762 100644
--- a/Flow/includes/Api/ApiFlowModeratePost.php
+++ b/Flow/includes/Api/ApiFlowModeratePost.php
@@ -11,7 +11,7 @@ class ApiFlowModeratePost extends ApiFlowBasePost {
}
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -19,54 +19,27 @@ class ApiFlowModeratePost extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'moderationState' => array(
+ return [
+ 'moderationState' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_TYPE => $this->getModerationStates(),
- ),
- 'reason' => array(
+ ],
+ 'reason' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'postId' => array(
+ ],
+ 'postId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'moderationState' => 'What level to moderate at',
- 'reason' => 'Reason for moderation',
- 'postId' => 'Id of post to moderate',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Moderates a Flow post';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=moderate-post&page=Topic:S2tycnas4hcucw8w&mppostId=050f30e34c87beebcd54080027630f57&mpmoderationState=delete&mpreason=Ahhhh',
- );
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=moderate-post&page=Topic:S2tycnas4hcucw8w&mppostId=050f30e34c87beebcd54080027630f57&mpmoderationState=delete&mpreason=Ahhhh'
=> 'apihelp-flow+moderate-post-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowModerateTopic.php b/Flow/includes/Api/ApiFlowModerateTopic.php
index a2c58365..013fcea6 100644
--- a/Flow/includes/Api/ApiFlowModerateTopic.php
+++ b/Flow/includes/Api/ApiFlowModerateTopic.php
@@ -11,7 +11,7 @@ class ApiFlowModerateTopic extends ApiFlowBasePost {
}
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -19,50 +19,24 @@ class ApiFlowModerateTopic extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'moderationState' => array(
+ return [
+ 'moderationState' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_TYPE => $this->getModerationStates(),
- ),
- 'reason' => array(
+ ],
+ 'reason' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'moderationState' => 'What level to moderate at',
- 'reason' => 'Reason for moderation',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Moderates a Flow topic';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=moderate-topic&page=Topic:S2tycnas4hcucw8w&mtmoderationState=delete&mtreason=Ahhhh',
- );
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=moderate-topic&page=Topic:S2tycnas4hcucw8w&mtmoderationState=delete&mtreason=Ahhhh'
=> 'apihelp-flow+moderate-topic-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowNewTopic.php b/Flow/includes/Api/ApiFlowNewTopic.php
index 25bb2b50..a7e67d69 100644
--- a/Flow/includes/Api/ApiFlowNewTopic.php
+++ b/Flow/includes/Api/ApiFlowNewTopic.php
@@ -15,7 +15,7 @@ class ApiFlowNewTopic extends ApiFlowBasePost {
* @return array
*/
protected function getBlockParams() {
- return array( 'topiclist' => $this->extractRequestParams() );
+ return [ 'topiclist' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -23,55 +23,28 @@ class ApiFlowNewTopic extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'topic' => array(
+ return [
+ 'topic' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'content' => array(
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
+ ],
+ 'format' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 'wikitext',
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'topic' => 'Text for new topic title',
- 'content' => 'Content for the topic\'s initial reply',
- 'format' => 'Format of the content (wikitext|html)',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Creates a new Flow topic on the given page, or workflow';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=new-topic&page=Talk:Sandbox&nttopic=Hi&ntcontent=Nice%20to&20meet%20you&ntformat=wikitext',
- );
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=new-topic&page=Talk:Sandbox&nttopic=Hi&ntcontent=Nice%20to&20meet%20you&ntformat=wikitext'
=> 'apihelp-flow+new-topic-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowReply.php b/Flow/includes/Api/ApiFlowReply.php
index 3e8c8927..193cee3f 100644
--- a/Flow/includes/Api/ApiFlowReply.php
+++ b/Flow/includes/Api/ApiFlowReply.php
@@ -14,7 +14,7 @@ class ApiFlowReply extends ApiFlowBasePost {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -22,55 +22,28 @@ class ApiFlowReply extends ApiFlowBasePost {
}
public function getAllowedParams() {
- return array(
- 'replyTo' => array(
+ return [
+ 'replyTo' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'content' => array(
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
+ ],
+ 'format' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_DFLT => 'wikitext',
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- ) + parent::getAllowedParams();
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'replyTo' => 'Post ID to reply to',
- 'content' => 'Content for new post',
- 'format' => 'Format of the content (wikitext|html)',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Replies to a post';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=reply&page=Topic:S2tycnas4hcucw8w&repreplyTo=050e554490c2b269143b080027630f57&repcontent=Nice%20to&20meet%20you&repformat=wikitext',
- );
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=reply&page=Topic:S2tycnas4hcucw8w&repreplyTo=050e554490c2b269143b080027630f57&repcontent=Nice%20to&20meet%20you&repformat=wikitext'
=> 'apihelp-flow+reply-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowSearch.php b/Flow/includes/Api/ApiFlowSearch.php
index 87f91709..d77eaff9 100644
--- a/Flow/includes/Api/ApiFlowSearch.php
+++ b/Flow/includes/Api/ApiFlowSearch.php
@@ -11,7 +11,6 @@ use Flow\Model\UUID;
use Flow\Search\Connection;
use Flow\Search\SearchEngine;
use Flow\Search\Searcher;
-use Flow\TalkpageManager;
use MWNamespace;
use Status;
@@ -55,17 +54,19 @@ class ApiFlowSearch extends ApiFlowBaseGet {
/** @var Status $status */
$status = $this->searchEngine->searchText( $params['term'] );
- if ( !$status->isGood() ) {
+ if ( !$status->isOK() ) {
throw new InvalidDataException( $status->getMessage(), 'fail-search' );
}
+ $this->getMain()->getErrorFormatter()->addMessagesFromStatus(
+ $this->getModuleName(), $status );
/** @var \Elastica\ResultSet|null $resultSet */
$resultSet = $status->getValue();
// $resultSet can be null, if nothing was found
- $results = $resultSet === null ? array() : $resultSet->getResults();
+ $results = $resultSet === null ? [] : $resultSet->getResults();
// list of highlighted words
- $highlights = array();
+ $highlights = [];
/** @var \Elastica\Result $result */
foreach ( $results as $result ) {
// there'll always be exactly 1 excerpt
@@ -85,7 +86,7 @@ class ApiFlowSearch extends ApiFlowBaseGet {
$ttf = $resultSet->getAggregation( 'ttf' );
$ttf = $ttf['value'];
- $topicIds = array();
+ $topicIds = [];
foreach ( $results as $topic ) {
$topicIds[] = UUID::create( $topic->getId() );
}
@@ -125,18 +126,18 @@ class ApiFlowSearch extends ApiFlowBaseGet {
* @return int[]
*/
protected function getPageIds( $params ) {
- $pageIds = array();
+ $pageIds = [];
// page is optional - if not provided, all pages will be searched
if ( $params['title'] || $params['pageid'] ) {
$page = $this->getTitleOrPageId( $params );
// validate the page that was passed in
if ( !$page->exists() ) {
- $this->dieUsage( 'Invalid page provided', 'invalid-page' );
+ $this->dieWithError( 'apierror-missingtitle', 'invalid-page' );
}
if ( $page->getTitle()->getContentModel() !== CONTENT_MODEL_FLOW_BOARD ) {
- $this->dieUsage( 'Page provided does not have Flow enabled', 'invalid-page' );
+ $this->dieWithError( 'apierror-flow-notenabled', 'invalid-page' );
}
$pageIds[] = $page->getId();
@@ -162,7 +163,7 @@ class ApiFlowSearch extends ApiFlowBaseGet {
protected function getModerationState( $params ) {
$moderationState = $params['moderationState'];
if ( $moderationState !== null && count( $moderationState ) === 0 ) {
- $moderationState = array( '' );
+ $moderationState = [ '' ];
}
return $moderationState;
@@ -173,49 +174,49 @@ class ApiFlowSearch extends ApiFlowBaseGet {
$sorts = $this->searchEngine->getValidSorts();
- return array(
- 'term' => array(
+ return [
+ 'term' => [
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_TYPE => 'string',
- ),
+ ],
'title' => null,
- 'pageid' => array(
+ 'pageid' => [
ApiBase::PARAM_ISMULTI => false,
ApiBase::PARAM_TYPE => 'integer'
- ),
- 'namespaces' => array(
+ ],
+ 'namespaces' => [
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_TYPE => MWNamespace::getValidNamespaces(),
- ),
- 'moderationState' => array(
+ ],
+ 'moderationState' => [
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_TYPE => $this->getModerationStates( false ),
- ),
- 'sort' => array(
+ ],
+ 'sort' => [
ApiBase::PARAM_TYPE => $sorts,
ApiBase::PARAM_DFLT => reset( $sorts ),
- ),
- 'type' => array(
+ ],
+ 'type' => [
// false is allowed (means we'll search *all* types)
- ApiBase::PARAM_TYPE => array_merge( Connection::getAllTypes(), array( false ) ),
+ ApiBase::PARAM_TYPE => array_merge( Connection::getAllTypes(), [ false ] ),
ApiBase::PARAM_DFLT => false,
- ),
- 'offset' => array(
+ ],
+ 'offset' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_DFLT => 0,
- ),
- 'limit' => array(
+ ],
+ 'limit' => [
ApiBase::PARAM_TYPE => 'limit',
ApiBase::PARAM_DFLT => $wgFlowDefaultLimit,
ApiBase::PARAM_MAX => $wgFlowDefaultLimit,
ApiBase::PARAM_MAX2 => $wgFlowDefaultLimit,
- ),
- );
+ ],
+ ];
}
public function getParamDescription() {
$p = $this->getModulePrefix();
- return array(
+ return [
'term' => 'Search term',
'title' => "Title of the boards to search in. Cannot be used together with {$p}pageid",
'pageid' => "ID of the boards to search in. Cannot be used together with {$p}title",
@@ -225,7 +226,7 @@ class ApiFlowSearch extends ApiFlowBaseGet {
'type' => 'Desired type of results (' . implode( '|', Connection::getAllTypes() ) . ')',
'offset' => 'Offset value to start fetching results at',
'limit' => 'Amount of results to fetch',
- );
+ ];
}
public function getDescription() {
@@ -233,9 +234,9 @@ class ApiFlowSearch extends ApiFlowBaseGet {
}
public function getExamples() {
- return array(
+ return [
'api.php?action=flow&submodule=search&qterm=keyword&qtitle=Main_Page',
- );
+ ];
}
public function needsPage() {
@@ -245,7 +246,7 @@ class ApiFlowSearch extends ApiFlowBaseGet {
protected function getBlockParams() {
// irrelevant for search API
- return array();
+ return [];
}
protected function getAction() {
diff --git a/Flow/includes/Api/ApiFlowUndoEditHeader.php b/Flow/includes/Api/ApiFlowUndoEditHeader.php
index df08bee5..700c41c6 100644
--- a/Flow/includes/Api/ApiFlowUndoEditHeader.php
+++ b/Flow/includes/Api/ApiFlowUndoEditHeader.php
@@ -14,7 +14,7 @@ class ApiFlowUndoEditHeader extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'header' => $this->extractRequestParams() );
+ return [ 'header' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -22,23 +22,23 @@ class ApiFlowUndoEditHeader extends ApiFlowBaseGet {
}
public function getAllowedParams() {
- return array(
- 'startId' => array(
+ return [
+ 'startId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'endId' => array(
+ ],
+ 'endId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=undo-edit-header&page=Talk:Sandbox&uehstartId=???&uehendId=???'
=> 'apihelp-flow+undo-edit-header-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowUndoEditPost.php b/Flow/includes/Api/ApiFlowUndoEditPost.php
index 1ea434fa..62a71e22 100644
--- a/Flow/includes/Api/ApiFlowUndoEditPost.php
+++ b/Flow/includes/Api/ApiFlowUndoEditPost.php
@@ -14,27 +14,27 @@ class ApiFlowUndoEditPost extends ApiFlowBaseGet {
}
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
public function getAllowedParams() {
- return array(
- 'startId' => array(
+ return [
+ 'startId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'endId' => array(
+ ],
+ 'endId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=undo-edit-post&page=Topic:S2tycnas4hcucw8w&uaepostId=???&uaestartId=???&uaeendId=???'
=> 'apihelp-flow+undo-edit-post-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowUndoEditTopicSummary.php b/Flow/includes/Api/ApiFlowUndoEditTopicSummary.php
index ef6038a3..3ebbd470 100644
--- a/Flow/includes/Api/ApiFlowUndoEditTopicSummary.php
+++ b/Flow/includes/Api/ApiFlowUndoEditTopicSummary.php
@@ -14,30 +14,30 @@ class ApiFlowUndoEditTopicSummary extends ApiFlowBaseGet {
}
protected function getBlockParams() {
- return array(
+ return [
'topicsummary' => $this->extractRequestParams(),
- 'topic' => array(),
- );
+ 'topic' => [],
+ ];
}
public function getAllowedParams() {
- return array(
- 'startId' => array(
+ return [
+ 'startId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'endId' => array(
+ ],
+ 'endId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- ) + parent::getAllowedParams();
+ ],
+ ] + parent::getAllowedParams();
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=undo-edit-topic-summary&page=Topic:S2tycnas4hcucw8w&uetsstartId=???&uetsendId=???'
=> 'apihelp-flow+undo-edit-topic-summary-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewHeader.php b/Flow/includes/Api/ApiFlowViewHeader.php
index 4a2eed86..c4124338 100644
--- a/Flow/includes/Api/ApiFlowViewHeader.php
+++ b/Flow/includes/Api/ApiFlowViewHeader.php
@@ -14,7 +14,7 @@ class ApiFlowViewHeader extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'header' => $this->extractRequestParams() );
+ return [ 'header' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -24,49 +24,23 @@ class ApiFlowViewHeader extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ return [
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
+ ],
'revId' => null,
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'format' => 'Format to return the content in',
- 'revId' => 'load a specific revision if provided, otherwise, load the most recent',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'View a board header';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=view-header&page=Talk:Sandbox&vhformat=wikitext&revId=',
- );
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-header&page=Talk:Sandbox&vhformat=wikitext&revId='
=> 'apihelp-flow+view-header-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewPost.php b/Flow/includes/Api/ApiFlowViewPost.php
index ab0caae6..d6121867 100644
--- a/Flow/includes/Api/ApiFlowViewPost.php
+++ b/Flow/includes/Api/ApiFlowViewPost.php
@@ -15,7 +15,7 @@ class ApiFlowViewPost extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -25,51 +25,25 @@ class ApiFlowViewPost extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'postId' => array(
+ return [
+ 'postId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ ],
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'postId' => 'Id of the post to view',
- 'format' => 'Format to return the content in',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'View a post';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=view-post&page=Topic:S2tycnas4hcucw8w&vppostId=???&vpformat=wikitext',
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-post&page=Topic:S2tycnas4hcucw8w&vppostId=???&vpformat=wikitext'
=> 'apihelp-flow+view-post-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewPostHistory.php b/Flow/includes/Api/ApiFlowViewPostHistory.php
index a0fb735f..2b9dcdcc 100644
--- a/Flow/includes/Api/ApiFlowViewPostHistory.php
+++ b/Flow/includes/Api/ApiFlowViewPostHistory.php
@@ -13,7 +13,7 @@ class ApiFlowViewPostHistory extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -23,25 +23,25 @@ class ApiFlowViewPostHistory extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'postId' => array(
+ return [
+ 'postId' => [
ApiBase::PARAM_REQUIRED => true,
- ),
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ ],
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-post-history&page=Topic:S2tycnas4hcucw8w&vphpostId=???&vphformat=wikitext'
=> 'apihelp-flow+view-post-history-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewTopic.php b/Flow/includes/Api/ApiFlowViewTopic.php
index f8d919bf..9fd4d45d 100644
--- a/Flow/includes/Api/ApiFlowViewTopic.php
+++ b/Flow/includes/Api/ApiFlowViewTopic.php
@@ -15,7 +15,7 @@ class ApiFlowViewTopic extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -25,38 +25,22 @@ class ApiFlowViewTopic extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ return [
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'View a topic';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=view-topic&page=Topic:S2tycnas4hcucw8w&vtformat=wikitext',
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-topic&page=Topic:S2tycnas4hcucw8w'
=> 'apihelp-flow+view-topic-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewTopicHistory.php b/Flow/includes/Api/ApiFlowViewTopicHistory.php
index e5364c6a..a854a151 100644
--- a/Flow/includes/Api/ApiFlowViewTopicHistory.php
+++ b/Flow/includes/Api/ApiFlowViewTopicHistory.php
@@ -13,7 +13,7 @@ class ApiFlowViewTopicHistory extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topic' => $this->extractRequestParams() );
+ return [ 'topic' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -23,22 +23,22 @@ class ApiFlowViewTopicHistory extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ return [
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-topic-history&page=Topic:S2tycnas4hcucw8w&vthformat=wikitext'
=> 'apihelp-flow+view-topic-history-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewTopicList.php b/Flow/includes/Api/ApiFlowViewTopicList.php
index 279a54bc..2abf2fac 100644
--- a/Flow/includes/Api/ApiFlowViewTopicList.php
+++ b/Flow/includes/Api/ApiFlowViewTopicList.php
@@ -15,7 +15,7 @@ class ApiFlowViewTopicList extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topiclist' => $this->extractRequestParams() );
+ return [ 'topiclist' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -25,88 +25,56 @@ class ApiFlowViewTopicList extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowDefaultLimit, $wgFlowMaxLimit, $wgFlowContentFormat;
- return array(
- 'offset-dir' => array(
- ApiBase::PARAM_TYPE => array( 'fwd', 'rev' ),
+ return [
+ 'offset-dir' => [
+ ApiBase::PARAM_TYPE => [ 'fwd', 'rev' ],
ApiBase::PARAM_DFLT => 'fwd',
- ),
- 'sortby' => array(
- ApiBase::PARAM_TYPE => array( 'newest', 'updated', 'user' ),
+ ],
+ 'sortby' => [
+ ApiBase::PARAM_TYPE => [ 'newest', 'updated', 'user' ],
ApiBase::PARAM_DFLT => 'user',
- ),
- 'savesortby' => array(
+ ],
+ 'savesortby' => [
ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false,
- ),
- 'offset-id' => array(
+ ],
+ 'offset-id' => [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => false,
- ),
- 'offset' => array(
+ ],
+ 'offset' => [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => false,
- ),
- 'include-offset' => array(
+ ],
+ 'include-offset' => [
ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false,
- ),
- 'limit' => array(
+ ],
+ 'limit' => [
ApiBase::PARAM_TYPE => 'limit',
ApiBase::PARAM_DFLT => $wgFlowDefaultLimit,
ApiBase::PARAM_MAX => $wgFlowMaxLimit,
ApiBase::PARAM_MAX2 => $wgFlowMaxLimit,
- ),
- 'toconly' => array(
+ ],
+ 'toconly' => [
ApiBase::PARAM_TYPE => 'boolean',
ApiBase::PARAM_DFLT => false,
- ),
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ ],
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'offset-dir' => 'Direction to get topics for',
- 'sortby' => 'Sorting option of the topics',
- 'savesortby' => 'Save sortby option, if set',
- 'offset-id' => 'Offset value (in UUID format) to start fetching topics at',
- 'offset' => 'Offset value to start fetching topics at',
- 'include-offset' => 'Includes the offset item in the results as well',
- 'limit' => 'Number of topics to fetch',
- 'toconly' => 'Whether to respond with only the information required for the TOC',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'View a list of topics';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=view-topiclist&page=Talk:Sandbox',
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-topiclist&page=Talk:Sandbox'
=> 'apihelp-flow+view-topiclist-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiFlowViewTopicSummary.php b/Flow/includes/Api/ApiFlowViewTopicSummary.php
index 5d8c4fbd..68d90a9f 100644
--- a/Flow/includes/Api/ApiFlowViewTopicSummary.php
+++ b/Flow/includes/Api/ApiFlowViewTopicSummary.php
@@ -14,7 +14,7 @@ class ApiFlowViewTopicSummary extends ApiFlowBaseGet {
* @return array
*/
protected function getBlockParams() {
- return array( 'topicsummary' => $this->extractRequestParams() );
+ return [ 'topicsummary' => $this->extractRequestParams() ];
}
protected function getAction() {
@@ -24,49 +24,23 @@ class ApiFlowViewTopicSummary extends ApiFlowBaseGet {
public function getAllowedParams() {
global $wgFlowContentFormat;
- return array(
- 'format' => array(
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext', 'fixed-html' ),
+ return [
+ 'format' => [
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'fixed-html' ],
// never default to unfixed html, only serve that when specifically asked!
ApiBase::PARAM_DFLT => $wgFlowContentFormat === 'html' ? 'fixed-html' : $wgFlowContentFormat,
- ),
+ ],
'revId' => null,
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- return array(
- 'format' => 'Format to return the content in',
- 'revId' => 'load a specific revision if provided, otherwise, load the most recent',
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'View a topic summary';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=flow&submodule=view-topic-summary&page=Topic:S2tycnas4hcucw8w&vtsformat=wikitext&revId=',
- );
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=flow&submodule=view-topic-summary&page=Topic:S2tycnas4hcucw8w&vtsformat=wikitext&revId='
=> 'apihelp-flow+view-topic-summary-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiParsoidUtilsFlow.php b/Flow/includes/Api/ApiParsoidUtilsFlow.php
index 66f5575a..1319d047 100644
--- a/Flow/includes/Api/ApiParsoidUtilsFlow.php
+++ b/Flow/includes/Api/ApiParsoidUtilsFlow.php
@@ -3,7 +3,7 @@
namespace Flow\Api;
use ApiBase;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Flow\Exception\WikitextException;
class ApiParsoidUtilsFlow extends ApiBase {
@@ -16,76 +16,47 @@ class ApiParsoidUtilsFlow extends ApiBase {
$content = Utils::convert( $params['from'], $params['to'], $params['content'], $page->getTitle() );
} catch ( WikitextException $e ) {
$code = $e->getErrorCode();
- $this->dieUsage( $this->msg( $code )->inContentLanguage()->useDatabase( false )->plain(), $code,
- $e->getStatusCode(), array( 'detail' => $e->getMessage() ) );
+ $this->dieWithError( $code, $code,
+ [ 'detail' => $e->getMessage() ], $e->getStatusCode()
+ );
return; // helps static analysis know execution does not continue past self::dieUsage
}
- $result = array(
+ $result = [
'format' => $params['to'],
'content' => $content,
- );
+ ];
$this->getResult()->addValue( null, $this->getModuleName(), $result );
}
public function getAllowedParams() {
- return array(
- 'from' => array(
+ return [
+ 'from' => [
ApiBase::PARAM_REQUIRED => true,
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- 'to' => array(
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ 'to' => [
ApiBase::PARAM_REQUIRED => true,
- ApiBase::PARAM_TYPE => array( 'html', 'wikitext' ),
- ),
- 'content' => array(
+ ApiBase::PARAM_TYPE => [ 'html', 'wikitext' ],
+ ],
+ 'content' => [
ApiBase::PARAM_REQUIRED => true,
- ),
+ ],
'title' => null,
- 'pageid' => array(
+ 'pageid' => [
ApiBase::PARAM_ISMULTI => false,
ApiBase::PARAM_TYPE => 'integer'
- ),
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getParamDescription() {
- $p = $this->getModulePrefix();
- return array(
- 'from' => 'Format of content tossed in',
- 'to' => 'Format to convert content to',
- 'content' => 'Content to be converted',
- 'title' => "Title of the page. Cannot be used together with {$p}pageid",
- 'pageid' => "ID of the page. Cannot be used together with {$p}title",
- );
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Convert text from/to wikitext/html';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- "api.php?action=flow-parsoid-utils&from=wikitext&to=html&content='''lorem'''+''blah''&title=Main_Page",
- );
+ ],
+ ];
}
/**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
"action=flow-parsoid-utils&from=wikitext&to=html&content='''lorem'''+''blah''&title=Main_Page"
=> 'apihelp-flow-parsoid-utils-example-1',
- );
+ ];
}
}
diff --git a/Flow/includes/Api/ApiQueryPropFlowInfo.php b/Flow/includes/Api/ApiQueryPropFlowInfo.php
index bff43ead..057ba54d 100644
--- a/Flow/includes/Api/ApiQueryPropFlowInfo.php
+++ b/Flow/includes/Api/ApiQueryPropFlowInfo.php
@@ -3,7 +3,6 @@
namespace Flow\Api;
use ApiQueryBase;
-use Flow\Container;
use Title;
class ApiQueryPropFlowInfo extends ApiQueryBase {
@@ -32,7 +31,7 @@ class ApiQueryPropFlowInfo extends ApiQueryBase {
* @return array
*/
protected function getPageInfo( Title $title ) {
- $result = array( 'flow' => array() );
+ $result = [ 'flow' => [] ];
if ( $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
$result['flow']['enabled'] = '';
}
@@ -41,29 +40,13 @@ class ApiQueryPropFlowInfo extends ApiQueryBase {
}
/**
- * @deprecated since MediaWiki core 1.25
- */
- public function getDescription() {
- return 'Get basic Flow information about a page including whether Flow is enabled on them';
- }
-
- /**
- * @deprecated since MediaWiki core 1.25
- */
- public function getExamples() {
- return array(
- 'api.php?action=query&prop=flowinfo&titles=Talk:Sandbox|Main_Page|Talk:Flow',
- );
- }
-
- /**
* @see ApiBase::getExamplesMessages()
*/
protected function getExamplesMessages() {
- return array(
+ return [
'action=query&prop=flowinfo&titles=Talk:Sandbox|Main_Page|Talk:Flow'
=> 'apihelp-query+flowinfo-example-1',
- );
+ ];
}
public function getHelpUrls() {
diff --git a/Flow/includes/Block/Block.php b/Flow/includes/Block/Block.php
index 121b0845..5fab0192 100644
--- a/Flow/includes/Block/Block.php
+++ b/Flow/includes/Block/Block.php
@@ -5,7 +5,6 @@ namespace Flow\Block;
use Flow\Container;
use Flow\Data\ManagerGroup;
use Flow\Exception\InvalidInputException;
-use Flow\Exception\PermissionException;
use Flow\FlowActions;
use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
@@ -25,7 +24,7 @@ interface Block {
* Perform validation of data model
*
* @param array $data
- * @return boolean True if data model is valid
+ * @return bool True if data model is valid
*/
function onSubmit( array $data );
@@ -94,7 +93,7 @@ abstract class AbstractBlock implements Block {
/** @var array|null */
protected $submitted = null;
/** @var array */
- protected $errors = array();
+ protected $errors = [];
/**
* @var string|null The commitable action being submitted, or null
@@ -109,19 +108,19 @@ abstract class AbstractBlock implements Block {
* A list of supported post actions
* @var array
*/
- protected $supportedPostActions = array();
+ protected $supportedPostActions = [];
/**
* A list of supported get actions
* @var array
*/
- protected $supportedGetActions = array();
+ protected $supportedGetActions = [];
/**
* Templates for each view actions
* @var array
*/
- protected $templates = array();
+ protected $templates = [];
public function __construct( Workflow $workflow, ManagerGroup $storage ) {
$this->workflow = $workflow;
@@ -134,14 +133,14 @@ abstract class AbstractBlock implements Block {
*/
abstract protected function validate();
- // This method exists in the Block interface and as such cannot be abstract
- // until php 5.3.9, but MediaWiki requires PHP version 5.3.2 or later (and
- // some of our test machines are on 5.3.3).
- //abstract public function commit();
+ /**
+ * {@inheritDoc}
+ */
+ abstract public function commit();
/**
- * @var IContextSource $context
- * @var string $action
+ * @param IContextSource $context
+ * @param string $action
*/
public function init( IContextSource $context, $action ) {
$this->context = $context;
@@ -231,7 +230,7 @@ abstract class AbstractBlock implements Block {
*/
public function hasErrors( $type = null ) {
if ( $type === null ) {
- return (bool) $this->errors;
+ return (bool)$this->errors;
}
return isset( $this->errors[$type] );
}
@@ -249,7 +248,7 @@ abstract class AbstractBlock implements Block {
}
/**
- * @param $type
+ * @param string $type
* @return \Message
*/
public function getErrorMessage( $type ) {
@@ -257,7 +256,7 @@ abstract class AbstractBlock implements Block {
}
/**
- * @param $type
+ * @param string $type
* @return mixed
*/
public function getErrorExtra( $type ) {
@@ -270,10 +269,10 @@ abstract class AbstractBlock implements Block {
* @param mixed[optional] $extra
*/
public function addError( $type, \Message $message, $extra = null ) {
- $this->errors[$type] = array(
+ $this->errors[$type] = [
'message' => $message,
'extra' => $extra,
- );
+ ];
}
public function getWorkflow() {
@@ -315,18 +314,24 @@ abstract class AbstractBlock implements Block {
*
* @param AbstractRevision|null $old null when $new is first revision
* @param AbstractRevision $new
- * @return boolean True when content is allowed by spam filter
+ * @return bool True when content is allowed by spam filter
*/
protected function checkSpamFilters( AbstractRevision $old = null, AbstractRevision $new ) {
/** @var SpamFilterController $spamFilter */
$spamFilter = Container::get( 'controller.spamfilter' );
- $status = $spamFilter->validate( $this->context, $new, $old, $this->workflow->getArticleTitle() );
+ $status = $spamFilter->validate( $this->context, $new, $old, $this->workflow->getArticleTitle(), $this->workflow->getOwnerTitle() );
if ( $status->isOK() ) {
return true;
}
$message = $status->getMessage();
- $this->addError( 'spamfilter', $message, $message->getKey() );
+
+ $details = $status->getValue();
+
+ $this->addError( 'spamfilter', $message, [
+ 'messageKey' => $message->getKey(),
+ 'details' => $details,
+ ] );
return false;
}
diff --git a/Flow/includes/Block/BoardHistory.php b/Flow/includes/Block/BoardHistory.php
index 6463225f..c12bb774 100644
--- a/Flow/includes/Block/BoardHistory.php
+++ b/Flow/includes/Block/BoardHistory.php
@@ -4,37 +4,17 @@ namespace Flow\Block;
use Flow\Container;
use Flow\Data\Pager\HistoryPager;
-use Flow\Data\ManagerGroup;
use Flow\Exception\DataModelException;
-use Flow\FlowActions;
use Flow\Formatter\BoardHistoryQuery;
use Flow\Formatter\RevisionFormatter;
-use Flow\Model\UUID;
-use Flow\Model\Workflow;
class BoardHistoryBlock extends AbstractBlock {
- protected $supportedGetActions = array( 'history' );
-
- /**
- * @var FlowActions
- */
- protected $actions;
-
- /**
- * @param Workflow $workflow Board workflow
- * @param ManagerGroup $storage Storage wrapper
- * @param FlowActions $actions Flow permission information
- */
- public function __construct( Workflow $workflow, ManagerGroup $storage, FlowActions $actions ) {
- parent::__construct( $workflow, $storage );
-
- $this->actions = $actions;
- }
+ protected $supportedGetActions = [ 'history' ];
// @Todo - fill in the template names
- protected $templates = array(
+ protected $templates = [
'history' => '',
- );
+ ];
/**
* Board history is read-only block which should not invoke write action
@@ -54,16 +34,16 @@ class BoardHistoryBlock extends AbstractBlock {
global $wgRequest;
if ( $this->workflow->isNew() ) {
- return array(
+ return [
'type' => $this->getName(),
- 'revisions' => array(),
- 'links' => array(
- ),
- );
+ 'revisions' => [],
+ 'links' => [
+ ],
+ ];
}
/** @var BoardHistoryQuery $query */
- $query = Container::get( 'query.board-history' );
+ $query = Container::get( 'query.board.history' );
/** @var RevisionFormatter $formatter */
$formatter = Container::get( 'formatter.revision' );
$formatter->setIncludeHistoryProperties( true );
@@ -72,15 +52,15 @@ class BoardHistoryBlock extends AbstractBlock {
// don't use offset from getLimitOffset - that assumes an int, which our
// UUIDs are not
$offset = $wgRequest->getText( 'offset' );
- $offset = $offset ? UUID::create( $offset ) : null;
+ $offset = $offset ?: null;
- $pager = new HistoryPager( $this->actions, $query, $this->workflow->getId() );
+ $pager = new HistoryPager( $query, $this->workflow->getId() );
$pager->setLimit( $limit );
$pager->setOffset( $offset );
$pager->doQuery();
$history = $pager->getResult();
- $revisions = array();
+ $revisions = [];
foreach ( $history as $row ) {
$serialized = $formatter->formatApi( $row, $this->context, 'history' );
if ( $serialized ) {
@@ -88,13 +68,13 @@ class BoardHistoryBlock extends AbstractBlock {
}
}
- return array(
+ return [
'type' => $this->getName(),
'revisions' => $revisions,
'navbar' => $pager->getNavigationBar(),
- 'links' => array(
- ),
- );
+ 'links' => [
+ ],
+ ];
}
public function getName() {
diff --git a/Flow/includes/Block/Header.php b/Flow/includes/Block/Header.php
index a4a3b2e0..1f53e89f 100644
--- a/Flow/includes/Block/Header.php
+++ b/Flow/includes/Block/Header.php
@@ -31,23 +31,29 @@ class HeaderBlock extends AbstractBlock {
protected $newRevision;
/**
+ * @var array Map of data to be passed on as
+ * commit metadata for event handlers
+ */
+ protected $extraCommitMetadata = [];
+
+ /**
* @var string[]
*/
- protected $supportedPostActions = array( 'edit-header', 'undo-edit-header' );
+ protected $supportedPostActions = [ 'edit-header', 'undo-edit-header' ];
/**
* @var string[]
*/
- protected $supportedGetActions = array( 'view', 'compare-header-revisions', 'edit-header', 'view-header', 'undo-edit-header' );
+ protected $supportedGetActions = [ 'view', 'compare-header-revisions', 'edit-header', 'view-header', 'undo-edit-header' ];
// @Todo - fill in the template names
- protected $templates = array(
+ protected $templates = [
'view' => '',
'compare-header-revisions' => 'diff_view',
'edit-header' => 'edit',
'undo-edit-header' => 'undo_edit',
'view-header' => 'single_view',
- );
+ ];
/**
* @var RevisionActionPermissions Allows or denies actions to be performed
@@ -65,8 +71,8 @@ class HeaderBlock extends AbstractBlock {
// Get the latest revision attached to this workflow
$found = $this->storage->find(
'Header',
- array( 'rev_type_id' => $this->workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $this->workflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( $found ) {
@@ -75,13 +81,7 @@ class HeaderBlock extends AbstractBlock {
}
protected function validate() {
- // @todo some sort of restriction along the lines of article protection
- // @todo this is superseeded by SubmissionHandler::onSubmit checking
- // Title::userCan() ?
- if ( !$this->context->getUser()->isAllowed( 'edit' ) ) {
- $this->addError( 'permissions', $this->context->msg( 'flow-error-not-allowed' ) );
- return;
- }
+ // @todo T113902: some sort of restriction along the lines of article protection
if ( !isset( $this->submitted['content'] ) ) {
$this->addError( 'content', $this->context->msg( 'flow-error-missing-header-content' ) );
}
@@ -115,7 +115,7 @@ class HeaderBlock extends AbstractBlock {
$this->header->getRevisionId()->getAlphadecimal(),
$this->context->getUser()->getName()
),
- array( 'revision_id' => $this->header->getRevisionId()->getAlphadecimal() ) // save current revision ID
+ [ 'revision_id' => $this->header->getRevisionId()->getAlphadecimal() ] // save current revision ID
);
}
@@ -129,7 +129,9 @@ class HeaderBlock extends AbstractBlock {
$this->workflow->getArticleTitle()
);
- if ( !$this->checkSpamFilters( $this->header, $this->newRevision ) ) {
+ if ( $this->newRevision->getRevisionId()->equals( $this->header->getRevisionId() ) ) {
+ $this->extraCommitMetadata['null-edit'] = true;
+ } elseif ( !$this->checkSpamFilters( $this->header, $this->newRevision ) ) {
return;
}
}
@@ -165,19 +167,27 @@ class HeaderBlock extends AbstractBlock {
}
public function commit() {
- switch( $this->action ) {
+ $metadata = $this->extraCommitMetadata;
+
+ switch ( $this->action ) {
case 'undo-edit-header':
case 'edit-header':
- $this->workflow->updateLastUpdated( $this->newRevision->getRevisionId() );
- $this->storage->put( $this->workflow, array() ); // 'discussion' workflow
- $this->storage->put( $this->newRevision, array(
- 'workflow' => $this->workflow,
- ) );
+ // store data, unless we're dealing with a null-edit (in which case
+ // is storing the same thing not only pointless, it can even be
+ // incorrect, since listeners will run & generate notifications etc)
+ if ( !isset( $this->extraCommitMetadata['null-edit'] ) ) {
+ $this->workflow->updateLastUpdated( $this->newRevision->getRevisionId() );
+ $this->storage->put( $this->workflow, $metadata ); // 'discussion' workflow
+ $this->storage->put( $this->newRevision, $metadata + [
+ 'workflow' => $this->workflow,
+ ] );
+ }
+
// Reload $this->header for renderApi() after save
$this->header = $this->newRevision;
- return array(
+ return [
'header-revision-id' => $this->newRevision->getRevisionId(),
- );
+ ];
default:
throw new InvalidActionException( 'Unrecognized commit action', 'invalid-action' );
@@ -185,10 +195,10 @@ class HeaderBlock extends AbstractBlock {
}
public function renderApi( array $options ) {
- $output = array(
+ $output = [
'type' => $this->getName(),
'editToken' => $this->getEditToken(),
- );
+ ];
switch ( $this->action ) {
case 'view':
@@ -220,7 +230,7 @@ class HeaderBlock extends AbstractBlock {
break;
}
- $output['submitted'] = $this->wasSubmitted() ? $this->submitted : array();
+ $output['submitted'] = $this->wasSubmitted() ? $this->submitted : [];
$output['errors'] = $this->errors;
return $output;
}
@@ -232,7 +242,7 @@ class HeaderBlock extends AbstractBlock {
}
$oldRevision = null;
if ( isset( $options['oldRevision'] ) ) {
- $oldRevision = $options['newRevision'];
+ $oldRevision = $options['oldRevision'];
}
/** @var HeaderViewQuery $query */
$query = Container::get( 'query.header.view' );
@@ -240,9 +250,9 @@ class HeaderBlock extends AbstractBlock {
/** @var RevisionDiffViewFormatter $formatter */
$formatter = Container::get( 'formatter.revision.diff.view' );
- return array(
+ return [
'revision' => $formatter->formatApi( $new, $old, $this->context )
- );
+ ];
}
// @Todo - duplicated logic in other single view block
@@ -255,12 +265,12 @@ class HeaderBlock extends AbstractBlock {
if ( !$this->permissions->isAllowed( $row->revision, 'view' ) ) {
$this->addError( 'permissions', $this->context->msg( 'flow-error-not-allowed' ) );
- return array();
+ return [];
}
- return array(
+ return [
'revision' => $formatter->formatApi( $row, $this->context )
- );
+ ];
}
/**
@@ -268,27 +278,34 @@ class HeaderBlock extends AbstractBlock {
* @return array
*/
protected function renderRevisionApi( $format ) {
- $output = array();
+ $output = [];
if ( $this->header === null ) {
if (
!$this->permissions->isRevisionAllowed( null, 'view' ) ||
!$this->permissions->isBoardAllowed( $this->workflow, 'view' )
) {
$this->addError( 'permissions', $this->context->msg( 'flow-error-not-allowed' ) );
- return array();
+ return [];
}
/** @var UrlGenerator $urlGenerator */
$urlGenerator = Container::get( 'url_generator' );
- $output['revision'] = array(
- // @todo
- 'actions' => array(
- 'edit' => $urlGenerator
- ->createHeaderAction( $this->workflow->getArticleTitle() ),
- ),
- 'links' => array(
- ),
- );
+
+ $title = $this->workflow->getArticleTitle();
+ $user = $this->context->getUser();
+
+ $actions = [];
+
+ if ( $this->workflow->userCan( 'edit', $user ) ) {
+ $actions['edit'] = $urlGenerator
+ ->createHeaderAction( $this->workflow->getArticleTitle() );
+ }
+
+ $output['revision'] = [
+ 'actions' => $actions,
+ 'links' => [
+ ],
+ ];
} else {
$row = new FormatterRow;
$row->workflow = $this->workflow;
@@ -297,7 +314,7 @@ class HeaderBlock extends AbstractBlock {
if ( !$this->permissions->isAllowed( $row->revision, 'view' ) ) {
$this->addError( 'permissions', $this->context->msg( 'flow-error-not-allowed' ) );
- return array();
+ return [];
}
$serializer = Container::get( 'formatter.revision' );
diff --git a/Flow/includes/Block/Topic.php b/Flow/includes/Block/Topic.php
index 18f78124..0af24cf1 100644
--- a/Flow/includes/Block/Topic.php
+++ b/Flow/includes/Block/Topic.php
@@ -3,9 +3,9 @@
namespace Flow\Block;
use Flow\Container;
-use Flow\FlowActions;
use Flow\Data\ManagerGroup;
use Flow\Data\Pager\HistoryPager;
+use Flow\Exception\DataModelException;
use Flow\Exception\FailCommitException;
use Flow\Exception\FlowException;
use Flow\Exception\InvalidActionException;
@@ -20,6 +20,7 @@ use Flow\Model\AbstractRevision;
use Flow\Model\PostRevision;
use Flow\Model\UUID;
use Flow\Model\Workflow;
+use Flow\NotificationController;
use Flow\Repository\RootPostLoader;
use Message;
@@ -46,22 +47,17 @@ class TopicBlock extends AbstractBlock {
protected $newRevision;
/**
- * @var FlowActions
- */
- protected $actions;
-
- /**
* @var array
*/
- protected $requestedPost = array();
+ protected $requestedPost = [];
/**
* @var array Map of data to be passed on as
* commit metadata for event handlers
*/
- protected $extraCommitMetadata = array();
+ protected $extraCommitMetadata = [];
- protected $supportedPostActions = array(
+ protected $supportedPostActions = [
// Standard editing
'edit-post', 'reply',
// Moderation
@@ -72,16 +68,16 @@ class TopicBlock extends AbstractBlock {
// Other stuff
'edit-title',
'undo-edit-post',
- );
+ ];
- protected $supportedGetActions = array(
+ protected $supportedGetActions = [
'reply', 'view', 'history', 'edit-post', 'edit-title', 'compare-post-revisions', 'single-view',
'view-topic', 'view-topic-history', 'view-post', 'view-post-history', 'undo-edit-post',
'moderate-topic', 'moderate-post', 'lock-topic',
- );
+ ];
// @Todo - fill in the template names
- protected $templates = array(
+ protected $templates = [
'single-view' => 'single_view',
'view' => '',
'reply' => '',
@@ -93,21 +89,19 @@ class TopicBlock extends AbstractBlock {
'moderate-topic' => 'moderate_topic',
'moderate-post' => 'moderate_post',
'lock-topic' => 'lock',
- );
+ ];
- public function __construct( Workflow $workflow, ManagerGroup $storage, $root, FlowActions $actions ) {
+ public function __construct( Workflow $workflow, ManagerGroup $storage, $root ) {
parent::__construct( $workflow, $storage );
if ( $root instanceof PostRevision ) {
$this->root = $root;
} elseif ( $root instanceof RootPostLoader ) {
$this->rootLoader = $root;
} else {
- throw new InvalidInputException(
+ throw new DataModelException(
'Expected PostRevision or RootPostLoader, received: ' . is_object( $root ) ? get_class( $root ) : gettype( $root ), 'invalid-input'
);
}
-
- $this->actions = $actions;
}
protected function validate() {
@@ -118,18 +112,7 @@ class TopicBlock extends AbstractBlock {
return;
}
- // If the topic is locked, the only allowed action is to unlock it
- if (
- $topicTitle->isLocked()
- && (
- $this->action !== 'lock-topic'
- || !in_array( $this->submitted['moderationState'], array( 'unlock', /* BC for unlock: */ 'reopen' ) )
- )
- ) {
- $this->addError( 'moderate', $this->context->msg( 'flow-error-topic-is-locked' ) );
- }
-
- switch( $this->action ) {
+ switch ( $this->action ) {
case 'edit-title':
$this->validateEditTitle();
break;
@@ -210,7 +193,7 @@ class TopicBlock extends AbstractBlock {
$topicTitle->getRevisionId()->getAlphadecimal(),
$this->context->getUser()->getName()
),
- array( 'revision_id' => $topicTitle->getRevisionId()->getAlphadecimal() ) // save current revision ID
+ [ 'revision_id' => $topicTitle->getRevisionId()->getAlphadecimal() ] // save current revision ID
);
return;
}
@@ -218,8 +201,7 @@ class TopicBlock extends AbstractBlock {
$this->newRevision = $topicTitle->newNextRevision(
$this->context->getUser(),
$this->submitted['content'],
- // default to wikitext when not specified, for old API requests
- isset( $this->submitted['format'] ) ? $this->submitted['format'] : 'wikitext',
+ 'topic-title-wikitext',
'edit-title',
$this->workflow->getArticleTitle()
);
@@ -304,7 +286,7 @@ class TopicBlock extends AbstractBlock {
// $moderationState should be a string like 'restore', 'suppress', etc. The exact strings allowed
// are checked below with $post->isValidModerationState(), but this is checked first otherwise
// a blank string would restore a post(due to AbstractRevision::MODERATED_NONE === '').
- if ( ! $moderationState ) {
+ if ( !$moderationState ) {
$this->addError( 'moderate', $this->context->msg( 'flow-error-invalid-moderation-state' ) );
return;
}
@@ -313,15 +295,15 @@ class TopicBlock extends AbstractBlock {
* BC: 'suppress' used to be called 'censor', 'lock' was 'close' &
* 'unlock' was 'reopen'
*/
- $bc = array(
+ $bc = [
'censor' => AbstractRevision::MODERATED_SUPPRESSED,
'close' => AbstractRevision::MODERATED_LOCKED,
'reopen' => 'un' . AbstractRevision::MODERATED_LOCKED
- );
+ ];
$moderationState = str_replace( array_keys( $bc ), array_values( $bc ), $moderationState );
// these all just mean set to no moderation, it returns a post to unmoderated status
- $allowedRestoreAliases = array( 'unlock', 'unhide', 'undelete', 'unsuppress', /* BC for unlock: */ 'reopen' );
+ $allowedRestoreAliases = [ 'unlock', 'unhide', 'undelete', 'unsuppress', /* BC for unlock: */ 'reopen' ];
if ( in_array( $moderationState, $allowedRestoreAliases ) ) {
$moderationState = 'restore';
}
@@ -336,7 +318,7 @@ class TopicBlock extends AbstractBlock {
$newState = $moderationState;
}
- if ( ! $post->isValidModerationState( $newState ) ) {
+ if ( !$post->isValidModerationState( $newState ) ) {
$this->addError( 'moderate', $this->context->msg( 'flow-error-invalid-moderation-state' ) );
return;
}
@@ -386,7 +368,6 @@ class TopicBlock extends AbstractBlock {
// also exists a unique index on rev_prev_revision in mysql,
// meaning if someone else inserts against the parent we and
// the submitter think is the latest, our insert will fail.
- //
// TODO: Catch whatever exception happens there, make sure the
// most recent revision is the one in the cache before handing
// user back to specific dialog indicating race condition
@@ -397,7 +378,7 @@ class TopicBlock extends AbstractBlock {
$post->getRevisionId()->getAlphadecimal(),
$this->context->getUser()->getName()
),
- array( 'revision_id' => $post->getRevisionId()->getAlphadecimal() ) // save current revision ID
+ [ 'revision_id' => $post->getRevisionId()->getAlphadecimal() ] // save current revision ID
);
return;
}
@@ -410,17 +391,19 @@ class TopicBlock extends AbstractBlock {
'edit-post',
$this->workflow->getArticleTitle()
);
- if ( !$this->checkSpamFilters( $post, $this->newRevision ) ) {
+
+ if ( $this->newRevision->getRevisionId()->equals( $post->getRevisionId() ) ) {
+ $this->extraCommitMetadata['null-edit'] = true;
+ } elseif ( !$this->checkSpamFilters( $post, $this->newRevision ) ) {
return;
}
}
public function commit() {
-
- switch( $this->action ) {
+ switch ( $this->action ) {
case 'edit-topic-summary':
// pseudo-action does not do anything, only includes data in api response
- return array();
+ return [];
case 'reply':
case 'moderate-topic':
@@ -434,10 +417,10 @@ class TopicBlock extends AbstractBlock {
throw new FailCommitException( 'Attempt to save null revision', 'fail-commit' );
}
- $metadata = $this->extraCommitMetadata + array(
+ $metadata = $this->extraCommitMetadata + [
'workflow' => $this->workflow,
'topic-title' => $this->loadTopicTitle(),
- );
+ ];
if ( !$metadata['topic-title'] instanceof PostRevision ) {
// permissions failure, should never have gotten this far
throw new PermissionException( 'Not Allowed', 'insufficient-permission' );
@@ -448,9 +431,32 @@ class TopicBlock extends AbstractBlock {
$metadata['topic-title'] = $this->newRevision;
}
- $this->storage->put( $this->newRevision, $metadata );
- $this->workflow->updateLastUpdated( $this->newRevision->getRevisionId() );
- $this->storage->put( $this->workflow, $metadata );
+ // store data, unless we're dealing with a null-edit (in which case
+ // is storing the same thing not only pointless, it can even be
+ // incorrect, since listeners will run & generate notifications etc)
+ if ( !isset( $this->extraCommitMetadata['null-edit'] ) ) {
+ $this->storage->put( $this->newRevision, $metadata );
+ $this->workflow->updateLastUpdated( $this->newRevision->getRevisionId() );
+ $this->storage->put( $this->workflow, $metadata );
+
+ if ( strpos( $this->action, 'moderate-' ) === 0 ) {
+ $topicId = $this->newRevision->getCollection()->getRoot()->getId();
+
+ $moderate = $this->newRevision->isModerated()
+ && ( $this->newRevision->getModerationState() === PostRevision::MODERATED_DELETED
+ || $this->newRevision->getModerationState() === PostRevision::MODERATED_SUPPRESSED );
+
+ /** @var NotificationController $controller */
+ $controller = Container::get( 'controller.notification' );
+ if ( $this->action === 'moderate-topic' ) {
+ $controller->moderateTopicNotifications( $topicId, $moderate );
+ } elseif ( $this->action === 'moderate-post' ) {
+ $postId = $this->newRevision->getPostId();
+ $controller->moderatePostNotifications( $topicId, $postId, $moderate );
+ }
+ }
+ }
+
$newRevision = $this->newRevision;
// If no context was loaded render the post in isolation
@@ -458,13 +464,13 @@ class TopicBlock extends AbstractBlock {
try {
$newRevision->getChildren();
} catch ( \MWException $e ) {
- $newRevision->setChildren( array() );
+ $newRevision->setChildren( [] );
}
- $returnMetadata = array(
+ $returnMetadata = [
'post-id' => $this->newRevision->getPostId(),
'post-revision-id' => $this->newRevision->getRevisionId(),
- );
+ ];
return $returnMetadata;
@@ -474,11 +480,11 @@ class TopicBlock extends AbstractBlock {
}
public function renderApi( array $options ) {
- $output = array( 'type' => $this->getName() );
+ $output = [ 'type' => $this->getName() ];
$topic = $this->loadTopicTitle();
if ( !$topic ) {
- return $output + $this->finalizeApiOutput($options);
+ return $output + $this->finalizeApiOutput( $options );
}
// there's probably some OO way to turn this stack of if/else into
@@ -543,16 +549,16 @@ class TopicBlock extends AbstractBlock {
$output += $this->renderTopicApi( $options );
break;
+ case 'edit-title':
case 'view-post':
case 'view':
default:
// view single post, possibly specific revision
- // @todo this isn't valid for the topic title
$output += $this->renderPostApi( $options );
break;
}
- return $output + $this->finalizeApiOutput($options);
+ return $output + $this->finalizeApiOutput( $options );
}
/**
@@ -562,15 +568,15 @@ class TopicBlock extends AbstractBlock {
protected function finalizeApiOutput( $options ) {
if ( $this->wasSubmitted() ) {
// Failed actions, like reply, end up here
- return array(
+ return [
'submitted' => $this->submitted,
'errors' => $this->errors,
- );
+ ];
} else {
- return array(
+ return [
'submitted' => $options,
'errors' => $this->errors,
- );
+ ];
}
}
@@ -585,9 +591,9 @@ class TopicBlock extends AbstractBlock {
}
list( $new, $old ) = Container::get( 'query.post.view' )->getDiffViewResult( UUID::create( $options['newRevision'] ), UUID::create( $oldRevision ) );
- return array(
+ return [
'revision' => Container::get( 'formatter.revision.diff.view' )->formatApi( $new, $old, $this->context )
- );
+ ];
}
// @Todo - duplicated logic in other single view block
@@ -596,12 +602,12 @@ class TopicBlock extends AbstractBlock {
if ( !$this->permissions->isAllowed( $row->revision, 'view' ) ) {
$this->addError( 'permissions', $this->getDisallowedErrorMessage( $row->revision ) );
- return array();
+ return [];
}
- return array(
+ return [
'revision' => Container::get( 'formatter.revisionview' )->formatApi( $row, $this->context )
- );
+ ];
}
protected function renderTopicApi( array $options, $workflowId = '' ) {
@@ -631,7 +637,7 @@ class TopicBlock extends AbstractBlock {
return $serializer->formatApi(
$this->workflow,
- Container::get( 'query.topiclist' )->getResults( array( $workflowId ) ),
+ Container::get( 'query.topiclist' )->getResults( [ $workflowId ] ),
$this->context
);
}
@@ -652,11 +658,13 @@ class TopicBlock extends AbstractBlock {
if ( !$postId ) {
if ( isset( $options['postId'] ) ) {
$postId = $options['postId'];
- } elseif( $this->newRevision ) {
+ } elseif ( $this->newRevision ) {
// API results after a reply will have no $postId (ID is not yet
// known when the reply is submitted) so we'll grab it from the
// newly added revision
$postId = $this->newRevision->getPostId();
+ } else {
+ throw new FlowException( 'No post id specified' );
}
} else {
// $postId is only set for lock-topic, which should default to
@@ -671,15 +679,15 @@ class TopicBlock extends AbstractBlock {
return null;
}
- return array(
- 'roots' => array( $serialized['postId'] ),
- 'posts' => array(
- $serialized['postId'] => array( $serialized['revisionId'] ),
- ),
- 'revisions' => array(
+ return [
+ 'roots' => [ $serialized['postId'] ],
+ 'posts' => [
+ $serialized['postId'] => [ $serialized['revisionId'] ],
+ ],
+ 'revisions' => [
$serialized['revisionId'] => $serialized,
- )
- );
+ ]
+ ];
}
protected function renderUndoApi( array $options ) {
@@ -703,7 +711,7 @@ class TopicBlock extends AbstractBlock {
}
/**
- * @param string $format Content format (html|wikitext|html-fixed|plaintext)
+ * @param string $format Content format (html|wikitext|fixed-html|topic-title-html|topic-title-wikitext)
* @return RevisionFormatter
*/
protected function getRevisionFormatter( $format ) {
@@ -749,13 +757,13 @@ class TopicBlock extends AbstractBlock {
$offset = $wgRequest->getText( 'offset' );
$offset = $offset ? UUID::create( $offset ) : null;
- $pager = new HistoryPager( $this->actions, $query, $uuid );
+ $pager = new HistoryPager( $query, $uuid );
$pager->setLimit( $limit );
$pager->setOffset( $offset );
$pager->doQuery();
$history = $pager->getResult();
- $revisions = array();
+ $revisions = [];
foreach ( $history as $row ) {
$serialized = $serializer->formatApi( $row, $this->context, 'history' );
// if the user is not allowed to see this row it will return empty
@@ -764,7 +772,7 @@ class TopicBlock extends AbstractBlock {
}
}
- $response = array( 'revisions' => $revisions );
+ $response = [ 'revisions' => $revisions ];
if ( $navbar ) {
$response['navbar'] = $pager->getNavigationBar();
}
@@ -804,8 +812,8 @@ class TopicBlock extends AbstractBlock {
if ( $this->topicTitle === null ) {
$found = $this->storage->find(
'PostRevision',
- array( 'rev_type_id' => $this->workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $this->workflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( !$found ) {
throw new InvalidDataException( 'Every workflow must have an associated topic title', 'missing-topic-title' );
@@ -814,7 +822,7 @@ class TopicBlock extends AbstractBlock {
// this method loads only title, nothing else; otherwise, you're
// looking for loadRootPost
- $this->topicTitle->setChildren( array() );
+ $this->topicTitle->setChildren( [] );
$this->topicTitle->setDepth( 0 );
$this->topicTitle->setRootPost( $this->topicTitle );
}
@@ -833,7 +841,7 @@ class TopicBlock extends AbstractBlock {
* @return Message
*/
protected function getDisallowedErrorMessage( AbstractRevision $revision ) {
- if ( in_array( $this->action, array( 'moderate-topic', 'moderate-post' ) ) ) {
+ if ( in_array( $this->action, [ 'moderate-topic', 'moderate-post' ] ) ) {
/*
* When failing to moderate an already moderated action (like
* undo), show the more general "you have insufficient
@@ -847,12 +855,12 @@ class TopicBlock extends AbstractBlock {
// display simple message
// i18n messages:
- // flow-error-not-allowed-hide,
- // flow-error-not-allowed-reply-to-hide-topic
- // flow-error-not-allowed-delete
- // flow-error-not-allowed-reply-to-delete-topic
- // flow-error-not-allowed-suppress
- // flow-error-not-allowed-reply-to-suppress-topic
+ // flow-error-not-allowed-hide,
+ // flow-error-not-allowed-reply-to-hide-topic
+ // flow-error-not-allowed-delete
+ // flow-error-not-allowed-reply-to-delete-topic
+ // flow-error-not-allowed-suppress
+ // flow-error-not-allowed-reply-to-suppress-topic
if ( $revision instanceof PostRevision ) {
$type = $revision->isTopicTitle() ? 'topic' : 'post';
} else {
@@ -873,24 +881,26 @@ class TopicBlock extends AbstractBlock {
// get log extract
$entries = \LogEventsList::showLogExtract(
$output,
- array( $state ),
+ [ $state ],
$this->workflow->getArticleTitle()->getPrefixedText(),
'',
- array(
+ [
'lim' => 10,
'showIfEmpty' => false,
// i18n messages:
- // flow-error-not-allowed-delete-extract
- // flow-error-not-allowed-reply-to-delete-topic-extract
- // flow-error-not-allowed-suppress-extract
- // flow-error-not-allowed-reply-to-suppress-topic-extract
- 'msgKey' => array(
- array(
+ // flow-error-not-allowed-hide-extract
+ // flow-error-not-allowed-reply-to-hide-topic-extract
+ // flow-error-not-allowed-delete-extract
+ // flow-error-not-allowed-reply-to-delete-topic-extract
+ // flow-error-not-allowed-suppress-extract
+ // flow-error-not-allowed-reply-to-suppress-topic-extract
+ 'msgKey' => [
+ [
"flow-error-not-allowed-{$this->action}-to-$state-$type",
"flow-error-not-allowed-$state-extract",
- ),
- )
- )
+ ],
+ ]
+ ]
);
// check if there were any log extracts
@@ -901,12 +911,12 @@ class TopicBlock extends AbstractBlock {
}
}
- return $this->context->msg( array(
+ return $this->context->msg( [
// set of keys to try in order
"flow-error-not-allowed-{$this->action}-to-$state-$type",
"flow-error-not-allowed-$state",
"flow-error-not-allowed"
- ) );
+ ] );
}
/**
@@ -970,7 +980,7 @@ class TopicBlock extends AbstractBlock {
* @param \OutputPage $out
*
* @todo Provide more informative page title for actions other than view,
- * e.g. "Hide post in <TITLE>", "Unlock <TITLE>", etc.
+ * e.g. "Hide post in <TITLE>", "Unlock <TITLE>", etc.
*/
public function setPageTitle( \OutputPage $out ) {
$topic = $this->loadTopicTitle( $this->action === 'history' ? 'history' : 'view' );
@@ -986,12 +996,12 @@ class TopicBlock extends AbstractBlock {
} else {
$key = 'flow-topic-html-title';
}
- $out->setHtmlTitle( $out->msg( $key, array(
+ $out->setHtmlTitle( $out->msg( $key, [
// This must be a rawParam to not expand {{foo}} in the title, it must
// not be htmlspecialchar'd because OutputPage::setHtmlTitle handles that.
- Message::rawParam( $topic->getContent( 'wikitext' ) ),
+ Message::rawParam( $topic->getContent( 'topic-title-plaintext' ) ),
$title->getPrefixedText()
- ) ) );
+ ] ) );
} else {
$out->setHtmlTitle( $title->getPrefixedText() );
}
diff --git a/Flow/includes/Block/TopicList.php b/Flow/includes/Block/TopicList.php
index e4d45696..7c6bf318 100644
--- a/Flow/includes/Block/TopicList.php
+++ b/Flow/includes/Block/TopicList.php
@@ -20,18 +20,18 @@ class TopicListBlock extends AbstractBlock {
/**
* @var array
*/
- protected $supportedPostActions = array( 'new-topic' );
+ protected $supportedPostActions = [ 'new-topic' ];
/**
* @var array
*/
- protected $supportedGetActions = array( 'view', 'view-topiclist' );
+ protected $supportedGetActions = [ 'view', 'view-topiclist' ];
// @Todo - fill in the template names
- protected $templates = array(
+ protected $templates = [
'view' => '',
'new-topic' => 'newtopic',
- );
+ ];
/**
* @var Workflow|null
@@ -58,7 +58,7 @@ class TopicListBlock extends AbstractBlock {
*
* Associative array mapping topic ID (in alphadecimal form) to PostRevision for the topic root.
*/
- protected $topicRootRevisionCache = array();
+ protected $topicRootRevisionCache = [];
/**
* @constant(TOCLIMIT)
@@ -122,12 +122,10 @@ class TopicListBlock extends AbstractBlock {
$user = $this->context->getUser();
$topicWorkflow = Workflow::create( 'topic', $title );
$topicListEntry = TopicListEntry::create( $this->workflow, $topicWorkflow );
- $topicTitle = PostRevision::create(
+ $topicTitle = PostRevision::createTopicPost(
$topicWorkflow,
$user,
- $this->submitted['topic'],
- // topic title is never parsed
- 'wikitext'
+ $this->submitted['topic']
);
$firstPost = null;
@@ -139,10 +137,10 @@ class TopicListBlock extends AbstractBlock {
// default to wikitext when not specified, for old API requests
isset( $this->submitted['format'] ) ? $this->submitted['format'] : 'wikitext'
);
- $topicTitle->setChildren( array( $firstPost ) );
+ $topicTitle->setChildren( [ $firstPost ] );
}
- return array( $topicWorkflow, $topicListEntry, $topicTitle, $firstPost );
+ return [ $topicWorkflow, $topicListEntry, $topicTitle, $firstPost ];
}
public function commit() {
@@ -150,12 +148,12 @@ class TopicListBlock extends AbstractBlock {
throw new FailCommitException( 'Unknown commit action', 'fail-commit' );
}
- $metadata = array(
+ $metadata = [
'workflow' => $this->topicWorkflow,
'board-workflow' => $this->workflow,
'topic-title' => $this->topicTitle,
'first-post' => $this->firstPost,
- );
+ ];
/*
* Order of storage is important! We've been changing when we stored
@@ -170,23 +168,23 @@ class TopicListBlock extends AbstractBlock {
* If you even feel the need to change the order, make sure you come
* up with a fix for the above things ;)
*/
- $this->storage->put( $this->workflow, array() ); // 'discussion' workflow
+ $this->storage->put( $this->workflow, [] ); // 'discussion' workflow
$this->storage->put( $this->topicWorkflow, $metadata ); // 'topic' workflow
$this->storage->put( $this->topicListEntry, $metadata );
$this->storage->put( $this->topicTitle, $metadata );
if ( $this->firstPost !== null ) {
- $this->storage->put( $this->firstPost, $metadata + array(
+ $this->storage->put( $this->firstPost, $metadata + [
'reply-to' => $this->topicTitle
- ) );
+ ] );
}
- $output = array(
+ $output = [
'topic-page' => $this->topicWorkflow->getArticleTitle()->getPrefixedText(),
'topic-id' => $this->topicTitle->getPostId(),
'topic-revision-id' => $this->topicTitle->getRevisionId(),
'post-id' => $this->firstPost ? $this->firstPost->getPostId() : null,
'post-revision-id' => $this->firstPost ? $this->firstPost->getRevisionId() : null,
- );
+ ];
return $output;
}
@@ -196,10 +194,10 @@ class TopicListBlock extends AbstractBlock {
$tocApiParams = array_merge(
$options,
- array(
+ [
'toconly' => true,
'limit' => self::TOCLIMIT
- )
+ ]
);
$findOptions = $this->getFindOptions( $options );
@@ -219,7 +217,7 @@ class TopicListBlock extends AbstractBlock {
// Make sure we found topiclist block
// and that it actually has roots in it
$existingRoots = isset( $topicList['roots'] ) && is_array( $topicList['roots'] ) ?
- $topicList['roots'] : array();
+ $topicList['roots'] : [];
if ( count( $existingRoots ) > 0 ) {
// Add new offset-id and limit to the api parameters and change the limit
@@ -234,10 +232,10 @@ class TopicListBlock extends AbstractBlock {
public function renderApi( array $options ) {
$options = $this->preloadTexts( $options );
- $response = array(
+ $response = [
'submitted' => $this->wasSubmitted() ? $this->submitted : $options,
'errors' => $this->errors,
- );
+ ];
// Repeating the default until we use the API for everything (bug 72659)
// Also, if this is removed other APIs (i.e. ApiFlowNewTopic) may need
@@ -255,7 +253,7 @@ class TopicListBlock extends AbstractBlock {
}
// @todo remove the 'api' => true, its always api
- $findOptions = $this->getFindOptions( $options + array( 'api' => true ) );
+ $findOptions = $this->getFindOptions( $options + [ 'api' => true ] );
// include the current sortby option. Note that when 'user' is either
// submitted or defaulted to this is the resulting sort. ex: newest
@@ -266,7 +264,7 @@ class TopicListBlock extends AbstractBlock {
}
$page = $this->getPage( $findOptions );
- $workflowIds = array();
+ $workflowIds = [];
/** @var TopicListEntry $topicListEntry */
foreach ( $page->getResults() as $topicListEntry ) {
$workflowIds[] = $topicListEntry->getId();
@@ -277,8 +275,8 @@ class TopicListBlock extends AbstractBlock {
if ( $isTocOnly ) {
// We don't need any further data, so we skip the TopicListQuery.
- $topicRootRevisionsByWorkflowId = array();
- $workflowsByWorkflowId = array();
+ $topicRootRevisionsByWorkflowId = [];
+ $workflowsByWorkflowId = [];
foreach ( $workflows as $workflow ) {
$alphaWorkflowId = $workflow->getId()->getAlphadecimal();
@@ -292,7 +290,7 @@ class TopicListBlock extends AbstractBlock {
/** @var TopicListQuery $query */
$query = Container::get( 'query.topiclist' );
$found = $query->getResults( $page->getResults() );
- wfDebugLog( 'FlowDebug', 'Rendering topiclist for ids: ' . implode( ', ', array_map( function( UUID $id ) {
+ wfDebugLog( 'FlowDebug', 'Rendering topiclist for ids: ' . implode( ', ', array_map( function ( UUID $id ) {
return $id->getAlphadecimal();
}, $workflowIds ) ) );
@@ -346,14 +344,14 @@ class TopicListBlock extends AbstractBlock {
}
protected function getFindOptions( array $requestOptions ) {
- $findOptions = array();
+ $findOptions = [];
// Compute offset/limit
$limit = $this->getLimit( $requestOptions );
// @todo Once we migrate View.php to use the API directly
// all defaults will be handled by API and not here.
- $requestOptions += array(
+ $requestOptions += [
'include-offset' => false,
'offset-id' => false,
'offset-dir' => 'fwd',
@@ -361,7 +359,7 @@ class TopicListBlock extends AbstractBlock {
'api' => true,
'sortby' => 'user',
'savesortby' => false,
- );
+ ];
$user = $this->context->getUser();
if ( strlen( $requestOptions['sortby'] ) === 0 ) {
@@ -372,13 +370,13 @@ class TopicListBlock extends AbstractBlock {
if ( $requestOptions['sortby'] === 'user' ) {
$requestOptions['sortby'] = $user->getOption( 'flow-topiclist-sortby' );
}
- switch( $requestOptions['sortby'] ) {
+ switch ( $requestOptions['sortby'] ) {
case 'updated':
- $findOptions = array(
+ $findOptions = [
'sortby' => 'updated',
'sort' => 'workflow_last_update_timestamp',
'order' => 'desc',
- ) + $findOptions;
+ ] + $findOptions;
if ( $requestOptions['offset-id'] ) {
throw new FlowException( 'The `updated` sort order does not allow the `offset-id` parameter. Please use `offset`.' );
@@ -387,11 +385,11 @@ class TopicListBlock extends AbstractBlock {
case 'newest':
default:
- $findOptions = array(
+ $findOptions = [
'sortby' => 'newest',
'sort' => 'topic_id',
'order' => 'desc',
- ) + $findOptions;
+ ] + $findOptions;
if ( $requestOptions['offset'] ) {
throw new FlowException( 'The `newest` sort order does not allow the `offset` parameter. Please use `offset-id`.' );
@@ -412,10 +410,6 @@ class TopicListBlock extends AbstractBlock {
$findOptions['pager-include-offset'] = $requestOptions['include-offset'];
}
- if ( $requestOptions['api'] ) {
- $findOptions['offset-elastic'] = false;
- }
-
$findOptions['pager-limit'] = $limit;
if (
@@ -425,7 +419,7 @@ class TopicListBlock extends AbstractBlock {
) {
$user->setOption( 'flow-topiclist-sortby', $findOptions['sortby'] );
// Save the user preferences post-send
- \DeferredUpdates::addCallableUpdate( function() use ( $user ) {
+ \DeferredUpdates::addCallableUpdate( function () use ( $user ) {
$user->saveSettings();
} );
}
@@ -446,7 +440,7 @@ class TopicListBlock extends AbstractBlock {
protected function getPage( array $findOptions ) {
$pager = new Pager(
$this->storage->getStorage( 'TopicListEntry' ),
- array( 'topic_list_id' => $this->workflow->getId() ),
+ [ 'topic_list_id' => $this->workflow->getId() ],
$findOptions
);
@@ -455,18 +449,18 @@ class TopicListBlock extends AbstractBlock {
// Work around lack of $this in closures until we can use PHP 5.4+ features.
$topicRootRevisionCache =& $this->topicRootRevisionCache;
- return $pager->getPage( function( array $found ) use ( $postStorage, &$topicRootRevisionCache ) {
- $queries = array();
+ return $pager->getPage( function ( array $found ) use ( $postStorage, &$topicRootRevisionCache ) {
+ $queries = [];
/** @var TopicListEntry[] $found */
foreach ( $found as $entry ) {
- $queries[] = array( 'rev_type_id' => $entry->getId() );
+ $queries[] = [ 'rev_type_id' => $entry->getId() ];
}
- $posts = $postStorage->findMulti( $queries, array(
+ $posts = $postStorage->findMulti( $queries, [
'sort' => 'rev_id',
'order' => 'DESC',
'limit' => 1,
- ) );
- $allowed = array();
+ ] );
+ $allowed = [];
foreach ( $posts as $queryResult ) {
$post = reset( $queryResult );
if ( !$post->isModerated() || $post->isLocked() ) {
diff --git a/Flow/includes/Block/TopicSummary.php b/Flow/includes/Block/TopicSummary.php
index 476b6c09..3b32298e 100644
--- a/Flow/includes/Block/TopicSummary.php
+++ b/Flow/includes/Block/TopicSummary.php
@@ -36,6 +36,12 @@ class TopicSummaryBlock extends AbstractBlock {
protected $nextRevision;
/**
+ * @var array Map of data to be passed on as
+ * commit metadata for event handlers
+ */
+ protected $extraCommitMetadata = [];
+
+ /**
* @var PostRevision|null
*/
protected $topicTitle;
@@ -43,19 +49,19 @@ class TopicSummaryBlock extends AbstractBlock {
/**
* @var string[]
*/
- protected $supportedPostActions = array( 'edit-topic-summary', 'undo-edit-topic-summary' );
+ protected $supportedPostActions = [ 'edit-topic-summary', 'undo-edit-topic-summary' ];
/**
* @var string[]
*/
- protected $supportedGetActions = array( 'view-topic-summary', 'compare-postsummary-revisions', 'edit-topic-summary', 'undo-edit-topic-summary' );
+ protected $supportedGetActions = [ 'view-topic-summary', 'compare-postsummary-revisions', 'edit-topic-summary', 'undo-edit-topic-summary' ];
- protected $templates = array(
+ protected $templates = [
'view-topic-summary' => 'single_view',
'compare-postsummary-revisions' => 'diff_view',
'edit-topic-summary' => 'edit',
'undo-edit-topic-summary' => 'undo_edit',
- );
+ ];
/**
* @param IContextSource $context
@@ -78,7 +84,7 @@ class TopicSummaryBlock extends AbstractBlock {
* Validate data before commiting change
*/
public function validate() {
- switch( $this->action ) {
+ switch ( $this->action ) {
case 'undo-edit-topic-summary':
case 'edit-topic-summary':
$this->validateTopicSummary();
@@ -131,6 +137,10 @@ class TopicSummaryBlock extends AbstractBlock {
isset( $this->submitted['format'] ) ? $this->submitted['format'] : 'wikitext',
'create-topic-summary'
);
+
+ if ( !trim( $this->submitted['summary'] ) ) {
+ $this->extraCommitMetadata['null-edit'] = true;
+ }
// Edit topic summary
} else {
if ( !$this->permissions->isAllowed( $this->topicSummary, 'edit-topic-summary' ) ) {
@@ -149,7 +159,7 @@ class TopicSummaryBlock extends AbstractBlock {
$this->topicSummary->getRevisionId()->getAlphadecimal(),
$this->context->getUser()->getName()
),
- array( 'revision_id' => $this->topicSummary->getRevisionId()->getAlphadecimal() )
+ [ 'revision_id' => $this->topicSummary->getRevisionId()->getAlphadecimal() ]
);
return;
}
@@ -162,6 +172,10 @@ class TopicSummaryBlock extends AbstractBlock {
'edit-topic-summary',
$this->workflow->getArticleTitle()
);
+
+ if ( $this->nextRevision->getRevisionId()->equals( $this->topicSummary->getRevisionId() ) ) {
+ $this->extraCommitMetadata['null-edit'] = true;
+ }
}
if ( !$this->checkSpamFilters( $this->topicSummary, $this->nextRevision ) ) {
@@ -181,8 +195,8 @@ class TopicSummaryBlock extends AbstractBlock {
}
$found = $this->storage->find(
'PostRevision',
- array( 'rev_type_id' => $this->workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $this->workflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( !$found ) {
throw new InvalidDataException( 'Every workflow must have an associated topic title', 'missing-topic-title' );
@@ -200,9 +214,15 @@ class TopicSummaryBlock extends AbstractBlock {
throw new FailCommitException( 'Attempt to save summary on null revision', 'fail-commit' );
}
- $this->storage->put( $this->nextRevision, array(
- 'workflow' => $this->workflow,
- ) );
+ // store data, unless we're dealing with a null-edit (in which case
+ // is storing the same thing not only pointless, it can even be
+ // incorrect, since listeners will run & generate notifications etc)
+ if ( !isset( $this->extraCommitMetadata['null-edit'] ) ) {
+ $this->storage->put( $this->nextRevision, $this->extraCommitMetadata + [
+ 'workflow' => $this->workflow,
+ 'topic-title' => $this->findTopicTitle(),
+ ] );
+ }
// Reload the $this->formatterRow for renderApi() after save
$this->formatterRow = new FormatterRow();
$this->formatterRow->revision = $this->nextRevision;
@@ -211,9 +231,9 @@ class TopicSummaryBlock extends AbstractBlock {
$this->formatterRow->workflow = $this->workflow;
$this->topicSummary = $this->nextRevision;
- return array(
+ return [
'summary-revision-id' => $this->nextRevision->getRevisionId(),
- );
+ ];
}
/**
@@ -222,7 +242,7 @@ class TopicSummaryBlock extends AbstractBlock {
* @throws InvalidActionException
*/
public function commit() {
- switch( $this->action ) {
+ switch ( $this->action ) {
case 'undo-edit-topic-summary':
case 'edit-topic-summary':
return $this->saveTopicSummary();
@@ -241,7 +261,7 @@ class TopicSummaryBlock extends AbstractBlock {
* @throws InvalidInputException
*/
public function renderApi( array $options ) {
- $output = array( 'type' => $this->getName() );
+ $output = [ 'type' => $this->getName() ];
switch ( $this->action ) {
case 'view-topic-summary':
@@ -278,7 +298,7 @@ class TopicSummaryBlock extends AbstractBlock {
}
$oldRevision = null;
if ( isset( $options['oldRevision'] ) ) {
- $oldRevision = $options['newRevision'];
+ $oldRevision = $options['oldRevision'];
}
list( $new, $old ) = Container::get( 'query.postsummary.view' )->getDiffViewResult( UUID::create( $options['newRevision'] ), UUID::create( $oldRevision ) );
if (
@@ -293,15 +313,15 @@ class TopicSummaryBlock extends AbstractBlock {
}
if ( $this->wasSubmitted() ) {
- $output += array(
+ $output += [
'submitted' => $this->submitted,
'errors' => $this->errors,
- );
+ ];
} else {
- $output += array(
- 'submitted' => array(),
+ $output += [
+ 'submitted' => [],
'errors' => $this->errors,
- );
+ ];
}
return $output;
@@ -321,10 +341,10 @@ class TopicSummaryBlock extends AbstractBlock {
!$this->permissions->isBoardAllowed( $boardWorkflow, 'view-topic-summary' )
) {
$this->addError( 'permissions', $this->context->msg( 'flow-error-not-allowed' ) );
- return array();
+ return [];
}
- $output = array();
+ $output = [];
$formatter = Container::get( 'formatter.revision' );
$formatter->setContentFormat( $format );
@@ -337,20 +357,20 @@ class TopicSummaryBlock extends AbstractBlock {
$urlGenerator = Container::get( 'url_generator' );
$title = $this->workflow->getArticleTitle();
$workflowId = $this->workflow->getId();
- $output['revision'] = array(
- 'actions' => array(
+ $output['revision'] = [
+ 'actions' => [
'summarize' => $urlGenerator->editTopicSummaryAction(
$title,
$workflowId
)
- ),
- 'links' => array(
+ ],
+ 'links' => [
'topic' => $urlGenerator->topicLink(
$title,
$workflowId
)
- )
- );
+ ]
+ ];
}
return $output;
}
@@ -392,12 +412,12 @@ class TopicSummaryBlock extends AbstractBlock {
} else {
$key = 'flow-topic-html-title';
}
- $out->setHtmlTitle( $out->msg( $key, array(
+ $out->setHtmlTitle( $out->msg( $key, [
// This must be a rawParam to not expand {{foo}} in the title, it must
// not be htmlspecialchar'd because OutputPage::setHtmlTitle handles that.
- Message::rawParam( $topic->getContent( 'wikitext' ) ),
+ Message::rawParam( $topic->getContent( 'topic-title-plaintext' ) ),
$title->getPrefixedText()
- ) ) );
+ ] ) );
} else {
$out->setHtmlTitle( $title->getPrefixedText() );
}
diff --git a/Flow/includes/BlockFactory.php b/Flow/includes/BlockFactory.php
index 8c16d7fa..b6f91402 100644
--- a/Flow/includes/BlockFactory.php
+++ b/Flow/includes/BlockFactory.php
@@ -10,7 +10,7 @@ use Flow\Block\TopicSummaryBlock;
use Flow\Block\BoardHistoryBlock;
use Flow\Model\Workflow;
use Flow\Data\ManagerGroup;
-use Flow\Exception\InvalidInputException;
+use Flow\Exception\DataModelException;
use Flow\Exception\InvalidDataException;
use Flow\Repository\RootPostLoader;
@@ -25,50 +25,43 @@ class BlockFactory {
*/
protected $rootPostLoader;
- /**
- * @var FlowActions
- */
- protected $actions;
-
public function __construct(
ManagerGroup $storage,
- RootPostLoader $rootPostLoader,
- FlowActions $actions
+ RootPostLoader $rootPostLoader
) {
$this->storage = $storage;
$this->rootPostLoader = $rootPostLoader;
- $this->actions = $actions;
}
/**
* @param Workflow $workflow
* @return AbstractBlock[]
- * @throws InvalidInputException When the workflow type is unrecognized
+ * @throws DataModelException When the workflow type is unrecognized
* @throws InvalidDataException When multiple blocks share the same name
*/
public function createBlocks( Workflow $workflow ) {
- switch( $workflow->getType() ) {
+ switch ( $workflow->getType() ) {
case 'discussion':
- $blocks = array(
+ $blocks = [
new HeaderBlock( $workflow, $this->storage ),
new TopicListBlock( $workflow, $this->storage ),
- new BoardHistoryBlock( $workflow, $this->storage, $this->actions ),
- );
+ new BoardHistoryBlock( $workflow, $this->storage ),
+ ];
break;
case 'topic':
- $blocks = array(
- new TopicBlock( $workflow, $this->storage, $this->rootPostLoader, $this->actions ),
+ $blocks = [
+ new TopicBlock( $workflow, $this->storage, $this->rootPostLoader ),
new TopicSummaryBlock( $workflow, $this->storage ),
- );
+ ];
break;
default:
- throw new InvalidInputException( 'Not Implemented', 'invalid-definition' );
+ throw new DataModelException( 'Not Implemented', 'process-data' );
break;
}
- $return = array();
+ $return = [];
/** @var AbstractBlock[] $blocks */
foreach ( $blocks as $block ) {
if ( isset( $return[$block->getName()] ) ) {
diff --git a/Flow/includes/BoardMover.php b/Flow/includes/BoardMover.php
index 6c1ee9d4..0f32d2b9 100644
--- a/Flow/includes/BoardMover.php
+++ b/Flow/includes/BoardMover.php
@@ -3,7 +3,6 @@
namespace Flow;
use DatabaseBase;
-use Flow\Data\BufferedCache;
use Flow\Data\ManagerGroup;
use Flow\Exception\FlowException;
use Flow\Model\Header;
@@ -11,9 +10,6 @@ use Flow\Model\Workflow;
use Title;
use User;
-/**
- *
- */
class BoardMover {
/**
* @var DbFactory
@@ -35,45 +31,50 @@ class BoardMover {
*/
protected $dbw;
- public function __construct( DbFactory $dbFactory, BufferedCache $cache, ManagerGroup $storage, User $nullEditUser ) {
+ public function __construct( DbFactory $dbFactory, ManagerGroup $storage, User $nullEditUser ) {
$this->dbFactory = $dbFactory;
- $this->cache = $cache;
$this->storage = $storage;
$this->nullEditUser = $nullEditUser;
}
/**
- * Collects the workflow and header (if it exists) and puts them into the database. Does
- * not commit yet. It is intended for prepareMove to be called from the TitleMove hook,
- * and committed from TitleMoveComplete hook. This ensures that if some error prevents the
- * core transaction from committing this transaction is also not committed.
- *
- * @param int $oldPageId Page ID before move/change
- * @param Title $newPage Page after move/change
+ * Starts a transaction on the Flow database.
*/
- public function prepareMove( $oldPageId, Title $newPage ) {
- if ( $this->dbw !== null ) {
- throw new FlowException( "Already prepared for move from {$oldPageId} to {$newPage->getArticleID()}" );
- }
-
+ protected function begin() {
// All reads must go through master to help ensure consistency
$this->dbFactory->forceMaster();
// Open a transaction, this will be closed from self::commit.
$this->dbw = $this->dbFactory->getDB( DB_MASTER );
- $this->dbw->begin();
- $this->cache->begin();
+ $this->dbw->startAtomic( __CLASS__ );
+ }
+
+ /**
+ * Collects the workflow and header (if it exists) and puts them into the database. Does
+ * not commit yet. It is intended for move to be called for each move, and commit
+ * to be called at the end the core transaction, via a hook.
+ *
+ * @param int $oldPageId Page ID before move/change
+ * @param Title $newPage Page after move/change
+ * @throws Exception\DataModelException
+ * @throws FlowException
+ */
+ public function move( $oldPageId, Title $newPage ) {
+ if ( $this->dbw === null ) {
+ $this->begin();
+ }
// @todo this loads every topic workflow this board has ever seen,
// would prefer to update db directly but that won't work due to
// the caching layer not getting updated. After dropping Flow\Data\Index\*
// revisit this.
- $found = $this->storage->find( 'Workflow', array(
- 'workflow_wiki' => wfWikiId(),
+ /** @var Workflow[] $found */
+ $found = $this->storage->find( 'Workflow', [
+ 'workflow_wiki' => wfWikiID(),
'workflow_page_id' => $oldPageId,
- ) );
+ ] );
if ( !$found ) {
- throw new FlowException( "Could not locate workflow for $oldPageId" );
+ throw new FlowException( "Could not locate workflow for page ID $oldPageId" );
}
$discussionWorkflow = null;
@@ -82,30 +83,33 @@ class BoardMover {
$discussionWorkflow = $workflow;
}
$workflow->updateFromPageId( $oldPageId, $newPage );
- $this->storage->put( $workflow, array() );
+ $this->storage->put( $workflow, [] );
}
if ( $discussionWorkflow === null ) {
- throw new FlowException( "Main discussion workflow for $oldPageId not found" );
+ throw new FlowException( "Main discussion workflow for page ID $oldPageId not found" );
}
+ /** @var Header[] $found */
$found = $this->storage->find(
'Header',
- array( 'rev_type_id' => $discussionWorkflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $discussionWorkflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( $found ) {
- $this->header = reset( $found );
- $nextHeader = $this->header->newNextRevision(
+ $header = reset( $found );
+ $nextHeader = $header->newNextRevision(
$this->nullEditUser,
- $this->header->getContentRaw(),
- $this->header->getContentFormat(),
+ $header->getContentRaw(),
+ $header->getContentFormat(),
'edit-header',
$newPage
);
- $this->storage->put( $nextHeader, array(
- 'workflow' => $discussionWorkflow,
- ) );
+ if ( $header !== $nextHeader ) {
+ $this->storage->put( $nextHeader, [
+ 'workflow' => $discussionWorkflow,
+ ] );
+ }
}
}
@@ -114,16 +118,18 @@ class BoardMover {
*/
public function commit() {
if ( $this->dbw === null ) {
- throw new FlowException( 'Board move not prepared.');
+ return;
}
try {
- $this->dbw->commit();
- $this->cache->commit();
+ $this->dbw->endAtomic( __CLASS__ );
} catch ( \Exception $e ) {
- $this->dbw->rollback();
- $this->cache->rollback();
+ $this->dbw->rollback( __METHOD__ );
throw $e;
}
+
+ // reset dbw (which is used to check if a move transaction is already in
+ // progress, which is no longer the case)
+ $this->dbw = null;
}
}
diff --git a/Flow/includes/Collection/AbstractCollection.php b/Flow/includes/Collection/AbstractCollection.php
index f69b32ae..81c34b1a 100644
--- a/Flow/includes/Collection/AbstractCollection.php
+++ b/Flow/includes/Collection/AbstractCollection.php
@@ -6,6 +6,7 @@ use Flow\Container;
use Flow\Data\ManagerGroup;
use Flow\Data\ObjectManager;
use Flow\Exception\InvalidDataException;
+use Flow\Exception\FlowException;
use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
use Flow\Model\Workflow;
@@ -24,7 +25,7 @@ abstract class AbstractCollection {
*
* @var AbstractRevision[]
*/
- protected $revisions = array();
+ protected $revisions = [];
/**
* @var Workflow
@@ -37,7 +38,10 @@ abstract class AbstractCollection {
*
* @return string
*/
- abstract public function getRevisionClass();
+ public static function getRevisionClass() {
+ // Workaround to allow static inheritance without strict standards warning from this being abstract
+ throw new FlowException( 'getRevisionClass() must be implemented in the subclass', 'not-implemented' );
+ }
/**
* Returns the id of the workflow this collection is associated with.
@@ -63,11 +67,12 @@ abstract class AbstractCollection {
* @param UUID $uuid
*/
protected function __construct( UUID $uuid ) {
- $this->uuid = $uuid ;
+ $this->uuid = $uuid;
}
/**
- * Instantiate a new object based on its id.
+ * Instantiate a new object based on its type id
+ * (post ID, header ID, etc.)
*
* @param UUID $uuid
* @return AbstractCollection
@@ -77,6 +82,22 @@ abstract class AbstractCollection {
}
/**
+ * Instantiate a new collection based on a revision ID
+ *
+ * @param UUID $revId Revision ID
+ * @return AbstractCollection
+ */
+ public static function newFromRevisionId( UUID $revId ) {
+ $revision = static::getStorage()->get( $revId );
+
+ if ( $revision === null ) {
+ throw new InvalidDataException( 'Revisions for ' . $revId->getAlphadecimal() . ' could not be found', 'invalid-revision-id' );
+ }
+
+ return static::newFromRevision( $revision );
+ }
+
+ /**
* Instantiate a new object based off of an AbstractRevision object.
*
* @param AbstractRevision $revision
@@ -97,9 +118,9 @@ abstract class AbstractCollection {
* @param string|null $class Storage class - defaults to getRevisionClass()
* @return ObjectManager
*/
- public function getStorage( $class = null ) {
+ public static function getStorage( $class = null ) {
if ( !$class ) {
- $class = $this->getRevisionClass();
+ $class = static::getRevisionClass();
}
/** @var ManagerGroup $storage */
@@ -116,13 +137,13 @@ abstract class AbstractCollection {
public function getAllRevisions() {
if ( !$this->revisions ) {
/** @var AbstractRevision[] $revisions */
- $revisions = $this->getStorage()->find(
- array( 'rev_type_id' => $this->uuid ),
- array( 'sort' => 'rev_id', 'order' => 'DESC' )
+ $revisions = self::getStorage()->find(
+ [ 'rev_type_id' => $this->uuid ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC' ]
);
if ( !$revisions ) {
- throw new InvalidDataException( 'Revisions for ' . $this->uuid->getAlphadecimal() . ' could not be found', 'invalid-revision-id' );
+ throw new InvalidDataException( 'Revisions for ' . $this->uuid->getAlphadecimal() . ' could not be found', 'invalid-type-id' );
}
foreach ( $revisions as $revision ) {
@@ -137,7 +158,7 @@ abstract class AbstractCollection {
* Returns the revision with the given id.
*
* @param UUID $uuid
- * @return AbstractRevision|null null if there is no such revision
+ * @return AbstractRevision|null null if there is no such revision in the collection
*/
public function getRevision( UUID $uuid ) {
// make sure all revisions have been loaded
@@ -227,7 +248,7 @@ abstract class AbstractCollection {
if ( !$this->workflow ) {
$uuid = $this->getWorkflowId();
- $this->workflow = $this->getStorage( 'Flow\\Model\\Workflow' )->get( $uuid );
+ $this->workflow = self::getStorage( 'Flow\\Model\\Workflow' )->get( $uuid );
if ( !$this->workflow ) {
throw new InvalidDataException( 'Invalid workflow: ' . $uuid->getAlphadecimal(), 'invalid-workflow' );
}
@@ -237,6 +258,6 @@ abstract class AbstractCollection {
}
public function getBoardWorkflow() {
- return $this->getStorage( 'Flow\\Model\\Workflow' )->get( $this->getBoardWorkflowId() );
+ return self::getStorage( 'Flow\\Model\\Workflow' )->get( $this->getBoardWorkflowId() );
}
}
diff --git a/Flow/includes/Collection/HeaderCollection.php b/Flow/includes/Collection/HeaderCollection.php
index 3f4eefa7..592ec9b5 100644
--- a/Flow/includes/Collection/HeaderCollection.php
+++ b/Flow/includes/Collection/HeaderCollection.php
@@ -3,7 +3,7 @@
namespace Flow\Collection;
class HeaderCollection extends LocalCacheAbstractCollection {
- public function getRevisionClass() {
+ public static function getRevisionClass() {
return 'Flow\\Model\\Header';
}
diff --git a/Flow/includes/Collection/LocalCacheAbstractCollection.php b/Flow/includes/Collection/LocalCacheAbstractCollection.php
index 4d958c77..494e9df2 100644
--- a/Flow/includes/Collection/LocalCacheAbstractCollection.php
+++ b/Flow/includes/Collection/LocalCacheAbstractCollection.php
@@ -26,7 +26,7 @@ abstract class LocalCacheAbstractCollection extends AbstractCollection {
// if we have not yet loaded everything, just clear what we have and
// fetch from cache
if ( !$this->loaded() ) {
- $this->revisions = array();
+ $this->revisions = [];
}
return parent::getAllRevisions();
@@ -64,8 +64,8 @@ abstract class LocalCacheAbstractCollection extends AbstractCollection {
$previousId = $oldest->getPrevRevisionId();
// check if it's in local storage already
- if ( $previousId && $this->getStorage()->got( $previousId ) ) {
- $revision = $this->getStorage()->get( $previousId );
+ if ( $previousId && self::getStorage()->got( $previousId ) ) {
+ $revision = self::getStorage()->get( $previousId );
// add this revision to revisions array
$this->revisions[$previousId->getAlphadecimal()] = $revision;
@@ -101,14 +101,14 @@ abstract class LocalCacheAbstractCollection extends AbstractCollection {
return reset( $this->revisions );
}
- $attributes = array( 'rev_type_id' => $this->uuid );
- $options = array( 'sort' => 'rev_id', 'limit' => 1, 'order' => 'DESC' );
+ $attributes = [ 'rev_type_id' => $this->uuid ];
+ $options = [ 'sort' => 'rev_id', 'limit' => 1, 'order' => 'DESC' ];
- if ( $this->getStorage()->found( $attributes, $options ) ) {
+ if ( self::getStorage()->found( $attributes, $options ) ) {
// if last revision is already known in local cache, fetch it
- $revision = $this->getStorage()->find( $attributes, $options );
+ $revision = self::getStorage()->find( $attributes, $options );
if ( !$revision ) {
- throw new InvalidDataException( 'Last revision for ' . $this->uuid->getAlphadecimal() . ' could not be found', 'invalid-revision-id' );
+ throw new InvalidDataException( 'Last revision for ' . $this->uuid->getAlphadecimal() . ' could not be found', 'invalid-type-id' );
}
$revision = reset( $revision );
$this->revisions[$revision->getRevisionId()->getAlphadecimal()] = $revision;
@@ -144,7 +144,6 @@ abstract class LocalCacheAbstractCollection extends AbstractCollection {
return $this->getRevision( UUID::create( $ids[$next] ) );
}
-
/**
* Returns true if all revisions have been loaded into $this->revisions.
*
diff --git a/Flow/includes/Collection/PostCollection.php b/Flow/includes/Collection/PostCollection.php
index cd2b4055..26e8a1d5 100644
--- a/Flow/includes/Collection/PostCollection.php
+++ b/Flow/includes/Collection/PostCollection.php
@@ -13,7 +13,7 @@ class PostCollection extends LocalCacheAbstractCollection {
*/
protected $rootId;
- public function getRevisionClass() {
+ public static function getRevisionClass() {
return 'Flow\\Model\\PostRevision';
}
@@ -37,11 +37,11 @@ class PostCollection extends LocalCacheAbstractCollection {
* @throws InvalidDataException
*/
public function getBoardWorkflowId() {
- $found = $this->getStorage( 'Flow\\Model\\TopicListEntry' )->find(
+ $found = self::getStorage( 'Flow\\Model\\TopicListEntry' )->find(
// uses flow_topic_list:topic index, for topic->board lookups
- array( 'topic_id' => $this->getWorkflowId() )
+ [ 'topic_id' => $this->getWorkflowId() ]
);
- if ( !$found) {
+ if ( !$found ) {
throw new InvalidDataException( 'No TopicListEntry founds for topic id ' . $this->getWorkflowId()->getAlphadecimal(), 'invalid-workflow' );
}
diff --git a/Flow/includes/Collection/PostSummaryCollection.php b/Flow/includes/Collection/PostSummaryCollection.php
index 02275c78..4286f8a0 100644
--- a/Flow/includes/Collection/PostSummaryCollection.php
+++ b/Flow/includes/Collection/PostSummaryCollection.php
@@ -11,7 +11,7 @@ class PostSummaryCollection extends LocalCacheAbstractCollection {
*/
protected $rootId;
- public function getRevisionClass() {
+ public static function getRevisionClass() {
return 'Flow\\Model\\PostSummary';
}
diff --git a/Flow/includes/Content/BoardContent.php b/Flow/includes/Content/BoardContent.php
index 0be2c298..e5cad4e8 100644
--- a/Flow/includes/Content/BoardContent.php
+++ b/Flow/includes/Content/BoardContent.php
@@ -9,7 +9,6 @@ use Flow\Container;
use Flow\Exception\UnknownWorkflowIdException;
use Flow\LinksTableUpdater;
use Flow\Model\UUID;
-use Flow\RevisionActionPermissions;
use Flow\View;
use Flow\WorkflowLoaderFactory;
use OutputPage;
@@ -159,9 +158,12 @@ class BoardContent extends \AbstractContent {
*
* @return ParserOutput
*/
- public function getParserOutput( Title $title, $revId = null,
- ParserOptions $options = null, $generateHtml = true )
- {
+ public function getParserOutput(
+ Title $title,
+ $revId = null,
+ ParserOptions $options = null,
+ $generateHtml = true
+ ) {
if ( $generateHtml ) {
try {
global $wgUser;
diff --git a/Flow/includes/Content/BoardContentHandler.php b/Flow/includes/Content/BoardContentHandler.php
index 49faf0e5..4c6d9962 100644
--- a/Flow/includes/Content/BoardContentHandler.php
+++ b/Flow/includes/Content/BoardContentHandler.php
@@ -17,7 +17,7 @@ class BoardContentHandler extends \ContentHandler {
throw new MWException( __CLASS__." initialised for invalid content model" );
}
- parent::__construct( CONTENT_MODEL_FLOW_BOARD, array( CONTENT_FORMAT_JSON ) );
+ parent::__construct( CONTENT_MODEL_FLOW_BOARD, [ CONTENT_FORMAT_JSON ] );
}
public function isSupportedFormat( $format ) {
@@ -41,11 +41,11 @@ class BoardContentHandler extends \ContentHandler {
* @throws MWException
*/
public function serializeContent( \Content $content, $format = null ) {
- if ( ! $content instanceof BoardContent ) {
+ if ( !$content instanceof BoardContent ) {
throw new MWException( "Expected a BoardContent object, got a " . get_class( $content ) );
}
- $info = array();
+ $info = [];
if ( $content->getWorkflowId() ) {
$info['flow-workflow'] = $content->getWorkflowId()->getAlphaDecimal();
@@ -62,16 +62,17 @@ class BoardContentHandler extends \ContentHandler {
* @param string $blob Serialized form of the content
* @param string $format The format used for serialization
*
- * @return Content The Content object created by deserializing $blob
+ * @return BoardContent The Content object created by deserializing $blob
*/
public function unserializeContent( $blob, $format = null ) {
$info = FormatJson::decode( $blob, true );
$uuid = null;
if ( !$info ) {
- // For transition from wikitext-type pages
- // Make a plain content object and then when we get a chance
- // we can insert a proper object.
+ // Temporary: Fix T167198 and instead throw an exception, to
+ // prevent corruption from software that does not understand
+ // Flow/content models.
+
return $this->makeEmptyContent();
} elseif ( isset( $info['flow-workflow'] ) ) {
$uuid = UUID::create( $info['flow-workflow'] );
@@ -115,14 +116,14 @@ class BoardContentHandler extends \ContentHandler {
*
* @since 1.21
*
- * @return array Always an empty array.
+ * @return array Associative array mapping action names to handler callables
*/
public function getActionOverrides() {
/** @var FlowActions $actions */
$actions = Container::get( 'flow_actions' );
- $output = array();
+ $output = [];
- foreach( $actions->getActions() as $action ) {
+ foreach ( $actions->getActions() as $action ) {
$actionData = $actions->getValue( $action );
if ( !is_array( $actionData ) ) {
continue;
@@ -133,7 +134,7 @@ class BoardContentHandler extends \ContentHandler {
}
if ( $actionData['handler-class'] === 'Flow\Actions\FlowAction' ) {
- $output[$action] = function( Page $page, IContextSource $source ) use ( $action ) {
+ $output[$action] = function ( Page $page, IContextSource $source ) use ( $action ) {
return new FlowAction( $page, $source, $action );
};
} else {
diff --git a/Flow/includes/Conversion/Utils.php b/Flow/includes/Conversion/Utils.php
new file mode 100644
index 00000000..c3f2eced
--- /dev/null
+++ b/Flow/includes/Conversion/Utils.php
@@ -0,0 +1,474 @@
+<?php
+
+namespace Flow\Conversion;
+
+use DOMDocument;
+use DOMNode;
+use FauxResponse;
+use Flow\Container;
+use Flow\Exception\FlowException;
+use Flow\Exception\NoParserException;
+use Flow\Exception\WikitextException;
+use Language;
+use Linker;
+use MultiHttpClient;
+use OutputPage;
+use RequestContext;
+use Sanitizer;
+use Title;
+use User;
+use VirtualRESTServiceClient;
+
+abstract class Utils {
+ /**
+ * Convert from/to wikitext <=> html or topic-title-wikitext => topic-title-html.
+ * Only these pairs are supported. html => wikitext requires Parsoid, and
+ * topic-title-html => topic-title-wikitext is not supported.
+ *
+ * @param string $from Format of content to convert: html|wikitext|topic-title-wikitext
+ * @param string $to Format to convert to: html|wikitext|topic-title-html
+ * @param string $content
+ * @param Title $title
+ * @return string
+ * @throws WikitextException When the requested conversion is unsupported
+ * @throws NoParserException When the conversion fails
+ */
+ public static function convert( $from, $to, $content, Title $title ) {
+ if ( $from === $to || $content === '' ) {
+ return $content;
+ }
+
+ if ( $from === 'wt' ) {
+ $from = 'wikitext';
+ }
+
+ if ( $from === 'wikitext' || $from === 'html' ) {
+ if ( $to === 'wikitext' || $to === 'html' ) {
+ if ( self::isParsoidConfigured() ) {
+ return self::parsoid( $from, $to, $content, $title );
+ } else {
+ return self::parser( $from, $to, $content, $title );
+ }
+ } else {
+ throw new WikitextException( "Conversion from '$from' to '$to' was requested, but this is not supported." );
+ }
+ } else {
+ return self::commentParser( $from, $to, $content );
+ }
+ }
+
+ /**
+ * Basic conversion of html to plaintext for use in recent changes, history,
+ * and other places where a roundtrip is undesired.
+ *
+ * @param string $html
+ * @param int|null $truncateLength Maximum length (including ellipses) or null for whole string.
+ * @param Language $lang Language to use for truncation. Defaults to $wgLang
+ * @return string plaintext
+ */
+ public static function htmlToPlaintext( $html, $truncateLength = null, Language $lang = null ) {
+ /** @var Language $wgLang */
+ global $wgLang;
+
+ $plain = trim( Sanitizer::stripAllTags( $html ) );
+
+ if ( $truncateLength === null ) {
+ return $plain;
+ } else {
+ $lang = $lang ?: $wgLang;
+ return $lang->truncate( $plain, $truncateLength );
+ }
+ }
+
+ /**
+ * Convert from/to wikitext/html via Parsoid/RESTBase.
+ *
+ * This will assume Parsoid/RESTBase is installed and configured.
+ *
+ * @param string $from Format of content to convert: html|wikitext
+ * @param string $to Format to convert to: html|wikitext
+ * @param string $content
+ * @param Title $title
+ * @return string
+ * @throws NoParserException When Parsoid/RESTBase operation fails
+ * @throws WikitextException When conversion is unsupported
+ */
+ protected static function parsoid( $from, $to, $content, Title $title ) {
+ global $wgVersion;
+
+ $serviceClient = self::getServiceClient();
+
+ if ( $from !== 'html' && $from !== 'wikitext' ) {
+ throw new WikitextException( 'Unknown source format: ' . $from, 'process-wikitext' );
+ }
+
+ $prefixedDbTitle = $title->getPrefixedDBkey();
+ $params = [
+ $from => $content,
+ 'body_only' => 'true',
+ ];
+ if ( $from === 'html' ) {
+ $params['scrub_wikitext'] = 'true';
+ }
+ $url = '/restbase/local/v1/transform/' . $from . '/to/' . $to . '/' .
+ urlencode( $prefixedDbTitle );
+ $request = [
+ 'method' => 'POST',
+ 'url' => $url,
+ 'body' => $params,
+ 'headers' => [
+ 'Accept' => 'text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/HTML/1.2.1"',
+ 'User-Agent' => "Flow-MediaWiki/$wgVersion",
+ ],
+ ];
+ $response = $serviceClient->run( $request );
+ if ( $response['code'] !== 200 ) {
+ if ( $response['error'] !== '' ) {
+ $statusMsg = $response['error'];
+ } else {
+ $statusMsg = $response['code'];
+ }
+ $vrsInfo = $serviceClient->getMountAndService( '/restbase/' );
+ $serviceName = $vrsInfo[1] ? $vrsInfo[1]->getName() : 'VRS service';
+ $msg = "Request to " . $serviceName . " for \"$from\" to \"$to\" conversion of content connected to title \"$prefixedDbTitle\" failed: $statusMsg";
+ Container::get( 'default_logger' )->error(
+ 'Request to {service} for "{sourceFormat}" to "{targetFormat}" conversion of content connected to title "{title}" failed. Code: {code}, Reason: "{reason}", Body: "{body}", Error: "{error}"',
+ [
+ 'service' => $serviceName,
+ 'sourceFormat' => $from,
+ 'targetFormat' => $to,
+ 'title' => $prefixedDbTitle,
+ 'code' => $response['code'],
+ 'reason' => $response['reason'],
+ 'error' => $response['error'], // This is sometimes/always empty string
+ 'headers' => $response['headers'],
+ 'body' => $response['body'],
+ 'response' => $response,
+ ]
+ );
+ throw new NoParserException( $msg, 'process-wikitext' );
+ }
+
+ $content = $response['body'];
+ // HACK remove trailing newline inserted by Parsoid (T106925)
+ if ( $to === 'wikitext' ) {
+ $content = preg_replace( '/\\n$/', '', $content );
+ }
+ return $content;
+ }
+
+ /**
+ * Convert from/to topic-title-wikitext/topic-title-html using Linker::formatLinksInComment
+ *
+ * @param string $from Format of content to convert: topic-title-wikitext
+ * @param string $to Format of content to convert to: topic-title-html
+ * @param string $content Content to convert, in topic-title-wikitext format.
+ * @return string $content in HTML
+ * @throws WikitextException
+ */
+ protected static function commentParser( $from, $to, $content ) {
+ if (
+ $from !== 'topic-title-wikitext' ||
+ ( $to !== 'topic-title-html' && $to !== 'topic-title-plaintext' )
+ ) {
+ throw new WikitextException( "Conversion from '$from' to '$to' was requested, but this is not supported." );
+ }
+
+ $html = Linker::formatLinksInComment( Sanitizer::escapeHtmlAllowEntities( $content ) );
+ if ( $to === 'topic-title-plaintext' ) {
+ return self::htmlToPlaintext( $html );
+ } else {
+ return $html;
+ }
+ }
+
+ /**
+ * Convert from/to wikitext/html using Parser.
+ *
+ * This only supports wikitext to HTML.
+ *
+ * @param string $from Format of content to convert: wikitext
+ * @param string $to Format to convert to: html
+ * @param string $content
+ * @param Title $title
+ * @return string
+ * @throws WikitextException When the conversion is unsupported
+ */
+ protected static function parser( $from, $to, $content, Title $title ) {
+ if ( $from !== 'wikitext' || $to !== 'html' ) {
+ throw new WikitextException( "Conversion from '$from' to '$to' was requested, but core's Parser only supports 'wikitext' to 'html' conversion", 'process-wikitext' );
+ }
+
+ global $wgParser;
+
+ $options = new \ParserOptions;
+ $options->setTidy( true );
+ $options->setEditSection( false );
+
+ $output = $wgParser->parse( $content, $title, $options );
+ return $output->getText();
+ }
+
+ /**
+ * Check to see whether a Parsoid or RESTBase service is configured.
+ *
+ * @return bool
+ */
+ public static function isParsoidConfigured() {
+ try {
+ self::getServiceClient();
+ return true;
+ } catch ( NoParserException $e ) {
+ return false;
+ }
+ }
+
+ /**
+ * @var VirtualRESTServiceClient
+ */
+ protected static $serviceClient = null;
+
+ /**
+ * Returns Flow's Virtual REST Service for Parsoid/RESTBase.
+ * The Parsoid/RESTBase service will be mounted at /restbase/
+ * and will answer RESTBase v1 API requests.
+ *
+ * @return VirtualRESTServiceClient
+ * @throws NoParserException When Parsoid/RESTBase is unconfigured
+ */
+ protected static function getServiceClient() {
+ if ( self::$serviceClient === null ) {
+ $sc = new VirtualRESTServiceClient( new MultiHttpClient( [] ) );
+ $sc->mount( '/restbase/', self::getVRSObject() );
+ self::$serviceClient = $sc;
+ }
+ return self::$serviceClient;
+ }
+
+ /**
+ * Creates the Virtual REST Service object to be used in Flow's
+ * API calls. The method determines whether to instantiate a
+ * ParsoidVirtualRESTService or a RestbaseVirtualRESTService
+ * object based on configuration directives: if
+ * `$wgVirtualRestConfig['modules']['restbase']` is defined,
+ * RESTBase is chosen; otherwise Parsoid is used.
+ * For backwards compatibility, $wgFlowParsoid* variables are used
+ * to specify a Parsoid configuration as a fall back.
+ *
+ * @return \VirtualRESTService the VirtualRESTService object to use
+ * @throws NoParserException When Parsoid/RESTBase is not configured
+ */
+ private static function getVRSObject() {
+ global $wgVirtualRestConfig, $wgFlowParsoidURL, $wgFlowParsoidPrefix,
+ $wgFlowParsoidTimeout, $wgFlowParsoidForwardCookies,
+ $wgFlowParsoidHTTPProxy;
+
+ // the params array to create the service object with
+ $params = [];
+ // the VRS class to use; defaults to Parsoid
+ $class = 'ParsoidVirtualRESTService';
+ // the global virtual rest service config object, if any
+ $vrs = $wgVirtualRestConfig;
+ // HACK: don't use RESTbase because it'll drop data-parsoid, see T115236
+ /*if ( isset( $vrs['modules'] ) && isset( $vrs['modules']['restbase'] ) ) {
+ // if restbase is available, use it
+ $params = $vrs['modules']['restbase'];
+ $params['parsoidCompat'] = false; // backward compatibility
+ $class = 'RestbaseVirtualRESTService';
+ } else
+ */
+ if ( isset( $vrs['modules'] ) && isset( $vrs['modules']['parsoid'] ) ) {
+ // there's a global parsoid config, use it next
+ $params = $vrs['modules']['parsoid'];
+ $params['restbaseCompat'] = true;
+ } else {
+ // no global modules defined, fall back to old defaults
+ if ( !$wgFlowParsoidURL ) {
+ throw new NoParserException( 'Flow Parsoid configuration is unavailable', 'process-wikitext' );
+ }
+ $params = [
+ 'URL' => $wgFlowParsoidURL,
+ 'prefix' => $wgFlowParsoidPrefix,
+ 'timeout' => $wgFlowParsoidTimeout,
+ 'HTTPProxy' => $wgFlowParsoidHTTPProxy,
+ 'forwardCookies' => $wgFlowParsoidForwardCookies
+ ];
+ }
+ // merge the global and service-specific params
+ if ( isset( $vrs['global'] ) ) {
+ $params = array_merge( $vrs['global'], $params );
+ }
+ // set up cookie forwarding
+ if ( $params['forwardCookies'] && !User::isEveryoneAllowed( 'read' ) ) {
+ if ( PHP_SAPI === 'cli' ) {
+ // From the command line we need to generate a cookie
+ $params['forwardCookies'] = self::generateForwardedCookieForCli();
+ } else {
+ $params['forwardCookies'] = RequestContext::getMain()->getRequest()->getHeader( 'Cookie' );
+ }
+ } else {
+ $params['forwardCookies'] = false;
+ }
+ // create the VRS object and return it
+ return new $class( $params );
+ }
+
+ /**
+ * Turns given $content string into a DOMDocument object.
+ *
+ * Note that, by default, $content will be prefixed with <?xml encoding="utf-8"?> to force
+ * libxml to interpret the content as UTF-8. If for some reason you don't want this to happen,
+ * or you are certain that your input already has <?xml encoding="utf-8"?> or
+ * <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> , then you can disable
+ * this behavior by setting $utf8Fragment=false to disable this behavior.
+ *
+ * Some libxml errors are forgivable, libxml errors that aren't
+ * ignored will throw a WikitextException.
+ *
+ * The default error codes allowed are:
+ * 9 - allow illegal characters (they are removed, but this option means it
+ * doesn't trigger an error.
+ * 76 - allow unexpected end tag. This is typically old wikitext using deprecated tags.
+ * 513 - allow multiple tags with same id
+ * 801 - allow unrecognized tags like figcaption
+ *
+ * @param string $content
+ * @param bool[optional] $utf8Fragment If true, prefix $content with <?xml encoding="utf-8"?>
+ * @param array[optional] $ignoreErrorCodes
+ * @return DOMDocument
+ * @throws WikitextException
+ * @see http://www.xmlsoft.org/html/libxml-xmlerror.html
+ */
+ public static function createDOM( $content, $utf8Fragment = true, $ignoreErrorCodes = [ 9, 76, 513, 801 ] ) {
+ $dom = new DOMDocument();
+
+ // Otherwise the parser may attempt to load the dtd from an external source.
+ // See: https://www.mediawiki.org/wiki/XML_External_Entity_Processing
+ $loadEntities = libxml_disable_entity_loader( true );
+
+ // don't output warnings
+ $useErrors = libxml_use_internal_errors( true );
+
+ // Work around DOMDocument's morbid insistence on using iso-8859-1
+ // Even $dom = new DOMDocument( '1.0', 'utf-8' ); doesn't work, you have to specify
+ // encoding ="utf-8" in the string fed to loadHTML()
+ $html = ( $utf8Fragment ? '<?xml encoding="utf-8"?>' : '' ) . $content;
+ $dom->loadHTML( $html, LIBXML_PARSEHUGE );
+
+ libxml_disable_entity_loader( $loadEntities );
+
+ // check error codes; if not in the supplied list of ignorable errors,
+ // throw an exception
+ $errors = array_filter(
+ libxml_get_errors(),
+ function ( $error ) use( $ignoreErrorCodes ) {
+ return !in_array( $error->code, $ignoreErrorCodes );
+ }
+ );
+
+ // restore libxml state before anything else
+ libxml_clear_errors();
+ libxml_use_internal_errors( $useErrors );
+
+ if ( $errors ) {
+ throw new WikitextException(
+ implode(
+ "\n",
+ array_map(
+ function ( $error ) {
+ return $error->message;
+ },
+ $errors
+ )
+ ) . "\n\nFrom source content:\n" . $content,
+ 'process-wikitext'
+ );
+ }
+
+ return $dom;
+ }
+
+ /**
+ * Handler for FlowAddModules, avoids rest of Flow having to be aware if
+ * Parsoid is in use.
+ *
+ * @param OutputPage $out OutputPage object
+ * @return bool
+ */
+ public static function onFlowAddModules( OutputPage $out ) {
+ if ( self::isParsoidConfigured() ) {
+ // The module is only necessary when we are using parsoid.
+ // XXX We only need the Parsoid CSS if some content being
+ // rendered has getContentFormat() === 'html'.
+ $out->addModuleStyles( [
+ 'mediawiki.skinning.content.parsoid',
+ 'ext.cite.style',
+ ] );
+ }
+
+ return true;
+ }
+
+ /**
+ * Retrieves the html of the nodes children.
+ *
+ * @param DOMNode|null $node
+ * @return string html of the nodes children
+ */
+ public static function getInnerHtml( DOMNode $node = null ) {
+ $html = [];
+ if ( $node ) {
+ $dom = $node instanceof DOMDocument ? $node : $node->ownerDocument;
+ foreach ( $node->childNodes as $child ) {
+ $html[] = $dom->saveHTML( $child );
+ }
+ }
+ return implode( '', $html );
+ }
+
+ /**
+ * Subpage links from Parsoid don't contain any direct context, its applied via
+ * a <base href="..."> tag, so here we apply a similar rule resolving against
+ * $title
+ *
+ * @param string $text
+ * @param Title $title Title to resolve relative links against
+ * @return Title|null
+ */
+ public static function createRelativeTitle( $text, Title $title ) {
+ // currently parsoid always uses enough ../ or ./ to go
+ // back to the root, a bit of a kludge but just assume we
+ // can strip and will end up with a non-relative text.
+ $text = preg_replace( '|^(\.\.?/)+|', '', $text );
+
+ if ( $text && ( $text[0] === '/' || $text[0] === '#' ) ) {
+ return Title::newFromText( $title->getDBkey() . $text, $title->getNamespace() );
+ }
+
+ return Title::newFromText( $text );
+ }
+
+ // @todo move into FauxRequest
+ public static function generateForwardedCookieForCli() {
+ global $wgCookiePrefix;
+
+ $user = Container::get( 'occupation_controller' )->getTalkpageManager();
+ // This takes a request object, but doesnt set the cookies against it.
+ // patch at https://gerrit.wikimedia.org/r/177403
+ $user->setCookies( null, null, /* rememberMe */ true );
+ $response = RequestContext::getMain()->getRequest()->response();
+ if ( !$response instanceof FauxResponse ) {
+ throw new FlowException( 'Expected a FauxResponse in CLI environment' );
+ }
+ $cookies = $response->getCookies();
+
+ // now we need to convert the array into the cookie format of
+ // foo=bar; baz=bang
+ $output = [];
+ foreach ( $cookies as $key => $value ) {
+ $output[] = "$wgCookiePrefix$key={$value['value']}";
+ }
+
+ return implode( '; ', $output );
+ }
+}
diff --git a/Flow/includes/Data/Compactor/FeatureCompactor.php b/Flow/includes/Data/Compactor/FeatureCompactor.php
index cc2dda93..13c9157e 100644
--- a/Flow/includes/Data/Compactor/FeatureCompactor.php
+++ b/Flow/includes/Data/Compactor/FeatureCompactor.php
@@ -47,7 +47,7 @@ class FeatureCompactor implements Compactor {
* @return array
*/
public function compactRows( array $rows ) {
- return array_map( array( $this, 'compactRow' ), $rows );
+ return array_map( [ $this, 'compactRow' ], $rows );
}
/**
@@ -66,7 +66,11 @@ class FeatureCompactor implements Compactor {
*/
public function expandCacheResult( array $cached, array $keyToQuery ) {
foreach ( $cached as $key => $rows ) {
- $query = $keyToQuery[$key];
+ $query = isset( $keyToQuery[$key] ) ? $keyToQuery[$key] : [];
+ if ( !is_array( $query ) ) {
+ throw new DataModelException( 'Cached data for "' . $key . '"" should map to a valid query: ' . print_r( $query, true ), 'process-data' );
+ }
+
foreach ( $query as $foo ) {
if ( $foo !== null && !is_scalar( $foo ) ) {
throw new DataModelException( 'Query values to merge with cache contains objects, should be scalar values: ' . print_r( $foo, true ), 'process-data' );
diff --git a/Flow/includes/Data/Compactor/ShallowCompactor.php b/Flow/includes/Data/Compactor/ShallowCompactor.php
index 7f0f2011..685ea39d 100644
--- a/Flow/includes/Data/Compactor/ShallowCompactor.php
+++ b/Flow/includes/Data/Compactor/ShallowCompactor.php
@@ -56,7 +56,7 @@ class ShallowCompactor implements Compactor {
* @return array
*/
public function compactRows( array $rows ) {
- return array_map( array( $this, 'compactRow' ), $rows );
+ return array_map( [ $this, 'compactRow' ], $rows );
}
/**
@@ -78,7 +78,7 @@ class ShallowCompactor implements Compactor {
$duplicator = new ResultDuplicator( $this->shallow->getPrimaryKeyColumns(), 2 );
foreach ( $results as $i => $rows ) {
foreach ( $rows as $j => $row ) {
- $duplicator->add( $row, array( $i, $j ) );
+ $duplicator->add( $row, [ $i, $j ] );
}
}
@@ -94,6 +94,7 @@ class ShallowCompactor implements Compactor {
$duplicator = $this->getResultDuplicator( $cached, $keyToQuery );
$queries = $duplicator->getUniqueQueries();
$innerResult = $this->shallow->findMulti( $queries );
+
foreach ( $innerResult as $rows ) {
// __construct guaranteed the shallow backing index is a unique, so $first is only result
$first = reset( $rows );
diff --git a/Flow/includes/Data/FlowObjectCache.php b/Flow/includes/Data/FlowObjectCache.php
new file mode 100644
index 00000000..74479f5d
--- /dev/null
+++ b/Flow/includes/Data/FlowObjectCache.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Flow\Data;
+
+use Flow\DbFactory;
+use WANObjectCache;
+
+class FlowObjectCache {
+ /**
+ * @var WANObjectCache
+ */
+ protected $cache;
+
+ /**
+ * @var int
+ */
+ protected $ttl = 0;
+
+ /**
+ * @var array
+ */
+ protected $setOptions;
+
+ /**
+ * @param WANObjectCache $cache The cache implementation to back this buffer with
+ * @param DbFactory $dbFactory
+ * @param int $ttl The default length of time to cache data. 0 for LRU.
+ */
+ public function __construct( WANObjectCache $cache, DbFactory $dbFactory, $ttl = 0 ) {
+ $this->ttl = $ttl;
+ $this->cache = $cache;
+ $this->setOptions = \Database::getCacheSetOptions( $dbFactory->getDB( DB_SLAVE ) );
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ public function get( $key ) {
+ return $this->cache->get( $key );
+ }
+
+ /**
+ * @param array $keys
+ * @return array
+ */
+ public function getMulti( array $keys ) {
+ return $this->cache->getMulti( $keys );
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return bool
+ */
+ public function set( $key, $value ) {
+ return $this->cache->set( $key, $value, $this->ttl, $this->setOptions );
+ }
+
+ /**
+ * @param string $key
+ * @return bool
+ */
+ public function delete( $key ) {
+ return $this->cache->delete( $key );
+ }
+}
diff --git a/Flow/includes/Data/Index.php b/Flow/includes/Data/Index.php
index ed05bb29..855b3919 100644
--- a/Flow/includes/Data/Index.php
+++ b/Flow/includes/Data/Index.php
@@ -11,19 +11,19 @@ interface Index extends LifecycleHandler {
*
* @param array $keys A map of k,v pairs to find via equality condition
* @param array[optional] $options Options to use
- * @return array|false Cached subset of data model rows matching the
+ * @return array Cached subset of data model rows matching the
* equality conditions provided in $keys.
*/
- function find( array $keys, array $options = array() );
+ function find( array $keys, array $options = [] );
/**
* Batch together multiple calls to self::find with minimal network round trips.
*
* @param array $queries An array of arrays in the form of $keys parameter of self::find
* @param array[optional] $options Options to use
- * @return array|false Array of arrays in same order as $queries representing batched result set.
+ * @return array[] Array of arrays in same order as $queries representing batched result set.
*/
- function findMulti( array $queries, array $options = array() );
+ function findMulti( array $queries, array $options = [] );
/**
* Returns a boolean true/false if the find()-operation for the given
@@ -36,7 +36,7 @@ interface Index extends LifecycleHandler {
* @param array[optional] $options Options to find()
* @return bool
*/
- public function found( array $attributes, array $options = array() );
+ public function found( array $attributes, array $options = [] );
/**
* Returns a boolean true/false if the findMulti()-operation for the given
@@ -49,10 +49,10 @@ interface Index extends LifecycleHandler {
* @param array[optional] $options Options to find()
* @return bool
*/
- public function foundMulti( array $attributes, array $options = array() );
+ public function foundMulti( array $attributes, array $options = [] );
/**
- * @return integer Maximum number of items in a single index value
+ * @return int Maximum number of items in a single index value
*/
function getLimit();
@@ -73,20 +73,11 @@ interface Index extends LifecycleHandler {
*
* @param array $keys
* @param array $options
- * @return boolean Can the index locate a result for this keys and options pair
+ * @return bool Can the index locate a result for this keys and options pair
*/
function canAnswer( array $keys, array $options );
/**
- * @param array $row
- * @param string $offset
- * @return integer An integer less than, equal to, or greater than zero
- * if $row is considered to be respectively less than, equal to, or
- * greater than $offset
- */
- function compareRowToOffset( array $row, $offset );
-
- /**
* @param object $object
* @param array $row
*/
diff --git a/Flow/includes/Data/Index/BoardHistoryIndex.php b/Flow/includes/Data/Index/BoardHistoryIndex.php
index ef7f93fd..e95f8a06 100644
--- a/Flow/includes/Data/Index/BoardHistoryIndex.php
+++ b/Flow/includes/Data/Index/BoardHistoryIndex.php
@@ -2,17 +2,16 @@
namespace Flow\Data\Index;
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Data\ObjectManager;
use Flow\Data\ObjectMapper;
use Flow\Data\Storage\BoardHistoryStorage;
use Flow\Exception\DataModelException;
-use Flow\Exception\InvalidInputException;
use Flow\Model\AbstractRevision;
-use Flow\Model\Header;
use Flow\Model\PostSummary;
use Flow\Model\PostRevision;
use Flow\Model\TopicListEntry;
+use Flow\Model\UUID;
use Flow\Model\Workflow;
/**
@@ -21,30 +20,29 @@ use Flow\Model\Workflow;
*
* Can be used with Header, PostRevision and PostSummary ObjectMapper's
*/
-class BoardHistoryIndex extends TopKIndex {
-
+abstract class BoardHistoryIndex extends TopKIndex {
/**
* @var ObjectManager Manager for the TopicListEntry model
*/
protected $om;
public function __construct(
- BufferedCache $cache,
+ FlowObjectCache $cache,
BoardHistoryStorage $storage,
ObjectMapper $mapper,
$prefix,
array $indexed,
- array $options = array(),
+ array $options = [],
ObjectManager $om
) {
- if ( $indexed !== array( 'topic_list_id' ) ) {
+ if ( $indexed !== [ 'topic_list_id' ] ) {
throw new DataModelException( __CLASS__ . ' is hardcoded to only index topic_list_id: ' . print_r( $indexed, true ), 'process-data' );
}
parent::__construct( $cache, $storage, $mapper, $prefix, $indexed, $options );
$this->om = $om;
}
- public function findMulti( array $queries, array $options = array() ) {
+ public function findMulti( array $queries, array $options = [] ) {
if ( count( $queries ) > 1 ) {
// why?
throw new DataModelException( __METHOD__ . ' expects only one value in $queries', 'process-data' );
@@ -60,20 +58,20 @@ class BoardHistoryIndex extends TopKIndex {
return $this->storage->findMulti(
$queries,
$this->queryOptions()
- ) ?: array();
+ ) ?: [];
}
/**
- * @param Header|PostRevision $object
+ * @param PostSummary|PostRevision $object
* @param string[] $row
*/
public function cachePurge( $object, array $row ) {
- $row['topic_list_id'] = $this->findTopicListId( $object, $row, array() );
+ $row['topic_list_id'] = $this->findTopicListId( $object, $row, [] );
parent::cachePurge( $object, $row );
}
/**
- * @param Header|PostRevision $object
+ * @param PostSummary|PostRevision $object
* @param string[] $new
* @param array $metadata
*/
@@ -83,7 +81,7 @@ class BoardHistoryIndex extends TopKIndex {
}
/**
- * @param Header|PostRevision $object
+ * @param PostSummary|PostRevision $object
* @param string[] $old
* @param string[] $new
* @param array $metadata
@@ -94,7 +92,7 @@ class BoardHistoryIndex extends TopKIndex {
}
/**
- * @param Header|PostRevision $object
+ * @param PostSummary|PostRevision $object
* @param string[] $old
* @param array $metadata
*/
@@ -104,35 +102,30 @@ class BoardHistoryIndex extends TopKIndex {
}
/**
- * Find a topic list id related to an abstract revision
+ * Find a topic ID given an AbstractRevision
+ *
+ * @param AbstractRevision $object
+ * @return UUID Topic ID
+ */
+ abstract protected function findTopicId( AbstractRevision $object );
+
+ /**
+ * Find a topic list ID related to an AbstractRevision
*
* @param AbstractRevision $object
* @param string[] $row
* @param array $metadata
* @return string Alphadecimal uid of the related board
- * @throws InvalidInputException When $object is not a Header, PostRevision or
- * PostSummary instance.
* @throws DataModelException When the related id cannot be located
*/
protected function findTopicListId( AbstractRevision $object, array $row, array $metadata ) {
- if ( $object instanceof Header ) {
- return $row['rev_type_id'];
- }
-
if ( isset( $metadata['workflow'] ) && $metadata['workflow'] instanceof Workflow ) {
$topicId = $metadata['workflow']->getId();
} else {
- if ( $object instanceof PostRevision ) {
- $post = $object;
- } elseif ( $object instanceof PostSummary ) {
- $post = $object->getCollection()->getPost()->getLastRevision();
- } else {
- throw new InvalidInputException( 'Unexpected object type: ' . get_class( $object ) );
- }
- $topicId = $post->getRootPost()->getPostId();
+ $topicId = $this->findTopicId( $object );
}
- $found = $this->om->find( array( 'topic_id' => $topicId ) );
+ $found = $this->om->find( [ 'topic_id' => $topicId ] );
if ( !$found ) {
throw new DataModelException(
"No topic list contains topic " . $topicId->getAlphadecimal() .
diff --git a/Flow/includes/Data/Index/FeatureIndex.php b/Flow/includes/Data/Index/FeatureIndex.php
index 52a36008..ed3261c0 100644
--- a/Flow/includes/Data/Index/FeatureIndex.php
+++ b/Flow/includes/Data/Index/FeatureIndex.php
@@ -3,7 +3,7 @@
namespace Flow\Data\Index;
use Flow\Container;
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Data\Compactor;
use Flow\Data\Compactor\FeatureCompactor;
use Flow\Data\Compactor\ShallowCompactor;
@@ -21,7 +21,7 @@ use Flow\Exception\DataModelException;
abstract class FeatureIndex implements Index {
/**
- * @var BufferedCache
+ * @var FlowObjectCache
*/
protected $cache;
@@ -63,13 +63,8 @@ abstract class FeatureIndex implements Index {
/**
* {@inheritDoc}
- *
- * This exists in the Index interface and as such can't be abstract
- * until php 5.3.9, but some of our test machines are on 5.3.3. It
- * is included here to a complete list of unimplemented methods are seen
- * by looking at just this class.
*/
- //abstract public function getLimit();
+ abstract public function getLimit();
/**
* @return array The options used for querying self::$storage
@@ -84,13 +79,6 @@ abstract class FeatureIndex implements Index {
abstract public function limitIndexSize( array $values );
/**
- * @todo Could the cache key be passed in instead of $indexed?
- * @param array $indexed The portion of $row that makes up the cache key
- * @param array $row A single row of data to add to its related feature bucket
- */
- abstract protected function addToIndex( array $indexed, array $row );
-
- /**
* @todo Similar, Could the cache key be passed in instead of $indexed?
* @param array $indexed The portion of $row that makes up the cache key
* @param array $row A single row of data to remove from its related feature bucket
@@ -98,13 +86,13 @@ abstract class FeatureIndex implements Index {
abstract protected function removeFromIndex( array $indexed, array $row );
/**
- * @param BufferedCache $cache
+ * @param FlowObjectCache $cache
* @param ObjectStorage $storage
* @param ObjectMapper $mapper
* @param string $prefix Prefix to utilize for all cache keys
* @param array $indexedColumns List of columns to index,
*/
- public function __construct( BufferedCache $cache, ObjectStorage $storage, ObjectMapper $mapper, $prefix, array $indexedColumns ) {
+ public function __construct( FlowObjectCache $cache, ObjectStorage $storage, ObjectMapper $mapper, $prefix, array $indexedColumns ) {
$this->cache = $cache;
$this->storage = $storage;
$this->mapper = $mapper;
@@ -133,6 +121,9 @@ abstract class FeatureIndex implements Index {
if ( $featureColumns !== $this->indexedOrdered ) {
return false;
}
+
+ // This can probably be moved to TopKIndex if it's not used
+ // by anything else.
if ( isset( $options['limit'] ) ) {
$max = $options['limit'];
if ( isset( $options['offset'] ) ) {
@@ -167,125 +158,6 @@ abstract class FeatureIndex implements Index {
}
/**
- * @param array $rows
- * @param array $options
- * @return array [offset, limit]
- */
- protected function getOffsetLimit( $rows, $options ) {
- $limit = isset( $options['limit'] ) ? $options['limit'] : $this->getLimit();
-
- // not using isset because offset-id could also just be null (in which
- // case we'll still not want to fallback to 0, because offset-dir may
- // need to to start from the end of the rows)
- if ( !array_key_exists( 'offset-id', $options ) ) {
- $offset = isset( $options['offset'] ) ? $options['offset'] : 0;
- return array( $offset, $limit );
- }
-
- $offsetId = $options['offset-id'];
- if ( $offsetId instanceof UUID ) {
- $offsetId = $offsetId->getAlphadecimal();
- }
-
- $dir = 'fwd';
- if (
- isset( $options['offset-dir'] ) &&
- $options['offset-dir'] === 'rev'
- ) {
- $dir = 'rev';
- }
-
- if ( $offsetId === null ) {
- $offset = $dir === 'fwd' ? 0 : count( $rows ) - $limit;
- return array( $offset, $limit );
- }
-
- $offset = $this->getOffsetFromKey( $rows, $offsetId );
- $includeOffset = isset( $options['include-offset'] ) && $options['include-offset'];
- if ( $dir === 'fwd' ) {
- if ( $includeOffset ) {
- $startPos = $offset;
- } else {
- $startPos = $offset + 1;
- }
- } elseif ( $dir === 'rev' ) {
- $startPos = $offset - $limit;
- if ( $includeOffset ) {
- $startPos++;
- }
-
- if ( $startPos < 0 ) {
- if (
- isset( $options['offset-elastic'] ) &&
- $options['offset-elastic'] === false
- ) {
- // If non-elastic, then reduce the number of items shown commensurately
- $limit += $startPos;
- }
- $startPos = 0;
- }
- } else {
- $startPos = 0;
- }
-
- return array( $startPos, $limit );
- }
-
- /**
- * Returns the 0-indexed position of $offsetKey within $rows or throws a
- * DataModelException if $offsetKey is not contained within $rows
- *
- * @todo seems wasteful to pass string offsetKey instead of exploding when it comes in
- * @param array $rows Current bucket contents
- * @param string $offsetKey
- * @return int The position of $offsetKey within $rows
- * @throws DataModelException When $offsetKey is not found within $rows
- */
- protected function getOffsetFromKey( $rows, $offsetKey ) {
- $rowIndex = 0;
- $nextInOrder = $this->getOrder() === 'DESC' ? -1 : 1;
- foreach ( $rows as $row ) {
- $comparisonValue = $this->compareRowToOffset( $row, $offsetKey );
- if ( $comparisonValue === 0 || $comparisonValue === $nextInOrder ) {
- return $rowIndex;
- }
- $rowIndex++;
- }
-
- throw new DataModelException( 'Unable to find specified offset in query results', 'process-data' );
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws DataModelException When the index does not support key offsets due to
- * having an undefined sort order.
- */
- public function compareRowToOffset( array $row, $offset ) {
- $sortFields = $this->getSort();
- $splitOffset = explode( '|', $offset );
- $fieldIndex = 0;
-
- if ( $sortFields === false ) {
- throw new DataModelException( 'This Index implementation does not support key offsets', 'process-data' );
- }
-
- foreach( $sortFields as $field ) {
- $valueInRow = $row[$field];
- $valueInOffset = $splitOffset[$fieldIndex];
-
- if ( $valueInRow > $valueInOffset ) {
- return 1;
- } elseif ( $valueInRow < $valueInOffset ) {
- return -1;
- }
- ++$fieldIndex;
- }
-
- return 0;
- }
-
- /**
* Delete any feature bucket $object would be contained in from the cache
*
* @param object $object
@@ -306,17 +178,13 @@ abstract class FeatureIndex implements Index {
* {@inheritDoc}
*/
public function onAfterInsert( $object, array $new, array $metadata ) {
- $indexed = ObjectManager::splitFromRow( $new , $this->indexed );
+ $indexed = ObjectManager::splitFromRow( $new, $this->indexed );
// is un-indexable a bail-worthy occasion? Probably not but makes debugging easier
if ( !$indexed ) {
throw new DataModelException( 'Un-indexable row: ' . FormatJson::encode( $new ), 'process-data' );
}
$compacted = $this->rowCompactor->compactRow( UUID::convertUUIDs( $new, 'alphadecimal' ) );
- // give implementing index option to create rather than append
- if ( !$this->maybeCreateIndex( $indexed, $new, $compacted ) ) {
- // fall back to append
- $this->addToIndex( $indexed, $compacted );
- }
+ $this->removeFromIndex( $indexed, $compacted );
}
/**
@@ -339,11 +207,10 @@ abstract class FeatureIndex implements Index {
return;
}
// object representation in feature bucket has changed
- $this->replaceInIndex( $oldIndexed, $oldCompacted, $newCompacted );
+ $this->removeFromIndex( $oldIndexed, $oldCompacted );
} else {
// object has moved from one feature bucket to another
$this->removeFromIndex( $oldIndexed, $oldCompacted );
- $this->addToIndex( $newIndexed, $newCompacted );
}
}
@@ -376,17 +243,17 @@ abstract class FeatureIndex implements Index {
/**
* {@inheritDoc}
*/
- public function find( array $attributes, array $options = array() ) {
- $results = $this->findMulti( array( $attributes ), $options );
+ public function find( array $attributes, array $options = [] ) {
+ $results = $this->findMulti( [ $attributes ], $options );
return reset( $results );
}
/**
* {@inheritDoc}
*/
- public function findMulti( array $queries, array $options = array() ) {
+ public function findMulti( array $queries, array $options = [] ) {
if ( !$queries ) {
- return array();
+ return [];
}
// get cache keys for all queries
@@ -408,36 +275,12 @@ abstract class FeatureIndex implements Index {
// $fromStorage will be an array containing (expanded) results as value
// and indexes matching $query as key
$storageQueries = array_diff_key( $queries, $keysFromCache );
- $fromStorage = array();
+ $fromStorage = [];
if ( $storageQueries ) {
$fromStorage = $this->backingStoreFindMulti( $storageQueries );
-
- // store the data we've just retrieved to cache
- foreach ( $fromStorage as $index => $rows ) {
- // backing store returns data that may not be valid to cache (e.g.
- // if we couldn't retrieve content from ExternalStore, we shouldn't
- // cache that result)
- $rows = array_filter( $rows, array( $this->storage, 'validate' ) );
- if ( $rows !== $fromStorage[$index] ) {
- continue;
- }
-
- // normalize rows fetched from DB: schema may be different than the
- // real data (e.g. nullable columns no longer used or in preparation
- // for changes)
- $rows = array_map( array( $this->mapper, 'normalizeRow' ), $rows );
-
- $compacted = $this->rowCompactor->compactRows( $rows );
- $callback = function( \BagOStuff $cache, $key, $value ) use ( $compacted ) {
- if ( $value !== false ) {
- // somehow, the data was already cached in the meantime
- return false;
- }
-
- return $compacted;
- };
-
- $this->cache->merge( $cacheKeys[$index], $callback );
+ foreach ( $fromStorage as $idx => $resultFromStorage ) {
+ $key = $this->cacheKey( $storageQueries[$idx] );
+ $this->cache->set( $key, $resultFromStorage );
}
}
@@ -467,7 +310,7 @@ abstract class FeatureIndex implements Index {
$order = array_intersect_key( $queries, $results );
$results = array_replace( $order, $results );
- $keyToQuery = array();
+ $keyToQuery = [];
foreach ( $keysFromCache as $index => $key ) {
// all redundant data has been stripped, now expand all cache values
// (we're only doing this now to avoid expanding redundant data)
@@ -502,12 +345,8 @@ abstract class FeatureIndex implements Index {
* @param array[optional] $options
* @return array
*/
- protected function filterResults( array $results, array $options = array() ) {
- foreach ( $results as $i => $result ) {
- list( $offset, $limit ) = $this->getOffsetLimit( $result, $options );
- $results[$i] = array_slice( $result, $offset, $limit, true );
- }
-
+ protected function filterResults( array $results, array $options = [] ) {
+ // Overriden in TopKIndex
return $results;
}
@@ -522,8 +361,8 @@ abstract class FeatureIndex implements Index {
* @param array[optional] $options Options to find()
* @return bool
*/
- public function found( array $attributes, array $options = array() ) {
- return $this->foundMulti( array( $attributes ), $options );
+ public function found( array $attributes, array $options = [] ) {
+ return $this->foundMulti( [ $attributes ], $options );
}
/**
@@ -537,7 +376,7 @@ abstract class FeatureIndex implements Index {
* @param array[optional] $options Options to findMulti()
* @return bool
*/
- public function foundMulti( array $queries, array $options = array() ) {
+ public function foundMulti( array $queries, array $options = [] ) {
if ( !$queries ) {
return true;
}
@@ -557,7 +396,7 @@ abstract class FeatureIndex implements Index {
}
}
- $keyToQuery = array();
+ $keyToQuery = [];
foreach ( $cacheKeys as $i => $key ) {
// These results will be merged into the query results, and as such need binary
// uuid's as would be received from storage
@@ -595,7 +434,7 @@ abstract class FeatureIndex implements Index {
* @throws DataModelException
*/
protected function getCacheKeys( $queries ) {
- $idxToKey = array();
+ $idxToKey = [];
foreach ( $queries as $idx => $query ) {
ksort( $query );
if ( array_keys( $query ) !== $this->indexedOrdered ) {
@@ -624,7 +463,7 @@ abstract class FeatureIndex implements Index {
// query backing store
$options = $this->queryOptions();
$stored = $this->storage->findMulti( $queries, $options );
- $results = array();
+ $results = [];
// map store results to cache key
foreach ( $stored as $idx => $rows ) {
@@ -644,44 +483,12 @@ abstract class FeatureIndex implements Index {
}
/**
- * Called prior to self::addToIndex only when new objects as inserted. Gives the
- * opportunity for indexes to create rather than append if this object signifies a new
- * feature list.
- *
- * @todo again, could just pass cache key instead of $indexed?
- * @param array $indexed The values that make up the cache key
- * @param array $sourceRow The input database row
- * @param array $compacted The database row reduced in size for storage within the index
- * @return boolean True if an index was created, or false if $sourceRow should be merged
- * into the index via self::addToIndex
- */
- protected function maybeCreateIndex( array $indexed, array $sourceRow, array $compacted ) {
- return false;
- }
-
- /**
- * Called to update a row's data within a feature bucket.
- *
- * Note that this naive implementation does two round trips, likely an implementing
- * class can do this in a single round trip.
- *
- * @todo again, could just pass cache key instead of $indexed?
- * @param array $indexed The values that make up the cache key
- * @param array $old The database row that was previously retrieved from cache
- * @param array $new The new version of that replacement row
- */
- protected function replaceInIndex( array $indexed, array $old, array $new ) {
- $this->removeFromIndex( $indexed, $old );
- $this->addToIndex( $indexed, $new );
- }
-
- /**
* Generate the cache key representing the attributes
* @param array $attributes
* @return string
*/
protected function cacheKey( array $attributes ) {
- foreach( $attributes as $key => $attr ) {
+ foreach ( $attributes as $key => $attr ) {
if ( $attr instanceof UUID ) {
$attributes[$key] = $attr->getAlphadecimal();
} elseif ( strlen( $attr ) === UUID::BIN_LEN && substr( $key, -3 ) === '_id' ) {
@@ -691,18 +498,18 @@ abstract class FeatureIndex implements Index {
// values in $attributes may not always be in the exact same order,
// which would lead to differences in cache key if we don't force that
- sort( $attributes );
+ ksort( $attributes );
- return wfForeignMemcKey( self::cachedDbId(), '', $this->prefix, implode( ':', $attributes ), Container::get( 'cache.version' ) );
+ return wfForeignMemcKey( self::cachedDbId(), '', $this->prefix, md5( implode( ':', $attributes ) ), Container::get( 'cache.version' ) );
}
/**
* @return string The id of the database being cached
*/
- static public function cachedDbId() {
+ public static function cachedDbId() {
global $wgFlowDefaultWikiDb;
if ( $wgFlowDefaultWikiDb === false ) {
- return wfWikiId();
+ return wfWikiID();
} else {
return $wgFlowDefaultWikiDb;
}
diff --git a/Flow/includes/Data/Index/PostRevisionBoardHistoryIndex.php b/Flow/includes/Data/Index/PostRevisionBoardHistoryIndex.php
new file mode 100644
index 00000000..c5ec0ef1
--- /dev/null
+++ b/Flow/includes/Data/Index/PostRevisionBoardHistoryIndex.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Flow\Data\Index;
+
+use Flow\Model\AbstractRevision;
+
+class PostRevisionBoardHistoryIndex extends BoardHistoryIndex {
+ protected function findTopicId( AbstractRevision $post ) {
+ return $post->getRootPost()->getPostId();
+ }
+}
diff --git a/Flow/includes/Data/Index/PostRevisionTopicHistoryIndex.php b/Flow/includes/Data/Index/PostRevisionTopicHistoryIndex.php
new file mode 100644
index 00000000..201157cd
--- /dev/null
+++ b/Flow/includes/Data/Index/PostRevisionTopicHistoryIndex.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace Flow\Data\Index;
+
+use Flow\Collection\PostCollection;
+use Flow\Data\FlowObjectCache;
+use Flow\Data\ObjectMapper;
+use Flow\Data\Storage\PostRevisionTopicHistoryStorage;
+use Flow\Exception\DataModelException;
+use Flow\Model\PostRevision;
+use Flow\Model\UUID;
+use MWException;
+
+/**
+ * TopKIndex that calculates the topic_root_id
+ */
+class PostRevisionTopicHistoryIndex extends TopKIndex {
+ public function __construct( FlowObjectCache $cache, PostRevisionTopicHistoryStorage $storage, ObjectMapper $mapper, $prefix, array $indexed, array $options = [] ) {
+ if ( $indexed !== [ 'topic_root_id' ] ) {
+ throw new \MWException( __CLASS__ . ' is hardcoded to only index topic_root_id: ' . print_r( $indexed, true ) );
+ }
+ parent::__construct( $cache, $storage, $mapper, $prefix, $indexed, $options );
+ }
+
+ /**
+ * @param PostRevision $object
+ * @param array $row
+ */
+ public function cachePurge( $object, array $row ) {
+ $row['topic_root_id'] = $this->findTopicId( $object );
+ parent::cachePurge( $object, $row );
+ }
+
+ /**
+ * @param PostRevision $object
+ * @param string[] $new
+ * @param array $metadata
+ */
+ public function onAfterInsert( $object, array $new, array $metadata ) {
+ $new['topic_root_id'] = $this->findTopicId( $object );
+ parent::onAfterInsert( $object, $new, $metadata );
+ }
+
+ /**
+ * @param PostRevision $object
+ * @param string[] $old
+ * @param string[] $new
+ * @param array $metadata
+ */
+ public function onAfterUpdate( $object, array $old, array $new, array $metadata ) {
+ $old['topic_root_id'] = $new['topic_root_id'] = $this->findTopicId( $object );
+ parent::onAfterUpdate( $object, $old, $new, $metadata );
+ }
+
+ /**
+ * @param PostRevision $object
+ * @param string[] $old
+ * @param array $metadata
+ */
+ public function onAfterRemove( $object, array $old, array $metadata ) {
+ $old['topic_root_id'] = $this->findTopicId( $object );
+ parent::onAfterRemove( $object, $old, $metadata );
+ }
+
+ /**
+ * Finds topic ID for given Post
+ *
+ * @param PostRevision $post
+ * @return UUID Topic ID
+ * @throws DataModelException
+ */
+ protected function findTopicId( PostRevision $post ) {
+ try {
+ $root = $post->getCollection()->getRoot();
+ } catch ( DataModelException $e ) {
+ // in some cases, we may fail to find root post from the current
+ // object (e.g. data has already been removed)
+ // try to find if via parent, in that case
+ $parentId = $post->getReplyToId();
+ if ( $parentId === null ) {
+ throw new DataModelException( 'Unable to locate root for post ' . $post->getCollectionId() );
+ }
+
+ $parent = PostCollection::newFromId( $parentId );
+ $root = $parent->getRoot();
+ }
+
+ return $root->getId();
+ }
+
+ protected function backingStoreFindMulti( array $queries ) {
+ return $this->storage->findMulti( $queries, $this->queryOptions() );
+ }
+}
diff --git a/Flow/includes/Data/Index/PostSummaryRevisionBoardHistoryIndex.php b/Flow/includes/Data/Index/PostSummaryRevisionBoardHistoryIndex.php
new file mode 100644
index 00000000..1adb5b6c
--- /dev/null
+++ b/Flow/includes/Data/Index/PostSummaryRevisionBoardHistoryIndex.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace Flow\Data\Index;
+
+use Flow\Model\AbstractRevision;
+
+class PostSummaryRevisionBoardHistoryIndex extends BoardHistoryIndex {
+ protected function findTopicId( AbstractRevision $postSummary ) {
+ return $postSummary->getCollection()->getWorkflowId();
+ }
+}
diff --git a/Flow/includes/Data/Index/TopKIndex.php b/Flow/includes/Data/Index/TopKIndex.php
index 9d6b4934..b2e5759f 100644
--- a/Flow/includes/Data/Index/TopKIndex.php
+++ b/Flow/includes/Data/Index/TopKIndex.php
@@ -2,15 +2,14 @@
namespace Flow\Data\Index;
-use BagOStuff;
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Data\ObjectManager;
use Flow\Data\ObjectMapper;
use Flow\Data\ObjectStorage;
use Flow\Data\Compactor\ShallowCompactor;
use Flow\Data\Utils\SortArrayByKeys;
-use Flow\Exception\InvalidInputException;
-use Flow\Model\UUID;
+use Flow\Exception\DataModelException;
+use Flow\Exception\InvalidParameterException;
/**
* Holds the top k items with matching $indexed columns. List is sorted and truncated to specified size.
@@ -19,25 +18,27 @@ class TopKIndex extends FeatureIndex {
/**
* @var array
*/
- protected $options = array();
+ protected $options = [];
- public function __construct( BufferedCache $cache, ObjectStorage $storage, ObjectMapper $mapper, $prefix, array $indexed, array $options = array() ) {
+ public function __construct( FlowObjectCache $cache, ObjectStorage $storage, ObjectMapper $mapper, $prefix, array $indexed, array $options = [] ) {
if ( empty( $options['sort'] ) ) {
- throw new InvalidInputException( 'TopKIndex must be sorted', 'invalid-input' );
+ throw new InvalidParameterException( 'TopKIndex must be sorted' );
}
parent::__construct( $cache, $storage, $mapper, $prefix, $indexed );
- $this->options = $options + array(
+ $this->options = $options + [
'limit' => 500,
'order' => 'DESC',
- 'create' => function() { return false; },
+ 'create' => function () {
+ return false;
+ },
'shallow' => null,
- );
+ ];
$this->options['order'] = strtoupper( $this->options['order'] );
if ( !is_array( $this->options['sort'] ) ) {
- $this->options['sort'] = array( $this->options['sort'] );
+ $this->options['sort'] = [ $this->options['sort'] ];
}
if ( $this->options['shallow'] ) {
// TODO: perhaps we shouldn't even get a shallow option, just receive a proper compactor in FeatureIndex::__construct
@@ -49,6 +50,11 @@ class TopKIndex extends FeatureIndex {
if ( !parent::canAnswer( $keys, $options ) ) {
return false;
}
+
+ if ( isset( $options['offset-id'] ) || ( isset( $options['offset-dir'] ) && $options['offset-dir'] !== 'fwd' ) ) {
+ return false;
+ }
+
if ( isset( $options['sort'], $options['order'] ) ) {
return ObjectManager::makeArray( $options['sort'] ) === $this->options['sort']
&& strtoupper( $options['order'] ) === $this->options['order'];
@@ -60,119 +66,135 @@ class TopKIndex extends FeatureIndex {
return $this->options['limit'];
}
- protected function maybeCreateIndex( array $indexed, array $sourceRow, array $compacted ) {
- if ( call_user_func( $this->options['create'], $sourceRow ) ) {
- $this->cache->set( $this->cacheKey( $indexed ), array( $compacted ) );
- return true;
+ protected function filterResults( array $results, array $options = [] ) {
+ foreach ( $results as $i => $result ) {
+ list( $offset, $limit ) = $this->getOffsetLimit( $result, $options );
+ $results[$i] = array_slice( $result, $offset, $limit, true );
}
- return false;
+
+ return $results;
}
- protected function addToIndex( array $indexed, array $row ) {
- $self = $this;
+ // TODO: This is only left for now to handle non-ID offsets (e.g. updated
+ // timestamps).
+ // This has always been broken once you query past the TopKIndex limit.
+ /**
+ * @param array $rows
+ * @param array $options
+ * @return array [offset, limit] 0-based index to start with and limit.
+ */
+ protected function getOffsetLimit( $rows, $options ) {
+ $limit = isset( $options['limit'] ) ? $options['limit'] : $this->getLimit();
- // If this used redis instead of memcached, could it add to index in position
- // without retry possibility? need a single number that will properly sort rows.
- $this->cache->merge(
- $this->cacheKey( $indexed ),
- function( BagOStuff $cache, $key, $value ) use( $self, $row ) {
- if ( $value === false ) {
- return false;
- }
+ $offsetValue = isset( $options['offset-value'] ) ? $options['offset-value'] : null;
- if ( count( $value ) > 0 ) {
- /*
- * Ideally, we'd expand the rows currently in cache, run them
- * through $this->storage->normalize & then re-compact them.
- * And then we can reliably locate $row in there.
- * However, that may require additional cache lookups for
- * the expand info.
- *
- * Instead of doing that, Let's just make the current row
- * columns conform the rows in cache ($schema)
- *
- * This is mostly to fight useless nullable columns in DB
- * (either in preparation for schema change or no longer needed)
- * Meaningful changes in data will need a cache key change, so
- * we're good here.
- */
- $row = $self->normalizeCompressed( $row, array_keys( reset( $value ) ) );
- }
+ $dir = 'fwd';
+ if (
+ isset( $options['offset-dir'] ) &&
+ $options['offset-dir'] === 'rev'
+ ) {
+ $dir = 'rev';
+ }
- $idx = array_search( $row, $value );
- if ( $idx !== false ) {
- return false; // This row already exists somehow
- }
- $retval = $value;
- $retval[] = $row;
- $retval = $self->sortIndex( $retval );
- $retval = $self->limitIndexSize( $retval );
- if ( $retval === $value ) {
- // object didn't fit in index
- return false;
- } else {
- return $retval;
- }
- }
- );
- }
+ if ( $offsetValue === null ) {
+ $offset = $dir === 'fwd' ? 0 : count( $rows ) - $limit;
+ return [ $offset, $limit ];
+ }
- protected function removeFromIndex( array $indexed, array $row ) {
- $self = $this;
+ $offset = $this->getOffsetFromOffsetValue( $rows, $offsetValue );
+ $includeOffset = isset( $options['include-offset'] ) && $options['include-offset'];
+ if ( $dir === 'fwd' ) {
+ if ( $includeOffset ) {
+ $startPos = $offset;
+ } else {
+ $startPos = $offset + 1;
+ }
+ } elseif ( $dir === 'rev' ) {
+ $startPos = $offset - $limit;
+ if ( $includeOffset ) {
+ $startPos++;
+ }
- $this->cache->merge(
- $this->cacheKey( $indexed ),
- function( BagOStuff $cache, $key, $value ) use( $self, $row ) {
- if ( $value === false ) {
- return false;
+ if ( $startPos < 0 ) {
+ if (
+ isset( $options['offset-elastic'] ) &&
+ $options['offset-elastic'] === false
+ ) {
+ // If non-elastic, then reduce the number of items shown commensurately
+ $limit += $startPos;
}
+ $startPos = 0;
+ }
+ } else {
+ $startPos = 0;
+ }
- if ( count( $value ) > 0 ) {
- // see comment in self::addToIndex on why to normalize
- $row = $self->normalizeCompressed( $row, array_keys( reset( $value ) ) );
- }
+ return [ $startPos, $limit ];
+ }
- $idx = array_search( $row, $value );
- if ( $idx === false ) {
- return false;
- }
- unset( $value[$idx] );
- return $value;
+ /**
+ * Returns the 0-indexed position of $offsetValue within $rows or throws a
+ * DataModelException if $offsetValue is not contained within $rows
+ *
+ * @todo seems wasteful to pass string offsetValue instead of exploding when it comes in
+ * @param array $rows Current bucket contents
+ * @param string $offsetValue
+ * @return int The position of $offsetValue within $rows
+ * @throws DataModelException When $offsetValue is not found within $rows
+ */
+ protected function getOffsetFromOffsetValue( $rows, $offsetValue ) {
+ $rowIndex = 0;
+ $nextInOrder = $this->getOrder() === 'DESC' ? -1 : 1;
+ foreach ( $rows as $row ) {
+ $comparisonValue = $this->compareRowToOffsetValue( $row, $offsetValue );
+ if ( $comparisonValue === 0 || $comparisonValue === $nextInOrder ) {
+ return $rowIndex;
}
- );
+ $rowIndex++;
+ }
+
+ throw new DataModelException( 'Unable to find specified offset in query results', 'process-data' );
}
- protected function replaceInIndex( array $indexed, array $oldRow, array $newRow ) {
- $self = $this;
- $this->cache->merge(
- $this->cacheKey( $indexed ),
- function( BagOStuff $cache, $key, $value ) use( $self, $oldRow, $newRow ) {
- if ( $value === false ) {
- return false;
- }
- $retval = $value;
+ /**
+ * @param array $row Row to compare to
+ * @param string $offsetValue Value to compare to. For instance, a timestamp if we
+ * want all rows before/after that timestamp. This consists of values for each field
+ * we sort by, delimited by |.
+ *
+ * @return int An integer less than, equal to, or greater than zero
+ * if $row is considered to be respectively less than, equal to, or
+ * greater than $offsetValue
+ *
+ * @throws DataModelException When the index does not support offset values due to
+ * having an undefined sort order.
+ */
+ public function compareRowToOffsetValue( array $row, $offsetValue ) {
+ $sortFields = $this->getSort();
+ $splitOffsetValue = explode( '|', $offsetValue );
+ $fieldIndex = 0;
- if ( count( $value ) > 0 ) {
- // see comment in self::addToIndex on why to normalize
- $oldRow = $self->normalizeCompressed( $oldRow, array_keys( reset( $value ) ) );
- $newRow = $self->normalizeCompressed( $newRow, array_keys( reset( $value ) ) );
- }
+ if ( $sortFields === false ) {
+ throw new DataModelException( 'This Index implementation does not support offset values', 'process-data' );
+ }
- $idx = array_search( $oldRow, $retval );
- if ( $idx !== false ) {
- unset( $retval[$idx] );
- }
- $retval[] = $newRow;
- $retval = $self->sortIndex( $retval );
- $retval = $self->limitIndexSize( $retval );
- if ( $value === $retval ) {
- // new item didn't fit in index and old item wasn't found in index
- return false;
- } else {
- return $retval;
- }
+ foreach ( $sortFields as $field ) {
+ $valueInRow = $row[$field];
+ $offsetValuePart = $splitOffsetValue[$fieldIndex];
+
+ if ( $valueInRow > $offsetValuePart ) {
+ return 1;
+ } elseif ( $valueInRow < $offsetValuePart ) {
+ return -1;
}
- );
+ ++$fieldIndex;
+ }
+
+ return 0;
+ }
+
+ protected function removeFromIndex( array $indexed, array $row ) {
+ $this->cache->delete( $this->cacheKey( $indexed ) );
}
/**
@@ -216,9 +238,9 @@ class TopKIndex extends FeatureIndex {
// INTERNAL: in 5.4 it can be protected
public function queryOptions() {
- $options = array( 'LIMIT' => $this->options['limit'] );
+ $options = [ 'LIMIT' => $this->options['limit'] ];
- $orderBy = array();
+ $orderBy = [];
$order = $this->options['order'];
foreach ( $this->options['sort'] as $key ) {
$orderBy[] = "$key $order";
diff --git a/Flow/includes/Data/Index/UniqueFeatureIndex.php b/Flow/includes/Data/Index/UniqueFeatureIndex.php
index caa0d9af..15ffa6be 100644
--- a/Flow/includes/Data/Index/UniqueFeatureIndex.php
+++ b/Flow/includes/Data/Index/UniqueFeatureIndex.php
@@ -15,7 +15,7 @@ class UniqueFeatureIndex extends FeatureIndex {
}
public function queryOptions() {
- return array( 'LIMIT' => $this->getLimit() );
+ return [ 'LIMIT' => $this->getLimit() ];
}
public function limitIndexSize( array $values ) {
@@ -25,15 +25,7 @@ class UniqueFeatureIndex extends FeatureIndex {
return $values;
}
- protected function addToIndex( array $indexed, array $row ) {
- $this->cache->set( $this->cacheKey( $indexed ), array( $row ) );
- }
-
protected function removeFromIndex( array $indexed, array $row ) {
$this->cache->delete( $this->cacheKey( $indexed ) );
}
-
- protected function replaceInIndex( array $indexed, array $oldRow, array $newRow ) {
- $this->cache->set( $this->cacheKey( $indexed ), array( $newRow ) );
- }
-} \ No newline at end of file
+}
diff --git a/Flow/includes/Data/Listener/AbstractListener.php b/Flow/includes/Data/Listener/AbstractListener.php
index 079f70aa..bc3586f1 100644
--- a/Flow/includes/Data/Listener/AbstractListener.php
+++ b/Flow/includes/Data/Listener/AbstractListener.php
@@ -2,15 +2,7 @@
namespace Flow\Data\Listener;
-use Closure;
-use Flow\Container;
use Flow\Data\LifecycleHandler;
-use Flow\Data\Utils\RecentChangeFactory;
-use Flow\FlowActions;
-use Flow\Formatter\IRCLineUrlFormatter;
-use Flow\Model\AbstractRevision;
-use Flow\Model\Workflow;
-use Flow\Repository\UserNameBatch;
/**
* Inserts mw recentchange rows for flow AbstractRevision instances.
diff --git a/Flow/includes/Data/Listener/DeferredInsertLifecycleHandler.php b/Flow/includes/Data/Listener/DeferredInsertLifecycleHandler.php
index 02c16f35..b6b07865 100644
--- a/Flow/includes/Data/Listener/DeferredInsertLifecycleHandler.php
+++ b/Flow/includes/Data/Listener/DeferredInsertLifecycleHandler.php
@@ -32,7 +32,7 @@ class DeferredInsertLifecycleHandler implements LifecycleHandler {
*/
public function onAfterInsert( $object, array $new, array $metadata ) {
$nested = $this->nested;
- $this->queue->enqueue( function() use ( $nested, $object, $new, $metadata ) {
+ $this->queue->enqueue( function () use ( $nested, $object, $new, $metadata ) {
$nested->onAfterInsert( $object, $new, $metadata );
} );
}
diff --git a/Flow/includes/Data/Listener/EditCountListener.php b/Flow/includes/Data/Listener/EditCountListener.php
index 8beac6d9..3ec4df9c 100644
--- a/Flow/includes/Data/Listener/EditCountListener.php
+++ b/Flow/includes/Data/Listener/EditCountListener.php
@@ -18,7 +18,7 @@ class EditCountListener extends AbstractListener {
public function onAfterInsert( $revision, array $new, array $metadata ) {
if ( !$revision instanceof AbstractRevision ) {
- throw new InvalidDataException( 'EditCountListener can only attach to AbstractRevision storage');
+ throw new InvalidDataException( 'EditCountListener can only attach to AbstractRevision storage' );
}
$action = $revision->getChangeType();
diff --git a/Flow/includes/Data/Listener/ModerationLoggingListener.php b/Flow/includes/Data/Listener/ModerationLoggingListener.php
index 3748ca9a..4ec13451 100644
--- a/Flow/includes/Data/Listener/ModerationLoggingListener.php
+++ b/Flow/includes/Data/Listener/ModerationLoggingListener.php
@@ -3,7 +3,6 @@
namespace Flow\Data\Listener;
use Flow\Log\ModerationLogger;
-use Flow\Model\AbstractRevision;
use Flow\Model\PostRevision;
use Flow\Model\Workflow;
@@ -30,8 +29,7 @@ class ModerationLoggingListener extends AbstractListener {
}
protected function log( PostRevision $post, Workflow $workflow ) {
- $moderationChangeTypes = self::getModerationChangeTypes();
- if ( ! in_array( $post->getChangeType(), $moderationChangeTypes ) ) {
+ if ( !$post->isModerationChange() ) {
// Do nothing for non-moderation actions
return;
}
@@ -47,23 +45,4 @@ class ModerationLoggingListener extends AbstractListener {
);
}
}
-
- public static function getModerationChangeTypes() {
- static $changeTypes = false;
-
- if ( ! $changeTypes ) {
- $changeTypes = array();
- foreach( AbstractRevision::$perms as $perm ) {
- if ( $perm != '' ) {
- $changeTypes[] = "{$perm}-topic";
- $changeTypes[] = "{$perm}-post";
- }
- }
-
- $changeTypes[] = 'restore-topic';
- $changeTypes[] = 'restore-post';
- }
-
- return $changeTypes;
- }
}
diff --git a/Flow/includes/Data/Listener/NotificationListener.php b/Flow/includes/Data/Listener/NotificationListener.php
index 84141332..fd739099 100644
--- a/Flow/includes/Data/Listener/NotificationListener.php
+++ b/Flow/includes/Data/Listener/NotificationListener.php
@@ -4,6 +4,7 @@ namespace Flow\Data\Listener;
use Flow\Exception\InvalidDataException;
use Flow\Model\AbstractRevision;
+use Flow\Model\PostRevision;
use Flow\Model\Workflow;
use Flow\NotificationController;
@@ -28,7 +29,7 @@ class NotificationListener extends AbstractListener {
return;
}
- switch( $row['rev_change_type'] ) {
+ switch ( $row['rev_change_type'] ) {
// Actually new-topic @todo rename
case 'new-post':
if ( !isset(
@@ -40,12 +41,12 @@ class NotificationListener extends AbstractListener {
throw new InvalidDataException( 'Invalid metadata for revision ' . $object->getRevisionId()->getAlphadecimal(), 'missing-metadata' );
}
- $this->notificationController->notifyNewTopic( array(
+ $this->notificationController->notifyNewTopic( [
'board-workflow' => $metadata['board-workflow'],
'topic-workflow' => $metadata['workflow'],
'topic-title' => $metadata['topic-title'],
'first-post' => $metadata['first-post'],
- ) );
+ ] );
break;
case 'edit-title':
@@ -53,30 +54,68 @@ class NotificationListener extends AbstractListener {
break;
case 'reply':
- $this->notifyPostChange( 'flow-post-reply', $object, $metadata, array(
- 'reply-to' => $metadata['reply-to'],
- ) );
+ $this->notifyPostChange( 'flow-post-reply', $object, $metadata );
break;
case 'edit-post':
$this->notifyPostChange( 'flow-post-edited', $object, $metadata );
break;
+
+ case 'lock-topic':
+ $this->notificationController->notifyTopicLocked( 'flow-topic-resolved', [
+ 'revision' => $object,
+ 'topic-workflow' => $metadata['workflow'],
+ 'topic-title' => $metadata['topic-title'],
+ ] );
+ break;
+
+ // "restore" can be a lot of different things
+ // - undo moderation (suppress/delete/hide) things
+ // - undo lock status
+ // we'll need to inspect the previous revision to figure out what is was
+ case 'restore-topic':
+ $post = $object->getCollection();
+ $previousRevision = $post->getPrevRevision( $object );
+ if ( $previousRevision->isLocked() ) {
+ $this->notificationController->notifyTopicLocked( 'flow-topic-reopened', [
+ 'revision' => $object,
+ 'topic-workflow' => $metadata['workflow'],
+ 'topic-title' => $metadata['topic-title'],
+ ] );
+ }
+ break;
+
+ case 'edit-header':
+ $this->notificationController->notifyHeaderChange( [
+ 'revision' => $object,
+ 'board-workflow' => $metadata['workflow'],
+ ] );
+ break;
+
+ case 'create-topic-summary':
+ case 'edit-topic-summary':
+ $this->notificationController->notifySummaryChange( [
+ 'revision' => $object,
+ 'topic-workflow' => $metadata['workflow'],
+ 'topic-title' => $metadata['topic-title'],
+ ] );
+ break;
}
}
/**
* @param string $type
- * @param AbstractRevision $object
+ * @param PostRevision $object
* @param array $metadata
* @param array $params
* @throws InvalidDataException
*/
- protected function notifyPostChange( $type, $object, $metadata, array $params = array() ) {
+ protected function notifyPostChange( $type, PostRevision $object, $metadata, array $params = [] ) {
if ( !isset(
$metadata['workflow'],
$metadata['topic-title']
) ) {
- throw new InvalidDataException( 'Invalid metadata for revision ' . $object->getRevisionId()->getAlphadecimal(), 'missing-metadata' );
+ throw new InvalidDataException( 'Invalid metadata for topic|post revision ' . $object->getRevisionId()->getAlphadecimal(), 'missing-metadata' );
}
$workflow = $metadata['workflow'];
@@ -84,11 +123,10 @@ class NotificationListener extends AbstractListener {
throw new InvalidDataException( 'Workflow metadata is not a Workflow', 'missing-metadata' );
}
- $this->notificationController->notifyPostChange( $type, $params + array(
+ $this->notificationController->notifyPostChange( $type, $params + [
'revision' => $object,
- 'title' => $workflow->getOwnerTitle(),
'topic-workflow' => $workflow,
'topic-title' => $metadata['topic-title'],
- ) );
+ ] );
}
}
diff --git a/Flow/includes/Data/Listener/RecentChangesListener.php b/Flow/includes/Data/Listener/RecentChangesListener.php
index b3a1b185..cfe173a1 100644
--- a/Flow/includes/Data/Listener/RecentChangesListener.php
+++ b/Flow/includes/Data/Listener/RecentChangesListener.php
@@ -3,7 +3,6 @@
namespace Flow\Data\Listener;
use Closure;
-use Flow\Container;
use Flow\Data\Utils\RecentChangeFactory;
use Flow\FlowActions;
use Flow\Formatter\IRCLineUrlFormatter;
@@ -60,7 +59,7 @@ class RecentChangesListener extends AbstractListener {
/**
* @param AbstractRevision $revision Revision object
* @param array $row Revision row
- * @param array $metadata;
+ * @param array $metadata
*/
public function onAfterInsert( $revision, array $row, array $metadata ) {
global $wgRCFeeds;
@@ -82,34 +81,37 @@ class RecentChangesListener extends AbstractListener {
}
$title = $this->getRcTitle( $workflow, $revision->getChangeType() );
- $attribs = array(
+ $attribs = [
'rc_namespace' => $title->getNamespace(),
'rc_title' => $title->getDBkey(),
'rc_user' => $row['rev_user_id'],
- 'rc_user_text' => $this->usernames->get( wfWikiId(), $row['rev_user_id'], $row['rev_user_ip'] ),
+ 'rc_user_text' => $this->usernames->get( wfWikiID(), $row['rev_user_id'], $row['rev_user_ip'] ),
'rc_type' => RC_FLOW,
'rc_source' => self::SRC_FLOW,
'rc_minor' => 0,
'rc_bot' => 0, // TODO: is revision by bot
+ 'rc_new' => 0,
'rc_patrolled' => $user->isAllowed( 'autopatrol' ) ? 1 : 0,
'rc_old_len' => $revision->getPreviousContentLength(),
'rc_new_len' => $revision->getContentLength(),
'rc_this_oldid' => 0,
'rc_last_oldid' => 0,
'rc_log_type' => null,
- 'rc_params' => serialize( array(
- 'flow-workflow-change' => array(
+ 'rc_params' => serialize( [
+ 'flow-workflow-change' => [
'action' => $action,
'revision_type' => get_class( $revision ),
'revision' => $revisionId,
'workflow' => $workflow->getId()->getAlphadecimal(),
- ),
- ) ),
+ ],
+ ] ),
'rc_cur_id' => 0,
'rc_comment' => '',
+ 'rc_comment_text' => '',
+ 'rc_comment_data' => null,
'rc_timestamp' => $timestamp,
'rc_deleted' => 0,
- );
+ ];
$rc = $this->rcFactory->newFromRow( (object)$attribs );
$rc->save( /* $noudp = */ true ); // Insert into db
@@ -120,9 +122,9 @@ class RecentChangesListener extends AbstractListener {
$feeds[$name]['formatter'] = $this->ircFormatter;
}
// pre-load the irc formatter which will be triggered via hook
- $this->ircFormatter->associate( $rc, array(
+ $this->ircFormatter->associate( $rc, [
'revision' => $revision
- ) + $metadata );
+ ] + $metadata );
// run the feeds/irc/etc external notifications
$rc->notifyRCFeeds( $feeds );
}
@@ -151,6 +153,6 @@ class RecentChangesListener extends AbstractListener {
$allowed = $allowed( $revision, $this );
}
- return (bool) $allowed;
+ return (bool)$allowed;
}
}
diff --git a/Flow/includes/Data/Listener/ReferenceRecorder.php b/Flow/includes/Data/Listener/ReferenceRecorder.php
index 99ceb053..b91978e4 100644
--- a/Flow/includes/Data/Listener/ReferenceRecorder.php
+++ b/Flow/includes/Data/Listener/ReferenceRecorder.php
@@ -67,11 +67,11 @@ class ReferenceRecorder extends AbstractListener {
}
public function onAfterInsert( $revision, array $new, array $metadata ) {
- if ( !isset( $metadata['workflow'] )) {
+ if ( !isset( $metadata['workflow'] ) ) {
return;
}
if ( !$revision instanceof AbstractRevision ) {
- throw new InvalidDataException( 'ReferenceRecorder can only attach to AbstractRevision storage');
+ throw new InvalidDataException( 'ReferenceRecorder can only attach to AbstractRevision storage' );
}
/** @var Workflow $workflow */
$workflow = $metadata['workflow'];
@@ -88,7 +88,7 @@ class ReferenceRecorder extends AbstractListener {
// Data has not yet been committed at this point, so let's delay
// updating `categorylinks`, `externallinks`, etc.
$linksTableUpdater = $this->linksTableUpdater;
- $this->deferredQueue->push( function() use ( $linksTableUpdater, $workflow ) {
+ $this->deferredQueue->push( function () use ( $linksTableUpdater, $workflow ) {
$linksTableUpdater->doUpdate( $workflow );
} );
}
@@ -118,10 +118,12 @@ class ReferenceRecorder extends AbstractListener {
}
/**
- * While topic's themselves are plaintext and do not contain any references,
- * moderation actions change what references are visible. When transitioning
- * from or to a generically visible state (unmoderated or locked) the entire
- * topic + summary needs to be re-evaluated.
+ * Topic titles themselves only support minimal wikitext, and references in the
+ * title itself are not tracked.
+ *
+ * However, moderation actions change what references are visible. When
+ * transitioning from or to a generically visible state (unmoderated or locked) the
+ * entire topic + summary needs to be re-evaluated.
*
* @param Workflow $workflow
* @param PostRevision $current Topic revision object that was inserted
@@ -131,34 +133,34 @@ class ReferenceRecorder extends AbstractListener {
*/
protected function calculateChangesFromTopic( Workflow $workflow, PostRevision $current ) {
if ( $current->isFirstRevision() ) {
- return array( array(), array() );
+ return [ [], [] ];
}
$previous = $this->storage->get( 'PostRevision', $current->getPrevRevisionId() );
if ( !$previous ) {
- throw new FlowException( 'Expcted previous revision of ' . $current->getPrevRevisionId()->getAlphadecimal() );
+ throw new FlowException( 'Expected previous revision of ' . $current->getPrevRevisionId()->getAlphadecimal() );
}
$isHidden = self::isHidden( $current );
$wasHidden = self::isHidden( $previous );
if ( $isHidden === $wasHidden ) {
- return array( array(), array() );
+ return [ [], [] ];
}
// re-run
$revisions = $this->collectTopicRevisions( $workflow );
- $added = array();
- $removed = array();
+ $added = [];
+ $removed = [];
foreach ( $revisions as $revision ) {
list( $add, $remove ) = $this->calculateChangesFromExisting( $workflow, $revision, $current );
$added = array_merge( $added, $add );
$removed = array_merge( $removed, $remove );
};
- return array( $added, $removed );
+ return [ $added, $removed ];
}
- static protected function isHidden( AbstractRevision $revision ) {
+ protected static function isHidden( AbstractRevision $revision ) {
return $revision->isModerated() && $revision->getModerationState() !== $revision::MODERATED_LOCKED;
}
@@ -171,23 +173,23 @@ class ReferenceRecorder extends AbstractListener {
* @return AbstractRevision[]
*/
protected function collectTopicRevisions( Workflow $workflow ) {
- $found = $this->treeRepository->fetchSubtreeNodeList( array( $workflow->getId() ) );
- $queries = array();
+ $found = $this->treeRepository->fetchSubtreeNodeList( [ $workflow->getId() ] );
+ $queries = [];
foreach ( reset( $found ) as $uuid ) {
- $queries[] = array( 'rev_type_id' => $uuid );
+ $queries[] = [ 'rev_type_id' => $uuid ];
}
$posts = $this->storage->findMulti(
'PostRevision',
$queries,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
// we also need the most recent topic summary if it exists
$summaries = $this->storage->find(
'PostSummary',
- array( 'rev_type_id' => $workflow->getId() ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $workflow->getId() ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
$result = $summaries;
@@ -202,9 +204,9 @@ class ReferenceRecorder extends AbstractListener {
/**
* Pulls references from a revision's content
*
- * @param Workflow $workflow The Workflow that the revision is attached to.
- * @param AbstractRevision $revision The Revision to pull references from.
- * @param PostRevision|null $root
+ * @param Workflow $workflow The Workflow that the revision is attached to.
+ * @param AbstractRevision $revision The Revision to pull references from.
+ * @param PostRevision|null $root
* @return Reference[] Array of References.
*/
public function getReferencesFromRevisionContent(
@@ -214,7 +216,12 @@ class ReferenceRecorder extends AbstractListener {
) {
// Locked is the only moderated state we still collect references for.
if ( self::isHidden( $revision ) ) {
- return array();
+ return [];
+ }
+
+ // We also do not track references in topic titles.
+ if ( $revision instanceof PostRevision && $revision->isTopicTitle() ) {
+ return [];
}
// If this is attached to a topic we also need to check its permissions
@@ -232,7 +239,7 @@ class ReferenceRecorder extends AbstractListener {
}
if ( $root && ( self::isHidden( $root ) ) ) {
- return array();
+ return [];
}
return $this->referenceExtractor->getReferences(
@@ -246,27 +253,24 @@ class ReferenceRecorder extends AbstractListener {
/**
* Retrieves references that are already stored in the database for a given revision
*
- * @param string $revType The value returned from Revision::getRevisionType() for the revision.
- * @param UUID $objectId The revision's Object ID.
+ * @param string $revType The value returned from Revision::getRevisionType() for the revision.
+ * @param UUID $objectId The revision's Object ID.
* @return Reference[] Array of References.
*/
public function getExistingReferences( $revType, UUID $objectId ) {
- global $wgFlowMigrateReferenceWiki;
- $wikiConds = $wgFlowMigrateReferenceWiki
- ? array()
- : array( 'ref_src_wiki' => wfWikiId() );
-
- $prevWikiReferences = $this->storage->find( 'WikiReference', $wikiConds + array(
+ $prevWikiReferences = $this->storage->find( 'WikiReference', [
+ 'ref_src_wiki' => wfWikiID(),
'ref_src_object_type' => $revType,
'ref_src_object_id' => $objectId,
- ) );
+ ] );
- $prevUrlReferences = $this->storage->find( 'URLReference', $wikiConds + array(
+ $prevUrlReferences = $this->storage->find( 'URLReference', [
+ 'ref_src_wiki' => wfWikiID(),
'ref_src_object_type' => $revType,
'ref_src_object_id' => $objectId,
- ) );
+ ] );
- return array_merge( (array) $prevWikiReferences, (array) $prevUrlReferences );
+ return array_merge( (array)$prevWikiReferences, (array)$prevUrlReferences );
}
/**
@@ -274,39 +278,39 @@ class ReferenceRecorder extends AbstractListener {
*
* Would be protected if not for testing.
*
- * @param Reference[] $old The old references.
- * @param Reference[] $new The new references.
+ * @param Reference[] $old The old references.
+ * @param Reference[] $new The new references.
* @return array Array with two elements: added and removed references.
*/
public function referencesDifference( array $old, array $new ) {
- $newReferences = array();
+ $newReferences = [];
- foreach( $new as $ref ) {
+ foreach ( $new as $ref ) {
$newReferences[$ref->getIdentifier()] = $ref;
}
- $oldReferences = array();
+ $oldReferences = [];
- foreach( $old as $ref ) {
+ foreach ( $old as $ref ) {
$oldReferences[$ref->getIdentifier()] = $ref;
}
- $addReferences = array();
+ $addReferences = [];
- foreach( $newReferences as $identifier => $ref ) {
- if ( ! isset( $oldReferences[$identifier] ) ) {
+ foreach ( $newReferences as $identifier => $ref ) {
+ if ( !isset( $oldReferences[$identifier] ) ) {
$addReferences[] = $ref;
}
}
- $removeReferences = array();
+ $removeReferences = [];
- foreach( $oldReferences as $identifier => $ref ) {
- if ( ! isset( $newReferences[$identifier] ) ) {
+ foreach ( $oldReferences as $identifier => $ref ) {
+ if ( !isset( $newReferences[$identifier] ) ) {
$removeReferences[] = $ref;
}
}
- return array( $addReferences, $removeReferences );
+ return [ $addReferences, $removeReferences ];
}
}
diff --git a/Flow/includes/Data/Listener/TopicPageCreationListener.php b/Flow/includes/Data/Listener/TopicPageCreationListener.php
index c86c0ce7..ff4e6bb9 100644
--- a/Flow/includes/Data/Listener/TopicPageCreationListener.php
+++ b/Flow/includes/Data/Listener/TopicPageCreationListener.php
@@ -14,22 +14,16 @@ class TopicPageCreationListener extends AbstractListener {
/** @var SplQueue */
protected $deferredQueue;
- /** @var string **/
- protected $defaultType;
-
/**
* @param OccupationController $occupationController The OccupationController to create the page with.
- * @param SplQueue $deferredQueue Queue of callbacks to run only if commit succeeds
- * @param string $defaultType The workflow type to look for
+ * @param SplQueue $deferredQueue Queue of callbacks to run only if commit succeeds
*/
public function __construct(
OccupationController $occupationController,
- SplQueue $deferredQueue,
- $defaultType
+ SplQueue $deferredQueue
) {
$this->occupationController = $occupationController;
$this->deferredQueue = $deferredQueue;
- $this->defaultType = $defaultType;
}
public function onAfterLoad( $object, array $old ) {
@@ -43,7 +37,7 @@ class TopicPageCreationListener extends AbstractListener {
// make sure this Topic:xyz page exists
$controller = $this->occupationController;
- $this->deferredQueue->push( function() use ( $controller, $object ) {
+ $this->deferredQueue->push( function () use ( $controller, $object ) {
$controller->ensureFlowRevision(
new Article( $object->getArticleTitle() ),
$object
diff --git a/Flow/includes/Data/Listener/UserNameListener.php b/Flow/includes/Data/Listener/UserNameListener.php
index 7655c1e2..eb46ae50 100644
--- a/Flow/includes/Data/Listener/UserNameListener.php
+++ b/Flow/includes/Data/Listener/UserNameListener.php
@@ -20,14 +20,14 @@ class UserNameListener extends AbstractListener {
/**
* @param UserNameBatch $batch
* @param array $keys key - a list of keys from storage that contain user ids, value - the wiki for the user id lookup, default to $wiki if null
- * @param string|null $wiki The wikiid to use when $wikiKey is null. If both are null wfWikiId() is used
+ * @param string|null $wiki The wikiid to use when $wikiKey is null. If both are null wfWikiID() is used
*/
public function __construct( UserNameBatch $batch, array $keys, $wiki = null ) {
$this->batch = $batch;
$this->keys = $keys;
if ( $wiki === null ) {
- $this->wiki = wfWikiId();
+ $this->wiki = wfWikiID();
} else {
$this->wiki = $wiki;
}
diff --git a/Flow/includes/Data/Listener/WatchTopicListener.php b/Flow/includes/Data/Listener/WatchTopicListener.php
index db8833b4..7004f662 100644
--- a/Flow/includes/Data/Listener/WatchTopicListener.php
+++ b/Flow/includes/Data/Listener/WatchTopicListener.php
@@ -10,7 +10,6 @@ use Flow\Model\Workflow;
use Flow\WatchedTopicItems;
use Title;
use User;
-use WatchedItem;
/**
* Auto-watch topics when the user performs one of the actions specified
@@ -61,7 +60,7 @@ abstract class AbstractTopicInsertListener extends AbstractListener {
* an array of users to subscribe
* @return User[]
*/
- public static function getUsersToSubscribe( $changeType, $watchType, array $params = array() ) {
+ public static function getUsersToSubscribe( $changeType, $watchType, array $params = [] ) {
/** @var FlowActions $actions */
$actions = Container::get( 'flow_actions' );
@@ -69,12 +68,12 @@ abstract class AbstractTopicInsertListener extends AbstractListener {
try {
$users = $actions->getValue( $changeType, 'watch', $watchType );
} catch ( \Exception $e ) {
- return array();
+ return [];
}
// Null will be returned if nothing is defined for this changeType
if ( !$users ) {
- return array();
+ return [];
}
// Some actions may have more complex logic to determine watching users
@@ -108,7 +107,7 @@ class ImmediateWatchTopicListener extends AbstractTopicInsertListener {
* @param Workflow $workflow
*/
public function onAfterInsertExpectedChange( $changeType, Workflow $workflow ) {
- $users = static::getUsersToSubscribe( $changeType, 'immediate', array( $this->watchedTopicItems ) );
+ $users = static::getUsersToSubscribe( $changeType, 'immediate', [ $this->watchedTopicItems ] );
foreach ( $users as $user ) {
if ( !$user instanceof User ) {
@@ -116,7 +115,7 @@ class ImmediateWatchTopicListener extends AbstractTopicInsertListener {
}
$title = $workflow->getArticleTitle();
- WatchedItem::fromUserTitle( $user, $title )->addWatch();
+ $user->addWatch( $title );
$this->watchedTopicItems->addOverrideWatched( $title );
}
}
@@ -126,6 +125,6 @@ class ImmediateWatchTopicListener extends AbstractTopicInsertListener {
* @return User[]
*/
public static function getCurrentUser( WatchedTopicItems $watchedTopicItems ) {
- return array( $watchedTopicItems->getUser() );
+ return [ $watchedTopicItems->getUser() ];
}
}
diff --git a/Flow/includes/Data/Listener/WorkflowTopicListListener.php b/Flow/includes/Data/Listener/WorkflowTopicListListener.php
index 18e0369f..a2b81c80 100644
--- a/Flow/includes/Data/Listener/WorkflowTopicListListener.php
+++ b/Flow/includes/Data/Listener/WorkflowTopicListListener.php
@@ -34,11 +34,11 @@ class WorkflowTopicListListener extends AbstractListener {
}
/**
- * @var string
+ * @param string $workflowId
* @return TopicListEntry|false
*/
protected function getTopicListEntry( $workflowId ) {
- $list = $this->topicListStorage->find( array( 'topic_id' => $workflowId ) );
+ $list = $this->topicListStorage->find( [ 'topic_id' => $workflowId ] );
// One topic maps to only one topic list now
if ( $list ) {
@@ -54,9 +54,9 @@ class WorkflowTopicListListener extends AbstractListener {
public function onAfterInsert( $object, array $new, array $metadata ) {
$entry = $this->getTopicListEntry( $new['workflow_id'] );
if ( $entry ) {
- $row = array(
+ $row = [
'workflow_last_update_timestamp' => $new['workflow_last_update_timestamp']
- ) + TopicListEntry::toStorageRow( $entry );
+ ] + TopicListEntry::toStorageRow( $entry );
$this->topicListLastUpdatedIndex->onAfterInsert( $entry, $row, $metadata );
}
}
@@ -67,12 +67,12 @@ class WorkflowTopicListListener extends AbstractListener {
$row = TopicListEntry::toStorageRow( $entry );
$this->topicListLastUpdatedIndex->onAfterUpdate(
$entry,
- array(
+ [
'workflow_last_update_timestamp' => $old['workflow_last_update_timestamp']
- ) + $row,
- array(
+ ] + $row,
+ [
'workflow_last_update_timestamp' => $new['workflow_last_update_timestamp']
- ) + $row,
+ ] + $row,
$metadata
);
}
diff --git a/Flow/includes/Data/ManagerGroup.php b/Flow/includes/Data/ManagerGroup.php
index 8f88f3df..1a45891f 100644
--- a/Flow/includes/Data/ManagerGroup.php
+++ b/Flow/includes/Data/ManagerGroup.php
@@ -24,7 +24,7 @@ class ManagerGroup {
/**
* @var string[] List of container keys that have been used
*/
- protected $used = array();
+ protected $used = [];
/**
* @param Container $container
@@ -44,7 +44,7 @@ class ManagerGroup {
foreach ( array_keys( $this->used ) as $key ) {
$this->container[$key]->clear();
}
- $this->used = array();
+ $this->used = [];
}
/**
@@ -87,13 +87,13 @@ class ManagerGroup {
* @throws DataModelException
*/
protected function multiMethod( $method, $objects, array $metadata ) {
- $itemsByClass = array();
+ $itemsByClass = [];
- foreach( $objects as $object ) {
+ foreach ( $objects as $object ) {
$itemsByClass[ get_class( $object ) ][] = $object;
}
- foreach( $itemsByClass as $class => $myObjects ) {
+ foreach ( $itemsByClass as $class => $myObjects ) {
$this->getStorage( $class )->$method( $myObjects, $metadata );
}
}
@@ -102,7 +102,7 @@ class ManagerGroup {
* @param array $objects
* @param array $metadata
*/
- public function multiPut( $objects, array $metadata = array() ) {
+ public function multiPut( array $objects, array $metadata = [] ) {
$this->multiMethod( 'multiPut', $objects, $metadata );
}
@@ -110,7 +110,7 @@ class ManagerGroup {
* @param array $objects
* @param array $metadata
*/
- public function multiRemove( $objects, array $metadata = array() ) {
+ public function multiRemove( array $objects, array $metadata = [] ) {
$this->multiMethod( 'multiRemove', $objects, $metadata );
}
@@ -124,7 +124,7 @@ class ManagerGroup {
$className = array_shift( $args );
return call_user_func_array(
- array( $this->getStorage( $className ), $method ),
+ [ $this->getStorage( $className ), $method ],
$args
);
}
diff --git a/Flow/includes/Data/Mapper/BasicObjectMapper.php b/Flow/includes/Data/Mapper/BasicObjectMapper.php
index 4d01613c..b8c197de 100644
--- a/Flow/includes/Data/Mapper/BasicObjectMapper.php
+++ b/Flow/includes/Data/Mapper/BasicObjectMapper.php
@@ -26,8 +26,8 @@ class BasicObjectMapper implements ObjectMapper {
$this->fromStorageRow = $fromStorageRow;
}
- static public function model( $className ) {
- return new self( array( $className, 'toStorageRow' ), array( $className, 'fromStorageRow' ) );
+ public static function model( $className ) {
+ return new self( [ $className, 'toStorageRow' ], [ $className, 'fromStorageRow' ] );
}
public function toStorageRow( $object ) {
diff --git a/Flow/includes/Data/Mapper/CachingObjectMapper.php b/Flow/includes/Data/Mapper/CachingObjectMapper.php
index bbb41f13..7b542487 100644
--- a/Flow/includes/Data/Mapper/CachingObjectMapper.php
+++ b/Flow/includes/Data/Mapper/CachingObjectMapper.php
@@ -53,10 +53,10 @@ class CachingObjectMapper implements ObjectMapper {
* @param string[] $primaryKey
* @return CachingObjectMapper
*/
- static public function model( $className, array $primaryKey ) {
+ public static function model( $className, array $primaryKey ) {
return new self(
- array( $className, 'toStorageRow' ),
- array( $className, 'fromStorageRow' ),
+ [ $className, 'toStorageRow' ],
+ [ $className, 'fromStorageRow' ],
$primaryKey
);
}
diff --git a/Flow/includes/Data/ObjectLocator.php b/Flow/includes/Data/ObjectLocator.php
index 1741024b..8e07628e 100644
--- a/Flow/includes/Data/ObjectLocator.php
+++ b/Flow/includes/Data/ObjectLocator.php
@@ -2,7 +2,8 @@
namespace Flow\Data;
-use Flow\Exception\FlowException;
+use Flow\DbFactory;
+use Flow\Data\Utils\RawSql;
use Flow\Exception\NoIndexException;
use Flow\Model\UUID;
use FormatJson;
@@ -11,10 +12,9 @@ use FormatJson;
* Denormalized indexes that are query-only. The indexes used here must
* be provided to some ObjectManager as a lifecycleHandler to receive
* update events.
- * Error handling is all wrong, but simplifies prototyping.
*/
class ObjectLocator {
- /*
+ /**
* @var ObjectMapper
*/
protected $mapper;
@@ -30,6 +30,13 @@ class ObjectLocator {
protected $indexes;
/**
+ * Database factory (only for addQuotes)
+ *
+ * @var DbFactory
+ */
+ protected $dbFactory;
+
+ /**
* @var LifecycleHandler[]
*/
protected $lifecycleHandlers;
@@ -37,13 +44,15 @@ class ObjectLocator {
/**
* @param ObjectMapper $mapper
* @param ObjectStorage $storage
+ * @param DbFactory $dbFactory
* @param Index[] $indexes
* @param LifecycleHandler[] $lifecycleHandlers
*/
- public function __construct( ObjectMapper $mapper, ObjectStorage $storage, array $indexes = array(), array $lifecycleHandlers = array() ) {
+ public function __construct( ObjectMapper $mapper, ObjectStorage $storage, DbFactory $dbFactory, array $indexes = [], array $lifecycleHandlers = [] ) {
$this->mapper = $mapper;
$this->storage = $storage;
$this->indexes = $indexes;
+ $this->dbFactory = $dbFactory;
$this->lifecycleHandlers = array_merge( $indexes, $lifecycleHandlers );
}
@@ -51,9 +60,9 @@ class ObjectLocator {
return $this->mapper;
}
- public function find( array $attributes, array $options = array() ) {
- $result = $this->findMulti( array( $attributes ), $options );
- return $result ? reset( $result ) : null;
+ public function find( array $attributes, array $options = [] ) {
+ $result = $this->findMulti( [ $attributes ], $options );
+ return $result ? reset( $result ) : [];
}
/**
@@ -63,11 +72,11 @@ class ObjectLocator {
*
* @param array $queries
* @param array $options
- * @return array|null null is query failure. empty array is no result. array is success
+ * @return array[]
*/
- public function findMulti( array $queries, array $options = array() ) {
+ public function findMulti( array $queries, array $options = [] ) {
if ( !$queries ) {
- return array();
+ return [];
}
$keys = array_keys( reset( $queries ) );
@@ -91,15 +100,11 @@ class ObjectLocator {
} else {
wfDebugLog( 'FlowDebug', __METHOD__ . ': ' . $e->getMessage() );
}
- $res = $this->storage->findMulti( $queries, $this->convertToDbOptions( $options ) );
+ $res = $this->storage->findMulti( $this->convertToDbQueries( $queries, $options ), $this->convertToDbOptions( $options ) );
}
- if ( $res === null ) {
- return null;
- }
-
- $output = array();
- foreach( $res as $index => $queryOutput ) {
+ $output = [];
+ foreach ( $res as $index => $queryOutput ) {
foreach ( $queryOutput as $k => $v ) {
if ( $v ) {
$output[$index][$k] = $this->load( $v );
@@ -121,8 +126,8 @@ class ObjectLocator {
* @param array[optional] $options Options to find()
* @return bool
*/
- public function found( array $attributes, array $options = array() ) {
- return $this->foundMulti( array( $attributes ), $options );
+ public function found( array $attributes, array $options = [] ) {
+ return $this->foundMulti( [ $attributes ], $options );
}
/**
@@ -136,7 +141,7 @@ class ObjectLocator {
* @param array[optional] $options Options to findMulti()
* @return bool
*/
- public function foundMulti( array $queries, array $options = array() ) {
+ public function foundMulti( array $queries, array $options = [] ) {
if ( !$queries ) {
return true;
}
@@ -146,7 +151,7 @@ class ObjectLocator {
$options['sort'] = ObjectManager::makeArray( $options['sort'] );
}
- foreach( $queries as $key => $value ) {
+ foreach ( $queries as $key => $value ) {
$queries[$key] = UUID::convertUUIDs( $value, 'alphadecimal' );
}
@@ -166,20 +171,19 @@ class ObjectLocator {
}
public function get( $id ) {
- $result = $this->getMulti( array( $id ) );
+ $result = $this->getMulti( [ $id ] );
return $result ? reset( $result ) : null;
}
// Just a helper to find by primary key
- //
// Be careful with regards to order on composite primary keys,
// must be in same order as provided to the storage implementation.
public function getMulti( array $objectIds ) {
if ( !$objectIds ) {
- return array();
+ return [];
}
$primaryKey = $this->storage->getPrimaryKeyColumns();
- $queries = array();
+ $queries = [];
$retval = null;
foreach ( $objectIds as $id ) {
// check internal cache
@@ -212,11 +216,11 @@ class ObjectLocator {
* Determining if a find() has not yet been resolved may be useful so that
* additional data may be loaded at once.
*
- * @param string|integer $id Id to get()
+ * @param string|int $id Id to get()
* @return bool
*/
public function got( $id ) {
- return $this->gotMulti( array( $id ) );
+ return $this->gotMulti( [ $id ] );
}
/**
@@ -235,7 +239,7 @@ class ObjectLocator {
}
$primaryKey = $this->storage->getPrimaryKeyColumns();
- $queries = array();
+ $queries = [];
foreach ( $objectIds as $id ) {
$query = array_combine( $primaryKey, ObjectManager::makeArray( $id ) );
$query = UUID::convertUUIDs( $query, 'alphadecimal' );
@@ -261,7 +265,7 @@ class ObjectLocator {
* @return Index
* @throws NoIndexException
*/
- public function getIndexFor( array $keys, array $options = array() ) {
+ public function getIndexFor( array $keys, array $options = [] ) {
sort( $keys );
/** @var Index|null $current */
$current = null;
@@ -276,7 +280,7 @@ class ObjectLocator {
$current = $index;
// Find the smallest matching index
- } else if ( isset( $options['limit'] ) ) {
+ } elseif ( isset( $options['limit'] ) ) {
$current = $index->getLimit() < $current->getLimit() ? $index : $current;
// if no limit specified, find biggest matching index
@@ -306,7 +310,7 @@ class ObjectLocator {
* Convert index options to db equivalent options
*/
protected function convertToDbOptions( $options ) {
- $dbOptions = $orderBy = array();
+ $dbOptions = $orderBy = [];
$order = '';
if ( isset( $options['limit'] ) ) {
@@ -316,15 +320,53 @@ class ObjectLocator {
if ( isset( $options['order'] ) ) {
$order = ' ' . $options['order'];
}
+
if ( isset( $options['sort'] ) ) {
foreach ( $options['sort'] as $val ) {
$orderBy[] = $val . $order;
}
}
+
if ( $orderBy ) {
$dbOptions['ORDER BY'] = $orderBy;
}
return $dbOptions;
}
+
+ /**
+ * Uses options to figure out conditions to add to the DB queries.
+ *
+ * @param array $queries Array of queries, with each element an array of attributes
+ * @param array $options Options for queries
+ * @return array Queries for BasicDbStorage class
+ */
+ protected function convertToDbQueries( $queries, $options ) {
+ if ( isset( $options['offset-id'] ) &&
+ isset( $options['sort'] ) && count( $options['sort'] ) === 1 &&
+ preg_match( '/_id$/', $options['sort'][0] ) ) {
+ if ( !$options['offset-id'] instanceof UUID ) {
+ $options['offset-id'] = UUID::create( $options['offset-id'] );
+ }
+
+ if ( $options['order'] === 'ASC' ) {
+ $operator = '>';
+ } else {
+ $operator = '<';
+ }
+
+ if ( isset( $options['offset-include'] ) && $options['offset-include'] ) {
+ $operator .= '=';
+ }
+
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+ $condition = new RawSql( $options['sort'][0] . ' ' . $operator . ' ' . $dbr->addQuotes( $options['offset-id']->getBinary() ) );
+
+ foreach ( $queries as &$query ) {
+ $query[] = $condition;
+ }
+ }
+
+ return $queries;
+ }
}
diff --git a/Flow/includes/Data/ObjectManager.php b/Flow/includes/Data/ObjectManager.php
index 8ab54613..90a48c3c 100644
--- a/Flow/includes/Data/ObjectManager.php
+++ b/Flow/includes/Data/ObjectManager.php
@@ -2,6 +2,7 @@
namespace Flow\Data;
+use Flow\DbFactory;
use Flow\Exception\DataModelException;
use Flow\Exception\FlowException;
use Flow\Model\UUID;
@@ -71,6 +72,7 @@ class ObjectManager extends ObjectLocator {
/**
* @param ObjectMapper $mapper Convert to/from database rows/domain objects.
* @param ObjectStorage $storage Implements persistence(typically sql)
+ * @param DbFactory $dbFactory
* @param Index[] $indexes Specialized listeners that cache rows and can respond
* to queries
* @param LifecycleHandler[] $lifecycleHandlers Listeners for insert, update,
@@ -79,10 +81,11 @@ class ObjectManager extends ObjectLocator {
public function __construct(
ObjectMapper $mapper,
ObjectStorage $storage,
- array $indexes = array(),
- array $lifecycleHandlers = array()
+ DbFactory $dbFactory,
+ array $indexes = [],
+ array $lifecycleHandlers = []
) {
- parent::__construct( $mapper, $storage, $indexes, $lifecycleHandlers );
+ parent::__construct( $mapper, $storage, $dbFactory, $indexes, $lifecycleHandlers );
// This needs to be SplObjectStorage rather than using spl_object_hash for keys
// in a normal array because if the object gets GC'd spl_object_hash can reuse
@@ -109,7 +112,7 @@ class ObjectManager extends ObjectLocator {
* Merge an object loaded from outside the object manager for update.
* Without merge using self::put will trigger an insert operation.
*
- * @var object $object
+ * @param object $object
*/
public function merge( $object ) {
if ( !isset( $this->loaded[$object] ) ) {
@@ -135,26 +138,26 @@ class ObjectManager extends ObjectLocator {
/**
* Persist a single object to storage.
*
- * @var object $object
- * @var array $metadata Additional information about the object for
+ * @param object $object
+ * @param array $metadata Additional information about the object for
* listeners to operate on.
*/
- public function put( $object, array $metadata = array() ) {
- $this->multiPut( array( $object ), $metadata );
+ public function put( $object, array $metadata = [] ) {
+ $this->multiPut( [ $object ], $metadata );
}
/**
* Persist multiple objects to storage.
*
- * @var object[] $objects
- * @var array $metadata Additional information about the object for
+ * @param object[] $objects
+ * @param array $metadata Additional information about the object for
* listeners to operate on.
*/
- public function multiPut( array $objects, array $metadata = array() ) {
- $updateObjects = array();
- $insertObjects = array();
+ public function multiPut( array $objects, array $metadata = [] ) {
+ $updateObjects = [];
+ $insertObjects = [];
- foreach( $objects as $object ) {
+ foreach ( $objects as $object ) {
if ( isset( $this->loaded[$object] ) ) {
$updateObjects[] = $object;
} else {
@@ -174,11 +177,11 @@ class ObjectManager extends ObjectLocator {
/**
* Remove an object from persistent storage.
*
- * @var object $object
- * @var array $metadata Additional information about the object for
+ * @param object $object
+ * @param array $metadata Additional information about the object for
* listeners to operate on.
*/
- public function remove( $object, array $metadata = array() ) {
+ public function remove( $object, array $metadata = [] ) {
if ( !isset( $this->loaded[$object] ) ) {
throw new FlowException( 'Object was not loaded through this object manager, use ObjectManager::merge if necessary' );
}
@@ -194,8 +197,8 @@ class ObjectManager extends ObjectLocator {
/**
* Remove multiple objects from persistent storage.
*
- * @var object[] $objects
- * @var array $metadata
+ * @param object[] $objects
+ * @param array $metadata
*/
public function multiRemove( $objects, array $metadata ) {
foreach ( $objects as $obj ) {
@@ -212,11 +215,11 @@ class ObjectManager extends ObjectLocator {
* @return string
*/
public function serializeOffset( $object, array $sortFields ) {
- $offsetFields = array();
+ $offsetFields = [];
// @todo $row = $this->loaded[$object] ?
$row = $this->mapper->toStorageRow( $object );
// @todo Why not self::splitFromRow?
- foreach( $sortFields as $field ) {
+ foreach ( $sortFields as $field ) {
$value = $row[$field];
if ( is_string( $value )
@@ -241,14 +244,14 @@ class ObjectManager extends ObjectLocator {
* @param array $metadata
*/
protected function insert( array $objects, array $metadata ) {
- $rows = array_map( array( $this->mapper, 'toStorageRow' ), $objects );
+ $rows = array_map( [ $this->mapper, 'toStorageRow' ], $objects );
$storedRows = $this->storage->insert( $rows );
if ( !$storedRows ) {
throw new DataModelException( 'failed insert', 'process-data' );
}
$numObjects = count( $objects );
- for( $i = 0; $i < $numObjects; ++$i ) {
+ for ( $i = 0; $i < $numObjects; ++$i ) {
$object = $objects[$i];
$stored = $storedRows[$i];
@@ -272,7 +275,7 @@ class ObjectManager extends ObjectLocator {
* @param array $metadata
*/
protected function update( array $objects, array $metadata ) {
- foreach( $objects as $object ) {
+ foreach ( $objects as $object ) {
$this->updateSingle( $object, $metadata );
}
}
@@ -314,9 +317,9 @@ class ObjectManager extends ObjectLocator {
* @param array $new
* @return bool
*/
- static public function arrayEquals( array $old, array $new ) {
- return array_diff_assoc( $old, $new ) === array()
- && array_diff_assoc( $new, $old ) === array();
+ public static function arrayEquals( array $old, array $new ) {
+ return array_diff_assoc( $old, $new ) === []
+ && array_diff_assoc( $new, $old ) === [];
}
/**
@@ -328,11 +331,11 @@ class ObjectManager extends ObjectLocator {
*
* @return array
*/
- static public function makeArray( $input ) {
+ public static function makeArray( $input ) {
if ( is_array( $input ) ) {
return $input;
} else {
- return array( $input );
+ return [ $input ];
}
}
@@ -347,8 +350,8 @@ class ObjectManager extends ObjectLocator {
* @param array $new
* @return array
*/
- static public function calcUpdatesWithoutValidation( array $old, array $new ) {
- $updates = array();
+ public static function calcUpdatesWithoutValidation( array $old, array $new ) {
+ $updates = [];
foreach ( array_keys( $new ) as $key ) {
/*
* $old[$key] and $new[$key] could both be the same value going into the same
@@ -358,7 +361,7 @@ class ObjectManager extends ObjectLocator {
* (different between them doesn't matter here, both are for the same database
* column), so I'm casting them to string before performing comparison.
*/
- if ( !array_key_exists( $key, $old ) || (string) $old[$key] !== (string) $new[$key] ) {
+ if ( !array_key_exists( $key, $old ) || (string)$old[$key] !== (string)$new[$key] ) {
$updates[$key] = $new[$key];
}
unset( $old[$key] );
@@ -370,17 +373,16 @@ class ObjectManager extends ObjectLocator {
return $updates;
}
-
/**
* Separate a set of keys from an array. Returns null if not
* all keys are set.
*
* @param array $row
* @param array $keys
- * @return array
+ * @return array|null
*/
- static public function splitFromRow( array $row, array $keys ) {
- $split = array();
+ public static function splitFromRow( array $row, array $keys ) {
+ $split = [];
foreach ( $keys as $key ) {
if ( !isset( $row[$key] ) ) {
return null;
diff --git a/Flow/includes/Data/ObjectStorage.php b/Flow/includes/Data/ObjectStorage.php
index fdf62668..8057442d 100644
--- a/Flow/includes/Data/ObjectStorage.php
+++ b/Flow/includes/Data/ObjectStorage.php
@@ -15,7 +15,7 @@ interface ObjectStorage {
* @param array $options Query options such as ORDER BY and LIMIT.
* @return array
*/
- function find( array $attributes, array $options = array() );
+ function find( array $attributes, array $options = [] );
/**
* Perform the equivalent of array_map against self::find for multiple
@@ -25,7 +25,7 @@ interface ObjectStorage {
* @param array $options Options to use for all queries
* @return array[] Array of results for every query
*/
- function findMulti( array $queries, array $options = array() );
+ function findMulti( array $queries, array $options = [] );
/**
* @return array The list of columns that together uniquely identify a row
@@ -47,7 +47,7 @@ interface ObjectStorage {
*
* @param array $old Map of columns to values that was initially loaded.
* @param array $new Map of columns to values that the row should become.
- * @return boolean true when the row is successfully updated
+ * @return bool true when the row is successfully updated
*/
function update( array $old, array $new );
@@ -55,7 +55,7 @@ interface ObjectStorage {
* Remove the specified row from the data store.
*
* @param array $row Map of columns to values. Must contain the primary key columns.
- * @return boolean true when the row is successfully removed
+ * @return bool true when the row is successfully removed
*/
function remove( array $row );
diff --git a/Flow/includes/Data/Pager/HistoryPager.php b/Flow/includes/Data/Pager/HistoryPager.php
index 6ee79c9c..4cce5eb6 100644
--- a/Flow/includes/Data/Pager/HistoryPager.php
+++ b/Flow/includes/Data/Pager/HistoryPager.php
@@ -2,7 +2,6 @@
namespace Flow\Data\Pager;
-use Flow\FlowActions;
use Flow\Exception\FlowException;
use Flow\Exception\InvalidDataException;
use Flow\Formatter\BoardHistoryQuery;
@@ -13,11 +12,6 @@ use Flow\Model\UUID;
class HistoryPager extends \ReverseChronologicalPager {
/**
- * @var FlowActions
- */
- protected $actions;
-
- /**
* @var BoardHistoryQuery|TopicHistoryQuery|PostHistoryQuery
*/
protected $query;
@@ -28,11 +22,6 @@ class HistoryPager extends \ReverseChronologicalPager {
protected $id;
/**
- * @var UUID|null
- */
- public $mOffset;
-
- /**
* @var FormatterRow[]
*/
public $mResult;
@@ -41,8 +30,7 @@ class HistoryPager extends \ReverseChronologicalPager {
* @param BoardHistoryQuery|TopicHistoryQuery|PostHistoryQuery $query
* @param UUID $id
*/
- public function __construct( FlowActions $actions, /* BoardHistoryQuery|TopicHistoryQuery|PostHistoryQuery */ $query, UUID $id ) {
- $this->actions = $actions;
+ public function __construct( /* BoardHistoryQuery|TopicHistoryQuery|PostHistoryQuery */ $query, UUID $id ) {
$this->query = $query;
$this->id = $id;
@@ -50,19 +38,11 @@ class HistoryPager extends \ReverseChronologicalPager {
$this->mIsBackwards = $this->getRequest()->getVal( 'dir' ) == 'prev';
}
- /**
- * @param FormatterRow $row
- * @return bool
- */
- protected function includeInHistory( FormatterRow $row ) {
- return !$this->actions->getValue( $row->revision->getChangeType(), 'exclude_from_history' );
- }
-
public function doQuery() {
$direction = $this->mIsBackwards ? 'rev' : 'fwd';
// over-fetch so we can figure out if there's anything after what we're showing
- $this->mResult = $this->query->getResults( $this->id, $this->getLimit() + 1, $this->mOffset, $direction );
+ $this->mResult = $this->query->getResults( $this->id, $this->getLimit() + 1, UUID::create( $this->mOffset ), $direction );
if ( !$this->mResult ) {
throw new InvalidDataException(
'Unable to load history for ' . $this->id->getAlphadecimal(),
@@ -83,12 +63,6 @@ class HistoryPager extends \ReverseChronologicalPager {
}
}
- // We needed the exact row counts (before filtering) to determine
- // whether there were was an extra row (which controls pagination).
- // Now we can get rid of rows we don't want to display. Offsets will also
- // be generated based on the last displayed row.
- $this->mResult = array_values( array_filter( $this->mResult, array( $this, 'includeInHistory' ) ) );
-
// set some properties that'll be used to generate navigation bar
$this->mLastShown = $this->mResult[count( $this->mResult ) - 1]->revision->getRevisionId()->getAlphadecimal();
$this->mFirstShown = $this->mResult[0]->revision->getRevisionId()->getAlphadecimal();
@@ -107,7 +81,7 @@ class HistoryPager extends \ReverseChronologicalPager {
if ( $this->mIsBackwards ) {
// swap values if we're going backwards
- list( $this->mIsFirst, $this->mIsLast ) = array( $this->mIsLast, $this->mIsFirst );
+ list( $this->mIsFirst, $this->mIsLast ) = [ $this->mIsLast, $this->mIsFirst ];
// id of the overfetched entry, used to build new links starting at
// this offset
@@ -134,7 +108,7 @@ class HistoryPager extends \ReverseChronologicalPager {
}
public function getQueryInfo() {
- return array();
+ return [];
}
public function getIndexField() {
diff --git a/Flow/includes/Data/Pager/Pager.php b/Flow/includes/Data/Pager/Pager.php
index 994b4c04..cd6a163b 100644
--- a/Flow/includes/Data/Pager/Pager.php
+++ b/Flow/includes/Data/Pager/Pager.php
@@ -10,7 +10,7 @@ use Flow\Exception\InvalidInputException;
* Fetches paginated results from the OM provided in constructor
*/
class Pager {
- private static $VALID_DIRECTIONS = array( 'fwd', 'rev' );
+ private static $VALID_DIRECTIONS = [ 'fwd', 'rev' ];
const DEFAULT_DIRECTION = 'fwd';
const DEFAULT_LIMIT = 1;
const MAX_LIMIT = 500;
@@ -46,19 +46,24 @@ class Pager {
*/
protected $offsetKey;
+ /**
+ * @var bool Whether this pager uses ID fields
+ */
+ protected $useId;
+
public function __construct( ObjectManager $storage, array $query, array $options ) {
// not sure i like this
$this->storage = $storage;
$this->query = $query;
- $this->options = $options + array(
+ $this->options = $options + [
'pager-include-offset' => null,
'pager-offset' => null,
'pager-limit' => self::DEFAULT_LIMIT,
'pager-dir' => self::DEFAULT_DIRECTION,
- );
+ ];
$this->options['pager-limit'] = intval( $this->options['pager-limit'] );
- if ( ! ( $this->options['pager-limit'] > 0 && $this->options['pager-limit'] < self::MAX_LIMIT ) ) {
+ if ( !( $this->options['pager-limit'] > 0 && $this->options['pager-limit'] < self::MAX_LIMIT ) ) {
$this->options['pager-limit'] = self::DEFAULT_LIMIT;
}
@@ -66,14 +71,14 @@ class Pager {
$this->options['pager-dir'] = self::DEFAULT_DIRECTION;
}
- $indexOptions = array(
+ $indexOptions = [
'limit' => $this->options['pager-limit']
- );
+ ];
if ( isset( $this->options['sort'], $this->options['order'] ) ) {
- $indexOptions += array(
- 'sort' => array( $this->options['sort'] ),
+ $indexOptions += [
+ 'sort' => [ $this->options['sort'] ],
'order' => $this->options['order'],
- );
+ ];
}
$this->sort = $storage->getIndexFor(
array_keys( $query ),
@@ -87,6 +92,8 @@ class Pager {
}
break;
}
+ $this->useId = $useId;
+
$this->offsetKey = $useId ? 'offset-id' : 'offset';
}
@@ -97,16 +104,17 @@ class Pager {
*/
public function getPage( $filter = null ) {
$numNeeded = $this->options['pager-limit'] + 1;
- $options = $this->options + array(
+ $storageOffsetKey = $this->useId ? 'offset-id' : 'offset-value';
+
+ $options = $this->options + [
// We need one item of leeway to determine if there are more items
'limit' => $numNeeded,
'offset-dir' => $this->options['pager-dir'],
- 'offset-id' => $this->options['pager-offset'],
+ $storageOffsetKey => $this->options['pager-offset'],
'include-offset' => $this->options['pager-include-offset'],
- 'offset-elastic' => true,
- );
+ ];
$offset = $this->options['pager-offset'];
- $results = array();
+ $results = [];
$queries = 0;
do {
@@ -116,9 +124,10 @@ class Pager {
}
// Retrieve results
- $found = $this->storage->find( $this->query, array(
- 'offset-id' => $offset,
- ) + $options );
+ $options = [
+ $storageOffsetKey => $offset,
+ ] + $options;
+ $found = $this->storage->find( $this->query, $options );
if ( !$found ) {
// nothing found
@@ -158,7 +167,7 @@ class Pager {
if ( $results ) {
return $this->processPage( $results );
} else {
- return new PagerPage( array(), array(), $this );
+ return new PagerPage( [], [], $this );
}
}
@@ -168,7 +177,7 @@ class Pager {
* @throws InvalidInputException
*/
protected function processPage( $results ) {
- $pagingLinks = array();
+ $pagingLinks = [];
// Retrieve paging links
if ( $this->options['pager-dir'] === 'fwd' ) {
@@ -217,15 +226,15 @@ class Pager {
/**
* @param string $direction
* @param object $object
- * @param integer $pageLimit
+ * @param int $pageLimit
* @return array
*/
protected function makePagingLink( $direction, $object, $pageLimit ) {
- $return = array(
+ $return = [
'offset-dir' => $direction,
'limit' => $pageLimit,
$this->offsetKey => $this->storage->serializeOffset( $object, $this->sort ),
- );
+ ];
if ( isset( $this->options['sortby'] ) ) {
$return['sortby'] = $this->options['sortby'];
}
diff --git a/Flow/includes/Data/Storage/BasicDbStorage.php b/Flow/includes/Data/Storage/BasicDbStorage.php
index 9c6be5f8..fe324c2e 100644
--- a/Flow/includes/Data/Storage/BasicDbStorage.php
+++ b/Flow/includes/Data/Storage/BasicDbStorage.php
@@ -46,8 +46,8 @@ class BasicDbStorage extends DbStorage {
/**
* Inserts a set of rows into the database
*
- * @param array $rows The rows to insert. Also accepts a single row.
- * @return array|false An array of the rows that now exist
+ * @param array $rows The rows to insert. Also accepts a single row.
+ * @return array|false An array of the rows that now exist
* in the database. Integrity of keys is guaranteed.
* False if we failed.
*/
@@ -76,9 +76,9 @@ class BasicDbStorage extends DbStorage {
/**
* Update a single row in the database.
*
- * @param array $old The current state of the row.
- * @param array $new The desired new state of the row.
- * @return boolean Whether or not the operation was successful.
+ * @param array $old The current state of the row.
+ * @param array $new The desired new state of the row.
+ * @return bool Whether or not the operation was successful.
* @throws DataPersistenceException
*/
public function update( array $old, array $new ) {
@@ -107,7 +107,7 @@ class BasicDbStorage extends DbStorage {
/**
* @param array $row
- * @return boolean success
+ * @return bool success
* @throws DataPersistenceException
*/
public function remove( array $row ) {
@@ -124,51 +124,66 @@ class BasicDbStorage extends DbStorage {
return $res && $dbw->affectedRows();
}
- /*
- * @return array|null Empty array means no result, null means query failure. Array with results is
- * success.
+ /**
+ * @param array $attributes
+ * @param array $options
+ * @return array Empty array means no result. Array with results is success.
+ * @throws DataModelException On query failure
+ * @throws \MWException
*/
- public function find( array $attributes, array $options = array() ) {
+ public function find( array $attributes, array $options = [] ) {
$attributes = $this->preprocessSqlArray( $attributes );
if ( !$this->validateOptions( $options ) ) {
throw new \MWException( "Validation error in database options" );
}
- $res = $this->dbFactory->getDB( DB_MASTER )->select(
- $this->table,
- '*',
- $attributes,
- __METHOD__ . " ({$this->table})",
- $options
- );
- if ( ! $res ) {
- return null;
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+ $res = $this->doFindQuery( $attributes, $options );
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
}
- $result = array();
+ $result = [];
foreach ( $res as $row ) {
- $result[] = UUID::convertUUIDs( (array) $row, 'alphadecimal' );
+ $result[] = UUID::convertUUIDs( (array)$row, 'alphadecimal' );
}
- // wfDebugLog( 'Flow', __METHOD__ . ': ' . print_r( $result, true ) );
return $result;
}
+ protected function doFindQuery( array $preprocessedAttributes, array $options = [] ) {
+ return $this->dbFactory->getDB( DB_SLAVE )->select(
+ $this->table,
+ '*',
+ $preprocessedAttributes,
+ __METHOD__ . " ({$this->table})",
+ $options
+ );
+ }
+
protected function fallbackFindMulti( array $queries, array $options ) {
- $result = array();
+ $result = [];
foreach ( $queries as $key => $query ) {
$result[$key] = $this->find( $query, $options );
}
return $result;
}
- public function findMulti( array $queries, array $options = array() ) {
+ /**
+ * @param array $queries
+ * @param array $options
+ * @return array
+ * @throws DataModelException
+ * @throws \DBUnexpectedError
+ * @throws \MWException
+ */
+ public function findMulti( array $queries, array $options = [] ) {
$keys = array_keys( reset( $queries ) );
$pks = $this->getPrimaryKeyColumns();
if ( count( $keys ) !== count( $pks ) || array_diff( $keys, $pks ) ) {
return $this->fallbackFindMulti( $queries, $options );
}
- $conds = array();
+ $conds = [];
$dbr = $this->dbFactory->getDB( DB_SLAVE );
foreach ( $queries as $query ) {
$conds[] = $dbr->makeList( $this->preprocessSqlArray( $query ), LIST_AND );
@@ -177,12 +192,8 @@ class BasicDbStorage extends DbStorage {
$conds = $dbr->makeList( $conds, LIST_OR );
- $result = array();
// options can be ignored for primary key search
- $res = $this->find( array( new RawSql( $conds ) ) );
- if ( !$res ) {
- return $result;
- }
+ $res = $this->find( [ new RawSql( $conds ) ] );
// create temp array with pk value (usually uuid) as key and full db row
// as value
@@ -194,10 +205,13 @@ class BasicDbStorage extends DbStorage {
// build return value by mapping the database rows to the matching array
// index in $queries
+ $result = [];
foreach ( $queries as $i => $val ) {
$val = UUID::convertUUIDs( $val, 'alphadecimal' );
$pk = ObjectManager::splitFromRow( $val, $this->primaryKey );
- $result[$i][] = isset( $temp[$pk] ) ? $temp[$pk] : null;
+ if ( isset( $temp[$pk] ) ) {
+ $result[$i][] = $temp[$pk];
+ }
}
return $result;
diff --git a/Flow/includes/Data/Storage/BoardHistoryStorage.php b/Flow/includes/Data/Storage/BoardHistoryStorage.php
index e3bb7455..d09c029d 100644
--- a/Flow/includes/Data/Storage/BoardHistoryStorage.php
+++ b/Flow/includes/Data/Storage/BoardHistoryStorage.php
@@ -2,121 +2,30 @@
namespace Flow\Data\Storage;
-use Flow\Model\UUID;
use Flow\Exception\DataModelException;
/**
* SQL backing for BoardHistoryIndex fetches revisions related
- * to a specific TopicList(board workflow)
+ * to a specific TopicList (board workflow)
+ * Subclassed for each type that needs it, so each TopKIndex
+ * has a distinct backend.
*/
-class BoardHistoryStorage extends DbStorage {
+abstract class BoardHistoryStorage extends DbStorage {
+ abstract public function find( array $attributes, array $options = [] );
- public function find( array $attributes, array $options = array() ) {
- $multi = $this->findMulti( array( $attributes ), $options );
- if ( $multi ) {
- return reset( $multi );
- }
- return null;
- }
-
- public function findMulti( array $queries, array $options = array() ) {
- if ( count( $queries ) > 1 ) {
- throw new DataModelException( __METHOD__ . ' expects only one value in $queries', 'process-data' );
- }
-
- $merged = $this->findHeaderHistory( $queries, $options ) +
- $this->findTopicListHistory( $queries, $options ) +
- $this->findTopicSummaryHistory( $queries, $options );
-
- // Having merged data from 3 sources, we now have to combine it
- // (according to the current sort & limit)
- $order = isset( $options['ORDER BY'][0] ) && preg_match( '/ASC$/', $options['ORDER BY'][0] ) ? 'ASC' : 'DESC';
- if ( $order === 'DESC' ) {
- krsort( $merged );
- } else {
- ksort( $merged );
+ public function findMulti( array $queries, array $options = [] ) {
+ if ( count( $queries ) !== 1 ) {
+ throw new DataModelException( __METHOD__ . ' expects exactly one value in $queries', 'process-data' );
}
- if ( isset( $options['LIMIT'] ) ) {
- $merged = array_splice( $merged, 0, $options['LIMIT'] );
+ $result = [];
+ foreach ( $queries as $i => $attributes ) {
+ $result[$i] = $this->find( $attributes, $options );
}
- $res = array( $merged );
- return RevisionStorage::mergeExternalContent( $res );
- }
-
- protected function findHeaderHistory( array $queries, array $options = array() ) {
- $queries = $this->preprocessSqlArray( reset( $queries ) );
-
- $res = $this->dbFactory->getDB( DB_SLAVE )->select(
- array( 'flow_revision' ),
- array( '*' ),
- array( 'rev_type' => 'header' ) + UUID::convertUUIDs( array( 'rev_type_id' => $queries['topic_list_id'] ) ),
- __METHOD__,
- $options
- );
+ $result = RevisionStorage::mergeExternalContent( $result );
- $retval = array();
-
- if ( $res ) {
- foreach ( $res as $row ) {
- $row = UUID::convertUUIDs( (array) $row, 'alphadecimal' );
- $retval[$row['rev_id']] = $row;
- }
- }
- return $retval;
- }
-
- protected function findTopicSummaryHistory( array $queries, array $options = array() ) {
- $queries = $this->preprocessSqlArray( reset( $queries ) );
-
- $res = $this->dbFactory->getDB( DB_SLAVE )->select(
- array( 'flow_revision', 'flow_topic_list', 'flow_tree_node' ),
- array( '*' ),
- array(
- 'rev_type' => 'post-summary',
- 'topic_id = tree_ancestor_id',
- 'rev_type_id = tree_descendant_id'
- ) + UUID::convertUUIDs( array( 'topic_list_id' => $queries['topic_list_id'] ) ),
- __METHOD__,
- $options
- );
-
- $retval = array();
-
- if ( $res ) {
- foreach ( $res as $row ) {
- $row = UUID::convertUUIDs( (array) $row, 'alphadecimal' );
- $retval[$row['rev_id']] = $row;
- }
- }
- return $retval;
- }
-
- protected function findTopicListHistory( array $queries, array $options = array() ) {
- $queries = $this->preprocessSqlArray( reset( $queries ) );
-
- $res = $this->dbFactory->getDB( DB_SLAVE )->select(
- array( 'flow_topic_list', 'flow_tree_node', 'flow_tree_revision', 'flow_revision' ),
- array( '*' ),
- array(
- 'topic_id = tree_ancestor_id',
- 'tree_descendant_id = tree_rev_descendant_id',
- 'tree_rev_id = rev_id',
- ) + $queries,
- __METHOD__,
- $options
- );
-
- $retval = array();
-
- if ( $res ) {
- foreach ( $res as $row ) {
- $row = UUID::convertUUIDs( (array) $row, 'alphadecimal' );
- $retval[$row['rev_id']] = $row;
- }
- }
- return $retval;
+ return $result;
}
/**
@@ -131,7 +40,7 @@ class BoardHistoryStorage extends DbStorage {
}
public function getPrimaryKeyColumns() {
- return array( 'topic_list_id' );
+ return [ 'topic_list_id' ];
}
public function insert( array $row ) {
diff --git a/Flow/includes/Data/Storage/DbStorage.php b/Flow/includes/Data/Storage/DbStorage.php
index 7f6bb392..44a9bec0 100644
--- a/Flow/includes/Data/Storage/DbStorage.php
+++ b/Flow/includes/Data/Storage/DbStorage.php
@@ -37,7 +37,7 @@ abstract class DbStorage implements ObjectStorage {
*
* @var string[] Array of columns to ignore
*/
- protected $obsoleteUpdateColumns = array();
+ protected $obsoleteUpdateColumns = [];
/**
* @param DbFactory $dbFactory
@@ -49,13 +49,13 @@ abstract class DbStorage implements ObjectStorage {
/**
* Runs preprocessSqlArray on each element of an array.
*
- * @param array $outer The array to check
- * @return array Preprocessed SQL array.
+ * @param array $outer The array to check
+ * @return array Preprocessed SQL array.
* @throws DataModelException
*/
protected function preprocessNestedSqlArray( array $outer ) {
foreach ( $outer as $i => $data ) {
- if ( ! is_array( $data) ) {
+ if ( !is_array( $data ) ) {
throw new DataModelException( "Unexpected non-array in nested SQL array" );
}
$outer[$i] = $this->preprocessSqlArray( $data );
@@ -79,12 +79,12 @@ abstract class DbStorage implements ObjectStorage {
$data = UUID::convertUUIDs( $data, 'binary' );
- foreach( $data as $key => $value ) {
+ foreach ( $data as $key => $value ) {
if ( $value instanceof RawSql ) {
$data[$key] = $value->getSql( $db );
} elseif ( is_numeric( $key ) ) {
throw new DataModelException( "Unescaped raw SQL found in " . __METHOD__, 'process-data' );
- } elseif ( ! preg_match( '/^[A-Za-z0-9\._]+$/', $key ) ) {
+ } elseif ( !preg_match( '/^[A-Za-z0-9\._]+$/', $key ) ) {
throw new DataModelException( "Dangerous SQL field name '$key' found in " . __METHOD__, 'process-data' );
}
}
@@ -99,10 +99,10 @@ abstract class DbStorage implements ObjectStorage {
* potentially unsafe characters.
*
* @param array $row The row to check.
- * @return boolean True if raw SQL is found
+ * @return bool True if raw SQL is found
*/
protected function hasUnescapedSQL( array $row ) {
- foreach( $row as $key => $value ) {
+ foreach ( $row as $key => $value ) {
if ( $value instanceof RawSql ) {
// Specifically allowed SQL
continue;
@@ -112,7 +112,7 @@ abstract class DbStorage implements ObjectStorage {
return true;
}
- if ( ! preg_match( '/^' . $this->getFieldRegexFragment() . '$/', $key ) ) {
+ if ( !preg_match( '/^' . $this->getFieldRegexFragment() . '$/', $key ) ) {
return true;
}
}
@@ -133,18 +133,18 @@ abstract class DbStorage implements ObjectStorage {
* Internal security function to check an options array for
* SQL injection and other funkiness
* @todo Currently only supports LIMIT, OFFSET and ORDER BY
- * @param array $options An options array passed to a query.
- * @return boolean
+ * @param array $options An options array passed to a query.
+ * @return bool
*/
protected function validateOptions( $options ) {
- static $validUnaryOptions = array(
+ static $validUnaryOptions = [
'UNIQUE',
'EXPLAIN',
- );
+ ];
$fieldRegex = $this->getFieldRegexFragment();
- foreach( $options as $key => $value ) {
+ foreach ( $options as $key => $value ) {
if ( is_numeric( $key ) && in_array( strtoupper( $value ), $validUnaryOptions ) ) {
continue;
} elseif ( is_numeric( $key ) ) {
@@ -154,7 +154,7 @@ abstract class DbStorage implements ObjectStorage {
if ( $key === 'LIMIT' ) {
// LIMIT is one or two integers, separated by a comma.
- if ( ! preg_match ( '/^\d+(,\d+)?$/', $value ) ) {
+ if ( !preg_match( '/^\d+(,\d+)?$/', $value ) ) {
wfDebug( __METHOD__.": Invalid LIMIT $value\n" );
return false;
}
@@ -165,20 +165,20 @@ abstract class DbStorage implements ObjectStorage {
}
$orderByRegex = "/^\s*$fieldRegex\s*(ASC|DESC)?\s*$/i";
- foreach( $value as $orderByField ) {
- if ( ! preg_match( $orderByRegex, $orderByField ) ) {
+ foreach ( $value as $orderByField ) {
+ if ( !preg_match( $orderByRegex, $orderByField ) ) {
wfDebug( __METHOD__.": invalid ORDER BY field $orderByField\n" );
return false;
}
}
} elseif ( $key === 'OFFSET' ) {
// OFFSET is just an integer
- if ( ! is_numeric( $value ) ) {
+ if ( !is_numeric( $value ) ) {
wfDebug( __METHOD__.": non-numeric offset $value\n" );
return false;
}
} elseif ( $key === 'GROUP BY' ) {
- if ( ! preg_match( "/^{$fieldRegex}(,{$fieldRegex})+$/", $value ) ) {
+ if ( !preg_match( "/^{$fieldRegex}(,{$fieldRegex})+$/", $value ) ) {
wfDebug( __METHOD__.": invalid GROUP BY field\n" );
}
} else {
diff --git a/Flow/includes/Data/Storage/PostRevisionBoardHistoryStorage.php b/Flow/includes/Data/Storage/PostRevisionBoardHistoryStorage.php
new file mode 100644
index 00000000..65ea52c3
--- /dev/null
+++ b/Flow/includes/Data/Storage/PostRevisionBoardHistoryStorage.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Flow\Data\Storage;
+
+use Flow\Exception\DataModelException;
+use Flow\Model\UUID;
+
+class PostRevisionBoardHistoryStorage extends BoardHistoryStorage {
+ /**
+ * @param array $attributes
+ * @param array $options
+ * @return array
+ * @throws DataModelException
+ */
+ public function find( array $attributes, array $options = [] ) {
+ $attributes = $this->preprocessSqlArray( $attributes );
+
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+ $res = $dbr->select(
+ [ 'flow_topic_list', 'flow_tree_node', 'flow_tree_revision', 'flow_revision' ],
+ [ '*' ],
+ array_merge( [
+ 'rev_type' => 'post',
+ 'topic_id = tree_ancestor_id',
+ 'tree_descendant_id = tree_rev_descendant_id',
+ 'tree_rev_id = rev_id',
+ ], $attributes ),
+ __METHOD__,
+ $options
+ );
+
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
+ }
+
+ $retval = [];
+ foreach ( $res as $row ) {
+ $row = UUID::convertUUIDs( (array)$row, 'alphadecimal' );
+ $retval[$row['rev_id']] = $row;
+ }
+
+ return $retval;
+ }
+}
diff --git a/Flow/includes/Data/Storage/PostRevisionStorage.php b/Flow/includes/Data/Storage/PostRevisionStorage.php
index c49dfa5e..dabd3407 100644
--- a/Flow/includes/Data/Storage/PostRevisionStorage.php
+++ b/Flow/includes/Data/Storage/PostRevisionStorage.php
@@ -5,7 +5,6 @@ namespace Flow\Data\Storage;
use Flow\DbFactory;
use Flow\Model\UUID;
use Flow\Repository\TreeRepository;
-use Flow\Exception\DataModelException;
/**
* SQL storage and query for PostRevision instances
@@ -18,7 +17,7 @@ class PostRevisionStorage extends RevisionStorage {
/**
* @param DbFactory $dbFactory
- * @param array|false List of external store servers available for insert
+ * @param array|false $externalStore List of external store servers available for insert
* or false to disable. See $wgFlowExternalStore.
* @param TreeRepository $treeRepo
*/
@@ -40,12 +39,12 @@ class PostRevisionStorage extends RevisionStorage {
}
protected function insertRelated( array $rows ) {
- if ( ! is_array( reset( $rows ) ) ) {
- $rows = array( $rows );
+ if ( !is_array( reset( $rows ) ) ) {
+ $rows = [ $rows ];
}
- $trees = array();
- foreach( $rows as $key => $row ) {
+ $trees = [];
+ foreach ( $rows as $key => $row ) {
$trees[$key] = $this->splitUpdate( $row, 'tree' );
}
@@ -59,7 +58,7 @@ class PostRevisionStorage extends RevisionStorage {
// If this is a brand new root revision it needs to be added to the tree
// If it has a rev_parent_id then its already a part of the tree
if ( $res ) {
- foreach( $rows as $row ) {
+ foreach ( $rows as $row ) {
if ( $row['rev_parent_id'] === null ) {
$res = $res && $this->treeRepo->insert(
UUID::create( $row['tree_rev_descendant_id'] ),
@@ -70,7 +69,7 @@ class PostRevisionStorage extends RevisionStorage {
}
if ( !$res ) {
- return array();
+ return [];
}
return $rows;
@@ -91,12 +90,12 @@ class PostRevisionStorage extends RevisionStorage {
$res = $dbw->update(
$this->joinTable(),
$this->preprocessSqlArray( $treeChanges ),
- array( 'tree_rev_id' => $old['tree_rev_id'] ),
+ [ 'tree_rev_id' => $old['tree_rev_id'] ],
__METHOD__
);
if ( !$res ) {
- return array();
+ return [];
}
return $changes;
@@ -108,7 +107,7 @@ class PostRevisionStorage extends RevisionStorage {
protected function removeRelated( array $row ) {
return $this->dbFactory->getDB( DB_MASTER )->delete(
$this->joinTable(),
- $this->preprocessSqlArray( array( $this->joinField() => $row['rev_id'] ) )
+ $this->preprocessSqlArray( [ $this->joinField() => $row['rev_id'] ] )
);
}
}
diff --git a/Flow/includes/Data/Storage/PostRevisionTopicHistoryStorage.php b/Flow/includes/Data/Storage/PostRevisionTopicHistoryStorage.php
new file mode 100644
index 00000000..c56f6226
--- /dev/null
+++ b/Flow/includes/Data/Storage/PostRevisionTopicHistoryStorage.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace Flow\Data\Storage;
+
+use Flow\Data\ObjectStorage;
+use Flow\Exception\DataModelException;
+use Flow\Model\UUID;
+use Flow\Repository\TreeRepository;
+
+/**
+ * Query-only storage implementation provides history of all post revisions in a topic.
+ */
+class PostRevisionTopicHistoryStorage implements ObjectStorage {
+
+ /**
+ * @var ObjectStorage
+ */
+ protected $postRevisionStorage;
+
+ /**
+ * @var TreeRepository
+ */
+ protected $treeRepository;
+
+ /**
+ * @param ObjectStorage $postRevisionStorage
+ * @param TreeRepository $treeRepo
+ */
+ public function __construct( ObjectStorage $postRevisionStorage, TreeRepository $treeRepo ) {
+ $this->postRevisionStorage = $postRevisionStorage;
+ $this->treeRepository = $treeRepo;
+ }
+
+ public function find( array $attributes, array $options = [] ) {
+ $multi = $this->findMulti( [ $attributes ], $options );
+ return $multi ? reset( $multi ) : [];
+ }
+
+ /**
+ * This is called with queries for 'topic_root_id': a "virtual" column that we'll
+ * interpret. Based on these root ids (=topic id), we'll fetch all post revisions inside
+ * that topic.
+ * @param array $queries
+ * @param array $options
+ * @return array
+ */
+ public function findMulti( array $queries, array $options = [] ) {
+ foreach ( $queries as $idx => $query ) {
+ if ( isset( $query['topic_root_id'] ) ) {
+ $descendantQuery = $this->findDescendantQuery( $query );
+ unset( $query['topic_root_id'] );
+ $queries[$idx] = array_merge( $query, $descendantQuery );
+ }
+ }
+
+ return $this->postRevisionStorage->findMulti( $queries, $options );
+ }
+
+ /**
+ * All queries are for roots (guaranteed in findMulti), so anything that falls
+ * through and has to be queried from storage will actually need to be doing a
+ * special condition either joining against flow_tree_node or first collecting the
+ * subtree node lists and then doing a big IN condition
+ *
+ * This isn't a hot path (should be pre-populated into index) but we still don't want
+ * horrible performance
+ *
+ * @param array $query
+ * @return array
+ * @throws \Flow\Exception\InvalidInputException
+ */
+ protected function findDescendantQuery( array $query ) {
+ $roots = [ UUID::create( $query['topic_root_id'] ) ];
+ $nodeList = $this->treeRepository->fetchSubtreeNodeList( $roots );
+ if ( $nodeList === false ) {
+ // We can't return the existing $retval, that false data would be cached.
+ return [];
+ }
+
+ /** @var UUID $topicRootId */
+ $topicRootId = UUID::create( $query['topic_root_id'] );
+ $nodes = $nodeList[$topicRootId->getAlphadecimal()];
+ return [
+ 'rev_type_id' => UUID::convertUUIDs( $nodes ),
+ ];
+ }
+
+ public function getPrimaryKeyColumns() {
+ return [ 'topic_root_id' ];
+ }
+
+ public function insert( array $row ) {
+ throw new DataModelException( __CLASS__ . ' does not support insert action', 'process-data' );
+ }
+
+ public function update( array $old, array $new ) {
+ throw new DataModelException( __CLASS__ . ' does not support update action', 'process-data' );
+ }
+
+ public function remove( array $row ) {
+ throw new DataModelException( __CLASS__ . ' does not support remove action', 'process-data' );
+ }
+
+ public function validate( array $row ) {
+ return true;
+ }
+}
diff --git a/Flow/includes/Data/Storage/PostSummaryRevisionBoardHistoryStorage.php b/Flow/includes/Data/Storage/PostSummaryRevisionBoardHistoryStorage.php
new file mode 100644
index 00000000..8ca67c1c
--- /dev/null
+++ b/Flow/includes/Data/Storage/PostSummaryRevisionBoardHistoryStorage.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Flow\Data\Storage;
+
+use Flow\Exception\DataModelException;
+use Flow\Model\UUID;
+
+class PostSummaryRevisionBoardHistoryStorage extends BoardHistoryStorage {
+ /**
+ * @param array $attributes
+ * @param array $options
+ * @return array
+ * @throws DataModelException
+ */
+ public function find( array $attributes, array $options = [] ) {
+ $attributes = $this->preprocessSqlArray( $attributes );
+
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+ $res = $dbr->select(
+ [ 'flow_revision', 'flow_topic_list', 'flow_tree_node' ],
+ [ '*' ],
+ array_merge( [
+ 'rev_type' => 'post-summary',
+ 'topic_id = tree_ancestor_id',
+ 'rev_type_id = tree_descendant_id',
+ ], $attributes ),
+ __METHOD__,
+ $options
+ );
+
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
+ }
+
+ $retval = [];
+ foreach ( $res as $row ) {
+ $row = UUID::convertUUIDs( (array)$row, 'alphadecimal' );
+ $retval[$row['rev_id']] = $row;
+ }
+
+ return $retval;
+ }
+}
diff --git a/Flow/includes/Data/Storage/RevisionStorage.php b/Flow/includes/Data/Storage/RevisionStorage.php
index 609ceeef..22ec0e1d 100644
--- a/Flow/includes/Data/Storage/RevisionStorage.php
+++ b/Flow/includes/Data/Storage/RevisionStorage.php
@@ -19,14 +19,14 @@ abstract class RevisionStorage extends DbStorage {
/**
* {@inheritDoc}
*/
- protected $allowedUpdateColumns = array(
+ protected $allowedUpdateColumns = [
'rev_mod_state',
'rev_mod_user_id',
'rev_mod_user_ip',
'rev_mod_user_wiki',
'rev_mod_timestamp',
'rev_mod_reason',
- );
+ ];
/**
* {@inheritDoc}
@@ -34,13 +34,13 @@ abstract class RevisionStorage extends DbStorage {
* @Todo - This may not be necessary anymore since we don't update historical
* revisions ( flow_revision ) during moderation
*/
- protected $obsoleteUpdateColumns = array (
+ protected $obsoleteUpdateColumns = [
'tree_orig_user_text',
'rev_user_text',
'rev_edit_user_text',
'rev_mod_user_text',
'rev_type_id',
- );
+ ];
protected $externalStore;
@@ -96,7 +96,7 @@ abstract class RevisionStorage extends DbStorage {
/**
* @param DbFactory $dbFactory
- * @param array|false List of external store servers available for insert
+ * @param array|false $externalStore List of external store servers available for insert
* or false to disable. See $wgFlowExternalStore.
*/
public function __construct( DbFactory $dbFactory, $externalStore ) {
@@ -106,40 +106,45 @@ abstract class RevisionStorage extends DbStorage {
// Find one by specific attributes
// @todo: this method can probably be generalized in parent class?
- public function find( array $attributes, array $options = array() ) {
- $multi = $this->findMulti( array( $attributes ), $options );
- if ( $multi ) {
- return reset( $multi );
- }
- return null;
+ public function find( array $attributes, array $options = [] ) {
+ $multi = $this->findMulti( [ $attributes ], $options );
+ return $multi ? reset( $multi ) : [];
}
- protected function findInternal( array $attributes, array $options = array() ) {
- $dbr = $this->dbFactory->getDB( DB_MASTER );
+ /**
+ * @param array $attributes
+ * @param array $options
+ * @return array
+ * @throws DataModelException
+ * @throws MWException
+ */
+ protected function findInternal( array $attributes, array $options = [] ) {
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
- if ( ! $this->validateOptions( $options ) ) {
+ if ( !$this->validateOptions( $options ) ) {
throw new MWException( "Validation error in database options" );
}
// Add rev_type if rev_type_id exists in query condition
$attributes = $this->addRevTypeToQuery( $attributes );
- $tables = array( 'rev' => 'flow_revision' );
- $joins = array();
+ $tables = [ 'rev' => 'flow_revision' ];
+ $joins = [];
if ( $this->joinTable() ) {
$tables[] = $this->joinTable();
- $joins = array( 'rev' => array( 'JOIN', $this->joinField() . ' = rev_id' ) );
+ $joins = [ 'rev' => [ 'JOIN', $this->joinField() . ' = rev_id' ] ];
}
$res = $dbr->select(
$tables, '*', $this->preprocessSqlArray( $attributes ), __METHOD__, $options, $joins
);
- if ( !$res ) {
- return null;
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
}
- $retval = array();
+
+ $retval = [];
foreach ( $res as $row ) {
- $row = UUID::convertUUIDs( (array) $row, 'alphadecimal' );
+ $row = UUID::convertUUIDs( (array)$row, 'alphadecimal' );
$retval[$row['rev_id']] = $row;
}
return $retval;
@@ -152,7 +157,7 @@ abstract class RevisionStorage extends DbStorage {
return $query;
}
- public function findMulti( array $queries, array $options = array() ) {
+ public function findMulti( array $queries, array $options = [] ) {
if ( count( $queries ) < 3 ) {
$res = $this->fallbackFindMulti( $queries, $options );
} else {
@@ -163,30 +168,30 @@ abstract class RevisionStorage extends DbStorage {
}
protected function fallbackFindMulti( array $queries, array $options ) {
- $result = array();
+ $result = [];
foreach ( $queries as $key => $attributes ) {
$result[$key] = $this->findInternal( $attributes, $options );
}
return $result;
}
- protected function findMultiInternal( array $queries, array $options = array() ) {
+ protected function findMultiInternal( array $queries, array $options = [] ) {
$queriedKeys = array_keys( reset( $queries ) );
// The findMulti doesn't map well to SQL, basically we are asking to answer a bunch
// of queries. We can optimize those into a single query in a few select instances:
if ( isset( $options['LIMIT'] ) && $options['LIMIT'] == 1 ) {
// Find by primary key
- if ( $options == array( 'LIMIT' => 1 ) &&
- $queriedKeys === array( 'rev_id' )
+ if ( $options == [ 'LIMIT' => 1 ] &&
+ $queriedKeys === [ 'rev_id' ]
) {
return $this->findRevId( $queries );
}
// Find most recent revision of a number of posts
if ( !isset( $options['OFFSET'] ) &&
- $queriedKeys == array( 'rev_type_id' ) &&
+ $queriedKeys == [ 'rev_type_id' ] &&
isset( $options['ORDER BY'] ) &&
- $options['ORDER BY'] === array( 'rev_id DESC' )
+ $options['ORDER BY'] === [ 'rev_id DESC' ]
) {
return $this->findMostRecent( $queries );
}
@@ -198,7 +203,7 @@ abstract class RevisionStorage extends DbStorage {
// but would still have the need to run a bunch of queries serially.
if ( count( $options ) === 2 &&
isset( $options['LIMIT'], $options['ORDER BY'] ) &&
- $options['ORDER BY'] === array( 'rev_id DESC' )
+ $options['ORDER BY'] === [ 'rev_id DESC' ]
) {
return $this->fallbackFindMulti( $queries, $options );
// unoptimizable query
@@ -214,10 +219,10 @@ abstract class RevisionStorage extends DbStorage {
}
protected function findRevId( array $queries ) {
- $duplicator = new ResultDuplicator( array( 'rev_id' ), 1 );
- $pks = array();
+ $duplicator = new ResultDuplicator( [ 'rev_id' ], 1 );
+ $pks = [];
foreach ( $queries as $idx => $query ) {
- $query = UUID::convertUUIDs( (array) $query, 'alphadecimal' );
+ $query = UUID::convertUUIDs( (array)$query, 'alphadecimal' );
$duplicator->add( $query, $idx );
$id = $query['rev_id'];
$pks[$id] = UUID::create( $id )->getBinary();
@@ -231,26 +236,25 @@ abstract class RevisionStorage extends DbStorage {
// FROM flow_tree_revision
// WHERE rev_type= 'post' AND rev_type_id IN (...)
// GROUP BY rev_type_id
- $duplicator = new ResultDuplicator( array( 'rev_type_id' ), 1 );
+ $duplicator = new ResultDuplicator( [ 'rev_type_id' ], 1 );
foreach ( $queries as $idx => $query ) {
- $query = UUID::convertUUIDs( (array) $query, 'alphadecimal' );
+ $query = UUID::convertUUIDs( (array)$query, 'alphadecimal' );
$duplicator->add( $query, $idx );
}
- $dbr = $this->dbFactory->getDB( DB_MASTER );
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
$res = $dbr->select(
- array( 'flow_revision' ),
- array( 'rev_id' => "MAX( 'rev_id' )" ),
- array( 'rev_type' => $this->getRevType() ) + $this->preprocessSqlArray( $this->buildCompositeInCondition( $dbr, $duplicator->getUniqueQueries() ) ),
+ [ 'flow_revision' ],
+ [ 'rev_id' => "MAX( 'rev_id' )" ],
+ [ 'rev_type' => $this->getRevType() ] + $this->preprocessSqlArray( $this->buildCompositeInCondition( $dbr, $duplicator->getUniqueQueries() ) ),
__METHOD__,
- array( 'GROUP BY' => 'rev_type_id' )
+ [ 'GROUP BY' => 'rev_type_id' ]
);
- if ( !$res ) {
- // TODO: dont fail, but dont end up caching bad result either
- throw new DataModelException( 'query failure', 'process-data' );
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
}
- $revisionIds = array();
+ $revisionIds = [];
foreach ( $res as $row ) {
$revisionIds[] = $row->rev_id;
}
@@ -269,34 +273,33 @@ abstract class RevisionStorage extends DbStorage {
*/
protected function findRevIdReal( ResultDuplicator $duplicator, array $revisionIds ) {
if ( $revisionIds ) {
- // SELECT * from flow_revision
- // JOIN flow_tree_revision ON tree_rev_id = rev_id
- // WHERE rev_id IN (...)
- $dbr = $this->dbFactory->getDB( DB_MASTER );
+ // SELECT * from flow_revision
+ // JOIN flow_tree_revision ON tree_rev_id = rev_id
+ // WHERE rev_id IN (...)
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
- $tables = array( 'flow_revision' );
- $joins = array();
+ $tables = [ 'flow_revision' ];
+ $joins = [];
if ( $this->joinTable() ) {
$tables['rev'] = $this->joinTable();
- $joins = array( 'rev' => array( 'JOIN', "rev_id = " . $this->joinField() ) );
+ $joins = [ 'rev' => [ 'JOIN', "rev_id = " . $this->joinField() ] ];
}
$res = $dbr->select(
$tables,
'*',
- array( 'rev_id' => $revisionIds ),
+ [ 'rev_id' => $revisionIds ],
__METHOD__,
- array(),
+ [],
$joins
);
- if ( !$res ) {
- // TODO: dont fail, but dont end up caching bad result either
- throw new DataModelException( 'query failure', 'process-data' );
+ if ( $res === false ) {
+ throw new DataModelException( __METHOD__ . ': Query failed: ' . $dbr->lastError(), 'process-data' );
}
foreach ( $res as $row ) {
$row = UUID::convertUUIDs( (array)$row, 'alphadecimal' );
- $duplicator->merge( $row, array( $row ) );
+ $duplicator->merge( $row, [ $row ] );
}
}
@@ -332,7 +335,7 @@ abstract class RevisionStorage extends DbStorage {
return Merger::mergeMulti(
$cacheResult,
/* fromKey = */ 'rev_content_url',
- /* callable = */ array( 'ExternalStore', 'batchFetchFromURLs' ),
+ /* callable = */ [ 'ExternalStore', 'batchFetchFromURLs' ],
/* name = */ 'rev_content',
/* default = */ ''
);
@@ -340,7 +343,7 @@ abstract class RevisionStorage extends DbStorage {
protected function buildCompositeInCondition( DatabaseBase $dbr, array $queries ) {
$keys = array_keys( reset( $queries ) );
- $conditions = array();
+ $conditions = [];
if ( count( $keys ) === 1 ) {
// standard in condition: tree_rev_descendant_id IN (1,2...)
$key = reset( $keys );
@@ -360,14 +363,14 @@ abstract class RevisionStorage extends DbStorage {
}
public function insert( array $rows ) {
- if ( ! is_array( reset( $rows ) ) ) {
- $rows = array( $rows );
+ if ( !is_array( reset( $rows ) ) ) {
+ $rows = [ $rows ];
}
// Holds the subset of the row to go into the revision table
- $revisions = array();
+ $revisions = [];
- foreach( $rows as $key => $row ) {
+ foreach ( $rows as $key => $row ) {
$row = $this->processExternalStore( $row );
$revisions[$key] = $this->splitUpdate( $row, 'rev' );
}
@@ -398,12 +401,12 @@ abstract class RevisionStorage extends DbStorage {
*/
public function isUpdatingExistingRevisionContentAllowed() {
// All of these are required to do a consistent mechanical update.
- $requiredColumnNames = array(
- 'rev_content',
- 'rev_content_length',
- 'rev_flags',
- 'rev_previous_content_length',
- );
+ $requiredColumnNames = [
+ 'rev_content',
+ 'rev_content_length',
+ 'rev_flags',
+ 'rev_previous_content_length',
+ ];
// compare required column names against allowedUpdateColumns
$diff = array_diff( $requiredColumnNames, $this->allowedUpdateColumns );
@@ -485,14 +488,13 @@ abstract class RevisionStorage extends DbStorage {
// The parent calcUpdates does the validation that we're not changing a non-allowed
// field, regardless of whether explicitly passed in, or done by processExternalStore.
- $validatedChangeset = parent::calcUpdates( array(), $unvalidatedChangeset );
+ $validatedChangeset = parent::calcUpdates( [], $unvalidatedChangeset );
return $validatedChangeset;
}
// This is to *UPDATE* a revision. It should hardly ever be used.
// For the most part should insert a new revision. This should only be called
// by maintenance scripts and (future) suppression features.
- //
// It supports updating content, which is only intended for required mechanical
// transformations, such as XSS fixes. However, since this is only intended for
// maintenance scripts, these columns must first be temporarily added to
@@ -507,17 +509,16 @@ abstract class RevisionStorage extends DbStorage {
$res = $dbw->update(
'flow_revision',
$this->preprocessSqlArray( $rev ),
- $this->preprocessSqlArray( array( 'rev_id' => $old['rev_id'] ) ),
+ $this->preprocessSqlArray( [ 'rev_id' => $old['rev_id'] ] ),
__METHOD__
);
if ( !( $res && $dbw->affectedRows() ) ) {
return false;
}
}
- return (bool) $this->updateRelated( $changeSet, $old );
+ return (bool)$this->updateRelated( $changeSet, $old );
}
-
// Revisions can only be removed for LIMITED circumstances, in almost all cases
// the offending revision should be updated with appropriate suppression.
// Also note this doesnt delete the whole post, it just deletes the revision.
@@ -526,7 +527,7 @@ abstract class RevisionStorage extends DbStorage {
public function remove( array $row ) {
$res = $this->dbFactory->getDB( DB_MASTER )->delete(
'flow_revision',
- $this->preprocessSqlArray( array( 'rev_id' => $row['rev_id'] ) ),
+ $this->preprocessSqlArray( [ 'rev_id' => $row['rev_id'] ] ),
__METHOD__
);
if ( !$res ) {
@@ -539,7 +540,7 @@ abstract class RevisionStorage extends DbStorage {
* Used to locate the index for a query by ObjectLocator::get()
*/
public function getPrimaryKeyColumns() {
- return array( 'rev_id' );
+ return [ 'rev_id' ];
}
/**
@@ -562,7 +563,7 @@ abstract class RevisionStorage extends DbStorage {
* @return array Remaining rows
*/
protected function splitUpdate( array $row, $prefix = 'rev' ) {
- $rev = array();
+ $rev = [];
foreach ( $row as $key => $value ) {
$keyPrefix = strstr( $key, '_', true );
if ( $keyPrefix === $prefix ) {
diff --git a/Flow/includes/Data/Storage/TopicListStorage.php b/Flow/includes/Data/Storage/TopicListStorage.php
index f36632a8..1c38c7c8 100644
--- a/Flow/includes/Data/Storage/TopicListStorage.php
+++ b/Flow/includes/Data/Storage/TopicListStorage.php
@@ -7,12 +7,23 @@ namespace Flow\Data\Storage;
*/
class TopicListStorage extends BasicDbStorage {
+ protected function doFindQuery( array $preprocessedAttributes, array $options = [] ) {
+ return $this->dbFactory->getDB( DB_SLAVE )->select(
+ [ $this->table, 'flow_workflow' ],
+ [ 'topic_list_id', 'topic_id', 'workflow_last_update_timestamp' ],
+ $preprocessedAttributes,
+ __METHOD__ . " ({$this->table})",
+ $options,
+ [ 'flow_workflow' => [ 'INNER JOIN', 'workflow_id = topic_id' ] ]
+ );
+ }
+
/**
* We need workflow_last_update_timestamp for updating
* the ordering in cache
*/
public function insert( array $rows ) {
- $updateRows = array();
+ $updateRows = [];
foreach ( $rows as $i => $row ) {
// Note, entries added directly to the index (rather than from DB
// fill) do have this key, but obviously it can't be used.
diff --git a/Flow/includes/Data/Utils/Merger.php b/Flow/includes/Data/Utils/Merger.php
index ee4e6194..258b6897 100644
--- a/Flow/includes/Data/Utils/Merger.php
+++ b/Flow/includes/Data/Utils/Merger.php
@@ -18,11 +18,11 @@ class Merger {
* @param string $default Value to use when no matching foreign value can be located
* @return array $source array with all found foreign key values merged
*/
- static public function merge( array $source, $fromKey, $callable, $name = null, $default = '' ) {
+ public static function merge( array $source, $fromKey, $callable, $name = null, $default = '' ) {
if ( $name === null ) {
$name = $fromKey;
}
- $ids = array();
+ $ids = [];
foreach ( $source as $row ) {
$id = $row[$fromKey];
if ( $id !== null ) {
@@ -57,11 +57,11 @@ class Merger {
* @param string $default Value to use when no matching foreign value can be located
* @return array $multiSource array with all found foreign key values merged
*/
- static public function mergeMulti( array $multiSource, $fromKey, $callable, $name = null, $default = '' ) {
+ public static function mergeMulti( array $multiSource, $fromKey, $callable, $name = null, $default = '' ) {
if ( $name === null ) {
$name = $fromKey;
}
- $ids = array();
+ $ids = [];
foreach ( $multiSource as $source ) {
if ( $source === null ) {
continue;
diff --git a/Flow/includes/Data/Utils/MultiDimArray.php b/Flow/includes/Data/Utils/MultiDimArray.php
index c96ec93c..a621c438 100644
--- a/Flow/includes/Data/Utils/MultiDimArray.php
+++ b/Flow/includes/Data/Utils/MultiDimArray.php
@@ -29,7 +29,7 @@ use RecursiveIteratorIterator;
* )
*/
class MultiDimArray implements \ArrayAccess {
- protected $data = array();
+ protected $data = [];
public function all() {
return $this->data;
@@ -44,9 +44,9 @@ class MultiDimArray implements \ArrayAccess {
public function offsetSet( $offset, $value ) {
$data =& $this->data;
- foreach ( (array) $offset as $key ) {
+ foreach ( (array)$offset as $key ) {
if ( !isset( $data[$key] ) ) {
- $data[$key] = array();
+ $data[$key] = [];
}
$data =& $data[$key];
}
@@ -55,11 +55,11 @@ class MultiDimArray implements \ArrayAccess {
public function offsetGet( $offset ) {
$data =& $this->data;
- foreach ( (array) $offset as $key ) {
+ foreach ( (array)$offset as $key ) {
if ( !isset( $data[$key] ) ) {
throw new \OutOfBoundsException( 'Does not exist' );
- } elseif ( ! is_array( $data ) ) {
- throw new \OutOfBoundsException( "Requested offset {$key} (full offset ".implode(':', $offset)."), but $data is not an array." );
+ } elseif ( !is_array( $data ) ) {
+ throw new \OutOfBoundsException( "Requested offset {$key} (full offset ".implode( ':', $offset )."), but $data is not an array." );
}
$data =& $data[$key];
}
@@ -67,10 +67,10 @@ class MultiDimArray implements \ArrayAccess {
}
public function offsetUnset( $offset ) {
- $offset = (array) $offset;
+ $offset = (array)$offset;
// while loop is required to not leave behind empty arrays
$first = true;
- while( $offset ) {
+ while ( $offset ) {
$end = array_pop( $offset );
$data =& $this->data;
foreach ( $offset as $key ) {
@@ -88,11 +88,11 @@ class MultiDimArray implements \ArrayAccess {
public function offsetExists( $offset ) {
$data =& $this->data;
- foreach ( (array) $offset as $key ) {
+ foreach ( (array)$offset as $key ) {
if ( !isset( $data[$key] ) ) {
return false;
- } elseif ( ! is_array( $data ) ) {
- throw new \OutOfBoundsException( "Requested offset {$key} (full offset ".implode(':', $offset)."), but $data is not an array." );
+ } elseif ( !is_array( $data ) ) {
+ throw new \OutOfBoundsException( "Requested offset {$key} (full offset ".implode( ':', $offset )."), but $data is not an array." );
}
$data =& $data[$key];
}
diff --git a/Flow/includes/Data/Utils/RecentChangeFactory.php b/Flow/includes/Data/Utils/RecentChangeFactory.php
index e64a6f26..f1d99a90 100644
--- a/Flow/includes/Data/Utils/RecentChangeFactory.php
+++ b/Flow/includes/Data/Utils/RecentChangeFactory.php
@@ -9,7 +9,7 @@ namespace Flow\Data\Utils;
class RecentChangeFactory {
public function newFromRow( $obj ) {
$rc = \RecentChange::newFromRow( $obj );
- $rc->setExtra( array( 'pageStatus' => 'update' ) );
+ $rc->setExtra( [ 'pageStatus' => 'update' ] );
return $rc;
}
}
diff --git a/Flow/includes/Data/Utils/ResultDuplicator.php b/Flow/includes/Data/Utils/ResultDuplicator.php
index 6f3bacf1..781e5f8a 100644
--- a/Flow/includes/Data/Utils/ResultDuplicator.php
+++ b/Flow/includes/Data/Utils/ResultDuplicator.php
@@ -3,14 +3,12 @@
namespace Flow\Data\Utils;
use Flow\Data\ObjectManager;
-use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
// Better name?
-//
// Add query arrays with a multi-dimensional position
// Merge results with their query value
// Get back result array with same positions as the original query
-//
// Maintains merge ordering
class ResultDuplicator {
/**
@@ -43,7 +41,7 @@ class ResultDuplicator {
/**
* @var array
*/
- protected $queries = array();
+ protected $queries = [];
/**
* @param array $queryKeys
@@ -59,9 +57,9 @@ class ResultDuplicator {
// Add a query and its position. Positions must be unique.
public function add( $query, $position ) {
- $dim = count( (array) $position );
+ $dim = count( (array)$position );
if ( $dim !== $this->dimensions ) {
- throw new InvalidInputException( "Expection position with {$this->dimensions} dimensions, received $dim", 'invalid-input' );
+ throw new InvalidParameterException( "Expected position with {$this->dimensions} dimensions, received $dim" );
}
$query = ObjectManager::splitFromRow( $query, $this->queryKeys );
if ( $query === null ) {
@@ -97,8 +95,8 @@ class ResultDuplicator {
// merge() wasn't necessarily called in the same order as add(), this walks back through
// the results to put them in the desired order with the correct keys.
- static public function sortResult( array $order, MultiDimArray $result, $dimensions ) {
- $final = array();
+ public static function sortResult( array $order, MultiDimArray $result, $dimensions ) {
+ $final = [];
foreach ( $order as $position => $query ) {
if ( $dimensions > 1 ) {
$final[$position] = self::sortResult( $query, $result, $dimensions - 1 );
@@ -111,4 +109,3 @@ class ResultDuplicator {
return $final;
}
}
-
diff --git a/Flow/includes/Data/Utils/SortArrayByKeys.php b/Flow/includes/Data/Utils/SortArrayByKeys.php
index 7eec2e1f..c3eea760 100644
--- a/Flow/includes/Data/Utils/SortArrayByKeys.php
+++ b/Flow/includes/Data/Utils/SortArrayByKeys.php
@@ -22,7 +22,7 @@ class SortArrayByKeys {
return self::compare( $a, $b, $this->keys, $this->strict );
}
- static public function compare( $a, $b, $keys, $strict = false ) {
+ public static function compare( $a, $b, $keys, $strict = false ) {
$key = array_shift( $keys );
if ( !isset( $a[$key] ) ) {
return isset( $b[$key] ) ? -1 : 0;
diff --git a/Flow/includes/Data/Utils/SortRevisionsByRevisionId.php b/Flow/includes/Data/Utils/SortRevisionsByRevisionId.php
new file mode 100644
index 00000000..70e7bbe2
--- /dev/null
+++ b/Flow/includes/Data/Utils/SortRevisionsByRevisionId.php
@@ -0,0 +1,55 @@
+<?php
+
+namespace Flow\Data\Utils;
+
+use Flow\InvalidParameterException;
+use Flow\Model\AbstractRevision;
+
+/**
+ * Sorts AbstractRevision objects by revision ID
+ */
+class SortRevisionsByRevisionId {
+ /**
+ * Order, either ASC or DESC.
+ *
+ * @var string
+ */
+ protected $order;
+
+ /**
+ * @param string $order ASC or DESC
+ * @throws InvalidParameterException
+ */
+ public function __construct( $order ) {
+ if ( $order !== 'ASC' && $order !== 'DESC' ) {
+ throw new InvalidParameterException( "Must specify ASC or DESC" );
+ }
+
+ $this->order = $order;
+ }
+
+ /**
+ * Compares two revisions
+ *
+ * @param AbstractRevision $a
+ * @param AbstractRevision $b
+ */
+ public function __invoke( AbstractRevision $a, AbstractRevision $b ) {
+ $aId = $a->getRevisionId()->getAlphadecimal();
+ $bId = $b->getRevisionId()->getAlphadecimal();
+
+ if ( $aId < $bId ) {
+ $result = -1;
+ } elseif ( $aId > $bId ) {
+ $result = 1;
+ } else {
+ $result = 0;
+ }
+
+ if ( $this->order === 'ASC' ) {
+ return $result;
+ } else {
+ return -$result;
+ }
+ }
+}
diff --git a/Flow/includes/Data/Utils/UserMerger.php b/Flow/includes/Data/Utils/UserMerger.php
index b8f4c075..b4ee0ec5 100644
--- a/Flow/includes/Data/Utils/UserMerger.php
+++ b/Flow/includes/Data/Utils/UserMerger.php
@@ -2,7 +2,7 @@
namespace Flow\Data\Utils;
-use EchoBatchRowIterator;
+use BatchRowIterator;
use Flow\Data\ManagerGroup;
use Flow\DbFactory;
use Flow\Model\AbstractRevision;
@@ -33,39 +33,39 @@ class UserMerger {
public function __construct( DbFactory $dbFactory, ManagerGroup $storage ) {
$this->dbFactory = $dbFactory;
$this->storage = $storage;
- $this->config = array(
- 'flow_tree_revision' => array(
- 'pk' => array( 'tree_rev_id' ),
- 'userColumns' => array(
+ $this->config = [
+ 'flow_tree_revision' => [
+ 'pk' => [ 'tree_rev_id' ],
+ 'userColumns' => [
'tree_orig_user_id' => 'getCreatorTuple',
- ),
- 'load' => array( $this, 'loadFromTreeRevision' ),
- ),
+ ],
+ 'load' => [ $this, 'loadFromTreeRevision' ],
+ ],
- 'flow_revision' => array(
- 'pk' => array( 'rev_id' ),
- 'userColumns' => array(
+ 'flow_revision' => [
+ 'pk' => [ 'rev_id' ],
+ 'userColumns' => [
'rev_user_id' => 'getUserTuple',
'rev_mod_user_id' => 'getModeratedByTuple',
'rev_edit_user_id' => 'getLastContentEditUserTuple',
- ),
- 'load' => array( $this, 'loadFromRevision' ),
- 'loadColumns' => array( 'rev_type' ),
- ),
- );
+ ],
+ 'load' => [ $this, 'loadFromRevision' ],
+ 'loadColumns' => [ 'rev_type' ],
+ ],
+ ];
}
/**
* @return array
*/
public function getAccountFields() {
- $fields = array();
+ $fields = [];
$dbw = $this->dbFactory->getDb( DB_MASTER );
foreach ( $this->config as $table => $config ) {
- $row = array(
+ $row = [
'db' => $dbw,
$table,
- );
+ ];
foreach ( array_keys( $config['userColumns'] ) as $column ) {
$row[] = $column;
}
@@ -78,16 +78,16 @@ class UserMerger {
* Called after all databases have been updated. Needs to purge any
* cache that contained data about $oldUser
*
- * @param integer $oldUserId
- * @param integer $newUserId
+ * @param int $oldUserId
+ * @param int $newUserId
*/
public function finalizeMerge( $oldUserId, $newUserId ) {
$dbw = $this->dbFactory->getDb( DB_MASTER );
foreach ( $this->config as $table => $config ) {
foreach ( $config['userColumns'] as $column => $userTupleGetter ) {
- $it = new EchoBatchRowIterator( $dbw, $table, $config['pk'], 500 );
+ $it = new BatchRowIterator( $dbw, $table, $config['pk'], 500 );
// The database is migrated, so look for the new user id
- $it->addConditions( array( $column => $newUserId ) );
+ $it->addConditions( [ $column => $newUserId ] );
if ( isset( $config['loadColumns'] ) ) {
$it->setFetchColumns( $config['loadColumns'] );
}
@@ -98,7 +98,7 @@ class UserMerger {
/**
* @param Iterator $it
- * @param integer $oldUserId
+ * @param int $oldUserId
* @param callable $callback Receives a single row, returns domain object or null
* @param string $userTupleGetter Method to call on domain object that will return
* a UserTuple instance.
@@ -114,7 +114,7 @@ class UserMerger {
// the db with new user ids, or the cache with old user ids.
// We need to tweak this object to look like the old user ids and then
// purge caches so they get the old user id cache keys.
- $tuple = call_user_func( array( $obj, $userTupleGetter ) );
+ $tuple = call_user_func( [ $obj, $userTupleGetter ] );
if ( !$tuple ) {
continue;
}
@@ -141,11 +141,11 @@ class UserMerger {
* @return AbstractRevision|null
*/
protected function loadFromRevision( $row ) {
- $revTypes = array(
+ $revTypes = [
'header' => 'Flow\Model\Header',
'post-summary' => 'Flow\Model\PostSummary',
'post' => 'Flow\Model\PostRevision',
- );
+ ];
if ( !isset( $revTypes[$row->rev_type] ) ) {
wfDebugLog( 'Flow', __METHOD__ . ': Unknown revision type ' . $row->rev_type . ' did not merge ' . UUID::create( $row->rev_id )->getAlphadecimal() );
return null;
diff --git a/Flow/includes/DbFactory.php b/Flow/includes/DbFactory.php
index 374255ab..9790d98f 100644
--- a/Flow/includes/DbFactory.php
+++ b/Flow/includes/DbFactory.php
@@ -8,13 +8,11 @@ namespace Flow;
* anything that needs to talk to the database.
*
* The factory receives, in its constructor, the wiki name and cluster name
- * that flow specific data is stored on. Multiple wiki's can and should be
- * using the same wiki name and cluster to share flow specific data. These values
- * are used. The $wiki parameter of getDB and getLB must be null to receive
- * the flow database.
+ * that Flow-specific data is stored on. Multiple wiki's can and should be
+ * using the same wiki name and cluster to share Flow-specific data. These values
+ * are used.
*
- * To access core tables, use wfGetDB() etc. This is solely for Flow-specific
- * data, which may live on a separate database.
+ * There are also get getWikiLB and getWikiDB for the main wiki database.
*/
class DbFactory {
/**
@@ -33,8 +31,8 @@ class DbFactory {
protected $forceMaster = false;
/**
- * @var string|boolean $wiki Wiki ID, or false for the current wiki
- * @var string|boolean $cluster External storage cluster, or false for core
+ * @param string|bool $wiki Wiki ID, or false for the current wiki
+ * @param string|bool $cluster External storage cluster, or false for core
*/
public function __construct( $wiki = false, $cluster = false ) {
$this->wiki = $wiki;
@@ -46,17 +44,19 @@ class DbFactory {
}
/**
- * @param integer $db index of the connection to get. DB_MASTER|DB_SLAVE.
- * @param mixed $groups query groups. An array of group names that this query
- * belongs to.
- * @return \DatabaseBase
+ * Gets a database connection for the Flow-specific database.
+ *
+ * @param int $db index of the connection to get. DB_MASTER|DB_SLAVE.
+ * @return \Database
*/
- public function getDB( $db, $groups = array() ) {
- return $this->getLB()->getConnection( $this->forceMaster ? DB_MASTER : $db, $groups, $this->wiki );
+ public function getDB( $db ) {
+ return $this->getLB()->getConnection( $this->forceMaster ? DB_MASTER : $db, [], $this->wiki );
}
/**
- * @return \LoadBalancer
+ * Gets a load balancer for the Flow-specific database.
+ *
+ * @return \Wikimedia\Rdbms\LoadBalancer
*/
public function getLB() {
if ( $this->cluster !== false ) {
@@ -67,22 +67,20 @@ class DbFactory {
}
/**
- * Mockable version of wfGetDB.
+ * Gets a database connection for the main wiki database. Mockable version of wfGetDB.
*
- * @param integer $db index of the connection to get. DB_MASTER|DB_SLAVE.
- * @param array $groups query groups. An array of group names that this query
- * belongs to.
- * @param string|boolean $wiki The wiki ID, or false for the current wiki
+ * @param int $db index of the connection to get. DB_MASTER|DB_SLAVE.
+ * @param string|bool $wiki The wiki ID, or false for the current wiki
* @return \DatabaseBase
*/
- public function getWikiDB( $db, $groups = array(), $wiki = false ) {
- return wfGetDB( $this->forceMaster ? DB_MASTER : $db, $groups, $wiki );
+ public function getWikiDB( $db, $wiki = false ) {
+ return wfGetDB( $this->forceMaster ? DB_MASTER : $db, [], $wiki );
}
/**
- * Mockable version of wfGetLB.
+ * Gets a load balancer for the main wiki database. Mockable version of wfGetLB.
*
- * @param string|boolean $wiki wiki ID, or false for the current wiki
+ * @param string|bool $wiki wiki ID, or false for the current wiki
* @return \LoadBalancer
*/
public function getWikiLB( $wiki = false ) {
@@ -95,4 +93,12 @@ class DbFactory {
public function waitForSlaves() {
wfWaitForSlaves( false, $this->wiki, $this->cluster );
}
+
+ /**
+ * Roll back changes on all databases.
+ * @see LBFactory::rollbackMasterChanges
+ */
+ public function rollbackMasterChanges( $fname = __METHOD__ ) {
+ wfGetLBFactory()->rollbackMasterChanges( $fname );
+ }
}
diff --git a/Flow/includes/Dump/Exporter.php b/Flow/includes/Dump/Exporter.php
new file mode 100644
index 00000000..9a43aba8
--- /dev/null
+++ b/Flow/includes/Dump/Exporter.php
@@ -0,0 +1,439 @@
+<?php
+
+namespace Flow\Dump;
+
+use BatchRowIterator;
+use DatabaseBase;
+use Exception;
+use Flow\Collection\PostSummaryCollection;
+use Flow\Container;
+use Flow\Data\ManagerGroup;
+use Flow\Model\AbstractRevision;
+use Flow\Model\Header;
+use Flow\Model\PostRevision;
+use Flow\Model\PostSummary;
+use Flow\Model\Workflow;
+use Flow\RevisionActionPermissions;
+use Flow\Search\Iterators\AbstractIterator;
+use Flow\Search\Iterators\HeaderIterator;
+use Flow\Search\Iterators\TopicIterator;
+use ReflectionProperty;
+use User;
+use WikiExporter;
+use Xml;
+use Wikimedia\Timestamp\TimestampException;
+
+class Exporter extends WikiExporter {
+ /**
+ * Map of [db column name => xml attribute name]
+ *
+ * @var array
+ */
+ public static $map = [
+ 'rev_id' => 'id',
+ 'rev_user_id' => 'userid',
+ 'rev_user_ip' => 'userip',
+ 'rev_user_wiki' => 'userwiki',
+ 'rev_parent_id' => 'parentid',
+ 'rev_change_type' => 'changetype',
+ 'rev_type' => 'type',
+ 'rev_type_id' => 'typeid',
+ 'rev_content' => 'content',
+ 'rev_content_url' => 'contenturl',
+ 'rev_flags' => 'flags',
+ 'rev_mod_state' => 'modstate',
+ 'rev_mod_user_id' => 'moduserid',
+ 'rev_mod_user_ip' => 'moduserip',
+ 'rev_mod_user_wiki' => 'moduserwiki',
+ 'rev_mod_timestamp' => 'modtimestamp',
+ 'rev_mod_reason' => 'modreason',
+ 'rev_last_edit_id' => 'lasteditid',
+ 'rev_edit_user_id' => 'edituserid',
+ 'rev_edit_user_ip' => 'edituserip',
+ 'rev_edit_user_wiki' => 'edituserwiki',
+ 'rev_content_length' => 'contentlength',
+ 'rev_previous_content_length' => 'previouscontentlength',
+
+ 'tree_parent_id' => 'treeparentid',
+ 'tree_rev_descendant_id' => 'treedescendantid',
+ 'tree_rev_id' => 'treerevid',
+ 'tree_orig_user_id' => 'treeoriguserid',
+ 'tree_orig_user_ip' => 'treeoriguserip',
+ 'tree_orig_user_wiki' => 'treeoriguserwiki',
+ ];
+
+ /**
+ * @var ReflectionProperty $prevRevisionProperty Previous revision property
+ */
+ protected $prevRevisionProperty;
+
+ /**
+ * @var ReflectionProperty $changeTypeProperty Change type property
+ */
+ protected $changeTypeProperty;
+
+ /**
+ * To convert between local and global user ids
+ *
+ * @var \CentralIdLookup
+ */
+ protected $lookup;
+
+ /**
+ * {@inheritDoc}
+ */
+ function __construct( $db, $history = WikiExporter::CURRENT,
+ $buffer = WikiExporter::BUFFER, $text = WikiExporter::TEXT ) {
+ parent::__construct( $db, $history, $buffer, $text );
+ $this->prevRevisionProperty = new ReflectionProperty( 'Flow\Model\AbstractRevision', 'prevRevision' );
+ $this->prevRevisionProperty->setAccessible( true );
+
+ $this->changeTypeProperty = new ReflectionProperty( 'Flow\Model\AbstractRevision', 'changeType' );
+ $this->changeTypeProperty->setAccessible( true );
+
+ $this->lookup = \CentralIdLookup::factory( 'CentralAuth' );
+ }
+
+ public static function schemaVersion() {
+ /*
+ * Be sure to also update the schema/namespace on mediawiki.org when
+ * making any changes:
+ * @see https://gerrit.wikimedia.org/r/#/c/281640/
+ */
+ return '1.0';
+ }
+
+ public function openStream() {
+ global $wgLanguageCode;
+ $version = static::schemaVersion();
+
+ $output = Xml::openElement(
+ 'mediawiki',
+ [
+ 'xmlns' => "http://www.mediawiki.org/xml/flow-$version/",
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => "http://www.mediawiki.org/xml/flow-$version/ http://www.mediawiki.org/xml/flow-$version.xsd",
+ 'version' => $version,
+ 'xml:lang' => $wgLanguageCode
+ ]
+ ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ /**
+ * @param string[]|null $pages Array of DB-prefixed page titles
+ * @param int|null $startId page_id to start from (inclusive)
+ * @param int|null $endId page_id to end (exclusive)
+ * @return BatchRowIterator
+ */
+ public function getWorkflowIterator( array $pages = null, $startId = null, $endId = null ) {
+ /** @var DatabaseBase $dbr */
+ $dbr = Container::get( 'db.factory' )->getDB( DB_SLAVE );
+
+ $iterator = new BatchRowIterator( $dbr, 'flow_workflow', 'workflow_id', 300 );
+ $iterator->setFetchColumns( [ '*' ] );
+ $iterator->addConditions( [ 'workflow_wiki' => wfWikiID() ] );
+ $iterator->addConditions( [ 'workflow_type' => 'discussion' ] );
+
+ if ( $pages ) {
+ $pageConds = [];
+ foreach ( $pages as $page ) {
+ $title = \Title::newFromDBkey( $page );
+ $pageConds[] = $dbr->makeList(
+ [
+ 'workflow_namespace' => $title->getNamespace(),
+ 'workflow_title_text' => $title->getDBkey()
+ ],
+ LIST_AND
+ );
+ }
+
+ $iterator->addConditions( [ $dbr->makeList( $pageConds, LIST_OR ) ] );
+ }
+ if ( $startId ) {
+ $iterator->addConditions( [ 'workflow_page_id >= ' . $dbr->addQuotes( $startId ) ] );
+ }
+ if ( $endId ) {
+ $iterator->addConditions( [ 'workflow_page_id < ' . $dbr->addQuotes( $endId ) ] );
+ }
+
+ return $iterator;
+ }
+
+ /**
+ * @param BatchRowIterator $workflowIterator
+ * @throws Exception
+ * @throws TimestampException
+ * @throws \Flow\Exception\InvalidInputException
+ */
+ public function dump( BatchRowIterator $workflowIterator ) {
+ foreach ( $workflowIterator as $rows ) {
+ foreach ( $rows as $row ) {
+ $workflow = Workflow::fromStorageRow( (array)$row );
+
+ $headerIterator = Container::get( 'search.index.iterators.header' );
+ $topicIterator = Container::get( 'search.index.iterators.topic' );
+ $topicIterator->orderByUUID = true;
+ /** @var AbstractIterator $iterator */
+ foreach ( [ $headerIterator, $topicIterator ] as $iterator ) {
+ $iterator->setPage( $row->workflow_page_id );
+ }
+
+ $this->formatWorkflow( $workflow, $headerIterator, $topicIterator );
+ }
+ }
+ }
+
+ protected function formatWorkflow( Workflow $workflow, HeaderIterator $headerIterator, TopicIterator $topicIterator ) {
+ if ( $workflow->isDeleted() ) {
+ return;
+ }
+
+ $output = Xml::openElement( 'board', [
+ 'id' => $workflow->getId()->getAlphadecimal(),
+ 'title' => $workflow->getOwnerTitle()->getPrefixedDBkey(),
+ ] ) . "\n";
+ $this->sink->write( $output );
+
+ foreach ( $headerIterator as $revision ) {
+ /** @var Header $revision */
+ $this->formatHeader( $revision );
+ }
+ foreach ( $topicIterator as $revision ) {
+ /** @var PostRevision $revision */
+ $this->formatTopic( $revision );
+ }
+
+ $output = Xml::closeElement( 'board' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatTopic( PostRevision $revision ) {
+ if ( !$this->isAllowed( $revision ) ) {
+ return;
+ }
+
+ $output = Xml::openElement( 'topic', [
+ 'id' => $revision->getCollectionId()->getAlphadecimal(),
+ ] ) . "\n";
+ $this->sink->write( $output );
+
+ $this->formatPost( $revision );
+
+ // find summary for this topic & add it as revision
+ $summaryCollection = PostSummaryCollection::newFromId( $revision->getCollectionId() );
+ try {
+ /** @var PostSummary $summary */
+ $summary = $summaryCollection->getLastRevision();
+ $this->formatSummary( $summary );
+ } catch ( \Exception $e ) {
+ // no summary - that's ok!
+ }
+
+ $output = Xml::closeElement( 'topic' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatHeader( Header $revision ) {
+ if ( !$this->isAllowed( $revision ) ) {
+ return;
+ }
+
+ $output = Xml::openElement( 'description', [
+ 'id' => $revision->getCollectionId()->getAlphadecimal()
+ ] ) . "\n";
+ $this->sink->write( $output );
+
+ $this->formatRevisions( $revision );
+
+ $output = Xml::closeElement( 'description' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatPost( PostRevision $revision ) {
+ if ( !$this->isAllowed( $revision ) ) {
+ return;
+ }
+
+ $output = Xml::openElement( 'post', [
+ 'id' => $revision->getCollectionId()->getAlphadecimal()
+ ] ) . "\n";
+ $this->sink->write( $output );
+
+ $this->formatRevisions( $revision );
+
+ if ( $revision->getChildren() ) {
+ $output = Xml::openElement( 'children' ) . "\n";
+ $this->sink->write( $output );
+
+ foreach ( $revision->getChildren() as $child ) {
+ $this->formatPost( $child );
+ }
+
+ $output = Xml::closeElement( 'children' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ $output = Xml::closeElement( 'post' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatSummary( PostSummary $revision ) {
+ if ( !$this->isAllowed( $revision ) ) {
+ return;
+ }
+
+ $output = Xml::openElement( 'summary', [
+ 'id' => $revision->getCollectionId()->getAlphadecimal()
+ ] ) . "\n";
+ $this->sink->write( $output );
+
+ $this->formatRevisions( $revision );
+
+ $output = Xml::closeElement( 'summary' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatRevisions( AbstractRevision $revision ) {
+ $output = Xml::openElement( 'revisions' ) . "\n";
+ $this->sink->write( $output );
+
+ $collection = $revision->getCollection();
+ if ( $this->history === WikiExporter::FULL ) {
+ /** @var AbstractRevision[] $revisions */
+ $revisions = array_reverse( $collection->getAllRevisions() );
+ $prevId = null;
+
+ foreach ( $revisions as $revision ) {
+ if ( $this->isAllowed( $revision ) ) {
+ if ( $prevId !== null ) {
+ // override parent id: this is used to get rid of gaps
+ // that are caused by moderated items, where the
+ // revision tree would be incorrect
+ $this->prevRevisionProperty->setValue( $revision, $prevId );
+
+ // Since $prevId is set, we know
+ // there was a gap, and the original
+ // hide-topic/delete-topic/suppress-topic
+ // was removed. Since that is used for
+ // listeners in FlowActions.php, we replace
+ // restore-topic with edit-title and make a
+ // null edit (we don't do null edits in the
+ // normal application flow, but this
+ // provides a way to replace restore).
+ $oldChangeType = $revision->getChangeType();
+
+ if ( $oldChangeType === 'restore-topic' ) {
+ $this->changeTypeProperty->setValue( $revision, 'edit-title' );
+ }
+
+ if ( $oldChangeType === 'restore-post' ) {
+ $this->changeTypeProperty->setValue( $revision, 'edit-post' );
+ }
+
+ $prevId = null;
+ }
+ $this->formatRevision( $revision );
+ } elseif ( $prevId === null ) {
+ // if revision can't be dumped, store its parent id so we
+ // can re-apply it to the next one that can be displayed, so
+ // we don't have gaps
+ $prevId = $revision->getPrevRevisionId();
+ }
+ }
+ } elseif ( $this->history === WikiExporter::CURRENT ) {
+ $first = $collection->getFirstRevision();
+
+ // storing only last revision won't work (it'll reference non-existing
+ // parents): we'll construct a bogus revision with most of the original
+ // metadata, but with the current content & id (= timestamp)
+ $first = $first->toStorageRow( $first );
+ $last = $revision->toStorageRow( $revision );
+ $first['rev_id'] = $last['rev_id'];
+ $first['rev_content'] = $last['rev_content'];
+ $first['rev_flags'] = $last['rev_flags'];
+ if ( isset( $first['tree_rev_id'] ) ) {
+ // PostRevision-only: tree_rev_id must match rev_id
+ $first['tree_rev_id'] = $first['rev_id'];
+ }
+
+ // clear buffered cache, to make sure it doesn't serve the existing (already
+ // loaded) revision when trying to turn our bogus mixed data into a revision
+ /** @var ManagerGroup $storage */
+ $storage = Container::get( 'storage' );
+ $storage->clear();
+
+ $mix = $revision->fromStorageRow( $first );
+
+ $this->formatRevision( $mix );
+ }
+
+ $output = Xml::closeElement( 'revisions' ) . "\n";
+ $this->sink->write( $output );
+ }
+
+ protected function formatRevision( AbstractRevision $revision ) {
+ if ( !$this->isAllowed( $revision ) ) {
+ return;
+ }
+
+ $attribs = $revision->toStorageRow( $revision );
+
+ // make sure there are no leftover key columns (unknown to $attribs)
+ $keys = array_intersect_key( static::$map, $attribs );
+ // now make sure $values columns are in the same order as $keys are
+ // (array_merge) and there are no leftover columns (array_intersect_key)
+ $values = array_intersect_key( array_merge( $keys, $attribs ), $keys );
+ // combine them
+ $attribs = array_combine( $keys, $values );
+ // and get rid of columns with null values
+ $attribs = array_filter( $attribs, function ( $value ) {
+ return $value !== null;
+ } );
+
+ // references to external store etc. are useless; we'll include the real
+ // content as node text
+ unset( $attribs['content'], $attribs['contenturl'] );
+ $format = $revision->getContentFormat();
+ $attribs['flags'] = 'utf-8,' . $format;
+
+ if ( $this->lookup ) {
+ $userIdFields = [ 'userid', 'treeoriguserid', 'moduserid', 'edituserid' ];
+ foreach ( $userIdFields as $userIdField ) {
+ if ( isset( $attribs[ $userIdField ] ) ) {
+ $user = User::newFromId( $attribs[ $userIdField ] );
+ $globalUserId = $this->lookup->centralIdFromLocalUser(
+ $user,
+ \CentralIdLookup::AUDIENCE_RAW
+ );
+ if ( $globalUserId ) {
+ $attribs[ 'global' . $userIdField ] = $globalUserId;
+ }
+ }
+ }
+ }
+
+ $output = Xml::element(
+ 'revision',
+ $attribs,
+ $revision->getContent( $format )
+ ) . "\n";
+ // filter out bad characters that may have crept into old revisions
+ $output = preg_replace( '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $output );
+ $this->sink->write( $output );
+ }
+
+ /**
+ * Test if anon users are allowed to view a particular revision.
+ *
+ * @param AbstractRevision $revision
+ * @return bool
+ */
+ protected function isAllowed( AbstractRevision $revision ) {
+ $user = User::newFromId( 0 );
+ $actions = Container::get( 'flow_actions' );
+ $permissions = new RevisionActionPermissions( $actions, $user );
+
+ return $permissions->isAllowed( $revision, 'view' );
+ }
+}
diff --git a/Flow/includes/Dump/Importer.php b/Flow/includes/Dump/Importer.php
new file mode 100644
index 00000000..1ef62797
--- /dev/null
+++ b/Flow/includes/Dump/Importer.php
@@ -0,0 +1,400 @@
+<?php
+
+namespace Flow\Dump;
+
+use Flow\Container;
+use Flow\Data\ManagerGroup;
+use Flow\DbFactory;
+use Flow\Import\HistoricalUIDGenerator;
+use Flow\Import\ImportException;
+use Flow\Model\AbstractRevision;
+use Flow\Model\Header;
+use Flow\Model\PostRevision;
+use Flow\Model\PostSummary;
+use Flow\Model\TopicListEntry;
+use Flow\Model\UUID;
+use Flow\Model\Workflow;
+use Flow\OccupationController;
+use MWException;
+use WikiImporter;
+use XMLReader;
+
+class Importer {
+ /**
+ * @var WikiImporter
+ */
+ protected $importer;
+
+ /**
+ * @var ManagerGroup|null
+ */
+ protected $storage;
+
+ /**
+ * The most recently imported board workflow (if any).
+ *
+ * @var Workflow|null
+ */
+ protected $boardWorkflow;
+
+ /**
+ * The most recently imported topic workflow (if any).
+ *
+ * @var Workflow|null
+ */
+ protected $topicWorkflow;
+
+ /**
+ * @var array Map of old to new IDs
+ */
+ protected $idMap = [];
+
+ /**
+ * To convert between global and local user ids
+ *
+ * @var \CentralIdLookup
+ */
+ protected $lookup;
+
+ /**
+ * Whether the current board is being imported in trans-wiki mode
+ *
+ * @var bool
+ */
+ protected $transWikiMode = false;
+
+ /**
+ * @param WikiImporter $importer
+ */
+ public function __construct( WikiImporter $importer ) {
+ $this->importer = $importer;
+ $this->lookup = \CentralIdLookup::factory( 'CentralAuth' );
+ }
+
+ /**
+ * @param ManagerGroup $storage
+ */
+ public function setStorage( ManagerGroup $storage ) {
+ $this->storage = $storage;
+ }
+
+ /**
+ * @param object $object
+ * @param array $metadata
+ */
+ protected function put( $object, array $metadata = [] ) {
+ if ( $this->storage ) {
+ $this->storage->put( $object, [ 'imported' => true ] + $metadata );
+
+ // prevent memory from being filled up
+ $this->storage->clear();
+
+ // keep workflow objects around, so follow-up `put`s (e.g. to update
+ // last_update_timestamp) don't confuse it for a new object
+ foreach ( [ $this->boardWorkflow, $this->topicWorkflow ] as $object ) {
+ if ( $object ) {
+ $this->storage->getStorage( get_class( $object ) )->merge( $object );
+ }
+ }
+ }
+ }
+
+ public function handleBoard() {
+ $this->checkTransWikiMode(
+ $this->importer->nodeAttribute( 'id' ),
+ $this->importer->nodeAttribute( 'title' )
+ );
+
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter board handler for ' . $id );
+
+ $uuid = UUID::create( $id );
+ $title = \Title::newFromDBkey( $this->importer->nodeAttribute( 'title' ) );
+
+ $this->boardWorkflow = Workflow::fromStorageRow( [
+ 'workflow_id' => $uuid->getAlphadecimal(),
+ 'workflow_type' => 'discussion',
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_page_id' => $title->getArticleID(),
+ 'workflow_namespace' => $title->getNamespace(),
+ 'workflow_title_text' => $title->getDBkey(),
+ 'workflow_last_update_timestamp' => $uuid->getTimestamp( TS_MW ),
+ ] );
+
+ // create page if it does not yet exist
+ /** @var OccupationController $occupationController */
+ $occupationController = Container::get( 'occupation_controller' );
+ $creationStatus = $occupationController->safeAllowCreation( $title, $occupationController->getTalkpageManager() );
+ if ( !$creationStatus->isOK() ) {
+ throw new MWException( $creationStatus->getWikiText() );
+ }
+
+ $ensureStatus = $occupationController->ensureFlowRevision( new \Article( $title ), $this->boardWorkflow );
+ if ( !$ensureStatus->isOK() ) {
+ throw new MWException( $ensureStatus->getWikiText() );
+ }
+
+ $this->put( $this->boardWorkflow, [] );
+ }
+
+ public function handleHeader() {
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter description handler for ' . $id );
+
+ $metadata = [ 'workflow' => $this->boardWorkflow ];
+
+ $revisions = $this->getRevisions( [ 'Flow\\Model\\Header', 'fromStorageRow' ] );
+ foreach ( $revisions as $revision ) {
+ $this->put( $revision, $metadata );
+ }
+
+ /** @var Header $revision */
+ $revision = end( $revisions );
+ $this->boardWorkflow->updateLastUpdated( $revision->getRevisionId() );
+ $this->put( $this->boardWorkflow, [] );
+ }
+
+ public function handleTopic() {
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter topic handler for ' . $id );
+
+ $uuid = UUID::create( $id );
+ $title = $this->boardWorkflow->getArticleTitle();
+
+ $this->topicWorkflow = Workflow::fromStorageRow( [
+ 'workflow_id' => $uuid->getAlphadecimal(),
+ 'workflow_type' => 'topic',
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_page_id' => $title->getArticleID(),
+ 'workflow_namespace' => $title->getNamespace(),
+ 'workflow_title_text' => $title->getDBkey(),
+ 'workflow_last_update_timestamp' => $uuid->getTimestamp( TS_MW ),
+ ] );
+ $topicListEntry = TopicListEntry::create( $this->boardWorkflow, $this->topicWorkflow );
+
+ $metadata = [
+ 'board-workflow' => $this->boardWorkflow,
+ 'workflow' => $this->topicWorkflow,
+ // @todo: topic-title & first-post? (used only in NotificationListener)
+ ];
+
+ // create page if it does not yet exist
+ /** @var OccupationController $occupationController */
+ $occupationController = Container::get( 'occupation_controller' );
+ $creationStatus = $occupationController->safeAllowCreation(
+ $this->topicWorkflow->getArticleTitle(),
+ $occupationController->getTalkpageManager()
+ );
+ if ( !$creationStatus->isOK() ) {
+ throw new MWException( $creationStatus->getWikiText() );
+ }
+
+ $ensureStatus = $occupationController->ensureFlowRevision(
+ new \Article( $this->topicWorkflow->getArticleTitle() ),
+ $this->topicWorkflow
+ );
+ if ( !$ensureStatus->isOK() ) {
+ throw new MWException( $ensureStatus->getWikiText() );
+ }
+
+ $this->put( $this->topicWorkflow, $metadata );
+ $this->put( $topicListEntry, $metadata );
+ }
+
+ public function handlePost() {
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter post handler for ' . $id );
+
+ $metadata = [
+ 'workflow' => $this->topicWorkflow
+ // @todo: topic-title? (used only in NotificationListener)
+ ];
+
+ $revisions = $this->getRevisions( [ 'Flow\\Model\\PostRevision', 'fromStorageRow' ] );
+ foreach ( $revisions as $revision ) {
+ $this->put( $revision, $metadata );
+ }
+
+ /** @var PostRevision $revision */
+ $revision = end( $revisions );
+ $this->topicWorkflow->updateLastUpdated( $revision->getRevisionId() );
+ $this->put( $this->topicWorkflow, $metadata );
+ }
+
+ public function handleSummary() {
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter summary handler for ' . $id );
+
+ $metadata = [ 'workflow' => $this->topicWorkflow ];
+
+ $revisions = $this->getRevisions( [ 'Flow\\Model\\PostSummary', 'fromStorageRow' ] );
+ foreach ( $revisions as $revision ) {
+ $this->put( $revision, $metadata );
+ }
+
+ /** @var PostSummary $revision */
+ $revision = end( $revisions );
+ $this->topicWorkflow->updateLastUpdated( $revision->getRevisionId() );
+ $this->put( $this->topicWorkflow, $metadata );
+ }
+
+ /**
+ * @param callable $callback The relevant fromStorageRow callback
+ * @return AbstractRevision[]
+ */
+ protected function getRevisions( $callback ) {
+ $revisions = [];
+
+ // keep processing <revision> nodes until </revisions>
+ while ( $this->importer->getReader()->localName !== 'revisions' || $this->importer->getReader()->nodeType !== XMLReader::END_ELEMENT ) {
+ if ( $this->importer->getReader()->localName === 'revision' ) {
+ $revisions[] = $this->getRevision( $callback );
+ }
+ $this->importer->getReader()->read();
+ }
+
+ return $revisions;
+ }
+
+ /**
+ * @param callable $callback The relevant fromStorageRow callback
+ * @return AbstractRevision
+ */
+ protected function getRevision( $callback ) {
+ $id = $this->mapId( $this->importer->nodeAttribute( 'id' ) );
+ $this->importer->debug( 'Enter revision handler for ' . $id );
+
+ // isEmptyElement will no longer be valid after we've started iterating
+ // the attributes
+ $empty = $this->importer->getReader()->isEmptyElement;
+
+ $attribs = [];
+
+ $this->importer->getReader()->moveToFirstAttribute();
+ do {
+ $attribs[$this->importer->getReader()->name] = $this->importer->getReader()->value;
+ } while ( $this->importer->getReader()->moveToNextAttribute() );
+
+ $idFields = [ 'id', 'typeid', 'treedescendantid', 'treerevid', 'parentid', 'treeparentid', 'lasteditid' ];
+ foreach ( $idFields as $idField ) {
+ if ( isset( $attribs[ $idField ] ) ) {
+ $attribs[ $idField ] = $this->mapId( $attribs[ $idField ] );
+ }
+ }
+
+ if ( $this->transWikiMode && $this->lookup ) {
+ $userFields = [ 'user', 'treeoriguser', 'moduser', 'edituser' ];
+ foreach ( $userFields as $userField ) {
+ $globalUserIdField = 'global' . $userField . 'id';
+ if ( isset( $attribs[ $globalUserIdField ] ) ) {
+ $localUser = $this->lookup->localUserFromCentralId(
+ $attribs[ $globalUserIdField ],
+ \CentralIdLookup::AUDIENCE_RAW
+ );
+ if ( !$localUser ) {
+ $localUser = $this->createLocalUser( $attribs[ $globalUserIdField ] );
+ }
+ $attribs[ $userField . 'id' ] = $localUser->getId();
+ $attribs[ $userField . 'wiki' ] = wfWikiID();
+ } elseif ( isset( $attribs[ $userField . 'ip' ] ) ) {
+ // make anons local users
+ $attribs[ $userField . 'wiki' ] = wfWikiID();
+ }
+ }
+ }
+
+ // now that we've moved inside the node (to fetch attributes),
+ // nodeContents() is no longer reliable: is uses isEmptyContent (which
+ // will now no longer respond with 'true') to see if the node should be
+ // skipped - use the value we've fetched earlier!
+ $attribs['content'] = $empty ? '' : $this->importer->nodeContents();
+
+ // make sure there are no leftover key columns (unknown to $attribs)
+ $keys = array_intersect_key( array_flip( Exporter::$map ), $attribs );
+ // now make sure $values columns are in the same order as $keys are
+ // (array_merge) and there are no leftover columns (array_intersect_key)
+ $values = array_intersect_key( array_merge( $keys, $attribs ), $keys );
+ // combine them
+ $attribs = array_combine( $keys, $values );
+
+ // now fill in missing attributes
+ $keys = array_fill_keys( array_keys( Exporter::$map ), null );
+ $attribs += $keys;
+
+ return call_user_func( $callback, $attribs );
+ }
+
+ /**
+ * When in trans-wiki mode, return a new id based on the same timestamp
+ *
+ * @param string $id
+ * @return string
+ */
+ private function mapId( $id ) {
+ if ( !$this->transWikiMode ) {
+ return $id;
+ }
+
+ if ( !isset( $this->idMap[ $id ] ) ) {
+ $this->idMap[ $id ] = UUID::create( HistoricalUIDGenerator::historicalTimestampedUID88(
+ UUID::hex2timestamp( UUID::create( $id )->getHex() )
+ ) )->getAlphadecimal();
+ }
+ return $this->idMap[ $id ];
+ }
+
+ /**
+ * Check if a board already exist and should be imported in trans-wiki mode
+ *
+ * @param string $boardWorkflowId
+ * @param string $title
+ */
+ private function checkTransWikiMode( $boardWorkflowId, $title ) {
+ /** @var DbFactory $dbFactory */
+ $dbFactory = Container::get( 'db.factory' );
+ $workflowExist = !!$dbFactory->getDB( DB_MASTER )->selectField(
+ 'flow_workflow',
+ 'workflow_id',
+ [ 'workflow_id' => UUID::create( $boardWorkflowId )->getBinary() ],
+ __METHOD__
+ );
+
+ if ( $workflowExist ) {
+ $this->importer->debug( "$title will be imported in trans-wiki mode" );
+ }
+ $this->transWikiMode = $workflowExist;
+ }
+
+ /**
+ * Create a local user corresponding to a global id
+ *
+ * @param int $globalUserId
+ * @return \User Local user
+ * @throws ImportException
+ */
+ private function createLocalUser( $globalUserId ) {
+ if ( !( $this->lookup instanceof \CentralAuthIdLookup ) ) {
+ throw new ImportException( 'Creating local users is not supported with central id provider: ' . get_class( $this->lookup ) );
+ }
+
+ $globalUser = \CentralAuthUser::newFromId( $globalUserId );
+ $localUser = \User::newFromName( $globalUser->getName() );
+
+ if ( $localUser->getId() ) {
+ throw new ImportException( "User '{$localUser->getName()}' already exists" );
+ }
+
+ $status = \CentralAuthUtils::autoCreateUser( $localUser );
+ if ( !$status->isGood() ) {
+ throw new ImportException(
+ "autoCreateUser failed for {$localUser->getName()}: " . print_r( $status->getErrors(), true )
+ );
+ }
+
+ # Update user count
+ $ssUpdate = \SiteStatsUpdate::factory( [ 'users' => 1 ] );
+ $ssUpdate->doUpdate();
+
+ return $localUser;
+ }
+}
diff --git a/Flow/includes/Dump/flow-1.0.xsd b/Flow/includes/Dump/flow-1.0.xsd
new file mode 100644
index 00000000..275c5a66
--- /dev/null
+++ b/Flow/includes/Dump/flow-1.0.xsd
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:flow="http://www.mediawiki.org/xml/flow-1.0/"
+ targetNamespace="http://www.mediawiki.org/xml/flow-1.0/"
+ elementFormDefault="qualified">
+
+ <!-- Need this to reference xml:lang -->
+ <import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd" />
+
+ <complexType name="AbstractRevision">
+ <simpleContent>
+ <extension base="string">
+ <attribute type="string" name="id" use="required"/>
+ <attribute type="nonNegativeInteger" name="userid" use="required"/>
+ <attribute type="nonNegativeInteger" name="globaluserid" use="optional"/>
+ <attribute type="string" name="userip" use="optional"/>
+ <attribute type="string" name="userwiki" use="required"/>
+ <attribute type="string" name="parentid" use="optional"/>
+ <attribute type="string" name="changetype" use="required"/>
+ <attribute type="string" name="type" use="required"/>
+ <attribute type="string" name="typeid" use="required"/>
+ <attribute type="string" name="flags" use="required"/>
+ <attribute type="string" name="modstate" use="required"/>
+ <attribute type="nonNegativeInteger" name="globalmoduserid" use="optional"/>
+ <attribute type="string" name="moduserid" use="optional"/>
+ <attribute type="string" name="moduserip" use="optional"/>
+ <attribute type="string" name="moduserwiki" use="optional"/>
+ <attribute type="string" name="modtimestamp" use="optional"/>
+ <attribute type="string" name="modreason" use="optional"/>
+ <attribute type="string" name="lasteditid" use="optional"/>
+ <attribute type="string" name="edituserid" use="optional"/>
+ <attribute type="nonNegativeInteger" name="globaledituserid" use="optional"/>
+ <attribute type="string" name="edituserip" use="optional"/>
+ <attribute type="string" name="edituserwiki" use="optional"/>
+ <attribute type="nonNegativeInteger" name="contentlength" use="required"/>
+ <attribute type="nonNegativeInteger" name="previouscontentlength" use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="PostRevision">
+ <simpleContent>
+ <extension base="flow:AbstractRevision">
+ <attribute type="string" name="treeparentid" use="optional"/>
+ <attribute type="string" name="treedescendantid" use="required"/>
+ <attribute type="string" name="treerevid" use="required"/>
+ <attribute type="nonNegativeInteger" name="treeoriguserid" use="required"/>
+ <attribute type="nonNegativeInteger" name="globaltreeoriguserid" use="optional"/>
+ <attribute type="string" name="treeoriguserip" use="optional"/>
+ <attribute type="string" name="treeoriguserwiki" use="required"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="Post">
+ <sequence>
+ <element name="revisions">
+ <complexType>
+ <choice minOccurs="1" maxOccurs="unbounded">
+ <element name="revision" type="flow:PostRevision"/>
+ </choice>
+ </complexType>
+ </element>
+ <element name="children" minOccurs="0" maxOccurs="1">
+ <complexType>
+ <choice minOccurs="1" maxOccurs="unbounded">
+ <!-- Recursion: post can have child posts -->
+ <element name="post" type="flow:Post"/>
+ </choice>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute type="string" name="id" use="required"/>
+ </complexType>
+
+ <element name="mediawiki">
+ <complexType>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element name="board">
+ <complexType mixed="true">
+ <sequence>
+ <element name="description" minOccurs="0" maxOccurs="1">
+ <complexType>
+ <all>
+ <element name="revisions">
+ <complexType>
+ <choice minOccurs="1" maxOccurs="unbounded">
+ <element name="revision" type="flow:AbstractRevision"/>
+ </choice>
+ </complexType>
+ </element>
+ </all>
+ <attribute type="string" name="id" use="required"/>
+ </complexType>
+ </element>
+ <element name="topic" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="post" type="flow:Post" minOccurs="1" maxOccurs="unbounded"/>
+ <element name="summary" minOccurs="0" maxOccurs="1">
+ <complexType>
+ <all>
+ <element name="revisions">
+ <complexType>
+ <choice minOccurs="1" maxOccurs="unbounded">
+ <element name="revision" type="flow:AbstractRevision"/>
+ </choice>
+ </complexType>
+ </element>
+ </all>
+ <attribute type="string" name="id" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute type="string" name="id" use="required"/>
+ </complexType>
+ </element>
+ </sequence>
+ <attribute type="string" name="id" use="required"/>
+ <attribute type="string" name="title" use="required"/>
+ </complexType>
+ </element>
+ </choice>
+ <attribute type="string" name="version" use="required"/>
+ <attribute ref="xml:lang" use="required"/>
+ </complexType>
+ </element>
+</schema>
diff --git a/Flow/includes/Exception/ExceptionHandling.php b/Flow/includes/Exception/ExceptionHandling.php
index ef4c6d63..e7e66e92 100644
--- a/Flow/includes/Exception/ExceptionHandling.php
+++ b/Flow/includes/Exception/ExceptionHandling.php
@@ -24,8 +24,8 @@ class FlowException extends MWException {
protected $output;
/**
- * @param string - The message from exception, used for debugging error
- * @param string - The error code used to display error message
+ * @param string $message The message from exception, used for debugging error
+ * @param string $code The error code used to display error message
*/
public function __construct( $message, $code = 'default' ) {
global $wgOut;
@@ -57,7 +57,8 @@ class FlowException extends MWException {
* Error code list for this exception
*/
protected function getErrorCodeList() {
- return array ( 'default' );
+ // flow-error-default
+ return [ 'default' ];
}
/**
@@ -137,15 +138,22 @@ class FlowException extends MWException {
/**
* Category: invalid input exception
+ *
+ * This is not logged, and must *only* be used when the error is caused by invalid end-user
+ * input. The same applies to the subclasses.
+ *
+ * If it is a logic error (including a missing or incorrect parameter not directly caused
+ * by user input), or another kind of failure, another (loggable) exception must be used.
*/
class InvalidInputException extends FlowException {
protected function getErrorCodeList() {
- return array (
- 'invalid-input',
- 'missing-revision',
- 'revision-comparison',
- 'invalid-workflow'
- );
+ // Comments are i18n messages, for grepping
+ return [
+ 'invalid-input', // flow-error-invalid-input
+ 'missing-revision', // flow-error-missing-revision
+ 'revision-comparison', // flow-error-revision-comparison
+ 'invalid-workflow', // flow-error-invalid-workflow
+ ];
}
/**
@@ -163,6 +171,10 @@ class InvalidInputException extends FlowException {
}
}
+/**
+ * This is not logged, and must *only* be used for reference
+ * errors caused by invalid (unprocessable) end-user input
+ */
class InvalidReferenceException extends InvalidInputException {
}
@@ -171,7 +183,8 @@ class InvalidReferenceException extends InvalidInputException {
*/
class InvalidActionException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'invalid-action' );
+ // flow-error-invalid-action
+ return [ 'invalid-action' ];
}
/**
@@ -212,7 +225,8 @@ class InvalidActionException extends FlowException {
*/
class FailCommitException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'fail-commit' );
+ // flow-error-fail-commit
+ return [ 'fail-commit' ];
}
}
@@ -221,7 +235,8 @@ class FailCommitException extends FlowException {
*/
class PermissionException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'insufficient-permission' );
+ // flow-error-insufficient-permission
+ return [ 'insufficient-permission' ];
}
/**
@@ -238,14 +253,15 @@ class PermissionException extends FlowException {
*/
class InvalidDataException extends FlowException {
protected function getErrorCodeList() {
- return array (
- 'invalid-title',
- 'fail-load-data',
- 'fail-load-history',
- 'fail-search',
- 'missing-topic-title',
- 'missing-metadata'
- );
+ return [
+ 'invalid-title', // flow-error-invalid-title
+ 'fail-load-data', // flow-error-fail-load-data
+ 'fail-load-history', // flow-error-fail-load-history
+ 'fail-search', // flow-error-fail-search
+ 'missing-topic-title', // flow-error-missing-topic-title
+ 'missing-metadata', // flow-error-missing-metadata
+ 'different-page', // flow-error-different-page
+ ];
}
}
@@ -254,7 +270,8 @@ class InvalidDataException extends FlowException {
*/
class DataModelException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'process-data' );
+ // flow-error-process-data
+ return [ 'process-data' ];
}
}
@@ -263,16 +280,18 @@ class DataModelException extends FlowException {
*/
class DataPersistenceException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'process-data' );
+ // flow-error-process-data
+ return [ 'process-data' ];
}
}
/**
* Category: Parsoid
*/
-class NoParsoidException extends FlowException {
+class NoParserException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'process-wikitext' );
+ // flow-error-process-wikitext
+ return [ 'process-wikitext' ];
}
}
@@ -281,7 +300,8 @@ class NoParsoidException extends FlowException {
*/
class WikitextException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'process-wikitext' );
+ // flow-error-process-wikitext
+ return [ 'process-wikitext' ];
}
}
@@ -290,14 +310,16 @@ class WikitextException extends FlowException {
*/
class NoIndexException extends FlowException {
protected function getErrorCodeList() {
- return array ( 'no-index' );
+ // flow-error-no-index
+ return [ 'no-index' ];
}
}
/**
* Category: Cross Wiki
*/
-class CrossWikiException extends FlowException {}
+class CrossWikiException extends FlowException {
+}
/**
* Category: Template helper
@@ -324,7 +346,8 @@ class WrongNumberArgumentsException extends FlowException {
*/
class UnknownWorkflowIdException extends InvalidInputException {
protected function getErrorCodeList() {
- return array( 'invalid-input' );
+ // flow-error-invalid-input
+ return [ 'invalid-input' ];
}
public function getHTML() {
@@ -342,7 +365,8 @@ class UnknownWorkflowIdException extends InvalidInputException {
*/
class InvalidTopicUuidException extends InvalidInputException {
protected function getErrorCodeList() {
- return array( 'invalid-input' );
+ // flow-error-invalid-input
+ return [ 'invalid-input' ];
}
public function getHTML() {
@@ -354,3 +378,19 @@ class InvalidTopicUuidException extends InvalidInputException {
}
}
+/**
+ * Exception for missing or invalid parameters to method calls, when not traced directly to
+ * user input.
+ *
+ * This deliberately does not extend InvalidInputException, and must be loggable
+ */
+class InvalidParameterException extends FlowException {
+ public function __construct( $message ) {
+ parent::__construct( $message, 'invalid-parameter' );
+ }
+
+ protected function getErrorCodeList() {
+ // flow-error-invalid-parameter
+ return [ 'invalid-parameter' ];
+ }
+}
diff --git a/Flow/includes/FlowActions.php b/Flow/includes/FlowActions.php
index 6c4ee457..f7ae0c3e 100644
--- a/Flow/includes/FlowActions.php
+++ b/Flow/includes/FlowActions.php
@@ -87,7 +87,7 @@ class FlowActions {
array_shift( $arguments );
array_unshift( $arguments, $referencedAction );
- return call_user_func_array( array( $this, 'getValue' ), $arguments );
+ return call_user_func_array( [ $this, 'getValue' ], $arguments );
}
} catch ( \OutOfBoundsException $e ) {
// Do nothing; the whole remainder of this method is fail-case.
diff --git a/Flow/includes/Formatter/AbstractFormatter.php b/Flow/includes/Formatter/AbstractFormatter.php
index 55b19dfc..34388b12 100644
--- a/Flow/includes/Formatter/AbstractFormatter.php
+++ b/Flow/includes/Formatter/AbstractFormatter.php
@@ -65,7 +65,7 @@ abstract class AbstractFormatter {
* have the same kind of links available)
* @return string HTML
*/
- protected function formatTimestamp( array $data, $key = 'timeAndDate', $linkKeys = array( 'header-revision', 'topic-revision', 'post-revision', 'summary-revision' ) ) {
+ protected function formatTimestamp( array $data, $key = 'timeAndDate', $linkKeys = [ 'header-revision', 'topic-revision', 'post-revision', 'summary-revision' ] ) {
// Format timestamp: add link
$formattedTime = $data['dateFormats'][$key];
@@ -78,7 +78,7 @@ abstract class AbstractFormatter {
}
}
- $class = array( 'mw-changeslist-date' );
+ $class = [ 'mw-changeslist-date' ];
if ( $data['isModeratedNotLocked'] ) {
$class[] = 'history-deleted';
}
@@ -86,11 +86,11 @@ abstract class AbstractFormatter {
if ( $anchor instanceof Anchor ) {
return Html::rawElement(
'span',
- array( 'class' => $class ),
+ [ 'class' => $class ],
$anchor->toHtml( $formattedTime )
);
} else {
- return Html::element( 'span', array( 'class' => $class ), $formattedTime );
+ return Html::element( 'span', [ 'class' => $class ], $formattedTime );
}
}
@@ -112,12 +112,12 @@ abstract class AbstractFormatter {
}
$have = array_combine( $request, $request );
- $formatted = array();
+ $formatted = [];
foreach ( $links as $key => $link ) {
if ( isset( $have[$key] ) ) {
if ( $link instanceof Anchor ) {
$formatted[] = $link->toHtml();
- } elseif( $link instanceof Message ) {
+ } elseif ( $link instanceof Message ) {
$formatted[] = $link->escaped();
} else {
// plain text
@@ -141,7 +141,7 @@ abstract class AbstractFormatter {
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
- * @param array[][] Associative array containing (url, message) tuples
+ * @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
@@ -159,7 +159,7 @@ abstract class AbstractFormatter {
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
- * @param array[][] Associative array containing (url, message) tuples
+ * @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
@@ -177,7 +177,7 @@ abstract class AbstractFormatter {
* in a format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
- * @param array[][] Associative array containing (url, message) tuples
+ * @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
@@ -195,7 +195,7 @@ abstract class AbstractFormatter {
* format that can be wrapped in an array and passed to
* formatLinksAsPipeList.
*
- * @param array[][] Associative array containing (url, message) tuples
+ * @param array[][] $input Associative array containing (url, message) tuples
* @param IContextSource $ctx
* @return Anchor|Message
*/
@@ -256,7 +256,7 @@ abstract class AbstractFormatter {
*/
protected function getDescriptionParams( array $data, FlowActions $actions, $changeType ) {
$source = $actions->getValue( $changeType, 'history', 'i18n-params' );
- $params = array();
+ $params = [];
foreach ( $source as $param ) {
if ( isset( $data['properties'][$param] ) ) {
$params[] = $data['properties'][$param];
@@ -294,7 +294,7 @@ abstract class AbstractFormatter {
$ownerLink = Linker::link(
$row->workflow->getOwnerTitle(),
null,
- array( 'class' => 'mw-title' )
+ [ 'class' => 'mw-title' ]
);
if ( !isset( $data['links']['topic'] ) || !$row->revision instanceof PostRevision ) {
@@ -306,7 +306,8 @@ abstract class AbstractFormatter {
// generated link has generic link text, should be actual topic title
$root = $row->revision->getRootPost();
if ( $root && $this->permissions->isAllowed( $root, 'view' ) ) {
- $topic->setMessage( Container::get( 'templating' )->getContent( $root, 'wikitext' ) );
+ $topicDisplayText = Container::get( 'templating' )->getContent( $root, 'topic-title-plaintext' );
+ $topic->setMessage( $topicDisplayText );
}
return $ctx->msg( 'flow-rc-topic-of-board' )->rawParams(
diff --git a/Flow/includes/Formatter/AbstractQuery.php b/Flow/includes/Formatter/AbstractQuery.php
index 5c0cd362..b608abc4 100644
--- a/Flow/includes/Formatter/AbstractQuery.php
+++ b/Flow/includes/Formatter/AbstractQuery.php
@@ -35,31 +35,31 @@ abstract class AbstractQuery {
/**
* @var UUID[] Associative array of post ID to root post's UUID object.
*/
- protected $rootPostIdCache = array();
+ protected $rootPostIdCache = [];
/**
* @var PostRevision[] Associative array of post ID to PostRevision object.
*/
- protected $postCache = array();
+ protected $postCache = [];
/**
* @var AbstractRevision[] Associative array of revision ID to AbstractRevision object
*/
- protected $revisionCache = array();
+ protected $revisionCache = [];
/**
* @var Workflow[] Associative array of workflow ID to Workflow object.
*/
- protected $workflowCache = array();
+ protected $workflowCache = [];
/**
* Array of collection ids mapping to their most recent revision ids.
*
* @var UUID[]
*/
- protected $currentRevisionsCache = array();
+ protected $currentRevisionsCache = [];
- protected $identityMap = array();
+ protected $identityMap = [];
/**
* @param ManagerGroup $storage
@@ -78,12 +78,12 @@ abstract class AbstractQuery {
*/
protected function loadMetadataBatch( $results ) {
// Batch load data related to a list of revisions
- $postIds = array();
- $workflowIds = array();
- $revisions = array();
- $previousRevisionIds = array();
- $collectionIds = array();
- foreach( $results as $result ) {
+ $postIds = [];
+ $workflowIds = [];
+ $revisions = [];
+ $previousRevisionIds = [];
+ $collectionIds = [];
+ foreach ( $results as $result ) {
if ( $result instanceof PostRevision ) {
// If top-level, then just get the workflow.
// Otherwise we need to find the root post.
@@ -114,13 +114,12 @@ abstract class AbstractQuery {
// map from post Id to the related root post id
$rootPostIds = array_filter( $this->treeRepository->findRoots( $postIds ) );
- $rootPostRequests = array();
- foreach( $rootPostIds as $postId ) {
- $rootPostRequests[] = array( 'rev_type_id' => $postId );
+ $rootPostRequests = [];
+ foreach ( $rootPostIds as $postId ) {
+ $rootPostRequests[] = [ 'rev_type_id' => $postId ];
}
// these tree identity maps are required for determining where a reply goes when
- //
// replying to a specific post.
$identityMap = $this->treeRepository->fetchSubtreeIdentityMap(
array_unique( $rootPostIds, SORT_REGULAR )
@@ -129,14 +128,14 @@ abstract class AbstractQuery {
$rootPostResult = $this->storage->findMulti(
'PostRevision',
$rootPostRequests,
- array(
+ [
'SORT' => 'rev_id',
'ORDER' => 'DESC',
'LIMIT' => 1,
- )
+ ]
);
- $rootPosts = array();
+ $rootPosts = [];
if ( count( $rootPostResult ) > 0 ) {
foreach ( $rootPostResult as $found ) {
$root = reset( $found );
@@ -149,7 +148,7 @@ abstract class AbstractQuery {
// So any post IDs that *are* root posts + found root post IDs + header workflow IDs
// should cover the lot.
$workflows = $this->storage->getMulti( 'Workflow', array_merge( $rootPostIds, $workflowIds ) );
- $workflows = $workflows ?: array();
+ $workflows = $workflows ?: [];
// preload all requested previous revisions
foreach ( $previousRevisionIds as $revisionType => $ids ) {
@@ -164,20 +163,21 @@ abstract class AbstractQuery {
// preload all current versions
foreach ( $collectionIds as $revisionType => $ids ) {
- $queries = array();
+ $queries = [];
foreach ( $ids as $uuid ) {
- $queries[] = array( 'rev_type_id' => $uuid );
+ $queries[] = [ 'rev_type_id' => $uuid ];
}
$found = $this->storage->findMulti( $revisionType,
$queries,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
/** @var AbstractRevision[] $result */
foreach ( $found as $result ) {
$rev = reset( $result );
- $this->currentRevisionsCache[$rev->getCollectionId()->getAlphadecimal()] = $rev->getRevisionId();
+ $cacheKey = $this->getCurrentRevisionCacheKey( $rev );
+ $this->currentRevisionsCache[$cacheKey] = $rev->getRevisionId();
$revisions[$rev->getRevisionId()->getAlphadecimal()] = $rev;
}
}
@@ -195,7 +195,7 @@ abstract class AbstractQuery {
*
* @param AbstractRevision $revision
* @param string $indexField The field used for pagination
- * @param FormatterRow|null Row to populate
+ * @param FormatterRow|null $row Row to populate
* @return FormatterRow
* @throws FlowException
*/
@@ -292,7 +292,7 @@ abstract class AbstractQuery {
/**
* Decides if the given abstract revision needs its prior revision for formatting
* @param AbstractRevision $revision
- * @return boolean true when the previous revision to this should be loaded
+ * @return bool true when the previous revision to this should be loaded
*/
protected function needsPreviousRevision( AbstractRevision $revision ) {
// crappy special case needs the previous object so it can show the title
@@ -303,8 +303,8 @@ abstract class AbstractQuery {
/**
* Retrieves the previous revision for a given AbstractRevision
- * @param AbstractRevision $revision The revision to retrieve the previous revision for.
- * @return AbstractRevision|null AbstractRevision of the previous revision or null if no previous revision.
+ * @param AbstractRevision $revision The revision to retrieve the previous revision for.
+ * @return AbstractRevision|null AbstractRevision of the previous revision or null if no previous revision.
*/
protected function getPreviousRevision( AbstractRevision $revision ) {
$previousRevisionId = $revision->getPrevRevisionId();
@@ -324,26 +324,26 @@ abstract class AbstractQuery {
/**
* Retrieves the current revision for a given AbstractRevision
- * @param AbstractRevision $revision The revision to retrieve the current revision for.
- * @return AbstractRevision|null AbstractRevision of the current revision.
+ * @param AbstractRevision $revision The revision to retrieve the current revision for.
+ * @return AbstractRevision|null AbstractRevision of the current revision.
*/
protected function getCurrentRevision( AbstractRevision $revision ) {
- $collectionId = $revision->getCollectionId();
- if ( !isset( $this->currentRevisionsCache[$collectionId->getAlphadecimal()] ) ) {
+ $cacheKey = $this->getCurrentRevisionCacheKey( $revision );
+ if ( !isset( $this->currentRevisionsCache[$cacheKey] ) ) {
$currentRevision = $revision->getCollection()->getLastRevision();
- $this->currentRevisionsCache[$collectionId->getAlphadecimal()] = $currentRevision->getRevisionId();
+ $this->currentRevisionsCache[$cacheKey] = $currentRevision->getRevisionId();
$this->revisionCache[$currentRevision->getRevisionId()->getAlphadecimal()] = $currentRevision;
}
- $currentRevisionId = $this->currentRevisionsCache[$collectionId->getAlphadecimal()];
+ $currentRevisionId = $this->currentRevisionsCache[$cacheKey];
return $this->revisionCache[$currentRevisionId->getAlphaDecimal()];
}
/**
* Retrieves the root post for a given PostRevision
- * @param PostRevision $revision The revision to retrieve the root post for.
- * @return PostRevision PostRevision of the root post.
+ * @param PostRevision $revision The revision to retrieve the root post for.
+ * @return PostRevision PostRevision of the root post.
* @throws \MWException
*/
protected function getRootPost( PostRevision $revision ) {
@@ -369,8 +369,8 @@ abstract class AbstractQuery {
/**
* Gets the root post ID for a given PostRevision
- * @param PostRevision $revision The revision to get the root post ID for.
- * @return UUID The UUID for the root post.
+ * @param PostRevision $revision The revision to get the root post ID for.
+ * @return UUID The UUID for the root post.
* @throws \MWException
*/
protected function getRootPostId( PostRevision $revision ) {
@@ -386,8 +386,8 @@ abstract class AbstractQuery {
/**
* Gets a Workflow object given its ID
- * @param UUID $workflowId The Workflow ID to retrieve.
- * @return Workflow The Workflow.
+ * @param UUID $workflowId The Workflow ID to retrieve.
+ * @return Workflow The Workflow.
*/
protected function getWorkflowById( UUID $workflowId ) {
$alpha = $workflowId->getAlphadecimal();
@@ -397,6 +397,14 @@ abstract class AbstractQuery {
return $this->workflowCache[$alpha] = $this->storage->get( 'Workflow', $workflowId );
}
}
+
+ /**
+ * @param AbstractRevision $revision
+ * @return string
+ */
+ protected function getCurrentRevisionCacheKey( AbstractRevision $revision ) {
+ return $revision->getRevisionType() . '-' . $revision->getCollectionId()->getAlphadecimal();
+ }
}
/**
@@ -432,4 +440,3 @@ class FormatterRow {
throw new \MWException( "Accessing non-existent parameter: $attribute" );
}
}
-
diff --git a/Flow/includes/Formatter/BaseTopicListFormatter.php b/Flow/includes/Formatter/BaseTopicListFormatter.php
index 0247ffd0..c8d8948f 100644
--- a/Flow/includes/Formatter/BaseTopicListFormatter.php
+++ b/Flow/includes/Formatter/BaseTopicListFormatter.php
@@ -2,7 +2,6 @@
namespace Flow\Formatter;
-use Flow\Data\Pager\PagerPage;
use Flow\Model\Anchor;
use Flow\Model\Workflow;
@@ -14,13 +13,13 @@ class BaseTopicListFormatter {
* @return array Associative array with the the result
*/
public function buildEmptyResult( Workflow $workflow ) {
- return array(
+ return [
'type' => 'topiclist',
- 'roots' => array(),
- 'posts' => array(),
- 'revisions' => array(),
- 'links' => array( 'pagination' => array() ),
- );
+ 'roots' => [],
+ 'posts' => [],
+ 'revisions' => [],
+ 'links' => [ 'pagination' => [] ],
+ ];
}
/**
@@ -30,11 +29,11 @@ class BaseTopicListFormatter {
* @return array link structure
*/
protected function buildPaginationLinks( Workflow $workflow, array $links ) {
- $res = array();
+ $res = [];
$title = $workflow->getArticleTitle();
foreach ( $links as $key => $options ) {
// prefix all options with topiclist_
- $realOptions = array();
+ $realOptions = [];
foreach ( $options as $k => $v ) {
$realOptions["topiclist_$k"] = $v;
}
diff --git a/Flow/includes/Formatter/BoardHistoryQuery.php b/Flow/includes/Formatter/BoardHistoryQuery.php
index bddb4363..6ca2c499 100644
--- a/Flow/includes/Formatter/BoardHistoryQuery.php
+++ b/Flow/includes/Formatter/BoardHistoryQuery.php
@@ -2,42 +2,45 @@
namespace Flow\Formatter;
+use Flow\Data\Utils\SortRevisionsByRevisionId;
use Flow\Exception\FlowException;
use Flow\Model\UUID;
use MWExceptionHandler;
-class BoardHistoryQuery extends AbstractQuery {
+class BoardHistoryQuery extends HistoryQuery {
/**
- * @param UUID $workflowId
+ * @param UUID $boardWorkflowId
* @param int $limit
* @param UUID|null $offset
* @param string $direction 'rev' or 'fwd'
* @return FormatterRow[]
*/
- public function getResults( UUID $workflowId, $limit = 50, UUID $offset = null, $direction = 'fwd' ) {
- // Load the history
- $history = $this->storage->find(
- 'BoardHistoryEntry',
- array( 'topic_list_id' => $workflowId ),
- array(
- 'sort' => 'rev_id',
- 'order' => 'DESC',
- 'limit' => $limit,
- 'offset-id' => $offset,
- 'offset-dir' => $direction,
- 'offset-include' => false,
- 'offset-elastic' => false,
- )
- );
+ public function getResults( UUID $boardWorkflowId, $limit = 50, UUID $offset = null, $direction = 'fwd' ) {
+ $options = $this->getOptions( $direction, $limit, $offset );
+
+ $headerHistory = $this->getHeaderResults( $boardWorkflowId, $options ) ?: [];
+ $topicListHistory = $this->getTopicListResults( $boardWorkflowId, $options ) ?: [];
+ $topicSummaryHistory = $this->getTopicSummaryResults( $boardWorkflowId, $options ) ?: [];
- if ( !$history ) {
- return array();
+ $history = array_merge( $headerHistory, $topicListHistory, $topicSummaryHistory );
+ usort( $history, new SortRevisionsByRevisionId( $options['order'] ) );
+
+ if ( isset( $options['limit'] ) ) {
+ $history = array_splice( $history, 0, $options['limit'] );
+ }
+
+ // We can't use ORDER BY ... DESC in SQL, because that will give us the
+ // largest entries that are > some offset. We want the smallest entries
+ // that are > that offset, but ordered in descending order. Core solves
+ // this problem in IndexPager->getBody by iterating in descending order.
+ if ( $direction === 'rev' ) {
+ $history = array_reverse( $history );
}
// fetch any necessary metadata
$this->loadMetadataBatch( $history );
// build rows with the extra metadata
- $results = array();
+ $results = [];
foreach ( $history as $revision ) {
try {
$result = $this->buildResult( $revision, 'rev_id' );
@@ -52,4 +55,36 @@ class BoardHistoryQuery extends AbstractQuery {
return $results;
}
+
+ protected function getHeaderResults( UUID $boardWorkflowId, $options ) {
+ return $this->storage->find(
+ 'Header',
+ [
+ 'rev_type_id' => $boardWorkflowId,
+ ],
+ $options
+ );
+ }
+
+ protected function getTopicListResults( UUID $boardWorkflowId, $options ) {
+ // Can't use 'PostRevision' because we need to get only the ones with the right board ID.
+ return $this->doInternalQueries(
+ 'PostRevisionBoardHistoryEntry',
+ [
+ 'topic_list_id' => $boardWorkflowId,
+ ],
+ $options,
+ self::POST_OVERFETCH_FACTOR
+ );
+ }
+
+ protected function getTopicSummaryResults( UUID $boardWorkflowId, $options ) {
+ return $this->storage->find(
+ 'PostSummaryBoardHistoryEntry',
+ [
+ 'topic_list_id' => $boardWorkflowId,
+ ],
+ $options
+ );
+ }
}
diff --git a/Flow/includes/Formatter/CategoryViewerFormatter.php b/Flow/includes/Formatter/CategoryViewerFormatter.php
index 0c060229..b0e2f451 100644
--- a/Flow/includes/Formatter/CategoryViewerFormatter.php
+++ b/Flow/includes/Formatter/CategoryViewerFormatter.php
@@ -3,7 +3,6 @@
namespace Flow\Formatter;
use Flow\RevisionActionPermissions;
-use Flow\Model\UUID;
use Linker;
/**
@@ -28,8 +27,8 @@ class CategoryViewerFormatter {
$topic = Linker::link(
$row->workflow->getArticleTitle(),
- htmlspecialchars( $row->revision->getContent( 'plaintext' ) ),
- array( 'class' => 'mw-title' )
+ htmlspecialchars( $row->revision->getContent( 'topic-title-wikitext' ) ),
+ [ 'class' => 'mw-title' ]
);
$board = Linker::link( $row->workflow->getOwnerTitle() );
diff --git a/Flow/includes/Formatter/CategoryViewerQuery.php b/Flow/includes/Formatter/CategoryViewerQuery.php
index 1bb21687..02d74dae 100644
--- a/Flow/includes/Formatter/CategoryViewerQuery.php
+++ b/Flow/includes/Formatter/CategoryViewerQuery.php
@@ -17,12 +17,12 @@ class CategoryViewerQuery {
/**
* @var PostRevision[]
*/
- protected $posts = array();
+ protected $posts = [];
/**
* @var Workflow[]
*/
- protected $workflows = array();
+ protected $workflows = [];
/**
* @var ManagerGroup
@@ -40,8 +40,8 @@ class CategoryViewerQuery {
* @param ResultWrapper|array $rows
*/
public function loadMetadataBatch( $rows ) {
- $neededPosts = array();
- $neededWorkflows = array();
+ $neededPosts = [];
+ $neededWorkflows = [];
foreach ( $rows as $row ) {
if ( $row->page_namespace != NS_TOPIC ) {
continue;
@@ -49,7 +49,7 @@ class CategoryViewerQuery {
$uuid = UUID::create( strtolower( $row->page_title ) );
if ( $uuid ) {
$alpha = $uuid->getAlphadecimal();
- $neededPosts[$alpha] = array( 'rev_type_id' => $uuid );
+ $neededPosts[$alpha] = [ 'rev_type_id' => $uuid ];
$neededWorkflows[$alpha] = $uuid;
}
}
@@ -60,7 +60,7 @@ class CategoryViewerQuery {
$this->posts = $this->storage->findMulti(
'PostRevision',
$neededPosts,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
$workflows = $this->storage->getMulti(
'Workflow',
diff --git a/Flow/includes/Formatter/ChangesListFormatter.php b/Flow/includes/Formatter/ChangesListFormatter.php
index 4981cc59..0123b926 100644
--- a/Flow/includes/Formatter/ChangesListFormatter.php
+++ b/Flow/includes/Formatter/ChangesListFormatter.php
@@ -6,9 +6,8 @@ use Flow\Exception\FlowException;
use Flow\Exception\PermissionException;
use Flow\Model\Anchor;
use ChangesList;
-use Flow\Model\PostRevision;
use Flow\Model\UUID;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use IContextSource;
use Linker;
@@ -40,7 +39,7 @@ class ChangesListFormatter extends AbstractFormatter {
// The ' . . ' text between elements
$separator = $this->changeSeparator();
- $links = array();
+ $links = [];
$links[] = $this->getDiffAnchor( $data['links'], $ctx );
$links[] = $this->getHistAnchor( $data['links'], $ctx );
@@ -57,9 +56,9 @@ class ChangesListFormatter extends AbstractFormatter {
$this->formatTimestamp( $data, 'time' ) .
$separator .
ChangesList::showCharacterDifference(
- $data['size']['old'],
- $data['size']['new'],
- $ctx
+ $data['size']['old'],
+ $data['size']['new'],
+ $ctx
) .
( Utils::htmlToPlaintext( $description ) ? $separator . $description : '' ) .
$this->getEditSummary( $row, $ctx, $data );
@@ -92,9 +91,9 @@ class ChangesListFormatter extends AbstractFormatter {
$prefix = $ctx->msg( 'autocomment-prefix' )->inContentLanguage()->escaped();
$link = Linker::link(
$title = $row->workflow->getOwnerTitle(),
- $ctx->getLanguage()->getArrow('backwards'),
- array(),
- array(),
+ $ctx->getLanguage()->getArrow( 'backwards' ),
+ [],
+ [],
'noclasses'
);
$summary = '<span class="autocomment">' . $msg->text() . '</span>';
@@ -178,7 +177,7 @@ class ChangesListFormatter extends AbstractFormatter {
* @throws FlowException
* @throws \Flow\Exception\InvalidInputException
*/
- public function getLogTextLinks( RecentChangesRow $row, IContextSource $ctx, array $block, array $links = array() ) {
+ public function getLogTextLinks( RecentChangesRow $row, IContextSource $ctx, array $block, array $links = [] ) {
$data = $this->serializer->formatApi( $row, $ctx, 'recentchanges' );
if ( !$data ) {
return false;
@@ -215,14 +214,13 @@ class ChangesListFormatter extends AbstractFormatter {
* @param IContextSource $ctx
* @return array
*/
- public function getFlags( RecentChangesRow $row, IContextSource $ctx )
- {
- return array(
+ public function getFlags( RecentChangesRow $row, IContextSource $ctx ) {
+ return [
'newpage' => $row->isFirstReply && $row->revision->isFirstRevision(),
'minor' => false,
'unpatrolled' => ChangesList::isUnpatrolled( $row->recentChange, $ctx->getUser() ),
'bot' => false,
- );
+ ];
}
/**
diff --git a/Flow/includes/Formatter/ChangesListQuery.php b/Flow/includes/Formatter/ChangesListQuery.php
index d502c073..b1b530db 100644
--- a/Flow/includes/Formatter/ChangesListQuery.php
+++ b/Flow/includes/Formatter/ChangesListQuery.php
@@ -8,6 +8,7 @@ use Flow\Exception\FlowException;
use Flow\FlowActions;
use Flow\Model\UUID;
use Flow\Repository\TreeRepository;
+use MediaWiki\Logger\LoggerFactory;
use RecentChange;
class ChangesListQuery extends AbstractQuery {
@@ -17,7 +18,7 @@ class ChangesListQuery extends AbstractQuery {
*
* @var array
*/
- protected $displayStatus = array();
+ protected $displayStatus = [];
/**
* @var FlowActions
@@ -46,7 +47,7 @@ class ChangesListQuery extends AbstractQuery {
* @param bool $isWatchlist
*/
public function loadMetadataBatch( $rows, $isWatchlist = false ) {
- $needed = array();
+ $needed = [];
foreach ( $rows as $row ) {
if ( !isset( $row->rc_source ) || $row->rc_source !== RecentChangesListener::SRC_FLOW ) {
continue;
@@ -79,7 +80,7 @@ class ChangesListQuery extends AbstractQuery {
$needed[$revisionType][] = UUID::create( $changeData['revision'] );
}
- $found = array();
+ $found = [];
foreach ( $needed as $type => $uids ) {
$found[] = $this->storage->getMulti( $type, $uids );
}
@@ -87,7 +88,7 @@ class ChangesListQuery extends AbstractQuery {
$found = array_filter( $found );
$count = count( $found );
if ( $count === 0 ) {
- $results = array();
+ $results = [];
} elseif ( $count === 1 ) {
$results = reset( $found );
} else {
@@ -109,7 +110,7 @@ class ChangesListQuery extends AbstractQuery {
if ( $isWatchlist ) {
return false;
} else {
- return (bool) $this->actions->getValue( $action, 'exclude_from_recentchanges' );
+ return (bool)$this->actions->getValue( $action, 'exclude_from_recentchanges' );
}
}
@@ -141,10 +142,6 @@ class ChangesListQuery extends AbstractQuery {
throw new FlowException( 'Corrupted rc without changeData: ' . $rc->getAttribute( 'rc_id' ) );
}
- /**
- * RC entries are not being created for 'new-topic' action but
- * old records exists. This filters them out.
- */
if ( $this->excludeFromChangesList( $isWatchlist, $changeData['action'] ) ) {
return false;
}
@@ -156,7 +153,14 @@ class ChangesListQuery extends AbstractQuery {
$alpha = UUID::create( $changeData['revision'] )->getAlphadecimal();
if ( !isset( $this->revisionCache[$alpha] ) ) {
- throw new FlowException( "Revision not found in revisionCache: $alpha" );
+ LoggerFactory::getInstance( 'Flow' )->error(
+ 'Revision not found in revisionCache: {alpha}',
+ [
+ 'alpha' => $alpha,
+ 'rcParams' => $rcParams,
+ ]
+ );
+ return false;
}
$revision = $this->revisionCache[$alpha];
diff --git a/Flow/includes/Formatter/CheckUserFormatter.php b/Flow/includes/Formatter/CheckUserFormatter.php
index c38197a5..2ef3d5e8 100644
--- a/Flow/includes/Formatter/CheckUserFormatter.php
+++ b/Flow/includes/Formatter/CheckUserFormatter.php
@@ -37,17 +37,17 @@ class CheckUserFormatter extends AbstractFormatter {
return null;
}
- $data = array(
- 'links' => array(
+ $data = [
+ 'links' => [
$this->getDiffAnchor( $links, $ctx ),
$this->getHistAnchor( $links, $ctx ),
- ),
+ ],
'properties' => $properties
- );
+ ];
- return array(
+ return [
'links' => $this->formatAnchorsAsPipeList( $data['links'], $ctx ),
'title' => $this->changeSeparator() . $this->getTitleLink( $data, $row, $ctx ),
- );
+ ];
}
}
diff --git a/Flow/includes/Formatter/CheckUserQuery.php b/Flow/includes/Formatter/CheckUserQuery.php
index e52c9c2c..bc5023ea 100644
--- a/Flow/includes/Formatter/CheckUserQuery.php
+++ b/Flow/includes/Formatter/CheckUserQuery.php
@@ -20,7 +20,7 @@ class CheckUserQuery extends AbstractQuery {
* @param \stdClass[] $rows List of checkuser database rows
*/
public function loadMetadataBatch( $rows ) {
- $needed = array();
+ $needed = [];
foreach ( $rows as $row ) {
if ( $row->cuc_type != RC_FLOW || !$row->cuc_comment ) {
@@ -46,14 +46,14 @@ class CheckUserQuery extends AbstractQuery {
$needed[$revisionType][] = $revisionId;
}
- $found = array();
+ $found = [];
foreach ( $needed as $type => $uids ) {
$found[] = $this->storage->getMulti( $type, $uids );
}
$count = count( $found );
if ( $count === 0 ) {
- $results = array();
+ $results = [];
} elseif ( $count === 1 ) {
$results = reset( $found );
} else {
@@ -131,7 +131,7 @@ class CheckUserQuery extends AbstractQuery {
return false;
}
- return array( $workflowId, $revisionId, $postId );
+ return [ $workflowId, $revisionId, $postId ];
}
}
diff --git a/Flow/includes/Formatter/ContributionsFormatter.php b/Flow/includes/Formatter/ContributionsFormatter.php
index 51ec52bb..6d5f2537 100644
--- a/Flow/includes/Formatter/ContributionsFormatter.php
+++ b/Flow/includes/Formatter/ContributionsFormatter.php
@@ -5,7 +5,7 @@ namespace Flow\Formatter;
use Flow\Exception\FlowException;
use Flow\Model\Anchor;
use Flow\Model\PostRevision;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use ChangesList;
use IContextSource;
use Html;
@@ -30,10 +30,6 @@ class ContributionsFormatter extends AbstractFormatter {
$isNewPage = isset( $data['isNewPage'] ) && $data['isNewPage'];
- if ( $ctx->newOnly && !$isNewPage ) {
- return false;
- }
-
$charDiff = ChangesList::showCharacterDifference(
$data['size']['old'],
$data['size']['new']
@@ -41,7 +37,7 @@ class ContributionsFormatter extends AbstractFormatter {
$separator = $this->changeSeparator();
- $links = array();
+ $links = [];
$links[] = $this->getDiffAnchor( $data['links'], $ctx );
$links[] = $this->getHistAnchor( $data['links'], $ctx );
@@ -89,17 +85,18 @@ class ContributionsFormatter extends AbstractFormatter {
/** @var Anchor $anchor */
$anchor = $data['actions'][$key];
-
- return ' (' . Html::rawElement(
+ $message = ' ' . wfMessage( 'parentheses' )->rawParams( Html::rawElement(
'a',
- array(
+ [
'href' => $anchor->getFullURL(),
'data-flow-interactive-handler' => 'moderationDialog',
'data-flow-template' => "flow_moderate_$type.partial",
'data-role' => $key,
'class' => 'flow-history-moderation-action flow-click-interactive',
- ),
+ ],
$ctx->msg( $msg )->escaped()
- ) . ')';
+ ) )->escaped();
+
+ return $message;
}
}
diff --git a/Flow/includes/Formatter/ContributionsQuery.php b/Flow/includes/Formatter/ContributionsQuery.php
index 8b85adb9..8bb7d085 100644
--- a/Flow/includes/Formatter/ContributionsQuery.php
+++ b/Flow/includes/Formatter/ContributionsQuery.php
@@ -36,8 +36,8 @@ class ContributionsQuery extends AbstractQuery {
/**
* @param ManagerGroup $storage
- * @param BagOStuff $cache
* @param TreeRepository $treeRepo
+ * @param BagOStuff $cache
* @param DbFactory $dbFactory
* @param FlowActions $actions
*/
@@ -46,8 +46,8 @@ class ContributionsQuery extends AbstractQuery {
TreeRepository $treeRepo,
BagOStuff $cache,
DbFactory $dbFactory,
- FlowActions $actions )
- {
+ FlowActions $actions
+ ) {
parent::__construct( $storage, $treeRepo );
$this->cache = $cache;
$this->dbFactory = $dbFactory;
@@ -65,14 +65,14 @@ class ContributionsQuery extends AbstractQuery {
// build DB query conditions
$conditions = $this->buildConditions( $pager, $offset, $descending );
- $types = array(
+ $types = [
// revision class => block type
'PostRevision' => 'topic',
'Header' => 'header',
'PostSummary' => 'topicsummary'
- );
+ ];
- $results = array();
+ $results = [];
foreach ( $types as $revisionClass => $blockType ) {
// query DB for requested revisions
$rows = $this->queryRevisions( $conditions, $limit, $revisionClass );
@@ -121,7 +121,7 @@ class ContributionsQuery extends AbstractQuery {
* @return bool
*/
private function excludeFromContributions( AbstractRevision $revision ) {
- return (bool) $this->actions->getValue( $revision->getChangeType(), 'exclude_from_contributions' );
+ return (bool)$this->actions->getValue( $revision->getChangeType(), 'exclude_from_contributions' );
}
/**
@@ -131,13 +131,13 @@ class ContributionsQuery extends AbstractQuery {
* @return array Query conditions
*/
protected function buildConditions( $pager, $offset, $descending ) {
- $conditions = array();
+ $conditions = [];
// Work out user condition
if ( property_exists( $pager, 'contribs' ) && $pager->contribs == 'newbie' ) {
list( $minUserId, $excludeUserIds ) = $this->getNewbieConditionInfo( $pager );
- $conditions['rev_user_wiki'] = wfWikiId();
+ $conditions['rev_user_wiki'] = wfWikiID();
$conditions[] = 'rev_user_id > '. (int)$minUserId;
if ( $excludeUserIds ) {
// better safe than sorry - make sure everything's an int
@@ -150,14 +150,19 @@ class ContributionsQuery extends AbstractQuery {
if ( $uid ) {
$conditions['rev_user_id'] = $uid;
$conditions['rev_user_ip'] = null;
- $conditions['rev_user_wiki'] = wfWikiId();
+ $conditions['rev_user_wiki'] = wfWikiID();
} else {
$conditions['rev_user_id'] = 0;
$conditions['rev_user_ip'] = $pager->target;
- $conditions['rev_user_wiki'] = wfWikiId();
+ $conditions['rev_user_wiki'] = wfWikiID();
}
}
+ if ( property_exists( $pager, 'newOnly' ) && $pager->newOnly ) {
+ $conditions['rev_parent_id'] = null;
+ $conditions['rev_type'] = 'post';
+ }
+
// Make offset parameter.
if ( $offset ) {
$dbr = $this->dbFactory->getDB( DB_SLAVE );
@@ -167,7 +172,7 @@ class ContributionsQuery extends AbstractQuery {
}
// Find only within requested wiki/namespace
- $conditions['workflow_wiki'] = wfWikiId();
+ $conditions['workflow_wiki'] = wfWikiID();
if ( $pager->namespace !== '' ) {
$conditions['workflow_namespace'] = $pager->namespace;
}
@@ -188,73 +193,79 @@ class ContributionsQuery extends AbstractQuery {
switch ( $revisionClass ) {
case 'PostRevision':
return $dbr->select(
- array(
+ [
'flow_revision', // revisions to find
'flow_tree_revision', // resolve to post id
'flow_tree_node', // resolve to root post (topic title)
'flow_workflow', // resolve to workflow, to test if in correct wiki/namespace
- ),
- array( '*' ),
+ ],
+ [ '*' ],
$conditions,
__METHOD__,
- array(
+ [
'LIMIT' => $limit,
'ORDER BY' => 'rev_id DESC',
- ),
- array(
- 'flow_tree_revision' => array(
+ ],
+ [
+ 'flow_tree_revision' => [
'INNER JOIN',
- array( 'tree_rev_id = rev_id' )
- ),
- 'flow_tree_node' => array(
+ [ 'tree_rev_id = rev_id' ]
+ ],
+ 'flow_tree_node' => [
'INNER JOIN',
- array(
+ [
'tree_descendant_id = tree_rev_descendant_id',
// the one with max tree_depth will be root,
// which will have the matching workflow id
- )
- ),
- 'flow_workflow' => array(
+ ]
+ ],
+ 'flow_workflow' => [
'INNER JOIN',
- array( 'workflow_id = tree_ancestor_id' )
- ),
- )
+ [ 'workflow_id = tree_ancestor_id' ]
+ ],
+ ]
);
break;
case 'Header':
return $dbr->select(
- array( 'flow_revision', 'flow_workflow' ),
- array( '*' ),
+ [ 'flow_revision', 'flow_workflow' ],
+ [ '*' ],
$conditions,
__METHOD__,
- array(
+ [
'LIMIT' => $limit,
'ORDER BY' => 'rev_id DESC',
- ),
- array(
- 'flow_workflow' => array(
+ ],
+ [
+ 'flow_workflow' => [
'INNER JOIN',
- array( 'workflow_id = rev_type_id' , 'rev_type' => 'header' )
- ),
- )
+ [ 'workflow_id = rev_type_id' , 'rev_type' => 'header' ]
+ ],
+ ]
);
break;
case 'PostSummary':
return $dbr->select(
- array( 'flow_revision', 'flow_workflow', 'flow_tree_node' ),
- array( '*' ),
- $conditions + array(
- 'workflow_id = tree_ancestor_id',
- 'tree_descendant_id = rev_type_id',
- 'rev_type' => 'post-summary'
- ),
+ [ 'flow_revision', 'flow_tree_node', 'flow_workflow' ],
+ [ '*' ],
+ $conditions,
__METHOD__,
- array(
+ [
'LIMIT' => $limit,
'ORDER BY' => 'rev_id DESC',
- )
+ ],
+ [
+ 'flow_tree_node' => [
+ 'INNER JOIN',
+ [ 'tree_descendant_id = rev_type_id', 'rev_type' => 'post-summary' ]
+ ],
+ 'flow_workflow' => [
+ 'INNER JOIN',
+ [ 'workflow_id = tree_ancestor_id' ]
+ ]
+ ]
);
break;
@@ -272,19 +283,19 @@ class ContributionsQuery extends AbstractQuery {
* @return array
*/
protected function loadRevisions( ResultWrapper $rows, $revisionClass ) {
- $revisions = array();
+ $revisions = [];
foreach ( $rows as $row ) {
- $revisions[UUID::create( $row->rev_id )->getAlphadecimal()] = (array) $row;
+ $revisions[UUID::create( $row->rev_id )->getAlphadecimal()] = (array)$row;
}
// get content in external storage
- $res = array( $revisions );
+ $res = [ $revisions ];
$res = RevisionStorage::mergeExternalContent( $res );
$revisions = reset( $res );
// we have all required data to build revision
$mapper = $this->storage->getStorage( $revisionClass )->getMapper();
- $revisions = array_map( array( $mapper, 'fromStorageRow' ), $revisions );
+ $revisions = array_map( [ $mapper, 'fromStorageRow' ], $revisions );
// @todo: we may already be able to build workflowCache (and rootPostIdCache) from this DB data
@@ -302,39 +313,41 @@ class ContributionsQuery extends AbstractQuery {
$max = $this->cache->get( $key );
if ( $max === false ) {
// max user id not present in cache; fetch from db & save to cache for 1h
- $max = (int) $pager->getDatabase()->selectField( 'user', 'MAX(user_id)', '', __METHOD__ );
+ $max = (int)$pager->getDatabase()->selectField( 'user', 'MAX(user_id)', '', __METHOD__ );
$this->cache->set( $key, $max, 60 * 60 );
}
- $minUserId = (int) ( $max - $max / 100 );
+ $minUserId = (int)( $max - $max / 100 );
- // exclude all users withing groups with bot permission
- $excludeUserIds = array();
+ // exclude all users within groups with bot permission
+ $excludeUserIds = [];
$groupsWithBotPermission = User::getGroupsWithPermission( 'bot' );
if ( count( $groupsWithBotPermission ) ) {
- $rows = $pager->getDatabase()->select(
- array( 'user', 'user_groups' ),
+ $db = $pager->getDatabase();
+ $rows = $db->select(
+ [ 'user', 'user_groups' ],
'user_id',
- array(
+ [
'user_id > ' . $minUserId,
- 'ug_group' => $groupsWithBotPermission
- ),
+ 'ug_group' => $groupsWithBotPermission,
+ 'ug_expiry IS NULL OR ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
+ ],
__METHOD__,
- array(),
- array(
- 'user_groups' => array(
+ [],
+ [
+ 'user_groups' => [
'INNER JOIN',
- array( 'ug_user = user_id' )
- )
- )
+ [ 'ug_user = user_id' ]
+ ]
+ ]
);
- $excludeUserIds = array();
+ $excludeUserIds = [];
foreach ( $rows as $row ) {
$excludeUserIds[] = $row->user_id;
}
}
- return array( $minUserId, $excludeUserIds );
+ return [ $minUserId, $excludeUserIds ];
}
/**
diff --git a/Flow/includes/Formatter/FeedItemFormatter.php b/Flow/includes/Formatter/FeedItemFormatter.php
index f182d351..9ce86dbd 100644
--- a/Flow/includes/Formatter/FeedItemFormatter.php
+++ b/Flow/includes/Formatter/FeedItemFormatter.php
@@ -2,10 +2,8 @@
namespace Flow\Formatter;
-use Exception;
use FeedItem;
use Flow\Exception\FlowException;
-use Flow\Model\PostRevision;
use IContextSource;
class FeedItemFormatter extends AbstractFormatter {
@@ -26,12 +24,12 @@ class FeedItemFormatter extends AbstractFormatter {
return false;
}
- $preferredLinks = array(
+ $preferredLinks = [
'header-revision',
'post-revision', 'post',
'topic-revision', 'topic',
'board'
- );
+ ];
$url = '';
foreach ( $preferredLinks as $link ) {
if ( isset( $data['links'][$link] ) ) {
diff --git a/Flow/includes/Formatter/HistoryQuery.php b/Flow/includes/Formatter/HistoryQuery.php
new file mode 100644
index 00000000..66538f17
--- /dev/null
+++ b/Flow/includes/Formatter/HistoryQuery.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Flow\Formatter;
+
+use Flow\FlowActions;
+use Flow\Data\ManagerGroup;
+use Flow\Model\AbstractRevision;
+use Flow\Model\UUID;
+use Flow\Repository\TreeRepository;
+
+abstract class HistoryQuery extends AbstractQuery {
+ // This requests extra to take into account that we will filter some out,
+ // to try to reduce the number of rounds (preferably to 1).
+ // If you raise this, also increase history_index_limit and bump the
+ // key of the indexes using history_index_limit
+ // This magic number is based on new-post/new-topic being about 26% of post revisions.
+ // (queried from production), since that is the only thing currently excluded.
+ const POST_OVERFETCH_FACTOR = 1.36;
+
+ /**
+ * @var FlowActions
+ */
+ protected $actions;
+
+ /**
+ * @param ManagerGroup $storage
+ * @param TreeRepository $treeRepo
+ * @param FlowActions $actions
+ */
+ public function __construct(
+ ManagerGroup $storage,
+ TreeRepository $treeRepo,
+ FlowActions $actions
+ ) {
+ parent::__construct( $storage, $treeRepo );
+ $this->actions = $actions;
+ }
+
+ /**
+ * @param AbstractRevision $revision
+ * @return bool
+ */
+ protected function includeInHistory( AbstractRevision $revision ) {
+ // If you add exclude_from_history to a new type, use doInternalQueries on additional
+ // queries as needed.
+ return !$this->actions->getValue( $revision->getChangeType(), 'exclude_from_history' );
+ }
+
+ /**
+ * Gets query options that are common to all history queries
+ *
+ * @param string $direction 'fwd' or 'rev'. 'fwd' means to get items older than
+ * the offset. 'rev' means to get items newer. Either way, an individual page is
+ * eventually returned and displayed in descending order.
+ * @param int $limit Maximum number of items
+ * @param UUID $offset UUID to use as offset (optional)
+ * @return array Associative array of options for query
+ */
+ protected function getOptions( $direction, $limit, UUID $offset = null ) {
+ return [
+ 'sort' => 'rev_id',
+ 'order' => $direction === 'fwd' ? 'DESC' : 'ASC',
+ 'limit' => $limit,
+ 'offset-id' => $offset,
+ 'offset-dir' => $direction,
+ 'offset-include' => false,
+ ];
+ }
+
+ /**
+ * Internally re-query as needed to handle items excluded from history
+ *
+ * Re-queries until there are no more entries or after filtering, there are the
+ * desired number of results.
+ *
+ * This respects the given order (ASC or DESC), but the reversing for 'rev' is in
+ * getResults.
+ *
+ * @param string $storageClass Storage class ID
+ * @param array $attributes Query attriutes
+ * @param array $options Query options, including offset-id and limit
+ * @param int $overfetchFactor Factor to overfetch by to anticipate excludes
+ * @return array Array of history rows
+ */
+ protected function doInternalQueries( $storageClass, $attributes, $options, $overfetchFactor ) {
+ $result = [];
+
+ $limit = $options['limit'];
+ $internalOffset = $options['offset-id'];
+
+ do {
+ $remainingNeeded = $limit - count( $result );
+
+ // The special cases here are to try reduce dribbling out of final requests (50, 25, 10, 5...).
+ if ( $remainingNeeded < 50 ) {
+ $overfetchFactor *= 2;
+ }
+
+ $beforeFilteringCountWanted = max( 10, intval( $overfetchFactor * $remainingNeeded ) );
+
+ // Over-fetch by 1 item so we can figure out when to stop re-querying.
+ $options['limit'] = $beforeFilteringCountWanted + 1;
+
+ $options['offset-id'] = $internalOffset;
+
+ $resultBeforeFiltering = $this->storage->find( $storageClass, $attributes, $options );
+
+ // We over-fetched, now get rid of redundant value for our "real" data
+ $internalOverfetched = null;
+ if ( count( $resultBeforeFiltering ) > $beforeFilteringCountWanted ) {
+ $internalOverfetched = array_pop( $resultBeforeFiltering );
+ }
+
+ $resultAfterFiltering = array_filter( $resultBeforeFiltering, [ $this, 'includeInHistory' ] );
+
+ if ( count( $resultBeforeFiltering ) >= 1 ) {
+ $internalOffset = end( $resultBeforeFiltering )->getRevisionId();
+ }
+
+ $trimmedResultAfterFiltering = array_slice( $resultAfterFiltering, 0, $remainingNeeded );
+ $result = array_merge( $result, $trimmedResultAfterFiltering );
+ } while ( count( $result ) < $limit && $internalOverfetched !== null );
+
+ return $result;
+ }
+
+}
diff --git a/Flow/includes/Formatter/IRCLineUrlFormatter.php b/Flow/includes/Formatter/IRCLineUrlFormatter.php
index 8cbce8bb..b11d4ab3 100644
--- a/Flow/includes/Formatter/IRCLineUrlFormatter.php
+++ b/Flow/includes/Formatter/IRCLineUrlFormatter.php
@@ -3,7 +3,6 @@
namespace Flow\Formatter;
use Flow\Container;
-use Flow\Exception\FlowException;
use Flow\RevisionActionPermissions;
use IContextSource;
use RCFeedFormatter;
@@ -50,7 +49,10 @@ class IRCLineUrlFormatter extends AbstractFormatter implements RCFeedFormatter {
return null;
}
+ // @todo Public access to $rc->mAttribs should be deprecated in core.
$rc->mAttribs['rc_comment'] = $this->formatDescription( $serialized, $ctx );
+ $rc->mAttribs['rc_comment_text'] = $rc->mAttribs['rc_comment'];
+ $rc->mAttribs['rc_comment_data'] = null;
/** @var RCFeedFormatter $formatter */
$formatter = new $feed['original_formatter']();
@@ -70,7 +72,7 @@ class IRCLineUrlFormatter extends AbstractFormatter implements RCFeedFormatter {
protected function serializeRcRevision( RecentChange $rc, IContextSource $ctx ) {
/** @var RecentChangesQuery $query */
$query = Container::get( 'query.changeslist' );
- $query->loadMetadataBatch( array( (object)$rc->mAttribs ) );
+ $query->loadMetadataBatch( [ (object)$rc->mAttribs ] );
$rcRow = $query->getResult( null, $rc );
if ( !$rcRow ) {
return false;
@@ -111,12 +113,12 @@ class IRCLineUrlFormatter extends AbstractFormatter implements RCFeedFormatter {
$links = $this->serializer->buildLinks( $row );
// Listed in order of preference
- $accept = array(
+ $accept = [
'diff',
'post-history', 'topic-history', 'board-history',
'post', 'topic',
'workflow'
- );
+ ];
foreach ( $accept as $key ) {
if ( isset( $links[$key] ) ) {
diff --git a/Flow/includes/Formatter/PostHistoryQuery.php b/Flow/includes/Formatter/PostHistoryQuery.php
index d7d967bc..30f91968 100644
--- a/Flow/includes/Formatter/PostHistoryQuery.php
+++ b/Flow/includes/Formatter/PostHistoryQuery.php
@@ -5,7 +5,7 @@ namespace Flow\Formatter;
use Flow\Exception\FlowException;
use Flow\Model\UUID;
-class PostHistoryQuery extends AbstractQuery {
+class PostHistoryQuery extends HistoryQuery {
/**
* @param UUID $postId
@@ -17,23 +17,20 @@ class PostHistoryQuery extends AbstractQuery {
public function getResults( UUID $postId, $limit = 50, UUID $offset = null, $direction = 'fwd' ) {
$history = $this->storage->find(
'PostRevision',
- array( 'rev_type_id' => $postId ),
- array(
- 'sort' => 'rev_id',
- 'order' => 'DESC',
- 'limit' => $limit,
- 'offset-id' => $offset,
- 'offset-dir' => $direction,
- 'offset-include' => false,
- 'offset-elastic' => false,
- )
+ [ 'rev_type_id' => $postId ],
+ $this->getOptions( $direction, $limit, $offset )
);
if ( !$history ) {
- return array();
+ return [];
+ }
+
+ // See explanation in BoardHistoryQuery::getResults.
+ if ( $direction === 'rev' ) {
+ $history = array_reverse( $history );
}
$this->loadMetadataBatch( $history );
- $results = array();
+ $results = [];
foreach ( $history as $revision ) {
try {
$results[] = $row = new FormatterRow;
diff --git a/Flow/includes/Formatter/PostSummaryQuery.php b/Flow/includes/Formatter/PostSummaryQuery.php
index 47ca8694..89625b67 100644
--- a/Flow/includes/Formatter/PostSummaryQuery.php
+++ b/Flow/includes/Formatter/PostSummaryQuery.php
@@ -12,8 +12,8 @@ class PostSummaryQuery extends AbstractQuery {
public function getResult( UUID $postId ) {
$found = $this->storage->find(
'PostSummary',
- array( 'rev_type_id' => $postId ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $postId ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( !$found ) {
return null;
diff --git a/Flow/includes/Formatter/RevisionDiffViewFormatter.php b/Flow/includes/Formatter/RevisionDiffViewFormatter.php
index f6ac2df2..7a89c1aa 100644
--- a/Flow/includes/Formatter/RevisionDiffViewFormatter.php
+++ b/Flow/includes/Formatter/RevisionDiffViewFormatter.php
@@ -33,8 +33,8 @@ class RevisionDiffViewFormatter {
$oldRes = $this->revisionViewFormatter->formatApi( $oldRow, $ctx );
$newRes = $this->revisionViewFormatter->formatApi( $newRow, $ctx );
- $oldContent = $oldRow->revision->getContent( 'wikitext' );
- $newContent = $newRow->revision->getContent( 'wikitext' );
+ $oldContent = $oldRow->revision->getContentInWikitext();
+ $newContent = $newRow->revision->getContentInWikitext();
$differenceEngine = new \DifferenceEngine();
@@ -67,14 +67,14 @@ class RevisionDiffViewFormatter {
)->getLocalURL();
}
- return array(
+ return [
'new' => $newRes,
'old' => $oldRes,
'diff_content' => $differenceEngine->getDiffBody(),
- 'links' => array(
+ 'links' => [
'previous' => $prevLink,
'next' => $nextLink,
- ),
- );
+ ],
+ ];
}
}
diff --git a/Flow/includes/Formatter/RevisionFormatter.php b/Flow/includes/Formatter/RevisionFormatter.php
index 2ab3bd4c..8a904456 100644
--- a/Flow/includes/Formatter/RevisionFormatter.php
+++ b/Flow/includes/Formatter/RevisionFormatter.php
@@ -3,7 +3,6 @@
namespace Flow\Formatter;
use Flow\Collection\PostCollection;
-use Flow\Container;
use Flow\Exception\PermissionException;
use Flow\Repository\UserNameBatch;
use Flow\Exception\FlowException;
@@ -12,7 +11,7 @@ use Flow\Model\Anchor;
use Flow\Model\PostRevision;
use Flow\Model\PostSummary;
use Flow\Model\UUID;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Flow\RevisionActionPermissions;
use Flow\Templating;
use Flow\UrlGenerator;
@@ -20,6 +19,7 @@ use ApiResult;
use GenderCache;
use IContextSource;
use Message;
+use Wikimedia\Timestamp\TimestampException;
/**
* This implements a serializer for converting revision objects
@@ -67,9 +67,12 @@ class RevisionFormatter {
protected $includeContent = true;
/**
- * @var string[]
+ * @var string[] Allowed content formats
+ *
+ * See setContentFormat.
*/
- protected $allowedContentFormats = array( 'html', 'wikitext', 'fixed-html', 'plaintext' );
+ protected $allowedContentFormats = [ 'html', 'wikitext', 'fixed-html',
+ 'topic-title-html', 'topic-title-wikitext' ];
/**
* @var string Default content format for revision output
@@ -77,9 +80,9 @@ class RevisionFormatter {
protected $contentFormat = 'fixed-html';
/**
- * @var array Map from alphadeicmal revision id to content format ovverride
+ * @var array Map from alphadecimal revision id to content format override
*/
- protected $revisionContentFormat = array();
+ protected $revisionContentFormat = [];
/**
* @var int
@@ -89,12 +92,12 @@ class RevisionFormatter {
/**
* @var Message[]
*/
- protected $messages = array();
+ protected $messages = [];
/**
* @var array
*/
- protected $userLinks = array();
+ protected $userLinks = [];
/**
* @var UserNameBatch
@@ -146,6 +149,27 @@ class RevisionFormatter {
$this->includeContent = (bool)$shouldInclude;
}
+ /**
+ * Sets the content format for all revisions formatted by this formatter, or a
+ * particular revision.
+ *
+ * @param string $format Format to use for revision content. If no revision ID is
+ * given, this is a default format, and the allowed formats are 'html', 'wikitext',
+ * and 'fixed-html'.
+ *
+ * For the default format, 'fixed-html' will be converted to 'topic-title-html'
+ * when formatting a topic title. 'html' and 'wikitext' will be converted to
+ * 'topic-title-wikitext' for topic titles (because 'html' and 'wikitext' are
+ * editable, and 'topic-title-html' is not editable).
+ *
+ * If a revision ID is given, the allowed formats are 'html', 'wikitext',
+ * 'fixed-html', 'topic-title-html', and 'topic-title-wikitext'. However, the
+ * format will not be converted, and must be valid for the given revision ('html',
+ * 'wikitext', and 'fixed-html' are valid only for non-topic titles.
+ * 'topic-title-html' and 'topic-title-wikitext' are only valid for topic titles.
+ * Otherwise, an exception will be thrown later.
+ * @param UUID $revisionId Revision ID this format applies for.
+ */
public function setContentFormat( $format, UUID $revisionId = null ) {
if ( false === array_search( $format, $this->allowedContentFormats ) ) {
throw new FlowException( "Unknown content format: $format" );
@@ -168,7 +192,7 @@ class RevisionFormatter {
* @throws PermissionException
* @throws \Exception
* @throws \Flow\Exception\InvalidInputException
- * @throws \TimestampException
+ * @throws TimestampException
*/
public function formatApi( FormatterRow $row, IContextSource $ctx, $action = 'view' ) {
$this->permissions->setUser( $ctx->getUser() );
@@ -179,13 +203,13 @@ class RevisionFormatter {
$moderatedRevision = $this->templating->getModeratedRevision( $row->revision );
$ts = $row->revision->getRevisionId()->getTimestampObj();
- $res = array(
- ApiResult::META_BC_BOOLS => array(
+ $res = [
+ ApiResult::META_BC_BOOLS => [
'isOriginalContent',
'isModerated',
'isLocked',
'isModeratedNotLocked',
- ),
+ ],
'workflowId' => $row->workflow->getId()->getAlphadecimal(),
'articleTitle' => $row->workflow->getArticleTitle()->getPrefixedText(),
'revisionId' => $row->revision->getRevisionId()->getAlphadecimal(),
@@ -200,10 +224,10 @@ class RevisionFormatter {
'links' => $this->buildLinks( $row ),
// These are write urls
'actions' => $this->buildActions( $row ),
- 'size' => array(
+ 'size' => [
'old' => $row->revision->getPreviousContentLength(),
'new' => $row->revision->getContentLength(),
- ),
+ ],
'author' => $this->serializeUser(
$row->revision->getUserWiki(),
$row->revision->getUserId(),
@@ -218,7 +242,7 @@ class RevisionFormatter {
'previousRevisionId' => $row->revision->isFirstRevision()
? null
: $row->revision->getPrevRevisionId()->getAlphadecimal(),
- );
+ ];
if ( $res['isModerated'] ) {
$res['moderator'] = $this->serializeUser(
@@ -228,10 +252,10 @@ class RevisionFormatter {
);
// @todo why moderate instead of moderated or something else?
$res['moderateState'] = $moderatedRevision->getModerationState();
- $res['moderateReason'] = array(
+ $res['moderateReason'] = [
'content' => $moderatedRevision->getModeratedReason(),
'format' => 'plaintext',
- );
+ ];
$res['isLocked'] = $moderatedRevision->isLocked();
} else {
$res['isLocked'] = false;
@@ -240,30 +264,29 @@ class RevisionFormatter {
$res['isModeratedNotLocked'] = $moderatedRevision->isModerated() && !$moderatedRevision->isLocked();
if ( $this->includeContent ) {
- // topic titles are always forced to plain text
$contentFormat = $this->decideContentFormat( $row->revision );
// @todo better name?
- $res['content'] = array(
+ $res['content'] = [
'content' => $this->templating->getContent( $row->revision, $contentFormat ),
'format' => $contentFormat
- );
+ ];
}
if ( $row instanceof TopicRow ) {
$res[ApiResult::META_BC_BOOLS] = array_merge(
$res[ApiResult::META_BC_BOOLS],
- array(
+ [
'isWatched',
'watchable',
- )
+ ]
);
if ( $row->summary ) {
$summary = $this->formatApi( $row->summary, $ctx, $action );
if ( $summary ) {
- $res['summary'] = array(
- 'revision' => $summary,
- );
+ $res['summary'] = [
+ 'revision' => $summary,
+ ];
}
}
@@ -272,7 +295,7 @@ class RevisionFormatter {
// watchable - the user could watch the topic, eg, anon-user can't watch a topic
if ( !$ctx->getUser()->isAnon() ) {
// default topic is not watched and topic is not always watched
- $res['isWatched'] = (bool) $row->isWatched;
+ $res['isWatched'] = (bool)$row->isWatched;
$res['watchable'] = true;
} else {
$res['watchable'] = false;
@@ -282,10 +305,10 @@ class RevisionFormatter {
if ( $row->revision instanceof PostRevision ) {
$res[ApiResult::META_BC_BOOLS] = array_merge(
$res[ApiResult::META_BC_BOOLS],
- array(
+ [
'isMaxThreadingDepth',
'isNewPage',
- )
+ ]
);
$replyTo = $row->revision->getReplyToId();
@@ -309,6 +332,19 @@ class RevisionFormatter {
$ctx,
$row
);
+
+ $res['properties']['topic-of-post-text-from-html'] = $this->processParam(
+ 'topic-of-post-text-from-html',
+ $row->revision,
+ $row->workflow->getId(),
+ $ctx,
+ $row
+ );
+
+ // moderated posts won't have that property
+ if ( isset( $res['properties']['topic-of-post-text-from-html']['plaintext'] ) ) {
+ $res['content']['plaintext'] = $res['properties']['topic-of-post-text-from-html']['plaintext'];
+ }
}
$res['isNewPage'] = $row->isFirstReply && $row->revision->isFirstRevision();
@@ -343,58 +379,58 @@ class RevisionFormatter {
$blockTitle = \SpecialPage::getTitleFor( 'Block', $name );
$userContribsTitle = \SpecialPage::getTitleFor( 'Contributions', $name );
- $userLinksBCBools = array(
- '_BC_bools' => array(
+ $userLinksBCBools = [
+ '_BC_bools' => [
'exists',
- ),
- );
- $links = array(
- 'contribs' => array(
+ ],
+ ];
+ $links = [
+ 'contribs' => [
'url' => $userContribsTitle->getLinkURL(),
'title' => $userContribsTitle->getText(),
'exists' => true,
- ) + $userLinksBCBools,
- 'userpage' => array(
+ ] + $userLinksBCBools,
+ 'userpage' => [
'url' => $userTitle->getLinkURL(),
'title' => $userTitle->getText(),
'exists' => $userTitle->isKnown(),
- ) + $userLinksBCBools,
- );
+ ] + $userLinksBCBools,
+ ];
if ( $talkPageTitle ) {
- $links['talk'] = array(
+ $links['talk'] = [
'url' => $talkPageTitle->getLinkURL(),
'title' => $talkPageTitle->getPrefixedText(),
'exists' => $talkPageTitle->isKnown()
- ) + $userLinksBCBools;
+ ] + $userLinksBCBools;
}
// is this right permissions? typically this would
// be sourced from Linker::userToolLinks, but that
// only undertands html strings.
if ( $this->permissions->getUser()->isAllowed( 'block' ) ) {
// only is the user has blocking rights
- $links += array(
- "block" => array(
+ $links += [
+ "block" => [
'url' => $blockTitle->getLinkURL(),
'title' => wfMessage( 'blocklink' ),
'exists' => true
- ) + $userLinksBCBools,
- );
+ ] + $userLinksBCBools,
+ ];
}
return $this->userLinks[$name] = $links;
}
public function serializeUser( $userWiki, $userId, $userIp ) {
- $res = array(
+ $res = [
'name' => $this->usernames->get( $userWiki, $userId, $userIp ),
'wiki' => $userWiki,
'gender' => 'unknown',
- 'links' => array(),
+ 'links' => [],
'id' => $userId
- );
+ ];
// Only works for the local wiki
- if ( wfWikiId() === $userWiki ) {
+ if ( wfWikiID() === $userWiki ) {
$res['gender'] = $this->genderCache->getGenderOf( $res['name'], __METHOD__ );
}
if ( $res['name'] ) {
@@ -412,18 +448,18 @@ class RevisionFormatter {
public function getDateFormats( AbstractRevision $revision, IContextSource $ctx ) {
// also restricted to history
if ( $this->includeProperties === false ) {
- return array();
+ return [];
}
$timestamp = $revision->getRevisionId()->getTimestampObj()->getTimestamp( TS_MW );
$user = $ctx->getUser();
$lang = $ctx->getLanguage();
- return array(
+ return [
'timeAndDate' => $lang->userTimeAndDate( $timestamp, $user ),
'date' => $lang->userDate( $timestamp, $user ),
'time' => $lang->userTime( $timestamp, $user ),
- );
+ ];
}
/**
@@ -436,16 +472,10 @@ class RevisionFormatter {
$workflow = $row->workflow;
$title = $workflow->getArticleTitle();
- // If a user is blocked from performing actions on this page return
+ // If a user does not have rights to perform actions on this page return
// an empty array of actions.
- //
- // We only check actual users and not anon's because the anonymous
- // version can be cached and served to many different ip addresses
- // which will not all be blocked.
- if ( !$user->isAnon() &&
- ( $user->isBlockedFrom( $title, true ) || !$title->quickUserCan( 'edit', $user ) )
- ) {
- return array();
+ if ( !$workflow->userCan( 'edit', $user ) ) {
+ return [];
}
$revision = $row->revision;
@@ -456,16 +486,16 @@ class RevisionFormatter {
$actionTypes = $this->permissions->getActions()->getValue( $action, 'actions' );
if ( $actionTypes === null ) {
wfDebugLog( 'Flow', __METHOD__ . ": No actions defined for action: $action" );
- return array();
+ return [];
}
// actions primarily vary by revision type...
- $links = array();
+ $links = [];
foreach ( $actionTypes as $type ) {
if ( !$this->permissions->isAllowed( $revision, $type ) ) {
continue;
}
- switch( $type ) {
+ switch ( $type ) {
case 'thank':
if (
// thanks extension must be available
@@ -547,7 +577,6 @@ class RevisionFormatter {
}
break;
-
case 'hide-post':
if ( !$postId ) {
throw new FlowException( "$type called without \$postId" );
@@ -610,7 +639,7 @@ class RevisionFormatter {
throw new FlowException( "$type called without \$postId" );
}
$moderateAction = $flowAction = null;
- switch( $revision->getModerationState() ) {
+ switch ( $revision->getModerationState() ) {
case AbstractRevision::MODERATED_HIDDEN:
case AbstractRevision::MODERATED_DELETED:
case AbstractRevision::MODERATED_SUPPRESSED:
@@ -630,13 +659,12 @@ class RevisionFormatter {
// Need to use 'edit-topic-summary' to match FlowActions
case 'edit-topic-summary':
// summarize link is only available to topic workflow
- if( !in_array( $workflow->getType(), array( 'topic', 'topicsummary' ) ) ) {
+ if ( !in_array( $workflow->getType(), [ 'topic', 'topicsummary' ] ) ) {
continue;
}
$links['summarize'] = $this->urlGenerator->editTopicSummaryAction( $title, $workflowId );
break;
-
default:
wfDebugLog( 'Flow', __METHOD__ . ': unkown action link type: ' . $type );
break;
@@ -663,12 +691,12 @@ class RevisionFormatter {
$linkTypes = $this->permissions->getActions()->getValue( $action, 'links' );
if ( $linkTypes === null ) {
wfDebugLog( 'Flow', __METHOD__ . ": No links defined for action: $action" );
- return array();
+ return [];
}
- $links = array();
+ $links = [];
foreach ( $linkTypes as $type ) {
- switch( $type ) {
+ switch ( $type ) {
case 'watch-topic':
$links['watch-topic'] = $this->urlGenerator->watchTopicLink( $title, $workflowId );
break;
@@ -737,14 +765,14 @@ class RevisionFormatter {
/** @noinspection PhpMissingBreakStatementInspection */
case 'diff-header':
- $diffCallback = isset( $diffCallback ) ? $diffCallback : array( $this->urlGenerator, 'diffHeaderLink' );
+ $diffCallback = isset( $diffCallback ) ? $diffCallback : [ $this->urlGenerator, 'diffHeaderLink' ];
// don't break, diff links are rendered below
/** @noinspection PhpMissingBreakStatementInspection */
case 'diff-post':
- $diffCallback = isset( $diffCallback ) ? $diffCallback : array( $this->urlGenerator, 'diffPostLink' );
+ $diffCallback = isset( $diffCallback ) ? $diffCallback : [ $this->urlGenerator, 'diffPostLink' ];
// don't break, diff links are rendered below
case 'diff-post-summary':
- $diffCallback = isset( $diffCallback ) ? $diffCallback : array( $this->urlGenerator, 'diffSummaryLink' );
+ $diffCallback = isset( $diffCallback ) ? $diffCallback : [ $this->urlGenerator, 'diffSummaryLink' ];
/*
* To diff against previous revision, we don't really need that
@@ -796,7 +824,6 @@ class RevisionFormatter {
}
}
-
return $links;
}
@@ -819,7 +846,7 @@ class RevisionFormatter {
FormatterRow $row = null
) {
if ( $this->includeProperties === false ) {
- return array();
+ return [];
}
$changeType = $revision->getChangeType();
@@ -828,10 +855,10 @@ class RevisionFormatter {
if ( !$params ) {
// should we have a sigil for i18n with no parameters?
wfDebugLog( 'Flow', __METHOD__ . ": No i18n params for changeType $changeType on " . $revision->getRevisionId()->getAlphadecimal() );
- return array();
+ return [];
}
- $res = array( '_key' => $actions->getValue( $changeType, 'history', 'i18n-message' ) );
+ $res = [ '_key' => $actions->getValue( $changeType, 'history', 'i18n-message' ) ];
foreach ( $params as $param ) {
$res[$param] = $this->processParam( $param, $revision, $workflowId, $ctx, $row );
}
@@ -894,7 +921,9 @@ class RevisionFormatter {
return '';
}
- $content = $this->templating->getContent( $revision, 'wikitext' );
+ $format = $revision->getWikitextFormat();
+
+ $content = $this->templating->getContent( $revision, $format );
// This must be escaped and marked raw to prevent special chars in
// content, like $1, from changing the i18n result
return Message::plaintextParam( $content );
@@ -917,7 +946,41 @@ class RevisionFormatter {
return '';
}
- $content = $this->templating->getContent( $previousRevision, 'wikitext' );
+ $format = $revision->getWikitextFormat();
+
+ $content = $this->templating->getContent( $previousRevision, $format );
+ return Message::plaintextParam( $content );
+ case 'plaintext':
+ if ( !$this->permissions->isAllowed( $revision, 'view' ) ) {
+ return '';
+ }
+
+ $format = $revision->getHtmlFormat();
+
+ $content = Utils::htmlToPlaintext( $this->templating->getContent( $revision, $format ) );
+ return Message::plaintextParam( $content );
+
+ // This is potentially two networked round trips, much too expensive for
+ // the rendering loop
+ case 'prev-plaintext':
+ if ( $revision->isFirstRevision() ) {
+ return '';
+ }
+ if ( $row === null ) {
+ $previousRevision = $revision->getCollection()->getPrevRevision( $revision );
+ } else {
+ $previousRevision = $row->previousRevision;
+ }
+ if ( !$previousRevision ) {
+ return '';
+ }
+ if ( !$this->permissions->isAllowed( $previousRevision, 'view' ) ) {
+ return '';
+ }
+
+ $format = $revision->getHtmlFormat();
+
+ $content = Utils::htmlToPlaintext( $this->templating->getContent( $previousRevision, $format ) );
return Message::plaintextParam( $content );
case 'workflow-url':
@@ -943,11 +1006,32 @@ class RevisionFormatter {
}
$root = $revision->getRootPost();
- if ( !$this->permissions->isAllowed( $root, 'view' ) ) {
+ if ( !$this->permissions->isAllowed( $root, 'view-topic-title' ) ) {
+ return '';
+ }
+
+ $content = $this->templating->getContent( $root, 'topic-title-wikitext' );
+
+ // TODO: We need to use plaintextParam or similar to avoid parsing,
+ // but the API output says "plaintext", which is confusing and
+ // should be fixed. From the API consumer's perspective, it's
+ // topic-title-wikitext.
+ return Message::plaintextParam( $content );
+
+ // Strip the tags from the HTML version to produce text:
+ // [[Red link 3]], [[Adrines]], [[Media:Earth.jpg]], http://example.com =>
+ // Red link 3, Adrines, Media:Earth.jpg, http://example.com
+ case 'topic-of-post-text-from-html':
+ if ( !$revision instanceof PostRevision ) {
+ throw new FlowException( 'Expected PostRevision but received ' . get_class( $revision ) );
+ }
+
+ $root = $revision->getRootPost();
+ if ( !$this->permissions->isAllowed( $root, 'view-topic-title' ) ) {
return '';
}
- $content = $this->templating->getContent( $root, 'wikitext' );
+ $content = $this->templating->getContent( $root, 'topic-title-plaintext' );
return Message::plaintextParam( $content );
@@ -958,12 +1042,13 @@ class RevisionFormatter {
/** @var PostRevision $post */
$post = $revision->getCollection()->getPost()->getLastRevision();
- if ( !$this->permissions->isAllowed( $post, 'view' ) ) {
+ $permissionAction = $post->isTopicTitle() ? 'view-topic-title' : 'view';
+ if ( !$this->permissions->isAllowed( $post, $permissionAction ) ) {
return '';
}
if ( $post->isTopicTitle() ) {
- return Message::plaintextParam( $this->templating->getContent( $post, 'wikitext' ) );
+ return Message::plaintextParam( $this->templating->getContent( $post, 'topic-title-plaintext' ) );
} else {
return Message::rawParam( $this->templating->getContent( $post, 'fixed-html' ) );
}
@@ -990,18 +1075,89 @@ class RevisionFormatter {
}
/**
+ * Determines the exact output content format, given the requested content format
+ * and the revision type.
+ *
* @param AbstractRevision $revision
- * @return string
+ * @return string Content format
+ * @throws FlowException If a per-revision format was given and it is
+ * invalid for the revision type (topic title/non-topic title).
*/
- protected function decideContentFormat( AbstractRevision $revision ) {
- if ( $revision instanceof PostRevision && $revision->isTopicTitle() ) {
- return 'plaintext';
- }
+ public function decideContentFormat( AbstractRevision $revision ) {
+ $requestedRevFormat = null;
+ $requestedDefaultFormat = null;
+
$alpha = $revision->getRevisionId()->getAlphadecimal();
if ( isset( $this->revisionContentFormat[$alpha] ) ) {
- return $this->revisionContentFormat[$alpha];
+ $requestedRevFormat = $this->revisionContentFormat[$alpha];
+ } else {
+ $requestedDefaultFormat = $this->contentFormat;
}
- return $this->contentFormat;
+ if ( $revision instanceof PostRevision && $revision->isTopicTitle() ) {
+ return $this->decideTopicTitleContentFormat( $revision, $requestedRevFormat, $requestedDefaultFormat );
+ } else {
+ return $this->decideNonTopicTitleContentFormat( $revision, $requestedRevFormat, $requestedDefaultFormat );
+ }
+ }
+
+ /**
+ * Decide the content format for a topic title
+ *
+ * @param PostRevision $topicTitle Topic title revision
+ * @param string|null $requestedRevFormat Format requested for this specific revision
+ * @param string|null $requestedDefaultFormat Default format requested
+ * @return string
+ * @throws FlowException If a per-revision format was given and it is
+ * invalid for topic titles.
+ */
+ protected function decideTopicTitleContentFormat( PostRevision $topicTitle, $requestedRevFormat, $requestedDefaultFormat ) {
+ if ( $requestedRevFormat !== null ) {
+ if ( $requestedRevFormat !== 'topic-title-html' &&
+ $requestedRevFormat !== 'topic-title-wikitext'
+ ) {
+ throw new FlowException( 'Per-revision format for a topic title must be \'topic-title-html\' or \'topic-title-wikitext\'' );
+ }
+ return $requestedRevFormat;
+ } else {
+ // Since this is a default format, we'll canonicalize it.
+
+ // Because these are both editable formats, and this is the only
+ // editable topic title format.
+ if ( $requestedDefaultFormat === 'topic-title-wikitext' || $requestedDefaultFormat === 'html' || $requestedDefaultFormat === 'wikitext' ) {
+ return 'topic-title-wikitext';
+ } else {
+ return 'topic-title-html';
+ }
+ }
+ }
+
+ /**
+ * Decide the content format for revisions other than topic titles
+ *
+ * @param AbstractRevision $revision Revision to decide format for
+ * @param string|null $requestedRevFormat Format requested for this specific revision
+ * @param string|null $requestedDefaultFormat Default format requested
+ * @return string
+ * @throws FlowException If a per-revision format was given and it is
+ * invalid for this type
+ */
+ protected function decideNonTopicTitleContentFormat( AbstractRevision $revision, $requestedRevFormat, $requestedDefaultFormat ) {
+ if ( $requestedRevFormat !== null ) {
+ if ( $requestedRevFormat === 'topic-title-html' ||
+ $requestedRevFormat === 'topic-title-wikitext'
+ ) {
+ throw new FlowException( 'Invalid per-revision format. Only topic titles can use \'topic-title-html\' and \'topic-title-wikitext\'' );
+ }
+ return $requestedRevFormat;
+ } else {
+ if ( $requestedDefaultFormat === 'topic-title-html' ||
+ $requestedDefaultFormat === 'topic-title-wikitext'
+ ) {
+ throw new FlowException( 'Default format of \'topic-title-html\' or \'topic-title-wikitext\' can only be used to format topic titles.' );
+ }
+
+ return $requestedDefaultFormat;
+ }
}
}
diff --git a/Flow/includes/Formatter/RevisionUndoViewFormatter.php b/Flow/includes/Formatter/RevisionUndoViewFormatter.php
index da6a6d13..44b4747d 100644
--- a/Flow/includes/Formatter/RevisionUndoViewFormatter.php
+++ b/Flow/includes/Formatter/RevisionUndoViewFormatter.php
@@ -3,7 +3,6 @@
namespace Flow\Formatter;
use DifferenceEngine;
-use Flow\Model\AbstractRevision;
use IContextSource;
use TextContent;
@@ -23,36 +22,37 @@ class RevisionUndoViewFormatter {
FormatterRow $current,
IContextSource $context
) {
+ $currentWikitext = $current->revision->getContentInWikitext();
+
$undoContent = $this->getUndoContent(
- $start->revision->getContent( 'wikitext' ),
- $stop->revision->getContent( 'wikitext' ),
- $current->revision->getContent( 'wikitext' )
+ $start->revision->getContentInWikitext(),
+ $stop->revision->getContentInWikitext(),
+ $currentWikitext
);
$differenceEngine = new DifferenceEngine();
$differenceEngine->setContent(
- new TextContent( $current->revision->getContent( 'wikitext' ) ),
+ new TextContent( $currentWikitext ),
new TextContent( $undoContent )
);
$this->revisionViewFormatter->setContentFormat( 'wikitext' );
// @todo if stop === current we could do a little less processing
- return array(
+ return [
'start' => $this->revisionViewFormatter->formatApi( $start, $context ),
'stop' => $this->revisionViewFormatter->formatApi( $stop, $context ),
'current' => $this->revisionViewFormatter->formatApi( $current, $context ),
- 'undo' => array(
+ 'undo' => [
'possible' => $undoContent !== false,
'content' => $undoContent,
'diff_content' => $differenceEngine->getDiffBody(),
- ),
+ ],
'articleTitle' => $start->workflow->getArticleTitle(),
- );
+ ];
}
protected function getUndoContent( $startContent, $stopContent, $currentContent ) {
-
if ( $currentContent === $stopContent ) {
return $startContent;
} else {
diff --git a/Flow/includes/Formatter/RevisionViewFormatter.php b/Flow/includes/Formatter/RevisionViewFormatter.php
index fa063c73..9004f587 100644
--- a/Flow/includes/Formatter/RevisionViewFormatter.php
+++ b/Flow/includes/Formatter/RevisionViewFormatter.php
@@ -50,6 +50,12 @@ class RevisionViewFormatter {
$row->workflow->getId(),
$ctx
);
+ $res['properties']['topic-of-post-text-from-html'] = $this->serializer->processParam(
+ 'topic-of-post-text-from-html',
+ $row->revision,
+ $row->workflow->getId(),
+ $ctx
+ );
}
if ( $row->revision instanceof PostSummary ) {
$res['properties']['post-of-summary'] = $this->serializer->processParam(
@@ -74,10 +80,10 @@ class RevisionViewFormatter {
$boardTitle = $row->workflow->getOwnerTitle();
$title = $row->workflow->getArticleTitle();
- $links = array(
+ $links = [
'hist' => $this->urlGenerator->boardHistoryLink( $title ),
'board' => $this->urlGenerator->boardLink( $boardTitle ),
- );
+ ];
if ( $row->revision instanceof PostRevision || $row->revision instanceof PostSummary ) {
$links['root'] = $this->urlGenerator->topicLink( $row->workflow->getArticleTitle(), $workflowId );
@@ -118,21 +124,22 @@ class RevisionViewFormatter {
);
$links['diff']->setMessage( wfMessage( 'diff' ) );
} else {
- $links['diff'] = array(
+ $links['diff'] = [
'url' => '',
'title' => ''
- );
+ ];
}
$recentChange = $row->revision->getRecentChange();
if ( $recentChange !== null ) {
$user = $ctx->getUser();
if ( ChangesList::isUnpatrolled( $recentChange, $user ) ) {
+ $token = $user->getEditToken( $recentChange->getAttribute( 'rc_id' ) );
$links['markPatrolled'] = $this->urlGenerator->markRevisionPatrolledAction(
$title,
$workflowId,
$recentChange,
- $user->getEditToken( $recentChange->getAttribute( 'rc_id' ) )
+ $token
);
}
}
diff --git a/Flow/includes/Formatter/RevisionViewQuery.php b/Flow/includes/Formatter/RevisionViewQuery.php
index a6999e08..c32902f6 100644
--- a/Flow/includes/Formatter/RevisionViewQuery.php
+++ b/Flow/includes/Formatter/RevisionViewQuery.php
@@ -4,6 +4,7 @@ namespace Flow\Formatter;
use Flow\Data\ManagerGroup;
use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
use Flow\Exception\PermissionException;
use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
@@ -46,13 +47,13 @@ abstract class RevisionViewQuery extends AbstractQuery {
*/
public function getSingleViewResult( $revId ) {
if ( !$revId ) {
- throw new InvalidInputException( 'Missing revision', 'missing-revision' );
+ throw new InvalidParameterException( 'Missing revision' );
}
$rev = $this->createRevision( $revId );
if ( !$rev ) {
throw new InvalidInputException( 'Could not find revision: ' . $revId, 'missing-revision' );
}
- $this->loadMetadataBatch( array( $rev ) );
+ $this->loadMetadataBatch( [ $rev ] );
return $this->buildResult( $rev, null );
}
@@ -100,12 +101,12 @@ abstract class RevisionViewQuery extends AbstractQuery {
throw new PermissionException( 'Insufficient permission to compare revisions', 'insufficient-permission' );
}
- $this->loadMetadataBatch( array( $oldRev, $newRev ) );
+ $this->loadMetadataBatch( [ $oldRev, $newRev ] );
- return array(
+ return [
$this->buildResult( $newRev, null ),
$this->buildResult( $oldRev, null ),
- );
+ ];
}
public function getUndoDiffResult( $startUndoId, $endUndoId ) {
@@ -133,13 +134,13 @@ abstract class RevisionViewQuery extends AbstractQuery {
throw new PermissionException( 'Insufficient permission to undo revisions', 'insufficient-permission' );
}
- $this->loadMetadataBatch( array( $start, $end, $current ) );
+ $this->loadMetadataBatch( [ $start, $end, $current ] );
- return array(
+ return [
$this->buildResult( $start, null ),
$this->buildResult( $end, null ),
$this->buildResult( $current, null ),
- );
+ ];
}
public function isComparable( AbstractRevision $cur, AbstractRevision $prev ) {
diff --git a/Flow/includes/Formatter/SinglePostQuery.php b/Flow/includes/Formatter/SinglePostQuery.php
index 961a7af8..867427d2 100644
--- a/Flow/includes/Formatter/SinglePostQuery.php
+++ b/Flow/includes/Formatter/SinglePostQuery.php
@@ -14,8 +14,8 @@ class SinglePostQuery extends AbstractQuery {
public function getResult( UUID $postId ) {
$found = $this->storage->find(
'PostRevision',
- array( 'rev_type_id' => $postId ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $postId ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( !$found ) {
throw new FlowException( '@todo' );
@@ -28,8 +28,8 @@ class SinglePostQuery extends AbstractQuery {
if ( $post->isTopicTitle() ) {
$summary = $this->storage->find(
'PostSummary',
- array( 'rev_type_id' => $postId ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $postId ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( $summary ) {
$formatterRow = new TopicRow();
diff --git a/Flow/includes/Formatter/TocTopicListFormatter.php b/Flow/includes/Formatter/TocTopicListFormatter.php
index f8697649..6308c7d6 100644
--- a/Flow/includes/Formatter/TocTopicListFormatter.php
+++ b/Flow/includes/Formatter/TocTopicListFormatter.php
@@ -37,28 +37,28 @@ class TocTopicListFormatter extends BaseTopicListFormatter {
foreach ( $topicRootRevisionsByWorkflowId as $topicId => $postRevision ) {
$result['roots'][] = $topicId;
$revisionId = $postRevision->getRevisionId()->getAlphadecimal();
- $result['posts'][$topicId] = array( $revisionId );
+ $result['posts'][$topicId] = [ $revisionId ];
- $contentFormat = 'plaintext';
+ $contentFormat = 'topic-title-wikitext';
$workflow = $workflowsByWorkflowId[$topicId];
$moderatedRevision = $this->templating->getModeratedRevision( $postRevision );
$moderationData = $moderatedRevision->isModerated() ?
- array(
+ [
'isModerated' => true,
'moderateState' => $moderatedRevision->getModerationState(),
- ) :
- array(
+ ] :
+ [
'isModerated' => false
- );
- $result['revisions'][$revisionId] = array(
+ ];
+ $result['revisions'][$revisionId] = [
// Keep this as a minimal subset of
// RevisionFormatter->formatApi, and keep the same content
// format for topic titles as specified in that class for
// topic titles.
- 'content' => array(
+ 'content' => [
// no need to check permissions before fetching content; that should've
// been done by whatever caller supplies $topicRootRevisionsByWorkflowId,
'content' => $this->templating->getContent(
@@ -66,9 +66,10 @@ class TocTopicListFormatter extends BaseTopicListFormatter {
$contentFormat
),
'format' => $contentFormat,
- ),
+ 'plaintext' => $this->templating->getContent( $postRevision, 'topic-title-plaintext' )
+ ],
'last_updated' => $workflow->getLastUpdatedObj()->getTimestamp() * 1000,
- ) + $moderationData;
+ ] + $moderationData;
}
$pagingOption = $page->getPagingLinksOptions();
diff --git a/Flow/includes/Formatter/TopicFormatter.php b/Flow/includes/Formatter/TopicFormatter.php
index 6ded65da..47c8a65e 100644
--- a/Flow/includes/Formatter/TopicFormatter.php
+++ b/Flow/includes/Formatter/TopicFormatter.php
@@ -28,20 +28,20 @@ class TopicFormatter {
}
public function getEmptyResult( Workflow $workflow ) {
- return array(
+ return [
'workflowId' => $workflow->getId()->getAlphadecimal(),
'type' => 'topic',
- 'roots' => array(),
- 'posts' => array(),
- 'revisions' => array(),
- 'links' => array(),
+ 'roots' => [],
+ 'posts' => [],
+ 'revisions' => [],
+ 'links' => [],
'actions' => $this->buildApiActions( $workflow ),
- );
+ ];
}
public function formatApi( Workflow $listWorkflow, array $found, IContextSource $ctx ) {
- $roots = $revisions = $posts = $replies = array();
- foreach( $found as $formatterRow ) {
+ $roots = $revisions = $posts = $replies = [];
+ foreach ( $found as $formatterRow ) {
$serialized = $this->serializer->formatApi( $formatterRow, $ctx );
if ( !$serialized ) {
continue;
@@ -57,11 +57,11 @@ class TopicFormatter {
foreach ( $revisions as $i => $serialized ) {
$alpha = $serialized['postId'];
- $revisions[$i]['replies'] = isset( $replies[$alpha] ) ? $replies[$alpha] : array();
+ $revisions[$i]['replies'] = isset( $replies[$alpha] ) ? $replies[$alpha] : [];
}
$alpha = $listWorkflow->getId()->getAlphadecimal();
- $workflows = array( $alpha => $listWorkflow );
+ $workflows = [ $alpha => $listWorkflow ];
if ( isset( $posts[$alpha] ) ) {
// Metadata that requires everything to be serialized first
$metadata = $this->generateTopicMetadata( $posts, $revisions, $workflows, $alpha );
@@ -70,20 +70,20 @@ class TopicFormatter {
}
}
- return array(
+ return [
'roots' => $roots,
'posts' => $posts,
'revisions' => $revisions,
- ) + $this->getEmptyResult( $listWorkflow );
+ ] + $this->getEmptyResult( $listWorkflow );
}
protected function buildApiActions( Workflow $workflow ) {
- return array(
- 'newtopic' => array(
+ return [
+ 'newtopic' => [
'url' => $this->urlGenerator
->newTopicAction( $workflow->getArticleTitle(), $workflow->getId() )
- ),
- );
+ ],
+ ];
}
/**
@@ -97,7 +97,7 @@ class TopicFormatter {
*/
protected function generateTopicMetadata( array $posts, array $revisions, array $workflows, $postAlphaId ) {
$replies = -1;
- $authors = array();
+ $authors = [];
$stack = new \SplStack;
$stack->push( $revisions[$posts[$postAlphaId][0]] );
do {
@@ -107,14 +107,14 @@ class TopicFormatter {
foreach ( $data['replies'] as $postId ) {
$stack->push( $revisions[$posts[$postId][0]] );
}
- } while( !$stack->isEmpty() );
+ } while ( !$stack->isEmpty() );
$workflow = isset( $workflows[$postAlphaId] ) ? $workflows[$postAlphaId] : null;
- return array(
+ return [
'reply_count' => $replies,
// ms timestamp
'last_updated' => $workflow ? $workflow->getLastUpdatedObj()->getTimestamp() * 1000 : null,
- );
+ ];
}
}
diff --git a/Flow/includes/Formatter/TopicHistoryQuery.php b/Flow/includes/Formatter/TopicHistoryQuery.php
index b2cd5025..7a0d4a91 100644
--- a/Flow/includes/Formatter/TopicHistoryQuery.php
+++ b/Flow/includes/Formatter/TopicHistoryQuery.php
@@ -2,38 +2,39 @@
namespace Flow\Formatter;
+use Flow\Data\Utils\SortRevisionsByRevisionId;
use Flow\Exception\FlowException;
use Flow\Model\PostRevision;
use Flow\Model\UUID;
-class TopicHistoryQuery extends AbstractQuery {
+class TopicHistoryQuery extends HistoryQuery {
/**
- * @param UUID $postId
+ * @param UUID $topicRootId
* @param int $limit
* @param UUID|null $offset
* @param string $direction 'rev' or 'fwd'
* @return FormatterRow[]
*/
- public function getResults( UUID $postId, $limit = 50, UUID $offset = null, $direction = 'fwd' ) {
- $history = $this->storage->find(
- 'TopicHistoryEntry',
- array( 'topic_root_id' => $postId ),
- array(
- 'sort' => 'rev_id',
- 'order' => 'DESC',
- 'limit' => $limit,
- 'offset-id' => $offset,
- 'offset-dir' => $direction,
- 'offset-include' => false,
- 'offset-elastic' => false,
- )
- );
- if ( !$history ) {
- return array();
+ public function getResults( UUID $topicRootId, $limit = 50, UUID $offset = null, $direction = 'fwd' ) {
+ $options = $this->getOptions( $direction, $limit, $offset );
+
+ $topicPostHistory = $this->getTopicPostResults( $topicRootId, $options ) ?: [];
+ $topicSummaryHistory = $this->getTopicSummaryResults( $topicRootId, $options ) ?: [];
+
+ $history = array_merge( $topicPostHistory, $topicSummaryHistory );
+ usort( $history, new SortRevisionsByRevisionId( $options['order'] ) );
+
+ if ( isset( $options['limit'] ) ) {
+ $history = array_splice( $history, 0, $options['limit'] );
+ }
+
+ // See explanation in BoardHistoryQuery::getResults.
+ if ( $direction === 'rev' ) {
+ $history = array_reverse( $history );
}
$this->loadMetadataBatch( $history );
- $results = $replies = array();
+ $results = $replies = [];
foreach ( $history as $revision ) {
try {
$results[] = $row = new TopicRow;
@@ -54,11 +55,32 @@ class TopicHistoryQuery extends AbstractQuery {
foreach ( $results as $result ) {
if ( $result->revision instanceof PostRevision ) {
$alpha = $result->revision->getPostId()->getAlphadecimal();
- $result->replies = isset( $replies[$alpha] ) ? array_keys( $replies[$alpha] ) : array();
+ $result->replies = isset( $replies[$alpha] ) ? array_keys( $replies[$alpha] ) : [];
}
}
return $results;
}
+ protected function getTopicPostResults( UUID $topicRootId, $options ) {
+ // Can't use 'PostRevision' because we need to get only the ones with the right topic ID.
+ return $this->doInternalQueries(
+ 'PostRevisionTopicHistoryEntry',
+ [
+ 'topic_root_id' => $topicRootId,
+ ],
+ $options,
+ self::POST_OVERFETCH_FACTOR
+ );
+ }
+
+ protected function getTopicSummaryResults( UUID $topicRootId, $options ) {
+ return $this->storage->find(
+ 'PostSummary',
+ [
+ 'rev_type_id' => $topicRootId,
+ ],
+ $options
+ );
+ }
}
diff --git a/Flow/includes/Formatter/TopicListFormatter.php b/Flow/includes/Formatter/TopicListFormatter.php
index 37058fc5..e8a5a0b4 100644
--- a/Flow/includes/Formatter/TopicListFormatter.php
+++ b/Flow/includes/Formatter/TopicListFormatter.php
@@ -30,11 +30,12 @@ class TopicListFormatter extends BaseTopicListFormatter {
public function buildEmptyResult( Workflow $workflow ) {
$title = $workflow->getArticleTitle();
- return array(
+ return [
'workflowId' => $workflow->getId()->getAlphadecimal(),
'title' => $title->getPrefixedText(),
'actions' => $this->buildApiActions( $workflow ),
- ) + parent::buildEmptyResult( $workflow );
+ 'links' => $this->buildLinks( $workflow ),
+ ] + parent::buildEmptyResult( $workflow );
}
public function formatApi(
@@ -51,13 +52,6 @@ class TopicListFormatter extends BaseTopicListFormatter {
$listWorkflow,
$pagingOption
);
- $title = $listWorkflow->getArticleTitle();
- $saveSortBy = true;
- $res['links']['board-sort']['updated'] = $this->urlGenerator->boardLink( $title, 'updated', $saveSortBy )->getLinkURL();
- $res['links']['board-sort']['newest'] = $this->urlGenerator->boardLink( $title, 'newest', $saveSortBy )->getLinkURL();
-
- // Link to designated new-topic page, for no-JS users
- $res['links']['newtopic'] = $this->urlGenerator->newTopicAction( $title, $listWorkflow->getId() )->getLinkURL();
return $res;
}
@@ -72,8 +66,8 @@ class TopicListFormatter extends BaseTopicListFormatter {
* @return array
*/
public function buildResult( array $workflows, array $found, IContextSource $ctx ) {
- $revisions = $posts = $replies = array();
- foreach( $found as $formatterRow ) {
+ $revisions = $posts = $replies = [];
+ foreach ( $found as $formatterRow ) {
$serialized = $this->serializer->formatApi( $formatterRow, $ctx );
if ( !$serialized ) {
continue;
@@ -85,13 +79,13 @@ class TopicListFormatter extends BaseTopicListFormatter {
foreach ( $revisions as $i => $serialized ) {
$alpha = $serialized['postId'];
- $revisions[$i]['replies'] = isset( $replies[$alpha] ) ? $replies[$alpha] : array();
+ $revisions[$i]['replies'] = isset( $replies[$alpha] ) ? $replies[$alpha] : [];
}
- $list = array();
+ $list = [];
if ( $workflows ) {
$orig = $workflows;
- $workflows = array();
+ $workflows = [];
foreach ( $orig as $workflow ) {
$alpha = $workflow->getId()->getAlphadecimal();
if ( isset( $posts[$alpha] ) ) {
@@ -111,18 +105,22 @@ class TopicListFormatter extends BaseTopicListFormatter {
}
}
- return array(
+ return [
// array_values must be used to ensure 0-indexed array
'roots' => $list,
'posts' => $posts,
'revisions' => $revisions,
- );
+ ];
}
protected function buildApiActions( Workflow $workflow ) {
- return array(
- 'newtopic' => $this->urlGenerator->newTopicAction( $workflow->getArticleTitle() ),
- );
+ $actions = [];
+
+ if ( !$workflow->isDeleted() ) {
+ $actions['newtopic'] = $this->urlGenerator->newTopicAction( $workflow->getArticleTitle() );
+ }
+
+ return $actions;
}
protected function generateTopicMetadata( array $posts, array $revisions, array $workflows, $postAlphaId, IContextSource $ctx ) {
@@ -130,7 +128,7 @@ class TopicListFormatter extends BaseTopicListFormatter {
$user = $ctx->getUser();
$replies = -1;
- $authors = array();
+ $authors = [];
$stack = new \SplStack;
$stack->push( $revisions[$posts[$postAlphaId][0]] );
do {
@@ -140,16 +138,32 @@ class TopicListFormatter extends BaseTopicListFormatter {
foreach ( $data['replies'] as $postId ) {
$stack->push( $revisions[$posts[$postId][0]] );
}
- } while( !$stack->isEmpty() );
+ } while ( !$stack->isEmpty() );
/** @var Workflow|null $workflow */
$workflow = isset( $workflows[$postAlphaId] ) ? $workflows[$postAlphaId] : null;
$ts = $workflow ? $workflow->getLastUpdatedObj()->getTimestamp() : 0;
- return array(
+ return [
'reply_count' => $replies,
'last_updated_readable' => $language->userTimeAndDate( $ts, $user ),
// ms timestamp
'last_updated' => $ts * 1000,
- );
+ ];
+ }
+
+ private function buildLinks( Workflow $workflow ) {
+ $links = [];
+
+ if ( !$workflow->isDeleted() ) {
+ $title = $workflow->getArticleTitle();
+ $saveSortBy = true;
+ $links['board-sort']['updated'] = $this->urlGenerator->boardLink( $title, 'updated', $saveSortBy )->getLinkURL();
+ $links['board-sort']['newest'] = $this->urlGenerator->boardLink( $title, 'newest', $saveSortBy )->getLinkURL();
+
+ // Link to designated new-topic page, for no-JS users
+ $links['newtopic'] = $this->urlGenerator->newTopicAction( $title, $workflow->getId() )->getLinkURL();
+ }
+
+ return $links;
}
}
diff --git a/Flow/includes/Formatter/TopicListQuery.php b/Flow/includes/Formatter/TopicListQuery.php
index 7961e045..216ad598 100644
--- a/Flow/includes/Formatter/TopicListQuery.php
+++ b/Flow/includes/Formatter/TopicListQuery.php
@@ -47,8 +47,10 @@ class TopicListQuery extends AbstractQuery {
array_keys( $posts )
);
if ( $missing ) {
- $needed = array();
+ $needed = [];
foreach ( $missing as $alpha ) {
+ wfDebugLog( 'Flow', __METHOD__ . ': Failed to load latest revision for post ID ' . $alpha );
+
// convert alpha back into UUID object
$needed[] = $allPostIds[$alpha];
}
@@ -56,11 +58,11 @@ class TopicListQuery extends AbstractQuery {
}
$this->loadMetadataBatch( $posts );
- $results = array();
- $replies = array();
+ $results = [];
+ $replies = [];
foreach ( $posts as $post ) {
try {
- if ( !$this->permissions->isAllowed( $post, 'view' ) ) {
+ if ( !$this->permissions->isAllowed( $post, 'view' ) ) {
continue;
}
$row = new TopicRow;
@@ -89,7 +91,7 @@ class TopicListQuery extends AbstractQuery {
foreach ( $results as $result ) {
$alpha = $result->revision->getPostId()->getAlphadecimal();
- $result->replies = isset( $replies[$alpha] ) ? $replies[$alpha] : array();
+ $result->replies = isset( $replies[$alpha] ) ? $replies[$alpha] : [];
}
return $results;
@@ -101,7 +103,7 @@ class TopicListQuery extends AbstractQuery {
* @return UUID[]
*/
protected function getTopicIds( array $topicsIdsOrEntries ) {
- $topicIds = array();
+ $topicIds = [];
foreach ( $topicsIdsOrEntries as $entry ) {
if ( $entry instanceof UUID ) {
$topicIds[] = $entry;
@@ -118,7 +120,7 @@ class TopicListQuery extends AbstractQuery {
*/
protected function collectPostIds( array $topicIds ) {
if ( !$topicIds ) {
- return array();
+ return [];
}
// Get the full list of postId's necessary
$nodeList = $this->treeRepository->fetchSubtreeNodeList( $topicIds );
@@ -136,7 +138,12 @@ class TopicListQuery extends AbstractQuery {
// re-index by alphadecimal id
return array_combine(
- array_map( function( UUID $x ) { return $x->getAlphadecimal(); }, $postIds ),
+ array_map(
+ function ( UUID $x ) {
+ return $x->getAlphadecimal();
+ },
+ $postIds
+ ),
$postIds
);
}
@@ -146,7 +153,7 @@ class TopicListQuery extends AbstractQuery {
* @return array
*/
protected function collectWatchStatus( $topicIds ) {
- $ids = array();
+ $ids = [];
foreach ( $topicIds as $topicId ) {
$ids[] = $topicId->getAlphadecimal();
}
@@ -159,18 +166,18 @@ class TopicListQuery extends AbstractQuery {
*/
protected function collectSummary( $topicIds ) {
if ( !$topicIds ) {
- return array();
+ return [];
}
- $conds = array();
+ $conds = [];
foreach ( $topicIds as $topicId ) {
- $conds[] = array( 'rev_type_id' => $topicId );
+ $conds[] = [ 'rev_type_id' => $topicId ];
}
- $found = $this->storage->findMulti( 'PostSummary', $conds, array(
+ $found = $this->storage->findMulti( 'PostSummary', $conds, [
'sort' => 'rev_id',
'order' => 'DESC',
'limit' => 1,
- ) );
- $result = array();
+ ] );
+ $result = [];
foreach ( $found as $row ) {
$summary = reset( $row );
$result[$summary->getSummaryTargetId()->getAlphadecimal()] = $summary;
@@ -183,18 +190,18 @@ class TopicListQuery extends AbstractQuery {
* @return PostRevision[] Indexed by alphadecimal post id
*/
protected function collectRevisions( array $postIds ) {
- $queries = array();
+ $queries = [];
foreach ( $postIds as $postId ) {
- $queries[] = array( 'rev_type_id' => $postId );
+ $queries[] = [ 'rev_type_id' => $postId ];
}
- $found = $this->storage->findMulti( 'PostRevision', $queries, array(
+ $found = $this->storage->findMulti( 'PostRevision', $queries, [
'sort' => 'rev_id',
'order' => 'DESC',
'limit' => 1,
- ) );
+ ] );
// index results by post id for later filtering
- $result = array();
+ $result = [];
foreach ( $found as $row ) {
$revision = reset( $row );
$result[$revision->getPostId()->getAlphadecimal()] = $revision;
@@ -217,7 +224,7 @@ class TopicListQuery extends AbstractQuery {
*/
protected function createFakePosts( array $missing ) {
$parents = $this->treeRepository->fetchParentMap( $missing );
- $posts = array();
+ $posts = [];
foreach ( $missing as $uuid ) {
$alpha = $uuid->getAlphadecimal();
if ( !isset( $parents[$alpha] ) ) {
diff --git a/Flow/includes/Import/ArchiveNameHelper.php b/Flow/includes/Import/ArchiveNameHelper.php
index c0a3088b..85c0af61 100644
--- a/Flow/includes/Import/ArchiveNameHelper.php
+++ b/Flow/includes/Import/ArchiveNameHelper.php
@@ -2,7 +2,6 @@
namespace Flow\Import;
-
use Flow\Repository\TitleRepository;
use Title;
@@ -71,15 +70,15 @@ class ArchiveNameHelper {
return false;
}
- $archivePages = array();
+ $archivePages = [];
for ( $n = 1; $n <= 20; ++$n ) {
$title = Title::newFromText( sprintf( $format, $text, $n ) );
if ( $title && $titleRepo->exists( $title ) ) {
- $archivePages[] = array(
+ $archivePages[] = [
'title' => $title,
'format' => $format,
'counter' => $n
- );
+ ];
} else {
break;
}
@@ -92,4 +91,4 @@ class ArchiveNameHelper {
return false;
}
-} \ No newline at end of file
+}
diff --git a/Flow/includes/Import/Converter.php b/Flow/includes/Import/Converter.php
index 44c8e843..512f9757 100644
--- a/Flow/includes/Import/Converter.php
+++ b/Flow/includes/Import/Converter.php
@@ -3,7 +3,6 @@
namespace Flow\Import;
use DatabaseBase;
-use Flow\Repository\TitleRepository;
use Flow\Exception\FlowException;
use MovePage;
use MWExceptionHandler;
@@ -16,7 +15,7 @@ use WikitextContent;
/**
* Converts provided titles to Flow. This converter is idempotent when
- * used with an appropriate ImportSourceStore, and may be run many times
+ * used with an appropriate SourceStoreInterface, and may be run many times
* without worry for duplicate imports.
*
* Flow does not currently support viewing the history of its page prior
@@ -65,8 +64,7 @@ class Converter {
* @param DatabaseBase $dbw Master wiki database to read from
* @param Importer $importer
* @param LoggerInterface $logger
- * @param User $user Administrative user for moves and edits related
- * to the conversion process.
+ * @param User $user User for moves and edits related to the conversion process
* @param IConversionStrategy $strategy
* @throws ImportException When $user does not have an Id
*/
@@ -185,7 +183,7 @@ class Converter {
}
$source = $this->strategy->createImportSource( $archiveTitle );
- if ( $this->importer->import( $source, $title, $this->strategy->getSourceStore() ) ) {
+ if ( $this->importer->import( $source, $title, $this->user, $this->strategy->getSourceStore() ) ) {
$this->createArchiveCleanupRevision( $title, $archiveTitle );
$this->logger->info( "Completed import to $title from $archiveTitle" );
} else {
@@ -208,19 +206,19 @@ class Converter {
*/
protected function getPageMovedFrom( Title $title ) {
$row = $this->dbw->selectRow(
- array( 'logging', 'page' ),
- array( 'log_namespace', 'log_title', 'log_user' ),
- array(
+ [ 'logging', 'page' ],
+ [ 'log_namespace', 'log_title', 'log_user' ],
+ [
'page_namespace' => $title->getNamespace(),
'page_title' => $title->getDBkey(),
'log_page = page_id',
'log_type' => 'move',
- ),
+ ],
__METHOD__,
- array(
+ [
'LIMIT' => 1,
'ORDER BY' => 'log_timestamp DESC'
- )
+ ]
);
// The page has never been moved
@@ -275,7 +273,7 @@ class Converter {
*/
protected function createArchiveCleanupRevision( Title $title, Title $archiveTitle ) {
$page = WikiPage::factory( $archiveTitle );
- // doEditContent will do this anyway, but we need to now for the revision.
+ // doEditContent will do this anyway, but we need to now for the revision.
$page->loadPageData( 'fromdbmaster' );
$revision = $page->getRevision();
if ( $revision === null ) {
diff --git a/Flow/includes/Import/Exception.php b/Flow/includes/Import/Exception.php
index 00da7678..6a6b4896 100644
--- a/Flow/includes/Import/Exception.php
+++ b/Flow/includes/Import/Exception.php
@@ -1,6 +1,7 @@
<?php
namespace Flow\Import;
+
use Flow\Exception\FlowException;
/**
@@ -8,11 +9,3 @@ use Flow\Exception\FlowException;
*/
class ImportException extends FlowException {
}
-
-/**
- * A failure occurred trying to read or write to the
- * permanant storage backing the ImportSourceStore.
- */
-class ImportSourceStoreException extends ImportException {
-}
-
diff --git a/Flow/includes/Import/IConversionStrategy.php b/Flow/includes/Import/IConversionStrategy.php
index a035a2cd..a5cd7ac1 100644
--- a/Flow/includes/Import/IConversionStrategy.php
+++ b/Flow/includes/Import/IConversionStrategy.php
@@ -2,8 +2,8 @@
namespace Flow\Import;
-use Flow\Import\ImportException;
use Flow\Import\Postprocessor\Postprocessor;
+use Flow\Import\SourceStore\SourceStoreInterface;
use Title;
use WikitextContent;
@@ -13,7 +13,7 @@ use WikitextContent;
*/
interface IConversionStrategy {
/**
- * @return ImportSourceStore This should consistently return the
+ * @return SourceStoreInterface This should consistently return the
* same store between conversion runs from the same source to
* guarantee idempotent imports (without duplicate content).
*/
diff --git a/Flow/includes/Import/ImportSource.php b/Flow/includes/Import/ImportSource.php
index 24a2a73c..9763ced1 100644
--- a/Flow/includes/Import/ImportSource.php
+++ b/Flow/includes/Import/ImportSource.php
@@ -82,4 +82,3 @@ interface IImportHeader extends IRevisionableObject {
interface IImportSummary extends IRevisionableObject {
}
-
diff --git a/Flow/includes/Import/Importer.php b/Flow/includes/Import/Importer.php
index d93a4d80..e1eda671 100644
--- a/Flow/includes/Import/Importer.php
+++ b/Flow/includes/Import/Importer.php
@@ -4,11 +4,12 @@ namespace Flow\Import;
use Article;
use DeferredUpdates;
-use Flow\Data\BufferedCache;
use Flow\Data\ManagerGroup;
use Flow\DbFactory;
use Flow\Import\Postprocessor\Postprocessor;
use Flow\Import\Postprocessor\ProcessorGroup;
+use Flow\Import\SourceStore\SourceStoreInterface as ImportSourceStore;
+use Flow\Import\SourceStore\Exception as ImportSourceStoreException;
use Flow\Model\AbstractRevision;
use Flow\Model\Header;
use Flow\Model\PostRevision;
@@ -18,7 +19,6 @@ use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\OccupationController;
use Flow\WorkflowLoaderFactory;
-use Flow\Container;
use IP;
use MWCryptRand;
use MWTimestamp;
@@ -42,8 +42,6 @@ class Importer {
protected $workflowLoaderFactory;
/** @var LoggerInterface|null */
protected $logger;
- /** @var BufferedCache */
- protected $cache;
/** @var DbFactory */
protected $dbFactory;
/** @var bool */
@@ -58,14 +56,12 @@ class Importer {
public function __construct(
ManagerGroup $storage,
WorkflowLoaderFactory $workflowLoaderFactory,
- BufferedCache $cache,
DbFactory $dbFactory,
SplQueue $deferredQueue,
OccupationController $occupationController
) {
$this->storage = $storage;
$this->workflowLoaderFactory = $workflowLoaderFactory;
- $this->cache = $cache;
$this->dbFactory = $dbFactory;
$this->postprocessors = new ProcessorGroup;
$this->deferredQueue = $deferredQueue;
@@ -105,13 +101,16 @@ class Importer {
/**
* Imports topics from a data source to a given page.
*
- * @param IImportSource $source
- * @param Title $targetPage
+ * @param IImportSource $source
+ * @param Title $targetPage
+ * @param User User doing the conversion actions (e.g. initial description,
+ * wikitext archive edit). However, actions will be attributed to the original
+ * user when possible (e.g. the user who did the original LQT reply)
* @param ImportSourceStore $sourceStore
* @return bool True When the import completes with no failures
*/
- public function import( IImportSource $source, Title $targetPage, ImportSourceStore $sourceStore ) {
- $operation = new TalkpageImportOperation( $source, $this->occupationController );
+ public function import( IImportSource $source, Title $targetPage, User $user, ImportSourceStore $sourceStore ) {
+ $operation = new TalkpageImportOperation( $source, $user, $this->occupationController );
$pageImportState = new PageImportState(
$this->workflowLoaderFactory
->createWorkflowLoader( $targetPage )
@@ -119,7 +118,6 @@ class Importer {
$this->storage,
$sourceStore,
$this->logger ?: new NullLogger,
- $this->cache,
$this->dbFactory,
$this->postprocessors,
$this->deferredQueue,
@@ -142,27 +140,29 @@ class Importer {
*/
class HistoricalUIDGenerator extends UIDGenerator {
public static function historicalTimestampedUID88( $timestamp, $base = 10 ) {
+ $COUNTER_MAX = 1023; // 2^10 - 1
+
static $counter = false;
if ( $counter === false ) {
- $counter = mt_rand( 0, 256 );
+ $counter = mt_rand( 0, $COUNTER_MAX );
}
- $time = array(
+ $time = [
// seconds
wfTimestamp( TS_UNIX, $timestamp ),
// milliseconds
mt_rand( 0, 999 )
- );
+ ];
// The UIDGenerator is implemented very specifically to have
// a single instance, we have to reuse that instance.
$gen = self::singleton();
self::rotateNodeId( $gen );
$binaryUUID = $gen->getTimestampedID88(
- array( $time, ++$counter % 1024 )
+ [ $time, ++$counter % ( $COUNTER_MAX + 1 ) ]
);
- return wfBaseConvert( $binaryUUID, 2, $base );
+ return \Wikimedia\base_convert( $binaryUUID, 2, $base );
}
/**
@@ -175,9 +175,9 @@ class HistoricalUIDGenerator extends UIDGenerator {
*/
protected static function rotateNodeId( UIDGenerator $gen ) {
// 4 bytes = 32 bits
- $gen->nodeId32 = wfBaseConvert( MWCryptRand::generateHex( 8, true ), 16, 2, 32 );
+ $gen->nodeId32 = \Wikimedia\base_convert( MWCryptRand::generateHex( 8, true ), 16, 2, 32 );
// 6 bytes = 48 bits, used for 128bit uid's
- //$gen->nodeId48 = wfBaseConvert( MWCryptRand::generateHex( 12, true ), 16, 2, 48 );
+ // $gen->nodeId48 = \Wikimedia\base_convert( MWCryptRand::generateHex( 12, true ), 16, 2, 48 );
}
}
@@ -237,17 +237,15 @@ class PageImportState {
ManagerGroup $storage,
ImportSourceStore $sourceStore,
LoggerInterface $logger,
- BufferedCache $cache,
DbFactory $dbFactory,
Postprocessor $postprocessor,
SplQueue $deferredQueue,
$allowUnknownUsernames = false
) {
- $this->storage = $storage;;
+ $this->storage = $storage;
$this->boardWorkflow = $boardWorkflow;
$this->sourceStore = $sourceStore;
$this->logger = $logger;
- $this->cache = $cache;
$this->dbw = $dbFactory->getDB( DB_MASTER );
$this->postprocessor = $postprocessor;
$this->deferredQueue = $deferredQueue;
@@ -268,7 +266,7 @@ class PageImportState {
/**
* @param object|object[] $object
- * @param array $metadata
+ * @param array $metadata
*/
public function put( $object, array $metadata ) {
$metadata['imported'] = true;
@@ -285,8 +283,8 @@ class PageImportState {
* WARNING: Before calling this method, ensure that you follow the rule
* given in clearManagerGroup.
*
- * @param string $type Class name to retrieve
- * @param UUID $id ID of the object to retrieve
+ * @param string $type Class name to retrieve
+ * @param UUID $id ID of the object to retrieve
* @return Object|false
*/
public function get( $type, UUID $id ) {
@@ -310,15 +308,15 @@ class PageImportState {
/**
* Gets the top revision of an item by ID
*
- * @param string $type The type of the object to return (e.g. PostRevision).
- * @param UUID $id The ID (e.g. post ID, topic ID, etc)
+ * @param string $type The type of the object to return (e.g. PostRevision).
+ * @param UUID $id The ID (e.g. post ID, topic ID, etc)
* @return object|false The top revision of the requested object, or false if not found.
*/
public function getTopRevision( $type, UUID $id ) {
$result = $this->storage->find(
$type,
- array( 'rev_type_id' => $id ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'rev_type_id' => $id ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
if ( count( $result ) ) {
@@ -338,12 +336,11 @@ class PageImportState {
return UUID::create( HistoricalUIDGenerator::historicalTimestampedUID88( $timestamp ) );
}
-
/**
* Update the id of the workflow to match the provided timestamp
*
* @param Workflow $workflow
- * @param string $timestamp
+ * @param string $timestamp
*/
public function setWorkflowTimestamp( Workflow $workflow, $timestamp ) {
$uid = $this->getTimestampId( $timestamp );
@@ -351,12 +348,11 @@ class PageImportState {
}
/**
- * @var AbstractRevision $summary
- * @var string $timestamp
+ * @param AbstractRevision $revision
+ * @param string $timestamp
*/
public function setRevisionTimestamp( AbstractRevision $revision, $timestamp ) {
$uid = $this->getTimestampId( $timestamp );
- $setRevId = true;
// We don't set the topic title postId as it was inherited from the workflow. We only set the
// postId for first revisions because further revisions inherit it from the parent which was
@@ -365,19 +361,17 @@ class PageImportState {
$this->postIdProperty->setValue( $revision, $uid );
}
- if ( $setRevId ) {
- if ( $revision->getRevisionId()->equals( $revision->getLastContentEditId() ) ) {
- $this->lastEditIdProperty->setValue( $revision, $uid );
- }
- $this->revIdProperty->setValue( $revision, $uid );
+ if ( $revision->getRevisionId()->equals( $revision->getLastContentEditId() ) ) {
+ $this->lastEditIdProperty->setValue( $revision, $uid );
}
+ $this->revIdProperty->setValue( $revision, $uid );
}
/**
* Records an association between a created object and its source.
*
- * @param UUID $objectId UUID representing the object that was created.
- * @param IImportObject $object Output from getObjectKey
+ * @param UUID $objectId UUID representing the object that was created.
+ * @param IImportObject $object Output from getObjectKey
*/
public function recordAssociation( UUID $objectId, IImportObject $object ) {
$this->sourceStore->setAssociation( $objectId, $object->getObjectKey() );
@@ -390,7 +384,7 @@ class PageImportState {
* @return UUID|false
*/
public function getImportedId( IImportObject $object ) {
- return $this->sourceStore->getImportedId( $object->getObjectKey() );
+ return $this->sourceStore->getImportedId( $object );
}
public function createUser( $name ) {
@@ -409,20 +403,17 @@ class PageImportState {
public function begin() {
$this->flushDeferredQueue();
- $this->dbw->begin();
- $this->cache->begin();
+ $this->dbw->begin( __METHOD__ );
}
public function commit() {
- $this->dbw->commit();
- $this->cache->commit();
+ $this->dbw->commit( __METHOD__ );
$this->sourceStore->save();
$this->flushDeferredQueue();
}
public function rollback() {
- $this->dbw->rollback();
- $this->cache->rollback();
+ $this->dbw->rollback( __METHOD__ );
$this->sourceStore->rollback();
$this->clearDeferredQueue();
$this->postprocessor->importAborted();
@@ -430,9 +421,12 @@ class PageImportState {
protected function flushDeferredQueue() {
while ( !$this->deferredQueue->isEmpty() ) {
- DeferredUpdates::addCallableUpdate( $this->deferredQueue->dequeue() );
+ DeferredUpdates::addCallableUpdate(
+ $this->deferredQueue->dequeue(),
+ DeferredUpdates::PRESEND
+ );
+ DeferredUpdates::tryOpportunisticExecute();
}
- DeferredUpdates::doUpdates();
}
protected function clearDeferredQueue() {
@@ -480,11 +474,11 @@ class TopicImportState {
}
public function getMetadata() {
- return array(
+ return [
'workflow' => $this->topicWorkflow,
'board-workflow' => $this->parent->boardWorkflow,
'topic-title' => $this->topicTitle,
- );
+ ];
}
/**
@@ -521,14 +515,24 @@ class TalkpageImportOperation {
*/
protected $importSource;
+ /** @var User User doing the conversion actions (e.g. initial description, wikitext
+ * archive edit). However, actions will be attributed to the original user when
+ * possible (e.g. the user who did the original LQT reply)
+ */
+ protected $user;
+
/** @var OccupationController */
protected $occupationController;
/**
* @param IImportSource $source
+ * @param User $user The import user; this will only be used when there is no
+ * 'original' user
+ * @param OccupationController $occupationController
*/
- public function __construct( IImportSource $source, OccupationController $occupationController ) {
+ public function __construct( IImportSource $source, User $user, OccupationController $occupationController ) {
$this->importSource = $source;
+ $this->user = $user;
$this->occupationController = $occupationController;
}
@@ -545,13 +549,13 @@ class TalkpageImportOperation {
$state->logger->debug( 'Workflow isNew: ' . var_export( $isNew, true ) );
if ( $isNew ) {
// Explicitly allow creation of board
- $allowCreationStatus = $this->occupationController->allowCreation(
+ $creationStatus = $this->occupationController->safeAllowCreation(
$destinationTitle,
- $this->occupationController->getTalkpageManager(),
+ $this->user,
/* $mustNotExist = */ true
);
- if ( !$allowCreationStatus->isGood() ) {
- throw new ImportException( "allowCreation failed to allow the import destination, with the following error:\n" . $allowCreationStatus->getWikiText() );
+ if ( !$creationStatus->isGood() ) {
+ throw new ImportException( "safeAllowCreation failed to allow the import destination, with the following error:\n" . $creationStatus->getWikiText() );
}
// Makes sure the page exists and a Flow-specific revision has been inserted
@@ -570,7 +574,7 @@ class TalkpageImportOperation {
$pageId = $revision->getTitle()->getArticleId( Title::GAID_FOR_UPDATE );
$state->logger->debug( "ensureFlowRevision revision ID: $revisionId, page ID: $pageId" );
- $state->put( $state->boardWorkflow, array() );
+ $state->put( $state->boardWorkflow, [] );
} else {
throw new ImportException( "ensureFlowRevision failed to create the Flow board" );
}
@@ -598,7 +602,7 @@ class TalkpageImportOperation {
$failed++;
}
- foreach( $this->importSource->getTopics() as $topic ) {
+ foreach ( $this->importSource->getTopics() as $topic ) {
try {
// @todo this may be too large of a chunk for one commit, unsure
$state->begin();
@@ -630,17 +634,25 @@ class TalkpageImportOperation {
/**
* @param PageImportState $pageState
- * @param IImportHeader $importHeader
+ * @param IImportHeader $importHeader
*/
public function importHeader( PageImportState $pageState, IImportHeader $importHeader ) {
$pageState->logger->info( 'Importing header' );
- if ( ! $importHeader->getRevisions()->valid() ) {
+ if ( !$importHeader->getRevisions()->valid() ) {
$pageState->logger->info( 'no revisions located for header' );
// No revisions
return;
}
- $existingId = $pageState->getImportedId( $importHeader );
+ /*
+ * We don't need $pageState->getImportedId( $importHeader ) here, there
+ * can only be 1 header per workflow and we already know the workflow,
+ * might as well query it from the workflow instead of using the id from
+ * the source store.
+ * reason I prefer not to use source store is that a header import is
+ * incomplete (it doesn't import full history, just the last revision.
+ */
+ $existingId = $pageState->boardWorkflow->getId();
if ( $existingId && $pageState->getTopRevision( 'Header', $existingId ) ) {
$pageState->logger->info( 'header previously imported' );
return;
@@ -648,7 +660,7 @@ class TalkpageImportOperation {
$revisions = $this->importObjectWithHistory(
$importHeader,
- function( IObjectRevision $rev ) use ( $pageState ) {
+ function ( IObjectRevision $rev ) use ( $pageState ) {
return Header::create(
$pageState->boardWorkflow,
$pageState->createUser( $rev->getAuthor() ),
@@ -662,9 +674,9 @@ class TalkpageImportOperation {
$pageState->boardWorkflow->getArticleTitle()
);
- $pageState->put( $revisions, array(
+ $pageState->put( $revisions, [
'workflow' => $pageState->boardWorkflow,
- ) );
+ ] );
$pageState->recordAssociation(
reset( $revisions )->getCollectionId(),
$importHeader
@@ -675,7 +687,7 @@ class TalkpageImportOperation {
/**
* @param TopicImportState $topicState
- * @param IImportTopic $importTopic
+ * @param IImportTopic $importTopic
*/
public function importTopic( TopicImportState $topicState, IImportTopic $importTopic ) {
$summary = $importTopic->getTopicSummary();
@@ -693,7 +705,7 @@ class TalkpageImportOperation {
/**
* @param PageImportState $state
- * @param IImportTopic $importTopic
+ * @param IImportTopic $importTopic
* @return TopicImportState
*/
protected function getTopicState( PageImportState $state, IImportTopic $importTopic ) {
@@ -715,7 +727,7 @@ class TalkpageImportOperation {
/**
* @param PageImportState $state
- * @param IImportTopic $importTopic
+ * @param IImportTopic $importTopic
* @return TopicImportState
*/
protected function createTopicState( PageImportState $state, IImportTopic $importTopic ) {
@@ -736,12 +748,11 @@ class TalkpageImportOperation {
$titleRevisions = $this->importObjectWithHistory(
$importTopic,
- function( IObjectRevision $rev ) use ( $state, $topicWorkflow ) {
- return PostRevision::create(
+ function ( IObjectRevision $rev ) use ( $state, $topicWorkflow ) {
+ return PostRevision::createTopicPost(
$topicWorkflow,
$state->createUser( $rev->getAuthor() ),
- $rev->getText(),
- 'wikitext'
+ $rev->getText()
);
},
'edit-title',
@@ -770,7 +781,7 @@ class TalkpageImportOperation {
/**
* @param PageImportState $state
- * @param IImportTopic $importTopic
+ * @param IImportTopic $importTopic
* @return TopicImportState|null
*/
protected function getExistingTopicState( PageImportState $state, IImportTopic $importTopic ) {
@@ -788,7 +799,7 @@ class TalkpageImportOperation {
/**
* @param TopicImportState $state
- * @param IImportSummary $importSummary
+ * @param IImportSummary $importSummary
*/
public function importSummary( TopicImportState $state, IImportSummary $importSummary ) {
$state->parent->logger->info( "Importing summary" );
@@ -804,7 +815,7 @@ class TalkpageImportOperation {
$revisions = $this->importObjectWithHistory(
$importSummary,
- function( IObjectRevision $rev ) use ( $state ) {
+ function ( IObjectRevision $rev ) use ( $state ) {
return PostSummary::create(
$state->topicWorkflow->getArticleTitle(),
$state->topicTitle,
@@ -819,9 +830,9 @@ class TalkpageImportOperation {
$state->topicWorkflow->getArticleTitle()
);
- $metadata = array(
+ $metadata = [
'workflow' => $state->topicWorkflow,
- );
+ ];
$state->parent->put( $revisions, $metadata );
$state->parent->recordAssociation(
reset( $revisions )->getCollectionId(), // Summary ID
@@ -834,15 +845,15 @@ class TalkpageImportOperation {
/**
* @param TopicImportState $state
- * @param IImportPost $post
- * @param PostRevision $replyTo
- * @param string $logPrefix
+ * @param IImportPost $post
+ * @param PostRevision $replyTo
+ * @param string $logPrefix
*/
public function importPost(
TopicImportState $state,
IImportPost $post,
PostRevision $replyTo,
- $logPrefix = ' '
+ $logPrefix = ''
) {
$state->parent->logger->info( $logPrefix . "Importing post" );
$postId = $state->parent->getImportedId( $post );
@@ -856,7 +867,7 @@ class TalkpageImportOperation {
} else {
$replyRevisions = $this->importObjectWithHistory(
$post,
- function( IObjectRevision $rev ) use ( $replyTo, $state ) {
+ function ( IObjectRevision $rev ) use ( $replyTo, $state ) {
return $replyTo->reply(
$state->topicWorkflow,
$state->parent->createUser( $rev->getAuthor() ),
@@ -871,12 +882,12 @@ class TalkpageImportOperation {
$topRevision = end( $replyRevisions );
- $metadata = array(
+ $metadata = [
'workflow' => $state->topicWorkflow,
'board-workflow' => $state->parent->boardWorkflow,
'topic-title' => $state->topicTitle,
'reply-to' => $replyTo,
- );
+ ];
$state->parent->put( $replyRevisions, $metadata );
$state->parent->recordAssociation(
@@ -884,7 +895,7 @@ class TalkpageImportOperation {
$post
);
$state->parent->logger->info( $logPrefix . "Finished importing post with " . count( $replyRevisions ) . " revisions" );
- $state->parent->postprocessor->afterPostImported( $state, $post, $topRevision->getPostId() );
+ $state->parent->postprocessor->afterPostImported( $state, $post, $topRevision );
}
$state->recordUpdateTime( $topRevision->getRevisionId() );
@@ -897,11 +908,11 @@ class TalkpageImportOperation {
/**
* Imports an object with all its revisions
*
- * @param IRevisionableObject $object Object to import.
- * @param callable $importFirstRevision Function which, given the appropriate import revision, creates the Flow revision.
- * @param string $editChangeType The Flow change type (from FlowActions.php) for each new operation.
- * @param PageImportState $state State of the import operation.
- * @param Title $title Title content is rendered against
+ * @param IRevisionableObject $object Object to import.
+ * @param callable $importFirstRevision Function which, given the appropriate import revision, creates the Flow revision.
+ * @param string $editChangeType The Flow change type (from FlowActions.php) for each new operation.
+ * @param PageImportState $state State of the import operation.
+ * @param Title $title Title content is rendered against
* @return AbstractRevision[] Objects to insert into the database.
* @throws ImportException
*/
@@ -912,11 +923,11 @@ class TalkpageImportOperation {
PageImportState $state,
Title $title
) {
- $insertObjects = array();
+ $insertObjects = [];
$revisions = $object->getRevisions();
$revisions->rewind();
- if ( ! $revisions->valid() ) {
+ if ( !$revisions->valid() ) {
throw new ImportException( "Attempted to import empty history" );
}
@@ -930,7 +941,7 @@ class TalkpageImportOperation {
$state->recordAssociation( $lastRevision->getCollectionId(), $importRevision );
$revisions->next();
- while( $revisions->valid() ) {
+ while ( $revisions->valid() ) {
$importRevision = $revisions->current();
$insertObjects[] = $lastRevision =
$lastRevision->newNextRevision(
diff --git a/Flow/includes/Import/LiquidThreadsApi/CachedData.php b/Flow/includes/Import/LiquidThreadsApi/CachedData.php
index c7f70b93..5569899e 100644
--- a/Flow/includes/Import/LiquidThreadsApi/CachedData.php
+++ b/Flow/includes/Import/LiquidThreadsApi/CachedData.php
@@ -9,10 +9,10 @@ use Iterator;
* Abstract class to store ID-indexed cached data.
*/
abstract class CachedData {
- protected $data = array();
+ protected $data = [];
public function reset() {
- $this->data = array();
+ $this->data = [];
}
/**
@@ -22,7 +22,7 @@ abstract class CachedData {
* @return mixed The data returned by retrieve()
*/
public function get( $id ) {
- $result = $this->getMulti( array( $id ) );
+ $result = $this->getMulti( [ $id ] );
return reset( $result );
}
@@ -43,8 +43,8 @@ abstract class CachedData {
public function getMulti( array $ids ) {
$this->ensureLoaded( $ids );
- $output = array();
- foreach( $ids as $id ) {
+ $output = [];
+ foreach ( $ids as $id ) {
$output[$id] = isset( $this->data[$id] ) ? $this->data[$id] : null;
}
@@ -104,12 +104,12 @@ abstract class CachedApiData extends CachedData {
* Cached LiquidThreads thread data.
*/
class CachedThreadData extends CachedApiData {
- protected $topics = array();
+ protected $topics = [];
protected function addData( array $data ) {
parent::addData( $data );
- foreach( $data as $thread ) {
+ foreach ( $data as $thread ) {
if ( self::isTopic( $thread ) ) {
$this->topics[$thread['id']] = true;
}
@@ -129,7 +129,7 @@ class CachedThreadData extends CachedApiData {
/**
* Create an iterator for the contained topic ids in ascending order
*
- * @return Iterator<integer>
+ * @return Iterator<int>
*/
public function getTopicIdIterator() {
return new ArrayIterator( $this->getTopics() );
@@ -139,24 +139,24 @@ class CachedThreadData extends CachedApiData {
* Retrieve data for threads from the given page starting with the provided
* offset.
*
- * @param string $pageName
- * @param integer $startId
+ * @param string $pageName
+ * @param int $startId
* @return array Associative result array
*/
public function getFromPage( $pageName, $startId = 0 ) {
- $data = $this->backend->retrieveThreadData( array(
+ $data = $this->backend->retrieveThreadData( [
'thpage' => $pageName,
'thstartid' => $startId
- ) );
+ ] );
$this->addData( $data );
return $data;
}
protected function retrieve( array $ids ) {
- return $this->backend->retrieveThreadData( array(
+ return $this->backend->retrieveThreadData( [
'thid' => implode( '|', $ids ),
- ) );
+ ] );
}
/**
diff --git a/Flow/includes/Import/LiquidThreadsApi/ConversionStrategy.php b/Flow/includes/Import/LiquidThreadsApi/ConversionStrategy.php
index d15cb4e1..a2310fa2 100644
--- a/Flow/includes/Import/LiquidThreadsApi/ConversionStrategy.php
+++ b/Flow/includes/Import/LiquidThreadsApi/ConversionStrategy.php
@@ -4,9 +4,8 @@ namespace Flow\Import\LiquidThreadsApi;
use DatabaseBase;
use Flow\Import\ArchiveNameHelper;
-use Flow\Import\Converter;
use Flow\Import\IConversionStrategy;
-use Flow\Import\ImportSourceStore;
+use Flow\Import\SourceStore\SourceStoreInterface as ImportSourceStore;
use Flow\Import\Postprocessor\ProcessorGroup;
use Flow\Import\Postprocessor\LqtNotifications;
use Flow\Import\Postprocessor\LqtRedirector;
@@ -111,9 +110,9 @@ class ConversionStrategy implements IConversionStrategy {
*/
public function decideArchiveTitle( Title $source ) {
$archiveNameHelper = new ArchiveNameHelper();
- return $archiveNameHelper->decideArchiveTitle( $source, array(
+ return $archiveNameHelper->decideArchiveTitle( $source, [
'%s/LQT Archive %d',
- ) );
+ ] );
}
/**
@@ -126,18 +125,17 @@ class ConversionStrategy implements IConversionStrategy {
* @return WikitextContent
*/
public function createArchiveCleanupRevisionContent( WikitextContent $content, Title $title ) {
- $arguments = implode( '|', array(
- 'from=' . $title->getPrefixedText(),
- 'date=' . MWTimestamp::getInstance()->timestamp->format( 'Y-m-d' ),
- ) );
+ // cleanup existing text
+ $existing = $content->getNativeData();
+ $existing = self::removeLqtMagicWord( $existing );
+ $existing = $this->removePrefixText( $existing );
- $newWikitext = self::removeLqtMagicWord( $content->getNativeData() );
- $newWikitext = self::getDisableLqtMagicWord() . "\n\n" . $newWikitext;
-
- $template = wfMessage( 'flow-importer-lqt-converted-archive-template' )->inContentLanguage()->plain();
- $newWikitext = "{{{$template}|$arguments}}\n\n" . $newWikitext;
+ // prefix the existing text with some additional info related to the conversion
+ $text = $this->getPrefixText( $content, $title ) . "\n\n";
+ $text .= self::getDisableLqtMagicWord() . "\n\n";
+ $text .= $existing;
- return new WikitextContent( $newWikitext );
+ return new WikitextContent( $text );
}
public function getPostprocessor() {
@@ -157,14 +155,49 @@ class ConversionStrategy implements IConversionStrategy {
}
/**
+ * Gets rid of any "This page is an archived page..." prefix that may have
+ * been added in an earlier conversion run.
+ *
+ * @param string $content
+ * @return string
+ */
+ protected function removePrefixText( $content ) {
+ $template = wfMessage( 'flow-importer-lqt-converted-archive-template' )->inContentLanguage()->plain();
+ return preg_replace( "{{{$template}\\|[^\\}]+}}", '', $content );
+ }
+
+ /**
+ * Generates a "This page is an archived page..." text to add to the
+ * existing content.
+ *
+ * @param WikitextContent $content
+ * @param Title $title
+ * @return string
+ */
+ protected function getPrefixText( WikitextContent $content, Title $title ) {
+ $arguments = implode( '|', [
+ 'from=' . $title->getPrefixedText(),
+ 'date=' . MWTimestamp::getInstance()->timestamp->format( 'Y-m-d' ),
+ ] );
+
+ $template = wfMessage( 'flow-importer-lqt-converted-archive-template' )->inContentLanguage()->plain();
+
+ return "{{{$template}|$arguments}}\n\n" . self::getDisableLqtMagicWord() . "\n\n";
+ }
+
+ /**
* Remove the LQT magic word or its localized version
* @param string $content
* @return string
*/
public static function removeLqtMagicWord( $content ) {
$patterns = array_map(
- function( $word ) { return '/{{\\s*#' . preg_quote( $word ) . ':\\s*0*1\\s*}}/i'; },
- array( 'useliquidthreads' ) + MagicWord::get( 'useliquidthreads' )->getSynonyms() );
+ // delete any status: enabled or disabled doesn't matter (we're
+ // adding disabled magic word anyway and having it twice is messy)
+ function ( $word ) {
+ return '/{{\\s*#' . preg_quote( $word ) . ':\\s*[01]*\\s*}}/i';
+ },
+ [ 'useliquidthreads' ] + MagicWord::get( 'useliquidthreads' )->getSynonyms() );
return preg_replace( $patterns, '', $content );
}
diff --git a/Flow/includes/Import/LiquidThreadsApi/Exception.php b/Flow/includes/Import/LiquidThreadsApi/Exception.php
index f5bde977..01c3b7c0 100644
--- a/Flow/includes/Import/LiquidThreadsApi/Exception.php
+++ b/Flow/includes/Import/LiquidThreadsApi/Exception.php
@@ -10,4 +10,3 @@ use Flow\Import\ImportException;
*/
class ApiNotFoundException extends ImportException {
}
-
diff --git a/Flow/includes/Import/LiquidThreadsApi/Iterators.php b/Flow/includes/Import/LiquidThreadsApi/Iterators.php
index 3ed42961..5f4dad55 100644
--- a/Flow/includes/Import/LiquidThreadsApi/Iterators.php
+++ b/Flow/includes/Import/LiquidThreadsApi/Iterators.php
@@ -18,7 +18,7 @@ class TopicIterator implements Iterator {
protected $threadData;
/**
- * @var integer|false|null Lqt id of the current topic, false if no current topic, null if unknown.
+ * @var int|false|null Lqt id of the current topic, false if no current topic, null if unknown.
*/
protected $current = false;
@@ -39,14 +39,14 @@ class TopicIterator implements Iterator {
protected $topicIdIterator;
/**
- * @var integer The maximum id received by self::loadMore
+ * @var int The maximum id received by self::loadMore
*/
protected $maxId;
/**
- * @param ImportSource $source
+ * @param ImportSource $source
* @param CachedThreadData $threadData
- * @param string $pageName
+ * @param string $pageName
*/
public function __construct( ImportSource $source, CachedThreadData $threadData, $pageName ) {
$this->importSource = $source;
@@ -67,7 +67,7 @@ class TopicIterator implements Iterator {
}
/**
- * @return integer
+ * @return int
*/
public function key() {
return $this->current;
@@ -80,7 +80,7 @@ class TopicIterator implements Iterator {
$lastOffset = $this->key();
do {
- while( $this->topicIdIterator->valid() ) {
+ while ( $this->topicIdIterator->valid() ) {
$topicId = $this->topicIdIterator->current();
$this->topicIdIterator->next();
@@ -99,7 +99,7 @@ class TopicIterator implements Iterator {
$this->currentTopic = $topic;
return;
}
- } while( $this->loadMore() );
+ } while ( $this->loadMore() );
// nothing found, nothing more to load
$this->current = false;
@@ -165,14 +165,14 @@ class ReplyIterator implements Iterator {
}
/**
- * @return integer
+ * @return int
*/
public function key() {
return $this->replyIndex;
}
public function next() {
- while( ++$this->replyIndex < count( $this->threadReplies ) ) {
+ while ( ++$this->replyIndex < count( $this->threadReplies ) ) {
try {
$replyId = $this->threadReplies[$this->replyIndex]['id'];
$this->current = $this->post->getSource()->getPost( $replyId );
diff --git a/Flow/includes/Import/LiquidThreadsApi/Objects.php b/Flow/includes/Import/LiquidThreadsApi/Objects.php
index 70862197..7d2bd46b 100644
--- a/Flow/includes/Import/LiquidThreadsApi/Objects.php
+++ b/Flow/includes/Import/LiquidThreadsApi/Objects.php
@@ -2,7 +2,6 @@
namespace Flow\Import\LiquidThreadsApi;
-use ApiResult;
use AppendIterator;
use ArrayIterator;
use Flow\Import\IImportHeader;
@@ -30,7 +29,7 @@ abstract class PageRevisionedObject implements IRevisionableObject {
/**
* @param ImportSource $source
- * @param int $pageId ID of the remote page
+ * @param int $pageId ID of the remote page
*/
function __construct( $source, $pageId ) {
$this->importSource = $source;
@@ -59,7 +58,7 @@ abstract class PageRevisionedObject implements IRevisionableObject {
public function getRevisions() {
$pageData = $this->getRevisionData();
$scriptUser = $this->importSource->getScriptUser();
- return new RevisionIterator( $pageData, $this, function( $data, $parent ) use ( $scriptUser ) {
+ return new RevisionIterator( $pageData, $this, function ( $data, $parent ) use ( $scriptUser ) {
return new ImportRevision( $data, $parent, $scriptUser );
} );
}
@@ -74,7 +73,7 @@ class ImportPost extends PageRevisionedObject implements IImportPost {
/**
* @param ImportSource $source
- * @param array $apiResponse
+ * @param array $apiResponse
*/
public function __construct( ImportSource $source, array $apiResponse ) {
parent::__construct( $source, $apiResponse['rootid'] );
@@ -173,7 +172,7 @@ class ImportPost extends PageRevisionedObject implements IImportPost {
$originalRevisions = parent::getRevisions();
$iterator = new AppendIterator();
$iterator->append( $originalRevisions );
- $iterator->append( new ArrayIterator( array( $signatureRevision ) ) );
+ $iterator->append( new ArrayIterator( [ $signatureRevision ] ) );
return $iterator;
} else {
return parent::getRevisions();
@@ -183,20 +182,20 @@ class ImportPost extends PageRevisionedObject implements IImportPost {
/**
* Creates revision clarifying signature difference
*
- * @param IObjectRevision Last revision prior to the clarification revision
+ * @param IObjectRevision $lastRevision Last revision prior to the clarification revision
* @param string $authorUsername Author username
* @param string $signatureUsername Username extracted from signature
* @return ScriptedImportRevision Generated top import revision
*/
- protected function createSignatureClarificationRevision( IObjectRevision $lastRevision, $authorUsername, $signatureUsername ) {
+ protected function createSignatureClarificationRevision( IObjectRevision $lastRevision, $authorUsername, $signatureUsername ) {
$wikitextForLastRevision = $lastRevision->getText();
$newWikitext = $wikitextForLastRevision;
$templateName = wfMessage( 'flow-importer-lqt-different-author-signature-template' )->inContentLanguage()->plain();
- $arguments = implode( '|', array(
+ $arguments = implode( '|', [
"authorUser=$authorUsername",
"signatureUser=$signatureUsername",
- ) );
+ ] );
$newWikitext .= "\n\n{{{$templateName}|$arguments}}";
$clarificationRevision = new ScriptedImportRevision(
@@ -230,12 +229,12 @@ class ImportTopic extends ImportPost implements IImportTopic, IObjectRevision {
public function getRevisions() {
// we only have access to a single revision of the topic
- return new ArrayIterator( array( $this ) );
+ return new ArrayIterator( [ $this ] );
}
public function getReplies() {
$topPost = new ImportPost( $this->importSource, $this->apiResponse );
- return new ArrayIterator( array( $topPost ) );
+ return new ArrayIterator( [ $topPost ] );
}
public function getTimestamp() {
@@ -260,7 +259,7 @@ class ImportTopic extends ImportPost implements IImportTopic, IObjectRevision {
}
/**
- * @return integer
+ * @return int
*/
protected function getSummaryId() {
return $this->apiResponse['summaryid'];
@@ -279,11 +278,11 @@ class ImportTopic extends ImportPost implements IImportTopic, IObjectRevision {
}
public function getLogParameters() {
- return array(
+ return [
'lqt_thread_id' => $this->apiResponse['id'],
'lqt_orig_title' => $this->getTitle()->getPrefixedText(),
'lqt_subject' => $this->getText(),
- );
+ ];
}
public function getLqtThreadId() {
@@ -296,7 +295,7 @@ class ImportSummary extends PageRevisionedObject implements IImportSummary {
protected $source;
/**
- * @param array $apiResponse
+ * @param array $apiResponse
* @param ImportSource $source
* @throws ImportException
*/
@@ -311,22 +310,22 @@ class ImportSummary extends PageRevisionedObject implements IImportSummary {
class ImportRevision implements IObjectRevision {
/** @var IImportObject **/
- protected $parentObject;
+ protected $parent;
/** @var array **/
protected $apiResponse;
/**
- * @var User Account used when the imported revision is by a supressed user
+ * @var User Account used when the imported revision is by a suppressed user
*/
protected $scriptUser;
/**
* Creates an ImportRevision based on a MW page revision
*
- * @param array $apiResponse An element from api.query.revisions
+ * @param array $apiResponse An element from api.query.revisions
* @param IImportObject $parentObject
- * @param User $user Account used when the imported revision is by a suppressed user
+ * @param User $scriptUser Account used when the imported revision is by a suppressed user
*/
function __construct( array $apiResponse, IImportObject $parentObject, User $scriptUser ) {
$this->apiResponse = $apiResponse;
@@ -374,7 +373,7 @@ class ImportRevision implements IObjectRevision {
class MovedImportTopic extends ImportTopic {
public function getReplies() {
$topPost = new MovedImportPost( $this->importSource, $this->apiResponse );
- return new ArrayIterator( array( $topPost ) );
+ return new ArrayIterator( [ $topPost ] );
}
}
@@ -408,11 +407,11 @@ class MovedImportRevision extends ImportRevision {
// To get the new talk page that this belongs to we would need to query the api
// for the new topic, for now not bothering.
$template = wfMessage( 'flow-importer-lqt-moved-thread-template' )->inContentLanguage()->plain();
- $arguments = implode( '|', array(
+ $arguments = implode( '|', [
'author=' . parent::getAuthor(),
'date=' . MWTimestamp::getInstance( $this->apiResponse['timestamp'] )->timestamp->format( 'Y-m-d' ),
'title=' . $target->getPrefixedText(),
- ) );
+ ] );
return "{{{$template}|$arguments}}";
}
@@ -421,7 +420,7 @@ class MovedImportRevision extends ImportRevision {
// Represents a revision the script makes on its own behalf, using a script user
class ScriptedImportRevision implements IObjectRevision {
/** @var IImportObject **/
- protected $parentObject;
+ protected $parent;
/** @var User */
protected $destinationScriptUser;
@@ -494,11 +493,11 @@ class ImportHeader extends PageRevisionedObject implements IImportHeader {
if ( $this->pageData === null ) {
// Previous revisions of the header are preserved in the underlying wikitext
// page history. Only the top revision is imported.
- $response = $this->api->retrieveTopRevisionByTitle( array( $this->title ) );
+ $response = $this->api->retrieveTopRevisionByTitle( [ $this->title ] );
$this->pageData = reset( $response );
}
- $revisions = array();
+ $revisions = [];
if ( isset( $this->pageData['revisions'] ) && count( $this->pageData['revisions'] ) > 0 ) {
$lastLqtRevision = new ImportRevision(
@@ -510,7 +509,7 @@ class ImportHeader extends PageRevisionedObject implements IImportHeader {
$titleObject = Title::newFromText( $this->title );
$cleanupRevision = $this->createHeaderCleanupRevision( $lastLqtRevision, $titleObject );
- $revisions = array( $lastLqtRevision, $cleanupRevision );
+ $revisions = [ $lastLqtRevision, $cleanupRevision ];
}
return new ArrayIterator( $revisions );
@@ -528,10 +527,10 @@ class ImportHeader extends PageRevisionedObject implements IImportHeader {
// matter.
$newWikitext = ConversionStrategy::removeLqtMagicWord( $wikitextForLastRevision );
$templateName = wfMessage( 'flow-importer-lqt-converted-template' )->inContentLanguage()->plain();
- $arguments = implode( '|', array(
+ $arguments = implode( '|', [
'archive=' . $archiveTitle->getPrefixedText(),
'date=' . MWTimestamp::getInstance()->timestamp->format( 'Y-m-d' ),
- ) );
+ ] );
$newWikitext .= "\n\n{{{$templateName}|$arguments}}";
diff --git a/Flow/includes/Import/LiquidThreadsApi/Source.php b/Flow/includes/Import/LiquidThreadsApi/Source.php
index 53e7b401..330d7c2e 100644
--- a/Flow/includes/Import/LiquidThreadsApi/Source.php
+++ b/Flow/includes/Import/LiquidThreadsApi/Source.php
@@ -3,17 +3,19 @@
namespace Flow\Import\LiquidThreadsApi;
use ApiBase;
+use ApiErrorFormatter;
use ApiMain;
+use ApiMessage;
use Exception;
use FauxRequest;
use Flow\Import\ImportException;
use Flow\Import\IImportSource;
-use Flow\Import\ApiNullResponseException;
use Http;
use RequestContext;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
+use ApiUsageException;
use UsageException;
use User;
@@ -93,7 +95,7 @@ class ImportSource implements IImportSource {
}
/**
- * @param integer $id
+ * @param int $id
* @return ImportTopic|null
*/
public function getTopic( $id ) {
@@ -132,7 +134,7 @@ class ImportSource implements IImportSource {
}
/**
- * @param integer $id
+ * @param int $id
* @return ImportPost
*/
public function getPost( $id ) {
@@ -140,7 +142,7 @@ class ImportSource implements IImportSource {
}
/**
- * @param integer $id
+ * @param int $id
* @return array
*/
public function getThreadData( $id ) {
@@ -152,7 +154,7 @@ class ImportSource implements IImportSource {
}
/**
- * @param integer[]|integer $pageIds
+ * @param int[]|int $pageIds
* @return array
*/
public function getPageData( $pageIds ) {
@@ -165,7 +167,7 @@ class ImportSource implements IImportSource {
/**
* @param string $pageName
- * @param integer $startId
+ * @param int $startId
* @return array
*/
public function getFromPage( $pageName, $startId = 0 ) {
@@ -189,7 +191,7 @@ class ImportSource implements IImportSource {
*/
public function getObjectKey( /* $args */ ) {
$components = array_merge(
- array( 'lqt-api', $this->getApiKey() ),
+ [ 'lqt-api', $this->getApiKey() ],
func_get_args()
);
@@ -215,7 +217,7 @@ abstract class ApiBackend implements LoggerAwareInterface {
/**
* Retrieves LiquidThreads data from the API
*
- * @param array $conditions The parameters to pass to select the threads. Usually used in two ways: with thstartid/thpage, or with ththreadid
+ * @param array $conditions The parameters to pass to select the threads. Usually used in two ways: with thstartid/thpage, or with ththreadid
* @return array Data as returned under query.threads by the API
* @throws ApiNotFoundException Thrown when the remote api reports that the provided conditions
* have no matching records.
@@ -223,17 +225,17 @@ abstract class ApiBackend implements LoggerAwareInterface {
* a bad request or lqt threw an exception trying to respond to a valid request.
*/
public function retrieveThreadData( array $conditions ) {
- $params = array(
+ $params = [
'action' => 'query',
'list' => 'threads',
'thprop' => 'id|subject|page|parent|ancestor|created|modified|author|summaryid|type|rootid|replies|signature',
'rawcontinue' => 1, // We're doing continuation a different way, but this avoids a warning.
'format' => 'json',
'limit' => ApiBase::LIMIT_BIG1,
- );
+ ];
$data = $this->apiCall( $params + $conditions );
- if ( ! isset( $data['query']['threads'] ) ) {
+ if ( !isset( $data['query']['threads'] ) ) {
if ( $this->isNotFoundError( $data ) ) {
$message = "Did not find thread with conditions: " . json_encode( $conditions );
$this->logger->debug( __METHOD__ . ": $message" );
@@ -245,7 +247,7 @@ abstract class ApiBackend implements LoggerAwareInterface {
}
$firstThread = reset( $data['query']['threads'] );
- if ( ! isset( $firstThread['replies'] ) ) {
+ if ( !isset( $firstThread['replies'] ) ) {
throw new ImportException( "Foreign API does not support reply exporting:" . json_encode( $data ) );
}
@@ -255,7 +257,7 @@ abstract class ApiBackend implements LoggerAwareInterface {
/**
* Retrieves data about a set of pages from the API
*
- * @param array $pageIds Page IDs to return data for.
+ * @param array $pageIds Page IDs to return data for.
* @return array The query.pages part of the API response.
* @throws \MWException
*/
@@ -264,9 +266,9 @@ abstract class ApiBackend implements LoggerAwareInterface {
throw new \MWException( 'At least one page id must be provided' );
}
- return $this->retrievePageData( array(
+ return $this->retrievePageData( [
'pageids' => implode( '|', $pageIds ),
- ) );
+ ] );
}
/**
@@ -283,18 +285,18 @@ abstract class ApiBackend implements LoggerAwareInterface {
throw new \MWException( 'At least one title must be provided' );
}
- return $this->retrievePageData( array(
+ return $this->retrievePageData( [
'titles' => implode( '|', $titles ),
'rvlimit' => 1,
'rvdir' => 'older',
- ), true );
+ ], true );
}
/**
* Retrieves data about a set of pages from the API
*
- * @param array $conditions Conditions to retrieve pages by; to be sent to the API.
- * @param bool $expectContinue Pass true here when caller expects more revisions to exist than
+ * @param array $conditions Conditions to retrieve pages by; to be sent to the API.
+ * @param bool $expectContinue Pass true here when caller expects more revisions to exist than they are requesting information about.
* they are requesting information about.
* @return array The query.pages part of the API response.
* @throws ApiNotFoundException Thrown when the remote api reports that the provided conditions
@@ -305,7 +307,7 @@ abstract class ApiBackend implements LoggerAwareInterface {
* query and the calling code does not set $expectContinue to true.
*/
public function retrievePageData( array $conditions, $expectContinue = false ) {
- $conditions += array(
+ $conditions += [
'action' => 'query',
'prop' => 'revisions',
'rvprop' => 'timestamp|user|content|ids',
@@ -313,16 +315,16 @@ abstract class ApiBackend implements LoggerAwareInterface {
'rvlimit' => 5000,
'rvdir' => 'newer',
'continue' => '',
- );
+ ];
$data = $this->apiCall( $conditions );
- if ( ! isset( $data['query'] ) ) {
- $this->logger->error( __METHOD__ . ': Failed API call against ' . $this->getKey() . ' with conditions : ' . json_encode( $conditions ) );
+ if ( !isset( $data['query'] ) ) {
if ( $this->isNotFoundError( $data ) ) {
$message = "Did not find pages: " . json_encode( $conditions );
$this->logger->debug( __METHOD__ . ": $message" );
throw new ApiNotFoundException( $message );
} else {
+ $this->logger->error( __METHOD__ . ': Failed API call against ' . $this->getKey() . ' with conditions : ' . json_encode( $conditions ) );
throw new ImportException( "Null response from API module: " . json_encode( $data ) );
}
} elseif ( !$expectContinue && isset( $data['continue'] ) ) {
@@ -336,7 +338,7 @@ abstract class ApiBackend implements LoggerAwareInterface {
* Calls the remote API
*
* @param array $params The API request to send
- * @param int $retry Retry the request on failure this many times
+ * @param int $retry Retry the request on failure this many times
* @return array API return value, decoded from JSON into an array.
*/
abstract function apiCall( array $params, $retry = 1 );
@@ -429,18 +431,36 @@ class LocalApiBackend extends ApiBackend {
$api = new ApiMain( $context );
$api->execute();
- return $api->getResult()->getResultData( null, array( 'Strip' => 'all' ) );
+ return $api->getResult()->getResultData( null, [ 'Strip' => 'all' ] );
+ } catch ( ApiUsageException $exception ) {
+ // Mimic the behaviour when called remotely
+ $errors = $exception->getStatusValue()->getErrorsByType( 'error' );
+ if ( !$errors ) {
+ $errors = $exception->getStatusValue()->getErrorsByType( 'warning' );
+ }
+ if ( !$errors ) {
+ $errors = [ [ 'message' => 'unknownerror-nocode', 'params' => [] ] ];
+ }
+ $msg = ApiMessage::create( $errors[0] );
+ return [
+ 'error' => [
+ 'code' => $msg->getApiCode(),
+ 'info' => ApiErrorFormatter::stripMarkup(
+ $msg->inLanguage( 'en' )->useDatabase( 'false' )->text()
+ ),
+ ] + $msg->getApiData()
+ ];
} catch ( UsageException $exception ) {
// Mimic the behaviour when called remotely
- return array( 'error' => $exception->getMessageArray() );
+ return [ 'error' => $exception->getMessageArray() ];
} catch ( Exception $exception ) {
// Mimic behaviour when called remotely
- return array(
- 'error' => array(
+ return [
+ 'error' => [
'code' => 'internal_api_error_' . get_class( $exception ),
'info' => 'Exception Caught: ' . $exception->getMessage(),
- ),
- );
+ ],
+ ];
}
}
}
diff --git a/Flow/includes/Import/OptInController.php b/Flow/includes/Import/OptInController.php
index d979c70f..c7c430e1 100644
--- a/Flow/includes/Import/OptInController.php
+++ b/Flow/includes/Import/OptInController.php
@@ -10,12 +10,13 @@ use Flow\Content\BoardContent;
use Flow\Exception\InvalidDataException;
use Flow\NotificationController;
use Flow\OccupationController;
-use Flow\Parsoid\Utils;
-use Flow\RevisionActionPermissions;
+use Flow\Conversion\Utils;
use Flow\WorkflowLoader;
use Flow\WorkflowLoaderFactory;
use IContextSource;
use MovePage;
+use Parser;
+use ParserOptions;
use RequestContext;
use Revision;
use Title;
@@ -74,19 +75,20 @@ class OptInController {
}
// archive existing wikitext talk page
- $linkToArchivedTalkpage = null;
+ $currentTemplate = null;
+ $templatesFromTalkpage = null;
if ( $title->exists( Title::GAID_FOR_UPDATE ) ) {
+ $templatesFromTalkpage = $this->extractTemplatesAboveFirstSection( $title );
$wikitextTalkpageArchiveTitle = $this->archiveExistingTalkpage( $title );
- $this->addArchiveTemplate( $wikitextTalkpageArchiveTitle, $title );
- $linkToArchivedTalkpage = $this->buildLinkToArchivedTalkpage( $wikitextTalkpageArchiveTitle );
+ $currentTemplate = $this->getFormattedCurrentTemplate( $wikitextTalkpageArchiveTitle );
}
// create or restore flow board
$archivedFlowPage = $this->findLatestFlowArchive( $title );
if ( $archivedFlowPage ) {
- $this->restoreExistingFlowBoard( $archivedFlowPage, $title, $linkToArchivedTalkpage );
+ $this->restoreExistingFlowBoard( $archivedFlowPage, $title, $currentTemplate );
} else {
- $this->createFlowBoard( $title, $linkToArchivedTalkpage );
+ $this->createFlowBoard( $title, $templatesFromTalkpage . "\n\n" . $currentTemplate );
$this->notificationController->notifyFlowEnabledOnTalkpage( $user );
}
}
@@ -100,22 +102,23 @@ class OptInController {
}
// archive the flow board
- $flowArchiveTitle = $this->findNextFlowArchive( $title );
- $this->movePage( $title, $flowArchiveTitle );
- $this->removeArchivedTalkpageTemplateFromFlowBoardDescription( $flowArchiveTitle );
+ $flowArchiveTitle = $this->archiveFlowBoard( $title );
// restore the original wikitext talk page
$archivedTalkpage = $this->findLatestArchive( $title );
if ( $archivedTalkpage ) {
- $this->movePage( $archivedTalkpage, $title );
- $this->removeArchiveTemplateFromWikitextTalkpage( $title );
+ $this->removeArchiveTemplateFromWikitextTalkpage( $archivedTalkpage );
+ $this->addCurrentTemplate( $archivedTalkpage, $flowArchiveTitle );
+ $restoreReason = wfMessage( 'flow-optin-restore-wikitext' )->inContentLanguage()->text();
+ $this->movePage( $archivedTalkpage, $title, $restoreReason );
}
}
/**
* Check whether the current user has a flow board archived already.
*
- * @return boolean Flow board archive exists
+ * @param User $user
+ * @return bool Flow board archive exists
*/
public function hasFlowBoardArchive( User $user ) {
return $this->findLatestFlowArchive( $user->getTalkPage() ) !== false;
@@ -132,10 +135,11 @@ class OptInController {
/**
* @param Title $from
* @param Title $to
+ * @param string $reason
*/
- private function movePage( Title $from, Title &$to ) {
+ private function movePage( Title $from, Title $to, $reason = '' ) {
$mp = new MovePage( $from, $to );
- $mp->move( $this->user, null, false );
+ $mp->move( $this->user, $reason, false );
/*
* Article IDs are cached inside title objects. Since we'll be
@@ -154,14 +158,10 @@ class OptInController {
$linkCache->addBadLinkObj( $from );
/*
- * WikiPage::updateRevisionOn (called form MovePage::moveToInternal)
- * updates LinkCache for $to. We're still stuck with the $to object,
- * which has cached the article ID.
- * We've accepted $to by-ref, so we'll just overwrite the object
- * with one that's unaware of its article ID, so it'll go look in
- * LinkCache once requested.
+ * Force id cached inside $title to be updated, as well as info
+ * inside LinkCache.
*/
- $to = Title::newFromDBkey( $to->getPrefixedDBkey() );
+ $to->getArticleID( Title::GAID_FOR_UPDATE );
}
/**
@@ -169,7 +169,7 @@ class OptInController {
* @param array $args
* @throws ImportException
*/
- private function fatal( $msgKey, $args = array() ) {
+ private function fatal( $msgKey, $args = [] ) {
throw new ImportException( wfMessage( $msgKey, $args )->inContentLanguage()->text() );
}
@@ -258,8 +258,8 @@ class OptInController {
$loaderFactory = Container::get( 'factory.loader.workflow' );
$page = $title->getPrefixedText();
- $allowCreationStatus = $this->occupationController->allowCreation( $title, $this->user, false );
- if ( !$allowCreationStatus->isGood() ) {
+ $creationStatus = $this->occupationController->safeAllowCreation( $title, $this->user, false );
+ if ( !$creationStatus->isGood() ) {
$this->fatal( 'flow-special-enableflow-board-creation-not-allowed', $page );
}
@@ -271,12 +271,12 @@ class OptInController {
}
$action = 'edit-header';
- $params = array(
- 'header' => array(
+ $params = [
+ 'header' => [
'content' => $boardDescription,
'format' => 'wikitext',
- ),
- );
+ ],
+ ];
$blocksToCommit = $loader->handleSubmit(
$this->context,
@@ -303,23 +303,44 @@ class OptInController {
*/
private function archiveExistingTalkpage( Title $title ) {
$archiveTitle = $this->findNextArchive( $title );
- $this->movePage( $title, $archiveTitle );
+ $archiveReason = wfMessage( 'flow-optin-archive-wikitext' )->inContentLanguage()->text();
+ $this->movePage( $title, $archiveTitle, $archiveReason );
+
+ $content = $this->getContent( $archiveTitle );
+ $content = $this->removeCurrentTemplateFromWikitext( $content, $archiveTitle );
+ $content = $this->getFormattedArchiveTemplate( $title ) . "\n\n" . $content;
+
+ $addTemplateReason = wfMessage( 'flow-beta-feature-add-archive-template-edit-summary' )->inContentLanguage()->plain();
+ $this->createRevision(
+ $archiveTitle,
+ $content,
+ $addTemplateReason
+ );
+
return $archiveTitle;
}
/**
* @param Title $archivedFlowPage
* @param Title $title
- * @param string|null $addToHeader
+ * @param string|null $currentTemplate
*/
- private function restoreExistingFlowBoard( Title $archivedFlowPage, Title $title, $addToHeader = null ) {
- $this->movePage( $archivedFlowPage, $title );
+ private function restoreExistingFlowBoard( Title $archivedFlowPage, Title $title, $currentTemplate = null ) {
+ $this->editBoardDescription(
+ $archivedFlowPage,
+ function ( $content ) use ( $currentTemplate, $archivedFlowPage ) {
+ $templateName = wfMessage( 'flow-importer-wt-converted-archive-template' )->inContentLanguage()->plain();
+ $content = TemplateHelper::removeFromHtml( $content, $templateName );
+ if ( $currentTemplate ) {
+ $content = Utils::convert( 'wikitext', 'html', $currentTemplate, $archivedFlowPage ) . "<br/><br/>" . $content;
+ }
+ return $content;
+ },
+ 'html'
+ );
- if ( $addToHeader ) {
- $this->editBoardDescription( $title, function( $oldDesc ) use ( $addToHeader ) {
- return $oldDesc . "\n\n" . $addToHeader;
- }, 'wikitext' );
- }
+ $restoreReason = wfMessage( 'flow-optin-restore-flow-board' )->inContentLanguage()->text();
+ $this->movePage( $archivedFlowPage, $title, $restoreReason );
}
/**
@@ -345,12 +366,12 @@ class OptInController {
* @param Title $archiveTitle
* @return string
*/
- private function buildLinkToArchivedTalkpage( Title $archiveTitle ) {
+ private function getFormattedCurrentTemplate( Title $archiveTitle ) {
$now = new DateTime( "now", new DateTimeZone( "GMT" ) );
- $arguments = array(
+ $arguments = [
'archive' => $archiveTitle->getPrefixedText(),
'date' => $now->format( 'Y-m-d' ),
- );
+ ];
$template = wfMessage( 'flow-importer-wt-converted-template' )->inContentLanguage()->plain();
return $this->formatTemplate( $template, $arguments );
}
@@ -363,7 +384,7 @@ class OptInController {
private function formatTemplate( $name, $args ) {
$arguments = implode( '|',
array_map(
- function( $key, $value ) {
+ function ( $key, $value ) {
return "$key=$value";
},
array_keys( $args ),
@@ -373,16 +394,6 @@ class OptInController {
}
/**
- * @param Title $flowArchiveTitle
- */
- private function removeArchivedTalkpageTemplateFromFlowBoardDescription( Title $flowArchiveTitle ) {
- $this->editBoardDescription( $flowArchiveTitle, function( $oldDesc ) {
- $templateName = wfMessage( 'flow-importer-wt-converted-template' )->inContentLanguage()->plain();
- return TemplateHelper::removeFromHtml( $oldDesc, $templateName );
- }, 'html' );
- }
-
- /**
* @param Title $title
* @param callable $newDescriptionCallback
* @param string $format
@@ -398,11 +409,20 @@ class OptInController {
* need to read from master here.
* We'll need WorkflowLoader further down anyway, but we'll
* then have the correct workflow ID to initialize it with!
+ *
+ * $title->getLatestRevId() should be fine, it'll be read from
+ * LinkCache, which has been updated.
+ * Revision::newFromId will try slave first. If it can't find
+ * the id, it'll try to find it on master.
*/
- $page = WikiPage::newFromID( $title->getArticleID(), WikiPage::READ_LATEST );
- $content = $page->getContent();
+ $revId = $title->getLatestRevID();
+ $revision = Revision::newFromId( $revId );
+ $content = $revision->getContent();
if ( !$content instanceof BoardContent ) {
- throw new InvalidDataException( 'Could not find board page for ' . $title->getPrefixedDBkey() );
+ throw new InvalidDataException(
+ 'Could not find board page for ' . $title->getPrefixedDBkey() . ' (id: ' . $title->getArticleID() . ').' .
+ 'Found content: ' . var_export( $content, true )
+ );
}
$workflowId = $content->getWorkflowId();
@@ -422,13 +442,13 @@ class OptInController {
$newDescription = call_user_func( $newDescriptionCallback, $content );
$action = 'edit-header';
- $params = array(
- 'header' => array(
+ $params = [
+ 'header' => [
'content' => $newDescription,
'format' => $format,
'prev_revision' => $revision->getRevisionId()->getAlphadecimal()
- ),
- );
+ ],
+ ];
/** @var WorkflowLoaderFactory $factory */
$factory = Container::get( 'factory.loader.workflow' );
@@ -458,24 +478,16 @@ class OptInController {
}
/**
- * @param Title $archive
* @param Title $current
- * @throws ImportException
+ * @return string
*/
- private function addArchiveTemplate( Title $archive, Title $current ) {
+ private function getFormattedArchiveTemplate( Title $current ) {
$templateName = wfMessage( 'flow-importer-wt-converted-archive-template' )->inContentLanguage()->plain();
$now = new DateTime( "now", new DateTimeZone( "GMT" ) );
- $template = $this->formatTemplate( $templateName, array(
+ return $this->formatTemplate( $templateName, [
'from' => $current->getPrefixedText(),
'date' => $now->format( 'Y-m-d' ),
- ) );
-
- $content = $this->getContent( $archive );
-
- $this->createRevision(
- $archive,
- $template . "\n\n" . $content,
- wfMessage( 'flow-beta-feature-add-archive-template-edit-summary' )->inContentLanguage()->plain());
+ ] );
}
/**
@@ -496,7 +508,99 @@ class OptInController {
$this->createRevision(
$title,
Utils::convert( 'html', 'wikitext', $newContent, $title ),
- wfMessage( 'flow-beta-feature-remove-archive-template-edit-summary' )->inContentLanguage()->plain());
+ wfMessage( 'flow-beta-feature-remove-archive-template-edit-summary' )->inContentLanguage()->plain() );
+ }
+
+ /**
+ * @param string $wikitextContent
+ * @param Title $title
+ * @return string
+ */
+ private function removeCurrentTemplateFromWikitext( $wikitextContent, Title $title ) {
+ $templateName = wfMessage( 'flow-importer-wt-converted-template' )->inContentLanguage()->plain();
+ $contentAsHtml = Utils::convert( 'wikitext', 'html', $wikitextContent, $title );
+ $contentWithoutTemplate = TemplateHelper::removeFromHtml( $contentAsHtml, $templateName );
+ return Utils::convert( 'html', 'wikitext', $contentWithoutTemplate, $title );
}
+ /**
+ * @param Title $title
+ * @return string
+ */
+ private function extractTemplatesAboveFirstSection( Title $title ) {
+ $content = $this->getContent( $title );
+ if ( !$content ) {
+ return '';
+ }
+
+ $parser = new Parser();
+ $output = $parser->parse( $content, $title, new ParserOptions );
+ $sections = $output->getSections();
+ if ( $sections ) {
+ $content = substr( $content, 0, $sections[0]['byteoffset'] );
+ }
+ return TemplateHelper::extractTemplates( $content, $title );
+ }
+
+ /**
+ * @param Title $title
+ * @param $reason
+ * @param callable $newDescriptionCallback
+ * @param string $format
+ * @throws ImportException
+ * @throws InvalidDataException
+ */
+ private function editWikitextContent( Title $title, $reason, callable $newDescriptionCallback, $format = 'html' ) {
+ $content = Utils::convert( 'wikitext', $format, $this->getContent( $title ), $title );
+ $newContent = call_user_func( $newDescriptionCallback, $content );
+ $this->createRevision(
+ $title,
+ Utils::convert( $format, 'wikitext', $newContent, $title ),
+ $reason
+ );
+ }
+
+ /**
+ * Add the "current" template to the page considered the current talkpage
+ * and link to the archived talkpage.
+ *
+ * @param Title $currentTalkpageTitle
+ * @param Title $archivedTalkpageTitle
+ */
+ private function addCurrentTemplate( Title $currentTalkpageTitle, Title $archivedTalkpageTitle ) {
+ $template = $this->getFormattedCurrentTemplate( $archivedTalkpageTitle );
+ $this->editWikitextContent(
+ $currentTalkpageTitle,
+ null,
+ function ( $content ) use ( $template ) {
+ return $template . "\n\n" . $content;
+ },
+ 'wikitext'
+ );
+ }
+
+ /**
+ * @param Title $title
+ * @return Title
+ * @throws InvalidDataException
+ */
+ private function archiveFlowBoard( Title $title ) {
+ $flowArchiveTitle = $this->findNextFlowArchive( $title );
+ $archiveReason = wfMessage( 'flow-optin-archive-flow-board' )->inContentLanguage()->text();
+ $this->movePage( $title, $flowArchiveTitle, $archiveReason );
+
+ $template = $this->getFormattedArchiveTemplate( $title );
+ $template = Utils::convert( 'wikitext', 'html', $template, $title );
+
+ $this->editBoardDescription(
+ $flowArchiveTitle,
+ function ( $content ) use ( $template ) {
+ $templateName = wfMessage( 'flow-importer-wt-converted-template' )->inContentLanguage()->plain();
+ $content = TemplateHelper::removeFromHtml( $content, $templateName );
+ return $template . "<br/><br/>" . $content;
+ },
+ 'html' );
+
+ return $flowArchiveTitle;
+ }
}
diff --git a/Flow/includes/Import/OptInUpdate.php b/Flow/includes/Import/OptInUpdate.php
index c5e6f27f..3c1a0f7d 100644
--- a/Flow/includes/Import/OptInUpdate.php
+++ b/Flow/includes/Import/OptInUpdate.php
@@ -56,4 +56,3 @@ class OptInUpdate implements DeferrableUpdate {
}
}
}
-
diff --git a/Flow/includes/Import/Postprocessor/LqtNotifications.php b/Flow/includes/Import/Postprocessor/LqtNotifications.php
index 05c10145..e57c87f2 100644
--- a/Flow/includes/Import/Postprocessor/LqtNotifications.php
+++ b/Flow/includes/Import/Postprocessor/LqtNotifications.php
@@ -3,7 +3,7 @@
namespace Flow\Import\Postprocessor;
use DatabaseBase;
-use EchoBatchRowIterator;
+use BatchRowIterator;
use EchoCallbackIterator;
use EchoEvent;
use Flow\Import\IImportHeader;
@@ -13,7 +13,7 @@ use Flow\Import\ImportException;
use Flow\Import\LiquidThreadsApi\ImportTopic as LqtImportTopic;
use Flow\Import\PageImportState;
use Flow\Import\TopicImportState;
-use Flow\Model\UUID;
+use Flow\Model\PostRevision;
use Flow\NotificationController;
use RecursiveIteratorIterator;
use User;
@@ -34,9 +34,9 @@ class LqtNotifications implements Postprocessor {
protected $dbw;
/**
- * @var bool True when posts have been imported for the current topic
+ * @var PostRevision[] Array of imported replies
*/
- protected $postsImported = false;
+ protected $postsImported = [];
public function __construct( NotificationController $controller, DatabaseBase $dbw ) {
$this->controller = $controller;
@@ -49,17 +49,7 @@ class LqtNotifications implements Postprocessor {
* of determining users to notify so they can be replaced with this class during imports.
*/
protected function overrideUsersToNotify() {
- global $wgHooks, $wgEchoNotifications;
-
- // Remove the hook subscriber that chooses users for some notifications
- $idx = array_search(
- 'Flow\NotificationController::getDefaultNotifiedUsers',
- $wgHooks['EchoGetDefaultNotifiedUsers']
- );
- if ( $idx !== false ) {
- unset( $wgHooks['EchoGetDefaultNotifiedUsers'][$idx] );
- }
-
+ global $wgEchoNotifications;
// Remove the user-locators that choose on a per-notification basis who
// should be notified.
@@ -78,11 +68,11 @@ class LqtNotifications implements Postprocessor {
// Overrides existing user-locators, because we don't want unintended
// notifications to go out here.
$self = $this;
- $wgEchoNotifications['flow-post-reply']['user-locators'] = array(
- function( EchoEvent $event ) use ( $self ) {
+ $wgEchoNotifications['flow-post-reply']['user-locators'] = [
+ function ( EchoEvent $event ) use ( $self ) {
return $self->locateUsersWithPendingLqtNotifications( $event );
}
- );
+ ];
}
/**
@@ -97,22 +87,22 @@ class LqtNotifications implements Postprocessor {
throw new ImportException( 'No active thread!' );
}
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
$this->dbw,
/* table = */ 'user_message_state',
- /* primary keys */ array( 'ums_user' ),
+ /* primary keys */ [ 'ums_user' ],
$batchSize
);
- $it->addConditions( array(
+ $it->addConditions( [
'ums_conversation' => $activeThreadId,
'ums_read_timestamp' => null,
- ) );
+ ] );
// flatten 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->ums_user );
} );
@@ -123,36 +113,36 @@ class LqtNotifications implements Postprocessor {
if ( !$topic instanceof LqtImportTopic ) {
return;
}
- if ( $this->postsImported === false ) {
+ if ( empty( $this->postsImported ) ) {
// nothing was imported in this topic
return;
}
- $this->postsImported = false;
- $this->controller->notifyPostChange( 'flow-post-reply', array(
- 'revision' => $state->topicTitle,
+ $this->controller->notifyPostChange( 'flow-post-reply', [
+ 'revision' => $this->postsImported[0],
'topic-title' => $state->topicTitle,
'topic-workflow' => $state->topicWorkflow,
'title' => $state->topicWorkflow->getOwnerTitle(),
'reply-to' => $state->topicTitle,
- 'extra-data' => array(
+ 'extra-data' => [
'lqtThreadId' => $topic->getLqtThreadId(),
'notifyAgent' => true,
- ),
+ ],
'timestamp' => $topic->getTimestamp(),
- ) );
+ ] );
+
+ $this->postsImported = [];
}
public function importAborted() {
- $this->postsImported = false;
+ $this->postsImported = [];
}
public function afterHeaderImported( PageImportState $state, IImportHeader $header ) {
// not a thing to do, yet
}
- public function afterPostImported( TopicImportState $state, IImportPost $post, UUID $newPostId ) {
- $this->postsImported = true;
+ public function afterPostImported( TopicImportState $state, IImportPost $post, PostRevision $newPost ) {
+ $this->postsImported[] = $newPost;
}
-
}
diff --git a/Flow/includes/Import/Postprocessor/LqtRedirector.php b/Flow/includes/Import/Postprocessor/LqtRedirector.php
index 1517b9e7..a5ba2f13 100644
--- a/Flow/includes/Import/Postprocessor/LqtRedirector.php
+++ b/Flow/includes/Import/Postprocessor/LqtRedirector.php
@@ -8,13 +8,13 @@ use Flow\Import\IImportTopic;
use Flow\Import\LiquidThreadsApi\ImportPost;
use Flow\Import\LiquidThreadsApi\ImportTopic;
use Flow\Import\PageImportState;
-use Flow\Import\PostImportState;
use Flow\Import\TopicImportState;
+use Flow\Model\PostRevision;
use Flow\Model\UUID;
use Flow\UrlGenerator;
+use MediaWiki\MediaWikiServices;
use Title;
use User;
-use WatchedItem;
use WikiPage;
use WikitextContent;
@@ -28,7 +28,7 @@ class LqtRedirector implements Postprocessor {
public function __construct( UrlGenerator $urlGenerator, User $user ) {
$this->urlGenerator = $urlGenerator;
- $this->redirectsToDo = array();
+ $this->redirectsToDo = [];
$this->user = $user;
}
@@ -36,13 +36,13 @@ class LqtRedirector implements Postprocessor {
// not a thing to do, yet
}
- public function afterPostImported( TopicImportState $state, IImportPost $post, UUID $newPostId ) {
+ public function afterPostImported( TopicImportState $state, IImportPost $post, PostRevision $newPost ) {
if ( $post instanceof ImportPost /* LQT */ ) {
- $this->redirectsToDo[] = array(
+ $this->redirectsToDo[] = [
$post->getTitle(),
$state->topicWorkflow->getId(),
- $newPostId
- );
+ $newPost->getPostId()
+ ];
}
}
@@ -54,15 +54,15 @@ class LqtRedirector implements Postprocessor {
$topic->getTitle(),
$state->topicWorkflow->getId()
);
- foreach( $this->redirectsToDo as $args ) {
- call_user_func_array( array( $this, 'doRedirect' ), $args );
+ foreach ( $this->redirectsToDo as $args ) {
+ call_user_func_array( [ $this, 'doRedirect' ], $args );
}
- $this->redirectsToDo = array();
+ $this->redirectsToDo = [];
}
public function importAborted() {
- $this->redirectsToDo = array();
+ $this->redirectsToDo = [];
}
protected function doRedirect( Title $fromTitle, UUID $toTopic, UUID $toPost = null ) {
@@ -74,11 +74,13 @@ class LqtRedirector implements Postprocessor {
$redirectTarget = $redirectAnchor->resolveTitle();
- $newContent = new WikiTextContent( "#REDIRECT [[".$redirectTarget->getFullText()."]]" );
+ $newContent = new WikitextContent( "#REDIRECT [[".$redirectTarget->getFullText()."]]" );
$page = WikiPage::factory( $fromTitle );
$summary = wfMessage( 'flow-lqt-redirect-reason' )->plain();
$page->doEditContent( $newContent, $summary, EDIT_FORCE_BOT, false, $this->user );
- WatchedItem::duplicateEntries( $fromTitle, $redirectTarget );
+ MediaWikiServices::getInstance()->getWatchedItemStore()->duplicateAllAssociatedEntries(
+ $fromTitle, $redirectTarget
+ );
}
}
diff --git a/Flow/includes/Import/Postprocessor/Postprocessor.php b/Flow/includes/Import/Postprocessor/Postprocessor.php
index 95db70be..745eacfb 100644
--- a/Flow/includes/Import/Postprocessor/Postprocessor.php
+++ b/Flow/includes/Import/Postprocessor/Postprocessor.php
@@ -2,7 +2,7 @@
namespace Flow\Import\Postprocessor;
-use Flow\Model\UUID;
+use Flow\Model\PostRevision;
use Flow\Import\IImportHeader;
use Flow\Import\IImportPost;
use Flow\Import\IImportTopic;
@@ -29,9 +29,9 @@ interface Postprocessor {
*
* @param TopicImportState $state
* @param IImportPost $post
- * @param UUID $newPostId
+ * @param PostRevision $newPost
*/
- function afterPostImported( TopicImportState $state, IImportPost $post, UUID $newPostId );
+ function afterPostImported( TopicImportState $state, IImportPost $post, PostRevision $newPost );
/**
* Called after the successful commit of a topic to the database.
@@ -39,7 +39,7 @@ interface Postprocessor {
* called on all topics run through the process regardless.
*
* @param TopicImportState $state
- * @param IImportPost $post
+ * @param IImportPost $topic
*/
function afterTopicImported( TopicImportState $state, IImportTopic $topic );
diff --git a/Flow/includes/Import/Postprocessor/ProcessorGroup.php b/Flow/includes/Import/Postprocessor/ProcessorGroup.php
index 15ca24f7..83df95ab 100644
--- a/Flow/includes/Import/Postprocessor/ProcessorGroup.php
+++ b/Flow/includes/Import/Postprocessor/ProcessorGroup.php
@@ -2,7 +2,7 @@
namespace Flow\Import\Postprocessor;
-use Flow\Model\UUID;
+use Flow\Model\PostRevision;
use Flow\Import\IImportHeader;
use Flow\Import\IImportPost;
use Flow\Import\IImportTopic;
@@ -13,8 +13,8 @@ class ProcessorGroup implements Postprocessor {
/** @var array<Postprocessor> **/
protected $processors;
- public function __construct( ) {
- $this->processors = array();
+ public function __construct() {
+ $this->processors = [];
}
public function add( Postprocessor $proc ) {
@@ -29,7 +29,7 @@ class ProcessorGroup implements Postprocessor {
$this->call( __FUNCTION__, func_get_args() );
}
- public function afterPostImported( TopicImportState $state, IImportPost $post, UUID $newPostId ) {
+ public function afterPostImported( TopicImportState $state, IImportPost $post, PostRevision $newPost ) {
$this->call( __FUNCTION__, func_get_args() );
}
@@ -38,8 +38,8 @@ class ProcessorGroup implements Postprocessor {
}
protected function call( $name, $args ) {
- foreach( $this->processors as $proc ) {
- call_user_func_array( array( $proc, $name ), $args );
+ foreach ( $this->processors as $proc ) {
+ call_user_func_array( [ $proc, $name ], $args );
}
}
}
diff --git a/Flow/includes/Import/Postprocessor/SpecialLogTopic.php b/Flow/includes/Import/Postprocessor/SpecialLogTopic.php
index 36167fc8..de818df8 100644
--- a/Flow/includes/Import/Postprocessor/SpecialLogTopic.php
+++ b/Flow/includes/Import/Postprocessor/SpecialLogTopic.php
@@ -7,7 +7,7 @@ use Flow\Import\IImportPost;
use Flow\Import\IImportTopic;
use Flow\Import\PageImportState;
use Flow\Import\TopicImportState;
-use Flow\Model\UUID;
+use Flow\Model\PostRevision;
use ManualLogEntry;
use User;
@@ -33,7 +33,7 @@ class SpecialLogTopic implements PostProcessor {
// nothing to do
}
- public function afterPostImported( TopicImportState $state, IImportPost $post, UUID $newPostId ) {
+ public function afterPostImported( TopicImportState $state, IImportPost $post, PostRevision $newPost ) {
$this->newPosts = true;
}
@@ -44,9 +44,9 @@ class SpecialLogTopic implements PostProcessor {
$logEntry = new ManualLogEntry( 'import', $topic->getLogType() );
$logEntry->setTarget( $state->topicWorkflow->getOwnerTitle() );
$logEntry->setPerformer( $this->user );
- $logEntry->setParameters( array(
+ $logEntry->setParameters( [
'topic' => $state->topicWorkflow->getArticleTitle()->getPrefixedText(),
- ) + $topic->getLogParameters() );
+ ] + $topic->getLogParameters() );
$logEntry->insert();
$this->newPosts = false;
diff --git a/Flow/includes/Import/SourceStore/Exception.php b/Flow/includes/Import/SourceStore/Exception.php
new file mode 100644
index 00000000..97df87fd
--- /dev/null
+++ b/Flow/includes/Import/SourceStore/Exception.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Flow\Import\SourceStore;
+
+use Flow\Import\ImportException;
+
+/**
+ * A failure occurred trying to read or write to the
+ * permanent storage backing the SourceStoreInterface.
+ */
+class Exception extends ImportException {
+}
diff --git a/Flow/includes/Import/SourceStore/FileImportSourceStore.php b/Flow/includes/Import/SourceStore/FileImportSourceStore.php
new file mode 100644
index 00000000..694455d3
--- /dev/null
+++ b/Flow/includes/Import/SourceStore/FileImportSourceStore.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Flow\Import\SourceStore;
+
+use Flow\Import\IImportObject;
+use Flow\Model\UUID;
+
+class FileImportSourceStore implements SourceStoreInterface {
+ /** @var string **/
+ protected $filename;
+ /** @var array */
+ protected $data;
+
+ public function __construct( $filename ) {
+ $this->filename = $filename;
+ $this->load();
+ }
+
+ protected function load() {
+ if ( file_exists( $this->filename ) ) {
+ $this->data = json_decode( file_get_contents( $this->filename ), true );
+ } else {
+ $this->data = [];
+ }
+ }
+
+ public function save() {
+ $bytesWritten = file_put_contents( $this->filename, json_encode( $this->data ) );
+ if ( $bytesWritten === false ) {
+ throw new Exception( 'Could not write out source store to ' . $this->filename );
+ }
+ }
+
+ public function rollback() {
+ $this->load();
+ }
+
+ public function setAssociation( UUID $objectId, $importSourceKey ) {
+ $this->data[$importSourceKey] = $objectId->getAlphadecimal();
+ }
+
+ public function getImportedId( IImportObject $importObject ) {
+ $importSourceKey = $importObject->getObjectKey();
+ return isset( $this->data[$importSourceKey] )
+ ? UUID::create( $this->data[$importSourceKey] )
+ : false;
+ }
+}
diff --git a/Flow/includes/Import/SourceStore/FlowRevisionsDb.php b/Flow/includes/Import/SourceStore/FlowRevisionsDb.php
new file mode 100644
index 00000000..4ca6c6b8
--- /dev/null
+++ b/Flow/includes/Import/SourceStore/FlowRevisionsDb.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace Flow\Import\SourceStore;
+
+use DatabaseBase;
+use IP;
+use Flow\Import\IImportHeader;
+use Flow\Import\IImportObject;
+use Flow\Import\IImportPost;
+use Flow\Import\IImportSummary;
+use Flow\Import\IImportTopic;
+use Flow\Import\IObjectRevision;
+use Flow\Import\IRevisionableObject;
+use Flow\Model\UserTuple;
+use Flow\Model\UUID;
+use MWTimestamp;
+use User;
+use Wikimedia\Timestamp\TimestampException;
+
+/**
+ * Unlike other source stores, this doesn't really "store" anything. This just
+ * does a lookup for certain types of objects to the database to figure out if
+ * they have already been imported.
+ *
+ * This is less versatile than other source stores (you can't just throw
+ * anything at it, it's tied to a specific schema and throwing new objects at it
+ * will prompt changes in here) but it's more reliable (if the source store is
+ * lost, it can use the "result" of a previous import)
+ */
+class FlowRevisionsDb implements SourceStoreInterface {
+ /**
+ * @var DatabaseBase
+ */
+ protected $dbr;
+
+ /**
+ * @param DatabaseBase $dbr
+ */
+ public function __construct( DatabaseBase $dbr ) {
+ $this->dbr = $dbr;
+ }
+
+ public function setAssociation( UUID $objectId, $importSourceKey ) {
+ return '';
+ }
+
+ public function getImportedId( IImportObject $object ) {
+ if ( $object instanceof IImportHeader ) {
+ $conds = [ 'rev_type' => 'header' ];
+ } elseif ( $object instanceof IImportSummary ) {
+ $conds = [ 'rev_type' => 'post-summary' ];
+ } elseif ( $object instanceof IImportTopic ) {
+ $conds = [ 'rev_type' => 'post', 'tree_parent_id' => null ];
+ } elseif ( $object instanceof IImportPost ) {
+ $conds = [ 'rev_type' => 'post', 'tree_parent_id IS NOT NULL' ];
+ } else {
+ throw new Exception( 'Import object of type ' . get_class( $object ) . ' not supported.' );
+ }
+
+ $revision = $this->getObjectRevision( $object );
+ return $this->getCollectionId( $revision->getTimestamp(), $revision->getAuthor(), $conds );
+ }
+
+ public function save() {
+ }
+
+ public function rollback() {
+ }
+
+ /**
+ * @param string $timestamp
+ * @param string $author
+ * @param array $conds
+ * @return bool|UUID
+ * @throws Exception
+ * @throws \DBUnexpectedError
+ * @throws \Flow\Exception\FlowException
+ * @throws \Flow\Exception\InvalidInputException
+ */
+ protected function getCollectionId( $timestamp, $author, array $conds = [] ) {
+ $range = $this->getUUIDRange( new MWTimestamp( $timestamp ) );
+ $tuple = $this->getUserTuple( $author );
+
+ // flow_revision will LEFT JOIN against flow_tree_revision, meaning that
+ // we'll also have info about the parent; or it can just be ignored if
+ // there is no parent
+ $rows = $this->dbr->select(
+ [ 'flow_revision', 'flow_tree_revision' ],
+ [ 'rev_type_id' ],
+ array_merge(
+ [
+ 'rev_type_id >= ' . $this->dbr->addQuotes( $range[0]->getBinary() ),
+ 'rev_type_id < ' . $this->dbr->addQuotes( $range[1]->getBinary() ),
+ ],
+ $tuple->toArray( 'rev_user_' ),
+ $conds
+ ),
+ __METHOD__,
+ [ 'LIMIT' => 1 ],
+ [
+ 'flow_tree_revision' => [
+ 'LEFT OUTER JOIN',
+ [ 'tree_rev_descendant_id = rev_type_id' ]
+ ],
+ ]
+ );
+
+ if ( $rows->numRows() === 0 ) {
+ return false;
+ }
+
+ return UUID::create( $rows->fetchObject()->rev_type_id );
+ }
+
+ /**
+ * @param IRevisionableObject $object
+ * @return IObjectRevision
+ */
+ protected function getObjectRevision( IRevisionableObject $object ) {
+ $revisions = $object->getRevisions();
+ $revisions->rewind();
+ return $revisions->current();
+ }
+
+ /**
+ * @param string $name
+ * @return UserTuple
+ * @throws Exception
+ */
+ protected function getUserTuple( $name ) {
+ $user = $this->getUser( $name );
+ if ( $user === false ) {
+ throw new Exception( 'Invalid author: ' . $name );
+ }
+ return UserTuple::newFromUser( $user );
+ }
+
+ /**
+ * @param string $name
+ * @return bool|User
+ */
+ protected function getUser( $name ) {
+ if ( IP::isIPAddress( $name ) ) {
+ return User::newFromName( $name, false );
+ }
+
+ return User::newFromName( $name );
+ }
+
+ /**
+ * Gets the min <= ? < max boundaries for a UUID that has a given
+ * timestamp. Returns an array where [0] = min & [1] is max.
+ *
+ * @param MWTimestamp $timestamp
+ * @return UUID[] [min, max]
+ * @throws TimestampException
+ */
+ protected function getUUIDRange( MWTimestamp $timestamp ) {
+ return [
+ UUID::getComparisonUUID( (int)$timestamp->getTimestamp( TS_UNIX ) ),
+ UUID::getComparisonUUID( (int)$timestamp->getTimestamp( TS_UNIX ) + 1 ),
+ ];
+ }
+}
diff --git a/Flow/includes/Import/SourceStore/NullImportSourceStore.php b/Flow/includes/Import/SourceStore/NullImportSourceStore.php
new file mode 100644
index 00000000..8d1a7d65
--- /dev/null
+++ b/Flow/includes/Import/SourceStore/NullImportSourceStore.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Flow\Import\SourceStore;
+
+use Flow\Import\IImportObject;
+use Flow\Model\UUID;
+
+class NullImportSourceStore implements SourceStoreInterface {
+ public function setAssociation( UUID $objectId, $importSourceKey ) {
+ return '';
+ }
+
+ public function getImportedId( IImportObject $importObject ) {
+ return false;
+ }
+
+ public function save() {
+ }
+
+ public function rollback() {
+ }
+}
diff --git a/Flow/includes/Import/SourceStore/SourceStoreInterface.php b/Flow/includes/Import/SourceStore/SourceStoreInterface.php
new file mode 100644
index 00000000..942651cd
--- /dev/null
+++ b/Flow/includes/Import/SourceStore/SourceStoreInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Flow\Import\SourceStore;
+
+use Flow\Import\IImportObject;
+use Flow\Model\UUID;
+
+interface SourceStoreInterface {
+ /**
+ * Stores the association between an object and where it was imported from.
+ *
+ * @param UUID $objectId ID for the object that was imported.
+ * @param string $importSourceKey String returned from IImportObject::getObjectKey()
+ */
+ function setAssociation( UUID $objectId, $importSourceKey );
+
+ /**
+ * @param IImportObject $importObject
+ * @return UUID|bool UUID of the imported object if appropriate; otherwise, false.
+ */
+ function getImportedId( IImportObject $importObject );
+
+ /**
+ * Save any associations that have been added
+ * @throws Exception When save fails
+ */
+ function save();
+
+ /**
+ * Forget any recorded associations since last save
+ */
+ function rollback();
+}
diff --git a/Flow/includes/Import/TemplateHelper.php b/Flow/includes/Import/TemplateHelper.php
index 67ccac3a..1309d515 100644
--- a/Flow/includes/Import/TemplateHelper.php
+++ b/Flow/includes/Import/TemplateHelper.php
@@ -5,7 +5,8 @@ namespace Flow\Import;
use DOMDocument;
use DOMElement;
use DOMXPath;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
+use Title;
class TemplateHelper {
@@ -34,7 +35,7 @@ class TemplateHelper {
}
}
- $body = $xpath->query( '/html/body' )->item(0);
+ $body = $xpath->query( '/html/body' )->item( 0 );
return $dom->saveHTML( $body );
}
@@ -63,4 +64,26 @@ class TemplateHelper {
}
}
-} \ No newline at end of file
+ /**
+ * Extract templates from wikitext content.
+ * Requires Parsoid to reliably extract templates.
+ *
+ * @param string $content
+ * @param Title $title
+ * @return string
+ */
+ public static function extractTemplates( $content, Title $title ) {
+ $content = Utils::convert( 'wikitext', 'html', $content, $title );
+ $dom = Utils::createDOM( $content );
+ $xpath = new \DOMXPath( $dom );
+ $templates = $xpath->query( '//*[@typeof="mw:Transclusion"]' );
+
+ $content = '';
+ foreach ( $templates as $template ) {
+ $content .= $dom->saveHTML( $template ) . "\n";
+ }
+
+ return Utils::convert( 'html', 'wikitext', $content, $title );
+ }
+
+}
diff --git a/Flow/includes/Import/Wikitext/ConversionStrategy.php b/Flow/includes/Import/Wikitext/ConversionStrategy.php
index 6fd8c30c..e32fba5f 100644
--- a/Flow/includes/Import/Wikitext/ConversionStrategy.php
+++ b/Flow/includes/Import/Wikitext/ConversionStrategy.php
@@ -5,14 +5,14 @@ namespace Flow\Import\Wikitext;
use DateTime;
use DateTimeZone;
use Flow\Import\ArchiveNameHelper;
-use Flow\Import\Converter;
use Flow\Import\IConversionStrategy;
-use Flow\Import\ImportSourceStore;
+use Flow\Import\SourceStore\SourceStoreInterface as ImportSourceStore;
use LinkBatch;
use Parser;
use Psr\Log\LoggerInterface;
use StubObject;
use Title;
+use User;
use WikitextContent;
/**
@@ -46,19 +46,28 @@ class ConversionStrategy implements IConversionStrategy {
protected $parser;
/**
- * @var array $archiveTitleSuggestions
+ * @var array
*/
protected $archiveTitleSuggestions;
/**
- * @var string $headerSuffix
+ * @var string
*/
protected $headerSuffix;
+ /** @var User User doing the conversion actions (e.g. initial description, wikitext
+ * archive edit). However, actions will be attributed to the original user when
+ * possible (e.g. the user who did the original LQT reply)
+ *
+ */
+ protected $user;
+
/**
* @param Parser|StubObject $parser
* @param ImportSourceStore $sourceStore
* @param LoggerInterface $logger
+ * @param User $user User to take conversion actions are (applicable for actions
+ * where if there is no 'original' user)
* @param Title[] $noConvertTemplates List of templates that flag pages that
* shouldn't be converted (optional)
* @param string $headerSuffix Wikitext to add to the end of the header (optional)
@@ -67,18 +76,20 @@ class ConversionStrategy implements IConversionStrategy {
$parser,
ImportSourceStore $sourceStore,
LoggerInterface $logger,
- array $noConvertTemplates = array(),
+ User $user,
+ array $noConvertTemplates = [],
$headerSuffix = null
) {
$this->parser = $parser;
$this->sourceStore = $sourceStore;
$this->logger = $logger;
+ $this->user = $user;
$this->noConvertTemplates = $noConvertTemplates;
$this->headerSuffix = $headerSuffix;
$archiveFormat = wfMessage( 'flow-conversion-archive-page-name-format' )->inContentLanguage()->plain();
- if ( strpos( $archiveFormat, "\n") === false ) {
- $this->archiveTitleSuggestions = array( $archiveFormat );
+ if ( strpos( $archiveFormat, "\n" ) === false ) {
+ $this->archiveTitleSuggestions = [ $archiveFormat ];
} else {
$this->archiveTitleSuggestions = explode( "\n", $archiveFormat );
}
@@ -124,7 +135,7 @@ class ConversionStrategy implements IConversionStrategy {
* {@inheritDoc}
*/
public function createImportSource( Title $title ) {
- return new ImportSource( $title, $this->parser, $this->headerSuffix );
+ return new ImportSource( $title, $this->parser, $this->user, $this->headerSuffix );
}
/**
@@ -147,10 +158,10 @@ class ConversionStrategy implements IConversionStrategy {
*/
public function createArchiveCleanupRevisionContent( WikitextContent $content, Title $title ) {
$now = new DateTime( "now", new DateTimeZone( "GMT" ) );
- $arguments = implode( '|', array(
+ $arguments = implode( '|', [
'from=' . $title->getPrefixedText(),
'date=' . $now->format( 'Y-m-d' ),
- ) );
+ ] );
$template = wfMessage( 'flow-importer-wt-converted-archive-template' )->inContentLanguage()->plain();
$newWikitext = "{{{$template}|$arguments}}" . "\n\n" . $content->getNativeData();
@@ -194,12 +205,12 @@ class ConversionStrategy implements IConversionStrategy {
$result = $dbr->select(
'templatelinks',
'tl_from',
- array(
+ [
'tl_from' => $sourceTitle->getArticleID(),
$batch->constructSet( 'tl', $dbr )
- ),
+ ],
__METHOD__,
- array( 'LIMIT' => 1 )
+ [ 'LIMIT' => 1 ]
);
return $dbr->numRows( $result ) > 0;
}
diff --git a/Flow/includes/Import/Wikitext/ImportSource.php b/Flow/includes/Import/Wikitext/ImportSource.php
index 93f0d41e..7b3d75e9 100644
--- a/Flow/includes/Import/Wikitext/ImportSource.php
+++ b/Flow/includes/Import/Wikitext/ImportSource.php
@@ -3,8 +3,7 @@
namespace Flow\Import\Wikitext;
use ArrayIterator;
-use Flow\Parsoid\Utils;
-use FlowHooks;
+use Flow\Import\TemplateHelper;
use Flow\Import\ImportException;
use Flow\Import\Plain\ImportHeader;
use Flow\Import\Plain\ObjectRevision;
@@ -15,6 +14,7 @@ use ParserOptions;
use Revision;
use StubObject;
use Title;
+use User;
/**
* Imports the header of a wikitext talk page. Does not attempt to
@@ -22,19 +22,26 @@ use Title;
* ConversionStrategy for more details.
*/
class ImportSource implements IImportSource {
+ /** @var User User doing the conversion actions (e.g. initial description, wikitext
+ * archive edit). However, actions will be attributed to the original user if
+ * applicable.
+ */
+ protected $user;
/**
* @param Title $title
* @param Parser|StubObject $parser
+ * @param User $user User to take actions as
* @param string $headerSuffix
* @throws ImportException When $title is an external title
*/
- public function __construct( Title $title, $parser, $headerSuffix = null ) {
+ public function __construct( Title $title, $parser, User $user, $headerSuffix = null ) {
if ( $title->isExternal() ) {
throw new ImportException( "Invalid non-local title: $title" );
}
$this->title = $title;
$this->parser = $parser;
+ $this->user = $user;
$this->headerSuffix = $headerSuffix;
}
@@ -63,13 +70,13 @@ class ImportSource implements IImportSource {
$content = substr( $content, 0, $sections[0]['byteoffset'] );
}
- $content = $this->extractTemplates( $content );
+ $content = TemplateHelper::extractTemplates( $content, $this->title );
$template = wfMessage( 'flow-importer-wt-converted-template' )->inContentLanguage()->plain();
- $arguments = implode( '|', array(
+ $arguments = implode( '|', [
'archive=' . $this->title->getPrefixedText(),
'date=' . MWTimestamp::getInstance()->timestamp->format( 'Y-m-d' ),
- ) );
+ ] );
$content .= "\n\n{{{$template}|$arguments}}";
if ( $this->headerSuffix && !empty( $this->headerSuffix ) ) {
@@ -77,42 +84,20 @@ class ImportSource implements IImportSource {
}
return new ImportHeader(
- array( new ObjectRevision(
+ [ new ObjectRevision(
$content,
wfTimestampNow(),
- FlowHooks::getOccupationController()->getTalkpageManager()->getName(),
+ $this->user->getName(),
"wikitext-import:header-revision:{$revision->getId()}"
- ) ),
+ ) ],
"wikitext-import:header:{$this->title->getPrefixedText()}"
);
}
/**
- * Only extract templates to copy to Flow description.
- * Requires Parsoid, to reliably extract templates.
- *
- * @param string $content
- * @return string
- */
- protected function extractTemplates( $content ) {
- $content = Utils::convert( 'wikitext', 'html', $content, $this->title );
- $dom = Utils::createDOM( $content );
- $xpath = new \DOMXPath( $dom );
- $templates = $xpath->query( '//*[@typeof="mw:Transclusion"]' );
-
- $content = '';
- foreach ( $templates as $template ) {
- $content .= $dom->saveHTML( $template ) . "\n";
- }
-
- return Utils::convert( 'html', 'wikitext', $content, $this->title );
- }
-
- /**
* {@inheritDoc}
*/
public function getTopics() {
- return new ArrayIterator( array() );
+ return new ArrayIterator( [] );
}
}
-
diff --git a/Flow/includes/LinksTableUpdater.php b/Flow/includes/LinksTableUpdater.php
index 436cff14..ff33ead8 100644
--- a/Flow/includes/LinksTableUpdater.php
+++ b/Flow/includes/LinksTableUpdater.php
@@ -2,7 +2,7 @@
namespace Flow;
-use DataUpdate;
+use DeferredUpdates;
use Flow\Data\ManagerGroup;
use Flow\Model\Reference;
use Flow\Model\URLReference;
@@ -31,12 +31,14 @@ class LinksTableUpdater {
$page = WikiPage::factory( $title );
$content = $page->getContent();
if ( $content === null ) {
- $updates = array();
+ $updates = [];
} else {
$updates = $content->getSecondaryDataUpdates( $title );
}
- DataUpdate::runUpdates( $updates );
+ foreach ( $updates as $update ) {
+ DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND );
+ }
}
/**
@@ -51,11 +53,11 @@ class LinksTableUpdater {
$linkBatch = new LinkBatch();
/** @var Title[] $internalLinks */
- $internalLinks = array();
+ $internalLinks = [];
/** @var Title[] $templates */
- $templates = array();
+ $templates = [];
- foreach( $references as $reference ) {
+ foreach ( $references as $reference ) {
if ( $reference->getType() === 'link' ) {
if ( $reference instanceof URLReference ) {
$parserOutput->mExternalLinks[$reference->getURL()] = true;
@@ -88,22 +90,22 @@ class LinksTableUpdater {
$linkBatch->execute();
$linkCache = LinkCache::singleton();
- foreach( $internalLinks as $title ) {
+ foreach ( $internalLinks as $title ) {
$ns = $title->getNamespace();
$dbk = $title->getDBkey();
if ( !isset( $parserOutput->mLinks[$ns] ) ) {
- $parserOutput->mLinks[$ns] = array();
+ $parserOutput->mLinks[$ns] = [];
}
$id = $linkCache->getGoodLinkID( $title->getPrefixedDBkey() );
$parserOutput->mLinks[$ns][$dbk] = $id;
}
- foreach( $templates as $title ) {
+ foreach ( $templates as $title ) {
$ns = $title->getNamespace();
$dbk = $title->getDBkey();
if ( !isset( $parserOutput->mTemplates[$ns] ) ) {
- $parserOutput->mTemplates[$ns] = array();
+ $parserOutput->mTemplates[$ns] = [];
}
$id = $linkCache->getGoodLinkID( $title->getPrefixedDBkey() );
@@ -112,30 +114,27 @@ class LinksTableUpdater {
}
public function getReferencesForTitle( Title $title ) {
- global $wgFlowMigrateReferenceWiki;
- $wikiConds = $wgFlowMigrateReferenceWiki
- ? array()
- : array( 'ref_src_wiki' => wfWikiId() );
-
$wikiReferences = $this->storage->find(
'WikiReference',
- $wikiConds + array(
+ [
+ 'ref_src_wiki' => wfWikiID(),
'ref_src_namespace' => $title->getNamespace(),
'ref_src_title' => $title->getDBkey(),
- )
+ ]
);
$urlReferences = $this->storage->find(
'URLReference',
- $wikiConds + array(
+ [
+ 'ref_src_wiki' => wfWikiID(),
'ref_src_namespace' => $title->getNamespace(),
'ref_src_title' => $title->getDBkey(),
- )
+ ]
);
// let's make sure the merge doesn't fail when nothing was found
- $wikiReferences = $wikiReferences ?: array();
- $urlReferences = $urlReferences ?: array();
+ $wikiReferences = $wikiReferences ?: [];
+ $urlReferences = $urlReferences ?: [];
return array_merge( $wikiReferences, $urlReferences );
}
diff --git a/Flow/includes/Log/ActionFormatter.php b/Flow/includes/Log/ActionFormatter.php
index 43468085..3c3818c8 100644
--- a/Flow/includes/Log/ActionFormatter.php
+++ b/Flow/includes/Log/ActionFormatter.php
@@ -6,23 +6,41 @@ use Flow\Collection\PostCollection;
use Flow\Container;
use Flow\Data\ManagerGroup;
use Flow\Model\UUID;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Flow\Repository\TreeRepository;
+use Flow\Templating;
use Flow\UrlGenerator;
+
+use LogEntry;
+use LogFormatter;
+use LogPage;
use Message;
-class ActionFormatter extends \LogFormatter {
+class ActionFormatter extends LogFormatter {
/**
* @var UUID[]
*/
- static $uuids = array();
+ private static $uuids = [];
+
+ /**
+ * @var RevisionActionPermissions
+ */
+ protected $permissions;
+
+ /**
+ * @var Templating
+ */
+ protected $templating;
/**
- * @param \LogEntry $entry
+ * @param LogEntry $entry
*/
- public function __construct( \LogEntry $entry ) {
+ public function __construct( LogEntry $entry ) {
parent::__construct( $entry );
+ $this->permissions = Container::get( 'permissions' );
+ $this->templating = Container::get( 'templating' );
+
$params = $this->entry->getParameters();
// serialized topicId or postId can be stored
foreach ( $params as $key => $value ) {
@@ -38,8 +56,6 @@ class ActionFormatter extends \LogFormatter {
* @return string The log entry
*/
protected function getActionMessage() {
- global $wgContLang;
-
/*
* At this point, all log entries will already have been created & we've
* gathered all uuids in constructor: we can now batch-load all of them.
@@ -69,13 +85,8 @@ class ActionFormatter extends \LogFormatter {
$type = $this->entry->getType();
$action = $this->entry->getSubtype();
$title = $this->entry->getTarget();
- $skin = $this->plaintext ? null : $this->context->getSkin();
$params = $this->entry->getParameters();
- // @todo: we should probably check if user isAllowed( <this-revision>, 'log' )
- // unlike RC, Contributions, ... this one does not batch-load all Flow
- // revisions & does not use the same Formatter, i18n message text, etc
-
if ( isset( $params['postId'] ) ) {
/** @var UrlGenerator $urlGenerator */
$urlGenerator = Container::get( 'url_generator' );
@@ -89,27 +100,51 @@ class ActionFormatter extends \LogFormatter {
$title = $anchor->resolveTitle();
}
+ $rootLastRevision = $root->getLastRevision();
+
// Give grep a chance to find the usages:
- // logentry-delete-flow-delete-post, logentry-delete-flow-restore-post,
- // logentry-suppress-flow-restore-post, logentry-suppress-flow-suppress-post,
- // logentry-delete-flow-delete-topic, logentry-delete-flow-restore-topic,
- // logentry-suppress-flow-restore-topic, logentry-suppress-flow-suppress-topic,
- $language = $skin === null ? $wgContLang : $skin->getLanguage();
- $message = wfMessage( "logentry-$type-$action" )
- ->params( array(
+ // A few of the -topic-title-not-visible are not reachable with the current
+ // config (since people looking at the suppression log can see suppressed
+ // content), but are included to make it less brittle.
+ // logentry-delete-flow-delete-post, logentry-delete-flow-delete-post-topic-title-not-visible,
+ // logentry-delete-flow-restore-post, logentry-delete-flow-restore-post-topic-title-not-visible,
+ // logentry-suppress-flow-restore-post, logentry-suppress-flow-restore-post-topic-title-not-visible,
+ // logentry-suppress-flow-suppress-post, logentry-suppress-flow-suppress-post-topic-title-not-visible,
+ // logentry-delete-flow-delete-topic, logentry-delete-flow-delete-topic-topic-title-not-visible,
+ // logentry-delete-flow-restore-topic, logentry-delete-flow-restore-topic-topic-title-not-visible,
+ // logentry-suppress-flow-restore-topic, logentry-suppress-flow-restore-topic-topic-title-not-visible,
+ // logentry-suppress-flow-suppress-topic, logentry-suppress-flow-suppress-topic-topic-title-not-visible,
+ // logentry-lock-flow-lock-topic, logentry-lock-flow-lock-topic-topic-title-not-visible
+ // logentry-lock-flow-restore-topic, logentry-lock-flow-restore-topic-topic-title-not-visible,
+ $messageKey = "logentry-$type-$action";
+ $isTopicTitleVisible = $this->permissions->isAllowed( $rootLastRevision, 'view-topic-title' );
+
+ if ( !$isTopicTitleVisible ) {
+ $messageKey .= '-topic-title-not-visible';
+ }
+
+ $message = $this->msg( $messageKey )
+ ->params( [
Message::rawParam( $this->getPerformerElement() ),
$this->entry->getPerformer()->getName(),
- $title, // link to topic
- $title->getFullUrl(), // link to topic, higlighted post
- $root->getLastRevision()->getContent(), // topic title
- $root->getWorkflow()->getOwnerTitle() // board title object
- ) )
- ->inLanguage( $language )
- ->parse();
+ ] );
+
+ if ( $isTopicTitleVisible ) {
+ $message->params( [
+ $title, // Title of topic
+ $title->getFullUrl(), // Full URL of topic, with highlighted post if applicable
+ ] );
+
+ $message->plaintextParams( $this->templating->getContent( $rootLastRevision, 'topic-title-plaintext' ) );
+ }
+
+ $message->params( $root->getWorkflow()->getOwnerTitle() ); // board title object
+
+ $message->parse();
return \Html::rawElement(
'span',
- array( 'class' => 'plainlinks' ),
+ [ 'class' => 'plainlinks' ],
$message
);
}
@@ -121,8 +156,12 @@ class ActionFormatter extends \LogFormatter {
* @return string
*/
public function getActionText() {
- $text = $this->getActionMessage();
- return $this->plaintext ? Utils::htmlToPlaintext( $text ) : $text;
+ if ( $this->canView( LogPage::DELETED_ACTION ) ) {
+ $text = $this->getActionMessage();
+ return $this->plaintext ? Utils::htmlToPlaintext( $text ) : $text;
+ } else {
+ return parent::getActionText();
+ }
}
/**
diff --git a/Flow/includes/Log/LqtImportFormatter.php b/Flow/includes/Log/LqtImportFormatter.php
index 3ef5b524..4462b0c8 100644
--- a/Flow/includes/Log/LqtImportFormatter.php
+++ b/Flow/includes/Log/LqtImportFormatter.php
@@ -8,10 +8,10 @@ use Title;
class LqtImportFormatter extends \LogFormatter {
public function getPreloadTitles() {
- $titles = array( $this->entry->getTarget() );
- $params = $this->entry->getParameters() + array(
+ $titles = [ $this->entry->getTarget() ];
+ $params = $this->entry->getParameters() + [
'topic' => '',
- );
+ ];
$topic = Title::newFromText( $params['topic'] );
if ( $topic ) {
$titles[] = $topic;
@@ -27,10 +27,10 @@ class LqtImportFormatter extends \LogFormatter {
*/
protected function getActionMessage() {
$board = $this->entry->getTarget();
- $params = $this->entry->getParameters() + array(
+ $params = $this->entry->getParameters() + [
'topic' => '',
'lqt_subject' => '',
- );
+ ];
$topic = Title::newFromText( $params['topic'] );
$message = $this->msg( "logentry-import-lqt-to-flow-topic" )
diff --git a/Flow/includes/Log/ModerationLogger.php b/Flow/includes/Log/ModerationLogger.php
index 4b2932bf..00254ae8 100644
--- a/Flow/includes/Log/ModerationLogger.php
+++ b/Flow/includes/Log/ModerationLogger.php
@@ -32,7 +32,7 @@ class ModerationLogger {
* @return bool
*/
public function canLog( PostRevision $post, $action ) {
- return (bool) $this->getLogType( $post, $action );
+ return (bool)$this->getLogType( $post, $action );
}
/**
@@ -49,9 +49,9 @@ class ModerationLogger {
return null;
}
- $params = array(
+ $params = [
'topicId' => $workflowId->getAlphadecimal(),
- );
+ ];
if ( !$post->isTopicTitle() ) {
$params['postId'] = $post->getPostId()->getAlphadecimal();
}
@@ -85,7 +85,7 @@ class ModerationLogger {
$logId = $logEntry->insert();
if ( $error ) {
- wfDebugLog( 'Flow', __METHOD__ . ': Could not map workflowId to workflow object for ' . $workflowId->getAlphadecimal() . " log entry $logId defaulted to Main_Page");
+ wfDebugLog( 'Flow', __METHOD__ . ': Could not map workflowId to workflow object for ' . $workflowId->getAlphadecimal() . " log entry $logId defaulted to Main_Page" );
}
return $logId;
@@ -98,7 +98,7 @@ class ModerationLogger {
*/
public function getLogType( PostRevision $post, $action ) {
$logType = $this->actions->getValue( $action, 'log_type' );
- if ( $logType instanceof Closure) {
+ if ( $logType instanceof Closure ) {
$logType = $logType( $post, $this );
}
diff --git a/Flow/includes/Log/Query.php b/Flow/includes/Log/Query.php
index 256c92b4..bf9a1a41 100644
--- a/Flow/includes/Log/Query.php
+++ b/Flow/includes/Log/Query.php
@@ -20,18 +20,18 @@ class LogQuery extends AbstractQuery {
* @return PostRevision[]
*/
protected function loadPostsBatch( array $uuids ) {
- $queries = array();
+ $queries = [];
foreach ( $uuids as $uuid ) {
- $queries[] = array( 'rev_type_id' => $uuid );
+ $queries[] = [ 'rev_type_id' => $uuid ];
}
$found = $this->storage->findMulti(
'PostRevision',
$queries,
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
- $revisions = array();
+ $revisions = [];
foreach ( $found as $result ) {
/** @var PostRevision $revision */
$revision = reset( $result );
diff --git a/Flow/includes/Model/AbstractRevision.php b/Flow/includes/Model/AbstractRevision.php
index ae1ba524..082fe2b7 100644
--- a/Flow/includes/Model/AbstractRevision.php
+++ b/Flow/includes/Model/AbstractRevision.php
@@ -6,9 +6,10 @@ use Flow\Collection\AbstractCollection;
use Flow\Exception\DataModelException;
use Flow\Exception\InvalidDataException;
use Flow\Exception\PermissionException;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use ContentHandler;
use Hooks;
+use Sanitizer;
use Title;
use User;
use RecentChange;
@@ -25,14 +26,21 @@ abstract class AbstractRevision {
* List of available permission levels.
*
* @var string[]
- **/
- static public $perms = array(
+ */
+ static public $perms = [
self::MODERATED_NONE,
self::MODERATED_HIDDEN,
self::MODERATED_DELETED,
self::MODERATED_SUPPRESSED,
self::MODERATED_LOCKED,
- );
+ ];
+
+ /**
+ * List of moderation change types
+ *
+ * @var array|null
+ */
+ static protected $moderationChangeTypes = null;
/**
* @var UUID
@@ -50,7 +58,7 @@ abstract class AbstractRevision {
*
* @var string[]
*/
- protected $flags = array();
+ protected $flags = [];
/**
* Name of the action performed that generated this revision.
@@ -83,14 +91,14 @@ abstract class AbstractRevision {
/**
* @var string[] Converted (wikitext|html) content, based off of $this->decompressedContent
*/
- protected $convertedContent = array();
+ protected $convertedContent = [];
/**
* html content has been allowed by the xss check. When we find the next xss
* in the parser this hook allows preventing any display of hostile html. True
* means the content is allowed. False means not allowed. Null means unchecked
*
- * @var boolean
+ * @var bool
*/
protected $xssCheck;
@@ -130,12 +138,12 @@ abstract class AbstractRevision {
protected $lastEditUser;
/**
- * @var integer Size of previous revision wikitext
+ * @var int Size of previous revision wikitext
*/
protected $previousContentLength = 0;
/**
- * @var integer Size of current revision wikitext
+ * @var int Size of current revision wikitext
*/
protected $contentLength = 0;
@@ -152,7 +160,7 @@ abstract class AbstractRevision {
* @return AbstractRevision
* @throws DataModelException
*/
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
if ( $obj === null ) {
/** @var AbstractRevision $obj */
$obj = new static;
@@ -164,9 +172,9 @@ abstract class AbstractRevision {
if ( $obj->user === null ) {
throw new DataModelException( 'Could not load UserTuple for rev_user_' );
}
- $obj->prevRevision = UUID::create( $row['rev_parent_id'] );
+ $obj->prevRevision = $row['rev_parent_id'] ? UUID::create( $row['rev_parent_id'] ) : null;
$obj->changeType = $row['rev_change_type'];
- $obj->flags = array_filter( explode( ',', $row['rev_flags'] ) );
+ $obj->flags = array_filter( explode( ',', $row['rev_flags'] ) );
$obj->content = $row['rev_content'];
// null if external store is not being used
$obj->contentUrl = isset( $row['rev_content_url'] ) ? $row['rev_content_url'] : null;
@@ -174,18 +182,18 @@ abstract class AbstractRevision {
$obj->moderationState = $row['rev_mod_state'];
$obj->moderatedBy = UserTuple::newFromArray( $row, 'rev_mod_user_' );
- $obj->moderationTimestamp = $row['rev_mod_timestamp'];
- $obj->moderatedReason = isset( $row['rev_mod_reason'] ) ? $row['rev_mod_reason'] : null;
+ $obj->moderationTimestamp = $row['rev_mod_timestamp'] ?: null;
+ $obj->moderatedReason = isset( $row['rev_mod_reason'] ) && $row['rev_mod_reason'] ? $row['rev_mod_reason'] : null;
// BC: 'suppress' used to be called 'censor' & 'lock' was 'close'
- $bc = array(
- 'censor' => AbstractRevision::MODERATED_SUPPRESSED,
- 'close' => AbstractRevision::MODERATED_LOCKED,
- );
+ $bc = [
+ 'censor' => self::MODERATED_SUPPRESSED,
+ 'close' => self::MODERATED_LOCKED,
+ ];
$obj->moderationState = str_replace( array_keys( $bc ), array_values( $bc ), $obj->moderationState );
// isset required because there is a possible db migration, cached data will not have it
- $obj->lastEditId = isset( $row['rev_last_edit_id'] ) ? UUID::create( $row['rev_last_edit_id'] ) : null;
+ $obj->lastEditId = isset( $row['rev_last_edit_id'] ) && $row['rev_last_edit_id'] ? UUID::create( $row['rev_last_edit_id'] ) : null;
$obj->lastEditUser = UserTuple::newFromArray( $row, 'rev_edit_user_' );
$obj->contentLength = isset( $row['rev_content_length'] ) ? $row['rev_content_length'] : 0;
@@ -198,8 +206,8 @@ abstract class AbstractRevision {
* @param AbstractRevision $obj
* @return string[]
*/
- static public function toStorageRow( $obj ) {
- return array(
+ public static function toStorageRow( $obj ) {
+ return [
'rev_id' => $obj->revId->getAlphadecimal(),
'rev_user_id' => $obj->user->id,
'rev_user_ip' => $obj->user->ip,
@@ -227,7 +235,7 @@ abstract class AbstractRevision {
'rev_content_length' => $obj->contentLength,
'rev_previous_content_length' => $obj->previousContentLength,
- );
+ ];
}
/**
@@ -255,6 +263,7 @@ abstract class AbstractRevision {
/**
* Create the next revision with new content
+ * or return itself when content is the same
*
* @param User $user
* @param string $content
@@ -267,7 +276,7 @@ abstract class AbstractRevision {
$obj = $this->newNullRevision( $user );
$obj->setNextContent( $user, $content, $format, $title );
$obj->changeType = $changeType;
- return $obj;
+ return $this->hasSameContentAs( $obj ) ? $this : $obj;
}
/**
@@ -278,7 +287,7 @@ abstract class AbstractRevision {
* @return AbstractRevision
*/
public function moderate( User $user, $state, $changeType, $reason ) {
- if ( ! $this->isValidModerationState( $state ) ) {
+ if ( !$this->isValidModerationState( $state ) ) {
wfWarn( __METHOD__ . ': Provided moderation state does not exist : ' . $state );
return null;
}
@@ -305,7 +314,7 @@ abstract class AbstractRevision {
} else {
// reset content length (we may be restoring, in which case $obj's
// current length will be 0)
- $obj->contentLength = mb_strlen( $this->getContent( 'wikitext' ) );
+ $obj->contentLength = $this->calculateContentLength();
}
return $obj;
@@ -313,7 +322,7 @@ abstract class AbstractRevision {
/**
* @param string $state
- * @return boolean
+ * @return bool
*/
public function isValidModerationState( $state ) {
return in_array( $state, self::$perms );
@@ -327,7 +336,7 @@ abstract class AbstractRevision {
}
/**
- * @return boolean
+ * @return bool
*/
public function hasHiddenContent() {
return $this->moderationState === self::MODERATED_HIDDEN;
@@ -345,18 +354,40 @@ abstract class AbstractRevision {
}
/**
+ * Checks whether the content is retrievable.
+ *
+ * False is an error state, used when the content is unretrievable, e.g. due to data loss (T95580)
+ * or a temporary database error.
+ *
+ * This is unrelated to whether the content is loaded on-demand.
+ *
+ * @return bool
+ */
+ public function isContentCurrentlyRetrievable() {
+ return $this->content !== false;
+ }
+
+ /**
* DO NOT USE THIS METHOD to output the content; use
* Templating::getContent, which will do additional (permissions-based)
* checks to make sure it outputs something the user can see.
*
- * @param string[optional] $format Format to output content in (html|wikitext)
+ * @param string[optional] $format Format to output content in (html|wikitext|topic-title-wikitext|topic-title-html|topic-title-plaintext)
* @return string
* @throws InvalidDataException
*/
public function getContent( $format = 'html' ) {
- if ( $this->content === false ) {
- throw new InvalidDataException( 'Failed to load the content' );
+ if ( !$this->isContentCurrentlyRetrievable() ) {
+ wfDebugLog( 'Flow', __METHOD__ . ': Failed to load the content of revision with rev_id ' . $this->revId->getAlphadecimal() );
+
+ $stubContent = wfMessage( 'flow-stub-post-content' )->parse();
+ if ( !in_array( $format, [ 'html', 'fixed-html' ] ) ) {
+ $stubContent = Sanitizer::stripAllTags( $stubContent );
+ }
+
+ return $stubContent;
}
+
if ( $this->xssCheck === false ) {
return '';
}
@@ -364,16 +395,13 @@ abstract class AbstractRevision {
$sourceFormat = $this->getContentFormat();
if ( $this->xssCheck === null && $sourceFormat === 'html' ) {
// returns true if no handler aborted the hook
- $this->xssCheck = Hooks::run( 'FlowCheckHtmlContentXss', array( $raw ) );
+ $this->xssCheck = Hooks::run( 'FlowCheckHtmlContentXss', [ $raw ] );
if ( !$this->xssCheck ) {
wfDebugLog( 'Flow', __METHOD__ . ': XSS check prevented display of revision ' . $this->revId->getAlphadecimal() );
return '';
}
}
- if ( !$this->isFormatted() ) {
- return $raw;
- }
if ( !isset( $this->convertedContent[$format] ) ) {
if ( $sourceFormat === $format ) {
$this->convertedContent[$format] = $raw;
@@ -391,6 +419,52 @@ abstract class AbstractRevision {
}
/**
+ * Gets the content in a wikitext format. In this class, it will be 'wikitext',
+ * but this can be overriden in sub-classes (e.g. to 'topic-title-wikitext' for topic titles).
+ *
+ * DO NOT USE THIS METHOD to output the content; use Templating::getContent for security reasons.
+ *
+ * @return string Text in a wikitext-based format.
+ */
+ public function getContentInWikitext() {
+ return $this->getContent( $this->getWikitextFormat() );
+ }
+
+ /**
+ * Gets a wikitext format that is suitable for this revision.
+ * In this class, it will be 'wikitext', but this can be overriden in sub-classes
+ * (e.g. to 'topic-title-wikitext' for topic titles).
+ *
+ * @return string Format name
+ */
+ public function getWikitextFormat() {
+ return 'wikitext';
+ }
+
+ /**
+ * Gets the content in an HTML format. In this class, it will be 'html',
+ * but this can be overriden in sub-classes (e.g. to 'topic-title-html' for topic titles).
+ *
+ * DO NOT USE THIS METHOD to output the content; use Templating::getContent for security reasons.
+ *
+ * @return string Text in an HTML-based format.
+ */
+ public function getContentInHtml() {
+ return $this->getContent( $this->getHtmlFormat() );
+ }
+
+ /**
+ * Gets an HTML format that is suitable for this revision.
+ * In this class, it will be 'html', but this can be overriden in sub-classes
+ * (e.g. to 'topic-title-html' for topic titles).
+ *
+ * @return string Format name
+ */
+ public function getHtmlFormat() {
+ return 'html';
+ }
+
+ /**
* @return UserTuple
*/
public function getUserTuple() {
@@ -398,7 +472,7 @@ abstract class AbstractRevision {
}
/**
- * @return integer
+ * @return int
*/
public function getUserId() {
return $this->user->id;
@@ -430,7 +504,7 @@ abstract class AbstractRevision {
* use self::setNextContent
*
* @param string $content
- * @param string $format wikitext|html
+ * @param string $format wikitext|html|topic-title-wikitext
* @param Title|null $title When null the related workflow will be lazy-loaded to locate the title
* @throws DataModelException
*/
@@ -447,28 +521,34 @@ abstract class AbstractRevision {
$title = $this->getCollection()->getTitle();
}
+ if ( $format !== 'wikitext' && $format !== 'html' && $format !== 'topic-title-wikitext' ) {
+ throw new DataModelException( 'Invalid format: Supported formats for new content are \'wikitext\', \'html\', and \'topic-title-wikitext\'' );
+ }
+
// never trust incoming html - roundtrip to wikitext first
- if ( $format !== 'wikitext' ) {
- $content = Utils::convert( $format, 'wikitext', $content, $title );
+ if ( $format === 'html' ) {
+ $content = Utils::convert( $format, 'wikitext', $content, $title );
$format = 'wikitext';
}
- // Run pre-save transform
- $content = ContentHandler::makeContent( $content, $title, CONTENT_MODEL_WIKITEXT )
- ->preSaveTransform(
- $title,
- $this->getUser(),
- WikiPage::factory( $title )->makeParserOptions( $this->getUser() )
- )
- ->serialize( 'text/x-wiki' );
+ if ( $format === 'wikitext' ) {
+ // Run pre-save transform
+ $content = ContentHandler::makeContent( $content, $title, CONTENT_MODEL_WIKITEXT )
+ ->preSaveTransform(
+ $title,
+ $this->getUser(),
+ WikiPage::factory( $title )->makeParserOptions( $this->getUser() )
+ )
+ ->serialize( 'text/x-wiki' );
+ }
// Keep consistent with normal edit page, trim only trailing whitespaces
$content = rtrim( $content );
- $this->convertedContent = array( $format => $content );
+ $this->convertedContent = [ $format => $content ];
// convert content to desired storage format
$storageFormat = $this->getStorageFormat();
- if ( $this->isFormatted() && $storageFormat !== $format ) {
+ if ( $storageFormat !== $format ) {
$this->convertedContent[$storageFormat] = Utils::convert( $format, $storageFormat, $content, $title );
}
@@ -479,7 +559,7 @@ abstract class AbstractRevision {
$this->flags = array_filter( explode( ',', \Revision::compressRevisionText( $this->content ) ) );
$this->flags[] = $storageFormat;
- $this->contentLength = mb_strlen( $this->getContent( 'wikitext' ) );
+ $this->contentLength = $this->calculateContentLength();
}
/**
@@ -487,7 +567,7 @@ abstract class AbstractRevision {
*
* @param User $user
* @param string $content
- * @param string $format wikitext|html
+ * @param string $format wikitext|html|topic-title-wikitext
* @param Title|null $title When null the related workflow will be lazy-loaded to locate the title
* @throws DataModelException
*/
@@ -495,7 +575,9 @@ abstract class AbstractRevision {
if ( $this->moderationState !== self::MODERATED_NONE ) {
throw new DataModelException( 'Cannot change content of restricted revision', 'process-data' );
}
- if ( $content !== $this->getContent() ) {
+
+ // Do we need this if check, or just the one in newNextRevision against the prior revision?
+ if ( $content !== $this->getContent( $format ) ) {
$this->content = null;
$this->setContent( $content, $format, $title );
$this->lastEditId = $this->getRevisionId();
@@ -504,19 +586,6 @@ abstract class AbstractRevision {
}
/**
- * Determines whether this revision contains formatted content
- * (i.e. content with separate HTML and WikiText representations)
- * or unformatted content (i.e. one plaintext representation)
- * Note that this function may return different values for different
- * instances of the same class.
- *
- * @return boolean True for formatted, False for plaintext
- */
- public function isFormatted() {
- return true;
- }
-
- /**
* @return string The content format of this revision
*/
public function getContentFormat() {
@@ -525,15 +594,14 @@ abstract class AbstractRevision {
/**
* Determines the appropriate format to store content in.
- * Usually, the default storage format, but if isFormatted() returns
- * false, then it will return 'wikitext'.
* NOTE: The format of the current content is retrieved with getContentFormat
*
* @return string The name of the storage format.
*/
protected function getStorageFormat() {
global $wgFlowContentFormat;
- return $this->isFormatted() ? $wgFlowContentFormat : 'wikitext';
+
+ return $wgFlowContentFormat;
}
/**
@@ -565,35 +633,35 @@ abstract class AbstractRevision {
}
/**
- * @return boolean
+ * @return bool
*/
public function isModerated() {
return $this->moderationState !== self::MODERATED_NONE;
}
/**
- * @return boolean
+ * @return bool
*/
public function isHidden() {
return $this->moderationState === self::MODERATED_HIDDEN;
}
/**
- * @return boolean
+ * @return bool
*/
public function isDeleted() {
return $this->moderationState === self::MODERATED_DELETED;
}
/**
- * @return boolean
+ * @return bool
*/
public function isSuppressed() {
return $this->moderationState === self::MODERATED_SUPPRESSED;
}
/**
- * @return boolean
+ * @return bool
*/
public function isLocked() {
return $this->moderationState === self::MODERATED_LOCKED;
@@ -608,10 +676,10 @@ abstract class AbstractRevision {
/**
* @param string|array $flags
- * @return boolean True when at least one flag in $flags is set
+ * @return bool True when at least one flag in $flags is set
*/
public function isFlaggedAny( $flags ) {
- foreach ( (array) $flags as $flag ) {
+ foreach ( (array)$flags as $flag ) {
if ( false !== array_search( $flag, $this->flags ) ) {
return true;
}
@@ -621,10 +689,10 @@ abstract class AbstractRevision {
/**
* @param string|array $flags
- * @return boolean
+ * @return bool
*/
public function isFlaggedAll( $flags ) {
- foreach ( (array) $flags as $flag ) {
+ foreach ( (array)$flags as $flag ) {
if ( false === array_search( $flag, $this->flags ) ) {
return false;
}
@@ -633,14 +701,14 @@ abstract class AbstractRevision {
}
/**
- * @return boolean
+ * @return bool
*/
public function isFirstRevision() {
return $this->prevRevision === null;
}
/**
- * @return boolean
+ * @return bool
*/
public function isOriginalContent() {
return $this->lastEditId === null;
@@ -661,7 +729,7 @@ abstract class AbstractRevision {
}
/**
- * @return integer
+ * @return int
*/
public function getLastContentEditUserId() {
return $this->lastEditUser ? $this->lastEditUser->id : null;
@@ -689,7 +757,7 @@ abstract class AbstractRevision {
}
/**
- * @return integer|null
+ * @return int|null
*/
public function getModeratedByUserId() {
return $this->moderatedBy ? $this->moderatedBy->id : null;
@@ -709,15 +777,46 @@ abstract class AbstractRevision {
return $this->moderatedBy ? $this->moderatedBy->wiki : null;
}
+ public static function getModerationChangeTypes() {
+ if ( self::$moderationChangeTypes === null ) {
+ self::$moderationChangeTypes = [];
+ foreach ( self::$perms as $perm ) {
+ if ( $perm != '' ) {
+ self::$moderationChangeTypes[] = "{$perm}-topic";
+ self::$moderationChangeTypes[] = "{$perm}-post";
+ }
+ }
+
+ self::$moderationChangeTypes[] = 'restore-topic';
+ self::$moderationChangeTypes[] = 'restore-post';
+ }
+
+ return self::$moderationChangeTypes;
+ }
+
+ public function isModerationChange() {
+ return in_array( $this->getChangeType(), self::getModerationChangeTypes() );
+ }
+
/**
- * @return integer
+ * @return int
*/
public function getContentLength() {
return $this->contentLength;
}
+ // Only public for FlowUpdateRevisionContentLength.
/**
- * @return integer
+ * Determines the content length by measuring the actual content.
+ *
+ * @return int
+ */
+ public function calculateContentLength() {
+ return mb_strlen( $this->getContentInWikitext() );
+ }
+
+ /**
+ * @return int
*/
public function getPreviousContentLength() {
return $this->previousContentLength;
@@ -743,12 +842,12 @@ abstract class AbstractRevision {
}
$namespace = $title->getNamespace();
- $conditions = array(
+ $conditions = [
'rc_title' => $title->getDBkey(),
'rc_timestamp' => $timestamp,
'rc_namespace' => $namespace
- );
- $options = array( 'USE INDEX' => 'rc_timestamp' );
+ ];
+ $options = [ 'USE INDEX' => 'rc_timestamp' ];
$dbr = wfGetDB( DB_SLAVE );
$rows = $dbr->select( 'recentchanges', RecentChange::selectFields(), $conditions, __METHOD__, $options );
@@ -764,7 +863,9 @@ abstract class AbstractRevision {
// it is possible that more than 1 changes on the same page have the same timestamp
// the revision id is hidden in rc_params['flow-workflow-change']['revision']
$revId = $this->revId->getAlphadecimal();
+ // @codingStandardsIgnoreStart
while ( $row = $rows->next() ) {
+ // @codingStandardsIgnoreEnd
$rc = RecentChange::newFromRow( $row );
$params = $rc->parseParams();
if ( $params && $params['flow-workflow-change']['revision'] === $revId ) {
@@ -793,7 +894,7 @@ abstract class AbstractRevision {
/**
* Get the user ID of the user who created this summary.
*
- * @return integer The user ID
+ * @return int The user ID
*/
public function getCreatorId() {
return $this->getCreatorTuple()->id;
@@ -817,6 +918,15 @@ abstract class AbstractRevision {
}
/**
+ * @param AbstractRevision $revision
+ * @return bool
+ * @throws InvalidDataException
+ */
+ protected function hasSameContentAs( AbstractRevision $revision ) {
+ return $this->getContentInWikitext() === $revision->getContentInWikitext();
+ }
+
+ /**
* @return string
*/
abstract public function getRevisionType();
diff --git a/Flow/includes/Model/AbstractSummary.php b/Flow/includes/Model/AbstractSummary.php
index ad12d647..9f270ffd 100644
--- a/Flow/includes/Model/AbstractSummary.php
+++ b/Flow/includes/Model/AbstractSummary.php
@@ -14,7 +14,7 @@ abstract class AbstractSummary extends AbstractRevision {
*/
protected $summaryTargetId;
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
/** @var $obj AbstractSummary */
$obj = parent::fromStorageRow( $row, $obj );
$obj->summaryTargetId = UUID::create( $row['rev_type_id'] );
diff --git a/Flow/includes/Model/Anchor.php b/Flow/includes/Model/Anchor.php
index d64e26d7..bdf8a747 100644
--- a/Flow/includes/Model/Anchor.php
+++ b/Flow/includes/Model/Anchor.php
@@ -23,7 +23,7 @@ class Anchor implements ApiSerializable {
/**
* Message used for the HTML title attribute of the anchor
*
- * @var Message $titleMessage
+ * @var Message
*/
protected $titleMessage;
@@ -37,7 +37,7 @@ class Anchor implements ApiSerializable {
/**
* @var array
*/
- public $query = array();
+ public $query = [];
/**
* @var string
@@ -51,7 +51,7 @@ class Anchor implements ApiSerializable {
* @param string|null $fragment URL fragment of the anchor
* @param Message|string $htmlTitleMessage Title text of anchor
*/
- public function __construct( $message, Title $title, array $query = array(), $fragment = null, $htmlTitleMessage = null ) {
+ public function __construct( $message, Title $title, array $query = [], $fragment = null, $htmlTitleMessage = null ) {
$this->title = $title;
$this->query = $query;
$this->fragment = $fragment;
@@ -106,20 +106,20 @@ class Anchor implements ApiSerializable {
// Should we instead use Linker?
return Html::element(
'a',
- array(
+ [
'href' => $this->getLinkURL(),
'title' => $titleText,
- ),
+ ],
$content === null ? $text : $content
);
}
public function toArray() {
- return array(
+ return [
'url' => $this->getLinkURL(),
'title' => $this->getTitleMessage()->text(), // Title text
'text' => $this->message->text(), // Main text of link
- );
+ ];
}
/**
@@ -138,7 +138,7 @@ class Anchor implements ApiSerializable {
/**
* Canonicalizes and returns a message, or null if null was provided
*
- * @param Message|string $message Message object, or text content, or null
+ * @param Message|string $rawMessage Message object, or text content, or null
* @return Message|null
*/
protected function buildMessage( $rawMessage ) {
diff --git a/Flow/includes/Model/Header.php b/Flow/includes/Model/Header.php
index a0cd5b63..d1cfdcb1 100644
--- a/Flow/includes/Model/Header.php
+++ b/Flow/includes/Model/Header.php
@@ -25,7 +25,7 @@ class Header extends AbstractRevision {
* @param string[optional] $changeType
* @return Header
*/
- static public function create( Workflow $workflow, User $user, $content, $format, $changeType = 'create-header' ) {
+ public static function create( Workflow $workflow, User $user, $content, $format, $changeType = 'create-header' ) {
$obj = new self;
$obj->revId = UUID::create();
$obj->workflowId = $workflow->getId();
@@ -41,7 +41,7 @@ class Header extends AbstractRevision {
* @param Header|null $obj
* @return Header
*/
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
/** @var $obj Header */
$obj = parent::fromStorageRow( $row, $obj );
$obj->workflowId = UUID::create( $row['rev_type_id'] );
diff --git a/Flow/includes/Model/HtmlRenderingInformation.php b/Flow/includes/Model/HtmlRenderingInformation.php
new file mode 100644
index 00000000..a6dfc315
--- /dev/null
+++ b/Flow/includes/Model/HtmlRenderingInformation.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Flow\Model;
+
+use ApiSerializable;
+
+/**
+ * Represents an HTML snippet, and associated information needed to render it
+ */
+class HtmlRenderingInformation implements ApiSerializable {
+ /**
+ * Main HTML
+ *
+ * @var string
+ */
+ protected $html;
+
+ /**
+ * Array of ResourceLoader module names
+ *
+ * @var array
+ */
+ protected $modules;
+
+ /**
+ * Array of ResourceLoader module names to be included as style-only modules.
+ *
+ * @var array
+ */
+ protected $moduleStyles;
+
+ /**
+ * Array of head items (see OutputPage::addHeadItems), as an array
+ * of raw HTML strings.
+ *
+ * @var array
+ */
+ protected $headItems;
+
+ /**
+ * @param string $html
+ * @param array $modules
+ * @param array $moduleStyles
+ * @param array $headItems
+ */
+ public function __construct( $html, array $modules, array $moduleStyles, array $headItems ) {
+ $this->html = $html;
+ $this->modules = $modules;
+ $this->moduleStyles = $moduleStyles;
+ $this->headItems = $headItems;
+ }
+
+ public function getHtml() {
+ return $this->html;
+ }
+
+ public function getModules() {
+ return $this->modules;
+ }
+
+ public function getModuleStyles() {
+ return $this->moduleStyles;
+ }
+
+ public function getHeadItems() {
+ return $this->headItems;
+ }
+
+ /**
+ * @return array
+ */
+ public function serializeForApiResult() {
+ return $this->toArray();
+ }
+
+ /**
+ * Constructs the object from an associative array
+ *
+ * @param array $info With following keys:
+ * - string $info['html']
+ * - array (optional) $info['modules']
+ * - array (optional) $info['modulestyles']
+ * - array (optional) $info['headitems']
+ */
+ public static function fromArray( array $info ) {
+ return new HtmlRenderingInformation(
+ $info['html'],
+ isset( $info['modules'] ) ? $info['modules'] : [],
+ isset( $info['modulestyles'] ) ? $info['modulestyles'] : [],
+ isset( $info['headitems'] ) ? $info['headitems'] : []
+ );
+ }
+
+ public function toArray() {
+ return [
+ 'html' => $this->html,
+ 'modules' => $this->modules,
+ 'modulestyles' => $this->moduleStyles,
+ 'headitems' => $this->headItems,
+ ];
+ }
+}
diff --git a/Flow/includes/Model/PostRevision.php b/Flow/includes/Model/PostRevision.php
index cac5c9cd..774443e1 100644
--- a/Flow/includes/Model/PostRevision.php
+++ b/Flow/includes/Model/PostRevision.php
@@ -54,17 +54,18 @@ class PostRevision extends AbstractRevision {
*
* @param Workflow $topic
* @param User $user
- * @param string $content The title of the topic(they are Collection as well)
- * @param string $format wikitext|html
+ * @param string $content The title of the topic (they are Collection as well), in
+ * topic-title-wikitext format.
* @return PostRevision
*/
- static public function create( Workflow $topic, User $user, $content, $format ) {
+ public static function createTopicPost( Workflow $topic, User $user, $content ) {
+ $format = 'topic-title-wikitext';
$obj = static::newFromId( $topic->getId(), $user, $content, $format, $topic->getArticleTitle() );
$obj->changeType = 'new-post';
// A newly created post has no children, a depth of 0, and
// is the root of its tree.
- $obj->setChildren( array() );
+ $obj->setChildren( [] );
$obj->setDepth( 0 );
$obj->rootPost = $obj;
@@ -95,7 +96,7 @@ class PostRevision extends AbstractRevision {
* @param Title|null $title
* @return PostRevision
*/
- static public function newFromId( UUID $uuid, User $user, $content, $format, Title $title = null ) {
+ public static function newFromId( UUID $uuid, User $user, $content, $format, Title $title = null ) {
$obj = new self;
$obj->revId = UUID::create();
$obj->postId = $uuid;
@@ -111,17 +112,17 @@ class PostRevision extends AbstractRevision {
}
/**
- * @var string[] $row
- * @var PostRevision|null $obj
+ * @param string[] $row
+ * @param PostRevision|null $obj
* @return PostRevision
* @throws DataModelException
*/
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
/** @var $obj PostRevision */
$obj = parent::fromStorageRow( $row, $obj );
$treeRevId = UUID::create( $row['tree_rev_id'] );
- if ( ! $obj->revId->equals( $treeRevId ) ) {
+ if ( !$obj->revId->equals( $treeRevId ) ) {
$treeRevIdStr = ( $treeRevId !== null )
? $treeRevId->getAlphadecimal()
: var_export( $row['tree_rev_id'], true );
@@ -132,7 +133,7 @@ class PostRevision extends AbstractRevision {
'process-data'
);
}
- $obj->replyToId = UUID::create( $row['tree_parent_id'] );
+ $obj->replyToId = $row['tree_parent_id'] ? UUID::create( $row['tree_parent_id'] ) : null;
$obj->postId = UUID::create( $row['rev_type_id'] );
$obj->origUser = UserTuple::newFromArray( $row, 'tree_orig_user_' );
if ( !$obj->origUser ) {
@@ -145,8 +146,8 @@ class PostRevision extends AbstractRevision {
* @param PostRevision $rev
* @return string[]
*/
- static public function toStorageRow( $rev ) {
- return parent::toStorageRow( $rev ) + array(
+ public static function toStorageRow( $rev ) {
+ return parent::toStorageRow( $rev ) + [
'tree_parent_id' => $rev->replyToId ? $rev->replyToId->getAlphadecimal() : null,
'tree_rev_descendant_id' => $rev->postId->getAlphadecimal(),
'tree_rev_id' => $rev->revId->getAlphadecimal(),
@@ -154,7 +155,7 @@ class PostRevision extends AbstractRevision {
'tree_orig_user_id' => $rev->origUser->id,
'tree_orig_user_ip' => $rev->origUser->ip,
'tree_orig_user_wiki' => $rev->origUser->wiki,
- );
+ ];
}
/**
@@ -178,7 +179,7 @@ class PostRevision extends AbstractRevision {
$reply->replyToId = $this->postId;
$reply->setContent( $content, $format, $workflow->getArticleTitle() );
$reply->changeType = $changeType;
- $reply->setChildren( array() );
+ $reply->setChildren( [] );
$reply->setDepth( $this->getDepth() + 1 );
$reply->rootPost = $this->rootPost;
@@ -200,12 +201,61 @@ class PostRevision extends AbstractRevision {
}
/**
- * @return boolean
+ * @return bool
*/
public function isTopicTitle() {
return $this->replyToId === null;
}
+ public function getContentFormat() {
+ // The canonical format must always be topic-title-wikitext, because we
+ // can not convert 'topic-title-html' to 'topic-title-wikitext'.
+ if ( $this->isTopicTitle() ) {
+ return 'topic-title-wikitext';
+ } else {
+ return parent::getContentFormat();
+ }
+ }
+
+ /**
+ * Gets the desired storage format.
+ *
+ * @return string
+ */
+ protected function getStorageFormat() {
+ if ( $this->isTopicTitle() ) {
+ return 'topic-title-wikitext';
+ } else {
+ return parent::getStorageFormat();
+ }
+ }
+
+ /**
+ * Gets the appropriate wikitext format string for this revision.
+ *
+ * @return string 'wikitext' or 'topic-title-wikitext'
+ */
+ public function getWikitextFormat() {
+ if ( $this->isTopicTitle() ) {
+ return 'topic-title-wikitext';
+ } else {
+ return parent::getWikitextFormat();
+ }
+ }
+
+ /**
+ * Gets the appropriate HTML format string for this revision.
+ *
+ * @return string 'html' or 'topic-title-html'
+ */
+ public function getHtmlFormat() {
+ if ( $this->isTopicTitle() ) {
+ return 'topic-title-html';
+ } else {
+ return parent::getHtmlFormat();
+ }
+ }
+
/**
* @param UUID|null $id
*/
@@ -243,14 +293,14 @@ class PostRevision extends AbstractRevision {
}
/**
- * @param integer $depth
+ * @param int $depth
*/
public function setDepth( $depth ) {
$this->depth = (int)$depth;
}
/**
- * @return integer
+ * @return int
* @throws DataModelException
*/
public function getDepth() {
@@ -335,15 +385,8 @@ class PostRevision extends AbstractRevision {
}
/**
- * @return boolean Posts are unformatted if they are title posts, formatted otherwise.
- */
- public function isFormatted() {
- return !$this->isTopicTitle();
- }
-
- /**
* @param User $user
- * @return boolean
+ * @return bool
*/
public function isCreator( User $user ) {
if ( $user->isAnon() ) {
diff --git a/Flow/includes/Model/PostSummary.php b/Flow/includes/Model/PostSummary.php
index 9a5aa0e9..a346ad55 100644
--- a/Flow/includes/Model/PostSummary.php
+++ b/Flow/includes/Model/PostSummary.php
@@ -17,7 +17,7 @@ class PostSummary extends AbstractSummary {
* @param string $changeType
* @return PostSummary
*/
- static public function create( Title $title, PostRevision $post, User $user, $content, $format, $changeType ) {
+ public static function create( Title $title, PostRevision $post, User $user, $content, $format, $changeType ) {
$obj = new self;
$obj->revId = UUID::create();
$obj->user = UserTuple::newFromUser( $user );
diff --git a/Flow/includes/Model/Reference.php b/Flow/includes/Model/Reference.php
index 88539540..f3f330c7 100644
--- a/Flow/includes/Model/Reference.php
+++ b/Flow/includes/Model/Reference.php
@@ -2,7 +2,7 @@
namespace Flow\Model;
-use Flow\Exception\InvalidReferenceException;
+use Flow\Exception\InvalidParameterException;
use Title;
abstract class Reference {
@@ -11,6 +11,11 @@ abstract class Reference {
/**
* @var UUID
*/
+ protected $id;
+
+ /**
+ * @var UUID
+ */
protected $workflowId;
/**
@@ -38,20 +43,22 @@ abstract class Reference {
*/
protected $wikiId;
- protected $validTypes = array( self::TYPE_LINK );
+ protected $validTypes = [ self::TYPE_LINK ];
/**
* Standard constructor. Called from subclasses only
*
- * @param String $wiki Wiki ID of the reference source
- * @param UUID $srcWorkflow Source Workflow's ID
- * @param Title $srcTitle Title of the Workflow from which this reference comes.
- * @param String $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
- * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
- * @param string $type The type of reference
- * @throws InvalidReferenceException
- */
- protected function __construct( $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type ) {
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
+ * @param UUID $srcWorkflow Source Workflow's ID
+ * @param Title $srcTitle Title of the Workflow from which this reference comes.
+ * @param string $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
+ * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
+ * @param string $type The type of reference
+ * @throws InvalidParameterException
+ */
+ protected function __construct( UUID $id, $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type ) {
+ $this->id = $id;
$this->wikiId = $wiki;
$this->workflowId = $srcWorkflow;
$this->objectType = $objectType;
@@ -60,7 +67,7 @@ abstract class Reference {
$this->srcTitle = $srcTitle;
if ( !in_array( $type, $this->validTypes ) ) {
- throw new InvalidReferenceException(
+ throw new InvalidParameterException(
"Invalid type $type specified for reference " . get_class( $this )
);
}
@@ -124,7 +131,8 @@ abstract class Reference {
* @return array
*/
public function getStorageRow() {
- return array(
+ return [
+ 'ref_id' => $this->id->getAlphadecimal(),
'ref_src_wiki' => $this->wikiId,
'ref_src_workflow_id' => $this->workflowId->getAlphadecimal(),
'ref_src_namespace' => $this->srcTitle->getNamespace(),
@@ -132,7 +140,7 @@ abstract class Reference {
'ref_src_object_type' => $this->objectType,
'ref_src_object_id' => $this->objectId->getAlphadecimal(),
'ref_type' => $this->type,
- );
+ ];
}
/**
@@ -145,13 +153,12 @@ abstract class Reference {
}
public function getUniqueIdentifier() {
- return $this->getSrcTitle() . '|' .
- $this->getObjectType() . '|' .
- $this->getObjectId()->getAlphadecimal() . '|' .
- $this->getIdentifier();
+ return $this->getSrcTitle() . '|' .
+ $this->getObjectType() . '|' .
+ $this->getObjectId()->getAlphadecimal() . '|' .
+ $this->getIdentifier();
}
-
/**
* We don't have a real PK (see comment in
* ReferenceClarifier::loadReferencesForPage) but I'll do a array_unique on
diff --git a/Flow/includes/Model/TopicListEntry.php b/Flow/includes/Model/TopicListEntry.php
index 89d1cbbf..b323fab5 100644
--- a/Flow/includes/Model/TopicListEntry.php
+++ b/Flow/includes/Model/TopicListEntry.php
@@ -27,7 +27,7 @@ class TopicListEntry {
* @param Workflow $topic
* @return TopicListEntry
*/
- static public function create( Workflow $topicList, Workflow $topic ) {
+ public static function create( Workflow $topicList, Workflow $topic ) {
$obj = new self;
$obj->topicListId = $topicList->getId();
$obj->topicId = $topic->getId();
@@ -41,7 +41,7 @@ class TopicListEntry {
* @return TopicListEntry
* @throws DataModelException
*/
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
if ( $obj === null ) {
$obj = new self;
} elseif ( !$obj instanceof self ) {
@@ -59,11 +59,11 @@ class TopicListEntry {
* @param TopicListEntry $obj
* @return array
*/
- static public function toStorageRow( TopicListEntry $obj ) {
- $row = array(
+ public static function toStorageRow( TopicListEntry $obj ) {
+ $row = [
'topic_list_id' => $obj->topicListId->getAlphadecimal(),
'topic_id' => $obj->topicId->getAlphadecimal(),
- );
+ ];
if ( $obj->topicWorkflowLastUpdated ) {
$row['workflow_last_update_timestamp'] = $obj->topicWorkflowLastUpdated;
}
@@ -91,4 +91,3 @@ class TopicListEntry {
return $this->topicWorkflowLastUpdated;
}
}
-
diff --git a/Flow/includes/Model/URLReference.php b/Flow/includes/Model/URLReference.php
index 16b4cf5d..86f247c0 100644
--- a/Flow/includes/Model/URLReference.php
+++ b/Flow/includes/Model/URLReference.php
@@ -9,16 +9,17 @@ class URLReference extends Reference {
protected $url;
/**
- * @param String $wiki Wiki ID of the reference source
- * @param UUID $srcWorkflow ID of the source Workflow
- * @param Title $srcTitle Title of the page that the Workflow exists on
- * @param String $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
- * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
- * @param string $type Type of reference
- * @param string $url URL of the reference's target.
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
+ * @param UUID $srcWorkflow ID of the source Workflow
+ * @param Title $srcTitle Title of the page that the Workflow exists on
+ * @param string $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
+ * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
+ * @param string $type Type of reference
+ * @param string $url URL of the reference's target.
* @throws InvalidReferenceException
*/
- public function __construct( $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type, $url ) {
+ public function __construct( UUID $id, $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type, $url ) {
$this->url = $url;
if ( !is_array( wfParseUrl( $url ) ) ) {
@@ -27,7 +28,7 @@ class URLReference extends Reference {
);
}
- parent::__construct( $wiki, $srcWorkflow, $srcTitle, $objectType, $objectId, $type );
+ parent::__construct( $id, $wiki, $srcWorkflow, $srcTitle, $objectType, $objectId, $type );
}
/**
@@ -36,29 +37,30 @@ class URLReference extends Reference {
* @return array
*/
public function getStorageRow() {
- return parent::getStorageRow() + array(
+ return parent::getStorageRow() + [
'ref_target' => $this->url,
- );
+ ];
}
/**
* Instantiates a URLReference object from a storage row.
*
- * @param \StdClass $row
+ * @param array $row
* @return URLReference
*/
public static function fromStorageRow( $row ) {
- global $wgFlowMigrateReferenceWiki;
-
+ // TODO: Remove this UUID::create() call when the field is populated
+ // everywhere relevant.
+ $id = ( !isset( $row['ref_id'] ) || $row['ref_id'] === null ) ? UUID::create() : UUID::create( $row['ref_id'] );
$workflow = UUID::create( $row['ref_src_workflow_id'] );
$objectType = $row['ref_src_object_type'];
$objectId = UUID::create( $row['ref_src_object_id'] );
$url = $row['ref_target'];
$type = $row['ref_type'];
$srcTitle = Title::makeTitle( $row['ref_src_namespace'], $row['ref_src_title'] );
- $wiki = $wgFlowMigrateReferenceWiki ? null : $row['ref_src_wiki'];
+ $wiki = $row['ref_src_wiki'];
- return new URLReference( $wiki, $workflow, $srcTitle, $objectType, $objectId, $type, $url );
+ return new URLReference( $id, $wiki, $workflow, $srcTitle, $objectType, $objectId, $type, $url );
}
/**
diff --git a/Flow/includes/Model/UUID.php b/Flow/includes/Model/UUID.php
index 16d951f7..7109fca8 100644
--- a/Flow/includes/Model/UUID.php
+++ b/Flow/includes/Model/UUID.php
@@ -6,11 +6,12 @@ use ApiSerializable;
use Blob;
use Flow\Data\ObjectManager;
use Flow\Exception\FlowException;
+use Flow\Exception\InvalidParameterException;
use Flow\Exception\InvalidInputException;
use Language;
use MWTimestamp;
-use TimestampException;
use User;
+use Wikimedia\Timestamp\TimestampException;
/**
* Immutable class modeling timestamped UUID's from
@@ -83,11 +84,13 @@ class UUID implements ApiSerializable {
* @param string $value UUID value
* @param string $format UUID format (static::INPUT_BIN, static::input_HEX
* or static::input_ALNUM)
+ * @throws InvalidParameterException On logic error, or for an invalid UUID string
+ * in a format not used directly by end-users
* @throws InvalidInputException
*/
protected function __construct( $value, $format ) {
- if ( !in_array( $format, array( static::INPUT_BIN, static::INPUT_HEX, static::INPUT_ALNUM ) ) ) {
- throw new InvalidInputException( 'Invalid UUID input format: ' . $format, 'invalid-input' );
+ if ( !in_array( $format, [ static::INPUT_BIN, static::INPUT_HEX, static::INPUT_ALNUM ] ) ) {
+ throw new InvalidParameterException( 'Invalid UUID input format: ' . $format );
}
// doublecheck validity of inputs, based on pre-determined lengths
@@ -117,7 +120,7 @@ class UUID implements ApiSerializable {
public function __sleep() {
// ensure alphadecimal is populated
$this->getAlphadecimal();
- return array( 'alphadecimalValue' );
+ return [ 'alphadecimalValue' ];
}
public function __wakeup() {
@@ -146,7 +149,7 @@ class UUID implements ApiSerializable {
* @return UUID|null
* @throws InvalidInputException
*/
- static public function create( $input = false ) {
+ public static function create( $input = false ) {
// Most calls to UUID::create are binary strings, check string first
if ( is_string( $input ) || is_int( $input ) || $input === false ) {
if ( $input === false ) {
@@ -172,7 +175,7 @@ class UUID implements ApiSerializable {
$type = static::INPUT_HEX;
} elseif ( is_numeric( $input ) ) {
// convert base 10 to base 16 and pad to HEX_LEN with 0's
- $value = wfBaseConvert( $input, 10, 16, self::HEX_LEN );
+ $value = \Wikimedia\base_convert( $input, 10, 16, self::HEX_LEN );
$type = static::INPUT_HEX;
} else {
throw new InvalidInputException( 'Unknown input to UUID class', 'invalid-input' );
@@ -184,18 +187,18 @@ class UUID implements ApiSerializable {
return new static( $value, $type );
}
}
- } else if ( is_object( $input ) ) {
+ } elseif ( is_object( $input ) ) {
if ( $input instanceof UUID ) {
return $input;
} elseif ( $input instanceof Blob ) {
return self::create( $input->fetch() );
} else {
- throw new InvalidInputException( 'Unknown input of type ' . get_class( $input ), 'invalid-input' );
+ throw new InvalidParameterException( 'Unknown input of type ' . get_class( $input ) );
}
} elseif ( $input === null ) {
return null;
} else {
- throw new InvalidInputException( 'Unknown input type to UUID class: ' . gettype( $input ), 'invalid-input' );
+ throw new InvalidParameterException( 'Unknown input type to UUID class: ' . gettype( $input ) );
}
}
@@ -242,6 +245,7 @@ class UUID implements ApiSerializable {
* in conjunction with LOWER(HEX('...')) in MySQL.
*
* @return string
+ * @throws FlowException
*/
public function getHex() {
if ( $this->hexValue !== null ) {
@@ -250,6 +254,8 @@ class UUID implements ApiSerializable {
$this->hexValue = static::bin2hex( $this->binaryValue );
} elseif ( $this->alphadecimalValue !== null ) {
$this->hexValue = static::alnum2hex( $this->alphadecimalValue );
+ } else {
+ throw new FlowException( 'No binary, hex or alphadecimal value available' );
}
self::$instances[self::INPUT_HEX][$this->hexValue] = $this;
return $this->hexValue;
@@ -257,17 +263,26 @@ class UUID implements ApiSerializable {
/**
* @return string base 36 representation
+ * @throws FlowException
*/
public function getAlphadecimal() {
if ( $this->alphadecimalValue !== null ) {
return $this->alphadecimalValue;
} elseif ( $this->hexValue !== null ) {
- $this->alphadecimalValue = static::hex2alnum( $this->hexValue );
+ $alnum = static::hex2alnum( $this->hexValue );
} elseif ( $this->binaryValue !== null ) {
$this->hexValue = static::bin2hex( $this->binaryValue );
self::$instances[self::INPUT_HEX][$this->hexValue] = $this;
- $this->alphadecimalValue = static::hex2alnum( $this->hexValue );
+ $alnum = static::hex2alnum( $this->hexValue );
+ } else {
+ throw new FlowException( 'No binary, hex or alphadecimal value available' );
}
+
+ // pad some zeroes because (if initialized via ::getComparisonUUID) it
+ // could end up shorted than MIN_ALNUM_LEN, and whatever we output here
+ // should be able to feed into ::create again
+ $this->alphadecimalValue = str_pad( $alnum, static::MIN_ALNUM_LEN, '0', STR_PAD_LEFT );
+
self::$instances[self::INPUT_ALNUM][$this->alphadecimalValue] = $this;
return $this->alphadecimalValue;
}
@@ -305,7 +320,7 @@ class UUID implements ApiSerializable {
* @param User|null $user
* @param Language|null $lang
* @return string|false
- * @throws InvalidInputException
+ * @throws InvalidParameterException
*/
public function getHumanTimestamp( $relativeTo = null, User $user = null, Language $lang = null ) {
if ( $relativeTo instanceof UUID ) {
@@ -313,7 +328,7 @@ class UUID implements ApiSerializable {
} elseif ( $relativeTo instanceof MWTimestamp ) {
$rel = $relativeTo;
} else {
- throw new InvalidInputException( 'Expected MWTimestamp or UUID, got ' . get_class( $relativeTo ), 'invalid-input' );
+ throw new InvalidParameterException( 'Expected MWTimestamp or UUID, got ' . get_class( $relativeTo ) );
}
$ts = $this->getTimestampObj();
return $ts ? $ts->getHumanTimestamp( $rel, $user, $lang ) : false;
@@ -330,11 +345,11 @@ class UUID implements ApiSerializable {
*/
public static function convertUUIDs( $array, $format = 'binary' ) {
$array = ObjectManager::makeArray( $array );
- foreach( $array as $key => $value ) {
+ foreach ( $array as $key => $value ) {
if ( $value instanceof UUIDBlob ) {
// database encoded binary value
if ( $format === 'alphadecimal' ) {
- $array[$key] = UUID::create( $value->fetch() )->getAlphadecimal();
+ $array[$key] = self::create( $value->fetch() )->getAlphadecimal();
}
} elseif ( $value instanceof UUID ) {
if ( $format === 'binary' ) {
@@ -346,17 +361,13 @@ class UUID implements ApiSerializable {
// things that look like uuids
$len = strlen( $value );
if ( $format === 'alphadecimal' && $len === self::BIN_LEN ) {
- $array[$key] = UUID::create( $value )->getAlphadecimal();
+ $array[$key] = self::create( $value )->getAlphadecimal();
} elseif ( $format === 'binary' && (
( $len >= self::MIN_ALNUM_LEN && $len <= self::ALNUM_LEN )
||
$len === self::HEX_LEN
) ) {
- // Note that if a value is a binary string, but needs to be encoded
- // for the database, that is unhandled here. A patch is under
- // consideration to allow binary data to always be wrapped in a Blob
- // to clear up this inconsistency.
- $array[$key] = UUID::create( $value )->getBinary();
+ $array[$key] = self::create( $value )->getBinary();
}
}
}
@@ -366,7 +377,7 @@ class UUID implements ApiSerializable {
/**
* @param UUID|null $other
- * @return boolean
+ * @return bool
*/
public function equals( UUID $other = null ) {
return $other && $other->getAlphadecimal() === $this->getAlphadecimal();
@@ -375,7 +386,7 @@ class UUID implements ApiSerializable {
/**
* Generates a fake UUID for a given timestamp that will have comparison
* results equivalent to a real UUID generated at that time
- * @param mixed $ts Something accepted by wfTimestamp()
+ * @param mixed $ts Something accepted by wfTimestamp()
* @return UUID object.
*/
public static function getComparisonUUID( $ts ) {
@@ -384,11 +395,11 @@ class UUID implements ApiSerializable {
// and pad the remaining characters with zeroes.
$millitime = wfTimestamp( TS_UNIX, $ts ) * 1000;
// base 10 -> base 2, taking 46 bits
- $timestampBinary = wfBaseConvert( $millitime, 10, 2, 46 );
+ $timestampBinary = \Wikimedia\base_convert( $millitime, 10, 2, 46 );
// pad out the 46 bits to binary len with 0's
$uuidBase2 = str_pad( $timestampBinary, self::BIN_LEN * 8, '0', STR_PAD_RIGHT );
// base 2 -> base 16
- $uuidHex = wfBaseConvert( $uuidBase2, 2, 16, self::HEX_LEN );
+ $uuidHex = \Wikimedia\base_convert( $uuidBase2, 2, 16, self::HEX_LEN );
return self::create( $uuidHex );
}
@@ -410,7 +421,7 @@ class UUID implements ApiSerializable {
* @return string
*/
public static function alnum2hex( $alnum ) {
- return str_pad( wfBaseConvert( $alnum, 36, 16 ), self::HEX_LEN, '0', STR_PAD_LEFT );
+ return str_pad( \Wikimedia\base_convert( $alnum, 36, 16 ), self::HEX_LEN, '0', STR_PAD_LEFT );
}
/**
@@ -430,7 +441,7 @@ class UUID implements ApiSerializable {
* @return string
*/
public static function hex2alnum( $hex ) {
- return wfBaseConvert( $hex, 16, 36 );
+ return \Wikimedia\base_convert( $hex, 16, 36 );
}
/**
@@ -438,7 +449,7 @@ class UUID implements ApiSerializable {
* been generated with \UIDGenerator::newTimestampedUID88.
*
* @param string $hex
- * @return integer Number of seconds since epoch
+ * @return int Number of seconds since epoch
*/
public static function hex2timestamp( $hex ) {
$msTimestamp = hexdec( substr( $hex, 0, 12 ) ) >> 2;
diff --git a/Flow/includes/Model/UserTuple.php b/Flow/includes/Model/UserTuple.php
index dcfc0a74..7f1f599f 100644
--- a/Flow/includes/Model/UserTuple.php
+++ b/Flow/includes/Model/UserTuple.php
@@ -13,23 +13,23 @@ use User;
*/
class UserTuple {
/**
- * @param string The wiki the user belongs to
+ * @var string The wiki the user belongs to
*/
public $wiki;
/**
- * @param integer The id of the user, or 0 for anonymous
+ * @var int The id of the user, or 0 for anonymous
*/
public $id;
/**
- * @param string|null The ip of the user, null if logged in.
+ * @var string|null The ip of the user, null if logged in.
*/
public $ip;
/**
* @param string $wiki The wiki the user belongs to
- * @param integer|string $id The id of the user, or 0 for anonymous
+ * @param int|string $id The id of the user, or 0 for anonymous
* @param string|null $ip The ip of the user, blank string for no ip.
* null special case pass-through to be removed.
* @throws InvalidDataException
@@ -64,7 +64,7 @@ class UserTuple {
public static function newFromUser( User $user ) {
return new self(
- wfWikiId(),
+ wfWikiID(),
$user->getId(),
$user->isAnon() ? $user->getName() : null
);
@@ -88,15 +88,15 @@ class UserTuple {
}
public function toArray( $prefix = '' ) {
- return array(
+ return [
"{$prefix}wiki" => $this->wiki,
"{$prefix}id" => $this->id,
"{$prefix}ip" => $this->ip
- );
+ ];
}
public function createUser() {
- if ( $this->wiki !== wfWikiId() ) {
+ if ( $this->wiki !== wfWikiID() ) {
throw new CrossWikiException( 'Can only retrieve same-wiki users' );
}
if ( $this->id ) {
diff --git a/Flow/includes/Model/WikiReference.php b/Flow/includes/Model/WikiReference.php
index 2973d70f..83981797 100644
--- a/Flow/includes/Model/WikiReference.php
+++ b/Flow/includes/Model/WikiReference.php
@@ -13,26 +13,27 @@ class WikiReference extends Reference {
protected $target;
/**
- * @param String $wiki Wiki ID of the reference source
- * @param UUID $srcWorkflow ID of the source Workflow
- * @param Title $srcTitle Title of the Workflow from which this reference comes.
- * @param string $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
- * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
- * @param string $type Type of reference
- * @param Title $targetTitle Title of the reference's target.
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
+ * @param UUID $srcWorkflow ID of the source Workflow
+ * @param Title $srcTitle Title of the Workflow from which this reference comes.
+ * @param string $objectType Output of getRevisionType for the AbstractRevision that this reference comes from.
+ * @param UUID $objectId Unique identifier for the revisioned object containing the reference.
+ * @param string $type Type of reference
+ * @param Title $targetTitle Title of the reference's target.
*/
- public function __construct( $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type, Title $targetTitle ) {
+ public function __construct( UUID $id, $wiki, UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type, Title $targetTitle ) {
$this->target = $targetTitle;
$this->validTypes = array_merge( $this->validTypes,
- array(
+ [
self::TYPE_FILE,
self::TYPE_TEMPLATE,
self::TYPE_CATEGORY,
- )
+ ]
);
- parent::__construct( $wiki, $srcWorkflow, $srcTitle, $objectType, $objectId, $type );
+ parent::__construct( $id, $wiki, $srcWorkflow, $srcTitle, $objectType, $objectId, $type );
}
/**
@@ -41,30 +42,31 @@ class WikiReference extends Reference {
* @return array
*/
public function getStorageRow() {
- return parent::getStorageRow() + array(
+ return parent::getStorageRow() + [
'ref_target_namespace' => $this->target->getNamespace(),
'ref_target_title' => $this->target->getDBkey(),
- );
+ ];
}
/**
* Instantiates a WikiReference object from a storage row.
*
- * @param \StdClass $row
+ * @param array $row
* @return WikiReference
*/
public static function fromStorageRow( $row ) {
- global $wgFlowMigrateReferenceWiki;
-
+ // TODO: Remove this UUID::create() call when the field is populated
+ // everywhere relevant.
+ $id = ( !isset( $row['ref_id'] ) || $row['ref_id'] === null ) ? UUID::create() : UUID::create( $row['ref_id'] );
$workflow = UUID::create( $row['ref_src_workflow_id'] );
$objectType = $row['ref_src_object_type'];
$objectId = UUID::create( $row['ref_src_object_id'] );
$srcTitle = self::makeTitle( $row['ref_src_namespace'], $row['ref_src_title'] );
$targetTitle = self::makeTitle( $row['ref_target_namespace'], $row['ref_target_title'] );
$type = $row['ref_type'];
- $wiki = $wgFlowMigrateReferenceWiki ? null : $row['ref_src_wiki'];
+ $wiki = $row['ref_src_wiki'];
- return new WikiReference( $wiki, $workflow, $srcTitle, $objectType, $objectId, $type, $targetTitle );
+ return new WikiReference( $id, $wiki, $workflow, $srcTitle, $objectType, $objectId, $type, $targetTitle );
}
/**
@@ -87,7 +89,7 @@ class WikiReference extends Reference {
*/
public static function makeTitle( $namespace, $title ) {
try {
- return Workflow::getFromTitleCache( wfWikiId(), $namespace, $title );
+ return Workflow::getFromTitleCache( wfWikiID(), $namespace, $title );
} catch ( InvalidInputException $e ) {
// duplicate Title::makeTitleSafe which returns null on failure,
// but only for InvalidInputException
diff --git a/Flow/includes/Model/Workflow.php b/Flow/includes/Model/Workflow.php
index 39c16325..6e338acb 100644
--- a/Flow/includes/Model/Workflow.php
+++ b/Flow/includes/Model/Workflow.php
@@ -2,14 +2,10 @@
namespace Flow\Model;
-use Article;
-use Flow\Container;
use Flow\Exception\CrossWikiException;
use Flow\Exception\DataModelException;
use Flow\Exception\FailCommitException;
use Flow\Exception\InvalidInputException;
-use Flow\Exception\PermissionException;
-use Flow\OccupationController;
use MapCacheLRU;
use MWTimestamp;
use Title;
@@ -25,7 +21,7 @@ class Workflow {
/**
* @var string[]
*/
- static private $allowedTypes = array( 'discussion', 'topic' );
+ static private $allowedTypes = [ 'discussion', 'topic' ];
/**
* @var UUID
@@ -43,12 +39,12 @@ class Workflow {
protected $wiki;
/**
- * @var integer
+ * @var int
*/
protected $pageId = 0;
/**
- * @var integer
+ * @var int
*/
protected $namespace;
@@ -73,12 +69,17 @@ class Workflow {
protected $ownerTitle;
/**
+ * @var bool|null Indicates if associated page_id exists (null if not yet looked up)
+ */
+ protected $exists;
+
+ /**
* @param array $row
* @param Workflow|null $obj
* @return Workflow
* @throws DataModelException
*/
- static public function fromStorageRow( array $row, $obj = null ) {
+ public static function fromStorageRow( array $row, $obj = null ) {
if ( $obj === null ) {
$obj = new self;
} elseif ( !$obj instanceof self ) {
@@ -87,8 +88,8 @@ class Workflow {
$obj->id = UUID::create( $row['workflow_id'] );
$obj->type = $row['workflow_type'];
$obj->wiki = $row['workflow_wiki'];
- $obj->pageId = (int) $row['workflow_page_id'];
- $obj->namespace = (int) $row['workflow_namespace'];
+ $obj->pageId = (int)$row['workflow_page_id'];
+ $obj->namespace = (int)$row['workflow_namespace'];
$obj->titleText = $row['workflow_title_text'];
$obj->lastUpdated = $row['workflow_last_update_timestamp'];
@@ -100,7 +101,7 @@ class Workflow {
* @return array
* @throws FailCommitException
*/
- static public function toStorageRow( Workflow $obj ) {
+ public static function toStorageRow( Workflow $obj ) {
if ( $obj->pageId === 0 ) {
/*
* We try to defer creating a new page as long as possible, which
@@ -111,16 +112,17 @@ class Workflow {
* page_id this workflow is associated with.
*/
- // store ID of newly created page
+ // store ID of newly created page & reset exists status
$title = $obj->getOwnerTitle();
$obj->pageId = $title->getArticleID( Title::GAID_FOR_UPDATE );
+ $obj->exists = null;
if ( $obj->pageId === 0 ) {
throw new FailCommitException( 'No page for workflow: ' . serialize( $obj ) );
}
}
- return array(
+ return [
'workflow_id' => $obj->id->getAlphadecimal(),
'workflow_type' => $obj->type,
'workflow_wiki' => $obj->wiki,
@@ -131,7 +133,7 @@ class Workflow {
'workflow_last_update_timestamp' => $obj->lastUpdated,
// not used, but set it to empty string so it doesn't fail in strict mode
'workflow_name' => '',
- );
+ ];
}
/**
@@ -140,13 +142,13 @@ class Workflow {
* @return Workflow
* @throws DataModelException
*/
- static public function create( $type, Title $title ) {
+ public static function create( $type, Title $title ) {
// temporary limitation until we implement something more concrete
if ( !in_array( $type, self::$allowedTypes ) ) {
throw new DataModelException( 'Invalid workflow type provided: ' . $type, 'process-data' );
}
if ( $title->isLocal() ) {
- $wiki = wfWikiId();
+ $wiki = wfWikiID();
} else {
$wiki = $title->getTransWikiID();
}
@@ -165,8 +167,8 @@ class Workflow {
// we just created a new workflow; wipe out any cached data for the
// associated title
if ( self::$titleCache !== null ) {
- $key = implode( '|', array( $obj->wiki, $obj->namespace, $obj->titleText ) );
- self::$titleCache->clear( array( $key ) );
+ $key = implode( '|', [ $obj->wiki, $obj->namespace, $obj->titleText ] );
+ self::$titleCache->clear( [ $key ] );
}
return $obj;
@@ -235,22 +237,18 @@ class Workflow {
* @throws InvalidInputException
*/
public static function getFromTitleCache( $wiki, $namespace, $titleText ) {
- if ( $wiki !== wfWikiId() ) {
- $thisWiki = wfWikiId();
- throw new CrossWikiException( "Interwiki to '$wiki' from '$thisWiki' not implemented", 'default' );
- }
if ( self::$titleCache === null ) {
self::$titleCache = new MapCacheLRU( 50 );
}
- $key = implode( '|', array( $wiki, $namespace, $titleText ) );
+ $key = implode( '|', [ $wiki, $namespace, $titleText ] );
$title = self::$titleCache->get( $key );
if ( $title === null ) {
$title = Title::makeTitleSafe( $namespace, $titleText );
if ( $title ) {
self::$titleCache->set( $key, $title );
} else {
- throw new InvalidInputException( 'Fail to create title from ' . $titleText, 'invalid-input' );
+ throw new InvalidInputException( "Fail to create title from namespace $namespace and title text '$titleText'", 'invalid-input' );
}
}
@@ -260,33 +258,43 @@ class Workflow {
/**
* @return UUID
*/
- public function getId() { return $this->id; }
+ public function getId() {
+ return $this->id;
+ }
/**
* @return string
*/
- public function getType() { return $this->type; }
+ public function getType() {
+ return $this->type;
+ }
/**
* Get the wiki ID, e.g. eswiki
*
* @return string
*/
- public function getWiki() { return $this->wiki; }
+ public function getWiki() {
+ return $this->wiki;
+ }
/**
* @return bool
*/
public function isDeleted() {
+ if ( $this->exists === null ) {
+ $this->exists = Title::newFromID( $this->pageId ) !== null;
+ }
+
// a board that does not yet exist (because workflow has not yet
// been stored) is not deleted, it just doesn't exist yet
- return !$this->isNew() && Title::newFromID( $this->pageId ) === null;
+ return !$this->isNew() && !$this->exists;
}
/**
* Returns true if the workflow is new as of this request.
*
- * @return boolean
+ * @return bool
*/
public function isNew() {
return $this->pageId === 0;
@@ -295,12 +303,16 @@ class Workflow {
/**
* @return string
*/
- public function getLastUpdated() { return $this->lastUpdated; }
+ public function getLastUpdated() {
+ return $this->lastUpdated;
+ }
/**
* @return \MWTimestamp
*/
- public function getLastUpdatedObj() { return new MWTimestamp( $this->lastUpdated ); }
+ public function getLastUpdatedObj() {
+ return new MWTimestamp( $this->lastUpdated );
+ }
public function updateLastUpdated( UUID $latestRevisionId ) {
$this->lastUpdated = $latestRevisionId->getTimestamp();
@@ -332,7 +344,7 @@ class Workflow {
* it should return false later on to allow wider use.
*
* @param Title $title
- * @return boolean
+ * @return bool
* @throws InvalidInputException
* @throws InvalidInputException
*/
@@ -341,17 +353,59 @@ class Workflow {
}
/**
- * @param string $permission
- * @param User $user
- * @return bool
+ * Convenience wrapper for checking user permissions as boolean.
+ * getPermissionErrors 'quick' + blocked check only for logged in users
+ *
+ * @param string $permission Permission to check; for 'edit', 'create' will also be
+ * checked if the title does not exist
+ * @return bool Whether the user can take the action, based on a quick check
*/
public function userCan( $permission, $user ) {
- $title = $this->getArticleTitle();
- $allowed = $title->userCan( $permission, $user );
- if ( $allowed && $this->type === 'topic' ) {
- $allowed = $this->getOwnerTitle()->userCan( $permission, $user );
+ return !count( $this->getPermissionErrors( $permission, $user, 'quick' ) ) &&
+
+ // We only check the blocked status of actual users and not anons, because
+ // the anonymous version can be cached and served to many different IP
+ // addresses which will not all be blocked.
+ // See T61928
+ !( $user->isLoggedIn() && $user->isBlockedFrom( $this->getOwnerTitle(), true ) );
+ }
+
+ /**
+ * Pass-through to Title::getUserPermissionsErrors
+ * with title, and owning title if needed.
+ *
+ * @param string $permission Permission to check; for 'edit', 'create' will also be
+ * checked if the title does not exist
+ * @param User $user User to check permissions for
+ * @param string $rigor Rigor of check; see Title->getUserPermissionsErrors
+ * @return array Array of arrays of the arguments to wfMessage to explain permissions problems.
+ */
+ public function getPermissionErrors( $permission, $user, $rigor ) {
+ $title = $this->type === 'topic' ? $this->getOwnerTitle() : $this->getArticleTitle();
+
+ $editErrors = $title->getUserPermissionsErrors( $permission, $user, $rigor );
+
+ $errors = $editErrors;
+
+ $titleExistsFlags = ( $rigor === 'secure' ) ? Title::GAID_FOR_UPDATE : 0;
+
+ if ( $permission === 'edit' && !$title->exists( $titleExistsFlags ) ) {
+ // If it's 'edit', but the title doesn't exist, check 'create' as
+ // well.
+
+ $editErrorKeys = array_map( function ( $val ) {
+ return reset( $val );
+ }, $editErrors );
+
+ // Pass in the edit errors to avoid duplicates
+ $createErrors = $title->getUserPermissionsErrors( 'create', $user, $rigor, $editErrorKeys );
+ $errors = array_merge( $errors, $createErrors );
+ }
+
+ if ( count( $errors ) ) {
+ return $errors;
}
- return $allowed;
+ return [];
}
}
diff --git a/Flow/includes/Notifications/Controller.php b/Flow/includes/Notifications/Controller.php
index a610318c..62477dce 100644
--- a/Flow/includes/Notifications/Controller.php
+++ b/Flow/includes/Notifications/Controller.php
@@ -2,12 +2,17 @@
namespace Flow;
-use Flow\Data\ManagerGroup;
+use EchoEventMapper;
+use EchoModerationController;
use Flow\Exception\FlowException;
+use Flow\Model\AbstractRevision;
+use Flow\Model\Header;
use Flow\Model\PostRevision;
+use Flow\Model\PostSummary;
use Flow\Model\UUID;
use Flow\Model\Workflow;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
+use Flow\Repository\TreeRepository;
use EchoEvent;
use Language;
use Title;
@@ -20,53 +25,141 @@ class NotificationController {
protected $language;
/**
+ * @var TreeRepository
+ */
+ protected $treeRepository;
+
+ /**
* @param Language $language
*/
- public function __construct( Language $language ) {
+ public function __construct( Language $language, TreeRepository $treeRepository ) {
$this->language = $language;
+ $this->treeRepository = $treeRepository;
}
public static function onBeforeCreateEchoEvent( &$notifs, &$categories, &$icons ) {
$notifs += require __DIR__ . "/Notifications.php";
- $categories['flow-discussion'] = array(
+ $categories['flow-discussion'] = [
'priority' => 3,
'tooltip' => 'echo-pref-tooltip-flow-discussion',
- );
- $icons['flow-discussion'] = array(
- 'path' => array(
- 'ltr' => 'Flow/modules/notification/icon/Talk-ltr.png',
- 'rtl' => 'Flow/modules/notification/icon/Talk-rtl.png'
- )
- );
+ ];
+ $icons['flow-new-topic'] = [
+ 'path' => 'Flow/modules/notification/icon/flow-new-topic.svg',
+ ];
+ $icons['flowusertalk-new-topic'] = [
+ 'path' => 'Flow/modules/notification/icon/flowusertalk-new-topic.svg',
+ ];
+ $icons['flow-post-edited'] = $icons['flowusertalk-post-edited'] = [
+ 'path' => 'Flow/modules/notification/icon/flow-post-edited.svg',
+ ];
+ $icons['flow-topic-renamed'] = $icons['flowusertalk-topic-renamed'] = [
+ 'path' => 'Flow/modules/notification/icon/flow-topic-renamed.svg',
+ ];
+ $icons['flow-topic-resolved'] = $icons['flowusertalk-topic-resolved'] = [
+ 'path' => 'Flow/modules/notification/icon/flow-topic-resolved.svg',
+ ];
+ $icons['flow-topic-reopened'] = $icons['flowusertalk-topic-reopened'] = [
+ 'path' => 'Flow/modules/notification/icon/flow-topic-reopened.svg',
+ ];
+ }
+
+ /**
+ * Causes notifications to be fired for a Header-related event.
+ * @param array $data Associative array of parameters. * revision: The PostRevision created by the action. Always required. * board-workflow: The Workflow object for the board. Always required. * timestamp: Original event timestamp, for imports. Optional. * extra-data: Additional data to pass along to Event extra.
+ * * revision: The PostRevision created by the action. Always required.
+ * * board-workflow: The Workflow object for the board. Always required.
+ * * timestamp: Original event timestamp, for imports. Optional.
+ * * extra-data: Additional data to pass along to Event extra.
+ * @return array Array of created EchoEvent objects.
+ * @throws FlowException When $data contains unexpected types/values
+ */
+ public function notifyHeaderChange( $data = [] ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
+ return [];
+ }
+
+ if ( isset( $data['extra-data'] ) ) {
+ $extraData = $data['extra-data'];
+ } else {
+ $extraData = [];
+ }
+
+ $revision = $data['revision'];
+ if ( !$revision instanceof Header ) {
+ throw new FlowException( 'Expected Header but received ' . get_class( $revision ) );
+ }
+ $boardWorkflow = $data['board-workflow'];
+ if ( !$boardWorkflow instanceof Workflow ) {
+ throw new FlowException( 'Expected Workflow but received ' . get_class( $boardWorkflow ) );
+ }
+
+ $user = $revision->getUser();
+ list( $mentionedUsers, $mentionsSkipped ) = $this->getMentionedUsersAndSkipState( $revision );
+
+ $extraData['content'] = Utils::htmlToPlaintext( $revision->getContent(), 200, $this->language );
+ $extraData['revision-id'] = $revision->getRevisionId();
+ $extraData['collection-id'] = $revision->getCollectionId();
+ $extraData['target-page'] = $boardWorkflow->getArticleTitle()->getArticleID();
+ // pass along mentioned users to other notification, so it knows who to ignore
+ $extraData['mentioned-users'] = $mentionedUsers;
+ $title = $boardWorkflow->getOwnerTitle();
+
+ $info = [
+ 'agent' => $user,
+ 'title' => $title,
+ 'extra' => $extraData,
+ ];
+
+ // Allow a specific timestamp to be set - useful when importing existing data
+ if ( isset( $data['timestamp'] ) ) {
+ $info['timestamp'] = $data['timestamp'];
+ }
+
+ $events = [ EchoEvent::create( [ 'type' => 'flow-description-edited' ] + $info ) ];
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $events[] = EchoEvent::create( [ 'type' => 'flowusertalk-description-edited' ] + $info );
+ }
+ if ( $mentionedUsers ) {
+ $mentionEvents = $this->generateMentionEvents(
+ $revision,
+ null,
+ $boardWorkflow,
+ $user,
+ $mentionedUsers,
+ $mentionsSkipped
+ );
+ $events = array_merge( $events, $mentionEvents );
+ }
+
+ return $events;
}
/**
* Causes notifications to be fired for a Flow event.
- * @param String $eventName The event that occurred. Choice of:
+ * @param String $eventName The event that occurred. Choice of:
* * flow-post-reply
* * flow-topic-renamed
* * flow-post-edited
- * @param array $data Associative array of parameters.
+ * @param array $data Associative array of parameters. * user: The user who made the change. Always required. * revision: The PostRevision created by the action. Always required. * title: The Title on which this Topic sits. Always required. * topic-workflow: The Workflow object for the topic. Always required. * topic-title: The Title of the Topic that the post belongs to. Required except for topic renames. * old-subject: The old subject of a Topic. Required for topic renames. * new-subject: The new subject of a Topic. Required for topic renames.
* * user: The user who made the change. Always required.
* * revision: The PostRevision created by the action. Always required.
* * title: The Title on which this Topic sits. Always required.
* * topic-workflow: The Workflow object for the topic. Always required.
- * * reply-to: The UUID of the post that is being replied to. Required for replies.
* * topic-title: The Title of the Topic that the post belongs to. Required except for topic renames.
* * old-subject: The old subject of a Topic. Required for topic renames.
* * new-subject: The new subject of a Topic. Required for topic renames.
* @return array Array of created EchoEvent objects.
* @throws FlowException When $data contains unexpected types/values
*/
- public function notifyPostChange( $eventName, $data = array() ) {
+ public function notifyPostChange( $eventName, $data = [] ) {
if ( !class_exists( 'EchoEvent' ) ) {
- return array();
+ return [];
}
if ( isset( $data['extra-data'] ) ) {
$extraData = $data['extra-data'];
} else {
- $extraData = array();
+ $extraData = [];
}
$revision = $data['revision'];
@@ -82,67 +175,163 @@ class NotificationController {
throw new FlowException( 'Expected Workflow but received ' . get_class( $topicWorkflow ) );
}
- $title = $data['title'];
$user = $revision->getUser();
+ list( $mentionedUsers, $mentionsSkipped ) = $this->getMentionedUsersAndSkipState( $revision );
+ $title = $topicWorkflow->getOwnerTitle();
$extraData['revision-id'] = $revision->getRevisionId();
$extraData['post-id'] = $revision->getPostId();
$extraData['topic-workflow'] = $topicWorkflow->getId();
$extraData['target-page'] = $topicWorkflow->getArticleTitle()->getArticleID();
+ // pass along mentioned users to other notification, so it knows who to ignore
+ $extraData['mentioned-users'] = $mentionedUsers;
- $newPost = null;
- switch( $eventName ) {
+ switch ( $eventName ) {
case 'flow-post-reply':
- $replyTo = $data['reply-to'];
- if ( !$replyTo instanceof PostRevision ) {
- throw new FlowException( 'Expected PostRevision but received ' . get_class( $replyTo ) );
- }
- $replyToPostId = $replyTo->getPostId();
- $extraData += array(
- 'reply-to' => $replyToPostId,
+ $extraData += [
+ 'reply-to' => $revision->getReplyToId(),
'content' => Utils::htmlToPlaintext( $revision->getContent(), 200, $this->language ),
- 'topic-title' => $this->language->truncate( trim( $topicRevision->getContent( 'wikitext' ) ), 200 ),
- );
- $newPost = array(
- 'title' => $title,
- 'user' => $user,
- 'post' => $revision,
- 'reply-to' => $replyToPostId,
- 'topic-title' => $topicRevision,
- 'topic-workflow' => $topicWorkflow,
- );
+ 'topic-title' => $this->language->truncate( $topicRevision->getContent( 'topic-title-plaintext' ), 200 ),
+ ];
+
+ // if we're looking at the initial post (submitted along with the topic
+ // title), we don't want to send the flow-post-reply notification,
+ // because users will already receive flow-new-topic as well
+ if ( $this->isFirstPost( $revision, $topicWorkflow ) ) {
+ // if users were mentioned here, we'll want to make sure
+ // that they weren't also mentioned in the topic title (in
+ // which case they would get 2 notifications...)
+ if ( $mentionedUsers ) {
+ list( $mentionedInTitle, $mentionsSkippedInTitle ) =
+ $this->getMentionedUsersAndSkipState( $topicRevision );
+ $mentionedUsers = array_diff_key( $mentionedUsers, $mentionedInTitle );
+ $mentionsSkipped = $mentionsSkipped || $mentionsSkippedInTitle;
+ $extraData['mentioned-users'] = $mentionedUsers;
+ }
+
+ return $this->generateMentionEvents(
+ $revision,
+ $topicRevision,
+ $topicWorkflow,
+ $user,
+ $mentionedUsers,
+ $mentionsSkipped
+ );
+ }
break;
case 'flow-topic-renamed':
- $extraData += array(
- 'old-subject' => $this->language->truncate( trim( $topicRevision->getContent( 'wikitext' ) ), 200 ),
- 'new-subject' => $this->language->truncate( trim( $revision->getContent( 'wikitext' ) ), 200 ),
- );
+ $previousRevision = $revision->getCollection()->getPrevRevision( $revision );
+ $extraData += [
+ 'old-subject' => $this->language->truncate( $previousRevision->getContent( 'topic-title-plaintext' ), 200 ),
+ 'new-subject' => $this->language->truncate( $revision->getContent( 'topic-title-plaintext' ), 200 ),
+ ];
break;
case 'flow-post-edited':
- $extraData += array(
+ $extraData += [
'content' => Utils::htmlToPlaintext( $revision->getContent(), 200, $this->language ),
- 'topic-title' => $this->language->truncate( trim( $topicRevision->getContent( 'wikitext' ) ), 200 ),
- );
+ 'topic-title' => $this->language->truncate( $topicRevision->getContent( 'topic-title-plaintext' ), 200 ),
+ ];
break;
}
- $info = array(
- 'type' => $eventName,
+ $info = [
'agent' => $user,
'title' => $title,
'extra' => $extraData,
- );
+ ];
// Allow a specific timestamp to be set - useful when importing existing data
- if ( isset( $data['timestamp'] ) ){
+ if ( isset( $data['timestamp'] ) ) {
$info['timestamp'] = $data['timestamp'];
}
- $events = array( EchoEvent::create( $info ) );
+ $events = [ EchoEvent::create( [ 'type' => $eventName ] + $info ) ];
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $usertalkEvent = str_replace( 'flow-', 'flowusertalk-', $eventName );
+ $events[] = EchoEvent::create( [ 'type' => $usertalkEvent ] + $info );
+ }
+ if ( $mentionedUsers ) {
+ $mentionEvents = $this->generateMentionEvents(
+ $revision,
+ $topicRevision,
+ $topicWorkflow,
+ $user,
+ $mentionedUsers,
+ $mentionsSkipped
+ );
+ $events = array_merge( $events, $mentionEvents );
+ }
+
+ return $events;
+ }
- if ( $newPost ) {
- $events = array_merge( $events, $this->notifyNewPost( $newPost ) );
+ /**
+ * Causes notifications to be fired for a Summary-related event.
+ * @param array $data Associative array of parameters. * revision: The PostRevision created by the action. Always required. * topic-title: The PostRevision object for the topic title. Always required. * topic-workflow: The Workflow object for the board. Always required. * extra-data: Additional data to pass along to Event extra.
+ * * revision: The PostRevision created by the action. Always required.
+ * * topic-title: The PostRevision object for the topic title. Always required.
+ * * topic-workflow: The Workflow object for the board. Always required.
+ * * extra-data: Additional data to pass along to Event extra.
+ * @return array Array of created EchoEvent objects.
+ * @throws FlowException When $data contains unexpected types/values
+ */
+ public function notifySummaryChange( $data = [] ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
+ return [];
+ }
+
+ $revision = $data['revision'];
+ if ( !$revision instanceof PostSummary ) {
+ throw new FlowException( 'Expected PostSummary but received ' . get_class( $revision ) );
+ }
+ $topicRevision = $data['topic-title'];
+ if ( !$topicRevision instanceof PostRevision ) {
+ throw new FlowException( 'Expected PostRevision but received ' . get_class( $topicRevision ) );
+ }
+ $topicWorkflow = $data['topic-workflow'];
+ if ( !$topicWorkflow instanceof Workflow ) {
+ throw new FlowException( 'Expected Workflow but received ' . get_class( $topicWorkflow ) );
+ }
+
+ $user = $revision->getUser();
+ list( $mentionedUsers, $mentionsSkipped ) = $this->getMentionedUsersAndSkipState( $revision );
+
+ $extraData['content'] = Utils::htmlToPlaintext( $revision->getContent(), 200, $this->language );
+ $extraData['revision-id'] = $revision->getRevisionId();
+ $extraData['prev-revision-id'] = $revision->getPrevRevisionId();
+ $extraData['topic-workflow'] = $topicWorkflow->getId();
+ $extraData['topic-title'] = $this->language->truncate( $topicRevision->getContent( 'topic-title-plaintext' ), 200 );
+ $extraData['target-page'] = $topicWorkflow->getArticleTitle()->getArticleID();
+ // pass along mentioned users to other notification, so it knows who to ignore
+ $extraData['mentioned-users'] = $mentionedUsers;
+ $title = $topicWorkflow->getOwnerTitle();
+
+ $info = [
+ 'agent' => $user,
+ 'title' => $title,
+ 'extra' => $extraData,
+ ];
+
+ // Allow a specific timestamp to be set - useful when importing existing data
+ if ( isset( $data['timestamp'] ) ) {
+ $info['timestamp'] = $data['timestamp'];
+ }
+
+ $events = [ EchoEvent::create( [ 'type' => 'flow-summary-edited' ] + $info ) ];
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $events[] = EchoEvent::create( [ 'type' => 'flowusertalk-summary-edited' ] + $info );
+ }
+ if ( $mentionedUsers ) {
+ $mentionEvents = $this->generateMentionEvents(
+ $revision,
+ $topicRevision,
+ $topicWorkflow,
+ $user,
+ $mentionedUsers,
+ $mentionsSkipped
+ );
+ $events = array_merge( $events, $mentionEvents );
}
return $events;
@@ -150,7 +339,7 @@ class NotificationController {
/**
* Triggers notifications for a new topic.
- * @param array $params Associative array of parameters, all required:
+ * @param array $params Associative array of parameters, all required:
* * board-workflow: Workflow object for the Flow board.
* * topic-workflow: Workflow object for the new Topic.
* * topic-title: PostRevision object for the "topic post", containing the
@@ -161,9 +350,9 @@ class NotificationController {
* @throws FlowException When $params contains unexpected types/values
*/
public function notifyNewTopic( $params ) {
- if ( ! class_exists( 'EchoEvent' ) ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
// Nothing to do here.
- return array();
+ return [];
}
$topicWorkflow = $params['topic-workflow'];
@@ -184,125 +373,219 @@ class NotificationController {
throw new FlowException( 'Expected Workflow but received ' . get_class( $boardWorkflow ) );
}
- $events = array();
- $events[] = EchoEvent::create( array(
- 'type' => 'flow-new-topic',
+ list( $mentionedUsers, $mentionsSkipped ) = $this->getMentionedUsersAndSkipState( $topicTitle );
+
+ $title = $boardWorkflow->getArticleTitle();
+ $events = [];
+ $eventData = [
'agent' => $user,
- 'title' => $boardWorkflow->getArticleTitle(),
- 'extra' => array(
+ 'title' => $title,
+ 'extra' => [
'board-workflow' => $boardWorkflow->getId(),
'topic-workflow' => $topicWorkflow->getId(),
'post-id' => $firstPost ? $firstPost->getRevisionId() : null,
- 'topic-title' => Utils::htmlToPlaintext( $topicTitle->getContent(), 200, $this->language ),
+ 'topic-title' => $this->language->truncate( $topicTitle->getContent( 'topic-title-plaintext' ), 200 ),
'content' => $firstPost
? Utils::htmlToPlaintext( $firstPost->getContent(), 200, $this->language )
: null,
// Force a read from master database since this could be a new page
- 'target-page' => array(
+ 'target-page' => [
$topicWorkflow->getOwnerTitle()->getArticleID( Title::GAID_FOR_UPDATE ),
$topicWorkflow->getArticleTitle()->getArticleID( Title::GAID_FOR_UPDATE ),
- ),
- )
- ) );
+ ],
+ // pass along mentioned users to other notification, so it knows who to ignore
+ // also look at users mentioned in first post: if there are any, this
+ // (flow-new-topic) notification shouldn't go through (because they'll
+ // already receive the mention notification)
+ 'mentioned-users' => $mentionedUsers,
+ ]
+ ];
+ $events[] = EchoEvent::create( [ 'type' => 'flow-new-topic' ] + $eventData );
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $events[] = EchoEvent::create( [ 'type' => 'flowusertalk-new-topic' ] + $eventData );
+ }
+ if ( $mentionedUsers ) {
+ $mentionEvents = $this->generateMentionEvents(
+ $topicTitle,
+ $topicTitle,
+ $topicWorkflow,
+ $user,
+ $mentionedUsers,
+ $mentionsSkipped
+ );
+ $events = array_merge( $events, $mentionEvents );
+ }
+
+ return $events;
+ }
+
+ /**
+ * Triggers notifications when a topic is resolved or reopened.
+ *
+ * @param string $type flow-topic-resolved|flow-topic-reopened
+ * @param array $data
+ * @return array
+ * @throws Exception\InvalidDataException
+ * @throws FlowException
+ * @throws \MWException
+ */
+ public function notifyTopicLocked( $type, $data = [] ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
+ return [];
+ }
+
+ $revision = $data['revision'];
+ if ( !$revision instanceof PostRevision ) {
+ throw new FlowException( 'Expected PostSummary but received ' . get_class( $revision ) );
+ }
+ $topicWorkflow = $data['topic-workflow'];
+ if ( !$topicWorkflow instanceof Workflow ) {
+ throw new FlowException( 'Expected Workflow but received ' . get_class( $topicWorkflow ) );
+ }
+
+ $extraData['topic-workflow'] = $topicWorkflow->getId();
+ $extraData['topic-title'] = Utils::htmlToPlaintext( $revision->getContent( 'topic-title-html' ), 200, $this->language );
+ $extraData['target-page'] = $topicWorkflow->getArticleTitle()->getArticleID();
+ // I'll treat resolve & reopen as the same notification type, but pass the
+ // different type so presentation models can differentiate
+ $extraData['type'] = $type;
+ $title = $topicWorkflow->getOwnerTitle();
+
+ $info = [
+ 'agent' => $revision->getUser(),
+ 'title' => $title,
+ 'extra' => $extraData,
+ ];
+
+ // Allow a specific timestamp to be set - useful when importing existing data
+ if ( isset( $data['timestamp'] ) ) {
+ $info['timestamp'] = $data['timestamp'];
+ }
+
+ $events = [ EchoEvent::create( [ 'type' => 'flow-topic-resolved' ] + $info ) ];
+ if ( $title->getNamespace() === NS_USER_TALK ) {
+ $events[] = EchoEvent::create( [ 'type' => 'flowusertalk-topic-resolved' ] + $info );
+ }
return $events;
}
public function notifyFlowEnabledOnTalkpage( User $user ) {
if ( !class_exists( 'EchoEvent' ) ) {
// Nothing to do here.
- return array();
+ return [];
}
- $events = array();
- $events[] = EchoEvent::create( array(
+ $events = [];
+ $events[] = EchoEvent::create( [
'type' => 'flow-enabled-on-talkpage',
'agent' => $user,
'title' => $user->getTalkPage(),
- 'extra' => array(
+ 'extra' => [
'notifyAgent' => true,
- ),
- ) );
+ ],
+ ] );
return $events;
}
/**
- * Called when a new Post is added, whether it be a new topic or a reply.
- * Do not call directly, use notifyPostChange for new replies.
- * @param array $data Associative array of parameters, all required:
- * * title: Title for the page on which the new Post sits.
- * * user: User who created the new Post.
- * * post: The Post that was created.
- * * topic-title: The title for the Topic.
- * @return array Array of created EchoEvent objects.
- * @throws FlowException When $data contains unexpected types/values
+ * @param AbstractRevision $content The (post|topic|header) revision that contains the content of the mention
+ * @param PostRevision|null $topic Topic PostRevision object, if relevant (e.g. not for Header)
+ * @param Workflow $workflow Workflow object
+ * @param User $user User who created the new post
+ * @param array $mentionedUsers
+ * @param bool $mentionsSkipped Were mentions skipped due to too many mentions being attempted?
+ * @return bool|EchoEvent[]
+ * @throws Exception\InvalidDataException
+ * @throws \MWException
*/
- protected function notifyNewPost( $data ) {
- // Handle mentions.
- $newRevision = $data['post'];
- if ( $newRevision !== null && !$newRevision instanceof PostRevision ) {
- throw new FlowException( 'Expected PostRevision but received ' . get_class( $newRevision ) );
+ protected function generateMentionEvents(
+ AbstractRevision $content,
+ PostRevision $topic = null,
+ Workflow $workflow,
+ User $user,
+ array $mentionedUsers,
+ $mentionsSkipped
+ ) {
+ global $wgEchoMentionStatusNotifications, $wgFlowMaxMentionCount;
+
+ if ( count( $mentionedUsers ) === 0 ) {
+ return false;
}
- $topicRevision = $data['topic-title'];
- if ( !$topicRevision instanceof PostRevision ) {
- throw new FlowException( 'Expected PostRevision but received ' . get_class( $topicRevision ) );
+
+ $extraData = [];
+ $extraData['mentioned-users'] = $mentionedUsers;
+ $extraData['target-page'] = $workflow->getArticleTitle()->getArticleID();
+ // don't include topic content again if the notification IS in the title
+ $extraData['content'] = $content === $topic ? '' : Utils::htmlToPlaintext( $content->getContent(), 200, $this->language );
+ // lets us differentiate between different revision types
+ $extraData['revision-type'] = $content->getRevisionType();
+
+ // additional data needed to render link to post
+ if ( $extraData['revision-type'] === 'post' ) {
+ $extraData['post-id'] = $content->getCollection()->getId();
}
- $title = $data['title'];
- if ( !$title instanceof \Title ) {
- throw new FlowException( 'Expected Title but received ' . get_class( $title ) );
+ // needed to render topic title text & link to topic
+ if ( $topic !== null ) {
+ $extraData['topic-workflow'] = $workflow->getId();
+ $extraData['topic-title'] = $this->language->truncate( $topic->getContent( 'topic-title-plaintext' ), 200 );
}
- $user = $data['user'];
- $topicWorkflow = $data['topic-workflow'];
- if ( !$topicWorkflow instanceof Workflow ) {
- throw new FlowException( 'Expected Workflow but received ' . get_class( $topicWorkflow ) );
- }
- $events = array();
- $mentionedUsers = $newRevision ? $this->getMentionedUsers( $newRevision, $title ) : array();
-
- if ( !$topicRevision instanceof PostRevision ) {
- throw new FlowException( 'Expected PostRevision but received: ' . get_class( $topicRevision ) );
- }
-
- if ( count( $mentionedUsers ) ) {
- $events[] = EchoEvent::create( array(
- 'type' => 'flow-mention',
- 'title' => $title,
- 'extra' => array(
- 'content' => $newRevision
- ? Utils::htmlToPlaintext( $newRevision->getContent(), 200, $this->language )
- : null,
- 'topic-title' => $this->language->truncate( trim( $topicRevision->getContent( 'wikitext' ) ), 200 ),
- 'post-id' => $newRevision ? $newRevision->getPostId() : null,
- 'mentioned-users' => $mentionedUsers,
- 'topic-workflow' => $topicWorkflow->getId(),
- 'target-page' => $topicWorkflow->getArticleTitle()->getArticleID(),
- 'reply-to' => isset( $data['reply-to'] ) ? $data['reply-to'] : null
- ),
+ $events = [];
+ $events[] = EchoEvent::create( [
+ 'type' => 'flow-mention',
+ 'title' => $workflow->getOwnerTitle(),
+ 'extra' => $extraData,
+ 'agent' => $user,
+ ] );
+ if ( $wgEchoMentionStatusNotifications && $mentionsSkipped ) {
+ $extra = [
+ 'topic-workflow' => $workflow->getId(),
+ 'max-mentions' => $wgFlowMaxMentionCount,
+ 'section-title' => $extraData['topic-title'],
+ 'failure-type' => 'too-many',
+ 'notifyAgent' => true
+ ];
+ if ( $content->getRevisionType() === 'post' ) {
+ $extra['post-id'] = $content->getCollection()->getId();
+ }
+ $events[] = EchoEvent::create( [
+ 'type' => 'flow-mention-failure-too-many',
+ 'title' => $workflow->getOwnerTitle(),
+ 'extra' => $extra,
'agent' => $user,
- ) );
+ ] );
}
-
return $events;
}
/**
* Analyses a PostRevision to determine which users are mentioned.
*
- * @param PostRevision $post The Post to analyse.
- * @param \Title $title
- * @return User[] Array of User objects.
+ * @param AbstractRevision $revision The Post to analyse.
+ * @return array
+ * 0 => int[] Array of user IDs
+ * 1 => bool Were some mentions ignored due to $wgFlowMaxMentionCount?
*/
- protected function getMentionedUsers( $post, $title ) {
+ protected function getMentionedUsersAndSkipState( AbstractRevision $revision ) {
// At the moment, it is not possible to get a list of mentioned users from HTML
- // unless that HTML comes from Parsoid. But VisualEditor (what is currently used
- // to convert wikitext to HTML) does not currently use Parsoid.
- $wikitext = $post->getContent( 'wikitext' );
+ // unless that HTML comes from Parsoid. But VisualEditor (what is currently used
+ // to convert wikitext to HTML) does not currently use Parsoid.
+ $wikitext = $revision->getContentInWikitext();
$mentions = $this->getMentionedUsersFromWikitext( $wikitext );
- $notifyUsers = $this->filterMentionedUsers( $mentions, $post, $title );
- return $notifyUsers;
+ // if this post had a previous revision (= this is an edit), we don't
+ // want to pick up on the same mentions as in the previous edit, only
+ // new mentions
+ $previousRevision = $revision->getCollection()->getPrevRevision( $revision );
+ if ( $previousRevision !== null ) {
+ $previousWikitext = $previousRevision->getContentInWikitext();
+ $previousMentions = $this->getMentionedUsersFromWikitext( $previousWikitext );
+ $mentions = array_diff( $mentions, $previousMentions );
+ }
+
+ return $this->filterMentionedUsers( $mentions, $revision );
}
/**
@@ -311,40 +594,44 @@ class NotificationController {
*
* Removes duplicates, anonymous users, self-mentions, and mentions of the
* owner of the talk page
- * @param User[] $mentions Array of User objects
- * @param PostRevision $post The Post that is being examined.
- * @param \Title $title The Title of the page that the comment is made on.
- * @return array Array of user IDs
+ * @param User[] $mentions Array of User objects
+ * @param AbstractRevision $revision The Post that is being examined.
+ * @return array
+ * 0 => int[] Array of user IDs
+ * 1 => bool Were some mentions ignored due to $wgFlowMaxMentionCount?
*/
- protected function filterMentionedUsers( $mentions, PostRevision $post, $title ) {
- $outputMentions = array();
+ protected function filterMentionedUsers( $mentions, AbstractRevision $revision ) {
global $wgFlowMaxMentionCount;
- foreach( $mentions as $mentionedUser ) {
+ $outputMentions = [];
+ $mentionsSkipped = false;
+
+ foreach ( $mentions as $mentionedUser ) {
// Don't notify anonymous users
if ( $mentionedUser->isAnon() ) {
continue;
}
// Don't notify the user who made the post
- if ( $mentionedUser->getId() == $post->getUserId() ) {
+ if ( $mentionedUser->getId() == $revision->getUserId() ) {
continue;
}
- if ( count( $outputMentions ) > $wgFlowMaxMentionCount ) {
+ if ( count( $outputMentions ) >= $wgFlowMaxMentionCount ) {
+ $mentionsSkipped = true;
break;
}
$outputMentions[$mentionedUser->getId()] = $mentionedUser->getId();
}
- return $outputMentions;
+ return [ $outputMentions, $mentionsSkipped ];
}
/**
* Examines a wikitext string and finds users that were mentioned
- * @param string $wikitext
- * @return array Array of User objects
+ * @param string $wikitext
+ * @return User[] Array of User objects
*/
protected function getMentionedUsersFromWikitext( $wikitext ) {
global $wgParser;
@@ -359,12 +646,12 @@ class NotificationController {
$links = $output->getLinks();
- if ( ! isset( $links[NS_USER] ) || ! is_array( $links[NS_USER] ) ) {
+ if ( !isset( $links[NS_USER] ) || !is_array( $links[NS_USER] ) ) {
// Nothing
- return array();
+ return [];
}
- $users = array();
+ $users = [];
foreach ( $links[NS_USER] as $dbk => $page_id ) {
$user = User::newFromName( $dbk );
if ( !$user || $user->isAnon() ) {
@@ -372,11 +659,6 @@ class NotificationController {
}
$users[$user->getId()] = $user;
- // If more than 20 users are being notified this is probably a spam/attack vector.
- // Don't send any mention notifications
- if ( count( $users ) > 20 ) {
- return array();
- }
}
return $users;
@@ -385,151 +667,251 @@ class NotificationController {
/**
* Handler for EchoGetBundleRule hook, which defines the bundle rules for each notification
*
- * @param $event EchoEvent
- * @param $bundleString string Determines how the notification should be bundled
- * @return boolean True for success
+ * @param EchoEvent $event
+ * @param string $bundleString Determines how the notification should be bundled
+ * @return bool True for success
*/
public static function onEchoGetBundleRules( $event, &$bundleString ) {
switch ( $event->getType() ) {
case 'flow-new-topic':
+ case 'flowusertalk-new-topic':
$board = $event->getExtraParam( 'board-workflow' );
if ( $board instanceof UUID ) {
$bundleString = $event->getType() . '-' . $board->getAlphadecimal();
}
- break;
+ break;
case 'flow-post-reply':
+ case 'flowusertalk-post-reply':
case 'flow-post-edited':
+ case 'flowusertalk-post-edited':
+ case 'flow-summary-edited':
+ case 'flowusertalk-summary-edited':
$topic = $event->getExtraParam( 'topic-workflow' );
if ( $topic instanceof UUID ) {
$bundleString = $event->getType() . '-' . $topic->getAlphadecimal();
}
- break;
+ break;
+
+ case 'flow-description-edited':
+ case 'flowusertalk-description-edited':
+ $headerId = $event->getExtraParam( 'collection-id' );
+ if ( $headerId instanceof UUID ) {
+ $bundleString = $event->getType() . '-' . $headerId->getAlphadecimal();
+ }
+ break;
}
return true;
}
/**
- * Handler for EchoGetDefaultNotifiedUsers hook
- * Returns a list of User objects in the second param
+ * Get the owner of the page if the workflow belongs to a talk page
*
- * @param $event EchoEvent being triggered
- * @param &$users Array of User objects.
- * @return bool
+ * @param string $topicId Topic workflow UUID
+ * @return array Map from userid to User object
*/
- public static function getDefaultNotifiedUsers( EchoEvent $event, &$users ) {
- $extra = $event->getExtra();
- switch ( $event->getType() ) {
- case 'flow-mention':
- $mentionedUsers = $extra['mentioned-users'];
-
- // Ignore mention if the user gets another notification
- // already from the same flow event
- $ids = array();
- $topic = $extra['topic-workflow'];
- if ( $topic instanceof UUID ) {
- $ids[$topic->getAlphadecimal()] = $topic;
- }
- if ( isset( $extra['reply-to'] ) ) {
- if ( $extra['reply-to'] instanceof UUID ) {
- $ids[$extra['reply-to']->getAlphadecimal()] = $extra['reply-to'];
- } else {
- wfDebugLog( 'Flow', __METHOD__ . ': Expected UUID but received ' . get_class( $extra['reply-to'] ) );
+ protected static function getTalkPageOwner( $topicId ) {
+ $talkUser = [];
+ // Owner of talk page should always get a reply notification
+ /** @var Workflow|null $workflow */
+ $workflow = Container::get( 'storage' )
+ ->getStorage( 'Workflow' )
+ ->get( UUID::create( $topicId ) );
+ if ( $workflow ) {
+ $title = $workflow->getOwnerTitle();
+ if ( $title->isTalkPage() ) {
+ $user = User::newFromName( $title->getDBkey() );
+ if ( $user && $user->getId() ) {
+ $talkUser[$user->getId()] = $user;
}
}
- $notifiedUsers = self::getCreatorsFromPostIDs( $ids );
+ }
+ return $talkUser;
+ }
- foreach( $mentionedUsers as $uid ) {
- if ( !isset( $notifiedUsers[$uid] ) ) {
- $users[$uid] = User::newFromId( $uid );
- }
- }
- break;
- case 'flow-topic-renamed':
- $users += self::getCreatorsFromPostIDs( array( $extra['topic-workflow'] ) );
- break;
- case 'flow-post-edited':
- case 'flow-post-moderated':
- if ( isset( $extra['reply-to'] ) ) {
- $postId = $extra['reply-to'];
- } else {
- $postId = $extra['post-id'];
- }
- if ( !$postId instanceof UUID ) {
- wfDebugLog( 'Flow', __METHOD__ . ': Non-UUID value provided' );
- break;
+ /**
+ * @param PostRevision $revision
+ * @param Workflow $workflow
+ * @return bool
+ */
+ protected function isFirstPost( PostRevision $revision, Workflow $workflow ) {
+ $postId = $revision->getPostId();
+ $workflowId = $workflow->getId();
+ $replyToId = $revision->getReplyToId();
+
+ // if the post is not a direct reply to the topic, it definitely can't be
+ // first post
+ if ( !$replyToId->equals( $workflowId ) ) {
+ return false;
+ }
+
+ /*
+ * We don't want to go fetch the entire topic tree, so we'll use a crude
+ * technique to figure out if we're dealing with the first post: check if
+ * they were posted at (almost) the exact same time.
+ * If they're more than 1 second apart, it's very likely a not-first-post
+ * (or a very slow server, upgrade your machine!). False positives on the
+ * other side are also very rare: who on earth can refresh the page, read
+ * the post and write a meaningful reply in just 1 second? :)
+ */
+ $diff = $postId->getTimestamp( TS_UNIX ) - $workflowId->getTimestamp( TS_UNIX );
+ return $diff <= 1;
+ }
+
+ /**
+ * Gets ID of topmost post
+ *
+ * This is the lowest-number post, numbering them using a pre-order depth-first
+ * search
+ *
+ * @param array Array of EchoEvents
+ * @return UUID|null Post ID, or null on failure
+ */
+ public function getTopmostPostId( array $bundledEvents ) {
+ $postIds = [];
+ foreach ( $bundledEvents as $event ) {
+ $postId = $event->getExtraParam( 'post-id' );
+ if ( $postId instanceof UUID ) {
+ $postIds[$postId->getAlphadecimal()] = $postId;
}
+ }
- $users += self::getCreatorsFromPostIDs( array( $postId ) );
- break;
- default:
- // Do nothing
+ $rootPaths = $this->treeRepository->findRootPaths( $postIds );
+
+ // We do this so we don't have to walk the whole topic.
+ $deepestCommonRoot = $this->getDeepestCommonRoot( $rootPaths );
+
+ $subtree = $this->treeRepository->fetchSubtreeIdentityMap( $deepestCommonRoot );
+
+ $topmostPostId = $this->getFirstPreorderDepthFirst( $postIds, $deepestCommonRoot, $subtree );
+ return $topmostPostId;
+ }
+
+ /**
+ * Walks a (sub)tree in pre-order depth-first search order and return the first
+ * post ID from a specified list
+ *
+ * @param array $relevantPostIds Associative array mapping alphadecimal post ID to
+ * UUID post ID
+ * @param UUID $root Root node
+ * @param array $tree Tree structure
+ * @return UUID First post ID found, or null on failure
+ */
+ protected function getFirstPreorderDepthFirst( array $relevantPostIds, UUID $root, array $tree ) {
+ $rootAlpha = $root->getAlphadecimal();
+
+ if ( isset( $relevantPostIds[$rootAlpha] ) ) {
+ return $root;
}
- return true;
+
+ if ( isset( $tree[$rootAlpha]['children'] ) ) {
+ $children = array_keys( $tree[$rootAlpha]['children'] );
+ } else {
+ $children = [];
+ }
+
+ foreach ( $children as $child ) {
+ $relevantPostId = $this->getFirstPreorderDepthFirst( $relevantPostIds, UUID::create( $child ), $tree );
+ if ( $relevantPostId !== null ) {
+ return $relevantPostId;
+ }
+ }
+
+ return null;
}
/**
- * Retrieves the post creators from a set of posts.
- * @param array $posts Array of UUIDs or hex representations
- * @return array Associative array, of user ID => User object.
+ * Gets the deepest common root post
+ *
+ * This is the root of the smallest subtree all the posts are in.
+ *
+ * @param array $rootPaths Associative array mapping post IDs to root paths
+ * @return UUID|null Common root, or null on failure
*/
- protected static function getCreatorsFromPostIDs( array $posts ) {
- $users = array();
- /** @var ManagerGroup $storage */
- $storage = Container::get( 'storage' );
-
- $user = new User;
- $actionPermissions = new RevisionActionPermissions( Container::get( 'flow_actions' ), $user );
-
- foreach ( $posts as $postId ) {
- $post = $storage->find(
- 'PostRevision',
- array(
- 'rev_type_id' => UUID::create( $postId )
- ),
- array(
- 'sort' => 'rev_id',
- 'order' => 'DESC',
- 'limit' => 1
- )
- );
+ protected function getDeepestCommonRoot( array $rootPaths ) {
+ if ( count( $rootPaths ) == 0 ) {
+ return null;
+ }
+
+ $deepestRoot = null;
+ $possibleDeepestRoot = null;
- $post = reset( $post );
+ $firstPath = reset( $rootPaths );
+ $pathLength = count( $firstPath );
- if ( $post && $actionPermissions->isAllowed( $post, 'view' ) ) {
- $userid = $post->getCreatorId();
- if ( $userid ) {
- $users[$userid] = User::newFromId( $userid );
+ for ( $i = 0; $i < $pathLength; $i++ ) {
+ $possibleDeepestRoot = $firstPath[$i];
+
+ foreach ( $rootPaths as $path ) {
+ if ( !isset( $path[$i] ) || !$path[$i]->equals( $possibleDeepestRoot ) ) {
+ // Mismatch. Return the last match we found
+ return $deepestRoot;
}
}
+
+ $deepestRoot = $possibleDeepestRoot;
}
- return $users;
+ return $deepestRoot;
}
/**
- * Get the owner of the page if the workflow belongs to a talk page
+ * Moderate or unmoderate Flow notifications associated with a topic.
*
- * @param string|UUID topic workflow id
- * @param array
- * @return array Map from userid to User object
+ * @param UUID $topicId
+ * @param bool $moderated Whether the events need to be moderated or unmoderated
+ * @throws FlowException
*/
- protected static function getTalkPageOwner( $topicId ) {
- $talkUser = array();
- // Owner of talk page should always get a reply notification
- /** @var Workflow|null $workflow */
- $workflow = Container::get( 'storage' )
- ->getStorage( 'Workflow' )
- ->get( UUID::create( $topicId ) );
- if ( $workflow ) {
- $title = $workflow->getOwnerTitle();
- if ( $title->isTalkPage() ) {
- $user = User::newFromName( $title->getDBkey() );
- if ( $user && $user->getId() ) {
- $talkUser[$user->getId()] = $user;
+ public function moderateTopicNotifications( UUID $topicId, $moderated ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
+ // Nothing to do here.
+ return;
+ }
+
+ $title = Title::makeTitle( NS_TOPIC, ucfirst( $topicId->getAlphadecimal() ) );
+ $pageId = $title->getArticleID();
+ \DeferredUpdates::addCallableUpdate( function () use ( $pageId, $moderated ) {
+ $eventMapper = new EchoEventMapper();
+ $eventIds = $eventMapper->fetchIdsByPage( $pageId );
+
+ EchoModerationController::moderate( $eventIds, $moderated );
+ } );
+ }
+
+ /**
+ * Moderate or unmoderate Flow notifications associated with a post within a topic.
+ *
+ * @param UUID $topicId
+ * @param UUID $postId
+ * @param bool $moderated Whether the events need to be moderated or unmoderated
+ * @throws FlowException
+ */
+ public function moderatePostNotifications( UUID $topicId, UUID $postId, $moderated ) {
+ if ( !class_exists( 'EchoEvent' ) ) {
+ // Nothing to do here.
+ return;
+ }
+
+ $title = Title::makeTitle( NS_TOPIC, ucfirst( $topicId->getAlphadecimal() ) );
+ $pageId = $title->getArticleID();
+ \DeferredUpdates::addCallableUpdate( function () use ( $pageId, $postId, $moderated ) {
+ $eventMapper = new \EchoEventMapper();
+ $moderatedPostIdAlpha = $postId->getAlphadecimal();
+ $eventIds = [];
+
+ $events = $eventMapper->fetchByPage( $pageId );
+
+ /** @var EchoEvent $event */
+ foreach ( $events as $event ) {
+ /** @var UUID|string $eventPostId */
+ $eventPostId = $event->getExtraParam( 'post-id' );
+ $eventPostIdAlpha = $eventPostId instanceof UUID ? $eventPostId->getAlphadecimal() : $eventPostId;
+ if ( $eventPostIdAlpha === $moderatedPostIdAlpha ) {
+ $eventIds[] = $event->getId();
}
}
- }
- return $talkUser;
+
+ EchoModerationController::moderate( $eventIds, $moderated );
+ } );
}
}
diff --git a/Flow/includes/Notifications/FlowEnabledOnTalkpagePresentationModel.php b/Flow/includes/Notifications/FlowEnabledOnTalkpagePresentationModel.php
new file mode 100644
index 00000000..6ef9dd38
--- /dev/null
+++ b/Flow/includes/Notifications/FlowEnabledOnTalkpagePresentationModel.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Flow;
+
+class FlowEnabledOnTalkpagePresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return 'chat';
+ }
+
+ public function canRender() {
+ return $this->hasTitle();
+ }
+
+ public function getPrimaryLink() {
+ return [
+ 'url' => $this->event->getTitle()->getFullURL(),
+ 'label' => $this->msg( 'flow-notification-link-text-enabled-on-talkpage' )->text()
+ ];
+ }
+
+ /**
+ * All Flow notifications have the 'Agent' link except this one.
+ *
+ * @return array Empty array
+ */
+ public function getSecondaryLinks() {
+ $userTalkLink = $this->getPageLink(
+ $this->event->getTitle(), '', true
+ );
+ return [ $userTalkLink ];
+ }
+
+ public function getHeaderMessage() {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ return $msg;
+ }
+
+}
diff --git a/Flow/includes/Notifications/FlowPresentationModel.php b/Flow/includes/Notifications/FlowPresentationModel.php
new file mode 100644
index 00000000..67d31db8
--- /dev/null
+++ b/Flow/includes/Notifications/FlowPresentationModel.php
@@ -0,0 +1,221 @@
+<?php
+
+namespace Flow;
+
+use EchoEventPresentationModel;
+use Flow\Model\UUID;
+use Title;
+
+abstract class FlowPresentationModel extends EchoEventPresentationModel {
+
+ protected function hasTitle() {
+ return (bool)$this->event->getTitle();
+ }
+
+ protected function hasValidTopicWorkflowId() {
+ $topicWorkflowId = $this->event->getExtraParam( 'topic-workflow' );
+ return $topicWorkflowId && $topicWorkflowId instanceof UUID;
+ }
+
+ protected function hasValidPostId() {
+ $postId = $this->event->getExtraParam( 'post-id' );
+ return $postId && $postId instanceof UUID;
+ }
+
+ public function getSecondaryLinks() {
+ return [ $this->getAgentLink() ];
+ }
+
+ /**
+ * Return a full url of following format:
+ * https://<site>/wiki/Topic:<topicId>?topic_showPostId=<$firstChronologicallyPostId>&fromnotif=1#flow-post-<$anchorPostID>
+ * @param UUID|null $firstChronologicallyPostId First unread post ID
+ * @param UUID|null $anchorPostId Post ID for anchor (i.e. to scroll to)
+ * @return string
+ */
+ protected function getPostLinkUrl( $firstChronologicallyPostId = null, $anchorPostId = null ) {
+ /** @var UUID $workflowId */
+ $workflowId = $this->event->getExtraParam( 'topic-workflow' );
+ if ( $firstChronologicallyPostId === null ) {
+ /** @var UUID $firstChronologicallyPostId */
+ $firstChronologicallyPostId = $this->event->getExtraParam( 'post-id' );
+ }
+
+ if ( $anchorPostId === null ) {
+ $anchorPostId = $firstChronologicallyPostId;
+ }
+
+ $title = $this->getTopicTitleObj(
+ 'flow-post-' . $anchorPostId->getAlphadecimal()
+ );
+
+ $url = $title->getFullURL(
+ [
+ 'topic_showPostId' => $firstChronologicallyPostId->getAlphadecimal(),
+ 'fromnotif' => 1,
+ ]
+ );
+
+ return $url;
+ }
+
+ /**
+ * Return a full url of following format:
+ * https://<site>/wiki/Topic:<topicId>&fromnotif=1
+ * @return string
+ */
+ protected function getTopicLinkUrl() {
+ /** @var UUID $workflowId */
+ $workflowId = $this->event->getExtraParam( 'topic-workflow' );
+
+ $url = $this->getTopicTitleObj()->getFullURL( [ 'fromnotif' => 1 ] );
+
+ return $url;
+ }
+
+ /**
+ * Get the topic title Title
+ *
+ * @param string $fragment Optional fragment
+ * @return Title Topic title
+ */
+ protected function getTopicTitleObj( $fragment = '' ) {
+ $workflowId = $this->event->getExtraParam( 'topic-workflow' );
+
+ return Title::makeTitleSafe(
+ NS_TOPIC,
+ $workflowId->getAlphadecimal(),
+ $fragment
+ );
+ }
+
+ /**
+ * Return a full url to a board sorted by newest topic
+ * ?topiclist_sortby=newest
+ * @return string
+ */
+ protected function getBoardLinkByNewestTopic() {
+ return [
+ 'url' => $this->getBoardByNewestTopicUrl(),
+ 'label' => $this->msg( 'flow-notification-link-text-view-topics' )->text()
+ ];
+ }
+
+ protected function getBoardByNewestTopicUrl() {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ $url = $urlGenerator->boardLink( $this->event->getTitle(), 'newest' )->getFullURL();
+ return $url;
+ }
+
+ protected function getViewTopicLink() {
+ $title = Title::newFromText( $this->event->getExtraParam( 'topic-workflow' )->getAlphadecimal(), NS_TOPIC );
+ return [
+ 'url' => $title->getFullURL(),
+ 'label' => $this->msg( 'flow-notification-link-text-view-topic' )->text(),
+ ];
+ }
+
+ protected function getBoardByNewestLink() {
+ return $this->getBoardLink( 'newest' );
+ }
+
+ protected function getBoardLink( $sortBy = null ) {
+ $query = $sortBy ? [ 'topiclist_sortby' => $sortBy ] : [];
+ return $this->getPageLink(
+ $this->event->getTitle(), '', true, $query
+ );
+ }
+
+ protected function getContentSnippet() {
+ return $this->event->getExtraParam( 'content' );
+ }
+
+ protected function getTopicTitle( $extraParamName = 'topic-title' ) {
+ $topicTitle = $this->event->getExtraParam( $extraParamName );
+ return $this->truncateTopicTitle( $topicTitle );
+ }
+
+ protected function truncateTopicTitle( $topicTitle ) {
+ return $this->language->embedBidi(
+ $this->language->truncate(
+ $topicTitle,
+ self::SECTION_TITLE_RECOMMENDED_LENGTH,
+ '...',
+ false
+ )
+ );
+ }
+
+ protected function isUserTalkPage() {
+ // Would like to do $this->event->getTitle()->equals( $this->user->getTalkPage() )
+ // but $this->user is private in the parent class
+ $username = $this->getViewingUserForGender();
+ return $this->event->getTitle()->getNamespace() === NS_USER_TALK &&
+ $this->event->getTitle()->getText() === $username;
+ }
+
+ /**
+ * Get a flow-specific watch/unwatch dynamic action link
+ *
+ * @param bool $isTopic Unwatching a topic. If set to false, the
+ * action is unwatching a board
+ * @return array|null Array representing the dynamic action secondary link.
+ * Returns null if either
+ * * The notification came from the user's talk page, as that
+ * page cannot be unwatched.
+ * * The page is not currently watched.
+ */
+ protected function getFlowUnwatchDynamicActionLink( $isTopic = false ) {
+ $title = $isTopic ? $this->getTopicTitleObj() : $this->event->getTitle();
+ $query = [ 'action' => 'unwatch' ];
+ $link = $this->getWatchActionLink( $title );
+ $type = $isTopic ? 'topic' : 'board';
+ $stringPageTitle = $isTopic ? $this->getTopicTitle() : $this->getTruncatedTitleText( $title );
+
+ if ( $this->isUserTalkPage() || !$this->getUser()->isWatched( $title ) ) {
+ return null;
+ }
+
+ $messageKeys = [
+ 'confirmation' => [
+ // notification-dynamic-actions-flow-board-unwatch-confirmation
+ // notification-dynamic-actions-flow-topic-unwatch-confirmation
+ 'title' => $this
+ ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch-confirmation' )
+ ->params(
+ $stringPageTitle,
+ $title->getFullURL(),
+ $this->getUser()->getName()
+ )
+ ->parse(),
+ // notification-dynamic-actions-flow-board-unwatch-confirmation-description
+ // notification-dynamic-actions-flow-topic-unwatch-confirmation-description
+ 'description' => $this
+ ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch-confirmation-description' )
+ ->params(
+ $stringPageTitle,
+ $title->getFullURL(),
+ $this->getUser()->getName()
+ )
+ ->parse(),
+ ],
+ ];
+
+ // Override messages with flow-specific messages
+ $link[ 'data' ][ 'messages' ] = array_replace( $link[ 'data' ][ 'messages' ], $messageKeys );
+
+ // notification-dynamic-actions-flow-board-unwatch
+ // notification-dynamic-actions-flow-topic-unwatch
+ $link['label'] = $this
+ ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch' )
+ ->params(
+ $stringPageTitle,
+ $title->getFullURL( $query ),
+ $this->getUser()->getName()
+ )
+ ->parse();
+
+ return $link;
+ }
+}
diff --git a/Flow/includes/Notifications/HeaderEditedPresentationModel.php b/Flow/includes/Notifications/HeaderEditedPresentationModel.php
new file mode 100644
index 00000000..a61b3915
--- /dev/null
+++ b/Flow/includes/Notifications/HeaderEditedPresentationModel.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Flow;
+
+class HeaderEditedPresentationModel extends FlowPresentationModel {
+ public function getIconType() {
+ return 'flow-topic-renamed';
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->event->getExtraParam( 'revision-id' ) !== null
+ && $this->event->getExtraParam( 'collection-id' ) !== null;
+ }
+
+ public function getPrimaryLink() {
+ $boardLink = $this->getBoardLink();
+ $boardLink['label'] = $this->msg( "notification-links-flow-description-edited-view-page" )->params( $this->getViewingUserForGender() )->text();
+ return $boardLink;
+ }
+
+ public function getSecondaryLinks() {
+ return [
+ $this->getAgentLink(),
+ $this->getDiffLink(),
+ $this->getFlowUnwatchDynamicActionLink()
+ ];
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ $key = 'notification-bundle-header-flow-description-edited';
+ } else {
+ $key = 'notification-header-flow-description-edited';
+ }
+
+ if ( $this->isUserTalkPage() ) {
+ $key .= '-user-talk';
+ }
+
+ return $key;
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $key = "notification-body-flow-description-edited";
+ if ( $this->isUserTalkPage() ) {
+ $key .= '-user-talk';
+ }
+
+ return $this->msg( $key )->plaintextParams( $this->getContentSnippet() );
+ }
+
+ protected function getDiffLink() {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ $anchor = $urlGenerator->diffHeaderLink(
+ $this->event->getTitle(),
+ $this->event->getExtraParam( 'collection-id' ),
+ $this->event->getExtraParam( 'revision-id' )
+ );
+
+ return [
+ 'url' => $anchor->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-changes' )->params( $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => true,
+ ];
+ }
+}
diff --git a/Flow/includes/Notifications/MentionPresentationModel.php b/Flow/includes/Notifications/MentionPresentationModel.php
new file mode 100644
index 00000000..c392dc30
--- /dev/null
+++ b/Flow/includes/Notifications/MentionPresentationModel.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Flow;
+
+class MentionPresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return 'mention';
+ }
+
+ public function canRender() {
+ return $this->hasTitle();
+ }
+
+ public function getPrimaryLink() {
+ $link = [
+ 'url' => $this->event->getTitle()->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-mention' )->text()
+ ];
+
+ // override url, link straight to that specific post/topic
+ if ( $this->getRevisionType() === 'post' ) {
+ $link['url'] = $this->getPostLinkUrl();
+ } elseif ( $this->getRevisionType() === 'post-summary' ) {
+ $link['url'] = $this->getTopicLinkUrl();
+ }
+
+ return $link;
+ }
+
+ public function getSecondaryLinks() {
+ return [
+ $this->getAgentLink(),
+ $this->getBoardByNewestLink(),
+ ];
+ }
+
+ public function getHeaderMessageKey() {
+ return parent::getHeaderMessageKey() . '-' . $this->getRevisionType();
+ }
+
+ public function getHeaderMessage() {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->params( $this->getViewingUserForGender() );
+
+ if ( in_array( $this->getRevisionType(), [ 'post', 'post-summary' ] ) ) {
+ $msg->plaintextParams( $this->getTopicTitle() );
+ }
+
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $msg = $this->msg( "notification-body-{$this->type}" );
+ $msg->plaintextParams( $this->getContentSnippet() );
+ return $msg;
+ }
+
+ protected function getRevisionType() {
+ // we didn't use to include the type to differentiate messages, but
+ // then we only supported posts
+ return $this->event->getExtraParam( 'revision-type', 'post' );
+ }
+}
diff --git a/Flow/includes/Notifications/MentionStatusPresentationModel.php b/Flow/includes/Notifications/MentionStatusPresentationModel.php
new file mode 100644
index 00000000..e68501a5
--- /dev/null
+++ b/Flow/includes/Notifications/MentionStatusPresentationModel.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Flow;
+
+use Title;
+
+class MentionStatusPresentationModel extends \EchoMentionStatusPresentationModel {
+ public function getPrimaryLink() {
+ return array_merge(
+ parent::getPrimaryLink(),
+ [ 'url' => $this->getTopicOrPostUrl() ]
+ );
+ }
+
+ private function getTopicOrPostUrl() {
+ $workflowId = $this->event->getExtraParam( 'topic-workflow' );
+ $postId = $this->event->getExtraParam( 'post-id' );
+ $fragment = '';
+ $query = [ 'fromnotif' => 1 ];
+ if ( $postId ) {
+ $fragment = 'flow-post-' . $postId->getAlphadecimal();
+ $query[ 'topic_showPostId' ] = $postId->getAlphadecimal();
+ }
+ $topicTitle = Title::makeTitleSafe(
+ NS_TOPIC,
+ $workflowId->getAlphadecimal(),
+ $fragment
+ );
+ return $topicTitle->getFullURL( $query );
+ }
+}
diff --git a/Flow/includes/Notifications/NewTopicPresentationModel.php b/Flow/includes/Notifications/NewTopicPresentationModel.php
new file mode 100644
index 00000000..c1e4b258
--- /dev/null
+++ b/Flow/includes/Notifications/NewTopicPresentationModel.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Flow;
+
+class NewTopicPresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return $this->getType();
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId();
+ }
+
+ public function getPrimaryLink() {
+ if ( $this->isBundled() ) {
+ return $this->getBoardLinkByNewestTopic();
+ } else {
+ return $this->getViewTopicLink();
+ }
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isBundled() ) {
+ return [
+ $this->getFlowUnwatchDynamicActionLink()
+ ];
+ } else {
+ return [
+ $this->getAgentLink(),
+ $this->getBoardByNewestLink(),
+ $this->getFlowUnwatchDynamicActionLink()
+ ];
+ }
+ }
+
+ public function getBodyMessage() {
+ if ( $this->isBundled() ) {
+ return false;
+ } elseif ( $this->isUserTalkPage() ) {
+ $msg = $this->msg( "notification-body-flow-new-topic-user-talk" );
+ } else {
+ $msg = $this->msg( "notification-body-flow-new-topic-v2" );
+ }
+
+ $msg->plaintextParams( $this->getContentSnippet() );
+ return $msg;
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-bundle-header-flow-new-topic-user-talk';
+ } else {
+ return 'notification-bundle-header-flow-new-topic';
+ }
+ } else {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-header-flow-new-topic-user-talk';
+ } else {
+ return 'notification-header-flow-new-topic-v2';
+ }
+ }
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+
+ if ( $this->isBundled() ) {
+ $count = $this->getNotificationCountForOutput();
+ // Repeat is B/C until unused parameter is removed from translations
+ $msg->numParams( $count, $count );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ } else {
+ $msg->params( $this->getAgentForOutput() );
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ }
+
+ return $msg;
+ }
+
+ public function getCompactHeaderMessage() {
+ $msg = $this->msg( 'notification-compact-header-flow-new-topic' );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ return $msg;
+ }
+}
diff --git a/Flow/includes/Notifications/Notifications.php b/Flow/includes/Notifications/Notifications.php
index d92d3150..148a8221 100644
--- a/Flow/includes/Notifications/Notifications.php
+++ b/Flow/includes/Notifications/Notifications.php
@@ -1,124 +1,282 @@
<?php
-$notificationTemplate = array(
+$notificationTemplate = [
'category' => 'flow-discussion',
'group' => 'other',
- 'section' => 'message',
- 'formatter-class' => 'Flow\NotificationFormatter',
- 'icon' => 'flow-discussion',
'immediate' => false, // Default
-);
+];
-$notifications = array(
- 'flow-new-topic' => array(
- 'formatter-class' => 'Flow\NewTopicFormatter',
- 'user-locators' => array(
+$newTopicNotification = [
+ 'presentation-model' => 'Flow\\NewTopicPresentationModel',
+ 'bundle' => [
+ 'web' => true,
+ 'email' => true,
+ 'expandable' => true,
+ ],
+ 'icon' => 'flow-new-topic'
+] + $notificationTemplate;
+
+$descriptionEditedNotification = [
+ 'presentation-model' => 'Flow\\HeaderEditedPresentationModel',
+ 'bundle' => [
+ 'web' => true,
+ 'email' => true,
+ ],
+ 'icon' => 'flow-topic-renamed',
+] + $notificationTemplate;
+
+$postEditedNotification = [
+ 'presentation-model' => 'Flow\\PostEditedPresentationModel',
+ 'bundle' => [
+ 'web' => true,
+ 'email' => true,
+ ],
+ 'icon' => 'flow-post-edited',
+] + $notificationTemplate;
+
+$postReplyNotification = [
+ 'presentation-model' => 'Flow\\PostReplyPresentationModel',
+ 'bundle' => [
+ 'web' => true,
+ 'email' => true,
+ 'expandable' => true,
+ ],
+ 'icon' => 'chat',
+] + $notificationTemplate;
+
+$topicRenamedNotification = [
+ 'presentation-model' => 'Flow\\TopicRenamedPresentationModel',
+ 'primary-link' => [
+ 'message' => 'flow-notification-link-text-view-post',
+ 'destination' => 'flow-post'
+ ],
+ 'title-message' => 'flow-notification-rename',
+ 'title-params' => [ 'agent', 'topic-permalink', 'old-subject', 'new-subject', 'flow-title', 'title' ],
+ 'email-subject-message' => 'flow-notification-rename-email-subject',
+ 'email-subject-params' => [ 'agent' ],
+ 'email-body-batch-message' => 'flow-notification-rename-email-batch-body',
+ 'email-body-batch-params' => [ 'agent', 'old-subject', 'new-subject', 'title' ],
+ 'icon' => 'flow-topic-renamed',
+] + $notificationTemplate;
+
+$summaryEditedNotification = [
+ 'presentation-model' => 'Flow\\SummaryEditedPresentationModel',
+ 'bundle' => [
+ 'web' => true,
+ 'email' => true,
+ ],
+ 'primary-link' => [
+ 'message' => 'flow-notification-link-text-view-topic',
+ 'destination' => 'flow-post'
+ ],
+ 'title-message' => 'notification-header-flow-summary-edited',
+ 'title-params' => [ 'subject', 'agent' ],
+ 'email-subject-message' => 'notification-email-subject-flow-summary-edited',
+ 'email-subject-params' => [ 'agent', 'subject' ],
+ 'email-body-batch-message' => 'notification-email-batch-body-flow-summary-edited',
+ 'email-body-batch-params' => [ 'agent', 'subject' ],
+ 'email-body-batch-bundle-message' => 'notification-email-batch-bundle-body-flow-summary-edited',
+ 'email-body-batch-bundle-params' => [ 'agent', 'subject', 'agent-other-display', 'agent-other-count' ],
+ 'icon' => 'flow-topic-renamed',
+] + $notificationTemplate;
+
+$topicResolvedNotification = [
+ 'presentation-model' => 'Flow\\TopicResolvedPresentationModel',
+ 'primary-link' => [
+ 'message' => 'flow-notification-link-text-view-topic',
+ 'destination' => 'flow-post'
+ ],
+ 'title-message' => 'notification-header-flow-topic-resolved',
+ 'title-params' => [ 'subject', 'agent' ],
+ 'email-subject-message' => 'notification-email-subject-flow-topic-resolved',
+ 'email-subject-params' => [ 'agent', 'subject' ],
+ 'email-body-batch-message' => 'notification-email-batch-body-flow-topic-resolved',
+ 'email-body-batch-params' => [ 'agent', 'subject' ],
+ 'icon' => 'flow-topic-resolved',
+] + $notificationTemplate;
+
+$notifications = [
+ 'flow-new-topic' => [
+ 'section' => 'message',
+ 'user-locators' => [
'EchoUserLocator::locateUsersWatchingTitle',
- 'EchoUserLocator::locateTalkPageOwner'
- ),
- 'primary-link' => array(
- 'message' => 'flow-notification-link-text-view-topic',
- 'destination' => 'flow-new-topics'
- ),
- 'title-message' => 'flow-notification-newtopic',
- 'title-params' => array( 'agent', 'flow-title', 'title', 'subject', 'topic-permalink' ),
- 'bundle' => array(
- 'web' => true,
- 'email' => true,
- ),
- 'bundle-type' => 'event',
- 'bundle-message' => 'flow-notification-newtopic-bundle',
- 'bundle-params' => array( 'event-count', 'title', 'new-topics-permalink' ),
- 'email-subject-message' => 'flow-notification-newtopic-email-subject',
- 'email-subject-params' => array( 'agent', 'title' ),
- 'email-body-batch-message' => 'flow-notification-newtopic-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'subject', 'title' ),
- 'email-body-batch-bundle-message' => 'flow-notification-newtopic-email-batch-bundle-body',
- 'email-body-batch-bundle-params' => array( 'event-count', 'title', 'new-topics-permalink' ),
- ) + $notificationTemplate,
- 'flow-post-reply' => array(
- 'user-locators' => array(
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $newTopicNotification,
+ 'flowusertalk-new-topic' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $newTopicNotification,
+ 'flow-post-reply' => [
+ 'section' => 'message',
+ 'user-locators' => [
'Flow\\NotificationsUserLocator::locateUsersWatchingTopic',
- ),
- 'primary-link' => array(
- 'message' => 'flow-notification-link-text-view-post',
- 'destination' => 'flow-post'
- ),
- 'title-message' => 'flow-notification-reply',
- 'title-params' => array( 'agent', 'subject', 'flow-title', 'title', 'post-permalink' ),
- 'bundle' => array(
- 'web' => true,
- 'email' => true,
- ),
- 'bundle-message' => 'flow-notification-reply-bundle',
- 'bundle-params' => array( 'agent', 'subject', 'title', 'post-permalink', 'agent-other-display', 'agent-other-count' ),
- 'email-subject-message' => 'flow-notification-reply-email-subject',
- 'email-subject-params' => array( 'agent', 'subject', 'title' ),
- 'email-body-batch-message' => 'flow-notification-reply-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'subject', 'title' ),
- 'email-body-batch-bundle-message' => 'flow-notification-reply-email-batch-bundle-body',
- 'email-body-batch-bundle-params' => array( 'agent', 'subject', 'title', 'agent-other-display', 'agent-other-count' ),
- ) + $notificationTemplate,
- 'flow-post-edited' => array(
- 'primary-link' => array(
- 'message' => 'flow-notification-link-text-view-post',
- 'destination' => 'flow-post'
- ),
- 'title-message' => 'flow-notification-edit',
- 'title-params' => array( 'agent', 'subject', 'flow-title', 'title', 'post-permalink', 'topic-permalink' ),
- 'bundle' => array(
- 'web' => true,
- 'email' => true,
- ),
- 'bundle-message' => 'flow-notification-edit-bundle',
- 'bundle-params' => array( 'agent', 'subject', 'title', 'post-permalink', 'agent-other-display', 'agent-other-count' ),
- 'email-subject-message' => 'flow-notification-edit-email-subject',
- 'email-subject-params' => array( 'agent' ),
- 'email-body-batch-message' => 'flow-notification-edit-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'subject', 'title' ),
- 'email-body-batch-bundle-message' => 'flow-notification-edit-email-batch-bundle-body',
- 'email-body-batch-bundle-params' => array( 'agent', 'subject', 'title', 'agent-other-display', 'agent-other-count' ),
- ) + $notificationTemplate,
- 'flow-topic-renamed' => array(
- 'primary-link' => array(
- 'message' => 'flow-notification-link-text-view-post',
- 'destination' => 'flow-post'
- ),
- 'title-message' => 'flow-notification-rename',
- 'title-params' => array( 'agent', 'topic-permalink', 'old-subject', 'new-subject', 'flow-title', 'title' ),
- 'email-subject-message' => 'flow-notification-rename-email-subject',
- 'email-subject-params' => array( 'agent' ),
- 'email-body-batch-message' => 'flow-notification-rename-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'old-subject', 'new-subject', 'title' ),
- ) + $notificationTemplate,
- 'flow-mention' => array(
- 'primary-link' => array(
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $postReplyNotification,
+ 'flowusertalk-post-reply' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $postReplyNotification,
+ 'flow-post-edited' => [
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'Flow\\NotificationsUserLocator::locatePostAuthors',
+ ],
+ 'user-filters' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $postEditedNotification,
+ 'flowusertalk-post-edited' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $postEditedNotification,
+ 'flow-topic-renamed' => [
+ 'section' => 'message',
+ 'user-locators' => [
+ 'Flow\\NotificationsUserLocator::locateUsersWatchingTopic',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $topicRenamedNotification,
+ 'flowusertalk-topic-renamed' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $topicRenamedNotification,
+ 'flow-summary-edited' => [
+ 'section' => 'message',
+ 'user-locators' => [
+ 'Flow\\NotificationsUserLocator::locateUsersWatchingTopic',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $summaryEditedNotification,
+ 'flowusertalk-summary-edited' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $summaryEditedNotification,
+ 'flow-description-edited' => [
+ 'section' => 'message',
+ 'user-locators' => [
+ 'EchoUserLocator::locateUsersWatchingTitle',
+ ],
+ 'user-filters' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $descriptionEditedNotification,
+ 'flowusertalk-description-edited' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ 'user-filters' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ ] + $descriptionEditedNotification,
+ 'flow-mention' => [
+ 'category' => 'mention',
+ 'presentation-model' => 'Flow\\MentionPresentationModel',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'Flow\\NotificationsUserLocator::locateMentionedUsers',
+ ],
+ 'primary-link' => [
'message' => 'notification-link-text-view-mention',
'destination' => 'flow-post'
- ),
+ ],
'title-message' => 'flow-notification-mention',
- 'title-params' => array( 'agent', 'post-permalink', 'subject', 'title', 'user' ),
+ 'title-params' => [ 'agent', 'post-permalink', 'subject', 'title', 'user' ],
'email-subject-message' => 'flow-notification-mention-email-subject',
- 'email-subject-params' => array( 'agent', 'flow-title', 'user' ),
+ 'email-subject-params' => [ 'agent', 'flow-title', 'user' ],
'email-body-batch-message' => 'flow-notification-mention-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'subject', 'title', 'user' ),
- ) + $notificationTemplate,
- 'flow-enabled-on-talkpage' => array(
- 'section' => null,
- 'user-locators' => array(
+ 'email-body-batch-params' => [ 'agent', 'subject', 'title', 'user' ],
+ 'icon' => 'mention',
+ ] + $notificationTemplate,
+ 'flow-enabled-on-talkpage' => [
+ 'category' => 'system',
+ 'presentation-model' => 'Flow\\FlowEnabledOnTalkpagePresentationModel',
+ 'section' => 'message',
+ 'user-locators' => [
'EchoUserLocator::locateTalkPageOwner'
- ),
- 'primary-link' => array(
+ ],
+ 'primary-link' => [
'message' => 'flow-notification-link-text-enabled-on-talkpage',
'destination' => 'title'
- ),
+ ],
'title-message' => 'flow-notification-enabled-on-talkpage-title',
- 'title-params' => array( 'agent', 'title' ),
+ 'title-params' => [ 'agent', 'title' ],
'email-subject-message' => 'flow-notification-enabled-on-talkpage-email-subject-message',
- 'email-subject-params' => array( 'agent', 'title' ),
+ 'email-subject-params' => [ 'agent', 'title' ],
'email-body-batch-message' => 'flow-notification-enabled-on-talkpage-email-batch-body',
- 'email-body-batch-params' => array( 'agent', 'title' ),
- ) + $notificationTemplate,
-);
+ 'email-body-batch-params' => [ 'agent', 'title' ],
+ 'icon' => 'chat',
+ ] + $notificationTemplate,
+ 'flow-topic-resolved' => [
+ 'section' => 'message',
+ 'user-locators' => [
+ 'Flow\\NotificationsUserLocator::locateUsersWatchingTopic',
+ ],
+ 'user-filters' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $topicResolvedNotification,
+ 'flowusertalk-topic-resolved' => [
+ 'category' => 'edit-user-talk',
+ 'section' => 'alert',
+ 'user-locators' => [
+ 'EchoUserLocator::locateTalkPageOwner',
+ ],
+ ] + $topicResolvedNotification,
+ 'flow-mention-failure-too-many' => [
+ 'user-locators' => [
+ 'EchoUserLocator::locateEventAgent'
+ ],
+ 'section' => 'alert',
+ 'presentation-model' => 'Flow\\MentionStatusPresentationModel'
+ ] + $notificationTemplate,
+];
return $notifications;
diff --git a/Flow/includes/Notifications/PostEditedPresentationModel.php b/Flow/includes/Notifications/PostEditedPresentationModel.php
new file mode 100644
index 00000000..42e7dcf9
--- /dev/null
+++ b/Flow/includes/Notifications/PostEditedPresentationModel.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Flow;
+
+use Title;
+
+class PostEditedPresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return 'flow-post-edited';
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId()
+ && $this->hasValidPostId();
+ }
+
+ public function getPrimaryLink() {
+ return [
+ 'url' => $this->getPostLinkUrl(),
+ 'label' => $this->msg( 'flow-notification-link-text-view-post' )->text()
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isBundled() ) {
+ $links = [ $this->getBoardLink() ];
+ } else {
+ if ( $this->isUserTalkPage() ) {
+ $links = [
+ $this->getAgentLink(),
+ $this->getDiffLink(),
+ ];
+ } else {
+ $links = [
+ $this->getAgentLink(),
+ $this->getBoardLink(),
+ $this->getDiffLink( false ),
+ ];
+ }
+ }
+
+ $links[] = $this->getFlowUnwatchDynamicActionLink( true );
+
+ return $links;
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ if ( $this->isUserTalkPage() ) {
+ return "notification-bundle-header-flow-post-edited-user-talk";
+ } else {
+ return "notification-bundle-header-flow-post-edited-v2";
+ }
+ } else {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-header-flow-post-edited-user-talk';
+ } else {
+ return 'notification-header-flow-post-edited-v2';
+ }
+ }
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ if ( $this->isUserTalkPage() ) {
+ $msg = $this->msg( 'notification-body-flow-post-edited-user-talk' );
+ } else {
+ $msg = $this->msg( 'notification-body-flow-post-edited-v2' );
+ }
+
+ $msg->plaintextParams( $this->getContentSnippet() );
+ return $msg;
+ }
+
+ protected function getDiffLink( $prioritized = true ) {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ $anchor = $urlGenerator->diffPostLink(
+ Title::newFromText( $this->event->getExtraParam( 'topic-workflow' )->getAlphadecimal(), NS_TOPIC ),
+ $this->event->getExtraParam( 'post-id' ),
+ $this->event->getExtraParam( 'revision-id' )
+ );
+
+ return [
+ 'url' => $anchor->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-changes' )->params( $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => $prioritized,
+ ];
+ }
+}
diff --git a/Flow/includes/Notifications/PostReplyPresentationModel.php b/Flow/includes/Notifications/PostReplyPresentationModel.php
new file mode 100644
index 00000000..7593edbe
--- /dev/null
+++ b/Flow/includes/Notifications/PostReplyPresentationModel.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace Flow;
+
+class PostReplyPresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return $this->isUserTalkPage() ? 'edit-user-talk' : 'chat';
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId()
+ && $this->hasValidPostId();
+ }
+
+ public function getPrimaryLink() {
+ $topmostPostID = null;
+
+ if ( $this->isBundled() ) {
+ // "Strict standards: Only variables should be passed by reference" in older PHP versions
+ $bundledEvents = $this->getBundledEvents();
+
+ $notificationController = Container::get( 'controller.notification' );
+ $firstChronologicallyEvent = end( $bundledEvents );
+ $firstChronologicallyPostId = $firstChronologicallyEvent->getExtraParam( 'post-id' );
+ $bundledEventsIncludingThis = array_merge( [ $this->event ], $bundledEvents );
+ $topmostPostID = $notificationController->getTopmostPostId( $bundledEventsIncludingThis ) ?:
+ $firstChronologicallyPostId;
+
+ } else {
+ $event = $this->event;
+ $firstChronologicallyPostId = $event->getExtraParam( 'post-id' );
+ }
+ return [
+ 'url' => $this->getPostLinkUrl( $firstChronologicallyPostId, $topmostPostID ),
+ 'label' => $this->msg( 'flow-notification-link-text-view-post' )->text(),
+ ];
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isBundled() ) {
+ $links = [ $this->getBoardLink() ];
+ } else {
+ $links = [ $this->getAgentLink(), $this->getBoardLink() ];
+ }
+
+ $links[] = $this->getFlowUnwatchDynamicActionLink( true );
+
+ return $links;
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-bundle-header-flow-post-reply-user-talk';
+ } else {
+ return 'notification-bundle-header-flow-post-reply-v2';
+ }
+ } else {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-header-flow-post-reply-user-talk';
+ } else {
+ return 'notification-header-flow-post-reply';
+ }
+ }
+ }
+
+ public function getHeaderMessage() {
+ if ( $this->isBundled() ) {
+ $count = $this->getNotificationCountForOutput();
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+
+ // Repeat is B/C until unused parameter is removed from translations
+ $msg->numParams( $count, $count );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ return $msg;
+ } else {
+ $msg = parent::getHeaderMessage();
+ $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ return $msg;
+ }
+ }
+
+ public function getCompactHeaderMessage() {
+ $msg = $this->getMessageWithAgent( 'notification-compact-header-flow-post-reply' );
+ $msg->plaintextParams( $this->getContentSnippet() );
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ if ( !$this->isBundled() ) {
+ if ( $this->isUserTalkPage() ) {
+ $msg = $this->msg( "notification-body-flow-post-reply-v2" );
+ } else {
+ $msg = $this->msg( "notification-body-flow-post-reply-user-talk" );
+ }
+ $msg->plaintextParams( $this->getContentSnippet() );
+ return $msg;
+ }
+ }
+
+}
diff --git a/Flow/includes/Notifications/SummaryEditedPresentationModel.php b/Flow/includes/Notifications/SummaryEditedPresentationModel.php
new file mode 100644
index 00000000..f4b5d267
--- /dev/null
+++ b/Flow/includes/Notifications/SummaryEditedPresentationModel.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace Flow;
+
+use Title;
+
+class SummaryEditedPresentationModel extends FlowPresentationModel {
+ public function getIconType() {
+ return 'flow-topic-renamed';
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId()
+ && $this->event->getExtraParam( 'revision-id' ) !== null;
+ }
+
+ public function getPrimaryLink() {
+ return $this->getViewTopicLink();
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isBundled() ) {
+ $links = [ $this->getBoardLink() ];
+ } else {
+ $links = [ $this->getAgentLink(), $this->getBoardLink() ];
+ if ( !$this->isFirstRevision() ) {
+ $links[] = $this->getDiffLink( false );
+ }
+ }
+
+ $links[] = $this->getFlowUnwatchDynamicActionLink( true );
+
+ return $links;
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ $key = "notification-bundle-header-flow-summary-edited";
+ } elseif ( $this->isFirstRevision() ) {
+ $key = 'notification-header-flow-summary-edited-first';
+ } else {
+ $key = 'notification-header-flow-summary-edited';
+ }
+
+ if ( $this->isUserTalkPage() ) {
+ $key .= '-user-talk';
+ }
+
+ return $key;
+ }
+
+ protected function isFirstRevision() {
+ return $this->event->getExtraParam( 'prev-revision-id' ) === null;
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+
+ public function getBodyMessage() {
+ $key = 'notification-body-flow-summary-edited';
+ if ( $this->isUserTalkPage() ) {
+ $key .= '-user-talk';
+ }
+
+ return $this->msg( $key )->plaintextParams( $this->getContentSnippet() );
+ }
+
+ protected function getDiffLink( $prioritized = true ) {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ $anchor = $urlGenerator->diffSummaryLink(
+ Title::newFromText( $this->event->getExtraParam( 'topic-workflow' )->getAlphadecimal(), NS_TOPIC ),
+ $this->event->getExtraParam( 'topic-workflow' ),
+ $this->event->getExtraParam( 'revision-id' )
+ );
+
+ return [
+ 'url' => $anchor->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-changes' )->params( $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => $prioritized,
+ ];
+ }
+}
diff --git a/Flow/includes/Notifications/TopicRenamedPresentationModel.php b/Flow/includes/Notifications/TopicRenamedPresentationModel.php
new file mode 100644
index 00000000..1d2c1538
--- /dev/null
+++ b/Flow/includes/Notifications/TopicRenamedPresentationModel.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Flow;
+
+use Title;
+
+class TopicRenamedPresentationModel extends FlowPresentationModel {
+
+ public function getIconType() {
+ return 'flow-topic-renamed';
+ }
+
+ public function canRender() {
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId();
+ }
+
+ public function getPrimaryLink() {
+ return $this->getViewTopicLink();
+ }
+
+ public function getSecondaryLinks() {
+ if ( $this->isUserTalkPage() ) {
+ $links = [
+ $this->getAgentLink(),
+ $this->getDiffLink(),
+ ];
+ } else {
+ $links = [
+ $this->getAgentLink(),
+ $this->getBoardByNewestLink(),
+ $this->getDiffLink( false ),
+ ];
+ }
+
+ $links[] = $this->getFlowUnwatchDynamicActionLink( true );
+
+ return $links;
+ }
+
+ protected function getHeaderMessageKey() {
+ if ( $this->isUserTalkPage() ) {
+ return 'notification-header-flow-topic-renamed-user-talk';
+ } else {
+ return 'notification-header-flow-topic-renamed-v2';
+ }
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+ $msg->plaintextParams( $this->getTopicTitle( 'old-subject' ) );
+ $msg->plaintextParams( $this->getTopicTitle( 'new-subject' ) );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+
+ protected function getDiffLink( $prioritized = true ) {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ $anchor = $urlGenerator->diffPostLink(
+ Title::newFromText( $this->event->getExtraParam( 'topic-workflow' )->getAlphadecimal(), NS_TOPIC ),
+ $this->event->getExtraParam( 'topic-workflow' ),
+ $this->event->getExtraParam( 'revision-id' )
+ );
+
+ return [
+ 'url' => $anchor->getFullURL(),
+ 'label' => $this->msg( 'notification-link-text-view-changes' )->params( $this->getViewingUserForGender() )->text(),
+ 'description' => '',
+ 'icon' => 'changes',
+ 'prioritized' => $prioritized,
+ ];
+ }
+}
diff --git a/Flow/includes/Notifications/TopicResolvedPresentationModel.php b/Flow/includes/Notifications/TopicResolvedPresentationModel.php
new file mode 100644
index 00000000..d92ff0a1
--- /dev/null
+++ b/Flow/includes/Notifications/TopicResolvedPresentationModel.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Flow;
+
+class TopicResolvedPresentationModel extends FlowPresentationModel {
+ public function getIconType() {
+ // flow-topic-resolved or flow-topic-reopened
+ return $this->event->getExtraParam( 'type' );
+ }
+
+ public function canRender() {
+ $type = $this->event->getExtraParam( 'type' );
+
+ return $this->hasTitle()
+ && $this->hasValidTopicWorkflowId()
+ && in_array( $type, [ 'flow-topic-resolved', 'flow-topic-reopened' ] );
+ }
+
+ public function getPrimaryLink() {
+ return $this->getViewTopicLink();
+ }
+
+ public function getSecondaryLinks() {
+ return [
+ $this->getAgentLink(),
+ $this->getBoardLink(),
+ $this->getFlowUnwatchDynamicActionLink( true ),
+ ];
+ }
+
+ protected function getHeaderMessageKey() {
+ // notification-header-flow-topic-resolved,
+ // notification-header-flow-topic-reopened,
+ // notification-header-flow-topic-resolved-user-talk or
+ // notification-header-flow-topic-reopened-user-talk
+ $key = "notification-header-" . $this->event->getExtraParam( 'type' );
+ if ( $this->isUserTalkPage() ) {
+ $key .= '-user-talk';
+ }
+
+ return $key;
+ }
+
+ public function getHeaderMessage() {
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+ $msg->plaintextParams( $this->getTopicTitle() );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+}
diff --git a/Flow/includes/Notifications/UserLocator.php b/Flow/includes/Notifications/UserLocator.php
index 67e64a76..ff7ccaba 100644
--- a/Flow/includes/Notifications/UserLocator.php
+++ b/Flow/includes/Notifications/UserLocator.php
@@ -4,6 +4,7 @@ namespace Flow;
use EchoEvent;
use EchoUserLocator;
+use Flow\Data\ManagerGroup;
use Flow\Model\UUID;
use Title;
use User;
@@ -22,7 +23,7 @@ class NotificationsUserLocator extends EchoUserLocator {
$workflowId = $event->getExtraParam( 'topic-workflow' );
if ( !$workflowId instanceof UUID ) {
// something wrong; don't notify anyone
- return array();
+ return [];
}
// topic title is just the workflow id, but in NS_TOPIC
@@ -47,4 +48,74 @@ class NotificationsUserLocator extends EchoUserLocator {
return $users;
}
+
+ /**
+ * @param EchoEvent $event
+ * @return User[]
+ */
+ public static function locatePostAuthors( EchoEvent $event ) {
+ $extra = $event->getExtra();
+
+ if ( isset( $extra['reply-to'] ) ) {
+ $postId = $extra['reply-to'];
+ } else {
+ $postId = $extra['post-id'];
+ }
+
+ if ( !$postId instanceof UUID ) {
+ // something wrong; don't notify anyone
+ return [];
+ }
+
+ return self::getCreatorsFromPostIDs( [ $postId ] );
+ }
+
+ /**
+ * @param EchoEvent $event
+ * @return array
+ */
+ public static function locateMentionedUsers( EchoEvent $event ) {
+ $userIds = $event->getExtraParam( 'mentioned-users', [] );
+ return array_map( [ 'User', 'newFromId' ], $userIds );
+ }
+
+ /**
+ * Retrieves the post creators from a set of posts.
+ *
+ * @param array $posts Array of UUIDs or hex representations
+ * @return User[] Associative array, of user ID => User object.
+ */
+ protected static function getCreatorsFromPostIDs( array $posts ) {
+ $users = [];
+ /** @var ManagerGroup $storage */
+ $storage = Container::get( 'storage' );
+
+ $user = new User;
+ $actionPermissions = new RevisionActionPermissions( Container::get( 'flow_actions' ), $user );
+
+ foreach ( $posts as $postId ) {
+ $post = $storage->find(
+ 'PostRevision',
+ [
+ 'rev_type_id' => UUID::create( $postId )
+ ],
+ [
+ 'sort' => 'rev_id',
+ 'order' => 'DESC',
+ 'limit' => 1
+ ]
+ );
+
+ $post = reset( $post );
+
+ if ( $post && $actionPermissions->isAllowed( $post, 'view' ) ) {
+ $userid = $post->getCreatorId();
+ if ( $userid ) {
+ $users[$userid] = User::newFromId( $userid );
+ }
+ }
+ }
+
+ return $users;
+ }
}
diff --git a/Flow/includes/OOUI/BoardDescriptionWidget.php b/Flow/includes/OOUI/BoardDescriptionWidget.php
index 78c17683..e80ceb0c 100644
--- a/Flow/includes/OOUI/BoardDescriptionWidget.php
+++ b/Flow/includes/OOUI/BoardDescriptionWidget.php
@@ -7,15 +7,11 @@ class BoardDescriptionWidget extends \OOUI\Widget {
protected $editButton;
protected $description = '';
- protected $descriptionFormat = 'plaintext';
- public function __construct( array $config = array() ) {
+ public function __construct( array $config = [] ) {
// Parent constructor
parent::__construct( $config );
- if ( isset( $config['descriptionFormat'] ) ) {
- $this->descriptionFormat = $config['descriptionFormat'];
- }
if ( isset( $config['description'] ) ) {
$this->description = $config['description'];
}
@@ -25,24 +21,28 @@ class BoardDescriptionWidget extends \OOUI\Widget {
}
// Edit button
- $this->editButton = new \OOUI\ButtonWidget( array(
+ $this->editButton = new \OOUI\ButtonWidget( [
'framed' => false,
'href' => $editLink,
'label' => wfMessage( 'flow-edit-header-link' )->text(),
'icon' => 'edit',
'flags' => 'progressive',
- 'classes' => array( 'flow-ui-boardDescriptionWidget-editButton' )
- ) );
+ 'classes' => [ 'flow-ui-boardDescriptionWidget-editButton' ]
+ ] );
// Content
$this->contentWrapper = $this->wrapInDiv(
$this->description,
- array( 'flow-ui-boardDescriptionWidget-content' )
+ [ 'flow-ui-boardDescriptionWidget-content', 'mw-parser-output' ]
);
// Initialize
- $this->addClasses( array( 'flow-ui-boardDescriptionWidget', 'flow-ui-boardDescriptionWidget-nojs' ) );
- $this->appendContent( $this->editButton, $this->contentWrapper );
+ $this->addClasses( [ 'flow-ui-boardDescriptionWidget', 'flow-ui-boardDescriptionWidget-nojs' ] );
+
+ if ( $editLink ) {
+ $this->appendContent( $this->wrapInDiv( (string)$this->editButton ) );
+ }
+ $this->appendContent( $this->contentWrapper );
}
/**
@@ -52,7 +52,7 @@ class BoardDescriptionWidget extends \OOUI\Widget {
* @param string $classes Classes to add to the div
* @return OOUI\Tag New div with content
*/
- private function wrapInDiv( $content, $classes ) {
+ private function wrapInDiv( $content, $classes = [] ) {
$tag = new \OOUI\Tag( 'div' );
$tag->addClasses( $classes );
$tag->appendContent( new \OOUI\HtmlSnippet( $content ) );
diff --git a/Flow/includes/Parsoid/ContentFixer.php b/Flow/includes/Parsoid/ContentFixer.php
index 99f421db..6ecda826 100644
--- a/Flow/includes/Parsoid/ContentFixer.php
+++ b/Flow/includes/Parsoid/ContentFixer.php
@@ -4,21 +4,21 @@ namespace Flow\Parsoid;
use DOMDocument;
use DOMXPath;
+use Flow\Conversion\Utils;
use Flow\Exception\FlowException;
use Flow\Model\AbstractRevision;
-use Flow\Model\PostRevision;
use Title;
class ContentFixer {
/**
* @var Fixer[] Array of Fixer objects
*/
- protected $contentFixers = array();
+ protected $contentFixers = [];
/**
* Accepts multiple content fixers.
*
- * @param Fixer $contentFixer...
+ * @param Fixer $contentFixer,...
* @throws FlowException When provided arguments are not an instance of Fixer
*/
public function __construct( Fixer $contentFixer /* [, Fixer $contentFixer2 [, ...]] */ ) {
@@ -77,7 +77,7 @@ class ContentFixer {
* @param string $content HTML from parsoid
* @return DOMDocument
*/
- static public function createDOM( $content ) {
+ public static function createDOM( $content ) {
/*
* The body tag is required otherwise <meta> tags at the top are
* magic'd into <head> rather than kept with the content.
diff --git a/Flow/includes/Parsoid/Extractor/CategoryExtractor.php b/Flow/includes/Parsoid/Extractor/CategoryExtractor.php
index 8b0a0d30..2e706eff 100644
--- a/Flow/includes/Parsoid/Extractor/CategoryExtractor.php
+++ b/Flow/includes/Parsoid/Extractor/CategoryExtractor.php
@@ -6,7 +6,6 @@ use DOMElement;
use Flow\Model\WikiReference;
use Flow\Parsoid\ReferenceFactory;
use Flow\Parsoid\Extractor;
-use Title;
/**
* Runs against page content via Flow\Parsoid\ReferenceExtractor
diff --git a/Flow/includes/Parsoid/Extractor/ExtLinkExtractor.php b/Flow/includes/Parsoid/Extractor/ExtLinkExtractor.php
index 43b46cb1..8ee09cf0 100644
--- a/Flow/includes/Parsoid/Extractor/ExtLinkExtractor.php
+++ b/Flow/includes/Parsoid/Extractor/ExtLinkExtractor.php
@@ -28,4 +28,3 @@ class ExtLinkExtractor implements Extractor {
);
}
}
-
diff --git a/Flow/includes/Parsoid/Extractor/TransclusionExtractor.php b/Flow/includes/Parsoid/Extractor/TransclusionExtractor.php
index 771be952..694f5a60 100644
--- a/Flow/includes/Parsoid/Extractor/TransclusionExtractor.php
+++ b/Flow/includes/Parsoid/Extractor/TransclusionExtractor.php
@@ -27,7 +27,7 @@ class TransclusionExtractor implements Extractor {
$orig = $element->getAttribute( 'data-mw' );
$data = FormatJson::decode( $orig );
if ( !isset( $data->parts ) || !is_array( $data->parts ) ) {
- throw new \Exception( "Missing template target: $orig" );
+ throw new \Exception( "Missing template target: $orig" );
}
$target = null;
foreach ( $data->parts as $part ) {
@@ -37,7 +37,7 @@ class TransclusionExtractor implements Extractor {
}
}
if ( $target === null ) {
- throw new \Exception( "Missing template target: $orig" );
+ throw new \Exception( "Missing template target: $orig" );
}
$templateTarget = Title::newFromText( $target, NS_TEMPLATE );
diff --git a/Flow/includes/Parsoid/Fixer.php b/Flow/includes/Parsoid/Fixer.php
index 93b894c1..7923ecc4 100644
--- a/Flow/includes/Parsoid/Fixer.php
+++ b/Flow/includes/Parsoid/Fixer.php
@@ -3,7 +3,6 @@
namespace Flow\Parsoid;
use DOMNode;
-use Flow\Model\PostRevision;
use Title;
interface Fixer {
diff --git a/Flow/includes/Parsoid/Fixer/BadImageRemover.php b/Flow/includes/Parsoid/Fixer/BadImageRemover.php
index 4d02231e..8f976754 100644
--- a/Flow/includes/Parsoid/Fixer/BadImageRemover.php
+++ b/Flow/includes/Parsoid/Fixer/BadImageRemover.php
@@ -4,9 +4,8 @@ namespace Flow\Parsoid\Fixer;
use DOMElement;
use DOMNode;
-use Flow\Model\PostRevision;
use Flow\Parsoid\Fixer;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Title;
/**
@@ -75,7 +74,7 @@ class BadImageRemover implements Fixer {
// Move up the DOM and remove the typeof="mw:Image" node
$nodeToRemove = $node->parentNode;
- while( $nodeToRemove instanceof DOMElement && $nodeToRemove->getAttribute( 'typeof' ) !== 'mw:Image' ) {
+ while ( $nodeToRemove instanceof DOMElement && $nodeToRemove->getAttribute( 'typeof' ) !== 'mw:Image' ) {
$nodeToRemove = $nodeToRemove->parentNode;
}
if ( !$nodeToRemove ) {
diff --git a/Flow/includes/Parsoid/Fixer/BaseHrefFixer.php b/Flow/includes/Parsoid/Fixer/BaseHrefFixer.php
index 28cb3ff4..536e9ad8 100644
--- a/Flow/includes/Parsoid/Fixer/BaseHrefFixer.php
+++ b/Flow/includes/Parsoid/Fixer/BaseHrefFixer.php
@@ -15,7 +15,7 @@ use Flow\Parsoid\Fixer;
*/
class BaseHrefFixer implements Fixer {
/**
- * @var string $baseHref
+ * @var string
*/
protected $baseHref;
diff --git a/Flow/includes/Parsoid/Fixer/WikiLinkFixer.php b/Flow/includes/Parsoid/Fixer/WikiLinkFixer.php
index 1c9e6cf0..a7c869e8 100644
--- a/Flow/includes/Parsoid/Fixer/WikiLinkFixer.php
+++ b/Flow/includes/Parsoid/Fixer/WikiLinkFixer.php
@@ -2,12 +2,10 @@
namespace Flow\Parsoid\Fixer;
-use ArrayObject;
use DOMElement;
use DOMNode;
-use Flow\Model\PostRevision;
use Flow\Parsoid\Fixer;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use LinkBatch;
use Linker;
use Title;
@@ -72,7 +70,7 @@ class WikiLinkFixer implements Fixer {
}
// gather existing link attributes
- $attributes = array();
+ $attributes = [];
foreach ( $node->attributes as $attribute ) {
$attributes[$attribute->name] = $attribute->value;
}
diff --git a/Flow/includes/Parsoid/ReferenceExtractor.php b/Flow/includes/Parsoid/ReferenceExtractor.php
index 94450529..47bc0537 100644
--- a/Flow/includes/Parsoid/ReferenceExtractor.php
+++ b/Flow/includes/Parsoid/ReferenceExtractor.php
@@ -3,6 +3,7 @@
namespace Flow\Parsoid;
use DOMXPath;
+use Flow\Conversion\Utils;
use Flow\Exception\InvalidReferenceException;
use Flow\Model\Reference;
use Flow\Model\UUID;
@@ -44,7 +45,7 @@ class ReferenceExtractor {
);
} else {
throw new \Exception( "No extractors available for $objectType" );
- return array();
+ return [];
}
}
@@ -59,11 +60,11 @@ class ReferenceExtractor {
protected function extractReferences( ReferenceFactory $factory, array $extractors, $text ) {
$dom = Utils::createDOM( $text );
- $output = array();
+ $output = [];
$xpath = new DOMXPath( $dom );
- foreach( $extractors as $extractor ) {
+ foreach ( $extractors as $extractor ) {
$elements = $xpath->query( $extractor->getXPath() );
if ( !$elements ) {
@@ -71,7 +72,7 @@ class ReferenceExtractor {
throw new MWException( "Malformed xpath from $class: " . $extractor->getXPath() );
}
- foreach( $elements as $element ) {
+ foreach ( $elements as $element ) {
try {
$ref = $extractor->perform( $factory, $element );
} catch ( InvalidReferenceException $e ) {
diff --git a/Flow/includes/Parsoid/ReferenceFactory.php b/Flow/includes/Parsoid/ReferenceFactory.php
index 5e768be9..713401fa 100644
--- a/Flow/includes/Parsoid/ReferenceFactory.php
+++ b/Flow/includes/Parsoid/ReferenceFactory.php
@@ -2,6 +2,7 @@
namespace Flow\Parsoid;
+use Flow\Conversion\Utils;
use Flow\Model\URLReference;
use Flow\Model\UUID;
use Flow\Model\WikiReference;
@@ -54,6 +55,7 @@ class ReferenceFactory {
*/
public function createUrlReference( $refType, $value ) {
return new URLReference(
+ UUID::create(),
$this->wikiId,
$this->workflowId,
$this->title,
@@ -82,6 +84,7 @@ class ReferenceFactory {
}
return new WikiReference(
+ UUID::create(),
$this->wikiId,
$this->workflowId,
$this->title,
diff --git a/Flow/includes/ReferenceClarifier.php b/Flow/includes/ReferenceClarifier.php
index 89eb12ad..d85a5b54 100644
--- a/Flow/includes/ReferenceClarifier.php
+++ b/Flow/includes/ReferenceClarifier.php
@@ -16,17 +16,17 @@ class ReferenceClarifier {
function __construct( ManagerGroup $storage, UrlGenerator $urlGenerator ) {
$this->storage = $storage;
$this->urlGenerator = $urlGenerator;
- $this->referenceCache = array();
+ $this->referenceCache = [];
}
public function getWhatLinksHereProps( $row, Title $from, Title $to ) {
- $ids = array();
- $props = array();
+ $ids = [];
+ $props = [];
$references = $this->getWikiReferences( $from, $to );
// Collect referenced workflow ids and load them so we can generate
// links to their pages
- foreach( $references as $reference ) {
+ foreach ( $references as $reference ) {
$id = $reference->getWorkflowId();
// utilize array key to de-duplicate
$ids[$id->getAlphadecimal()] = $id;
@@ -41,7 +41,7 @@ class ReferenceClarifier {
// * flow-whatlinkshere-post
// * flow-whatlinkshere-post-summary
// Topic is plain text and do not have links.
- foreach( $references as $reference ) {
+ foreach ( $references as $reference ) {
if ( $reference->getType() === WikiReference::TYPE_CATEGORY ) {
// While it might make sense to have backlinks from categories to
// a page in what links here, thats not what mediawiki currently does.
@@ -67,7 +67,7 @@ class ReferenceClarifier {
* @return WikiReference[]
*/
public function getWikiReferences( Title $from, Title $to ) {
- if ( ! isset( $this->referenceCache[$from->getPrefixedDBkey()] ) ) {
+ if ( !isset( $this->referenceCache[$from->getPrefixedDBkey()] ) ) {
$this->loadReferencesForPage( $from );
}
@@ -76,7 +76,7 @@ class ReferenceClarifier {
return isset( $this->referenceCache[$fromT][$toT] )
? $this->referenceCache[$fromT][$toT]
- : array();
+ : [];
}
/**
@@ -100,24 +100,17 @@ class ReferenceClarifier {
protected function loadReferencesForPage( Title $from ) {
/** @var Reference[] $allReferences */
- $allReferences = array();
+ $allReferences = [];
- foreach( array( 'WikiReference', 'URLReference' ) as $refType ) {
+ foreach ( [ 'WikiReference', 'URLReference' ] as $refType ) {
// find() returns null for error or empty result
-
- $conds = array(
- 'ref_src_namespace' => $from->getNamespace(),
- 'ref_src_title' => $from->getDBkey(),
- );
-
- global $wgFlowMigrateReferenceWiki;
- if ( ! $wgFlowMigrateReferenceWiki ) {
- $conds['ref_src_wiki'] = wfWikiId();
- }
-
$res = $this->storage->find(
$refType,
- $conds
+ [
+ 'ref_src_wiki' => wfWikiID(),
+ 'ref_src_namespace' => $from->getNamespace(),
+ 'ref_src_title' => $from->getDBkey(),
+ ]
);
if ( $res ) {
@@ -135,10 +128,10 @@ class ReferenceClarifier {
}
}
- $cache = array();
- foreach( $allReferences as $reference ) {
+ $cache = [];
+ foreach ( $allReferences as $reference ) {
if ( !isset( $cache[$reference->getTargetIdentifier()] ) ) {
- $cache[$reference->getTargetIdentifier()] = array();
+ $cache[$reference->getTargetIdentifier()] = [];
}
$cache[$reference->getTargetIdentifier()][] = $reference;
diff --git a/Flow/includes/Repository/MultiGetList.php b/Flow/includes/Repository/MultiGetList.php
index 7cfca54a..9219177d 100644
--- a/Flow/includes/Repository/MultiGetList.php
+++ b/Flow/includes/Repository/MultiGetList.php
@@ -2,45 +2,43 @@
namespace Flow\Repository;
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Model\UUID;
-use Flow\Container;
-use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
class MultiGetList {
/**
- * @var BufferedCache
+ * @var FlowObjectCache
*/
protected $cache;
/**
- * @param BufferedCache $cache
+ * @param FlowObjectCache $cache
*/
- public function __construct( BufferedCache $cache ) {
+ public function __construct( FlowObjectCache $cache ) {
$this->cache = $cache;
}
/**
- * @param string $key
+ * @param string $treeType
* @param array $ids
* @param callable $loadCallback
* @return array
- * @throws InvalidInputException
+ * @throws InvalidParameterException
*/
- public function get( $key, array $ids, $loadCallback ) {
- $key = implode( ':', (array) $key );
- $cacheKeys = array();
+ public function get( $treeType, array $ids, $loadCallback ) {
+ $cacheKeys = [];
foreach ( $ids as $id ) {
if ( $id instanceof UUID ) {
- $cacheId = $id->getAlphadecimal();
- } elseif ( !is_scalar( $id ) ) {
- $type = is_object( $id ) ? get_class( $id ) : gettype( $id );
- throw new InvalidInputException( 'Not scalar:' . $type, 'invalid-input' );
- } else {
$cacheId = $id;
+ } elseif ( is_scalar( $id ) ) {
+ $cacheId = UUID::create( $id );
+ } else {
+ $type = is_object( $id ) ? get_class( $id ) : gettype( $id );
+ throw new InvalidParameterException( 'Not scalar:' . $type, 'invalid-input' );
}
- $cacheKeys[wfForeignMemcKey( 'flow', '', $key, $cacheId, Container::get( 'cache.version' ) )] = $id;
+ $cacheKeys[ TreeCacheKey::build( $treeType, $cacheId ) ] = $id;
}
return $this->getByKey( $cacheKeys, $loadCallback );
}
@@ -52,9 +50,9 @@ class MultiGetList {
*/
public function getByKey( array $cacheKeys, $loadCallback ) {
if ( !$cacheKeys ) {
- return array();
+ return [];
}
- $result = array();
+ $result = [];
$multiRes = $this->cache->getMulti( array_keys( $cacheKeys ) );
if ( $multiRes === false ) {
// Falls through to query only backend
@@ -64,7 +62,9 @@ class MultiGetList {
// returns false for not found keys.
$multiRes = array_filter(
$multiRes,
- function( $val ) { return $val !== false; }
+ function ( $val ) {
+ return $val !== false;
+ }
);
foreach ( $multiRes as $key => $value ) {
$idx = $cacheKeys[$key];
@@ -83,7 +83,7 @@ class MultiGetList {
// storage failure of some sort
return $result;
}
- $invCacheKeys = array();
+ $invCacheKeys = [];
foreach ( $cacheKeys as $cacheKey => $id ) {
if ( $id instanceof UUID ) {
$id = $id->getAlphadecimal();
diff --git a/Flow/includes/Repository/RootPostLoader.php b/Flow/includes/Repository/RootPostLoader.php
index 9f688753..8564b309 100644
--- a/Flow/includes/Repository/RootPostLoader.php
+++ b/Flow/includes/Repository/RootPostLoader.php
@@ -47,16 +47,16 @@ class RootPostLoader {
$rootId = $this->treeRepo->findRoot( $postId );
$found = $this->storage->findMulti(
'PostRevision',
- array(
- array( 'rev_type_id' => $postId ),
- array( 'rev_type_id' => $rootId ),
- ),
- array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
+ [
+ [ 'rev_type_id' => $postId ],
+ [ 'rev_type_id' => $rootId ],
+ ],
+ [ 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 ]
);
- $res = array(
+ $res = [
'post' => null,
'root' => null,
- );
+ ];
if ( !$found ) {
return $res;
}
@@ -65,7 +65,7 @@ class RootPostLoader {
$post = reset( $result );
if ( $postId->equals( $post->getPostId() ) ) {
$res['post'] = $post;
- } elseif( $rootId->equals( $post->getPostId() ) ) {
+ } elseif ( $rootId->equals( $post->getPostId() ) ) {
$res['root'] = $post;
} else {
throw new InvalidDataException( 'Unmatched: ' . $post->getPostId()->getAlphadecimal() );
@@ -84,7 +84,7 @@ class RootPostLoader {
* @throws InvalidDataException
*/
public function get( $topicId ) {
- $result = $this->getMulti( array( $topicId ) );
+ $result = $this->getMulti( [ $topicId ] );
return reset( $result );
}
@@ -95,21 +95,21 @@ class RootPostLoader {
*/
public function getMulti( array $topicIds ) {
if ( !$topicIds ) {
- return array();
+ return [];
}
// load posts for all located post ids
- $allPostIds = $this->fetchRelatedPostIds( $topicIds );
- $queries = array();
+ $allPostIds = $this->fetchRelatedPostIds( $topicIds );
+ $queries = [];
foreach ( $allPostIds as $postId ) {
- $queries[] = array( 'rev_type_id' => $postId );
+ $queries[] = [ 'rev_type_id' => $postId ];
}
- $found = $this->storage->findMulti( 'PostRevision', $queries, array(
+ $found = $this->storage->findMulti( 'PostRevision', $queries, [
'sort' => 'rev_id',
'order' => 'DESC',
'limit' => 1,
- ) );
+ ] );
/** @var PostRevision[] $posts */
- $posts = $children = array();
+ $posts = $children = [];
foreach ( $found as $indexResult ) {
$post = reset( $indexResult ); // limit => 1 means only 1 result per query
if ( isset( $posts[$post->getPostId()->getAlphadecimal()] ) ) {
@@ -117,7 +117,7 @@ class RootPostLoader {
}
$posts[$post->getPostId()->getAlphadecimal()] = $post;
}
- $prettyPostIds = array();
+ $prettyPostIds = [];
foreach ( $allPostIds as $id ) {
$prettyPostIds[] = $id->getAlphadecimal();
}
@@ -125,7 +125,7 @@ class RootPostLoader {
if ( $missing ) {
// convert string uuid's into UUID objects
/** @var UUID[] $missingUUID */
- $missingUUID = array_map( array( 'Flow\Model\UUID', 'create' ), $missing );
+ $missingUUID = array_map( [ 'Flow\Model\UUID', 'create' ], $missing );
// we'll need to know parents to add stub post correctly in post hierarchy
$parents = $this->treeRepo->fetchParentMap( $missingUUID );
@@ -146,7 +146,7 @@ class RootPostLoader {
$post->setReplyToId( $parents[$postId->getAlphadecimal()] );
$posts[$postId->getAlphadecimal()] = $post;
- wfWarn( 'Missing Posts: ' . FormatJson::encode( $missing ) );
+ wfDebugLog( 'Flow', __METHOD__ . ': Missing posts: ' . FormatJson::encode( $missing ) );
}
}
// another helper to catch bugs in dev
@@ -167,7 +167,7 @@ class RootPostLoader {
}
foreach ( $posts as $postId => $post ) {
- $postChildren = array();
+ $postChildren = [];
$postDepth = 0;
// link parents to their children
@@ -191,7 +191,7 @@ class RootPostLoader {
// return only the requested posts, rest are available as children.
// Return in same order as requested
/** @var PostRevision[] $roots */
- $roots = array();
+ $roots = [];
foreach ( $topicIds as $id ) {
$roots[$id->getAlphadecimal()] = $posts[$id->getAlphadecimal()];
}
@@ -215,13 +215,13 @@ class RootPostLoader {
// It should have returned at least $postIds
// TODO: log errors?
$res = $postIds;
- } elseif( count( $nodeList ) === 1 ) {
+ } elseif ( count( $nodeList ) === 1 ) {
$res = reset( $nodeList );
} else {
$res = call_user_func_array( 'array_merge', $nodeList );
}
- $retval = array();
+ $retval = [];
foreach ( $res as $id ) {
$retval[$id->getAlphadecimal()] = $id;
}
diff --git a/Flow/includes/Repository/TreeCacheKey.php b/Flow/includes/Repository/TreeCacheKey.php
new file mode 100644
index 00000000..f4d8ef9f
--- /dev/null
+++ b/Flow/includes/Repository/TreeCacheKey.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Flow\Repository;
+
+use Flow\Container;
+use Flow\Model\UUID;
+
+class TreeCacheKey {
+
+ /**
+ * Generate the following cache keys
+ * flow:tree:subtree|parent|rootpath:<object id>:<cache version>
+ * For example:
+ * flow:tree:parent:srkbd1u0mzz81x51:4.7
+ *
+ * @param string $treeType
+ * @param UUID $id
+ * @return string
+ */
+ public static function build( $treeType, UUID $id ) {
+ return wfForeignMemcKey( 'flow', '', 'tree', $treeType, $id->getAlphadecimal(), Container::get( 'cache.version' ) );
+ }
+}
diff --git a/Flow/includes/Repository/TreeRepository.php b/Flow/includes/Repository/TreeRepository.php
index ee262a1e..4478acb3 100644
--- a/Flow/includes/Repository/TreeRepository.php
+++ b/Flow/includes/Repository/TreeRepository.php
@@ -2,12 +2,10 @@
namespace Flow\Repository;
-use Flow\Data\BufferedCache;
+use Flow\Data\FlowObjectCache;
use Flow\Data\ObjectManager;
use Flow\DbFactory;
use Flow\Model\UUID;
-use BagOStuff;
-use Flow\Container;
use Flow\Exception\DataModelException;
/*
@@ -45,63 +43,55 @@ class TreeRepository {
protected $dbFactory;
/**
- * @var BufferedCache
+ * @var FlowObjectCache
*/
protected $cache;
/**
* @param DbFactory $dbFactory Factory to source connection objects from
- * @param BufferedCache $cache
+ * @param FlowObjectCache $cache
*/
- public function __construct( DbFactory $dbFactory, BufferedCache $cache ) {
+ public function __construct( DbFactory $dbFactory, FlowObjectCache $cache ) {
$this->dbFactory = $dbFactory;
$this->cache = $cache;
}
/**
* A helper function to generate cache keys for tree repository
- * @param string $type
- * @param \Flow\Model\UUID $uuid
+ * @param string $treeType
+ * @param UUID $uuid
* @return string
*/
- protected function cacheKey( $type, UUID $uuid ) {
- return wfForeignMemcKey( 'flow', '', 'tree', $type, $uuid->getAlphadecimal(), Container::get( 'cache.version' ) );
+ protected function cacheKey( $treeType, UUID $uuid ) {
+ return TreeCacheKey::build( $treeType, $uuid );
}
/**
* Insert a new tree node. If ancestor === null then this node is a root.
*
- * To also write this to cache we would have to read our own write, which
- * isn't guaranteed during a node split. Master reads can potentially be
- * a different server than master writes.
- *
- * The way to do it without that is to CAS update memcache, assuming it currently
- * has what we need
+ * Also delete cache entries related to this tree.
*/
public function insert( UUID $descendant, UUID $ancestor = null ) {
- $subtreeKey = $this->cacheKey( 'subtree', $descendant );
- $parentKey = $this->cacheKey( 'parent', $descendant );
- $pathKey = $this->cacheKey( 'rootpath', $descendant );
- $this->cache->set( $subtreeKey, array( $descendant ) );
+ $this->cache->delete( $this->cacheKey( 'subtree', $descendant ) );
+ $this->cache->delete( $this->cacheKey( 'parent', $descendant ) );
+ $this->cache->delete( $this->cacheKey( 'rootpath', $descendant ) );
+
if ( $ancestor === null ) {
- $this->cache->set( $parentKey, null );
- $this->cache->set( $pathKey, array( $descendant ) );
- $path = array( $descendant );
+ $path = [ $descendant ];
} else {
- $this->cache->set( $parentKey, $ancestor );
$path = $this->findRootPath( $ancestor );
$path[] = $descendant;
- $this->cache->set( $pathKey, $path );
}
+ $this->deleteSubtreeCache( $descendant, $path );
$dbw = $this->dbFactory->getDB( DB_MASTER );
$res = $dbw->insert(
$this->tableName,
- array(
+ [
'tree_descendant_id' => $descendant->getBinary(),
'tree_ancestor_id' => $descendant->getBinary(),
'tree_depth' => 0,
- ),
+ ],
__METHOD__
);
@@ -120,17 +110,17 @@ class TreeRepository {
$res = $dbw->insertSelect(
$this->tableName,
$this->tableName,
- array(
+ [
'tree_descendant_id' => $dbw->addQuotes( $descendant->getBinary() ),
'tree_ancestor_id' => 'tree_ancestor_id',
'tree_depth' => 'tree_depth + 1',
- ),
- array(
+ ],
+ [
'tree_descendant_id' => $ancestor->getBinary(),
- ),
+ ],
__METHOD__
);
- } catch( \DBQueryError $e ) {
+ } catch ( \DBQueryError $e ) {
$res = false;
/*
@@ -149,8 +139,8 @@ class TreeRepository {
$rows = $dbw->select(
$this->tableName,
- array( 'tree_depth', 'tree_ancestor_id' ),
- array( 'tree_descendant_id' => $ancestor->getBinary() ),
+ [ 'tree_depth', 'tree_ancestor_id' ],
+ [ 'tree_descendant_id' => $ancestor->getBinary() ],
__METHOD__
);
@@ -158,11 +148,11 @@ class TreeRepository {
foreach ( $rows as $row ) {
$res &= $dbw->insert(
$this->tableName,
- array(
+ [
'tree_descendant_id' => $descendant->getBinary(),
'tree_ancestor_id' => $row->tree_ancestor_id,
'tree_depth' => $row->tree_depth + 1,
- ),
+ ],
__METHOD__
);
}
@@ -172,39 +162,50 @@ class TreeRepository {
}
if ( !$res ) {
- $this->cache->delete( $parentKey );
- $this->cache->delete( $pathKey );
throw new DataModelException( 'Failed inserting new tree node', 'process-data' );
}
- $this->appendToSubtreeCache( $descendant, $path );
+
return true;
}
- protected function appendToSubtreeCache( UUID $descendant, array $rootPath ) {
- $callback = function( BagOStuff $cache, $key, $value ) use( $descendant ) {
- if ( $value === false ) {
- return false;
- }
- $value[$descendant->getAlphadecimal()] = $descendant;
- return $value;
- };
-
- // This could be pretty slow if there is contention
+ protected function deleteSubtreeCache( UUID $descendant, array $rootPath ) {
foreach ( $rootPath as $subtreeRoot ) {
$cacheKey = $this->cacheKey( 'subtree', $subtreeRoot );
- $success = $this->cache->merge( $cacheKey, $callback );
+ $this->cache->delete( $cacheKey );
+ }
+ }
- // $success is always true if bufferCache starts with begin()
- // if we failed to CAS new data, kill the cached value so it'll be
- // re-fetched from DB
- if ( !$success ) {
- $this->cache->delete( $cacheKey );
- }
+ /**
+ * Deletes a descendant from the tree repo.
+ *
+ * @param UUID $descendant
+ * @return bool
+ */
+ public function delete( UUID $descendant ) {
+ $dbw = $this->dbFactory->getDB( DB_MASTER );
+ $res = $dbw->delete(
+ $this->tableName,
+ [
+ 'tree_descendant_id' => $descendant->getBinary(),
+ ],
+ __METHOD__
+ );
+
+ if ( $res ) {
+ $subtreeKey = $this->cacheKey( 'subtree', $descendant );
+ $parentKey = $this->cacheKey( 'parent', $descendant );
+ $pathKey = $this->cacheKey( 'rootpath', $descendant );
+
+ $this->cache->delete( $subtreeKey );
+ $this->cache->delete( $parentKey );
+ $this->cache->delete( $pathKey );
}
+
+ return $res;
}
public function findParent( UUID $descendant ) {
- $map = $this->fetchParentMap( array( $descendant ) );
+ $map = $this->fetchParentMap( [ $descendant ] );
return isset( $map[$descendant->getAlphadecimal()] ) ? $map[$descendant->getAlphadecimal()] : null;
}
@@ -216,40 +217,40 @@ class TreeRepository {
*/
public function findRootPaths( array $descendants ) {
// alphadecimal => cachekey
- $cacheKeys = array();
+ $cacheKeys = [];
// alphadecimal => cache result ( distance => parent uuid obj )
- $cacheValues = array();
+ $cacheValues = [];
// list of binary values for db query
- $missingValues = array();
+ $missingValues = [];
// alphadecimal => distance => parent uuid obj
- $paths = array();
+ $paths = [];
- foreach( $descendants as $descendant ) {
+ foreach ( $descendants as $descendant ) {
$cacheKeys[$descendant->getAlphadecimal()] = $this->cacheKey( 'rootpath', $descendant );
}
$cacheResult = $this->cache->getMulti( array_values( $cacheKeys ) );
- foreach( $descendants as $descendant ) {
+ foreach ( $descendants as $descendant ) {
$alpha = $descendant->getAlphadecimal();
if ( isset( $cacheResult[$cacheKeys[$alpha]] ) ) {
$cacheValues[$alpha] = $cacheResult[$cacheKeys[$alpha]];
} else {
$missingValues[] = $descendant->getBinary();
- $paths[$alpha] = array();
+ $paths[$alpha] = [];
}
}
- if ( ! count( $missingValues ) ) {
+ if ( !count( $missingValues ) ) {
return $cacheValues;
}
$dbr = $this->dbFactory->getDB( DB_SLAVE );
$res = $dbr->select(
$this->tableName,
- array( 'tree_descendant_id', 'tree_ancestor_id', 'tree_depth' ),
- array(
+ [ 'tree_descendant_id', 'tree_ancestor_id', 'tree_depth' ],
+ [
'tree_descendant_id' => $missingValues,
- ),
+ ],
__METHOD__
);
@@ -262,7 +263,7 @@ class TreeRepository {
$paths[$alpha][$row->tree_depth] = UUID::create( $row->tree_ancestor_id );
}
- foreach( $paths as $descendantId => &$path ) {
+ foreach ( $paths as $descendantId => &$path ) {
if ( !$path ) {
$path = null;
continue;
@@ -281,25 +282,25 @@ class TreeRepository {
/**
* Finds the root path for a single post ID.
- * @param UUID $descendant Post ID
+ * @param UUID $descendant Post ID
* @return UUID[]|null Path to the root of that node.
*/
public function findRootPath( UUID $descendant ) {
- $paths = $this->findRootPaths( array( $descendant ) );
+ $paths = $this->findRootPaths( [ $descendant ] );
return isset( $paths[$descendant->getAlphadecimal()] ) ? $paths[$descendant->getAlphadecimal()] : null;
}
/**
* Finds the root posts of a list of posts.
- * @param UUID[] $descendants Array of PostRevision objects to find roots for.
+ * @param UUID[] $descendants Array of PostRevision objects to find roots for.
* @return UUID[] Associative array of post ID (as hex) to UUID object representing its root.
*/
public function findRoots( array $descendants ) {
$paths = $this->findRootPaths( $descendants );
- $roots = array();
+ $roots = [];
- foreach( $descendants as $descendant ) {
+ foreach ( $descendants as $descendant ) {
$alpha = $descendant->getAlphadecimal();
if ( isset( $paths[$alpha] ) ) {
$roots[$alpha] = $paths[$alpha][0];
@@ -344,7 +345,7 @@ class TreeRepository {
public function fetchSubtreeIdentityMap( $roots ) {
$roots = ObjectManager::makeArray( $roots );
if ( !$roots ) {
- return array();
+ return [];
}
$nodes = $this->fetchSubtreeNodeList( $roots );
if ( !$nodes ) {
@@ -354,10 +355,10 @@ class TreeRepository {
} else {
$parentMap = $this->fetchParentMap( call_user_func_array( 'array_merge', $nodes ) );
}
- $identityMap = array();
+ $identityMap = [];
foreach ( $parentMap as $child => $parent ) {
if ( !array_key_exists( $child, $identityMap ) ) {
- $identityMap[$child] = array( 'children' => array() );
+ $identityMap[$child] = [ 'children' => [] ];
}
// Root nodes have no parent
if ( $parent !== null ) {
@@ -377,7 +378,7 @@ class TreeRepository {
throw new DataModelException( 'No root exists in the identityMap', 'process-data' );
}
- return $identityMap[$root];
+ return $identityMap[$root->getAlphadecimal()];
}
public function fetchFullTree( UUID $nodeId ) {
@@ -394,16 +395,16 @@ class TreeRepository {
public function fetchSubtreeNodeList( array $roots ) {
$list = new MultiGetList( $this->cache );
$res = $list->get(
- array( 'tree', 'subtree' ),
+ 'subtree',
$roots,
- array( $this, 'fetchSubtreeNodeListFromDb' )
+ [ $this, 'fetchSubtreeNodeListFromDb' ]
);
if ( $res === false ) {
wfDebugLog( 'Flow', __METHOD__ . ': Failure fetching node list from cache' );
return false;
}
// $idx is a binary UUID
- $retval = array();
+ $retval = [];
foreach ( $res as $idx => $val ) {
$retval[UUID::create( $idx )->getAlphadecimal()] = $val;
}
@@ -413,10 +414,10 @@ class TreeRepository {
public function fetchSubtreeNodeListFromDb( array $roots ) {
$res = $this->dbFactory->getDB( DB_SLAVE )->select(
$this->tableName,
- array( 'tree_ancestor_id', 'tree_descendant_id' ),
- array(
+ [ 'tree_ancestor_id', 'tree_descendant_id' ],
+ [
'tree_ancestor_id' => UUID::convertUUIDs( $roots ),
- ),
+ ],
__METHOD__
);
if ( $res === false ) {
@@ -424,9 +425,9 @@ class TreeRepository {
return false;
}
if ( !$res ) {
- return array();
+ return [];
}
- $nodes = array();
+ $nodes = [];
foreach ( $res as $node ) {
$ancestor = UUID::create( $node->tree_ancestor_id );
$descendant = UUID::create( $node->tree_descendant_id );
@@ -443,9 +444,9 @@ class TreeRepository {
public function fetchParentMap( array $nodes ) {
$list = new MultiGetList( $this->cache );
return $list->get(
- array( 'tree', 'parent' ),
+ 'parent',
$nodes,
- array( $this, 'fetchParentMapFromDb' )
+ [ $this, 'fetchParentMapFromDb' ]
);
}
@@ -459,17 +460,17 @@ class TreeRepository {
$dbr = $this->dbFactory->getDB( DB_SLAVE );
$res = $dbr->select(
$this->tableName,
- array( 'tree_ancestor_id', 'tree_descendant_id' ),
- array(
+ [ 'tree_ancestor_id', 'tree_descendant_id' ],
+ [
'tree_descendant_id' => UUID::convertUUIDs( $nodes ),
'tree_depth' => 1,
- ),
+ ],
__METHOD__
);
if ( !$res ) {
- return array();
+ return [];
}
- $result = array();
+ $result = [];
foreach ( $res as $node ) {
if ( isset( $result[$node->tree_descendant_id] ) ) {
throw new DataModelException( 'Already have a parent for ' . $node->tree_descendant_id, 'process-data' );
diff --git a/Flow/includes/Repository/UserName/OneStepUserNameQuery.php b/Flow/includes/Repository/UserName/OneStepUserNameQuery.php
index 4adf018b..8bd755d7 100644
--- a/Flow/includes/Repository/UserName/OneStepUserNameQuery.php
+++ b/Flow/includes/Repository/UserName/OneStepUserNameQuery.php
@@ -30,24 +30,24 @@ class OneStepUserNameQuery implements UserNameQuery {
* @return \ResultWrapper|null
*/
public function execute( $wiki, array $userIds ) {
- $dbr = $this->dbFactory->getWikiDb( DB_SLAVE, array(), $wiki );
+ $dbr = $this->dbFactory->getWikiDb( DB_SLAVE, $wiki );
return $dbr->select(
- /* table */ array( 'user', 'ipblocks' ),
- /* select */ array( 'user_id', 'user_name' ),
- /* conds */ array(
+ /* table */ [ 'user', 'ipblocks' ],
+ /* select */ [ 'user_id', 'user_name' ],
+ /* conds */ [
'user_id' => $userIds,
// only accept records that did not match ipblocks
'ipb_deleted is null'
- ),
+ ],
__METHOD__,
- /* options */ array(),
- /* join_conds */ array(
- 'ipblocks' => array( 'LEFT OUTER', array(
+ /* options */ [],
+ /* join_conds */ [
+ 'ipblocks' => [ 'LEFT OUTER', [
'ipb_user' => 'user_id',
// match only deleted users
'ipb_deleted' => 1,
- ) )
- )
+ ] ]
+ ]
);
}
}
diff --git a/Flow/includes/Repository/UserName/TwoStepUserNameQuery.php b/Flow/includes/Repository/UserName/TwoStepUserNameQuery.php
index c23ffb4b..539fb56d 100644
--- a/Flow/includes/Repository/UserName/TwoStepUserNameQuery.php
+++ b/Flow/includes/Repository/UserName/TwoStepUserNameQuery.php
@@ -42,20 +42,20 @@ class TwoStepUserNameQuery implements UserNameQuery {
throw new FlowException( 'No wiki provided with user ids' );
}
- $dbr = $this->dbFactory->getWikiDB( DB_SLAVE, array(), $wiki );
+ $dbr = $this->dbFactory->getWikiDB( DB_SLAVE, $wiki );
$res = $dbr->select(
'ipblocks',
'ipb_user',
- array(
+ [
'ipb_user' => $userIds,
'ipb_deleted' => 1,
- ),
+ ],
__METHOD__
);
if ( !$res ) {
return $res;
}
- $blocked = array();
+ $blocked = [];
foreach ( $res as $row ) {
$blocked[] = $row->ipb_user;
}
@@ -66,8 +66,8 @@ class TwoStepUserNameQuery implements UserNameQuery {
}
return $dbr->select(
'user',
- array( 'user_id', 'user_name' ),
- array( 'user_id' => $allowed ),
+ [ 'user_id', 'user_name' ],
+ [ 'user_id' => $allowed ],
__METHOD__
);
}
diff --git a/Flow/includes/Repository/UserName/UserNameQuery.php b/Flow/includes/Repository/UserName/UserNameQuery.php
index ac9cd6d0..92492d9b 100644
--- a/Flow/includes/Repository/UserName/UserNameQuery.php
+++ b/Flow/includes/Repository/UserName/UserNameQuery.php
@@ -9,7 +9,7 @@ namespace Flow\Repository\UserName;
* Classes implementing the interface can lookup
* user names based on wiki + id
*/
-Interface UserNameQuery {
+interface UserNameQuery {
/**
* @param string $wiki wiki id
* @param array $userIds List of user ids to lookup
diff --git a/Flow/includes/Repository/UserNameBatch.php b/Flow/includes/Repository/UserNameBatch.php
index 7df7eebe..2bceec82 100644
--- a/Flow/includes/Repository/UserNameBatch.php
+++ b/Flow/includes/Repository/UserNameBatch.php
@@ -24,26 +24,26 @@ class UserNameBatch {
/**
* @var array[] map from wikiid to list of userid's to request
*/
- protected $queued = array();
+ protected $queued = [];
/**
* @var array Map from wiki id to MapCacheLRU. MapCacheLRU is a map of user ID (as
* string, though to PHP it's the same anyway...) to username.
*/
- protected $usernames = array();
+ protected $usernames = [];
/**
* @param UserName\UserNameQuery $query
* @param array $queued map from wikiid to list of userid's to request
*/
- public function __construct( UserName\UserNameQuery $query, array $queued = array() ) {
+ public function __construct( UserName\UserNameQuery $query, array $queued = [] ) {
$this->query = $query;
foreach ( $queued as $wiki => $userIds ) {
$this->queued[$wiki] = array_map( 'intval', $userIds );
}
}
- /*
+ /**
* Make sure the LRU for the given wiki is in place.
*
* @param string $wiki Wiki identifier
@@ -55,13 +55,13 @@ class UserNameBatch {
}
public function clear() {
- $this->queued = array();
- $this->usernames = array();
+ $this->queued = [];
+ $this->usernames = [];
}
/**
* @param string $wiki
- * @param integer $userId
+ * @param int $userId
* @param string $userName Non null to set known usernames like $wgUser
*/
public function add( $wiki, $userId, $userName = null ) {
@@ -69,8 +69,8 @@ class UserNameBatch {
$this->ensureLRU( $wiki );
if ( $userName !== null ) {
- $this->usernames[$wiki]->set( (string) $userId, $userName );
- } elseif ( !$this->usernames[$wiki]->has( (string) $userId ) ) {
+ $this->usernames[$wiki]->set( (string)$userId, $userName );
+ } elseif ( !$this->usernames[$wiki]->has( (string)$userId ) ) {
$this->queued[$wiki][] = $userId;
}
}
@@ -86,9 +86,9 @@ class UserNameBatch {
* Get the displayable username
*
* @param string $wiki
- * @param integer $userId
- * @param string|boolean $userIp
- * @return string|boolean false if username is not found or display is suppressed
+ * @param int $userId
+ * @param string|bool $userIp
+ * @return string|bool false if username is not found or display is suppressed
* @todo Return something better for not found / suppressed, but what? Making
* return type string|Message would suck.
*/
@@ -99,16 +99,16 @@ class UserNameBatch {
}
$this->ensureLRU( $wiki );
- if ( !$this->usernames[$wiki]->has( (string) $userId ) ) {
+ if ( !$this->usernames[$wiki]->has( (string)$userId ) ) {
$this->queued[$wiki][] = $userId;
$this->resolve( $wiki );
}
- return $this->usernames[$wiki]->get( (string) $userId );
+ return $this->usernames[$wiki]->get( (string)$userId );
}
/**
* @param UserTuple $tuple
- * @return string|boolean false if username is not found or display is suppressed
+ * @return string|bool false if username is not found or display is suppressed
*/
public function getFromTuple( UserTuple $tuple ) {
return $this->get( $tuple->wiki, $tuple->id, $tuple->ip );
@@ -133,11 +133,11 @@ class UserNameBatch {
$res = $this->query->execute( $wiki, $queued );
unset( $this->queued[$wiki] );
if ( $res ) {
- $usernames = array();
+ $usernames = [];
foreach ( $res as $row ) {
$id = (int)$row->user_id;
$usernames[$id] = $row->user_name;
- $this->usernames[$wiki]->set( (string) $id, $row->user_name );
+ $this->usernames[$wiki]->set( (string)$id, $row->user_name );
}
$this->resolveUserPages( $wiki, $usernames );
$missing = array_diff( $queued, array_keys( $usernames ) );
@@ -145,7 +145,7 @@ class UserNameBatch {
$missing = $queued;
}
foreach ( $missing as $id ) {
- $this->usernames[$wiki]->set( (string) $id, false );
+ $this->usernames[$wiki]->set( (string)$id, false );
}
}
@@ -158,7 +158,7 @@ class UserNameBatch {
*/
protected function resolveUserPages( $wiki, array $usernames ) {
// LinkBatch currently only supports the current wiki
- if ( $wiki !== wfWikiId() || !$usernames ) {
+ if ( $wiki !== wfWikiID() || !$usernames ) {
return;
}
diff --git a/Flow/includes/RevisionActionPermissions.php b/Flow/includes/RevisionActionPermissions.php
index 6ba20905..83baaee5 100644
--- a/Flow/includes/RevisionActionPermissions.php
+++ b/Flow/includes/RevisionActionPermissions.php
@@ -5,7 +5,6 @@ namespace Flow;
use Flow\Collection\CollectionCache;
use Flow\Collection\PostCollection;
use Flow\Exception\DataModelException;
-use Flow\Exception\FlowException;
use Flow\Model\AbstractRevision;
use Flow\Model\PostRevision;
use Closure;
@@ -20,7 +19,7 @@ class RevisionActionPermissions {
/**
* @var FlowActions
*/
- protected $actions = array();
+ protected $actions = [];
/**
* @var User
@@ -43,8 +42,8 @@ class RevisionActionPermissions {
* @return array Array of action names that are allowed
*/
public function getAllowedActions( AbstractRevision $revision = null ) {
- $allowed = array();
- foreach( array_keys( $this->actions->getActions() ) as $action ) {
+ $allowed = [];
+ foreach ( array_keys( $this->actions->getActions() ) as $action ) {
if ( $this->isAllowedAny( $revision, $action ) ) {
$allowed[] = $action;
}
@@ -65,26 +64,37 @@ class RevisionActionPermissions {
return false;
}
+ /** @var AbstractRevision[] $roots */
+ static $roots = [];
+ /** @var Workflow[] $workflows */
+ static $workflows = [];
+
+ $revisionId = $revision->getRevisionId()->getAlphadecimal();
+
+ if ( !isset( $roots[$revisionId] ) ) {
+ $roots[$revisionId] = $this->getRoot( $revision );
+ }
// see if we're allowed to perform $action on anything inside this root
- $root = $this->getRoot( $revision );
- if ( !$revision->getRevisionId()->equals( $root->getRevisionId() ) && !$this->isRootAllowed( $root, $action ) ) {
+ if ( !$revision->getRevisionId()->equals( $roots[$revisionId]->getRevisionId() ) && !$this->isRootAllowed( $roots[$revisionId], $action ) ) {
return false;
}
+ if ( !isset( $workflows[$revisionId] ) ) {
+ $collection = $revision->getCollection();
+ $workflows[$revisionId] = $collection->getBoardWorkflow();
+ }
// see if we're allowed to perform $action on anything inside this board
- $collection = $revision->getCollection();
- $workflow = $collection->getBoardWorkflow();
- if ( !$this->isBoardAllowed( $workflow, $action ) ) {
+ if ( !$this->isBoardAllowed( $workflows[$revisionId], $action ) ) {
return false;
}
+ /** @var CollectionCache $cache */
+ $cache = Container::get( 'collection.cache' );
+ $last = $cache->getLastRevisionFor( $revision );
// Also check if the user would be allowed to perform this
// against the most recent revision - the last revision is the
// current state of an object, so checking against a revision at
// one point in time alone isn't enough.
- /** @var CollectionCache $cache */
- $cache = Container::get( 'collection.cache' );
- $last = $cache->getLastRevisionFor( $revision );
$isLastRevision = $last->getRevisionId()->equals( $revision->getRevisionId() );
if ( !$isLastRevision && !$this->isRevisionAllowed( $last, $action ) ) {
return false;
@@ -104,18 +114,14 @@ class RevisionActionPermissions {
$actions = func_get_args();
// Pull $revision out of the actions list
array_shift( $actions );
- $allowed = false;
foreach ( $actions as $action ) {
- $allowed |= $this->isAllowed( $revision, $action );
-
- // as soon as we've found one that is allowed, break
- if ( $allowed ) {
- break;
+ if ( $this->isAllowed( $revision, $action ) ) {
+ return true;
}
}
- return $allowed;
+ return false;
}
/**
@@ -142,8 +148,8 @@ class RevisionActionPermissions {
}
return call_user_func_array(
- array( $this->user, 'isAllowedAny' ),
- (array) $permission
+ [ $this->user, 'isAllowedAny' ],
+ (array)$permission
);
}
@@ -161,8 +167,8 @@ class RevisionActionPermissions {
// If user is allowed to see deleted page content, there's no need to
// even check if it's been deleted (additional storage lookup)
$allowed = call_user_func_array(
- array( $this->user, 'isAllowedAny' ),
- (array) $permissions
+ [ $this->user, 'isAllowedAny' ],
+ (array)$permissions
);
if ( $allowed ) {
return true;
@@ -197,8 +203,8 @@ class RevisionActionPermissions {
// Check if user is allowed to perform action against this revision
return call_user_func_array(
- array( $this->user, 'isAllowedAny' ),
- (array) $permission
+ [ $this->user, 'isAllowedAny' ],
+ (array)$permission
);
}
diff --git a/Flow/includes/Search/Connection.php b/Flow/includes/Search/Connection.php
index c4b15b0e..d765c79d 100644
--- a/Flow/includes/Search/Connection.php
+++ b/Flow/includes/Search/Connection.php
@@ -2,8 +2,6 @@
namespace Flow\Search;
-use Elastica\SearchableInterface;
-
/**
* Provides the connection to the elasticsearch backend.
*/
@@ -30,19 +28,36 @@ class Connection extends \ElasticaConnection {
const FLOW_INDEX_TYPE = 'flow';
/**
+ * @var string[]
+ */
+ protected $servers;
+
+ /**
+ * @var int
+ */
+ protected $maxConnectionAttempts;
+
+ /**
+ * @param string[] $servers
+ * @param int $maxConnectionAttempts
+ */
+ public function __construct( array $servers, $maxConnectionAttempts ) {
+ $this->servers = $servers;
+ $this->maxConnectionAttempts = $maxConnectionAttempts;
+ }
+
+ /**
* @return string[]
*/
public function getServerList() {
- global $wgFlowSearchServers;
- return $wgFlowSearchServers;
+ return $this->servers;
}
/**
* @return int
*/
public function getMaxConnectionAttempts() {
- global $wgFlowSearchConnectionAttempts;
- return $wgFlowSearchConnectionAttempts;
+ return $this->maxConnectionAttempts;
}
/**
@@ -51,7 +66,7 @@ class Connection extends \ElasticaConnection {
* @return string[]
*/
public static function getAllIndices() {
- return array( static::FLOW_INDEX_TYPE );
+ return [ static::FLOW_INDEX_TYPE ];
}
/**
@@ -60,14 +75,14 @@ class Connection extends \ElasticaConnection {
* @return string[]
*/
public static function getAllTypes() {
- return array( static::TOPIC_TYPE_NAME, static::HEADER_TYPE_NAME );
+ return [ static::TOPIC_TYPE_NAME, static::HEADER_TYPE_NAME ];
}
/**
* @param string $name
* @return \Elastica\Index
*/
- public static function getFlowIndex( $name ) {
- return static::getSingleton()->getIndex2( $name, static::FLOW_INDEX_TYPE );
+ public function getFlowIndex( $name ) {
+ return $this->getIndex( $name, static::FLOW_INDEX_TYPE );
}
}
diff --git a/Flow/includes/Search/Iterators/AbstractIterator.php b/Flow/includes/Search/Iterators/AbstractIterator.php
new file mode 100644
index 00000000..4fb1fc50
--- /dev/null
+++ b/Flow/includes/Search/Iterators/AbstractIterator.php
@@ -0,0 +1,189 @@
+<?php
+
+namespace Flow\Search\Iterators;
+
+use DatabaseBase;
+use Flow\Container;
+use Flow\Data\ManagerGroup;
+use Flow\DbFactory;
+use Flow\Model\AbstractRevision;
+use Flow\Model\UUID;
+use Iterator;
+use ResultWrapper;
+use stdClass;
+
+abstract class AbstractIterator implements Iterator {
+ /**
+ * @var DatabaseBase
+ */
+ protected $dbr;
+
+ /**
+ * @var array
+ */
+ protected $conditions = [];
+
+ /**
+ * @var ResultWrapper|null
+ */
+ protected $results;
+
+ /**
+ * Depending on where we are in the iteration, this can be null (object
+ * constructed but not yet being iterated over), AbstractRevision (being
+ * iterated) or false (end of iteration, no more revisions)
+ *
+ * @var AbstractRevision|null|false
+ */
+ protected $current;
+
+ /**
+ * Depending on where we are in the iteration, this can be integer (object
+ * being iterated over) or null (iteration not yet started, or completed)
+ *
+ * @var int|null
+ */
+ protected $key;
+
+ /**
+ * @param DbFactory $dbFactory
+ */
+ public function __construct( DbFactory $dbFactory ) {
+ $this->dbr = $dbFactory->getDB( DB_SLAVE );
+ $this->conditions = [ 'workflow_wiki' => wfWikiID() ];
+ }
+
+ /**
+ * @return bool|ResultWrapper
+ */
+ abstract protected function query();
+
+ /**
+ * @param array|int|null $pageId
+ */
+ public function setPage( $pageId = null ) {
+ $this->results = null;
+
+ unset( $this->conditions['workflow_page_id'] );
+ if ( $pageId !== null ) {
+ $this->conditions['workflow_page_id'] = $pageId;
+ }
+ }
+
+ /**
+ * @param int|null $namespace
+ */
+ public function setNamespace( $namespace = null ) {
+ $this->results = null;
+
+ unset( $this->conditions['workflow_namespace'] );
+ if ( $namespace !== null ) {
+ $this->conditions['workflow_namespace'] = $namespace;
+ }
+ }
+
+ /**
+ * Define where to start iterating (inclusive)
+ *
+ * @param UUID|null $revId
+ */
+ public function setFrom( UUID $revId = null ) {
+ $this->results = null;
+
+ unset( $this->conditions[0] );
+ if ( $revId !== null ) {
+ $this->conditions[0] = 'rev_id >= ' . $this->dbr->addQuotes( $revId->getBinary() );
+ }
+ }
+
+ /**
+ * Define where to stop iterating (exclusive)
+ *
+ * @param UUID|null $revId
+ */
+ public function setTo( UUID $revId = null ) {
+ $this->results = null;
+
+ unset( $this->conditions[1] );
+ if ( $revId !== null ) {
+ $this->conditions[1] = 'rev_id < ' . $this->dbr->addQuotes( $revId->getBinary() );
+ }
+ }
+
+ /**
+ * @return AbstractRevision|null The most recently fetched revision object
+ */
+ public function current() {
+ return $this->current;
+ }
+
+ /**
+ * @return int 0-indexed count of the page number fetched
+ */
+ public function key() {
+ return $this->key;
+ }
+
+ /**
+ * Reset the iterator to the beginning of the table.
+ */
+ public function rewind() {
+ $this->results = null;
+ $this->key = -1; // self::next() will turn this into 0
+ $this->current = null;
+ $this->next();
+ }
+
+ /**
+ * @return bool True when the iterator is in a valid state
+ */
+ public function valid() {
+ return (bool)$this->current;
+ }
+
+ /**
+ * Fetch the next set of rows from the database.
+ */
+ public function next() {
+ if ( $this->results === null ) {
+ $this->results = $this->query();
+ }
+
+ $current = $this->results->fetchObject();
+ if ( $current !== false ) {
+ $this->current = $this->transform( $current );
+ $this->key++;
+ } else {
+ // end of iteration reached
+ $this->current = false;
+ $this->key = null;
+ }
+ }
+
+ /**
+ * Transforms the DB row into a revision object.
+ *
+ * $row will be one of the results of static::query(). In this method, $row
+ * is expected to have at least properties `rev_id` & `rev_type`, which will
+ * be used to fetch this specific row's data from storage.
+ *
+ * This will need to do some DB/cache requests. Ideally, those would be
+ * bundled instead of being done on a per-row record. These iterators
+ * are only meant to be run in maintenance scripts, however, so it
+ * doesn't really matter that much ;)
+ *
+ * @param stdClass $row
+ * @return AbstractRevision
+ */
+ protected function transform( stdClass $row ) {
+ $uuid = UUID::create( $row->rev_id );
+
+ /** @var ManagerGroup $storage */
+ $storage = Container::get( 'storage' );
+
+ // prevent memory from being filled up
+ $storage->clear();
+
+ return $storage->getStorage( $row->rev_type )->get( $uuid );
+ }
+}
diff --git a/Flow/includes/Search/Iterators/HeaderIterator.php b/Flow/includes/Search/Iterators/HeaderIterator.php
new file mode 100644
index 00000000..abb95589
--- /dev/null
+++ b/Flow/includes/Search/Iterators/HeaderIterator.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Flow\Search\Iterators;
+
+class HeaderIterator extends AbstractIterator {
+ /**
+ * {@inheritDoc}
+ */
+ protected function query() {
+ // get the current (=most recent, =max) revision id for all headers
+ return $this->dbr->select(
+ [ 'flow_revision', 'flow_workflow' ],
+ [ 'rev_id' => 'MAX(rev_id)', 'rev_type' ],
+ $this->conditions,
+ __METHOD__,
+ [
+ 'ORDER BY' => 'rev_id ASC',
+ 'GROUP BY' => 'rev_type_id',
+ ],
+ [
+ 'flow_workflow' => [
+ 'INNER JOIN',
+ [ 'workflow_id = rev_type_id' , 'rev_type' => 'header' ]
+ ],
+ ]
+ );
+ }
+}
diff --git a/Flow/includes/Search/Iterators/TopicIterator.php b/Flow/includes/Search/Iterators/TopicIterator.php
new file mode 100644
index 00000000..22cc1305
--- /dev/null
+++ b/Flow/includes/Search/Iterators/TopicIterator.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace Flow\Search\Iterators;
+
+use Flow\DbFactory;
+use Flow\Model\PostRevision;
+use Flow\Model\UUID;
+use Flow\Repository\RootPostLoader;
+use stdClass;
+
+class TopicIterator extends AbstractIterator {
+ /**
+ * @var PostRevision
+ */
+ protected $previous;
+
+ /**
+ * @var RootPostLoader
+ */
+ protected $rootPostLoader;
+
+ /**
+ * @param DbFactory $dbFactory
+ * @param RootPostLoader $rootPostLoader
+ */
+ public function __construct( DbFactory $dbFactory, RootPostLoader $rootPostLoader ) {
+ parent::__construct( $dbFactory );
+ $this->rootPostLoader = $rootPostLoader;
+ $this->orderByUUID = false;
+ }
+
+ /**
+ * Define where to start iterating (inclusive)
+ *
+ * We'll be querying the workflow table instead of the revisions table.
+ * Because it's possible to request only a couple of revisions (in between
+ * certain ids), we'll need to override the parent buildQueryConditions
+ * method to also work on the workflow table.
+ * A topic workflow is updated with a workflow_last_update_timestamp for
+ * every change made in the topic. Our UUIDs are sequential & time-based,
+ * so we can just query for workflows with a timestamp higher than the
+ * timestamp derived from the starting UUID and lower than the end UUID.
+ *
+ * @param UUID|null $revId
+ */
+ public function setFrom( UUID $revId = null ) {
+ $this->results = null;
+
+ unset( $this->conditions[0] );
+ if ( $revId !== null ) {
+ $this->conditions[0] = 'workflow_last_update_timestamp >= ' . $this->dbr->addQuotes( $revId->getBinary() );
+ }
+ }
+
+ /**
+ * Define where to stop iterating (exclusive)
+ *
+ * We'll be querying the workflow table instead of the revisions table.
+ * Because it's possible to request only a couple of revisions (in between
+ * certain ids), we'll need to override the parent buildQueryConditions
+ * method to also work on the workflow table.
+ * A topic workflow is updated with a workflow_last_update_timestamp for
+ * every change made in the topic. Our UUIDs are sequential & time-based,
+ * so we can just query for workflows with a timestamp higher than the
+ * timestamp derived from the starting UUID and lower than the end UUID.
+ *
+ * @param UUID|null $revId
+ */
+ public function setTo( UUID $revId = null ) {
+ $this->results = null;
+
+ unset( $this->conditions[1] );
+ if ( $revId !== null ) {
+ $this->conditions[1] = 'workflow_last_update_timestamp < ' . $this->dbr->addQuotes( $revId->getBinary() );
+ }
+ }
+
+ /**
+ * Instead of querying for revisions (which is what we actually need), we'll
+ * just query the workflow table, which will save us some complicated joins.
+ * The workflow_id for a topic title (aka root post) is the same as its
+ * collection id, so we can pass that to the root post loader and *poof*, we
+ * have our revisions!
+ *
+ * {@inheritDoc}
+ */
+ protected function query() {
+ if ( $this->orderByUUID ) {
+ $order = 'workflow_id ASC';
+ } else {
+ $order = 'workflow_last_update_timestamp ASC';
+ }
+ return $this->dbr->select(
+ [ 'flow_workflow' ],
+ // for root post (topic title), workflow_id is the same as its rev_type_id
+ [ 'workflow_id', 'workflow_last_update_timestamp' ],
+ [
+ 'workflow_type' => 'topic'
+ ] + $this->conditions,
+ __METHOD__,
+ [
+ 'ORDER BY' => $order,
+ ]
+ );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function transform( stdClass $row ) {
+ $root = UUID::create( $row->workflow_id );
+
+ // we need to fetch all data via rootloader because we'll want children
+ // to be populated
+ return $this->rootPostLoader->get( $root );
+ }
+}
diff --git a/Flow/includes/Search/SearchEngine.php b/Flow/includes/Search/SearchEngine.php
index 089c294c..efa98f7f 100644
--- a/Flow/includes/Search/SearchEngine.php
+++ b/Flow/includes/Search/SearchEngine.php
@@ -2,10 +2,10 @@
namespace Flow\Search;
-use Elastica\Filter\Bool;
+use Elastica\Filter\BoolFilter;
use Elastica\Filter\Terms;
use Elastica\Query;
-use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
class SearchEngine extends \SearchEngine {
/**
@@ -23,17 +23,17 @@ class SearchEngine extends \SearchEngine {
*
* @var int[]
*/
- public $namespaces = array();
+ public $namespaces = [];
/**
* @var int[]
*/
- protected $pageIds = array();
+ protected $pageIds = [];
/**
* @var string[]
*/
- protected $moderationStates = array();
+ protected $moderationStates = [];
/**
* @var string
@@ -61,7 +61,7 @@ class SearchEngine extends \SearchEngine {
$query->setSize( $this->limit );
}
- $filter = new Bool();
+ $filter = new BoolFilter();
// filters
if ( $this->namespaces ) {
@@ -95,12 +95,12 @@ class SearchEngine extends \SearchEngine {
* false is allowed (means we'll search *all* types)
*
* @param string|false $type
- * @throws InvalidInputException
+ * @throws InvalidParameterException
*/
public function setType( $type ) {
- $allowedTypes = array_merge( Connection::getAllTypes(), array( false ) );
+ $allowedTypes = array_merge( Connection::getAllTypes(), [ false ] );
if ( !in_array( $type, $allowedTypes ) ) {
- throw new InvalidInputException( 'Invalid search sort requested', 'invalid-input' );
+ throw new InvalidParameterException( 'Invalid search index requested' );
}
$this->type = $type;
@@ -120,17 +120,17 @@ class SearchEngine extends \SearchEngine {
*
* @param string[] $moderationStates
*/
- public function setModerationStates( array $moderationStates = array() ) {
+ public function setModerationStates( array $moderationStates = [] ) {
$this->moderationStates = $moderationStates;
}
/**
* @param string $sort
- * @throws InvalidInputException
+ * @throws InvalidParameterException
*/
public function setSort( $sort ) {
if ( !in_array( $sort, $this->getValidSorts() ) ) {
- throw new InvalidInputException( 'Invalid search sort requested', 'invalid-input' );
+ throw new InvalidParameterException( 'Invalid search sort requested' );
}
$this->sort = $sort;
@@ -160,13 +160,13 @@ class SearchEngine extends \SearchEngine {
* @return array [description => [sort field => order]]
*/
public function getSortArgs() {
- return array(
- 'relevance' => array( /* default */ ),
- 'timestamp_asc' => array( 'timestamp' => 'asc' ),
- 'timestamp_desc' => array( 'timestamp' => 'desc' ),
- 'update_timestamp_asc' => array( 'update_timestamp' => 'asc' ),
- 'update_timestamp_desc' => array( 'update_timestamp' => 'desc' ),
- );
+ return [
+ 'relevance' => [ /* default */ ],
+ 'timestamp_asc' => [ 'timestamp' => 'asc' ],
+ 'timestamp_desc' => [ 'timestamp' => 'desc' ],
+ 'update_timestamp_asc' => [ 'update_timestamp' => 'asc' ],
+ 'update_timestamp_desc' => [ 'update_timestamp' => 'desc' ],
+ ];
}
/**
diff --git a/Flow/includes/Search/Searcher.php b/Flow/includes/Search/Searcher.php
index 2930bde2..ad3523d7 100644
--- a/Flow/includes/Search/Searcher.php
+++ b/Flow/includes/Search/Searcher.php
@@ -6,7 +6,7 @@ use Elastica\Query;
use Elastica\Query\QueryString;
use Elastica\Exception\ExceptionInterface;
use Elastica\Request;
-use Elastica\ResultSet;
+use Flow\Container;
use PoolCounterWorkViaCallback;
use Status;
@@ -16,7 +16,7 @@ class Searcher {
const HIGHLIGHT_POST = '</span>';
/**
- * @var string|false $type
+ * @var string|bool
*/
protected $type = false;
@@ -31,14 +31,20 @@ class Searcher {
protected $query;
/**
+ * @var Connection
+ */
+ protected $connection;
+
+ /**
* @param Query $query
- * @param string|bool $index Base name for index to search from, defaults to wfWikiId()
+ * @param string|bool $index Base name for index to search from, defaults to wfWikiID()
* @param string|bool $type Type of revisions to retrieve, defaults to all
*/
public function __construct( Query $query, $index = false, $type = false ) {
$this->query = $query;
- $this->indexBaseName = $index ?: wfWikiId();
+ $this->indexBaseName = $index ?: wfWikiID();
$this->type = $type;
+ $this->connection = Container::get( 'search.connection' );
}
/**
@@ -50,7 +56,7 @@ class Searcher {
public function searchText( $term ) {
// full-text search
$queryString = new QueryString( $term );
- $queryString->setFields( array( 'revisions.text' ) );
+ $queryString->setFields( [ 'revisions.text' ] );
$this->query->setQuery( $queryString );
// add aggregation to determine exact amount of matching search terms
@@ -58,24 +64,24 @@ class Searcher {
$this->query->addAggregation( $this->termsAggregation( $terms ) );
// @todo: abstract-away this config? (core/cirrus also has this - share it somehow?)
- $this->query->setHighlight( array(
- 'fields' => array(
- static::HIGHLIGHT_FIELD => array(
+ $this->query->setHighlight( [
+ 'fields' => [
+ static::HIGHLIGHT_FIELD => [
'type' => 'plain',
'order' => 'score',
// we want just 1 excerpt of result text, which includes all highlights
'number_of_fragments' => 1,
'fragment_size' => 10000, // We want the whole value but more than this is crazy
- ),
- ),
- 'pre_tags' => array( static::HIGHLIGHT_PRE ),
- 'post_tags' => array( static::HIGHLIGHT_POST ),
- ) );
+ ],
+ ],
+ 'pre_tags' => [ static::HIGHLIGHT_PRE ],
+ 'post_tags' => [ static::HIGHLIGHT_POST ],
+ ] );
// @todo: support insource: queries (and perhaps others)
- $searchable = Connection::getFlowIndex( $this->indexBaseName );
+ $searchable = $this->connection->getFlowIndex( $this->indexBaseName );
if ( $this->type !== false ) {
$searchable = $searchable->getType( $this->type );
}
@@ -85,8 +91,8 @@ class Searcher {
// @todo: do we want this class to extend from ElasticsearchIntermediary and use its success & failure methods (like CirrusSearch/Searcher does)?
// Perform the search
- $work = new PoolCounterWorkViaCallback( 'Flow-Search', "_elasticsearch", array(
- 'doWork' => function() use ( $search ) {
+ $work = new PoolCounterWorkViaCallback( 'Flow-Search', "_elasticsearch", [
+ 'doWork' => function () use ( $search ) {
try {
$result = $search->search();
return Status::newGood( $result );
@@ -102,12 +108,12 @@ class Searcher {
return Status::newFatal( 'flow-error-search' );
}
},
- 'error' => function( Status $status ) {
+ 'error' => function ( Status $status ) {
$status = $status->getErrorsArray();
wfLogWarning( 'Pool error searching Elasticsearch: ' . $status[0][0] );
return Status::newFatal( 'flow-error-search' );
}
- ) );
+ ] );
$result = $work->execute();
@@ -144,18 +150,18 @@ class Searcher {
// _termvectors only works on a type, but our types are
// configured exactly the same so it doesn't matter which
$types = Connection::getAllTypes();
- $searchable = Connection::getFlowIndex( $this->indexBaseName );
+ $searchable = $this->connection->getFlowIndex( $this->indexBaseName );
$searchable = $searchable->getType( array_pop( $types ) );
- $query = array(
+ $query = [
// bogus document that contains the current search term
- 'doc' => array(
- 'revisions' => array(
+ 'doc' => [
+ 'revisions' => [
'text' => $terms,
- ),
- ),
- "fields" => array( "revisions.text" ),
- );
+ ],
+ ],
+ "fields" => [ "revisions.text" ],
+ ];
// Elastica has no abstraction over _termvector like it has
// for _query, so just do the request ourselves
@@ -163,7 +169,7 @@ class Searcher {
'_termvector',
Request::POST,
$query,
- array()
+ []
);
$data = $response->getData();
@@ -194,7 +200,7 @@ return total';
// $aggregation->setScript() doesn't seem to properly set 'lang': 'groovy'
// see https://github.com/ruflin/Elastica/pull/748
// $aggregation->setScript( $script );
- $aggregation->setParams( array( 'lang' => 'groovy' ) );
+ $aggregation->setParams( [ 'lang' => 'groovy' ] );
$aggregation->setParam( 'script', $script->getScript() );
return $aggregation;
diff --git a/Flow/includes/Search/Updaters/AbstractUpdater.php b/Flow/includes/Search/Updaters/AbstractUpdater.php
new file mode 100644
index 00000000..63226339
--- /dev/null
+++ b/Flow/includes/Search/Updaters/AbstractUpdater.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace Flow\Search\Updaters;
+
+use Flow\Container;
+use Flow\Exception\FlowException;
+use Flow\Model\AbstractRevision;
+use Flow\RevisionActionPermissions;
+use Flow\Search\Connection;
+use Flow\Search\Iterators\AbstractIterator;
+use MWExceptionHandler;
+
+abstract class AbstractUpdater {
+ /**
+ * @var AbstractIterator
+ */
+ public $iterator;
+
+ /**
+ * @var RevisionActionPermissions
+ */
+ protected $permissions;
+
+ /**
+ * @var Connection
+ */
+ protected $connection;
+
+ /**
+ * @param AbstractIterator $iterator
+ * @param RevisionActionPermissions $permissions
+ */
+ public function __construct( AbstractIterator $iterator, RevisionActionPermissions $permissions ) {
+ $this->iterator = $iterator;
+ $this->permissions = $permissions;
+ $this->connection = Container::get( 'search.connection' );
+ }
+
+ /**
+ * @return string One of the Connection::*_TYPE_NAME constants
+ */
+ abstract public function getTypeName();
+
+ /**
+ * @param AbstractRevision $revision
+ * @return \Elastica\Document
+ */
+ abstract public function buildDocument( AbstractRevision $revision );
+
+ /**
+ * @param string|null $shardTimeout Timeout in Elasticsearch time format (1m, 15s, ...)
+ * @param int|null $clientSideTimeout
+ * @param int $batchSize
+ * @return int
+ */
+ public function updateRevisions( $shardTimeout = null, $clientSideTimeout = null, $batchSize = 50 ) {
+ if ( $clientSideTimeout !== null ) {
+ $this->connection->setTimeout( $clientSideTimeout );
+ }
+
+ $documents = [];
+ $count = 0;
+ foreach ( $this->iterator as $revision ) {
+ try {
+ $documents[] = $this->buildDocument( $revision );
+ $count++;
+ } catch ( FlowException $e ) {
+ // just ignore revisions that fail to build document...
+ wfWarn( __METHOD__ . ': Failed to build document for ' . $revision->getRevisionId()->getAlphadecimal() . ': ' . $e->getMessage() );
+ MWExceptionHandler::logException( $e );
+ }
+
+ // send documents in small batches
+ if ( count( $documents ) > $batchSize ) {
+ $this->sendDocuments( $documents, $shardTimeout );
+ $documents = [];
+ }
+ }
+
+ if ( $documents ) {
+ // send remaining documents
+ $this->sendDocuments( $documents, $shardTimeout );
+ }
+
+ return $count;
+ }
+
+ /**
+ * @param \Elastica\Document[] $documents
+ * @param string|null $shardTimeout Timeout in Elasticsearch time format (1m, 15s, ...)
+ */
+ protected function sendDocuments( array $documents, $shardTimeout = null ) {
+ if ( count( $documents ) === 0 ) {
+ return;
+ }
+
+ try {
+ // addDocuments (notice plural) is the bulk api
+ $bulk = new \Elastica\Bulk( $this->connection->getClient() );
+ if ( $shardTimeout !== null ) {
+ $bulk->setShardTimeout( $shardTimeout );
+ }
+
+ $index = $this->connection->getFlowIndex( wfWikiID() );
+ $type = $index->getType( $this->getTypeName() );
+ $bulk->setType( $type );
+ $bulk->addDocuments( $documents );
+ $bulk->send();
+ } catch ( \Exception $e ) {
+ $documentIds = array_map( function ( $doc ) {
+ return $doc->getId();
+ }, $documents );
+ wfWarn( __METHOD__ . ': Failed updating documents (' . implode( ',', $documentIds ) . '): ' . $e->getMessage() );
+ }
+ }
+}
diff --git a/Flow/includes/Search/Updaters/HeaderUpdater.php b/Flow/includes/Search/Updaters/HeaderUpdater.php
new file mode 100644
index 00000000..69494b94
--- /dev/null
+++ b/Flow/includes/Search/Updaters/HeaderUpdater.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Flow\Search\Updaters;
+
+use Flow\Model\AbstractRevision;
+use Flow\Model\Header;
+use Flow\Search\Connection;
+use Sanitizer;
+
+class HeaderUpdater extends AbstractUpdater {
+ /**
+ * {@inheritDoc}
+ */
+ public function getTypeName() {
+ return Connection::HEADER_TYPE_NAME;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function buildDocument( AbstractRevision /* Header */ $revision ) {
+ /** @var Header $revision */
+
+ // get article title associated with this revision
+ $title = $revision->getCollection()->getWorkflow()->getArticleTitle();
+
+ $format = 'html';
+
+ $creationTimestamp = $revision->getCollectionId()->getTimestampObj();
+ $updateTimestamp = $revision->getRevisionId()->getTimestampObj();
+
+ $revisions = [];
+ if ( $this->permissions->isAllowed( $revision, 'view' ) ) {
+ $revisions[] = [
+ 'id' => $revision->getCollectionId()->getAlphadecimal(),
+ 'text' => trim( Sanitizer::stripAllTags( $revision->getContent( $format ) ) ),
+ 'source_text' => $revision->getContent( 'wikitext' ), // for insource: searches
+ 'moderation_state' => $revision->getModerationState(), // headers can't (currently) be moderated, so should always be MODERATED_NONE
+ 'timestamp' => $creationTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'update_timestamp' => $updateTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'type' => $revision->getRevisionType(),
+ ];
+ }
+
+ // for consistency with topics, headers will also get "revisions",
+ // although there's always only 1 revision per document (unlike topics,
+ // which may have multiple sub-posts)
+ return new \Elastica\Document(
+ $revision->getCollectionId()->getAlphadecimal(),
+ [
+ 'namespace' => $title->getNamespace(),
+ 'namespace_text' => $title->getPageLanguage()->getFormattedNsText( $title->getNamespace() ),
+ 'pageid' => $title->getArticleID(),
+ 'title' => $title->getText(),
+ 'timestamp' => $creationTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'update_timestamp' => $updateTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'revisions' => $revisions,
+ ]
+ );
+ }
+}
diff --git a/Flow/includes/Search/Updaters/TopicUpdater.php b/Flow/includes/Search/Updaters/TopicUpdater.php
new file mode 100644
index 00000000..92dc4b07
--- /dev/null
+++ b/Flow/includes/Search/Updaters/TopicUpdater.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Flow\Search\Updaters;
+
+use Flow\Collection\PostSummaryCollection;
+use Flow\Model\AbstractRevision;
+use Flow\Model\PostRevision;
+use Flow\Model\PostSummary;
+use Flow\Repository\RootPostLoader;
+use Flow\RevisionActionPermissions;
+use Flow\Search\Connection;
+use Flow\Search\Iterators\AbstractIterator;
+use Sanitizer;
+
+class TopicUpdater extends AbstractUpdater {
+ /**
+ * @var RootPostLoader
+ */
+ protected $rootPostLoader;
+
+ /**
+ * @param AbstractIterator $iterator
+ * @param RevisionActionPermissions $permissions
+ * @param RootPostLoader $rootPostLoader
+ */
+ public function __construct( AbstractIterator $iterator, RevisionActionPermissions $permissions, RootPostLoader $rootPostLoader ) {
+ parent::__construct( $iterator, $permissions );
+ $this->rootPostLoader = $rootPostLoader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getTypeName() {
+ return Connection::TOPIC_TYPE_NAME;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function buildDocument( AbstractRevision /* PostRevision */ $revision ) {
+ /** @var PostRevision $revision */
+
+ // get timestamp from the most recent revision
+ $updateTimestamp = $revision->getCollection()->getWorkflow()->getLastUpdatedObj();
+ // timestamp for initial topic post
+ $creationTimestamp = $revision->getCollectionId()->getTimestampObj();
+
+ // get content from all child posts in a [post id => [data]] array
+ $revisions = $this->getRevisionsData( $revision );
+
+ // find summary for this topic & add it as revision
+ $summaryCollection = PostSummaryCollection::newFromId( $revision->getCollectionId() );
+ try {
+ /** @var PostSummary $summaryRevision */
+ $summaryRevision = $summaryCollection->getLastRevision();
+ $data = current( $this->getRevisionsData( $summaryRevision ) );
+ if ( $data !== false ) {
+ $revisions[] = $data;
+ }
+ } catch ( \Exception $e ) {
+ // no summary - that's ok!
+ }
+
+ // get board title associated with this revision
+ $title = $revision->getCollection()->getWorkflow()->getOwnerTitle();
+
+ $doc = new \Elastica\Document(
+ $revision->getCollectionId()->getAlphadecimal(),
+ [
+ 'namespace' => $title->getNamespace(),
+ 'namespace_text' => $title->getPageLanguage()->getFormattedNsText( $title->getNamespace() ),
+ 'pageid' => $title->getArticleID(),
+ 'title' => $title->getText(),
+ 'timestamp' => $creationTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'update_timestamp' => $updateTimestamp->getTimestamp( TS_ISO_8601 ),
+ 'revisions' => $revisions,
+ ]
+ );
+
+ return $doc;
+ }
+
+ /**
+ * Recursively get the data for all children. This will add the revision's
+ * content to the results array, with the post ID as key.
+ *
+ * @param PostRevision|PostSummary $revision
+ * @return array
+ */
+ public function getRevisionsData( /* PostRevision|PostSummary */ $revision ) {
+ // store type of revision so we can also search for very specific types
+ // (e.g. titles only)
+ // possible values will be:
+ // * title
+ // * post
+ // * post-summary
+ $type = $revision->getRevisionType();
+ if ( method_exists( $revision, 'isTopicTitle' ) && $revision->isTopicTitle() ) {
+ $type = 'title';
+ }
+
+ $data = [];
+
+ if ( $this->permissions->isAllowed( $revision, 'view' ) ) {
+ $data[] = [
+ 'id' => $revision->getCollectionId()->getAlphadecimal(),
+ 'text' => trim( Sanitizer::stripAllTags( $revision->getContentInHtml() ) ),
+ 'source_text' => $revision->getContentInWikitext(),
+ 'moderation_state' => $revision->getModerationState(),
+ 'timestamp' => $revision->getCollectionId()->getTimestamp( TS_ISO_8601 ),
+ 'update_timestamp' => $revision->getRevisionId()->getTimestamp( TS_ISO_8601 ),
+ 'type' => $type,
+ ];
+ }
+
+ if ( $revision instanceof PostRevision ) {
+ // get data from all child posts too
+ foreach ( $revision->getChildren() as $child ) {
+ $data = array_merge( $data, $this->getRevisionsData( $child ) );
+ }
+ }
+
+ return $data;
+ }
+}
diff --git a/Flow/includes/Search/maintenance/MappingConfigBuilder.php b/Flow/includes/Search/maintenance/MappingConfigBuilder.php
index 98c6307b..82895156 100644
--- a/Flow/includes/Search/maintenance/MappingConfigBuilder.php
+++ b/Flow/includes/Search/maintenance/MappingConfigBuilder.php
@@ -14,51 +14,51 @@ class MappingConfigBuilder extends \CirrusSearch\Maintenance\MappingConfigBuilde
* @return array the mapping config
*/
public function buildConfig( $prefixSearchStartsWithAnyWord = null, $phraseSuggestUseText = null ) {
- $config = array(
+ $config = [
'dynamic' => false,
-// '_all' => array( 'enabled' => false ),
- 'properties' => array(
+ // '_all' => array( 'enabled' => false ),
+ 'properties' => [
'namespace' => $this->buildLongField(),
'namespace_text' => $this->buildKeywordField(),
'pageid' => $this->buildLongField(),
// no need to analyze title, we won't be searching it
'title' => $this->buildKeywordField(),
- 'timestamp' => array(
+ 'timestamp' => [
'type' => 'date',
'format' => 'dateOptionalTime',
- ),
- 'update_timestamp' => array(
+ ],
+ 'update_timestamp' => [
'type' => 'date',
'format' => 'dateOptionalTime',
- ),
- 'revisions' => array(
+ ],
+ 'revisions' => [
// object can be flattened (probably doesn't have to be
// "nested", which would allow them to be querried independently)
'type' => 'object',
- 'properties' => array(
+ 'properties' => [
'id' => $this->buildKeywordField(),
// @todo: Cirrus' config for 'text' had some more - see if we need those?
'text' => $this->buildStringField( static::ENABLE_NORMS | static::SPEED_UP_HIGHLIGHTING ),
'source_text' => $this->buildStringField( static::MINIMAL ),
'moderation_state' => $this->buildKeywordField(),
- 'timestamp' => array(
+ 'timestamp' => [
'type' => 'date',
'format' => 'dateOptionalTime',
- ),
- 'update_timestamp' => array(
+ ],
+ 'update_timestamp' => [
'type' => 'date',
'format' => 'dateOptionalTime',
- ),
+ ],
'type' => $this->buildKeywordField(),
- )
- )
- ),
- );
+ ]
+ ]
+ ],
+ ];
// same config for both types (well, so far...)
- return array(
+ return [
'topic' => $config,
'header' => $config,
- );
+ ];
}
}
diff --git a/Flow/includes/SpamFilter/AbuseFilter.php b/Flow/includes/SpamFilter/AbuseFilter.php
index 726a4aae..69c55b05 100644
--- a/Flow/includes/SpamFilter/AbuseFilter.php
+++ b/Flow/includes/SpamFilter/AbuseFilter.php
@@ -6,25 +6,17 @@ use Flow\Model\AbstractRevision;
use IContextSource;
use Status;
use Title;
-use User;
class AbuseFilter implements SpamFilter {
/**
- * @var User
- */
- protected $user;
-
- /**
* @var string
*/
protected $group;
/**
- * @param User $user The user submitting content
* @param string $group The abuse filter group to use
*/
- public function __construct( User $user, $group ) {
- $this->user = $user;
+ public function __construct( $group ) {
$this->group = $group;
}
@@ -33,7 +25,7 @@ class AbuseFilter implements SpamFilter {
*
* @param array $emergencyDisable optional AbuseFilter emergency disable values
*/
- public function setup( array $emergencyDisable = array() ) {
+ public function setup( array $emergencyDisable = [] ) {
global
$wgAbuseFilterValidGroups,
$wgAbuseFilterEmergencyDisableThreshold,
@@ -45,11 +37,11 @@ class AbuseFilter implements SpamFilter {
}
// if no Flow-specific emergency disable threshold given, use defaults
- $emergencyDisable += array(
+ $emergencyDisable += [
'threshold' => $wgAbuseFilterEmergencyDisableThreshold['default'],
'count' => $wgAbuseFilterEmergencyDisableCount['default'],
'age' => $wgAbuseFilterEmergencyDisableAge['default'],
- );
+ ];
// register Flow's AbuseFilter filter group
if ( !in_array( $this->group, $wgAbuseFilterValidGroups ) ) {
@@ -67,11 +59,17 @@ class AbuseFilter implements SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
$vars = \AbuseFilter::getEditVars( $title );
- $vars->addHolders( \AbuseFilter::generateUserVars( $this->user ), \AbuseFilter::generateTitleVars( $title , 'ARTICLE' ) );
+ $vars->addHolders(
+ \AbuseFilter::generateUserVars( $context->getUser() ),
+ \AbuseFilter::generateTitleVars( $title, 'ARTICLE' ),
+ \AbuseFilter::generateTitleVars( $ownerTitle, 'BOARD' )
+ );
+
$vars->setVar( 'ACTION', $newRevision->getChangeType() );
/*
@@ -80,16 +78,16 @@ class AbuseFilter implements SpamFilter {
* submitted in wikitext. It will only be transformed once it's being
* saved to DB.
*/
- $vars->setLazyLoadVar( 'new_wikitext', 'FlowRevisionContent', array( 'revision' => $newRevision ) );
- $vars->setLazyLoadVar( 'new_size', 'length', array( 'length-var' => 'new_wikitext' ) );
+ $vars->setLazyLoadVar( 'new_wikitext', 'FlowRevisionContent', [ 'revision' => $newRevision ] );
+ $vars->setLazyLoadVar( 'new_size', 'length', [ 'length-var' => 'new_wikitext' ] );
/*
* This may roundtrip to Parsoid if content is stored in HTML.
* Since the variable is lazy-loaded, it will not roundtrip unless the
* variable is actually used.
*/
- $vars->setLazyLoadVar( 'old_wikitext', 'FlowRevisionContent', array( 'revision' => $oldRevision ) );
- $vars->setLazyLoadVar( 'old_size', 'length', array( 'length-var' => 'old_wikitext' ) );
+ $vars->setLazyLoadVar( 'old_wikitext', 'FlowRevisionContent', [ 'revision' => $oldRevision ] );
+ $vars->setLazyLoadVar( 'old_size', 'length', [ 'length-var' => 'old_wikitext' ] );
return \AbuseFilter::filterAction( $vars, $title, $this->group );
}
@@ -100,7 +98,7 @@ class AbuseFilter implements SpamFilter {
* @return bool
*/
public function enabled() {
- return class_exists( 'AbuseFilter' ) && (bool) $this->group;
+ return class_exists( 'AbuseFilter' ) && (bool)$this->group;
}
/**
@@ -110,7 +108,7 @@ class AbuseFilter implements SpamFilter {
* @return array
*/
public function lazyLoadMethods() {
- return array(
+ return [
/**
* @param string $method: Method to generate the variable
* @param \AbuseFilterVariableHolder $vars
@@ -118,16 +116,16 @@ class AbuseFilter implements SpamFilter {
* @param mixed &$result Result of the computation
*/
'FlowRevisionContent' => function ( \AbuseFilterVariableHolder $vars, $parameters ) {
- if ( !isset( $parameters['revision'] ) ) {
- return '';
- }
- $revision = $parameters['revision'];
- if ( $revision instanceof AbstractRevision ) {
- return $revision->getContent( 'wikitext' );
- } else {
- return '';
- }
+ if ( !isset( $parameters['revision'] ) ) {
+ return '';
}
- );
+ $revision = $parameters['revision'];
+ if ( $revision instanceof AbstractRevision ) {
+ return $revision->getContentInWikitext();
+ } else {
+ return '';
+ }
+ }
+ ];
}
}
diff --git a/Flow/includes/SpamFilter/ConfirmEdit.php b/Flow/includes/SpamFilter/ConfirmEdit.php
index 02cb578f..de434199 100644
--- a/Flow/includes/SpamFilter/ConfirmEdit.php
+++ b/Flow/includes/SpamFilter/ConfirmEdit.php
@@ -4,6 +4,7 @@ namespace Flow\SpamFilter;
use ConfirmEditHooks;
use Flow\Model\AbstractRevision;
+use Flow\Model\HtmlRenderingInformation;
use IContextSource;
use SimpleCaptcha;
use Status;
@@ -16,12 +17,12 @@ class ConfirmEdit implements SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
- global $wgOut;
- $newContent = $newRevision->getContent( 'wikitext' );
- $oldContent = ( $oldRevision !== null ) ? $oldRevision->getContent( 'wikitext' ) : '';
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
+ $newContent = $newRevision->getContentInWikitext();
+ $oldContent = ( $oldRevision !== null ) ? $oldRevision->getContentInWikitext() : '';
/** @var SimpleCaptcha $captcha */
$captcha = ConfirmEditHooks::getInstance();
@@ -29,21 +30,22 @@ class ConfirmEdit implements SpamFilter {
// first check if the submitted content is offensive (as flagged by
// ConfirmEdit), next check for a (valid) captcha to have been entered
- if ( $captcha->shouldCheck( $wikiPage, $newContent, false, $context, $oldContent ) && !$captcha->passCaptchaLimited() ) {
+ if (
+ $captcha->shouldCheck( $wikiPage, $newContent, false, $context, $oldContent ) &&
+ !$captcha->passCaptchaLimitedFromRequest( $context->getRequest(), $context->getUser() )
+ ) {
// getting here means we submitted bad content without good captcha
// result (or any captcha result at all) - let's get the captcha
- // HTML to display as error message!
- $html = $captcha->getForm( $context->getOutput() );
-
- // some captcha implementations need CSS and/or JS, which is added
- // via their getForm() methods (which we just called) -
- // let's extract those and respond them along with the form HTML
- $html = $wgOut->buildCssLinks() .
- $wgOut->getScriptsForBottomQueue( true ) .
- $html;
-
- $msg = wfMessage( 'flow-spam-confirmedit-form' )->rawParams( $html );
- return Status::newFatal( $msg );
+ // information (HTML, modules, etc.) to display as error message!
+ $captchaInfo = $captcha->getFormInformation();
+ $captchaRenderingInfo = HtmlRenderingInformation::fromArray(
+ $captchaInfo
+ );
+
+ $msg = wfMessage( 'flow-spam-confirmedit-form' )->rawParams( $captchaInfo['html'] );
+ $status = Status::newFatal( $msg );
+ $status->setResult( false, $captchaRenderingInfo );
+ return $status;
}
return Status::newGood();
diff --git a/Flow/includes/SpamFilter/ContentLengthFilter.php b/Flow/includes/SpamFilter/ContentLengthFilter.php
index 33ea50b5..352d2bf7 100644
--- a/Flow/includes/SpamFilter/ContentLengthFilter.php
+++ b/Flow/includes/SpamFilter/ContentLengthFilter.php
@@ -10,7 +10,7 @@ use Title;
class ContentLengthFilter implements SpamFilter {
/**
- * @var integer The maximum number of characters of wikitext to allow through filter
+ * @var int The maximum number of characters of wikitext to allow through filter
*/
protected $maxLength;
@@ -27,9 +27,10 @@ class ContentLengthFilter implements SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
return $newRevision->getContentLength() > $this->maxLength
? Status::newFatal( 'flow-error-content-too-long', $this->maxLength )
: Status::newGood();
diff --git a/Flow/includes/SpamFilter/Controller.php b/Flow/includes/SpamFilter/Controller.php
index 9b8b1429..c04faeff 100644
--- a/Flow/includes/SpamFilter/Controller.php
+++ b/Flow/includes/SpamFilter/Controller.php
@@ -12,12 +12,12 @@ class Controller {
/**
* @var SpamFilter[] Array of SpamFilter objects
*/
- protected $spamfilters = array();
+ protected $spamfilters = [];
/**
* Accepts multiple spamfilters.
*
- * @param SpamFilter $spamfilter...
+ * @param SpamFilter $spamfilter,...
* @throws FlowException When provided arguments are not an instance of SpamFilter
*/
public function __construct( SpamFilter $spamfilter /* [, SpamFilter $spamfilter2 [, ...]] */ ) {
@@ -35,22 +35,24 @@ class Controller {
* @param IContextSource $context
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
- * @param Title $title
+ * @param Title $title Title that is most specific to the action, e.g. topic for
+ * replies and board for header edits.
+ * @param Title $ownerTitle Board title
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
foreach ( $this->spamfilters as $spamfilter ) {
if ( !$spamfilter->enabled() ) {
continue;
}
- $status = $spamfilter->validate( $context, $newRevision, $oldRevision, $title );
+ $status = $spamfilter->validate( $context, $newRevision, $oldRevision, $title, $ownerTitle );
// no need to go through other filters when invalid data is discovered
if ( !$status->isOK() ) {
$titleString = $title->getPrefixedDBkey();
- $oldRevid = ( $oldRevision !== null ) ? $oldRevision->getRevisionId() : 'None';
- $newRevid = $newRevision->getRevisionId();
+ $oldRevid = ( $oldRevision !== null ) ? $oldRevision->getRevisionId()->getAlphadecimal() : 'None';
+ $newRevid = $newRevision->getRevisionId()->getAlphadecimal();
$klass = get_class( $spamfilter );
wfDebugLog( 'Flow', __METHOD__ . ": Spam filter failed on '" . $titleString . "'. Old revid: $oldRevid. New revid: $newRevid. Filter: $klass" );
return $status;
diff --git a/Flow/includes/SpamFilter/RateLimits.php b/Flow/includes/SpamFilter/RateLimits.php
new file mode 100644
index 00000000..7e048cc7
--- /dev/null
+++ b/Flow/includes/SpamFilter/RateLimits.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Flow\SpamFilter;
+
+use Flow\Model\AbstractRevision;
+use IContextSource;
+use Status;
+use Title;
+
+class RateLimits implements SpamFilter {
+ /**
+ * @param IContextSource $context
+ * @param AbstractRevision $newRevision
+ * @param AbstractRevision|null $oldRevision
+ * @param Title $title
+ * @param Title $ownerTitle
+ * @return Status
+ */
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
+ if ( $context->getUser()->pingLimiter( 'edit' ) ) {
+ return Status::newFatal( 'actionthrottledtext' );
+ }
+
+ return Status::newGood();
+ }
+
+ /**
+ * Checks if RateLimits is enabled.
+ *
+ * @return bool
+ */
+ public function enabled() {
+ return true;
+ }
+}
diff --git a/Flow/includes/SpamFilter/SpamBlacklist.php b/Flow/includes/SpamFilter/SpamBlacklist.php
index 9b4e9d74..91efc655 100644
--- a/Flow/includes/SpamFilter/SpamBlacklist.php
+++ b/Flow/includes/SpamFilter/SpamBlacklist.php
@@ -14,14 +14,19 @@ class SpamBlacklist implements SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
$spamObj = BaseBlacklist::getInstance( 'spam' );
if ( !$spamObj instanceof \SpamBlacklist ) {
wfWarn( __METHOD__ . ': Expected a SpamBlacklist instance but instead received: ' . get_class( $spamObj ) );
return Status::newFatal( 'something' );
}
+
+ // TODO: This seems to check topic titles. Should it? There can't
+ // actually be a link in a topic title, but http://spam.com can still look
+ // spammy even if it's not a working link.
$links = $this->getLinks( $newRevision, $title );
$matches = $spamObj->filter( $links, $title );
@@ -46,7 +51,7 @@ class SpamBlacklist implements SpamFilter {
public function getLinks( AbstractRevision $revision, Title $title ) {
global $wgParser;
$options = new \ParserOptions;
- $output = $wgParser->parse( $revision->getContent( 'wikitext' ), $title, $options );
+ $output = $wgParser->parse( $revision->getContentInWikitext(), $title, $options );
return array_keys( $output->getExternalLinks() );
}
diff --git a/Flow/includes/SpamFilter/SpamFilter.php b/Flow/includes/SpamFilter/SpamFilter.php
index 12841e28..eca30dd6 100644
--- a/Flow/includes/SpamFilter/SpamFilter.php
+++ b/Flow/includes/SpamFilter/SpamFilter.php
@@ -13,9 +13,10 @@ interface SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title );
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle );
/**
* @return bool
diff --git a/Flow/includes/SpamFilter/SpamRegex.php b/Flow/includes/SpamFilter/SpamRegex.php
index f3472f08..48fe32f2 100644
--- a/Flow/includes/SpamFilter/SpamRegex.php
+++ b/Flow/includes/SpamFilter/SpamRegex.php
@@ -13,21 +13,23 @@ class SpamRegex implements SpamFilter {
* @param AbstractRevision $newRevision
* @param AbstractRevision|null $oldRevision
* @param Title $title
+ * @param Title $ownerTitle
* @return Status
*/
- public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title ) {
+ public function validate( IContextSource $context, AbstractRevision $newRevision, AbstractRevision $oldRevision = null, Title $title, Title $ownerTitle ) {
global $wgSpamRegex;
/*
- * This should not roundtrip to Parsoid; SpamRegex checks will be
- * performed upon submitting new content, and content is always
- * submitted in wikitext. It will only be transformed once it's being
- * saved to DB.
+ * This should not cause an extra conversion; SpamRegex checks will be
+ * performed upon submitting new content. Content is always either
+ * submitted in (topic-title-)wikitext, or submitted in HTML, but
+ * immediately converted to wikitext and then treated as such. It will only
+ * be transformed once it's being saved to DB.
*/
- $text = $newRevision->getContent( 'wikitext' );
+ $text = $newRevision->getContentInWikitext();
// back compat, $wgSpamRegex may be a single string or an array of regexes
- $regexes = (array) $wgSpamRegex;
+ $regexes = (array)$wgSpamRegex;
foreach ( $regexes as $regex ) {
if ( preg_match( $regex, $text, $matches ) ) {
@@ -45,6 +47,6 @@ class SpamRegex implements SpamFilter {
*/
public function enabled() {
global $wgSpamRegex;
- return (bool) $wgSpamRegex;
+ return (bool)$wgSpamRegex;
}
}
diff --git a/Flow/includes/Specials/SpecialEnableStructuredDiscussions.php b/Flow/includes/Specials/SpecialEnableStructuredDiscussions.php
new file mode 100644
index 00000000..87b701a7
--- /dev/null
+++ b/Flow/includes/Specials/SpecialEnableStructuredDiscussions.php
@@ -0,0 +1,175 @@
+<?php
+
+namespace Flow\Specials;
+
+use FormSpecialPage;
+use Status;
+use Title;
+use Flow\Container;
+use Flow\Import\Converter;
+use Flow\Import\EnableFlow\EnableFlowWikitextConversionStrategy;
+use Flow\Import\SourceStore\NullImportSourceStore;
+
+/**
+ * A special page that allows users with the flow-create-board right to create
+ * boards where there no page exists
+ */
+class SpecialEnableStructuredDiscussions extends FormSpecialPage {
+ /**
+ * @var \Flow\WorkflowLoaderFactory
+ */
+ protected $loaderFactory;
+
+ /**
+ * @var \Flow\TalkpageManager
+ */
+ protected $occupationController;
+
+ /**
+ * @var string $page Full page name that was converted to a board
+ */
+ protected $page = '';
+
+ public function __construct() {
+ parent::__construct( 'EnableStructuredDiscussions', 'flow-create-board' );
+
+ $this->loaderFactory = Container::get( 'factory.loader.workflow' );
+ $this->occupationController = Container::get( 'occupation_controller' );
+ }
+
+ public function execute( $par ) {
+ if ( $par !== null ) {
+ $title = Title::newFromText( $par );
+ if ( $title ) {
+ $this->page = $title->getPrefixedText();
+ }
+ }
+
+ parent::execute( $par );
+ }
+
+ protected function getFormFields() {
+ return [
+ 'page' => [
+ 'type' => 'text',
+ 'label-message' => 'flow-special-enableflow-page',
+ 'default' => $this->page,
+ ],
+ 'header' => [
+ 'type' => 'textarea',
+ 'label-message' => 'flow-special-enableflow-header'
+ ],
+ ];
+ }
+
+ protected function getDisplayFormat() {
+ return 'ooui';
+ }
+
+ protected function getMessagePrefix() {
+ return 'flow-special-enableflow';
+ }
+
+ /**
+ * Creates a flow board.
+ * Archives any pre-existing wikitext talk page.
+ *
+ * @param array $data Form data
+ * @return Status Status indicating result
+ */
+ public function onSubmit( array $data ) {
+ $page = $data['page'];
+ $title = Title::newFromText( $page );
+ if ( !$title ) {
+ return Status::newFatal( 'flow-special-enableflow-invalid-title', $page );
+ }
+
+ // Canonicalize so the error or confirmation message looks nicer (no underscores).
+ $page = $title->getPrefixedText();
+
+ if ( $title->getContentModel() === CONTENT_MODEL_FLOW_BOARD ) {
+ return Status::newFatal( 'flow-special-enableflow-board-already-exists', $page );
+ }
+
+ $status = Status::newGood();
+
+ if ( $title->exists( Title::GAID_FOR_UPDATE ) ) {
+ if ( class_exists( 'LqtDispatch' ) && \LqtDispatch::isLqtPage( $title ) ) {
+ return Status::newFatal( 'flow-special-enableflow-page-is-liquidthreads', $page );
+ }
+
+ $logger = Container::get( 'default_logger' );
+
+ $converter = new Converter(
+ wfGetDB( DB_MASTER ),
+ Container::get( 'importer' ),
+ $logger,
+ $this->getUser(),
+ new EnableFlowWikitextConversionStrategy(
+ Container::get( 'parser' ),
+ new NullImportSourceStore(),
+ $logger,
+ $this->getUser(),
+ [],
+ $data['header']
+ )
+ );
+
+ try {
+ $converter->convert( $title );
+ } catch ( \Exception $e ) {
+ \MWExceptionHandler::logException( $e );
+ $status->fatal( 'flow-error-external', $e->getMessage() );
+ }
+
+ } else {
+ $creationStatus = $this->occupationController->safeAllowCreation( $title, $this->getUser(), false );
+ if ( !$creationStatus->isGood() ) {
+ return Status::newFatal( 'flow-special-enableflow-board-creation-not-allowed', $page );
+ }
+
+ $loader = $this->loaderFactory->createWorkflowLoader( $title );
+ $blocks = $loader->getBlocks();
+
+ $action = 'edit-header';
+ $params = [
+ 'header' => [
+ 'content' => $data['header'],
+ 'format' => 'wikitext',
+ ],
+ ];
+
+ $blocksToCommit = $loader->handleSubmit(
+ $this->getContext(),
+ $action,
+ $params
+ );
+
+ foreach ( $blocks as $block ) {
+ if ( $block->hasErrors() ) {
+ $errors = $block->getErrors();
+
+ foreach ( $errors as $errorKey ) {
+ $status->fatal( $block->getErrorMessage( $errorKey ) );
+ }
+ }
+ }
+
+ if ( $status->isOK() ) {
+ $loader->commit( $blocksToCommit );
+ }
+ }
+
+ $this->page = $data['page'];
+ return $status;
+ }
+
+ public function onSuccess() {
+ $confirmationMessage = $this->msg( 'flow-special-enableflow-confirmation', wfEscapeWikiText( $this->page ) )->parse();
+ $this->getOutput()->addHTML( $confirmationMessage );
+ }
+
+ protected function getGroupName() {
+ return 'wiki';
+ }
+}
diff --git a/Flow/includes/Specials/SpecialStructuredDiscussions.php b/Flow/includes/Specials/SpecialStructuredDiscussions.php
new file mode 100644
index 00000000..184138a0
--- /dev/null
+++ b/Flow/includes/Specials/SpecialStructuredDiscussions.php
@@ -0,0 +1,200 @@
+<?php
+
+/**
+ * A special page that redirects to a workflow or PostRevision given a UUID
+ */
+
+namespace Flow\Specials;
+
+use Flow\Container;
+use Flow\Data\ObjectManager;
+use Flow\Exception\FlowException;
+use Flow\Model\Workflow;
+use Flow\Model\UUID;
+use Flow\Repository\TreeRepository;
+use FormSpecialPage;
+use HTMLForm;
+use Status;
+
+class SpecialStructuredDiscussions extends FormSpecialPage {
+
+ /**
+ * The type of content, e.g. 'post', 'workflow'
+ * @var string
+ */
+ protected $type;
+
+ /**
+ * Flow UUID
+ * @var string
+ */
+ protected $uuid;
+
+ function __construct() {
+ parent::__construct( 'StructuredDiscussions' );
+ }
+
+ /**
+ * Initialize $this->type and $this-uuid using the subpage string.
+ * @param string $par
+ */
+ protected function setParameter( $par ) {
+ $tokens = explode( '/', $par, 2 );
+ $this->type = $tokens[0];
+ if ( count( $tokens ) > 1 ) {
+ $this->uuid = $tokens[1];
+ }
+ }
+
+ /**
+ * Get the mapping between display text and value for the type dropdown.
+ * @return array
+ */
+ protected function getTypes() {
+ $mapping = [
+ 'flow-special-type-post' => 'post',
+ 'flow-special-type-workflow' => 'workflow',
+ ];
+
+ $types = [];
+ foreach ( $mapping as $msgKey => $option ) {
+ $types[$this->msg( $msgKey )->escaped()] = $option;
+ }
+ return $types;
+ }
+
+ protected function getFormFields() {
+ return [
+ 'type' => [
+ 'id' => 'mw-flow-special-type',
+ 'name' => 'type',
+ 'type' => 'select',
+ 'label-message' => 'flow-special-type',
+ 'options' => $this->getTypes(),
+ 'default' => empty( $this->type ) ? 'post' : $this->type,
+ ],
+ 'uuid' => [
+ 'id' => 'mw-flow-special-uuid',
+ 'name' => 'uuid',
+ 'type' => 'text',
+ 'label-message' => 'flow-special-uuid',
+ 'default' => $this->uuid,
+ ],
+ ];
+ }
+
+ /**
+ * Description shown at the top of the page
+ * @return string
+ */
+ protected function preText() {
+ return '<p>' . $this->msg( 'flow-special-desc' )->escaped() . '</p>';
+ }
+
+ protected function alterForm( HTMLForm $form ) {
+ $form->setMethod( 'get' ); // This also submits the form every time the page loads.
+ }
+
+ /**
+ * @return string
+ */
+ protected function getDisplayFormat() {
+ return 'ooui';
+ }
+
+ /**
+ * Get the URL of a UUID for a PostRevision.
+ * @return string|null
+ */
+ protected function getPostUrl() {
+ try {
+ $postId = UUID::create( $this->uuid );
+ /** @var TreeRepository $treeRepo */
+ $treeRepo = Container::get( 'repository.tree' );
+ $rootId = $treeRepo->findRoot( $postId );
+ /** @var ObjectManager $om */
+ $om = Container::get( 'storage.workflow' );
+ $workflow = $om->get( $rootId );
+ if ( $workflow instanceof Workflow ) {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ return $urlGenerator->postLink(
+ null,
+ $rootId,
+ $postId
+ )->getFullUrl();
+ } else {
+ return null;
+ }
+ } catch ( FlowException $e ) {
+ return null; // The UUID is invalid or has no root post.
+ }
+ }
+
+ /**
+ * Get the URL of a UUID for a workflow.
+ * @return string|null
+ */
+ protected function getWorkflowUrl() {
+ try {
+ $rootId = UUID::create( $this->uuid );
+ /** @var ObjectManager $om */
+ $om = Container::get( 'storage.workflow' );
+ $workflow = $om->get( $rootId );
+ if ( $workflow instanceof Workflow ) {
+ /** @var UrlGenerator $urlGenerator */
+ $urlGenerator = Container::get( 'url_generator' );
+ return $urlGenerator->workflowLink(
+ null,
+ $rootId
+ )->getFullUrl();
+ } else {
+ return null;
+ }
+ } catch ( FlowException $e ) {
+ return null; // The UUID is invalid or has no root post.
+ }
+ }
+
+ /**
+ * Set redirect and return true if $data['uuid'] or $this->par exists and is
+ * a valid UUID; otherwise return false or a Status object encapsulating any
+ * error, which causes the form to be shown.
+ * @param array $data
+ * @return bool|Status
+ */
+ public function onSubmit( array $data ) {
+ if ( !empty( $data['type'] ) && !empty( $data['uuid'] ) ) {
+ $this->setParameter( $data['type'] . '/' . $data['uuid'] );
+ }
+
+ // Assume no data has been passed in if there is no UUID.
+ if ( empty( $this->uuid ) ) {
+ return false; // Display the form.
+ }
+
+ switch ( $this->type ) {
+ case 'post':
+ $url = $this->getPostUrl();
+ break;
+ case 'workflow':
+ $url = $this->getWorkflowUrl();
+ break;
+ default:
+ $url = null;
+ break;
+ }
+
+ if ( $url ) {
+ $this->getOutput()->redirect( $url );
+ return true;
+ } else {
+ $this->getOutput()->setStatusCode( 404 );
+ return Status::newFatal( 'flow-special-invalid-uuid' );
+ }
+ }
+
+ protected function getGroupName() {
+ return 'redirects';
+ }
+}
diff --git a/Flow/includes/SubmissionHandler.php b/Flow/includes/SubmissionHandler.php
index d83fbd78..dfa9ef7e 100644
--- a/Flow/includes/SubmissionHandler.php
+++ b/Flow/includes/SubmissionHandler.php
@@ -5,8 +5,8 @@ namespace Flow;
use DeferredUpdates;
use Flow\Block\AbstractBlock;
use Flow\Block\Block;
-use Flow\Data\BufferedCache;
use Flow\Data\ManagerGroup;
+use Flow\Exception\FailCommitException;
use Flow\Exception\InvalidDataException;
use Flow\Exception\InvalidActionException;
use Flow\Model\Workflow;
@@ -16,21 +16,16 @@ use SplQueue;
class SubmissionHandler {
/**
- * @var ManagerGroup $storage
+ * @var ManagerGroup
*/
protected $storage;
/**
- * @var DbFactory $dbFactory
+ * @var DbFactory
*/
protected $dbFactory;
/**
- * @var BufferedCache $bufferedCache
- */
- protected $bufferedCache;
-
- /**
* @var SplQueue Updates to add to DeferredUpdates post-commit
*/
protected $deferredQueue;
@@ -38,12 +33,10 @@ class SubmissionHandler {
public function __construct(
ManagerGroup $storage,
DbFactory $dbFactory,
- BufferedCache $bufferedCache,
SplQueue $deferredQueue
) {
$this->storage = $storage;
$this->dbFactory = $dbFactory;
- $this->bufferedCache = $bufferedCache;
$this->deferredQueue = $deferredQueue;
}
@@ -68,7 +61,7 @@ class SubmissionHandler {
$this->dbFactory->forceMaster();
/** @var Block[] $interestedBlocks */
- $interestedBlocks = array();
+ $interestedBlocks = [];
foreach ( $blocks as $block ) {
// This is just a check whether the block understands the action,
// Doesn't consider permissions
@@ -82,7 +75,7 @@ class SubmissionHandler {
if ( !$blocks ) {
throw new InvalidDataException( 'No Blocks?!?', 'fail-load-data' );
}
- $type = array();
+ $type = [];
foreach ( $blocks as $block ) {
$type[] = get_class( $block );
}
@@ -92,80 +85,80 @@ class SubmissionHandler {
// Check mediawiki core permissions for title protection, blocked
// status, etc.
- if ( !$workflow->userCan( 'edit', $context->getUser() ) ) {
- reset( $interestedBlocks )->addError( 'block', wfMessage( 'blockedtitle' ) );
- return array();
+ $errors = $workflow->getPermissionErrors( 'edit', $context->getUser(), 'secure' );
+ if ( count( $errors ) ) {
+ foreach ( $errors as $errorMsgArgs ) {
+ $msg = wfMessage( array_shift( $errorMsgArgs ) );
+ if ( $errorMsgArgs ) {
+ $msg->params( $errorMsgArgs );
+ }
+ // I guess this is the "user block" meaning of 'block'. If
+ // so, this is misleading, since it could be protection,
+ // etc. The specific error message (protect, block, etc.)
+ // will still be output, though.
+ // In theory, something could be relying on the string 'block',
+ // since it's exposed to the API, but probably not.
+ reset( $interestedBlocks )->addError( 'block', $msg );
+ }
+ return [];
}
$success = true;
foreach ( $interestedBlocks as $block ) {
$name = $block->getName();
- $data = isset( $parameters[$name] ) ? $parameters[$name] : array();
+ $data = isset( $parameters[$name] ) ? $parameters[$name] : [];
$success &= $block->onSubmit( $data );
}
- return $success ? $interestedBlocks : array();
+ return $success ? $interestedBlocks : [];
}
/**
* @param Workflow $workflow
* @param AbstractBlock[] $blocks
* @return array Map from committed block name to an array of metadata returned
- * about inserted objects.
+ * about inserted objects. This must be non-empty. An empty block array
+ * indicates there were errors, in which case this method should not be called.
* @throws \Exception
*/
public function commit( Workflow $workflow, array $blocks ) {
- $cache = $this->bufferedCache;
$dbw = $this->dbFactory->getDB( DB_MASTER );
- /**
- * Ideally, I'd create the page in Workflow::toStorageRow, but
- * WikiPage::doEditContent uses transactions & our DB wrapper
- * doesn't allow nested transactions, so that part has moved.
- *
- * Don't allowCreation() here: a board has to be explicitly created,
- * or allowed via the occupyNamespace & occupyPages globals, in
- * which case allowCreation() won't be needed.
- *
- * @var OccupationController $occupationController
- */
+ /** @var OccupationController $occupationController */
$occupationController = Container::get( 'occupation_controller' );
$title = $workflow->getOwnerTitle();
- $occupationController->ensureFlowRevision( new \Article( $title ), $workflow );
- $isNew = $workflow->isNew();
+
+ if ( count( $blocks ) === 0 ) {
+ // This is a logic error in the code, but we need to preserve
+ // consistent state.
+ throw new FailCommitException(
+ __METHOD__ . ' was called with $blocks set to an empty ' .
+ 'array or a falsy value. This indicates the blocks are ' .
+ 'not able to commit, so ' . __METHOD__ . ' should not be ' .
+ 'called.',
+ 'fail-commit'
+ );
+ }
try {
- $dbw->begin();
- $cache->begin();
- $results = array();
+ $dbw->startAtomic( __METHOD__ );
+ // Create the occupation page/revision if needed
+ $occupationController->ensureFlowRevision( new \Article( $title ), $workflow );
+ // Create/modify each Flow block as requested
+ $results = [];
foreach ( $blocks as $block ) {
$results[$block->getName()] = $block->commit();
}
- $dbw->commit();
-
- // Now commit to cache. If this fails, cache keys should have been
- // invalidated, but still log the failure.
- if ( !$cache->commit() ) {
- wfDebugLog( 'Flow', __METHOD__ . ': Committed to database but failed applying to cache' );
- }
+ $dbw->endAtomic( __METHOD__ );
} catch ( \Exception $e ) {
- while( !$this->deferredQueue->isEmpty() ) {
+ while ( !$this->deferredQueue->isEmpty() ) {
$this->deferredQueue->dequeue();
}
-
- if ( $isNew ) {
- $article = new \Article( $title );
- $page = $article->getPage();
- $reason = '/* Failed to create Flow board */';
- $page->doDeleteArticleReal( $reason, false, 0, true, $errors, $occupationController->getTalkpageManager() );
- }
-
- $dbw->rollback();
- $cache->rollback();
+ $this->dbFactory->rollbackMasterChanges( __METHOD__ );
throw $e;
}
- while( !$this->deferredQueue->isEmpty() ) {
+ while ( !$this->deferredQueue->isEmpty() ) {
DeferredUpdates::addCallableUpdate( $this->deferredQueue->dequeue() );
}
diff --git a/Flow/includes/TalkpageManager.php b/Flow/includes/TalkpageManager.php
index f59669b1..dacb569e 100644
--- a/Flow/includes/TalkpageManager.php
+++ b/Flow/includes/TalkpageManager.php
@@ -21,15 +21,50 @@ interface OccupationController {
public function ensureFlowRevision( Article $title, Workflow $workflow );
/**
- * @param Title $title
- * @param User $user
+ * Checks whether creation is technically possible.
+ *
+ * This considers all issues other than the user.
+ *
+ * @param Title $title Title to check
+ * @param bool $mustNotExist Whether the page is required to not exist; true means
+ * it must not exist.
+ * @return Status Status indicating whether the creation is technically allowed
+ */
+ public function checkIfCreationIsPossible( Title $title, $mustNotExist = true );
+
+ /**
+ * Check if user has permission to create board.
+ *
+ * @param Title $title Title to check
+ * @param User $user User doing creation or move
+ * @return Status Status indicating whether the creation is technically allowed
+ */
+ public function checkIfUserHasPermission( Title $title, User $user );
+
+ /**
+ * Checks whether the given user is allowed to create a board at the given
+ * title. If so, allows it to be created.
+ *
+ * @param Title $title Title to check
+ * @param User $user User who wants to create a board
* @param bool $mustNotExist Whether the page is required to not exist; defaults to
* true.
* @return Status Returns successful status when the provided user has the rights to
* convert $title from whatever it is now to a flow board; otherwise, specifies
* the error.
*/
- public function allowCreation( Title $title, User $user, $mustNotExist = true );
+ public function safeAllowCreation( Title $title, User $user, $mustNotExist = true );
+
+ /**
+ * Allows creation, *WITHOUT* checks.
+ *
+ * checkIfCreationIsPossible *MUST* be called earlier, and
+ * checkIfUserHasPermission *MUST* be called earlier except when permission checks
+ * are deliberately being bypassed (very rare cases like global rename)
+ *
+ * @param Title $title
+ */
+ public function forceAllowCreation( Title $title );
/**
* Gives a user object used to manage talk pages
@@ -42,9 +77,9 @@ interface OccupationController {
class TalkpageManager implements OccupationController {
/**
- * @var Title[]
+ * @var string[]
*/
- protected $allowCreation = array();
+ protected $allowedPageNames = [];
/**
* Cached talk page manager user
@@ -84,10 +119,10 @@ class TalkpageManager implements OccupationController {
$content = $revision->getContent();
if ( $content instanceof BoardContent && $content->getWorkflowId() ) {
// Revision is already a valid BoardContent
- return Status::newGood( array(
+ return Status::newGood( [
'revision' => $revision,
'already-existed' => true,
- ) );
+ ] );
}
}
@@ -106,18 +141,9 @@ class TalkpageManager implements OccupationController {
}
/**
- * Checks whether the given user is allowed to create a board at the given
- * title and allows it to be created.
- *
- * @param Title $title Title to check
- * @param User $user User who wants to create a board
- * @param bool $mustNotExist Whether the page is required to not exist; defaults to
- * true.
- * @return Status Returns successful status when the provided user has the rights to
- * convert $title from whatever it is now to a flow board; otherwise, specifies
- * the error.
+ * {@inheritdoc}
*/
- public function allowCreation( Title $title, User $user, $mustNotExist = true ) {
+ public function checkIfCreationIsPossible( Title $title, $mustNotExist = true, $forWrite = true ) {
global $wgContentHandlerUseDB;
// Arbitrary pages can only be enabled when content handler
@@ -126,48 +152,88 @@ class TalkpageManager implements OccupationController {
return Status::newFatal( 'flow-error-allowcreation-no-usedb' );
}
- // Only allow converting a non-existent page to flow
+ // Only allow converting a non-existent page to Flow
if ( $mustNotExist ) {
- // Make sure existence status is up to date
- $title->getArticleID( Title::GAID_FOR_UPDATE );
-
- if ( $title->exists() ) {
+ if ( $title->exists( $forWrite ? Title::GAID_FOR_UPDATE : 0 ) ) {
return Status::newFatal( 'flow-error-allowcreation-already-exists' );
}
}
- // Gate this on the flow-create-board right, essentially giving
- // wiki communities control over if flow board creation is allowed
- // to everyone or just a select few.
- if ( !$user->isAllowedAll( 'flow-create-board' ) ) {
+ return Status::newGood();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function checkIfUserHasPermission( Title $title, User $user ) {
+ if (
+ // If the title is default-Flow, the user always has permission
+ ContentHandler::getDefaultModelFor( $title ) === CONTENT_MODEL_FLOW_BOARD ||
+
+ // Gate this on the flow-create-board right, essentially giving
+ // wiki communities control over if Flow board creation is allowed
+ // to everyone or just a select few.
+ $user->isAllowedAll( 'flow-create-board' )
+ ) {
+ return Status::newGood();
+ } else {
return Status::newFatal( 'flow-error-allowcreation-flow-create-board' );
}
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeAllowCreation( Title $title, User $user, $mustNotExist = true, $forWrite = true ) {
+ $status = Status::newGood();
+
+ $technicallyAllowedStatus = $this->checkIfCreationIsPossible( $title, $mustNotExist, $forWrite );
+ $permissionStatus = $this->checkIfUserHasPermission( $title, $user );
+
+ $status->merge( $technicallyAllowedStatus );
+ $status->merge( $permissionStatus );
+
+ if ( $status->isOK() ) {
+ $this->forceAllowCreation( $title );
+ }
+
+ return $status;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function forceAllowCreation( Title $title ) {
/*
- * tracks which titles are allowed so that when
+ * Tracks which titles are allowed so that when
* BoardContentHandler::canBeUsedOn is called for this title, it
* can verify this title was explicitly allowed.
*/
- $this->allowCreation[] = $title->getPrefixedDBkey();
-
- return Status::newGood();
+ $this->allowedPageNames[] = $title->getPrefixedDBkey();
}
/**
* Before creating a flow board, BoardContentHandler::canBeUsedOn will be
* called to verify it's ok to create it.
* That, in turn, will call this, which will check if the title we want to
- * turn into a Flow board was allowed to create (with static::allowCreation)
+ * turn into a Flow board was allowed to create (with allowedPageNames)
*
* @param Title $title
* @return bool
*/
public function canBeUsedOn( Title $title ) {
+ global $wgUser;
+
+ // If the user has rights, mark the page as allowed
+ // For MovePage
+ $this->safeAllowCreation( $title, $wgUser, /* $mustNotExist = */ true );
+
return
// default content model already
ContentHandler::getDefaultModelFor( $title ) === CONTENT_MODEL_FLOW_BOARD ||
- // explicitly allowed via allowCreation()
- in_array( $title->getPrefixedDBkey(), $this->allowCreation );
+ // explicitly allowed via safeAllowCreation()
+ in_array( $title->getPrefixedDBkey(), $this->allowedPageNames );
}
/**
@@ -180,24 +246,19 @@ class TalkpageManager implements OccupationController {
return $this->talkPageManagerUser;
}
- $user = User::newFromName( FLOW_TALK_PAGE_MANAGER_USER );
-
- if ( $user->getId() === 0 ) {
- // Does not exist, lets create it
- $user->loadDefaults( FLOW_TALK_PAGE_MANAGER_USER );
- $user->addToDatabase();
- if ( class_exists( 'CentralAuthUser' ) ) {
- // Attach to CentralAuth if a global account already
- // exists
- $ca = CentralAuthUser::getInstance( $user );
- if ( $ca->exists() ) {
- $ca->attach( wfWikiID(), 'admin' );
- }
+ $user = User::newSystemUser( FLOW_TALK_PAGE_MANAGER_USER, [ 'steal' => true ] );
+
+ if ( class_exists( 'CentralAuthUser' ) ) {
+ // Attach to CentralAuth if a global account already
+ // exists
+ $ca = CentralAuthUser::getMasterInstance( $user );
+ if ( $ca->exists() && !$ca->isAttached() ) {
+ $ca->attach( wfWikiID(), 'admin' );
}
}
$groups = $user->getGroups();
- foreach ( array( 'bot', 'flow-bot' ) as $group ) {
+ foreach ( [ 'bot', 'flow-bot' ] as $group ) {
if ( !in_array( $group, $groups ) ) {
$user->addGroup( $group );
}
diff --git a/Flow/includes/TemplateHelper.php b/Flow/includes/TemplateHelper.php
index 0a1a8f0d..cd1251f4 100644
--- a/Flow/includes/TemplateHelper.php
+++ b/Flow/includes/TemplateHelper.php
@@ -7,6 +7,7 @@ use Flow\Exception\WrongNumberArgumentsException;
use Flow\Model\UUID;
use Closure;
use HTML;
+use OOUI\IconWidget;
use LightnCandy;
use MWTimestamp;
use RequestContext;
@@ -31,7 +32,7 @@ class TemplateHelper {
/**
* @param string $templateDir
- * @param boolean $forceRecompile
+ * @param bool $forceRecompile
*/
public function __construct( $templateDir, $forceRecompile = false ) {
$this->templateDir = $templateDir;
@@ -65,10 +66,10 @@ class TemplateHelper {
throw new FlowException( "Malformed \$templateName: $templateName" );
}
- return array(
+ return [
'template' => "{$this->templateDir}/{$templateName}.handlebars",
'compiled' => "{$this->templateDir}/compiled/{$templateName}.handlebars.php",
- );
+ ];
}
/**
@@ -108,7 +109,7 @@ class TemplateHelper {
/** @var callable $renderer */
$renderer = require $filenames['compiled'];
- return $this->renderers[$templateName] = function( $args, array $scopes = array() ) use ( $templateName, $renderer ) {
+ return $this->renderers[$templateName] = function ( $args, array $scopes = [] ) use ( $templateName, $renderer ) {
return $renderer( $args, $scopes );
};
}
@@ -119,18 +120,18 @@ class TemplateHelper {
*
* @return string PHP code
*/
- static public function compile( $code, $templateDir ) {
+ public static function compile( $code, $templateDir ) {
return LightnCandy::compile(
$code,
- array(
+ [
'flags' => LightnCandy::FLAG_ERROR_EXCEPTION
| LightnCandy::FLAG_EXTHELPER
| LightnCandy::FLAG_SPVARS
| LightnCandy::FLAG_HANDLEBARS
| LightnCandy::FLAG_RUNTIMEPARTIAL,
- 'basedir' => array( $templateDir ),
- 'fileext' => array( '.partial.handlebars' ),
- 'helpers' => array(
+ 'basedir' => [ $templateDir ],
+ 'fileext' => [ '.partial.handlebars' ],
+ 'helpers' => [
'l10n' => 'Flow\TemplateHelper::l10n',
'uuidTimestamp' => 'Flow\TemplateHelper::uuidTimestamp',
'timestamp' => 'Flow\TemplateHelper::timestampHelper',
@@ -151,15 +152,15 @@ class TemplateHelper {
'escapeContent' => 'Flow\TemplateHelper::escapeContent',
'enablePatrollingLink' => 'Flow\TemplateHelper::enablePatrollingLink',
'oouify' => 'Flow\TemplateHelper::oouify',
- ),
- 'hbhelpers' => array(
+ ],
+ 'hbhelpers' => [
'eachPost' => 'Flow\TemplateHelper::eachPost',
'ifAnonymous' => 'Flow\TemplateHelper::ifAnonymous',
'ifCond' => 'Flow\TemplateHelper::ifCond',
'tooltip' => 'Flow\TemplateHelper::tooltip',
'progressiveEnhancement' => 'Flow\TemplateHelper::progressiveEnhancement',
- ),
- )
+ ],
+ ]
);
}
@@ -172,7 +173,7 @@ class TemplateHelper {
*
* @return string
*/
- static public function processTemplate( $templateName, $args, array $scopes = array() ) {
+ public static function processTemplate( $templateName, $args, array $scopes = [] ) {
// Undesirable, but lightncandy helpers have to be static methods
/** @var TemplateHelper $lightncandy */
$lightncandy = Container::get( 'lightncandy' );
@@ -196,7 +197,7 @@ class TemplateHelper {
* @return null|string
* @throws WrongNumberArgumentsException
*/
- static public function uuidTimestamp( array $args, array $named ) {
+ public static function uuidTimestamp( array $args, array $named ) {
if ( count( $args ) !== 1 ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -219,7 +220,7 @@ class TemplateHelper {
* @return string
* @throws WrongNumberArgumentsException
*/
- static public function timestampHelper( array $args, array $named ) {
+ public static function timestampHelper( array $args, array $named ) {
if ( count( $args ) < 1 || count( $args ) > 2 ) {
throw new WrongNumberArgumentsException( $args, 'one', 'two' );
}
@@ -230,11 +231,11 @@ class TemplateHelper {
}
/**
- * @param integer $timestamp milliseconds since the unix epoch
+ * @param int $timestamp milliseconds since the unix epoch
*
* @return string|false
*/
- static protected function timestamp( $timestamp ) {
+ protected static function timestamp( $timestamp ) {
global $wgLang, $wgUser;
if ( !$timestamp ) {
@@ -247,12 +248,12 @@ class TemplateHelper {
return self::html( self::processTemplate(
'timestamp',
- array(
+ [
'time_iso' => $timestamp,
'time_ago' => $ts->getHumanTimestamp(),
'time_readable' => $wgLang->userTimeAndDate( $timestamp, $wgUser ),
- 'guid' => null, //generated client-side
- )
+ 'guid' => null, // generated client-side
+ ]
) );
}
@@ -265,8 +266,8 @@ class TemplateHelper {
*
* @return string[] array(html, 'raw')
*/
- static protected function html( $string ) {
- return array( $string, 'raw' );
+ protected static function html( $string ) {
+ return [ $string, 'raw' ];
}
/**
@@ -275,7 +276,7 @@ class TemplateHelper {
*
* @return string[] array(html, 'raw')
*/
- static public function htmlHelper( array $args, array $named ) {
+ public static function htmlHelper( array $args, array $named ) {
return self::html( isset( $args[0] ) ? $args[0] : 'undefined' );
}
@@ -286,7 +287,7 @@ class TemplateHelper {
* @return string[]
* @throws WrongNumberArgumentsException
*/
- static public function block( array $args, array $named ) {
+ public static function block( array $args, array $named ) {
if ( !isset( $args[0] ) ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -309,15 +310,15 @@ class TemplateHelper {
* @return null|string HTML
* @throws FlowException When callbacks are not Closure instances
*/
- static public function eachPost( $context, $postIds, $options ) {
+ public static function eachPost( $context, $postIds, $options ) {
/** @var callable $inverse */
$inverse = isset( $options['inverse'] ) ? $options['inverse'] : null;
/** @var callable $fn */
$fn = $options['fn'];
if ( $postIds && !is_array( $postIds ) ) {
- $postIds = array( $postIds );
- } elseif ( count( $postIds ) === 0 ) {
+ $postIds = [ $postIds ];
+ } elseif ( $postIds === [] ) {
// Failure callback, if any
if ( !$inverse ) {
return null;
@@ -325,7 +326,7 @@ class TemplateHelper {
if ( !$inverse instanceof Closure ) {
throw new FlowException( 'Invalid inverse callback, expected Closure' );
}
- return $inverse( $options['cx'], array() );
+ return $inverse( $options['cx'], [] );
} else {
return null;
}
@@ -333,7 +334,7 @@ class TemplateHelper {
if ( !$fn instanceof Closure ) {
throw new FlowException( 'Invalid callback, expected Closure' );
}
- $html = array();
+ $html = [];
foreach ( $postIds as $id ) {
$revId = $context['posts'][$id][0];
@@ -358,15 +359,15 @@ class TemplateHelper {
* @return string[]
* @throws WrongNumberArgumentsException
*/
- static public function post( array $args, array $named ) {
+ public static function post( array $args, array $named ) {
if ( count( $args ) !== 2 ) {
throw new WrongNumberArgumentsException( $args, 'two' );
}
list( $rootBlock, $revision ) = $args;
- return self::html( self::processTemplate( 'flow_post', array(
+ return self::html( self::processTemplate( 'flow_post', [
'revision' => $revision,
'rootBlock' => $rootBlock,
- ) ) );
+ ] ) );
}
/**
@@ -376,23 +377,23 @@ class TemplateHelper {
* @return string[]
* @throws WrongNumberArgumentsException
*/
- static public function historyTimestamp( array $args, array $named ) {
+ public static function historyTimestamp( array $args, array $named ) {
if ( !$args ) {
throw new WrongNumberArgumentsException( $args, 'one', 'two' );
}
$revision = $args[0];
$raw = false;
$formattedTime = $revision['dateFormats']['timeAndDate'];
- $linkKeys = array( 'header-revision', 'topic-revision', 'post-revision', 'summary-revision' );
+ $linkKeys = [ 'header-revision', 'topic-revision', 'post-revision', 'summary-revision' ];
foreach ( $linkKeys as $linkKey ) {
if ( isset( $revision['links'][$linkKey] ) ) {
$link = $revision['links'][$linkKey];
$formattedTime = Html::element(
'a',
- array(
+ [
'href' => $link['url'],
'title' => $link['title'],
- ),
+ ],
$formattedTime
);
$raw = true;
@@ -404,14 +405,14 @@ class TemplateHelper {
$formattedTime = htmlspecialchars( $formattedTime );
}
- $class = array( 'mw-changeslist-date' );
+ $class = [ 'mw-changeslist-date' ];
if ( $revision['isModeratedNotLocked'] ) {
$class[] = 'history-deleted';
}
return self::html(
'<span class="plainlinks">'
- . Html::rawElement( 'span', array( 'class' => $class ), $formattedTime )
+ . Html::rawElement( 'span', [ 'class' => $class ], $formattedTime )
. '</span>'
);
}
@@ -423,7 +424,7 @@ class TemplateHelper {
* @return string[]
* @throws WrongNumberArgumentsException
*/
- static public function historyDescription( array $args, array $named ) {
+ public static function historyDescription( array $args, array $named ) {
if ( count( $args ) !== 1 ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -435,8 +436,12 @@ class TemplateHelper {
$i18nKey = $revision['properties']['_key'];
unset( $revision['properties']['_key'] );
- // a variety of the i18n history messages contain wikitext and require ->parse()
- return self::html( wfMessage( $i18nKey, $revision['properties'] )->parse() );
+ // $revision['properties'] contains the params for the i18n message, which are named,
+ // so we need array_values() to strip the names. They are in the correct order because
+ // RevisionFormatter::getDescriptionParams() uses a foreach loop to build this array
+ // from the i18n-params definition in FlowActions.php.
+ // A variety of the i18n history messages contain wikitext and require ->parse().
+ return self::html( wfMessage( $i18nKey, array_values( $revision['properties'] ) )->parse() );
}
/**
@@ -446,7 +451,7 @@ class TemplateHelper {
* @return string[]
* @throws WrongNumberArgumentsException
*/
- static public function showCharacterDifference( array $args, array $named ) {
+ public static function showCharacterDifference( array $args, array $named ) {
if ( count( $args ) !== 2 ) {
throw new WrongNumberArgumentsException( $args, 'two' );
}
@@ -464,7 +469,7 @@ class TemplateHelper {
*
* @return string[]
*/
- static public function progressiveEnhancement( array $options ) {
+ public static function progressiveEnhancement( array $options ) {
$fn = $options['fn'];
$input = $options['hash'];
$insertionType = empty( $input['type'] ) ? 'insert' : htmlspecialchars( $input['type'] );
@@ -491,41 +496,38 @@ class TemplateHelper {
* @param array $named named object for arguments given by handlebars
* @return string Representation of an ooui widget dom
*/
- static public function oouify( array $args, array $named ) {
+ public static function oouify( array $args, array $named ) {
$widgetType = $named[ 'type' ];
- $data = array();
+ $data = [];
- // Parse label
- if ( isset( $named['label'] ) ) {
- $label = $named[ 'label' ];
- }
- $classes = array();
+ $classes = [];
if ( isset( $named['classes'] ) ) {
$classes = explode( ' ', $named[ 'classes' ] );
}
- if ( empty( $label ) && !empty( $named['l10n'] ) ) {
- $label = TemplateHelper::l10n( explode( ' ', $named['l10n'] ), array() );
- }
-
// Push raw arguments
$data['args'] = $args;
- $baseConfig = array(
+ $baseConfig = [
// 'infusable' => true,
- 'id' => $named[ 'name' ],
+ 'id' => isset( $named[ 'name' ] ) ? isset( $named[ 'name' ] ) : null,
'classes' => $classes,
'data' => $data
- );
- switch( $widgetType ) {
+ ];
+ switch ( $widgetType ) {
case 'BoardDescriptionWidget':
- $dataArgs = array(
+ $dataArgs = [
'infusable' => false,
- 'descriptionFormat' => $args[0],
- 'description' => $args[1],
- 'editLink' => $args[2]
- );
+ 'description' => $args[0],
+ 'editLink' => $args[1]
+ ];
$widget = new OOUI\BoardDescriptionWidget( $baseConfig + $dataArgs );
break;
+ case 'IconWidget':
+ $dataArgs = [
+ 'icon' => $args[0],
+ ];
+ $widget = new IconWidget( $baseConfig + $dataArgs );
+ break;
}
return $widget;
@@ -535,9 +537,9 @@ class TemplateHelper {
* @param array $args one or more arguments, i18n key and parameters
* @param array $named unused
*
- * @return string Plaintext
+ * @return string Message output, using the 'text' format
*/
- static public function l10n( array $args, array $named ) {
+ public static function l10n( array $args, array $named ) {
$message = null;
$str = array_shift( $args );
@@ -549,7 +551,7 @@ class TemplateHelper {
*
* @return string[] HTML
*/
- static public function l10nParse( array $args, array $named ) {
+ public static function l10nParse( array $args, array $named ) {
$str = array_shift( $args );
return self::html( wfMessage( $str, $args )->parse() );
}
@@ -562,7 +564,7 @@ class TemplateHelper {
* @return string[] HTML wrapped in array to prevent lightncandy from escaping
* @throws WrongNumberArgumentsException
*/
- static public function diffRevision( array $args, array $named ) {
+ public static function diffRevision( array $args, array $named ) {
if ( count( $args ) !== 1 ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -583,22 +585,22 @@ class TemplateHelper {
return self::html( $differenceEngine->addHeader(
$data['diff_content'],
- $renderer( array(
+ $renderer( [
'old' => true,
'revision' => $data['old'],
'links' => $data['links'],
- ) ),
- $renderer( array(
+ ] ),
+ $renderer( [
'new' => true,
'revision' => $data['new'],
'links' => $data['links'],
- ) ),
+ ] ),
$multi,
$notice
) );
}
- static public function diffUndo( array $args, array $named ) {
+ public static function diffUndo( array $args, array $named ) {
if ( count( $args ) !== 1 ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -630,7 +632,7 @@ class TemplateHelper {
* @return string
* @throws WrongNumberArgumentsException
*/
- static public function moderationAction( array $args, array $named ) {
+ public static function moderationAction( array $args, array $named ) {
if ( count( $args ) !== 2 ) {
throw new WrongNumberArgumentsException( $args, 'two' );
}
@@ -644,7 +646,7 @@ class TemplateHelper {
*
* @return string all unnamed arguments joined together
*/
- static public function concat( array $args, array $named ) {
+ public static function concat( array $args, array $named ) {
return implode( '', $args );
}
@@ -656,13 +658,13 @@ class TemplateHelper {
*
* @return string value of property
*/
- static public function user( array $args, array $named ) {
+ public static function user( array $args, array $named ) {
$feature = isset( $args[0] ) ? $args[0] : 'name';
$user = RequestContext::getMain()->getUser();
- $userInfo = array(
+ $userInfo = [
'id' => $user->getId(),
'name' => $user->getName(),
- );
+ ];
return $userInfo[$feature];
}
@@ -675,7 +677,7 @@ class TemplateHelper {
* @return mixed result of callback
* @throws FlowException Fails when callbacks are not Closure instances
*/
- static public function ifAnonymous( $options ) {
+ public static function ifAnonymous( $options ) {
if ( RequestContext::getMain()->getUser()->isAnon() ) {
$fn = $options['fn'];
if ( !$fn instanceof Closure ) {
@@ -700,7 +702,7 @@ class TemplateHelper {
*
* @return string modified url
*/
- static protected function addReturnTo( $url ) {
+ protected static function addReturnTo( $url ) {
$ctx = RequestContext::getMain();
$returnTo = $ctx->getTitle();
if ( !$returnTo ) {
@@ -711,9 +713,9 @@ class TemplateHelper {
unset( $returnToQuery['title'] );
- $args = array(
+ $args = [
'returnto' => $returnTo->getPrefixedUrl(),
- );
+ ];
if ( $returnToQuery ) {
$args['returntoquery'] = wfArrayToCgi( $returnToQuery );
}
@@ -729,7 +731,7 @@ class TemplateHelper {
* @return string modified url
* @throws WrongNumberArgumentsException
*/
- static public function linkWithReturnTo( array $args, array $named ) {
+ public static function linkWithReturnTo( array $args, array $named ) {
if ( count( $args ) !== 1 ) {
throw new WrongNumberArgumentsException( $args, 'one' );
}
@@ -757,12 +759,12 @@ class TemplateHelper {
* @return string
* @throws WrongNumberArgumentsException
*/
- static public function escapeContent( array $args, array $named ) {
+ public static function escapeContent( array $args, array $named ) {
if ( count( $args ) !== 2 ) {
throw new WrongNumberArgumentsException( $args, 'two' );
}
list( $contentType, $content ) = $args;
- return in_array( $contentType, array( 'html', 'fixed-html' ) ) ? self::html( $content ) : $content;
+ return in_array( $contentType, [ 'html', 'fixed-html', 'topic-title-html' ] ) ? self::html( $content ) : $content;
}
/**
@@ -776,7 +778,7 @@ class TemplateHelper {
* @return mixed result of callback
* @throws FlowException Fails when callbacks are not Closure instances
*/
- static public function ifCond( $value, $operator, $value2, $options ) {
+ public static function ifCond( $value, $operator, $value2, $options ) {
$doCallback = false;
// Perform operator
@@ -819,25 +821,25 @@ class TemplateHelper {
*
* @return string tooltip
*/
- static public function tooltip( $options ) {
+ public static function tooltip( $options ) {
$fn = $options['fn'];
$params = $options['hash'];
return (
- self::processTemplate( 'flow_tooltip', array(
+ self::processTemplate( 'flow_tooltip', [
'positionClass' => $params['positionClass'] ? 'flow-ui-tooltip-' . $params['positionClass'] : null,
'contextClass' => $params['contextClass'] ? 'mw-ui-' . $params['contextClass'] : null,
'extraClass' => $params['extraClass'] ?: '',
'blockClass' => $params['isBlock'] ? 'flow-ui-tooltip-block' : null,
'content' => $fn(),
- ) )
+ ] )
);
}
/**
* Adds required resource and protection for patrolling link.
*/
- static public function enablePatrollingLink() {
+ public static function enablePatrollingLink() {
$outputPage = RequestContext::getMain()->getOutput();
$outputPage->preventClickjacking();
diff --git a/Flow/includes/Templating.php b/Flow/includes/Templating.php
index 2b71ae6f..8370c358 100644
--- a/Flow/includes/Templating.php
+++ b/Flow/includes/Templating.php
@@ -2,7 +2,7 @@
namespace Flow;
-use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
use Flow\Exception\PermissionException;
use Flow\Repository\UserNameBatch;
use Flow\Exception\FlowException;
@@ -12,7 +12,6 @@ use Flow\Parsoid\ContentFixer;
use OutputPage;
// These don't really belong here
use Linker;
-use Message;
/**
* This class is slowly being deprecated. It used to house a minimalist
@@ -83,8 +82,8 @@ class Templating {
*
* Moderation-aware.
*
- * @param AbstractRevision $revision Revision to display
- * @return string HTML
+ * @param AbstractRevision $revision Revision to display
+ * @return string HTML
* @throws PermissionException
*/
public function getUserLinks( AbstractRevision $revision ) {
@@ -101,7 +100,7 @@ class Templating {
if ( isset( $cache[$userid][$userip] ) ) {
return $cache[$userid][$userip];
}
- $username = $this->usernames->get( wfWikiId(), $userid, $userip );
+ $username = $this->usernames->get( wfWikiID(), $userid, $userip );
return $cache[$userid][$userip] = Linker::userLink( $userid, $username ) . Linker::userToolLinks( $userid, $username );
}
@@ -116,19 +115,23 @@ class Templating {
*
* The content-type of the return value varies on the $format parameter.
* Further processing in the final output stage must escape all formats
- * other than the default 'html'.
+ * other than the default 'html' and 'fixed-html'.
*
* @param AbstractRevision $revision Revision to display content for
- * @param string[optional] $format Format to output content in (fixed-html|html|wikitext|plaintext)
+ * @param string[optional] $format Format to output content in (fixed-html|html|wikitext|topic-title-html|topic-title-wikitext|topic-title-plaintext)
* @return string HTML if requested, otherwise plain text
- * @throws InvalidInputException
+ * @throws InvalidParameterException
*/
public function getContent( AbstractRevision $revision, $format = 'fixed-html' ) {
- if ( !in_array( $format, array( 'fixed-html', 'html', 'plaintext', 'wikitext' ) ) ) {
- throw new InvalidInputException( 'Invalid format: ' . $format );
+ if ( !in_array( $format, [ 'fixed-html', 'html', 'wikitext', 'topic-title-html', 'topic-title-wikitext', 'topic-title-plaintext' ] ) ) {
+ throw new InvalidParameterException( 'Invalid format: ' . $format );
}
- $allowed = $this->permissions->isAllowed( $revision, 'view' );
+ $mainPermissionAction = ( $revision instanceof PostRevision && $revision->isTopicTitle() ) ?
+ 'view-topic-title' :
+ 'view';
+
+ $allowed = $this->permissions->isAllowed( $revision, $mainPermissionAction );
// Posts require view access to the topic title as well
if ( $allowed && $revision instanceof PostRevision && !$revision->isTopicTitle() ) {
$allowed = $this->permissions->isAllowed(
@@ -142,23 +145,11 @@ class Templating {
return '';
}
- try {
- if ( $format === 'fixed-html' ) {
- // Parsoid doesn't render redlinks & doesn't strip bad images
- $content = $this->contentFixer->getContent( $revision );
- } else {
- // plaintext = wikitext
- $format = $format === 'plaintext' ? 'wikitext' : $format;
- $content = $revision->getContent( $format );
- }
- } catch ( \Exception $e ) {
- wfDebugLog( 'Flow', __METHOD__ . ': Failed to get content for rev_id = ' . $revision->getRevisionId()->getAlphadecimal() );
- \MWExceptionHandler::logException( $e );
-
- $content = wfMessage( 'flow-stub-post-content' )->parse();
- if ( !in_array( $format, array( 'html', 'fixed-html' ) ) ) {
- $content = strip_tags( $content );
- }
+ if ( $format === 'fixed-html' ) {
+ // Parsoid doesn't render redlinks & doesn't strip bad images
+ $content = $this->contentFixer->getContent( $revision );
+ } else {
+ $content = $revision->getContent( $format );
}
return $content;
diff --git a/Flow/includes/UrlGenerator.php b/Flow/includes/UrlGenerator.php
index 20ab2083..5d176eab 100644
--- a/Flow/includes/UrlGenerator.php
+++ b/Flow/includes/UrlGenerator.php
@@ -46,9 +46,9 @@ class UrlGenerator {
}
$alpha = $workflowId->getAlphadecimal();
- $workflow = $this->workflowMapper->get( array(
+ $workflow = $this->workflowMapper->get( [
'workflow_id' => $alpha,
- ) );
+ ] );
if ( $workflow === null ) {
throw new InvalidInputException( 'Unloaded workflow:' . $alpha, 'invalid-workflow' );
}
@@ -66,7 +66,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-new' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'new-topic' )
+ [ 'action' => 'new-topic' ]
);
}
@@ -81,22 +81,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-edit-header' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'edit-header' )
- );
- }
-
- /**
- * Edit the title of a topic workflow.
- *
- * @param Title|null $title
- * @param UUID $workflowId
- * @return Anchor
- */
- public function editTitleLink( Title $title = null, UUID $workflowId ) {
- return new Anchor(
- wfMessage( 'flow-edit-title' ),
- $this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'edit-title' )
+ [ 'action' => 'edit-header' ]
);
}
@@ -112,10 +97,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-link-header-revision' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'header_revId' => $revId->getAlphadecimal(),
'action' => 'view-header'
- )
+ ]
);
}
@@ -131,10 +116,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-link-topic-revision' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'topic_revId' => $revId->getAlphadecimal(),
'action' => 'single-view'
- )
+ ]
);
}
@@ -151,11 +136,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-link-post-revision' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'topic_postId' => $postId->getAlphadecimal(),
'topic_revId' => $revId->getAlphadecimal(),
'action' => 'single-view'
- )
+ ]
);
}
@@ -171,10 +156,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-link-summary-revision' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'topicsummary_revId' => $revId->getAlphadecimal(),
'action' => 'view-topic-summary'
- )
+ ]
);
}
@@ -205,11 +190,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-link-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
// If the post is moderated this will flag the backend to still
// include the content in the html response.
'topic_showPostId' => $postId->getAlphadecimal()
- ),
+ ],
'#flow-post-' . $postId->getAlphadecimal()
);
}
@@ -226,10 +211,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-post-history' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'history',
'topic_postId' => $postId->getAlphadecimal(),
- )
+ ]
);
}
@@ -244,7 +229,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-history' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'history' )
+ [ 'action' => 'history' ]
);
}
@@ -258,7 +243,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'hist' ),
$title,
- array( 'action' => 'history' )
+ [ 'action' => 'history' ]
);
}
@@ -297,11 +282,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-undo' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'undo-edit-post',
'topic_startId' => $startId->getAlphadecimal(),
'topic_endId' => $endId->getAlphadecimal(),
- )
+ ]
);
}
@@ -316,11 +301,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-undo' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'undo-edit-header',
'header_startId' => $startId->getAlphadecimal(),
'header_endId' => $endId->getAlphadecimal(),
- )
+ ]
);
}
@@ -335,11 +320,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-undo' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'undo-edit-topic-summary',
'topicsummary_startId' => $startId->getAlphadecimal(),
'topicsummary_endId' => $endId->getAlphadecimal(),
- )
+ ]
);
}
@@ -380,12 +365,12 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'diff' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'compare-header-revisions',
'header_newRevision' => $revId->getAlphadecimal(),
- ) + ( $oldRevId === null ? array() : array(
+ ] + ( $oldRevId === null ? [] : [
'header_oldRevision' => $oldRevId->getAlphadecimal(),
- ) )
+ ] )
);
}
@@ -406,12 +391,12 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'diff' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'compare-post-revisions',
'topic_newRevision' => $revId->getAlphadecimal(),
- ) + ( $oldRevId === null ? array() : array(
+ ] + ( $oldRevId === null ? [] : [
'topic_oldRevision' => $oldRevId->getAlphadecimal(),
- ) )
+ ] )
);
}
@@ -432,12 +417,12 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'diff' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'compare-postsummary-revisions',
'topicsummary_newRevision' => $revId->getAlphadecimal(),
- ) + ( $oldRevId === null ? array() : array(
+ ] + ( $oldRevId === null ? [] : [
'topicsummary_oldRevision' => $oldRevId->getAlphadecimal(),
- ) )
+ ] )
);
}
@@ -467,7 +452,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'watch' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'watch' )
+ [ 'action' => 'watch' ]
);
}
@@ -483,7 +468,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'unwatch' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'unwatch' )
+ [ 'action' => 'unwatch' ]
);
}
@@ -498,7 +483,7 @@ class UrlGenerator {
* @return Anchor
*/
public function boardLink( Title $title, $sortBy = null, $saveSortBy = false ) {
- $options = array();
+ $options = [];
if ( $sortBy !== null ) {
$options['topiclist_sortby'] = $sortBy;
@@ -536,15 +521,14 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-reply-link' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'reply',
'topic_postId' => $postId->getAlphadecimal(),
- ),
+ ],
$hash
);
}
-
/**
* Edit the specified topic summary
*
@@ -556,7 +540,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-summarize-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'edit-topic-summary' )
+ [ 'action' => 'edit-topic-summary' ]
);
}
@@ -571,10 +555,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-lock-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'lock-topic',
'flow_moderationState' => AbstractRevision::MODERATED_LOCKED,
- )
+ ]
);
}
@@ -591,10 +575,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-' . $moderationAction . '-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => $flowAction,
'flow_moderationState' => $moderationAction,
- )
+ ]
);
}
@@ -612,11 +596,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-' . $moderationAction . '-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => $flowAction,
'topic_moderationState' => $moderationAction,
'topic_postId' => $postId->getAlphadecimal(),
- )
+ ]
);
}
@@ -630,7 +614,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-edit-header-link' ),
$title,
- array( 'action' => 'edit-header' )
+ [ 'action' => 'edit-header' ]
);
}
@@ -646,7 +630,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-edit-header-link' ),
$this->resolveTitle( $title, $workflowId ),
- array( 'action' => 'edit-header' )
+ [ 'action' => 'edit-header' ]
);
}
@@ -663,11 +647,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-edit-title' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'edit-title',
- // @todo not necessary?
- 'topic_revId' => $revId->getAlphadecimal(),
- )
+ 'topic_postId' => $postId->getAlphadecimal(),
+ 'topic_format' => 'wikitext',
+ ]
);
}
@@ -684,12 +668,12 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-edit-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'edit-post',
'topic_postId' => $postId->getAlphadecimal(),
// @todo not necessary?
'topic_revId' => $revId->getAlphadecimal(),
- ),
+ ],
'#flow-post-' . $postId->getAlphadecimal()
);
@@ -706,10 +690,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-hide-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-topic',
'topic_moderationState' => AbstractRevision::MODERATED_HIDDEN,
- )
+ ]
);
}
@@ -725,11 +709,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-hide-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-post',
'topic_postId' => $postId->getAlphadecimal(),
'topic_moderationState' => AbstractRevision::MODERATED_HIDDEN,
- )
+ ]
);
}
@@ -744,10 +728,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-delete-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-topic',
'topic_moderationState' => AbstractRevision::MODERATED_DELETED,
- )
+ ]
);
}
@@ -763,11 +747,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-delete-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-post',
'topic_postId' => $postId->getAlphadecimal(),
'topic_moderationState' => AbstractRevision::MODERATED_DELETED,
- )
+ ]
);
}
@@ -782,10 +766,10 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-topic-action-suppress-topic' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-topic',
'topic_moderationState' => AbstractRevision::MODERATED_SUPPRESSED,
- )
+ ]
);
}
@@ -801,11 +785,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-post-action-suppress-post' ),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'moderate-post',
'topic_postId' => $postId->getAlphadecimal(),
'topic_moderationState' => AbstractRevision::MODERATED_SUPPRESSED,
- )
+ ]
);
}
@@ -814,9 +798,9 @@ class UrlGenerator {
wfMessage( 'flow-newtopic-start-placeholder' ),
// resolveTitle doesn't accept null uuid
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'new-topic'
- )
+ ]
);
}
@@ -830,7 +814,7 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-thank-link', $sender, $recipient )->text(),
SpecialPage::getTitleFor( 'Thanks', 'Flow/' . $postId->getAlphadecimal() ),
- array(),
+ [],
null,
wfMessage( 'flow-thank-link-title', $sender, $recipient )->text()
);
@@ -851,11 +835,11 @@ class UrlGenerator {
return new Anchor(
wfMessage( 'flow-mark-revision-patrolled-link-text' )->text(),
$this->resolveTitle( $title, $workflowId ),
- array(
+ [
'action' => 'markpatrolled',
'rcid' => $rc->getAttribute( 'rc_id' ),
- 'token' => $token
- )
+ 'token' => $token,
+ ]
);
}
}
diff --git a/Flow/includes/Utils/NamespaceIterator.php b/Flow/includes/Utils/NamespaceIterator.php
index a52a3564..012c3e44 100644
--- a/Flow/includes/Utils/NamespaceIterator.php
+++ b/Flow/includes/Utils/NamespaceIterator.php
@@ -3,7 +3,7 @@
namespace Flow\Utils;
use DatabaseBase;
-use EchoBatchRowIterator;
+use BatchRowIterator;
use EchoCallbackIterator;
use Iterator;
use IteratorAggregate;
@@ -38,20 +38,20 @@ class NamespaceIterator implements IteratorAggregate {
* @return Iterator<Title>
*/
public function getIterator() {
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
$this->db,
- /* tables */ array( 'page' ),
+ /* tables */ [ 'page' ],
/* pk */ 'page_id',
/* rows per batch */ 500
);
- $it->addConditions( array(
+ $it->addConditions( [
'page_namespace' => $this->namespace,
- ) );
- $it->setFetchColumns( array( 'page_title' ) );
+ ] );
+ $it->setFetchColumns( [ 'page_title' ] );
$it = new RecursiveIteratorIterator( $it );
$namespace = $this->namespace;
- return new EchoCallbackIterator( $it, function( $row ) use ( $namespace ) {
+ return new EchoCallbackIterator( $it, function ( $row ) use ( $namespace ) {
return Title::makeTitle( $namespace, $row->page_title );
} );
}
diff --git a/Flow/includes/Utils/PagesWithPropertyIterator.php b/Flow/includes/Utils/PagesWithPropertyIterator.php
index c6cc33ba..615c70e9 100644
--- a/Flow/includes/Utils/PagesWithPropertyIterator.php
+++ b/Flow/includes/Utils/PagesWithPropertyIterator.php
@@ -3,7 +3,7 @@
namespace Flow\Utils;
use DatabaseBase;
-use EchoBatchRowIterator;
+use BatchRowIterator;
use EchoCallbackIterator;
use IteratorAggregate;
use RecursiveIteratorIterator;
@@ -51,17 +51,17 @@ class PagesWithPropertyIterator implements IteratorAggregate {
}
/**
- * @return Iterator<Title>
+ * @return \Iterator<Title>
*/
public function getIterator() {
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
$this->db,
- /* tables */ array( 'page_props', 'page' ),
+ /* tables */ [ 'page_props', 'page' ],
/* pk */ 'pp_page',
/* rows per batch */ 500
);
- $conditions = array( 'pp_propname' => $this->propName );
+ $conditions = [ 'pp_propname' => $this->propName ];
if ( $this->startId !== null ) {
$conditions[] = 'pp_page >= ' . $this->db->addQuotes( $this->startId );
}
@@ -70,13 +70,13 @@ class PagesWithPropertyIterator implements IteratorAggregate {
}
$it->addConditions( $conditions );
- $it->addJoinConditions( array(
- 'page' => array( 'JOIN', 'pp_page=page_id' ),
- ) );
- $it->setFetchColumns( array( 'page_namespace', 'page_title' ) );
+ $it->addJoinConditions( [
+ 'page' => [ 'JOIN', 'pp_page=page_id' ],
+ ] );
+ $it->setFetchColumns( [ 'page_namespace', 'page_title' ] );
$it = new RecursiveIteratorIterator( $it );
- return new EchoCallbackIterator( $it, function( $row ) {
+ return new EchoCallbackIterator( $it, function ( $row ) {
return Title::makeTitle( $row->page_namespace, $row->page_title );
} );
}
diff --git a/Flow/includes/View.php b/Flow/includes/View.php
index a0eb9c59..e2b8d626 100644
--- a/Flow/includes/View.php
+++ b/Flow/includes/View.php
@@ -6,15 +6,14 @@ use ContextSource;
use Flow\Block\AbstractBlock;
use Flow\Exception\InvalidActionException;
use Flow\Model\Anchor;
+use Flow\Model\HtmlRenderingInformation;
use Flow\Model\UUID;
use Flow\Model\Workflow;
-use FormatJson;
use Html;
use Hooks;
use IContextSource;
use Message;
use OutputPage;
-use ResourceLoader;
use Title;
use WebRequest;
@@ -77,7 +76,6 @@ class View extends ContextSource {
$block->setPageTitle( $output );
}
-
$this->renderApiResponse( $apiResponse );
}
@@ -85,46 +83,42 @@ class View extends ContextSource {
if ( $this->actions->hasValue( $action, 'modules' ) ) {
$out->addModules( $this->actions->getValue( $action, 'modules' ) );
} else {
- $out->addModules( array( 'ext.flow' ) );
+ $out->addModules( [ 'ext.flow' ] );
}
if ( $this->actions->hasValue( $action, 'moduleStyles' ) ) {
$out->addModuleStyles( $this->actions->getValue( $action, 'moduleStyles' ) );
} else {
- $out->addModuleStyles( array(
+ $out->addModuleStyles( [
'mediawiki.ui',
'mediawiki.ui.anchor',
'mediawiki.ui.button',
'mediawiki.ui.input',
'mediawiki.ui.icon',
'mediawiki.ui.text',
+ 'mediawiki.special.changeslist',
'ext.flow.styles.base' ,
- 'ext.flow.mediawiki.ui.tooltips',
'ext.flow.mediawiki.ui.form',
- 'ext.flow.mediawiki.ui.modal',
'ext.flow.mediawiki.ui.text',
- 'oojs-ui.styles.icons',
- 'oojs-ui.styles.icons-layout',
- 'oojs-ui.styles.icons-interactions',
'ext.flow.board.styles',
'ext.flow.board.topic.styles',
- 'oojs-ui.styles.icons',
'oojs-ui.styles.icons-alerts',
'oojs-ui.styles.icons-content',
'oojs-ui.styles.icons-layout',
'oojs-ui.styles.icons-movement',
'oojs-ui.styles.icons-indicators',
+ 'oojs-ui.styles.icons-interactions',
'oojs-ui.styles.icons-editing-core',
'oojs-ui.styles.icons-moderation',
// Needed for pending texture while switching editors
'oojs-ui.styles.textures'
- ) );
+ ] );
}
// Add Parsoid modules if necessary
- Parsoid\Utils::onFlowAddModules( $out );
+ Conversion\Utils::onFlowAddModules( $out );
// Allow other extensions to add modules
- Hooks::run( 'FlowAddModules', array( $out ) );
+ Hooks::run( 'FlowAddModules', [ $out ] );
}
protected function handleSubmit( WorkflowLoader $loader, $action, array $parameters ) {
@@ -151,23 +145,41 @@ class View extends ContextSource {
$workflow = $loader->getWorkflow();
$title = $workflow->getArticleTitle();
$user = $this->getUser();
+ $categories = array_keys( $title->getParentCategories() );
+ $categoryObject = [];
+ $linkedCategories = [];
+
+ // Transform the raw category names into links
+ foreach ( $categories as $value ) {
+ $categoryTitle = Title::newFromText( $value );
+ $categoryObject[ $value ] = [
+ 'name' => $value,
+ 'exists' => $categoryTitle->exists()
+ ];
+ $linkedCategories[] = \Linker::link( $categoryTitle, htmlspecialchars( $categoryTitle->getText() ) );
+ }
// @todo This and API should use same code
- $apiResponse = array(
+ $apiResponse = [
'title' => $title->getPrefixedText(),
+ 'categories' => $categoryObject,
+ // We need to store the link to the Special:Categories page from the
+ // back end php script, because there is no way in JS front end to
+ // get the localized link of a special page
+ 'specialCategoryLink' => \SpecialPage::getTitleFor( 'Categories' )->getLocalURL(),
'workflow' => $workflow->isNew() ? '' : $workflow->getId()->getAlphadecimal(),
- 'blocks' => array(),
+ 'blocks' => [],
'isWatched' => $user->isWatched( $title ),
'watchable' => !$user->isAnon(),
- 'links' => array(
- 'watch-board' => array(
+ 'links' => [
+ 'watch-board' => [
'url' => $title->getLocalUrl( 'action=watch' ),
- ),
- 'unwatch-board' => array(
+ ],
+ 'unwatch-board' => [
'url' => $title->getLocalUrl( 'action=unwatch' ),
- ),
- )
- );
+ ],
+ ]
+ ];
$editToken = $user->getEditToken();
$wasPosted = $this->getRequest()->wasPosted();
@@ -175,17 +187,28 @@ class View extends ContextSource {
foreach ( $blocks as $block ) {
if ( $wasPosted ? $block->canSubmit( $action ) : $block->canRender( $action ) ) {
$apiResponse['blocks'][$block->getName()] = $block->renderApi( $parameters[$block->getName()] )
- + array(
+ + [
'title' => $apiResponse['title'],
'block-action-template' => $block->getTemplate( $action ),
'editToken' => $editToken,
- );
+ ];
if ( $block->getName() == 'topiclist' ) {
$topicListBlock = $block;
}
}
}
+ // Add category items to the header if they exist
+ if ( count( $linkedCategories ) > 0 && isset( $apiResponse['blocks']['header'] ) ) {
+ $apiResponse['blocks']['header']['categories'] = [
+ 'link' => \Linker::link(
+ \SpecialPage::getTitleFor( 'Categories' ),
+ wfMessage( 'pagecategories' )->params( count( $linkedCategories ) )->text()
+ ) . wfMessage( 'colon-separator' )->text(),
+ 'items' => $linkedCategories
+ ];
+ }
+
if ( isset( $topicListBlock ) && isset( $parameters['topiclist'] ) ) {
$apiResponse['toc'] = $topicListBlock->renderTocApi(
$apiResponse['blocks']['topiclist'],
@@ -194,10 +217,10 @@ class View extends ContextSource {
}
if ( count( $apiResponse['blocks'] ) === 0 ) {
- throw new InvalidActionException( "No blocks accepted action: $action" );
+ throw new InvalidActionException( "No blocks accepted action: $action", 'invalid-action' );
}
- array_walk_recursive( $apiResponse, function( &$value ) {
+ array_walk_recursive( $apiResponse, function ( &$value ) {
if ( $value instanceof Anchor ) {
$anchor = $value;
$value = $value->toArray();
@@ -221,7 +244,7 @@ class View extends ContextSource {
protected function renderApiResponse( array $apiResponse ) {
// Render the flow-component wrapper
if ( empty( $apiResponse['blocks'] ) ) {
- return array();
+ return [];
}
$out = $this->getOutput();
@@ -238,7 +261,7 @@ class View extends ContextSource {
// Add JSON blob for OOUI widgets
$out->addJsConfigVars( 'wgFlowData', $jsonBlobResponse );
- $renderedBlocks = array();
+ $renderedBlocks = [];
foreach ( $apiResponse['blocks'] as $block ) {
// @todo find a better way to do this; potentially make all blocks their own components
switch ( $block['type'] ) {
@@ -260,6 +283,20 @@ class View extends ContextSource {
$page = 'board';
}
+ if ( isset( $block['errors'] ) ) {
+ foreach ( $block['errors'] as $error ) {
+ if ( isset( $error['extra']['details'] ) &&
+ $error['extra']['details'] instanceof HtmlRenderingInformation
+ ) {
+ $renderingInfo = $error['extra']['details'];
+
+ $out->addHeadItems( $renderingInfo->getHeadItems() );
+ $out->addModuleStyles( $renderingInfo->getModuleStyles() );
+ $out->addModules( $renderingInfo->getModules() );
+ }
+ }
+ }
+
// Don't re-render a block type twice in one page
if ( isset( $renderedBlocks[$flowComponent] ) ) {
continue;
@@ -269,20 +306,23 @@ class View extends ContextSource {
// Get the block loop template
$template = $this->lightncandy->getTemplate( 'flow_block_loop' );
- $classes = array( 'flow-component', "$page-page" );
- // Add mw-content-{ltr,rtl} text if necessary (MW core doesn't add it for non-view actions
- if ( \Action::getActionName( $this ) !== 'view' ) {
- $title = Title::newFromText( $apiResponse['title'] );
- $classes[] = 'mw-content-' . $title->getPageViewLanguage()->getDir();
- }
+ $classes = [ 'flow-component', "flow-$page-page" ];
+
+ // Always add mw-content-{ltr,rtl} class
+ $title = Title::newFromText( $apiResponse['title'] );
+ $classes[] = 'mw-content-' . $title->getPageViewLanguage()->getDir();
+
+ $action = $this->getRequest()->getVal( 'action', 'view' );
+ $classes[] = "flow-action-$action";
+
// Output the component, with the rendered blocks inside it
$out->addHTML( Html::rawElement(
'div',
- array(
+ [
'class' => implode( ' ', $classes ),
'data-flow-component' => $flowComponent,
'data-flow-id' => $apiResponse['workflow'],
- ),
+ ],
$template( $apiResponse )
) );
}
@@ -300,23 +340,22 @@ class View extends ContextSource {
* Helper function extracts parameters from a WebRequest.
*
* @param string $action
- * @param WebRequest $request
* @param AbstractBlock[] $blocks
* @return array
*/
public function extractBlockParameters( $action, array $blocks ) {
$request = $this->getRequest();
- $result = array();
+ $result = [];
// BC for old parameters enclosed in square brackets
foreach ( $blocks as $block ) {
$name = $block->getName();
- $result[$name] = $request->getArray( $name, array() );
+ $result[$name] = $request->getArray( $name, [] );
}
// BC for topic_list renamed to topiclist
if ( isset( $result['topiclist'] ) && !$result['topiclist'] ) {
- $result['topiclist'] = $request->getArray( 'topic_list', array() );
+ $result['topiclist'] = $request->getArray( 'topic_list', [] );
}
- $globalData = array( 'action' => $action );
+ $globalData = [ 'action' => $action ];
foreach ( $request->getValues() as $name => $value ) {
// between urls only allowing [-_.] as unencoded special chars and
// php mangling all of those into '_', we have to split on '_'
diff --git a/Flow/includes/WatchedTopicItems.php b/Flow/includes/WatchedTopicItems.php
index f57c4c6c..8860a9e5 100644
--- a/Flow/includes/WatchedTopicItems.php
+++ b/Flow/includes/WatchedTopicItems.php
@@ -14,7 +14,7 @@ class WatchedTopicItems {
protected $user;
protected $watchListDb;
- protected $overrides = array();
+ protected $overrides = [];
public function __construct( User $user, DatabaseBase $watchListDb ) {
$this->user = $user;
@@ -31,7 +31,7 @@ class WatchedTopicItems {
}
/**
- * @param string[] array of UUID string
+ * @param string[] $titles Array of UUID strings
* @return array
* @throws Exception\DataModelException
*/
@@ -43,7 +43,7 @@ class WatchedTopicItems {
return $result;
}
- $queryTitles = array();
+ $queryTitles = [];
foreach ( $titles as $id ) {
$obj = Title::makeTitleSafe( NS_TOPIC, $id );
if ( $obj ) {
@@ -61,13 +61,13 @@ class WatchedTopicItems {
}
$res = $this->watchListDb->select(
- array( 'watchlist' ),
- array( 'wl_title' ),
- array(
+ [ 'watchlist' ],
+ [ 'wl_title' ],
+ [
'wl_user' => $this->user->getId(),
'wl_namespace' => NS_TOPIC,
'wl_title' => $queryTitles
- ),
+ ],
__METHOD__
);
if ( !$res ) {
diff --git a/Flow/includes/WorkflowLoaderFactory.php b/Flow/includes/WorkflowLoaderFactory.php
index 126dcce2..59f9f8f1 100644
--- a/Flow/includes/WorkflowLoaderFactory.php
+++ b/Flow/includes/WorkflowLoaderFactory.php
@@ -7,7 +7,9 @@ use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\Data\ManagerGroup;
use Flow\Exception\CrossWikiException;
+use Flow\Exception\InvalidDataException;
use Flow\Exception\InvalidInputException;
+use Flow\Exception\InvalidParameterException;
use Flow\Exception\InvalidTopicUuidException;
use Flow\Exception\UnknownWorkflowIdException;
use Title;
@@ -29,11 +31,6 @@ class WorkflowLoaderFactory {
protected $submissionHandler;
/**
- * @var string
- */
- protected $defaultWorkflowName;
-
- /**
* @var bool
*/
protected $pageMoveInProgress = false;
@@ -42,18 +39,15 @@ class WorkflowLoaderFactory {
* @param ManagerGroup $storage
* @param BlockFactory $blockFactory
* @param SubmissionHandler $submissionHandler
- * @param string $defaultWorkflowName
*/
function __construct(
ManagerGroup $storage,
BlockFactory $blockFactory,
- SubmissionHandler $submissionHandler,
- $defaultWorkflowName
+ SubmissionHandler $submissionHandler
) {
$this->storage = $storage;
$this->blockFactory = $blockFactory;
$this->submissionHandler = $submissionHandler;
- $this->defaultWorkflowName = $defaultWorkflowName;
}
public function pageMoveInProgress() {
@@ -68,12 +62,12 @@ class WorkflowLoaderFactory {
* @throws CrossWikiException
*/
public function createWorkflowLoader( Title $pageTitle, $workflowId = null ) {
- if ( $pageTitle === null ) {
- throw new InvalidInputException( 'Invalid article requested', 'invalid-title' );
+ if ( $pageTitle->isExternal() ) {
+ throw new CrossWikiException( 'Interwiki to ' . $pageTitle->getInterwiki() . ' not implemented ', 'default' );
}
- if ( $pageTitle && $pageTitle->isExternal() ) {
- throw new CrossWikiException( 'Interwiki to ' . $pageTitle->getInterwiki() . ' not implemented ', 'default' );
+ if ( $pageTitle->getNamespace() < 0 ) {
+ throw new InvalidDataException( 'Can not load workflow for special (< 0) namespace', 'invalid-title' );
}
// @todo: ideally, workflowId is always set and this stuff is done in the places that call this
@@ -104,7 +98,7 @@ class WorkflowLoaderFactory {
$title->resetArticleID( 0 );
// no existing workflow found, create new one
- $workflow = Workflow::create( $this->defaultWorkflowName, $title );
+ $workflow = Workflow::create( 'discussion', $title );
} else {
$workflow = $this->loadWorkflowById( $pageTitle, $workflowId );
}
@@ -120,16 +114,20 @@ class WorkflowLoaderFactory {
* @param Title|false $title
* @param UUID $workflowId
* @return Workflow
- * @throws InvalidInputException
+ * @throws InvalidDataException
+ * @throws UnknownWorkflowIdException
*/
- protected function loadWorkflowById( /* Title or false */ $title, $workflowId ) {
+ public function loadWorkflowById( /* Title or false */ $title, $workflowId ) {
/** @var Workflow $workflow */
$workflow = $this->storage->getStorage( 'Workflow' )->get( $workflowId );
if ( !$workflow ) {
throw new UnknownWorkflowIdException( 'Invalid workflow requested by id', 'invalid-input' );
}
+ if ( $workflow->getWiki() !== wfWikiID() ) {
+ throw new UnknownWorkflowIdException( 'The requested workflow does not exist on this wiki.' );
+ }
if ( $title !== false && $this->pageMoveInProgress === false && !$workflow->matchesTitle( $title ) ) {
- throw new InvalidInputException( 'Flow workflow is for different page', 'invalid-input' );
+ throw new InvalidDataException( 'Flow workflow is for different page', 'different-page' );
}
return $workflow;
@@ -149,14 +147,14 @@ class WorkflowLoaderFactory {
/**
* Create a UUID for a ns/dbkey title pair
*
- * @param integer $ns
+ * @param int $ns
* @param string $dbKey
* @return UUID
* @throws InvalidInputException When the pair does not represent a valid uuid
*/
public static function uuidFromTitlePair( $ns, $dbKey ) {
if ( $ns !== NS_TOPIC ) {
- throw new InvalidInputException( "Title is not from NS_TOPIC: $ns", 'invalid-input' );
+ throw new InvalidParameterException( "Title is not from NS_TOPIC: $ns" );
}
try {
diff --git a/Flow/jsduck.external.js b/Flow/jsduck.external.js
index e1697b61..86428bbd 100644
--- a/Flow/jsduck.external.js
+++ b/Flow/jsduck.external.js
@@ -1,48 +1,58 @@
/**
+ * Source: <https://api.jquery.com/>
* @class jQuery
- * <http://api.jquery.com/>
*/
/**
+ * Source: <https://api.jquery.com/jQuery.ajax/>
* @method ajax
- * @source <http://api.jquery.com/jQuery.ajax/>
+ * @static
* @return {jqXHR}
*/
/**
+ * Source: <https://api.jquery.com/Types/#Event>
* @class jQuery.Event
- * @source <http://api.jquery.com/Types/#Event>
*/
/**
+ * Source: <https://api.jquery.com/Types/#Promise>
* @class jQuery.Promise
- * @source <http://api.jquery.com/Types/#Promise>
*/
/**
+ * Source: <https://api.jquery.com/jQuery.Deferred/>
* @class jQuery.Deferred
* @mixins jQuery.Promise
- * @source <http://api.jquery.com/jQuery.Deferred/>
*/
/**
+ * Source: <https://api.jquery.com/Types/#jqXHR>
* @class jQuery.jqXHR
- * @source <http://api.jquery.com/Types/#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
- * @source <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Title>
*/
/**
+ * Source: <http://handlebarsjs.com/reference.html>
* @class Handlebars
- * <http://handlebarsjs.com/reference.html>
*/
/**
+ * Source: <http://handlebarsjs.com/reference.html#base-SafeString>
* @class Handlebars.SafeString
- * <http://handlebarsjs.com/reference.html#base-SafeString>
*/
-
diff --git a/Flow/jsduck.json b/Flow/jsduck.json
index cd197195..bb290fe9 100644
--- a/Flow/jsduck.json
+++ b/Flow/jsduck.json
@@ -2,7 +2,7 @@
"--title": "Flow - Documentation",
"--processes": "0",
"--warnings-exit-nonzero": true,
- "--external": "OO.*,ve.*,DocumentFragment,Storer",
+ "--external": "OO.*,ve.*,mw.libs.ve.*,DocumentFragment",
"--output": "docs",
"--tags": "jsduck_custom_tags.rb",
"--": [
diff --git a/Flow/jsduck_custom_tags.rb b/Flow/jsduck_custom_tags.rb
index 96b1ea6c..e6b19edf 100644
--- a/Flow/jsduck_custom_tags.rb
+++ b/Flow/jsduck_custom_tags.rb
@@ -31,23 +31,6 @@ class CommonTag < JsDuck::Tag::Tag
end
end
-class SourceTag < CommonTag
- def initialize
- @tagname = :source
- @pattern = "source"
- super
- end
-
- def to_html(context)
- context[@tagname].map do |source|
- <<-EOHTML
- <h3 class='pa'>Source</h3>
- #{source[:doc]}
- EOHTML
- end.join
- end
-end
-
class UntilTag < CommonTag
def initialize
@tagname = :until
diff --git a/Flow/maintenance/FlowAddMissingModerationLogs.php b/Flow/maintenance/FlowAddMissingModerationLogs.php
index 9236d175..a9553452 100644
--- a/Flow/maintenance/FlowAddMissingModerationLogs.php
+++ b/Flow/maintenance/FlowAddMissingModerationLogs.php
@@ -1,12 +1,12 @@
<?php
use Flow\Container;
-use Flow\Data\Listener\ModerationLoggingListener;
+use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
-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';
/**
* Adjusts edit counts for all existing Flow data.
@@ -23,6 +23,8 @@ class FlowAddMissingModerationLogs extends LoggedUpdateMaintenance {
$this->addOption( 'stop', 'rev_id of first revision that was logged correctly after moderation logging fix.', true, true );
$this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
}
protected function getUpdateKey() {
@@ -33,45 +35,46 @@ class FlowAddMissingModerationLogs extends LoggedUpdateMaintenance {
$container = Container::getContainer();
$dbFactory = $container['db.factory'];
+ /** @var IDatabase $dbw */
$dbw = $dbFactory->getDb( DB_MASTER );
$storage = $container['storage'];
$moderationLoggingListener = $container['storage.post.listeners.moderation_logging'];
- $rowIterator = new EchoBatchRowIterator(
+ $rowIterator = new BatchRowIterator(
$dbw,
/* table = */'flow_revision',
/* primary key = */'rev_id',
$this->mBatchSize
);
- $rowIterator->setFetchColumns( array(
+ $rowIterator->setFetchColumns( [
'rev_id',
'rev_type',
- ) );
+ ] );
// Fetch rows that are a moderation action
- $rowIterator->addConditions( array(
- 'rev_change_type' => ModerationLoggingListener::getModerationChangeTypes(),
+ $rowIterator->addConditions( [
+ 'rev_change_type' => AbstractRevision::getModerationChangeTypes(),
'rev_user_wiki' => wfWikiID(),
- ) );
+ ] );
$start = $this->getOption( 'start' );
$startId = UUID::create( $start );
- $rowIterator->addConditions( array(
+ $rowIterator->addConditions( [
'rev_id > ' . $dbw->addQuotes( $startId->getBinary() ),
- ) );
+ ] );
$stop = $this->getOption( 'stop' );
$stopId = UUID::create( $stop );
- $rowIterator->addConditions( array(
+ $rowIterator->addConditions( [
'rev_id < ' . $dbw->addQuotes( $stopId->getBinary() ),
- ) );
+ ] );
$total = $fail = 0;
foreach ( $rowIterator as $batch ) {
- $dbw->begin();
+ $this->beginTransaction( $dbw, __METHOD__ );
foreach ( $batch as $row ) {
$total++;
$objectManager = $storage->getStorage( $row->rev_type );
@@ -84,12 +87,12 @@ class FlowAddMissingModerationLogs extends LoggedUpdateMaintenance {
}
$workflow = $obj->getCollection()->getWorkflow();
- $moderationLoggingListener->onAfterInsert( $obj, array(), array(
+ $moderationLoggingListener->onAfterInsert( $obj, [], [
'workflow' => $workflow,
- ) );
+ ] );
}
- $dbw->commit();
+ $this->commitTransaction( $dbw, __METHOD__ );
$storage->clear();
$dbFactory->waitForSlaves();
}
@@ -104,4 +107,4 @@ class FlowAddMissingModerationLogs extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowAddMissingModerationLogs';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowCreateTemplates.php b/Flow/maintenance/FlowCreateTemplates.php
index 817cd7be..3c723407 100644
--- a/Flow/maintenance/FlowCreateTemplates.php
+++ b/Flow/maintenance/FlowCreateTemplates.php
@@ -1,8 +1,8 @@
<?php
-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';
/**
* The templates will be created with a default content, but can be customized.
@@ -22,9 +22,9 @@ class FlowCreateTemplates extends LoggedUpdateMaintenance {
* @return array [title i18n key => content callback]
*/
protected function getTemplates() {
- return array(
+ return [
// Template:FlowMention, used to render mentions in Flow's Visual Editor
- 'flow-ve-mention-template-title' => function( Title $title ) {
+ 'flow-ve-mention-template-title' => function ( Title $title ) {
// get "User:" namespace prefix in wiki language
global $wgContLang;
$namespaces = $wgContLang->getFormattedNamespaces();
@@ -32,35 +32,37 @@ class FlowCreateTemplates extends LoggedUpdateMaintenance {
return '@[[' . $namespaces[NS_USER] . ':{{{1|Example}}}|{{{2|{{{1|Example}}}}}}]]';
},
// LiquidThread import templates
- 'flow-importer-lqt-moved-thread-template' => function( Title $title ) {
+ 'flow-importer-lqt-moved-thread-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-lqt-moved-thread-template-content' )->inContentLanguage()->plain();
},
- 'flow-importer-lqt-converted-template' => function( Title $title ) {
+ 'flow-importer-lqt-converted-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-lqt-converted-template-content' )->inContentLanguage()->plain();
},
- 'flow-importer-lqt-converted-archive-template' => function( Title $title ) {
+ 'flow-importer-lqt-converted-archive-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-lqt-converted-archive-template-content' )->inContentLanguage()->plain();
},
- 'flow-importer-lqt-suppressed-user-template' => function( Title $title ) {
+ 'flow-importer-lqt-suppressed-user-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-lqt-suppressed-user-template-content' )->inContentLanguage()->plain();
},
- 'flow-importer-lqt-different-author-signature-template' => function( Title $title ) {
+ 'flow-importer-lqt-different-author-signature-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-lqt-different-author-signature-template-content' )->inContentLanguage()->plain();
},
// Wikitext import templates
- 'flow-importer-wt-converted-template' => function( Title $title ) {
+ 'flow-importer-wt-converted-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-wt-converted-template-content' )->inContentLanguage()->plain();
},
- 'flow-importer-wt-converted-archive-template' => function( Title $title ) {
+ 'flow-importer-wt-converted-archive-template' => function ( Title $title ) {
return wfMessage( 'flow-importer-wt-converted-archive-template-content' )->inContentLanguage()->plain();
},
- );
+ ];
}
public function __construct() {
parent::__construct();
$this->mDescription = "Creates templates required by Flow";
+
+ $this->requireExtension( 'Flow' );
}
protected function getUpdateKey() {
@@ -115,4 +117,4 @@ class FlowCreateTemplates extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowCreateTemplates';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowExternalStoreMoveCluster.php b/Flow/maintenance/FlowExternalStoreMoveCluster.php
new file mode 100644
index 00000000..fe3389c1
--- /dev/null
+++ b/Flow/maintenance/FlowExternalStoreMoveCluster.php
@@ -0,0 +1,288 @@
+<?php
+
+use Flow\Container;
+use Flow\Model\UUID;
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
+require_once "$IP/maintenance/Maintenance.php";
+require_once "$IP/includes/utils/RowUpdateGenerator.php";
+
+/**
+ * @ingroup Maintenance
+ */
+abstract class ExternalStoreMoveCluster extends Maintenance {
+ /**
+ * Must return an array in the form:
+ * array(
+ * 'dbr' => DatabaseBase object,
+ * 'dbw' => DatabaseBase object,
+ * 'table' => 'flow_revision',
+ * 'pk' => 'rev_id',
+ * 'content' => 'rev_content',
+ * 'flags' => 'rev_flags',
+ * )
+ *
+ * It will roughly translate into these queries, where PK is the
+ * unique key to control batching & updates, content & flags are
+ * the columns to read from & update with new ES data.
+ * It will roughly translate into these queries:
+ *
+ * Against dbr: ('cluster' will be the argument passed to --from)
+ * SELECT <pk>, <content>, <flags>
+ * FROM <table>
+ * WHERE <flags> LIKE "%external%"
+ * AND <content> LIKE "DB://cluster/%";
+ *
+ * Against dbw:
+ * UPDATE <table>
+ * SET <content> = ..., <flags> = ...
+ * WHERE <pk> = ...;
+ *
+ * @return array
+ */
+ abstract protected function schema();
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Moves ExternalStore content from (a) particular cluster(s) to (an)other(s). Just make sure all clusters are valid $wgExternalServers.';
+
+ $this->addOption( 'from', 'ExternalStore cluster to move from (comma-separated). E.g.: --from=cluster24,cluster25', true, true );
+ $this->addOption( 'to', 'ExternalStore cluster to move to (comma-separated). E.g.: --to=cluster26', true, true );
+ $this->addOption( 'dry-run', 'Outputs the old user content, inserts into new External Store, gives hypothetical new column values for flow_revision (but does not actually change flow_revision), and checks that old and new ES are the same.' );
+
+ $this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
+ }
+
+ public function execute() {
+ $from = explode( ',', $this->getOption( 'from' ) );
+ $to = explode( ',', $this->getOption( 'to' ) );
+
+ $schema = $this->schema();
+ /** @var DatabaseBase $dbr */
+ $dbr = $schema['dbr'];
+ /** @var DatabaseBase $dbw */
+ $dbw = $schema['dbw'];
+
+ $iterator = new BatchRowIterator( $dbr, $schema['table'], $schema['pk'], $this->mBatchSize );
+ $iterator->setFetchColumns( [ $schema['content'], $schema['flags'] ] );
+
+ $clusterConditions = [];
+ foreach ( $from as $cluster ) {
+ $clusterConditions[] = $schema['content'] . $dbr->buildLike( "DB://$cluster/", $dbr->anyString() );
+ }
+ $iterator->addConditions( [
+ $schema['wiki'] => wfWikiID(),
+ $schema['flags'] . $dbr->buildLike( $dbr->anyString(), 'external', $dbr->anyString() ),
+ $dbr->makeList( $clusterConditions, LIST_OR ),
+ ] );
+
+ $updateGenerator = new ExternalStoreUpdateGenerator( $this, $to, $schema );
+
+ if ( $this->hasOption( 'dry-run' ) ) {
+ $this->output( "Starting dry run\n\n" );
+ foreach ( $iterator as $rows ) {
+ $this->output( "Starting dry run batch\n" );
+ foreach ( $rows as $row ) {
+ $url = $row->{$schema['content']};
+ $flags = explode( ',', $row->{$schema['flags']} );
+
+ $oldContent = $updateGenerator->read( $url, $flags );
+ $this->output( "\nOld content: $oldContent\n" );
+
+ // Update itself just generates the update, it doesn't write
+ // to flow_revision.
+ $updatedColumns = $updateGenerator->update( $row );
+ $this->output( "flow_revision columns would become:\n" );
+ $this->output( var_export( $updatedColumns, true ) . "\n" );
+
+ $newContent = $updatedColumns[$schema['content']];
+ $newFlags = explode( ',', $updatedColumns[$schema['flags']] );
+ if ( in_array( 'external', $newFlags, true ) ) {
+ $newContent = $updateGenerator->read( $newContent, $newFlags );
+ }
+
+ if ( $newContent === $oldContent ) {
+ $this->output( "New external store content matches old external store content\n" );
+ } else {
+ $revIdStr = UUID::create( $row->rev_id )->getAlphadecimal();
+ $this->error( "New content for ID $revIdStr does not match prior content.\nNew content: $newContent\nOld content: $oldContent\n\nTerminating dry run.\n", 1 );
+ }
+ }
+
+ $this->output( "\n\n" );
+ }
+ $this->output( "Dry run completed\n" );
+ return;
+ }
+
+ $updater = new BatchRowUpdate(
+ $iterator,
+ new BatchRowWriter( $dbw, $schema['table'] ),
+ $updateGenerator
+ );
+ $updater->setOutput( [ $this, 'output' ] );
+ $updater->execute();
+ }
+
+ /**
+ * 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.
+ *
+ * @param string $out
+ * @param mixed $channel
+ */
+ public function output( $out, $channel = null ) {
+ parent::output( $out, $channel );
+ }
+
+ /**
+ * parent::error() is a protected method, only way to access it from the
+ * outside is to make it public.
+ *
+ * @param string $err
+ * @param int $die
+ */
+ public function error( $err, $die = 0 ) {
+ parent::error( $err, $die );
+ }
+}
+
+class ExternalStoreUpdateGenerator implements RowUpdateGenerator {
+ /**
+ * @var ExternalStoreMoveCluster
+ */
+ protected $script;
+
+ /**
+ * @var array
+ */
+ protected $stores = [];
+
+ /**
+ * @var array
+ */
+ protected $schema = [];
+
+ /**
+ * @param ExternalStoreMoveCluster $script
+ * @param array $stores
+ * @param array $schema
+ */
+ public function __construct( ExternalStoreMoveCluster $script, array $stores, array $schema ) {
+ $this->script = $script;
+ $this->stores = $stores;
+ $this->schema = $schema;
+ }
+
+ /**
+ * @param stdClass $row
+ * @return array
+ */
+ public function update( $row ) {
+ $url = $row->{$this->schema['content']};
+ $flags = explode( ',', $row->{$this->schema['flags']} );
+
+ try {
+ $content = $this->read( $url, $flags );
+ $data = $this->write( $content, $flags );
+ } catch ( \Exception $e ) {
+ // something went wrong, just output the error & don't update!
+ $this->script->error( $e->getMessage(). "\n" );
+ return [];
+ }
+
+ return [
+ $this->schema['content'] => $data['content'],
+ $this->schema['flags'] => implode( ',', $data['flags'] ),
+ ];
+ }
+
+ /**
+ * @param string $url
+ * @param array $flags
+ * @return string
+ * @throws MWException
+ */
+ public function read( $url, array $flags = [] ) {
+ $content = ExternalStore::fetchFromURL( $url );
+ if ( $content === false ) {
+ throw new MWException( "Failed to fetch content from URL: $url" );
+ }
+
+ $content = \Revision::decompressRevisionText( $content, $flags );
+ if ( $content === false ) {
+ throw new MWException( "Failed to decompress content from URL: $url" );
+ }
+
+ return $content;
+ }
+
+ /**
+ * @param string $content
+ * @param array $flags
+ * @return array New ExternalStore data in the form of ['content' => ..., 'flags' => array( ... )]
+ * @throws MWException
+ */
+ protected function write( $content, array $flags = [] ) {
+ // external, utf-8 & gzip flags are no longer valid at this point
+ $oldFlags = array_diff( $flags, [ 'external', 'utf-8', 'gzip' ] );
+
+ if ( $content === '' ) {
+ // don't store empty content elsewhere
+ return [
+ 'content' => $content,
+ 'flags' => $oldFlags,
+ ];
+ }
+
+ // re-compress (if $wgCompressRevisions is enabled) the content & set flags accordingly
+ $flags = array_filter( explode( ',', \Revision::compressRevisionText( $content ) ) );
+
+ // ExternalStore::insertWithFallback expects stores with protocol
+ $stores = [];
+ foreach ( $this->stores as $store ) {
+ $stores[] = 'DB://' . $store;
+ }
+ $url = ExternalStore::insertWithFallback( $stores, $content );
+ if ( $url === false ) {
+ throw new MWException( 'Failed to write content to stores ' . json_encode( $stores ) );
+ }
+
+ // add flag indicating content is external again, and restore unrelated flags
+ $flags[] = 'external';
+ $flags = array_merge( $flags, $oldFlags );
+
+ return [
+ 'content' => $url,
+ 'flags' => array_unique( $flags ),
+ ];
+ }
+}
+
+class FlowExternalStoreMoveCluster extends ExternalStoreMoveCluster {
+ protected function schema() {
+ $container = Container::getContainer();
+ $dbFactory = $container['db.factory'];
+
+ return [
+ 'dbr' => $dbFactory->getDb( DB_SLAVE ),
+ 'dbw' => $dbFactory->getDb( DB_MASTER ),
+ 'table' => 'flow_revision',
+ 'pk' => 'rev_id',
+ 'content' => 'rev_content',
+ 'flags' => 'rev_flags',
+ 'wiki' => 'rev_user_wiki',
+ ];
+ }
+}
+
+$maintClass = 'FlowExternalStoreMoveCluster';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixEditCount.php b/Flow/maintenance/FlowFixEditCount.php
index 224b8d60..273a3ffc 100644
--- a/Flow/maintenance/FlowFixEditCount.php
+++ b/Flow/maintenance/FlowFixEditCount.php
@@ -4,9 +4,9 @@ use Flow\Container;
use Flow\FlowActions;
use Flow\Model\UUID;
-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';
/**
* Adjusts edit counts for all existing Flow data.
@@ -19,7 +19,7 @@ class FlowFixEditCount extends LoggedUpdateMaintenance {
*
* @var array
*/
- protected $updates = array();
+ protected $updates = [];
public function __construct() {
parent::__construct();
@@ -30,6 +30,8 @@ class FlowFixEditCount extends LoggedUpdateMaintenance {
$this->addOption( 'stop', 'Timestamp to stop counting revisions at', false, true );
$this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
}
protected function getUpdateKey() {
@@ -63,19 +65,19 @@ class FlowFixEditCount extends LoggedUpdateMaintenance {
public function refreshBatch( DatabaseBase $dbr, UUID $continue, $countableActions, UUID $stop ) {
$rows = $dbr->select(
'flow_revision',
- array( 'rev_id', 'rev_user_id' ),
- array(
+ [ 'rev_id', 'rev_user_id' ],
+ [
'rev_id > ' . $dbr->addQuotes( $continue->getBinary() ),
'rev_id <= ' . $dbr->addQuotes( $stop->getBinary() ),
'rev_user_id > 0',
'rev_user_wiki' => wfWikiID(),
'rev_change_type' => $countableActions,
- ),
+ ],
__METHOD__,
- array(
+ [
'ORDER BY' => 'rev_id ASC',
'LIMIT' => $this->mBatchSize,
- )
+ ]
);
// end of data
@@ -111,7 +113,7 @@ class FlowFixEditCount extends LoggedUpdateMaintenance {
* @return array
*/
protected function getCountableActions() {
- $allowedActions = array();
+ $allowedActions = [];
/** @var FlowActions $actions */
$actions = \Flow\Container::get( 'flow_actions' );
@@ -126,4 +128,4 @@ class FlowFixEditCount extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowFixEditCount';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixInconsistentBoards.php b/Flow/maintenance/FlowFixInconsistentBoards.php
new file mode 100644
index 00000000..b53cc8e4
--- /dev/null
+++ b/Flow/maintenance/FlowFixInconsistentBoards.php
@@ -0,0 +1,184 @@
+<?php
+
+use Flow\Content\BoardContent;
+use Flow\Container;
+use Flow\Exception\UnknownWorkflowIdException;
+
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+/**
+ * Changes Flow boards and their topics to be associated with their current title, based on the JSON content
+ * Fixes inconsistent bugs like T138310.
+ *
+ * There is a dry run available.
+ *
+ * @ingroup Maintenance
+ */
+class FlowFixInconsistentBoards extends LoggedUpdateMaintenance {
+ /**
+ * @var Flow\DbFactory
+ */
+ protected $dbFactory;
+
+ /**
+ * @var Flow\WorkflowLoaderFactory
+ */
+ protected $workflowLoaderFactory;
+
+ /**
+ * @var Flow\BoardMover
+ */
+ protected $boardMover;
+
+ /**
+ * @var Flow\Data\ManagerGroup
+ */
+ protected $storage;
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Changes Flow boards and their topics to be associated with their current title, based on the JSON content. Must be run separately for each affected wiki.';
+
+ $this->addOption( 'dry-run', 'Only prints the board names, without changing anything.' );
+ $this->addOption( 'namespaceName', 'Name of namespace to check, otherwise all', false, true );
+ $this->addOption( 'limit', 'Limit of inconsistent pages to identify (and fix if not a dry run). Defaults to no limit', false, true );
+
+ $this->setBatchSize( 300 );
+ }
+
+ protected function getUpdateKey() {
+ return 'FlowFixInconsistentBoards:version1';
+ }
+
+ public function doDBUpdates() {
+ global $wgLang;
+
+ $this->dbFactory = Container::get( 'db.factory' );
+ $this->workflowLoaderFactory = Container::get( 'factory.loader.workflow' );
+ $this->boardMover = Container::get( 'board_mover' );
+ $this->storage = Container::get( 'storage' );
+
+ $dryRun = $this->hasOption( 'dry-run' );
+
+ $limit = $this->getOption( 'limit' );
+
+ $wikiDbw = $this->dbFactory->getWikiDB( DB_MASTER );
+
+ $iterator = new BatchRowIterator( $wikiDbw, 'page', 'page_id', $this->mBatchSize );
+ $iterator->setFetchColumns( [ 'page_namespace', 'page_title', 'page_latest' ] );
+ $iterator->addConditions( [
+ 'page_content_model' => CONTENT_MODEL_FLOW_BOARD,
+ ] );
+
+ if ( $this->hasOption( 'namespaceName' ) ) {
+ $namespaceName = $this->getOption( 'namespaceName' );
+ $namespaceId = $wgLang->getNsIndex( $namespaceName );
+
+ if ( !$namespaceId ) {
+ $this->error( "'$namespaceName' is not a valid namespace name" );
+ return;
+ }
+
+ if ( $namespaceId == NS_TOPIC ) {
+ $this->error( 'This script can not be run on the Flow topic namespace' );
+ return;
+ }
+
+ $iterator->addConditions( [
+ 'page_namespace' => $namespaceId,
+ ] );
+ } else {
+ $iterator->addConditions( [
+ 'page_namespace != ' . NS_TOPIC,
+ ] );
+ }
+
+ $checkedCount = 0;
+ $inconsistentCount = 0;
+
+ // Not all of $inconsistentCount are fixable by the current script.
+ $fixableInconsistentCount = 0;
+
+ foreach ( $iterator as $rows ) {
+ foreach ( $rows as $row ) {
+ $checkedCount++;
+ $coreTitle = Title::makeTitle( $row->page_namespace, $row->page_title );
+ $revision = Revision::newFromId( $row->page_latest );
+ $content = $revision->getContent( Revision::RAW );
+ if ( !$content instanceof BoardContent ) {
+ $actualClass = get_class( $content );
+ $this->error( "ERROR: '$coreTitle' content is a '$actualClass', but should be '" . BoardContent::class . "'." );
+ continue;
+ }
+ $workflowId = $content->getWorkflowId();
+ if ( is_null( $workflowId ) ) {
+ // See T153320. If the workflow exists, it could
+ // be looked up by title/page ID and the JSON could
+ // be fixed with an edit.
+ // Otherwise, the core revision has to be deleted. This
+ // script does not do either of these things.
+ $this->error( "ERROR: '$coreTitle' JSON content does not have a valid workflow ID." );
+ continue;
+ }
+
+ $workflowIdAlphadecimal = $workflowId->getAlphadecimal();
+
+ try {
+ $workflow = $this->workflowLoaderFactory->loadWorkflowById( false, $workflowId );
+ } catch ( UnknownWorkflowIdException $ex ) {
+ // This is a different error (a core page refers to
+ // a non-existent workflow), which this script can not fix.
+ $this->error( "ERROR: '$coreTitle' refers to workflow ID '$workflowIdAlphadecimal', which could not be found." );
+ continue;
+ }
+
+ if ( !$workflow->matchesTitle( $coreTitle ) ) {
+ $pageId = (int)$row->page_id;
+
+ $workflowTitle = $workflow->getOwnerTitle();
+ $this->output( "INCONSISTENT: Core title for '$workflowIdAlphadecimal' is '$coreTitle', but Flow title is '$workflowTitle'\n" );
+
+ $inconsistentCount++;
+
+ // Sanity check, or this will fail in BoardMover
+ $workflowByPageId = $this->storage->find( 'Workflow', [
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_page_id' => $pageId,
+ ] );
+
+ if ( !$workflowByPageId ) {
+ $this->error( "ERROR: '$coreTitle' has page ID '$pageId', but no workflow is linked to this page ID" );
+ continue;
+ }
+
+ if ( !$dryRun ) {
+ $this->boardMover->move( $pageId, $coreTitle );
+ $this->boardMover->commit();
+ $this->output( "FIXED: Updated '$workflowIdAlphadecimal' to match core title, '$coreTitle'\n" );
+ }
+
+ $fixableInconsistentCount++;
+
+ if ( $limit !== null && $fixableInconsistentCount >= $limit ) {
+ break;
+ }
+ }
+ }
+
+ $action = $dryRun ? 'identified as fixable' : 'fixed';
+ $this->output( "\nChecked a total of $checkedCount Flow boards. Of those, $inconsistentCount boards had an inconsistent title; $fixableInconsistentCount were $action.\n" );
+ if ( $limit !== null && $fixableInconsistentCount >= $limit ) {
+ break;
+ }
+ }
+
+ // Only mark it as completed if it's run on everything.
+ return ( !$dryRun && $limit === null && !$this->hasOption( 'namespaceName' ) );
+ }
+}
+
+$maintClass = 'FlowFixInconsistentBoards';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixLinks.php b/Flow/maintenance/FlowFixLinks.php
index 2f5542a5..956b6473 100644
--- a/Flow/maintenance/FlowFixLinks.php
+++ b/Flow/maintenance/FlowFixLinks.php
@@ -8,10 +8,10 @@ $installPath = getenv( 'MW_INSTALL_PATH' ) !== false ?
getenv( 'MW_INSTALL_PATH' ) :
__DIR__ . '/../../..';
-require_once( $installPath . '/maintenance/Maintenance.php' );
+require_once $installPath . '/maintenance/Maintenance.php';
// extending these - autoloader not yet wired up at the point these are interpreted
-require_once( $installPath .'/includes/utils/BatchRowWriter.php' );
-require_once( $installPath . '/includes/utils/RowUpdateGenerator.php' );
+require_once $installPath . '/includes/utils/BatchRowWriter.php';
+require_once $installPath . '/includes/utils/RowUpdateGenerator.php';
/**
* Fixes Flow References & entries in categorylinks & related tables.
@@ -25,6 +25,8 @@ class FlowFixLinks extends LoggedUpdateMaintenance {
$this->mDescription = 'Fixes Flow References & entries in categorylinks & related tables';
$this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
}
protected function getUpdateKey() {
@@ -33,13 +35,9 @@ class FlowFixLinks extends LoggedUpdateMaintenance {
protected function doDBUpdates() {
// disable Echo notifications for this script
- global $wgEchoNotifications, $wgFlowMigrateReferenceWiki;
-
- if ( $wgFlowMigrateReferenceWiki ) {
- $this->error( '$wgFlowMigrateReferenceWiki must be false to ensure links from the wrong wiki are not loaded.', 1 );
- }
+ global $wgEchoNotifications;
- $wgEchoNotifications = array();
+ $wgEchoNotifications = [];
$this->removeVirtualPages();
$this->rebuildCoreTables();
@@ -52,15 +50,15 @@ class FlowFixLinks extends LoggedUpdateMaintenance {
protected function removeVirtualPages() {
/** @var \Flow\Data\ObjectManager $storage */
$storage = Container::get( 'storage.wiki_reference' );
- $links = $storage->find( array(
- 'ref_src_wiki' => wfWikiId(),
- 'ref_target_namespace' => array( -1, -2 ),
- ) );
+ $links = $storage->find( [
+ 'ref_src_wiki' => wfWikiID(),
+ 'ref_target_namespace' => [ -1, -2 ],
+ ] );
if ( $links ) {
- $storage->multiRemove( $links, array() );
+ $storage->multiRemove( $links, [] );
}
- $this->output( "Removed " . count( $links ) . " links to special pages.\n");
+ $this->output( "Removed " . count( $links ) . " links to special pages.\n" );
}
protected function rebuildCoreTables() {
@@ -70,36 +68,38 @@ class FlowFixLinks extends LoggedUpdateMaintenance {
$linksTableUpdater = Container::get( 'reference.updater.links-tables' );
$iterator = new BatchRowIterator( $dbr, 'flow_workflow', 'workflow_id', $this->mBatchSize );
- $iterator->setFetchColumns( array( '*' ) );
- $iterator->addConditions( array( 'workflow_wiki' => wfWikiId() ) );
+ $iterator->setFetchColumns( [ '*' ] );
+ $iterator->addConditions( [ 'workflow_wiki' => wfWikiID() ] );
+ $count = 0;
foreach ( $iterator as $rows ) {
- $dbw->begin();
+ $this->beginTransaction( $dbw, __METHOD__ );
foreach ( $rows as $row ) {
- $workflow = Workflow::fromStorageRow( (array) $row );
+ $workflow = Workflow::fromStorageRow( (array)$row );
$id = $workflow->getArticleTitle()->getArticleID();
// delete existing links from DB
- $dbw->delete( 'pagelinks', array( 'pl_from' => $id ), __METHOD__ );
- $dbw->delete( 'imagelinks', array( 'il_from' => $id ), __METHOD__ );
- $dbw->delete( 'categorylinks', array( 'cl_from' => $id ), __METHOD__ );
- $dbw->delete( 'templatelinks', array( 'tl_from' => $id ), __METHOD__ );
- $dbw->delete( 'externallinks', array( 'el_from' => $id ), __METHOD__ );
- $dbw->delete( 'langlinks', array( 'll_from' => $id ), __METHOD__ );
- $dbw->delete( 'iwlinks', array( 'iwl_from' => $id ), __METHOD__ );
+ $dbw->delete( 'pagelinks', [ 'pl_from' => $id ], __METHOD__ );
+ $dbw->delete( 'imagelinks', [ 'il_from' => $id ], __METHOD__ );
+ $dbw->delete( 'categorylinks', [ 'cl_from' => $id ], __METHOD__ );
+ $dbw->delete( 'templatelinks', [ 'tl_from' => $id ], __METHOD__ );
+ $dbw->delete( 'externallinks', [ 'el_from' => $id ], __METHOD__ );
+ $dbw->delete( 'langlinks', [ 'll_from' => $id ], __METHOD__ );
+ $dbw->delete( 'iwlinks', [ 'iwl_from' => $id ], __METHOD__ );
// regenerate & store those links
$linksTableUpdater->doUpdate( $workflow );
}
- $dbw->commit();
+ $this->commitTransaction( $dbw, __METHOD__ );
- $this->output( "Rebuilt links for " . count( $rows ) . " workflows...\n" );
+ $count += count( $rows );
+ $this->output( "Rebuilt links for " . $count . " workflows...\n" );
wfWaitForSlaves();
}
}
}
$maintClass = 'FlowFixLinks';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixLog.php b/Flow/maintenance/FlowFixLog.php
index 34097bb3..69330806 100644
--- a/Flow/maintenance/FlowFixLog.php
+++ b/Flow/maintenance/FlowFixLog.php
@@ -7,10 +7,13 @@ use Flow\Model\PostRevision;
use Flow\Model\UUID;
use Flow\Collection\PostCollection;
-require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
- ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
- : dirname( __FILE__ ) . '/../../../maintenance/Maintenance.php' );
-require_once( __DIR__ . '/../../Echo/includes/BatchRowUpdate.php' );
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
+require_once "$IP/maintenance/Maintenance.php";
+require_once "$IP/includes/utils/RowUpdateGenerator.php";
/**
* Fixes Flow log entries.
@@ -24,6 +27,8 @@ class FlowFixLog extends LoggedUpdateMaintenance {
$this->mDescription = 'Fixes Flow log entries';
$this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
}
protected function getUpdateKey() {
@@ -31,22 +36,22 @@ class FlowFixLog extends LoggedUpdateMaintenance {
}
protected function doDBUpdates() {
- $iterator = new EchoBatchRowIterator( wfGetDB( DB_SLAVE ), 'logging', 'log_id', $this->mBatchSize );
- $iterator->setFetchColumns( array( 'log_id', 'log_params' ) );
- $iterator->addConditions( array(
- 'log_type' => array( 'delete', 'suppress' ),
- 'log_action' => array(
+ $iterator = new BatchRowIterator( wfGetDB( DB_SLAVE ), 'logging', 'log_id', $this->mBatchSize );
+ $iterator->setFetchColumns( [ 'log_id', 'log_params' ] );
+ $iterator->addConditions( [
+ 'log_type' => [ 'delete', 'suppress' ],
+ 'log_action' => [
'flow-delete-post', 'flow-suppress-post', 'flow-restore-post',
'flow-delete-topic', 'flow-suppress-topic', 'flow-restore-topic',
- ),
- ) );
+ ],
+ ] );
- $updater = new EchoBatchRowUpdate(
+ $updater = new BatchRowUpdate(
$iterator,
- new EchoBatchRowWriter( wfGetDB( DB_MASTER ), 'logging' ),
+ new BatchRowWriter( wfGetDB( DB_MASTER ), 'logging' ),
new LogRowUpdateGenerator( $this )
);
- $updater->setOutput( array( $this, 'output' ) );
+ $updater->setOutput( [ $this, 'output' ] );
$updater->execute();
return true;
@@ -76,7 +81,7 @@ class FlowFixLog extends LoggedUpdateMaintenance {
}
}
-class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
+class LogRowUpdateGenerator implements RowUpdateGenerator {
/**
* @var FlowFixLog
*/
@@ -90,12 +95,12 @@ class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
}
public function update( $row ) {
- $updates = array();
+ $updates = [];
$params = unserialize( $row->log_params );
if ( !$params ) {
$this->maintenance->error( "Failed to unserialize log_params for log_id {$row->log_id}" );
- return array();
+ return [];
}
$topic = false;
@@ -110,7 +115,7 @@ class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
if ( !$topic ) {
$this->maintenance->error( "Missing topicId & postId for log_id {$row->log_id}" );
- return array();
+ return [];
}
try {
@@ -119,7 +124,7 @@ class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
$updates['log_title'] = $topic->getTitle()->getDBkey();
} catch ( \Exception $e ) {
$this->maintenance->error( "Couldn't load Title for log_id {$row->log_id}" );
- $updates = array();
+ $updates = [];
}
if ( isset( $params['postId'] ) && $post ) {
@@ -174,8 +179,8 @@ class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
$storage = Container::get( 'storage' );
$result = $storage->find(
'PostRevision',
- array( 'rev_id' => $postId ),
- array( 'LIMIT' => 1 )
+ [ 'rev_id' => $postId ],
+ [ 'LIMIT' => 1 ]
);
if ( $result ) {
@@ -192,4 +197,4 @@ class LogRowUpdateGenerator implements EchoRowUpdateGenerator {
}
$maintClass = 'FlowFixLog';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixUserIp.php b/Flow/maintenance/FlowFixUserIp.php
index b9288976..b184a776 100644
--- a/Flow/maintenance/FlowFixUserIp.php
+++ b/Flow/maintenance/FlowFixUserIp.php
@@ -4,9 +4,9 @@ use Flow\Container;
use Flow\Data\ManagerGroup;
use Flow\Model\UUID;
-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';
/**
* Sets *_user_ip to null when *_user_id is > 0
@@ -26,32 +26,39 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
*/
protected $storage;
- static private $types = array(
+ static private $types = [
'post' => 'Flow\Model\PostRevision',
'header' => 'Flow\Model\Header',
'post-summary' => 'Flow\Model\PostSummary',
- );
+ ];
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->requireExtension( 'Flow' );
+ }
protected function doDBUpdates() {
$this->storage = $storage = Container::get( 'storage' );
$dbf = Container::get( 'db.factory' );
+ /** @var IDatabase $dbw */
$dbw = $dbf->getDB( DB_MASTER );
- $runUpdate = function( $callback ) use ( $dbf, $dbw, $storage ) {
+ $runUpdate = function ( $callback ) use ( $dbf, $dbw, $storage ) {
$continue = "\0";
do {
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
$continue = call_user_func( $callback, $dbw, $continue );
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
$dbf->waitForSlaves();
$storage->clear();
} while ( $continue !== null );
};
- $runUpdate( array( $this, 'updateTreeRevision' ) );
+ $runUpdate( [ $this, 'updateTreeRevision' ] );
$self = $this;
- foreach ( array( 'rev_user', 'rev_mod_user', 'rev_edit_user' ) as $prefix ){
- $runUpdate( function( $dbw, $continue ) use ( $self, $prefix ) {
+ foreach ( [ 'rev_user', 'rev_mod_user', 'rev_edit_user' ] as $prefix ) {
+ $runUpdate( function ( $dbw, $continue ) use ( $self, $prefix ) {
return $self->updateRevision( $prefix, $dbw, $continue );
} );
}
@@ -62,18 +69,18 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
public function updateTreeRevision( DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'flow_tree_revision',
- /* select */array( 'tree_rev_id' ),
- array(
+ /* select */[ 'tree_rev_id' ],
+ [
'tree_rev_id > ' . $dbw->addQuotes( $continue ),
'tree_orig_user_ip IS NOT NULL',
'tree_orig_user_id > 0',
- ),
+ ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'tree_rev_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'tree_rev_id' ]
);
$om = Container::get( 'storage' )->getStorage( 'PostRevision' );
- $objs = $ids = array();
+ $objs = $ids = [];
foreach ( $rows as $row ) {
$id = UUID::create( $row->tree_rev_id );
$found = $om->get( $id );
@@ -89,8 +96,8 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
}
$dbw->update(
/* table */'flow_tree_revision',
- /* update */array( 'tree_orig_user_ip' => null ),
- /* conditions */array( 'tree_rev_id' => $ids ),
+ /* update */[ 'tree_orig_user_ip' => null ],
+ /* conditions */[ 'tree_rev_id' => $ids ],
__METHOD__
);
foreach ( $objs as $obj ) {
@@ -105,17 +112,17 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
public function updateRevision( $columnPrefix, DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'flow_revision',
- /* select */array( 'rev_id', 'rev_type' ),
- /* conditions */ array(
+ /* select */[ 'rev_id', 'rev_type' ],
+ /* conditions */ [
'rev_id > ' . $dbw->addQuotes( $continue ),
"{$columnPrefix}_id > 0",
"{$columnPrefix}_ip IS NOT NULL",
- ),
+ ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rev_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rev_id' ]
);
- $ids = $objs = array();
+ $ids = $objs = [];
foreach ( $rows as $row ) {
$id = UUID::create( $row->rev_id );
$type = self::$types[$row->rev_type];
@@ -135,8 +142,8 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
$dbw->update(
/* table */ 'flow_revision',
- /* update */ array( "{$columnPrefix}_ip" => null ),
- /* conditions */ array( 'rev_id' => $ids ),
+ /* update */ [ "{$columnPrefix}_ip" => null ],
+ /* conditions */ [ 'rev_id' => $ids ],
__METHOD__
);
@@ -160,4 +167,4 @@ class FlowFixUserIp extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowFixUserIp'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowFixWorkflowLastUpdateTimestamp.php b/Flow/maintenance/FlowFixWorkflowLastUpdateTimestamp.php
index 3acd0283..82e7fdec 100644
--- a/Flow/maintenance/FlowFixWorkflowLastUpdateTimestamp.php
+++ b/Flow/maintenance/FlowFixWorkflowLastUpdateTimestamp.php
@@ -8,11 +8,16 @@ use Flow\Model\PostRevision;
use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\Repository\RootPostLoader;
+use Wikimedia\Timestamp\TimestampException;
-require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
- ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
- : dirname( __FILE__ ) . '/../../../maintenance/Maintenance.php' );
-require_once( __DIR__ . '/../../Echo/includes/BatchRowUpdate.php' );
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
+require_once "$IP/maintenance/Maintenance.php";
+require_once "$IP/includes/utils/RowUpdateGenerator.php";
+require_once "$IP/includes/utils/BatchRowWriter.php";
/**
* @ingroup Maintenance
@@ -24,6 +29,8 @@ class FlowFixWorkflowLastUpdateTimestamp extends Maintenance {
$this->mDescription = 'Fixes any incorrect workflow_last_update_timestamp for topics';
$this->setBatchSize( 10 );
+
+ $this->requireExtension( 'Flow' );
}
public function execute() {
@@ -33,16 +40,16 @@ class FlowFixWorkflowLastUpdateTimestamp extends Maintenance {
$storage = Container::get( 'storage' );
$rootPostLoader = Container::get( 'loader.root_post' );
- $iterator = new EchoBatchRowIterator( $dbFactory->getDB( DB_SLAVE ), 'flow_workflow', 'workflow_id', $this->mBatchSize );
- $iterator->setFetchColumns( array( 'workflow_id', 'workflow_type', 'workflow_last_update_timestamp' ) );
- $iterator->addConditions( array( 'workflow_wiki' => wfWikiId() ) );
+ $iterator = new BatchRowIterator( $dbFactory->getDB( DB_SLAVE ), 'flow_workflow', 'workflow_id', $this->mBatchSize );
+ $iterator->setFetchColumns( [ 'workflow_id', 'workflow_type', 'workflow_last_update_timestamp' ] );
+ $iterator->addConditions( [ 'workflow_wiki' => wfWikiID() ] );
- $updater = new EchoBatchRowUpdate(
+ $updater = new BatchRowUpdate(
$iterator,
new UpdateWorkflowLastUpdateTimestampWriter( $storage, $wgFlowCluster ),
new UpdateWorkflowLastUpdateTimestampGenerator( $storage, $rootPostLoader )
);
- $updater->setOutput( array( $this, 'output' ) );
+ $updater->setOutput( [ $this, 'output' ] );
$updater->execute();
}
@@ -59,7 +66,7 @@ class FlowFixWorkflowLastUpdateTimestamp extends Maintenance {
}
}
-class UpdateWorkflowLastUpdateTimestampGenerator implements EchoRowUpdateGenerator {
+class UpdateWorkflowLastUpdateTimestampGenerator implements RowUpdateGenerator {
/**
* @var ManagerGroup
*/
@@ -104,17 +111,17 @@ class UpdateWorkflowLastUpdateTimestampGenerator implements EchoRowUpdateGenerat
throw new FlowException( 'Unknown workflow type: ' . $row->workflow_type );
}
- if ( !$revision) {
- return array();
+ if ( !$revision ) {
+ return [];
}
$timestamp = $this->getUpdateTimestamp( $revision )->getTimestamp( TS_MW );
if ( $timestamp === $row->workflow_last_update_timestamp ) {
// correct update timestamp already, nothing to update
- return array();
+ return [];
}
- return array( 'workflow_last_update_timestamp' => $timestamp );
+ return [ 'workflow_last_update_timestamp' => $timestamp ];
}
/**
@@ -148,7 +155,7 @@ class UpdateWorkflowLastUpdateTimestampGenerator implements EchoRowUpdateGenerat
}
}
-class UpdateWorkflowLastUpdateTimestampWriter extends EchoBatchRowWriter {
+class UpdateWorkflowLastUpdateTimestampWriter extends BatchRowWriter {
/**
* @var ManagerGroup
*/
@@ -185,12 +192,12 @@ class UpdateWorkflowLastUpdateTimestampWriter extends EchoBatchRowWriter {
);
/** @var UUID[] $uuids */
- $uuids = array_map( array( 'Flow\\Model\\UUID', 'create' ), array_keys( $timestamps ) );
+ $uuids = array_map( [ 'Flow\\Model\\UUID', 'create' ], array_keys( $timestamps ) );
/** @var Workflow[] $workflows */
$workflows = $this->storage->getMulti( 'Workflow', $uuids );
foreach ( $workflows as $workflow ) {
- $timestamp = $timestamps[$workflow->getId()->getBinary()];
+ $timestamp = $timestamps[$workflow->getId()->getBinary()->__toString()];
$workflow->updateLastUpdated( UUID::getComparisonUUID( $timestamp ) );
}
@@ -210,7 +217,7 @@ class UpdateWorkflowLastUpdateTimestampWriter extends EchoBatchRowWriter {
* @return array
*/
protected function arrayColumn( array $array, $key ) {
- return array_map( function( $item ) use ( $key ) {
+ return array_map( function ( $item ) use ( $key ) {
return $item[$key];
}, $array );
}
diff --git a/Flow/maintenance/FlowForceSearchIndex.php b/Flow/maintenance/FlowForceSearchIndex.php
index f58d1c01..38948d42 100644
--- a/Flow/maintenance/FlowForceSearchIndex.php
+++ b/Flow/maintenance/FlowForceSearchIndex.php
@@ -1,14 +1,13 @@
<?php
use Flow\Container;
-use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
use Flow\Search\Connection;
-use Flow\Search\Updater;
+use Flow\Search\Updaters\AbstractUpdater;
-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';
/**
* Similar to CirrusSearch's forceSearchIndex, this will force indexing of Flow
@@ -19,6 +18,11 @@ require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
class FlowForceSearchIndex extends Maintenance {
// @todo: do we need to steal more from Cirrus' ForceSearchIndex? What options are important?
+ /**
+ * @var Connection
+ */
+ protected $connection;
+
public function __construct() {
parent::__construct();
@@ -28,98 +32,46 @@ class FlowForceSearchIndex extends Maintenance {
$this->addOption( 'fromId', 'Start indexing at a specific revision id (inclusive).', false, true );
$this->addOption( 'toId', 'Stop indexing at a specific revision (inclusive).', false, true );
- $this->addOption( 'limit', 'Maximum number of revisions to process before exiting the script. Default to unlimited.', false, true );
$this->addOption( 'namespace', 'Only index revisions in this given namespace', false, true );
+
+ $this->requireExtension( 'Flow' );
}
public function execute() {
global $wgFlowSearchMaintenanceTimeout;
+ $this->connection = Container::get( 'search.connection' );
+
// Set the timeout for maintenance actions
- Connection::getSingleton()->setTimeout2( $wgFlowSearchMaintenanceTimeout );
+ $this->connection->setTimeout( $wgFlowSearchMaintenanceTimeout );
- /** @var Updater[] $updaters */
- $updaters = Container::get( 'searchindex.updaters' );
+ /** @var AbstractUpdater[] $updaters */
+ $updaters = Container::get( 'search.index.updaters' );
foreach ( $updaters as $updaterType => $updater ) {
$fromId = $this->getOption( 'fromId', null );
$fromId = $fromId ? UUID::create( $fromId ) : null;
$toId = $this->getOption( 'toId', null );
$toId = $toId ? UUID::create( $toId ) : null;
+ if ( $toId !== null ) {
+ // AbstractIterator::toId is exclusive, but we want inclusive,
+ // so just feed toId() the next possible UUID (UUID + 1)
+ // We need some base conversion & bcadd because the number may
+ // be too large to be an int.
+ $decimal = \Wikimedia\base_convert( $toId->getAlphadecimal(), 36, 10 );
+ $new = bcadd( $decimal, 1, 0 );
+ $alnum = \Wikimedia\base_convert( $new, 10, 36 );
+ $toId = UUID::create( $alnum );
+ }
$namespace = $this->getOption( 'namespace', null );
- $numRevisionsToIndex = $this->getOption( 'limit', null );
$total = 0;
- while ( true ) {
- // if a limit was provided, we should make sure to not fetch
- // more revisions than asked for
- $options = array( 'LIMIT' => $this->mBatchSize );
- if ( $numRevisionsToIndex ) {
- $options['LIMIT'] = min( $numRevisionsToIndex, $this->mBatchSize );
-
- // since we do this in batches, we'll subtract the size of
- // each batch until $numRevisionsToIndex is reached
- $numRevisionsToIndex -= $this->mBatchSize;
- if ( $options['LIMIT'] <= 0 ) {
- break;
- }
- }
-
- $conditions = $updater->buildQueryConditions( $fromId, $toId, $namespace );
- $revisions = $updater->getRevisions( $conditions, $options );
-
- // stop if we're all out of revisions
- if ( !$revisions ) {
- break;
- }
-
- $total += $updater->updateRevisions( $revisions, null, null );
- $this->output( "Indexed $total $updaterType document(s)\n" );
-
- // prepare for next batch, starting at the next id
- // prevFromId will default to around unix epoch - there can be
- // no data before that
- $prevFromId = $fromId ?: UUID::getComparisonUUID( '1' );
- $fromId = $this->getNextFromId( $revisions );
-
- // make sure we don't get stuck in an infinite loop
- $diff = $prevFromId->getTimestampObj()->diff( $fromId->getTimestampObj() );
- // invert will be 1 if the diff is a negative time period from
- // $prevFromId to $fromId, which means that the new $timestamp is
- // more recent than our current $result
- if ( $diff->invert ) {
- $this->error(
- 'Got stuck in an infinite loop.' . "\n" .
- 'workflow_last_update_timestamp is likely incorrect ' .
- 'for some workflows.' . "\n" .
- 'Run maintenance/FlowFixWorkflowLastUpdateTimestamp.php ' .
- 'to automatically fix those.', 1 );
- }
-
- // prevent memory from being filled up
- Container::get( 'storage' )->clear();
- }
- }
- }
+ $updater->iterator->setNamespace( $namespace );
+ $updater->iterator->setFrom( $fromId );
+ $updater->iterator->setTo( $toId );
- /**
- * @param AbstractRevision[] $revisions
- * @return UUID
- */
- protected function getNextFromId( array $revisions ) {
- /** @var AbstractRevision $last */
- $last = end( $revisions );
-
- if ( $last instanceof \Flow\Model\Header ) {
- $timestamp = $last->getRevisionId()->getTimestampObj();
- } else {
- $timestamp = $last->getCollection()->getWorkflow()->getLastUpdatedObj();
+ $total += $updater->updateRevisions( null, null, $this->mBatchSize );
+ $this->output( "Indexed $total $updaterType document(s)\n" );
}
-
- // $timestamp is the timestamp of the last revision we fetched. fromId
- // is inclusive, and we don't want to include what we already have here,
- // so we'll advance 1 more and call that the next fromId
- $timestamp = (int) $timestamp->getTimestamp( TS_UNIX );
- return UUID::getComparisonUUID( $timestamp + 1 );
}
}
diff --git a/Flow/maintenance/FlowPopulateLinksTables.php b/Flow/maintenance/FlowPopulateLinksTables.php
index 5e1220ec..f2e00ee3 100644
--- a/Flow/maintenance/FlowPopulateLinksTables.php
+++ b/Flow/maintenance/FlowPopulateLinksTables.php
@@ -3,9 +3,9 @@
use Flow\Container;
use Flow\Model\UUID;
-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';
/**
* Currently iterates through all revisions for debugging purposes, the
@@ -18,6 +18,7 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Populates links tables for wikis deployed before change 110090";
+ $this->requireExtension( 'Flow' );
}
public function getUpdateKey() {
@@ -42,11 +43,11 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
while ( $count === $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_revision' ),
- array( 'rev_type_id' ),
- array( 'rev_type' => 'header', 'rev_type_id > ' . $dbr->addQuotes( $id ) ),
+ [ 'flow_revision' ],
+ [ 'rev_type_id' ],
+ [ 'rev_type' => 'header', 'rev_type_id > ' . $dbr->addQuotes( $id ) ],
__METHOD__,
- array( 'ORDER BY' => 'rev_type_id ASC', 'LIMIT' => $this->mBatchSize )
+ [ 'ORDER BY' => 'rev_type_id ASC', 'LIMIT' => $this->mBatchSize ]
);
if ( !$res ) {
throw new \MWException( 'SQL error in maintenance script ' . __METHOD__ );
@@ -60,10 +61,10 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
if ( $header ) {
echo "Processing header $alpha\n";
$recorder->onAfterInsert(
- $header, array(),
- array(
+ $header, [],
+ [
'workflow' => $header->getCollection()->getWorkflow()
- )
+ ]
);
}
}
@@ -79,14 +80,14 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
while ( $count === $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_tree_revision' ),
- array( 'tree_rev_id' ),
- array(
+ [ 'flow_tree_revision' ],
+ [ 'tree_rev_id' ],
+ [
'tree_parent_id IS NOT NULL',
'tree_rev_id > ' . $dbr->addQuotes( $id ),
- ),
+ ],
__METHOD__,
- array( 'ORDER BY' => 'tree_rev_id ASC', 'LIMIT' => $this->mBatchSize )
+ [ 'ORDER BY' => 'tree_rev_id ASC', 'LIMIT' => $this->mBatchSize ]
);
if ( !$res ) {
throw new \MWException( 'SQL error in maintenance script ' . __METHOD__ );
@@ -100,10 +101,10 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
if ( $post ) {
echo "Processing post $alpha\n";
$recorder->onAfterInsert(
- $post, array(),
- array(
+ $post, [],
+ [
'workflow' => $post->getCollection()->getWorkflow()
- )
+ ]
);
}
}
@@ -112,4 +113,4 @@ class FlowPopulateLinksTables extends LoggedUpdateMaintenance {
}
$maintClass = "FlowPopulateLinksTables";
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowPopulateRefId.php b/Flow/maintenance/FlowPopulateRefId.php
new file mode 100644
index 00000000..ea2e495e
--- /dev/null
+++ b/Flow/maintenance/FlowPopulateRefId.php
@@ -0,0 +1,73 @@
+<?php
+
+use Flow\Container;
+use Flow\Data\ObjectManager;
+
+$installPath = getenv( 'MW_INSTALL_PATH' ) !== false ?
+ getenv( 'MW_INSTALL_PATH' ) :
+ __DIR__ . '/../../..';
+
+require_once $installPath . '/maintenance/Maintenance.php';
+// extending these - autoloader not yet wired up at the point these are interpreted
+require_once $installPath . '/includes/utils/BatchRowWriter.php';
+require_once $installPath . '/includes/utils/RowUpdateGenerator.php';
+
+/**
+ * Populates ref_id in flow_wiki_ref & flow_ext_ref.
+ *
+ * @ingroup Maintenance
+ */
+class FlowPopulateRefId extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Populates ref_id in flow_wiki_ref & flow_ext_ref';
+
+ $this->setBatchSize( 300 );
+
+ $this->requireExtension( 'Flow' );
+ }
+
+ protected function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ protected function doDBUpdates() {
+ $types = [
+ 'flow_wiki_ref' => Container::get( 'storage.wiki_reference' ),
+ 'flow_ext_ref' => Container::get( 'storage.url_reference' ),
+ ];
+
+ foreach ( $types as $table => $storage ) {
+ $this->update( $storage );
+ }
+
+ $this->output( "Completed\n" );
+
+ return true;
+ }
+
+ /**
+ * @param ObjectManager $storage
+ * @throws \Flow\Exception\InvalidInputException
+ */
+ protected function update( ObjectManager $storage ) {
+ global $wgFlowCluster;
+
+ $total = 0;
+ while ( true ) {
+ $references = (array)$storage->find( [ 'ref_id' => null, 'ref_src_wiki' => wfWikiID() ], [ 'limit' => $this->mBatchSize ] );
+ if ( !$references ) {
+ break;
+ }
+
+ $storage->multiPut( $references, [] );
+ $total += count( $references );
+ $this->output( "Ensured ref_id for " . $total . " " . get_class( $references[0] ) . " references...\n" );
+ wfWaitForSlaves( false, false, $wgFlowCluster );
+ }
+ }
+}
+
+$maintClass = 'FlowPopulateRefId';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowRemoveOldTopics.php b/Flow/maintenance/FlowRemoveOldTopics.php
new file mode 100644
index 00000000..0c5160b8
--- /dev/null
+++ b/Flow/maintenance/FlowRemoveOldTopics.php
@@ -0,0 +1,391 @@
+<?php
+
+use Flow\Container;
+use Flow\Data\ManagerGroup;
+use Flow\Data\Utils\RawSql;
+use Flow\DbFactory;
+use Flow\Model\AbstractRevision;
+use Flow\Model\Header;
+use Flow\Model\PostRevision;
+use Flow\Model\UUID;
+use Flow\Model\Workflow;
+use Flow\Repository\TreeRepository;
+
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+/**
+ * @ingroup Maintenance
+ */
+class FlowRemoveOldTopics extends Maintenance {
+ /**
+ * @var bool
+ */
+ protected $dryRun = false;
+
+ /**
+ * @var ManagerGroup
+ */
+ protected $storage;
+
+ /**
+ * @var TreeRepository
+ */
+ protected $treeRepo;
+
+ /**
+ * @var DbFactory
+ */
+ protected $dbFactory;
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = "Deletes old topics";
+
+ $this->addOption( 'date', 'Date cutoff (in any format understood by wfTimestamp), topics older than this date will be deleted.', true, true );
+ $this->addOption( 'dryrun', 'Simulate script run, without actually deleting anything' );
+
+ $this->setBatchSize( 10 );
+
+ $this->requireExtension( 'Flow' );
+ }
+
+ public function execute() {
+ $this->dryRun = $this->getOption( 'dryrun', false );
+ $this->storage = Container::get( 'storage' );
+ $this->treeRepo = Container::get( 'repository.tree' );
+ $this->dbFactory = Container::get( 'db.factory' );
+
+ $timestamp = wfTimestamp( TS_MW, $this->getOption( 'date' ) );
+
+ $this->removeHeader( $timestamp );
+ // remove topics that are older than the given timestamp
+ $this->removeTopics( $timestamp );
+ // remove topics that have more recent updates, but only from Flow talk
+ // page manager
+ $this->removeTopicsWithFlowUpdates( $timestamp );
+ }
+
+ protected function removeHeader( $timestamp ) {
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+
+ // we don't store a timestamp with revisions - the id also holds date
+ // info, so that's what we should compare against
+ $endId = UUID::getComparisonUUID( $timestamp );
+
+ // start from around unix epoch - there can be no Flow data before that
+ $startId = UUID::getComparisonUUID( '1' );
+ do {
+ /** @var Header[] $revisions */
+ $revisions = $this->storage->find(
+ 'Header',
+ [
+ 'rev_user_wiki' => wfWikiID(),
+ 'rev_type' => 'header',
+ new RawSql( 'rev_id > ' . $dbr->addQuotes( $startId->getBinary() ) ),
+ new RawSql( 'rev_id < ' . $dbr->addQuotes( $endId->getBinary() ) ),
+ // only fetch original post at this point: we still need to
+ // narrow down the results
+ 'rev_parent_id' => null,
+ ],
+ [
+ 'limit' => $this->mBatchSize,
+ 'sort' => 'rev_id',
+ 'order' => 'ASC',
+ ]
+ );
+
+ if ( empty( $revisions ) ) {
+ break;
+ }
+
+ // prepare for next batch, which will start at this
+ /** @var UUID $startId */
+ $startId = end( $revisions )->getRevisionId();
+
+ // we've now found all first revisions prior to a certain date, but we
+ // don't want to remove those that have revisions after that date cutoff
+ // (we don't want to break history)
+ // let's see if any has revisions more recent than timestamp
+ $conds = [];
+ $uuids = [];
+ foreach ( $revisions as $revision ) {
+ // keep track of UUIDs we may want to delete
+ $uuids[$revision->getCollectionId()->getAlphadecimal()] = $revision->getCollectionId();
+
+ $conds[] = [
+ 'rev_user_wiki' => wfWikiID(),
+ 'rev_type' => 'header',
+ new RawSql( 'rev_id >= ' . $dbr->addQuotes( $endId->getBinary() ) ),
+ 'rev_type_id' => $revision->getCollectionId()->getBinary(),
+ ];
+ }
+
+ /** @var Header[] $recent */
+ $recent = $this->storage->findMulti( 'Header', $conds, [ 'limit' => 1 ] );
+
+ // now exclude collection ids where there's a revision that is more
+ // recent than the timestamp cutoff
+ foreach ( $recent as $revisions ) {
+ foreach ( $revisions as $revision ) {
+ unset( $uuids[$revision->getCollectionId()->getAlphadecimal()] );
+ }
+ }
+
+ // by now, there may be nothing left to remove, so move on to the
+ // next batch...
+ if ( empty( $uuids ) ) {
+ continue;
+ }
+
+ $revisions = $this->storage->find(
+ 'Header',
+ [
+ 'rev_user_wiki' => wfWikiID(),
+ 'rev_type' => 'header',
+ 'rev_type_id' => UUID::convertUUIDs( $uuids ),
+ ]
+ );
+
+ $this->output( 'Removing ' . count( $revisions ) . ' header revisions from ' . count( $uuids ) . ' headers (up to ' . $startId->getTimestamp() . ")\n" );
+
+ $this->dbFactory->getDB( DB_MASTER )->begin();
+
+ foreach ( $revisions as $revision ) {
+ $this->removeReferences( $revision );
+ }
+
+ $this->multiRemove( $revisions );
+
+ if ( $this->dryRun ) {
+ $this->dbFactory->getDB( DB_MASTER )->rollback();
+ } else {
+ $this->dbFactory->getDB( DB_MASTER )->commit();
+ $this->dbFactory->waitForSlaves();
+ }
+ } while ( !empty( $revisions ) );
+ }
+
+ /**
+ * @param string $timestamp Timestamp in TS_MW format
+ * @throws \Flow\Exception\FlowException
+ */
+ protected function removeTopics( $timestamp ) {
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+
+ // start from around unix epoch - there can be no Flow data before that
+ $startId = UUID::getComparisonUUID( '1' );
+ do {
+ $workflows = $this->storage->find(
+ 'Workflow',
+ [
+ new RawSql( 'workflow_id > ' . $dbr->addQuotes( $startId->getBinary() ) ),
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_type' => 'topic',
+ new RawSql( 'workflow_last_update_timestamp < ' . $dbr->addQuotes( $timestamp ) ),
+ ],
+ [
+ 'limit' => $this->mBatchSize,
+ 'sort' => 'workflow_id',
+ 'order' => 'ASC',
+ ]
+ );
+
+ if ( empty( $workflows ) ) {
+ break;
+ }
+
+ // prepare for next batch
+ /** @var UUID $startId */
+ $startId = end( $workflows )->getId();
+
+ $this->output( 'Removing ' . count( $workflows ) . ' topic workflows (up to ' . $startId->getTimestamp() . ")\n" );
+ $this->removeWorkflows( $workflows );
+ } while ( !empty( $workflows ) );
+ }
+
+ /**
+ * @param string $timestamp Timestamp in TS_MW format
+ * @throws DBUnexpectedError
+ * @throws \Flow\Exception\FlowException
+ */
+ protected function removeTopicsWithFlowUpdates( $timestamp ) {
+ $dbr = $this->dbFactory->getDB( DB_SLAVE );
+ $talkpageManager = FlowHooks::getOccupationController()->getTalkpageManager();
+
+ // start from around unix epoch - there can be no Flow data before that
+ $batchStartId = UUID::getComparisonUUID( '1' );
+
+ // we only care about revisions since cutoff here
+ $cutoffStartId = UUID::getComparisonUUID( $timestamp );
+
+ do {
+ $workflowIds = $dbr->selectFieldValues(
+ [ 'flow_workflow', 'flow_tree_node', 'flow_revision' ],
+ 'workflow_id',
+ [
+ // revisions more recent than cutoff time
+ 'rev_id > ' . $dbr->addQuotes( $cutoffStartId->getBinary() ),
+ // workflow_id condition is only used to batch, the exact
+ // $batchStartId otherwise doesn't matter (unlike rev_id)
+ 'workflow_id > ' . $dbr->addQuotes( $batchStartId->getBinary() ),
+ 'workflow_wiki' => wfWikiID(),
+ 'workflow_type' => 'topic',
+ 'workflow_last_update_timestamp >= ' . $dbr->addQuotes( $timestamp ),
+ ],
+ __METHOD__,
+ [
+ 'LIMIT' => $this->mBatchSize,
+ 'ORDER BY' => 'workflow_id ASC',
+ // we only want to find topics that were only altered by talk
+ // page manager: as long as anyone else edited any post, we're
+ // not interested in it
+ 'GROUP BY' => 'workflow_id',
+ 'HAVING' => [ 'GROUP_CONCAT(DISTINCT rev_user_id)' => $talkpageManager->getId() ],
+ ],
+ [
+ 'flow_tree_node' => [ 'INNER JOIN', [ 'tree_ancestor_id = workflow_id' ] ],
+ 'flow_revision' => [ 'INNER JOIN', [ 'rev_type_id = tree_descendant_id' ] ],
+ ]
+ );
+
+ if ( empty( $workflowIds ) ) {
+ break;
+ }
+
+ $workflows = $this->storage->getMulti( 'Workflow', $workflowIds );
+
+ // prepare for next batch
+ /** @var UUID $batchStartId */
+ $batchStartId = end( $workflows )->getId();
+
+ $this->output( 'Removing ' . count( $workflows ) . ' topic workflows with recent Flow updates (up to ' . $batchStartId->getTimestamp() . ")\n" );
+ $this->removeWorkflows( $workflows );
+ } while ( !empty( $workflows ) );
+ }
+
+ /**
+ * @param Workflow[] $workflows
+ * @throws DBUnexpectedError
+ */
+ protected function removeWorkflows( array $workflows ) {
+ $this->dbFactory->getDB( DB_MASTER )->begin();
+
+ foreach ( $workflows as $workflow ) {
+ $this->removeSummary( $workflow );
+ $this->removePosts( $workflow );
+ $this->removeTopicList( $workflow );
+ }
+
+ $this->multiRemove( $workflows );
+
+ if ( $this->dryRun ) {
+ $this->dbFactory->getDB( DB_MASTER )->rollback();
+ } else {
+ $this->dbFactory->getDB( DB_MASTER )->commit();
+ $this->dbFactory->waitForSlaves();
+ }
+ }
+
+ protected function removeTopicList( Workflow $workflow ) {
+ $entries = $this->storage->find( 'TopicListEntry', [ 'topic_id' => $workflow->getId() ] );
+ if ( $entries ) {
+ $this->output( 'Removing ' . count( $entries ) . " topiclist entries.\n" );
+ $this->multiRemove( $entries );
+ }
+ }
+
+ protected function removeSummary( Workflow $workflow ) {
+ $revisions = $this->storage->find( 'PostSummary', [ 'rev_type_id' => $workflow->getId() ] );
+ if ( $revisions ) {
+ foreach ( $revisions as $revision ) {
+ $this->removeReferences( $revision );
+ }
+
+ $this->output( 'Removing ' . count( $revisions ) . " summary revisions from 1 topic.\n" );
+ $this->multiRemove( $revisions );
+ }
+ }
+
+ /**
+ * @param UUID $parentId
+ * @param array $subtree
+ * @return array
+ */
+ protected function sortSubtree( UUID $parentId, array $subtree ) {
+ $flat = [];
+
+ // first recursively process all children, so they come first in $flat
+ foreach ( $subtree['children'] as $id => $data ) {
+ $flat = array_merge(
+ $flat,
+ $this->sortSubtree( UUID::create( $id ), $data )
+ );
+ }
+
+ // then add parent, which should come last in $flat
+ $flat[] = $parentId;
+
+ return $flat;
+ }
+
+ protected function removePosts( Workflow $workflow ) {
+ // fetch all children (posts) from a topic & reverse-sort all the posts:
+ // deepest-nested children should come first, parents last
+ $subtree = $this->treeRepo->fetchSubtree( $workflow->getId() );
+ $uuids = $this->sortSubtree( $workflow->getId(), $subtree );
+
+ $conds = [];
+ foreach ( $uuids as $id ) {
+ $conds[] = [ 'rev_type_id' => $id ];
+ }
+
+ $posts = $this->storage->findMulti( 'PostRevision', $conds );
+ $count = 0;
+ foreach ( $posts as $revisions ) {
+ /** @var PostRevision[] $revisions */
+ foreach ( $revisions as $revision ) {
+ $this->removeReferences( $revision );
+ }
+
+ $count += count( $revisions );
+ $this->multiRemove( $revisions );
+
+ foreach ( $revisions as $revision ) {
+ $this->treeRepo->delete( $revision->getCollectionId() );
+ }
+ }
+ $this->output( 'Removing ' . $count . ' post revisions from ' . count( $posts ) . " posts.\n" );
+ }
+
+ protected function removeReferences( AbstractRevision $revision ) {
+ $wikiReferences = $this->storage->find( 'WikiReference', [
+ 'ref_src_wiki' => wfWikiID(),
+ 'ref_src_object_type' => $revision->getRevisionType(),
+ 'ref_src_object_id' => $revision->getCollectionId(),
+ ] );
+ if ( $wikiReferences ) {
+ $this->output( 'Removing ' . count( $wikiReferences ) . " wiki references from 1 revision.\n" );
+ $this->multiRemove( $wikiReferences );
+ }
+
+ $urlReferences = $this->storage->find( 'URLReference', [
+ 'ref_src_wiki' => wfWikiID(),
+ 'ref_src_object_type' => $revision->getRevisionType(),
+ 'ref_src_object_id' => $revision->getCollectionId(),
+ ] );
+ if ( $urlReferences ) {
+ $this->output( 'Removing ' . count( $urlReferences ) . " url references from 1 revision.\n" );
+ $this->multiRemove( $urlReferences );
+ }
+ }
+
+ protected function multiRemove( array $objects ) {
+ $this->storage->multiRemove( $objects );
+ }
+}
+
+$maintClass = 'FlowRemoveOldTopics';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowRestoreLQT.php b/Flow/maintenance/FlowRestoreLQT.php
new file mode 100644
index 00000000..bb36aebe
--- /dev/null
+++ b/Flow/maintenance/FlowRestoreLQT.php
@@ -0,0 +1,302 @@
+<?php
+
+use Flow\Container;
+use Flow\DbFactory;
+use Flow\Import\ArchiveNameHelper;
+
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+class FlowRestoreLQT extends Maintenance {
+ /**
+ * @var User
+ */
+ protected $talkpageManagerUser;
+
+ /**
+ * @var DbFactory
+ */
+ protected $dbFactory;
+
+ /**
+ * @var bool
+ */
+ protected $dryRun = false;
+
+ /**
+ * @var bool
+ */
+ protected $overwrite = false;
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Restores LQT boards after a Flow conversion (revert LQT conversion edits & move LQT boards back)';
+
+ $this->addOption( 'dryrun', 'Simulate script run, without making actual changes' );
+ $this->addOption( 'overwrite-flow', 'Removes the Flow board entirely, restoring LQT to its original location' );
+
+ $this->setBatchSize( 1 );
+
+ $this->requireExtension( 'Flow' );
+ }
+
+ public function execute() {
+ $this->talkpageManagerUser = FlowHooks::getOccupationController()->getTalkpageManager();
+ $this->dbFactory = Container::get( 'db.factory' );
+ $this->dryRun = $this->getOption( 'dryrun', false );
+ $this->overwrite = $this->getOption( 'overwrite-flow', false );
+
+ $this->output( "Restoring posts...\n" );
+ $this->restoreLQTThreads();
+
+ $this->output( "Restoring boards...\n" );
+ $this->restoreLQTBoards();
+ }
+
+ /**
+ * During an import, LQT boards are moved out of the way (archived) to make
+ * place for the Flow board.
+ * And after completing an import, LQT boards are disabled with
+ * {{#useliquidthreads:0}}
+ * That's all perfectly fine assuming the conversion goes well, but we'll
+ * want to go back to the original content with this script...
+ */
+ protected function restoreLQTBoards() {
+ $dbr = $this->dbFactory->getWikiDB( DB_SLAVE );
+ $startId = 0;
+
+ do {
+ // fetch all LQT boards that have been moved out of the way,
+ // with their original title & their current title
+ $rows = $dbr->select(
+ [ 'logging', 'page', 'revision' ],
+ // log_namespace & log_title will be the original location
+ // page_namespace & page_title will be the current location
+ // rev_id is the first Flow talk page manager edit id
+ // log_id is the log entry for when importer moved LQT page
+ [ 'log_namespace', 'log_title', 'page_id', 'page_namespace', 'page_title', 'rev_id' => 'MIN(rev_id)', 'log_id' ],
+ [
+ 'log_user' => $this->talkpageManagerUser->getId(),
+ 'log_type' => 'move',
+ 'page_content_model' => 'wikitext',
+ 'page_id > ' . $dbr->addQuotes( $startId ),
+ ],
+ __METHOD__,
+ [
+ 'GROUP BY' => 'rev_page',
+ 'LIMIT' => $this->mBatchSize,
+ 'ORDER BY' => 'log_id ASC',
+ ],
+ [
+ 'page' => [
+ 'INNER JOIN',
+ [ 'page_id = log_page' ],
+ ],
+ 'revision' => [
+ 'INNER JOIN',
+ [ 'rev_page = log_page', 'rev_user = log_user' ],
+ ],
+ ]
+ );
+
+ foreach ( $rows as $row ) {
+ $from = Title::newFromText( $row->page_title, $row->page_namespace );
+ $to = Title::newFromText( $row->log_title, $row->log_namespace );
+
+ // undo {{#useliquidthreads:0}}
+ $this->restorePageRevision( $row->page_id, $row->rev_id );
+ // undo page move to archive location
+ $this->restoreLQTPage( $from, $to, $row->log_id );
+
+ $startId = $row->page_id;
+ }
+
+ wfWaitForSlaves();
+ } while ( $rows->numRows() >= $this->mBatchSize );
+ }
+
+ /**
+ * After converting an LQT thread to Flow, it's content is altered to
+ * redirect to the new Flow topic.
+ * This finds all last original revisions & restores them.
+ */
+ protected function restoreLQTThreads() {
+ $dbr = $this->dbFactory->getWikiDB( DB_SLAVE );
+ $startId = 0;
+
+ do {
+ // for every LQT post, find the first edit by Flow talk page manager
+ // (to redirect to the new Flow copy)
+ $rows = $dbr->select(
+ [ 'page', 'revision' ],
+ [ 'rev_page', 'rev_id' => ' MIN(rev_id)' ],
+ [
+ 'page_namespace' => [ NS_LQT_THREAD, NS_LQT_SUMMARY ],
+ 'rev_user' => $this->talkpageManagerUser->getId(),
+ 'page_id > ' . $dbr->addQuotes( $startId ),
+ ],
+ __METHOD__,
+ [
+ 'GROUP BY' => 'page_id',
+ 'LIMIT' => $this->mBatchSize,
+ 'ORDER BY' => 'page_id ASC',
+ ],
+ [
+ 'revision' => [
+ 'INNER JOIN',
+ [ 'rev_page = page_id' ],
+ ],
+ ]
+ );
+
+ foreach ( $rows as $row ) {
+ // undo #REDIRECT edit
+ $this->restorePageRevision( $row->rev_page, $row->rev_id );
+ $startId = $row->rev_page;
+ }
+
+ wfWaitForSlaves();
+ } while ( $rows->numRows() >= $this->mBatchSize );
+ }
+
+ /**
+ * @param Title $lqt Title of the LQT board
+ * @param Title $flow Title of the Flow board
+ * @param int $logId Log id for when LQT board was moved by import
+ * @return Status
+ * @throws MWException
+ */
+ protected function restoreLQTPage( Title $lqt, Title $flow, $logId ) {
+ if ( $lqt->equals( $flow ) ) {
+ // is at correct location already (probably a rerun of this script)
+ return Status::newGood();
+ }
+
+ $archiveNameHelper = new ArchiveNameHelper();
+
+ if ( !$flow->exists() ) {
+ $this->movePage( $lqt, $flow, '/* Restore LQT board to original location */' );
+ } else {
+ /*
+ * The importer will query the log table to find the LQT archive
+ * location. It will assume that Flow talk page manager moved the
+ * LQT board to its archive location, and will not recognize the
+ * board if it's been moved by someone else.
+ * Because of that feature (yes, that is intended), we need to make
+ * sure that - in order to enable LQT imports to be picked up again
+ * after this - the move from <original page> to <archive page>
+ * happens in 1 go, by Flow talk page manager.
+ */
+ if ( !$this->overwrite ) {
+ /*
+ * Before we go moving pages around like crazy, let's see if we
+ * actually need to. While it's certainly possible that the LQT
+ * pages have been moved since the import and we need to fix
+ * them, it's very likely that they haven't. In that case, we
+ * won't have to do the complex moves.
+ */
+ $dbr = $this->dbFactory->getWikiDB( DB_SLAVE );
+ $count = $dbr->selectRowCount(
+ [ 'logging' ],
+ '*',
+ [
+ 'log_page' => $lqt->getArticleID(),
+ 'log_type' => 'move',
+ 'log_id > ' . $dbr->addQuotes( $logId ),
+ ],
+ __METHOD__
+ );
+
+ if ( $count > 0 ) {
+ $this->output( "Ensuring LQT board '{$lqt->getPrefixedDBkey()}' is recognized as archive of Flow board '{$flow->getPrefixedDBkey()}'.\n" );
+
+ // 1: move Flow board out of the way so we can restore LQT to
+ // its original location
+ $archive = $archiveNameHelper->decideArchiveTitle( $flow, [ '%s/Flow Archive %d' ] );
+ $this->movePage( $flow, $archive, '/* Make place to restore LQT board */' );
+
+ // 2: move LQT board to the original location
+ $this->movePage( $lqt, $flow, '/* Restore LQT board to original location */' );
+
+ // 3: move LQT board back to archive location
+ $this->movePage( $flow, $lqt, '/* Restore LQT board to archive location */' );
+
+ // 4: move Flow board back to the original location
+ $this->movePage( $archive, $flow, '/* Restore Flow board to correct location */' );
+ }
+ } else {
+ $this->output( "Deleting '{$flow->getPrefixedDBkey()}' & moving '{$lqt->getPrefixedDBkey()}' there.\n" );
+
+ if ( !$this->dryRun ) {
+ $page = WikiPage::factory( $flow );
+ $page->doDeleteArticleReal( '/* Make place to restore LQT board */', false, null, null, $error, $this->talkpageManagerUser );
+ }
+
+ $this->movePage( $lqt, $flow, '/* Restore LQT board to original location */' );
+ }
+ }
+ }
+
+ /**
+ * @param Title $from
+ * @param Title $to
+ * @param string $reason
+ * @return Status
+ */
+ protected function movePage( Title $from, Title $to, $reason ) {
+ $this->output( " Moving '{$from->getPrefixedDBkey()}' to '{$to->getPrefixedDBkey()}'.\n" );
+
+ $movePage = new MovePage( $from, $to );
+ $status = $movePage->isValidMove();
+ if ( !$status->isGood() ) {
+ return $status;
+ }
+
+ if ( $this->dryRun ) {
+ return Status::newGood();
+ }
+
+ return $movePage->move( $this->talkpageManagerUser, $reason, false );
+ }
+
+ /**
+ * @param int $pageId
+ * @param int $nextRevisionId Revision of the first *bad* revision
+ * @return Status
+ * @throws MWException
+ */
+ protected function restorePageRevision( $pageId, $nextRevisionId ) {
+ global $wgLang;
+
+ $page = WikiPage::newFromID( $pageId );
+ $revisionId = $page->getTitle()->getPreviousRevisionID( $nextRevisionId );
+ $revision = Revision::newFromPageId( $pageId, $revisionId );
+
+ if ( $page->getContent()->equals( $revision->getContent() ) ) {
+ // has correct content already (probably a rerun of this script)
+ return Status::newGood();
+ }
+
+ $content = $revision->getContent()->serialize();
+ $content = $wgLang->truncate( $content, 150 );
+ $content = str_replace( "\n", '\n', $content );
+ $this->output( "Restoring revision {$revisionId} for LQT page {$pageId}: {$content}\n" );
+
+ if ( $this->dryRun ) {
+ return Status::newGood();
+ } else {
+ return $page->doEditContent(
+ $revision->getContent( Revision::RAW ),
+ '/* Restore LQT topic content */',
+ EDIT_UPDATE | EDIT_MINOR | EDIT_FORCE_BOT,
+ $revision->getId(),
+ $this->talkpageManagerUser
+ );
+ }
+ }
+}
+
+$maintClass = 'FlowRestoreLQT';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowSearchConfig.php b/Flow/maintenance/FlowSearchConfig.php
index a4951269..8a29763f 100644
--- a/Flow/maintenance/FlowSearchConfig.php
+++ b/Flow/maintenance/FlowSearchConfig.php
@@ -1,5 +1,6 @@
<?php
+use Flow\Container;
use Flow\Search\Connection;
use Flow\Search\Maintenance\MappingConfigBuilder;
use CirrusSearch\ElasticsearchIntermediary;
@@ -20,10 +21,10 @@ use CirrusSearch\Maintenance\Validators\SpecificAliasValidator;
use CirrusSearch\Maintenance\Validators\Validator;
use CirrusSearch\Util;
-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' );
-require_once( __DIR__ . '/../../CirrusSearch/includes/Maintenance/Maintenance.php' );
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+require_once __DIR__ . '/../../CirrusSearch/includes/Maintenance/Maintenance.php';
/**
* Similar to CirrusSearch's UpdateOneSearchIndexConfig.
@@ -162,7 +163,7 @@ class FlowSearchConfig extends Maintenance {
"rebuilding it. Once you specify a new indexIdentifier for this wiki you'll have to " .
"run this script with the same identifier each time. Defaults to 'current' which " .
"infers the currently in use identifier. You can also use 'now' to set the identifier " .
- "to the current time in seconds which should give you a unique identifier.", false, true);
+ "to the current time in seconds which should give you a unique identifier.", false, true );
$this->addOption( 'reindexAndRemoveOk', "If the alias is held by another index then " .
"reindex all documents from that index (via the alias) to this one, swing the " .
"alias to this index, and then remove other index. You'll have to redo all updates ".
@@ -190,6 +191,8 @@ class FlowSearchConfig extends Maintenance {
$this->addOption( 'justAllocation', 'Just validate the shard allocation settings. Use ' .
"when you need to apply new cache warmers but want to be sure that you won't apply any other " .
'changes at an inopportune time.' );
+
+ $this->requireExtension( 'Flow' );
}
protected function setProperties() {
@@ -202,12 +205,12 @@ class FlowSearchConfig extends Maintenance {
$wgFlowSearchMaxShardsPerNode,
$wgFlowSearchCacheWarmers;
- $this->connection = Connection::getSingleton();
+ $this->connection = Container::get( 'search.connection' );
$this->utils = new ConfigUtils( $this->getClient(), $this );
$this->indexType = 'flow'; // only 1 index for Flow
$this->startOver = $this->getOption( 'startOver', false );
- $this->indexBaseName = $this->getOption( 'baseName', wfWikiId() );
+ $this->indexBaseName = $this->getOption( 'baseName', wfWikiID() );
$this->reindexAndRemoveOk = $this->getOption( 'reindexAndRemoveOk', false );
$this->reindexProcesses = $this->getOption( 'reindexProcesses', wfIsWindows() ? 1 : 5 );
$this->reindexChunkSize = $this->getOption( 'reindexChunkSize', 100 );
@@ -221,7 +224,7 @@ class FlowSearchConfig extends Maintenance {
$this->maintenanceTimeout = $wgFlowSearchMaintenanceTimeout;
$this->refreshInterval = $wgFlowSearchRefreshInterval;
$this->maxShardsPerNode = isset( $wgFlowSearchMaxShardsPerNode[$this->indexType] ) ? $wgFlowSearchMaxShardsPerNode[$this->indexType] : 'unlimited';
- $this->cacheWarmers = isset( $wgFlowSearchCacheWarmers[$this->indexType] ) ? $wgFlowSearchCacheWarmers[$this->indexType] : array();
+ $this->cacheWarmers = isset( $wgFlowSearchCacheWarmers[$this->indexType] ) ? $wgFlowSearchCacheWarmers[$this->indexType] : [];
$this->indexIdentifier = $this->utils->pickIndexIdentifierFromOption( $this->getOption( 'indexIdentifier', 'current' ), $this->getIndexTypeName() );
$this->reindexAcceptableCountDeviation = Util::parsePotentialPercent( $this->getOption( 'reindexAcceptableCountDeviation', '5%' ) );
@@ -237,7 +240,7 @@ class FlowSearchConfig extends Maintenance {
* @return Validator[]
*/
protected function getIndexSettingsValidators() {
- $validators = array();
+ $validators = [];
$validators[] = new NumberOfShardsValidator( $this->getIndex(), $this->getShardCount(), $this );
$validators[] = new ReplicaRangeValidator( $this->getIndex(), $this->getReplicaCount(), $this );
@@ -251,7 +254,7 @@ class FlowSearchConfig extends Maintenance {
* @return Validator[]
*/
protected function getValidators() {
- $validators = array();
+ $validators = [];
if ( $this->getOption( 'justCacheWarmers', false ) ) {
$validators[] = new CacheWarmersValidator( $this->indexType, $this->getTopicType(), $this->cacheWarmers, $this );
@@ -272,7 +275,7 @@ class FlowSearchConfig extends Maintenance {
$validator->printDebugCheckConfig( $this->printDebugCheckConfig );
$validators[] = $validator;
- $types = array( 'topic' => $this->getTopicType(), 'header' => $this->getHeaderType() );
+ $types = [ 'topic' => $this->getTopicType(), 'header' => $this->getHeaderType() ];
$validator = new MappingValidator( $this->getIndex(), $this->optimizeIndexForExperimentalHighlighter, $this->availablePlugins, $this->getMappingConfig(), $types, $this );
$validator->printDebugCheckConfig( $this->printDebugCheckConfig );
$validators[] = $validator;
@@ -280,10 +283,10 @@ class FlowSearchConfig extends Maintenance {
$validators[] = new CacheWarmersValidator( $this->indexType, $this->getTopicType(), $this->cacheWarmers, $this );
$validators[] = new CacheWarmersValidator( $this->indexType, $this->getHeaderType(), $this->cacheWarmers, $this );
- $types = array( $this->getTopicType(), $this->getHeaderType() );
- $oldTypes = array( $this->getOldTopicType(), $this->getOldHeaderType() );
+ $types = [ $this->getTopicType(), $this->getHeaderType() ];
+ $oldTypes = [ $this->getOldTopicType(), $this->getOldHeaderType() ];
$reindexer = new Reindexer( $this->getIndex(), Connection::getSingleton(), $types, $oldTypes, $this->getShardCount(), $this->getReplicaCount(), $this->maintenanceTimeout, $this->getMergeSettings(), $this->getMappingConfig(), $this );
- $reindexParams = array( $this->reindexProcesses, $this->refreshInterval, $this->reindexRetryAttempts, $this->reindexChunkSize, $this->reindexAcceptableCountDeviation );
+ $reindexParams = [ $this->reindexProcesses, $this->refreshInterval, $this->reindexRetryAttempts, $this->reindexChunkSize, $this->reindexAcceptableCountDeviation ];
$reindexValidators = $this->getIndexSettingsValidators();
$validators[] = new SpecificAliasValidator( $this->getClient(), $this->getIndexTypeName(), $this->getSpecificIndexName(), $this->startOver, $reindexer, $reindexParams, $reindexValidators, $this->reindexAndRemoveOk, $this->tooFewReplicas, $this );
@@ -323,7 +326,7 @@ class FlowSearchConfig extends Maintenance {
}
}
-// $this->updateVersions(); // @todo: might need this some day? (see CirrusSearch's UpdateOneSearchIndexConfig::updateVersions)
+ // $this->updateVersions(); // @todo: might need this some day? (see CirrusSearch's UpdateOneSearchIndexConfig::updateVersions)
} catch ( \Elastica\Exception\Connection\HttpException $e ) {
$message = $e->getMessage();
$this->output( "\nUnexpected Elasticsearch failure.\n" );
@@ -382,7 +385,7 @@ class FlowSearchConfig extends Maintenance {
* @param array $availablePlugins
* @return AnalysisConfigBuilder
*/
- protected function pickAnalyzer( $langCode, array $availablePlugins = array() ) {
+ protected function pickAnalyzer( $langCode, array $availablePlugins = [] ) {
$analysisConfigBuilder = new AnalysisConfigBuilder( $langCode, $availablePlugins );
$this->outputIndented( 'Picking analyzer...' . $analysisConfigBuilder->getDefaultTextAnalyzerType() . "\n" );
return $analysisConfigBuilder;
@@ -397,23 +400,23 @@ class FlowSearchConfig extends Maintenance {
}
protected function getClient() {
- return $this->connection->getClient2();
+ return $this->connection->getClient();
}
protected function getIndex() {
- return $this->connection->getIndex2( $this->indexBaseName, $this->indexType, $this->indexIdentifier );
+ return $this->connection->getIndex( $this->indexBaseName, $this->indexType, $this->indexIdentifier );
}
protected function getIndexName() {
- return $this->connection->getIndexName2( $this->indexBaseName );
+ return $this->connection->getIndexName( $this->indexBaseName );
}
protected function getSpecificIndexName() {
- return $this->connection->getIndexName2( $this->indexBaseName, $this->indexType, $this->indexIdentifier );
+ return $this->connection->getIndexName( $this->indexBaseName, $this->indexType, $this->indexIdentifier );
}
protected function getIndexTypeName() {
- return $this->connection->getIndexName2( $this->indexBaseName, $this->indexType );
+ return $this->connection->getIndexName( $this->indexBaseName, $this->indexType );
}
protected function getTopicType() {
@@ -425,12 +428,12 @@ class FlowSearchConfig extends Maintenance {
}
protected function getOldTopicType() {
- $index = Connection::getFlowIndex( $this->indexBaseName );
+ $index = $this->connection->getFlowIndex( $this->indexBaseName );
return $index->getType( Connection::TOPIC_TYPE_NAME );
}
protected function getOldHeaderType() {
- $index = Connection::getFlowIndex( $this->indexBaseName );
+ $index = $this->connection->getFlowIndex( $this->indexBaseName );
return $index->getType( Connection::HEADER_TYPE_NAME );
}
@@ -439,7 +442,7 @@ class FlowSearchConfig extends Maintenance {
}
protected function setConnectionTimeout() {
- $this->connection->setTimeout2( $this->maintenanceTimeout );
+ $this->connection->setTimeout( $this->maintenanceTimeout );
}
}
diff --git a/Flow/maintenance/FlowSetUserIp.php b/Flow/maintenance/FlowSetUserIp.php
index a04314e7..c19ab12a 100644
--- a/Flow/maintenance/FlowSetUserIp.php
+++ b/Flow/maintenance/FlowSetUserIp.php
@@ -2,9 +2,9 @@
use Flow\Container;
-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';
/**
* Populate the *_user_ip fields within flow. This only updates
@@ -21,12 +21,18 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
*/
private $completeCount = 0;
+ public function __construct() {
+ parent::__construct();
+
+ $this->requireExtension( 'Flow' );
+ }
+
protected function doDBUpdates() {
$dbf = Container::get( 'db.factory' );
$dbw = $dbf->getDB( DB_MASTER );
$hasRun = false;
- $runUpdate = function( $callback ) use ( $dbf, $dbw, &$hasRun ) {
+ $runUpdate = function ( $callback ) use ( $dbf, $dbw, &$hasRun ) {
$hasRun = true;
$continue = "\0";
do {
@@ -37,17 +43,17 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
// run updates only if we have the required source data
if ( $dbw->fieldExists( 'flow_workflow', 'workflow_user_text' ) ) {
- $runUpdate( array( $this, 'updateWorkflow' ) );
+ $runUpdate( [ $this, 'updateWorkflow' ] );
}
if ( $dbw->fieldExists( 'flow_tree_revision', 'tree_orig_user_text' ) ) {
- $runUpdate( array( $this, 'updateTreeRevision' ) );
+ $runUpdate( [ $this, 'updateTreeRevision' ] );
}
if (
$dbw->fieldExists( 'flow_revision', 'rev_user_text' ) &&
$dbw->fieldExists( 'flow_revision', 'rev_mod_user_text' ) &&
$dbw->fieldExists( 'flow_revision', 'rev_edit_user_text' )
) {
- $runUpdate( array( $this, 'updateRevision' ) );
+ $runUpdate( [ $this, 'updateRevision' ] );
}
if ( $hasRun ) {
@@ -67,14 +73,14 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
public function updateWorkflow( DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'flow_workflow',
- /* select */array( 'workflow_id', 'workflow_user_text' ),
- /* conds */array(
+ /* select */[ 'workflow_id', 'workflow_user_text' ],
+ /* conds */[
'workflow_id > ' . $dbw->addQuotes( $continue ),
'workflow_user_ip IS NULL',
'workflow_user_id = 0'
- ),
+ ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'workflow_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'workflow_id' ]
);
$continue = null;
@@ -83,8 +89,8 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
$continue = $row->workflow_id;
$dbw->update(
/* table */'flow_workflow',
- /* update */array( 'workflow_user_ip' => $row->workflow_user_text ),
- /* conditions */array( 'workflow_id' => $row->workflow_id ),
+ /* update */[ 'workflow_user_ip' => $row->workflow_user_text ],
+ /* conditions */[ 'workflow_id' => $row->workflow_id ],
__METHOD__
);
@@ -97,14 +103,14 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
public function updateTreeRevision( DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'flow_tree_revision',
- /* select */array( 'tree_rev_id', 'tree_orig_user_text' ),
- array(
+ /* select */[ 'tree_rev_id', 'tree_orig_user_text' ],
+ [
'tree_rev_id > ' . $dbw->addQuotes( $continue ),
'tree_orig_user_ip IS NULL',
'tree_orig_user_id = 0',
- ),
+ ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'tree_rev_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'tree_rev_id' ]
);
$continue = null;
@@ -112,8 +118,8 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
$continue = $row->tree_rev_id;
$dbw->update(
/* table */'flow_tree_revision',
- /* update */array( 'tree_orig_user_ip' => $row->tree_orig_user_text ),
- /* conditions */array( 'tree_rev_id' => $row->tree_rev_id ),
+ /* update */[ 'tree_orig_user_ip' => $row->tree_orig_user_text ],
+ /* conditions */[ 'tree_rev_id' => $row->tree_rev_id ],
__METHOD__
);
@@ -126,26 +132,26 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
public function updateRevision( DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'flow_revision',
- /* select */array( 'rev_id', 'rev_user_id', 'rev_user_text', 'rev_mod_user_id', 'rev_mod_user_text', 'rev_edit_user_id', 'rev_edit_user_text' ),
- /* conditions */ array(
+ /* select */[ 'rev_id', 'rev_user_id', 'rev_user_text', 'rev_mod_user_id', 'rev_mod_user_text', 'rev_edit_user_id', 'rev_edit_user_text' ],
+ /* conditions */ [
'rev_id > ' . $dbw->addQuotes( $continue ),
$dbw->makeList(
- array(
+ [
'rev_user_id' => 0,
'rev_mod_user_id' => 0,
'rev_edit_user_id' => 0,
- ),
+ ],
LIST_OR
),
- ),
+ ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rev_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rev_id' ]
);
$continue = null;
foreach ( $rows as $row ) {
$continue = $row->rev_id;
- $updates = array();
+ $updates = [];
if ( $row->rev_user_id == 0 ) {
$updates['rev_user_ip'] = $row->rev_user_text;
@@ -160,7 +166,7 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
$dbw->update(
/* table */ 'flow_revision',
/* update */ $updates,
- /* conditions */ array( 'rev_id' => $row->rev_id ),
+ /* conditions */ [ 'rev_id' => $row->rev_id ],
__METHOD__
);
}
@@ -180,4 +186,4 @@ class FlowSetUserIp extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowSetUserIp'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateBetaFeaturePreference.php b/Flow/maintenance/FlowUpdateBetaFeaturePreference.php
index 8e69043b..43e4cd65 100644
--- a/Flow/maintenance/FlowUpdateBetaFeaturePreference.php
+++ b/Flow/maintenance/FlowUpdateBetaFeaturePreference.php
@@ -1,8 +1,8 @@
<?php
-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';
/**
* Sets Flow beta feature preference to true
@@ -14,7 +14,9 @@ require_once ( getenv( 'MW_INSTALL_PATH' ) !== false
class FlowUpdateBetaFeaturePreference extends LoggedUpdateMaintenance {
public function __construct() {
+ parent::__construct();
$this->setBatchSize( 300 );
+ $this->requireExtension( 'Flow' );
}
/**
@@ -37,27 +39,27 @@ class FlowUpdateBetaFeaturePreference extends LoggedUpdateMaintenance {
$innerQuery = $db->selectSQLText(
'user_properties',
'up_user',
- array(
+ [
'up_property' => BETA_FEATURE_FLOW_USER_TALK_PAGE,
'up_value' => 1
- )
+ ]
);
$result = $db->select(
- array( 'page', 'user' ),
+ [ 'page', 'user' ],
'user_id',
- array(
+ [
'page_content_model' => CONTENT_MODEL_FLOW_BOARD,
"user_id NOT IN($innerQuery)"
- ),
+ ],
__METHOD__,
- array(),
- array(
- 'user' => array( 'JOIN', array(
+ [],
+ [
+ 'user' => [ 'JOIN', [
'page_namespace' => NS_USER_TALK,
"page_title = REPLACE(user_name, ' ', '_')"
- ) ),
- )
+ ] ],
+ ]
);
$i = 0;
@@ -90,4 +92,4 @@ class FlowUpdateBetaFeaturePreference extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowUpdateBetaFeaturePreference'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateRecentChanges.php b/Flow/maintenance/FlowUpdateRecentChanges.php
index df2a6c7e..99623096 100644
--- a/Flow/maintenance/FlowUpdateRecentChanges.php
+++ b/Flow/maintenance/FlowUpdateRecentChanges.php
@@ -2,9 +2,9 @@
use Flow\Data\Listener\RecentChangesListener;
-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';
/**
* Updates recentchanges entries to contain information to build the
@@ -27,6 +27,12 @@ class FlowUpdateRecentChanges extends LoggedUpdateMaintenance {
*/
protected $batchSize = 300;
+ public function __construct() {
+ parent::__construct();
+
+ $this->requireExtension( 'Flow' );
+ }
+
protected function doDBUpdates() {
$dbw = wfGetDB( DB_MASTER );
@@ -50,10 +56,10 @@ class FlowUpdateRecentChanges extends LoggedUpdateMaintenance {
public function refreshBatch( DatabaseBase $dbw, $continue = null ) {
$rows = $dbw->select(
/* table */'recentchanges',
- /* select */array( 'rc_id', 'rc_params' ),
- /* conds */array( "rc_id > $continue", 'rc_source' => RecentChangesListener::SRC_FLOW ),
+ /* select */[ 'rc_id', 'rc_params' ],
+ /* conds */[ "rc_id > $continue", 'rc_source' => RecentChangesListener::SRC_FLOW ],
__METHOD__,
- /* options */array( 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rc_id' )
+ /* options */[ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'rc_id' ]
);
$continue = null;
@@ -62,11 +68,11 @@ class FlowUpdateRecentChanges extends LoggedUpdateMaintenance {
$continue = $row->rc_id;
// build params
- wfSuppressWarnings();
+ MediaWiki\suppressWarnings();
$params = unserialize( $row->rc_params );
- wfRestoreWarnings();
+ MediaWiki\restoreWarnings();
if ( !$params ) {
- $params = array();
+ $params = [];
}
// Don't fix entries that have been dealt with already
@@ -153,8 +159,8 @@ class FlowUpdateRecentChanges extends LoggedUpdateMaintenance {
// update log entry
$dbw->update(
'recentchanges',
- array( 'rc_params' => serialize( $params ) ),
- array( 'rc_id' => $row->rc_id )
+ [ 'rc_params' => serialize( $params ) ],
+ [ 'rc_id' => $row->rc_id ]
);
$this->completeCount++;
@@ -174,4 +180,4 @@ class FlowUpdateRecentChanges extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowUpdateRecentChanges'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateResolvedNotifTitles.php b/Flow/maintenance/FlowUpdateResolvedNotifTitles.php
new file mode 100644
index 00000000..62b2131b
--- /dev/null
+++ b/Flow/maintenance/FlowUpdateResolvedNotifTitles.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Update the titles of flow-topic-resolved events to point to boards instead of topics
+ *
+ * @ingroup Maintenance
+ */
+
+use Flow\Container;
+use Flow\WorkflowLoaderFactory;
+
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
+
+/**
+ * Maintenance script that update flow-topic-resolved events to point event_page_id to the board instead of the topic.
+ *
+ * @ingroup Maintenance
+ */
+class FlowUpdateResolvedNotifTitles extends LoggedUpdateMaintenance {
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = "Update the titles of flow-topic-resolved Echo events to point to boards instead of topics";
+
+ $this->setBatchSize( 500 );
+
+ $this->requireExtension( 'Flow' );
+ }
+
+ public function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ public function doDBUpdates() {
+ $dbFactory = MWEchoDbFactory::newFromDefault();
+ $dbw = $dbFactory->getEchoDb( DB_MASTER );
+ $dbr = $dbFactory->getEchoDb( DB_SLAVE );
+ // We can't join echo_event with page, because those tables can be on different
+ // DB clusters. If we had been able to do that, we could have added
+ // wHERE page_namespace=NS_TOPIC, but instead we have to examine all rows
+ // and skip the non-NS_TOPIC ones.
+ $iterator = new BatchRowIterator(
+ $dbr,
+ 'echo_event',
+ 'event_id',
+ $this->mBatchSize
+ );
+ $iterator->addConditions( [
+ 'event_type' => 'flow-topic-resolved',
+ 'event_page_id IS NOT NULL',
+ ] );
+ $iterator->setFetchColumns( [ 'event_page_id' ] );
+
+ $storage = Container::get( 'storage.workflow' );
+
+ $this->output( "Retitling flow-topic-resolved events...\n" );
+
+ $processed = 0;
+ foreach ( $iterator as $batch ) {
+ foreach ( $batch as $row ) {
+ $topicTitle = Title::newFromId( $row->event_page_id );
+ if ( !$topicTitle || $topicTitle->getNamespace() !== NS_TOPIC ) {
+ continue;
+ }
+ $boardTitle = null;
+ try {
+ $uuid = WorkflowLoaderFactory::uuidFromTitle( $topicTitle );
+ $workflow = $storage->get( $uuid );
+ if ( $workflow ) {
+ $boardTitle = $workflow->getOwnerTitle();
+ }
+ } catch ( Exception $e ) {
+ }
+ if ( $boardTitle ) {
+ $dbw->update(
+ 'echo_event',
+ [ 'event_page_id' => $boardTitle->getArticleId() ],
+ [ 'event_id' => $row->event_id ]
+ );
+ $processed += $dbw->affectedRows();
+ } else {
+ $this->output( "Could not find board for topic: " . $topicTitle->getPrefixedText() . "\n" );
+ }
+ }
+
+ $this->output( "Updated $processed events.\n" );
+ $dbFactory->waitForSlaves();
+ }
+
+ return true;
+ }
+}
+
+$maintClass = 'FlowUpdateResolvedNotifTitles';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateRevContentModelFromOccupyPages.php b/Flow/maintenance/FlowUpdateRevContentModelFromOccupyPages.php
index b26de04b..ea67f933 100644
--- a/Flow/maintenance/FlowUpdateRevContentModelFromOccupyPages.php
+++ b/Flow/maintenance/FlowUpdateRevContentModelFromOccupyPages.php
@@ -1,8 +1,8 @@
<?php
-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';
/**
* This script should be run immediately before dropping the wgFlowOccupyPages
@@ -20,6 +20,8 @@ class FlowUpdateRevContentModelFromOccupyPages extends Maintenance {
$this->mDescription = 'Sets rev_content_model from wgFlowOccupyPages, in preparation for dropping that config variable.';
+ $this->requireExtension( 'Flow' );
+
// Given the number of occupied pages, this probably doesn't need to be
// batched; just being cautious.
$this->setBatchSize( 10 );
@@ -36,20 +38,20 @@ class FlowUpdateRevContentModelFromOccupyPages extends Maintenance {
$skippedCount = 0;
while ( $overallInd < $pageCount ) {
- $dbw->begin();
+ $this->beginTransaction( $dbw, __METHOD__ );
$batchInd = 0;
- while( $overallInd < $pageCount && $batchInd < $this->mBatchSize ) {
+ while ( $overallInd < $pageCount && $batchInd < $this->mBatchSize ) {
$pageName = $wgFlowOccupyPages[$overallInd];
$title = Title::newFromTextThrow( $pageName );
$revId = $title->getLatestRevID( Title::GAID_FOR_UPDATE );
if ( $revId !== 0 ) {
$dbw->update(
'revision',
- array(
+ [
'rev_content_model' =>
CONTENT_MODEL_FLOW_BOARD
- ),
- array( 'rev_id' => $revId ),
+ ],
+ [ 'rev_id' => $revId ],
__METHOD__
);
$updatedCount++;
@@ -63,7 +65,7 @@ class FlowUpdateRevContentModelFromOccupyPages extends Maintenance {
$batchInd++;
}
- $dbw->commit();
+ $this->commitTransaction( $dbw, __METHOD__ );
$this->output( "Completed batch.\n\n" );
}
@@ -72,4 +74,4 @@ class FlowUpdateRevContentModelFromOccupyPages extends Maintenance {
}
$maintClass = 'FlowUpdateRevContentModelFromOccupyPages';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateRevisionContentLength.php b/Flow/maintenance/FlowUpdateRevisionContentLength.php
index b281979c..2e06bcde 100644
--- a/Flow/maintenance/FlowUpdateRevisionContentLength.php
+++ b/Flow/maintenance/FlowUpdateRevisionContentLength.php
@@ -4,9 +4,9 @@ use Flow\Container;
use Flow\Model\AbstractRevision;
use Flow\Model\UUID;
-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';
/**
* @ingroup Maintenance
@@ -19,11 +19,11 @@ class FlowUpdateRevisionContentLength extends LoggedUpdateMaintenance {
*
* @var string[]
*/
- static private $revisionTypes = array(
+ static private $revisionTypes = [
'post' => 'Flow\Model\PostRevision',
'header' => 'Flow\Model\Header',
'post-summary' => 'Flow\Model\PostSummary',
- );
+ ];
/**
* @var Flow\DbFactory
@@ -48,6 +48,7 @@ class FlowUpdateRevisionContentLength extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Updates content length for revisions with unset content length.";
+ $this->requireExtension( 'Flow' );
}
public function getUpdateKey() {
@@ -74,22 +75,22 @@ class FlowUpdateRevisionContentLength extends LoggedUpdateMaintenance {
$dbw = $this->dbFactory->getDb( DB_MASTER );
// Walk through the flow_revision table
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
$dbw,
/* table = */'flow_revision',
/* primary key = */'rev_id',
$this->mBatchSize
);
// Only fetch rows created by users from the current wiki.
- $it->addConditions( array(
- 'rev_user_wiki' => wfWikiId(),
- ) );
+ $it->addConditions( [
+ 'rev_user_wiki' => wfWikiID(),
+ ] );
// We only need the id and type field
- $it->setFetchColumns( array( 'rev_id', 'rev_type' ) );
+ $it->setFetchColumns( [ 'rev_id', 'rev_type' ] );
$total = $fail = 0;
foreach ( $it as $batch ) {
- $dbw->begin();
+ $this->beginTransaction( $dbw, __METHOD__ );
foreach ( $batch as $row ) {
$total++;
if ( !isset( self::$revisionTypes[$row->rev_type] ) ) {
@@ -129,7 +130,7 @@ class FlowUpdateRevisionContentLength extends LoggedUpdateMaintenance {
}
$this->output( '.' );
}
- $dbw->commit();
+ $this->commitTransaction( $dbw, __METHOD__ );
$this->storage->clear();
$this->dbFactory->waitForSlaves();
}
@@ -154,10 +155,10 @@ class FlowUpdateRevisionContentLength extends LoggedUpdateMaintenance {
if ( $revision->isModerated() && !$revision->isLocked() ) {
return 0;
} else {
- return $revision->getContentLength() ?: mb_strlen( $revision->getContent( 'wikitext' ) );
+ return $revision->getContentLength() ?: $revision->calculateContentLength();
}
}
}
$maintClass = 'FlowUpdateRevisionContentLength';
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/FlowUpdateRevisionTypeId.php b/Flow/maintenance/FlowUpdateRevisionTypeId.php
index e0637a29..7a5443d2 100644
--- a/Flow/maintenance/FlowUpdateRevisionTypeId.php
+++ b/Flow/maintenance/FlowUpdateRevisionTypeId.php
@@ -6,7 +6,7 @@ $IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
$IP = __DIR__ . '/../../..';
}
-require_once( "$IP/maintenance/Maintenance.php" );
+require_once "$IP/maintenance/Maintenance.php";
/**
* Update flow_revision.rev_type_id
@@ -18,6 +18,7 @@ class FlowUpdateRevisionTypeId extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Update flow_revision.rev_type_id";
+ $this->requireExtension( 'Flow' );
$this->setBatchSize( 300 );
}
@@ -38,15 +39,15 @@ class FlowUpdateRevisionTypeId extends LoggedUpdateMaintenance {
while ( $count == $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_revision', 'flow_tree_revision', 'flow_header_revision' ),
- array( 'rev_id', 'rev_type', 'tree_rev_descendant_id', 'header_workflow_id' ),
- array( 'rev_id > ' . $dbr->addQuotes( $revId ) ),
+ [ 'flow_revision', 'flow_tree_revision', 'flow_header_revision' ],
+ [ 'rev_id', 'rev_type', 'tree_rev_descendant_id', 'header_workflow_id' ],
+ [ 'rev_id > ' . $dbr->addQuotes( $revId ) ],
__METHOD__,
- array( 'ORDER BY' => 'rev_id ASC', 'LIMIT' => $this->mBatchSize ),
- array(
- 'flow_tree_revision' => array( 'LEFT JOIN', 'rev_id=tree_rev_id' ),
- 'flow_header_revision' => array( 'LEFT JOIN', 'rev_id=header_rev_id' )
- )
+ [ 'ORDER BY' => 'rev_id ASC', 'LIMIT' => $this->mBatchSize ],
+ [
+ 'flow_tree_revision' => [ 'LEFT JOIN', 'rev_id=tree_rev_id' ],
+ 'flow_header_revision' => [ 'LEFT JOIN', 'rev_id=header_rev_id' ]
+ ]
);
if ( $res ) {
@@ -82,8 +83,8 @@ class FlowUpdateRevisionTypeId extends LoggedUpdateMaintenance {
$res = $dbw->update(
'flow_revision',
- array( 'rev_type_id' => $revTypeId ),
- array( 'rev_id' => $revId ),
+ [ 'rev_type_id' => $revTypeId ],
+ [ 'rev_id' => $revId ],
__METHOD__
);
if ( !$res ) {
@@ -102,4 +103,4 @@ class FlowUpdateRevisionTypeId extends LoggedUpdateMaintenance {
}
$maintClass = 'FlowUpdateRevisionTypeId';
-require_once( DO_MAINTENANCE );
+require_once DO_MAINTENANCE;
diff --git a/Flow/maintenance/FlowUpdateUserWiki.php b/Flow/maintenance/FlowUpdateUserWiki.php
index 1f208897..5160f16b 100644
--- a/Flow/maintenance/FlowUpdateUserWiki.php
+++ b/Flow/maintenance/FlowUpdateUserWiki.php
@@ -6,9 +6,9 @@ use Flow\Model\PostRevision;
$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";
/**
* Update all xxx_user_wiki field to have the correct wiki name
@@ -25,6 +25,7 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Update xxx_user_wiki field in tables: flow_workflow, flow_tree_revision, flow_revision";
+ $this->requireExtension( 'Flow' );
$this->setBatchSize( 300 );
}
@@ -37,7 +38,6 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
* empty *_user_id and *_user_ip, but this doesn't hurt. Alternatively, we could
* add a check user_id != 0 and user_ip is not null to the query, but this will
* result in more db queries
- *
*/
protected function doDBUpdates() {
$id = '';
@@ -54,13 +54,13 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
while ( $count == $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_workflow' ),
- array( 'workflow_wiki', 'workflow_id', 'workflow_type' ),
- array(
+ [ 'flow_workflow' ],
+ [ 'workflow_wiki', 'workflow_id', 'workflow_type' ],
+ [
'workflow_id > ' . $dbr->addQuotes( $id ),
- ),
+ ],
__METHOD__,
- array( 'ORDER BY' => 'workflow_id ASC', 'LIMIT' => $this->mBatchSize )
+ [ 'ORDER BY' => 'workflow_id ASC', 'LIMIT' => $this->mBatchSize ]
);
if ( $res ) {
foreach ( $res as $row ) {
@@ -96,15 +96,15 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
while ( $count == $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_header_revision', 'flow_revision' ),
- array( 'rev_id', 'rev_type' ),
- array(
+ [ 'flow_header_revision', 'flow_revision' ],
+ [ 'rev_id', 'rev_type' ],
+ [
'rev_id > ' . $dbr->addQuotes( $id ),
'header_rev_id = rev_id',
'header_workflow_id' => $workflow->getId()->getBinary()
- ),
+ ],
__METHOD__,
- array( 'ORDER BY' => 'header_rev_id ASC', 'LIMIT' => $this->mBatchSize )
+ [ 'ORDER BY' => 'header_rev_id ASC', 'LIMIT' => $this->mBatchSize ]
);
if ( $res ) {
foreach ( $res as $row ) {
@@ -133,14 +133,14 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
while ( $count == $this->mBatchSize ) {
$count = 0;
$res = $dbr->select(
- array( 'flow_topic_list' ),
- array( 'topic_id' ),
- array(
+ [ 'flow_topic_list' ],
+ [ 'topic_id' ],
+ [
'topic_list_id' => $workflow->getId()->getBinary(),
'topic_id > ' . $dbr->addQuotes( $id ),
- ),
+ ],
__METHOD__,
- array( 'ORDER BY' => 'topic_id ASC', 'LIMIT' => $this->mBatchSize )
+ [ 'ORDER BY' => 'topic_id ASC', 'LIMIT' => $this->mBatchSize ]
);
if ( $res ) {
$index = 0;
@@ -195,14 +195,14 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
$dbw = Container::get( 'db.factory' )->getDB( DB_MASTER );
$res = $dbw->update(
'flow_revision',
- array(
+ [
'rev_user_wiki' => $wiki,
'rev_mod_user_wiki' => $wiki,
'rev_edit_user_wiki' => $wiki,
- ),
- array(
+ ],
+ [
'rev_id' => $revision->getRevisionId()->getBinary(),
- ),
+ ],
__METHOD__
);
if ( !$res ) {
@@ -213,12 +213,12 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
if ( $type === 'post' ) {
$res = $dbw->update(
'flow_tree_revision',
- array(
+ [
'tree_orig_user_wiki' => $wiki,
- ),
- array(
+ ],
+ [
'tree_rev_id' => $revision->getRevisionId()->getBinary(),
- ),
+ ],
__METHOD__
);
if ( !$res ) {
@@ -226,7 +226,6 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
}
$this->checkForSlave();
}
-
}
private function checkForSlave() {
@@ -250,4 +249,4 @@ class FlowUpdateUserWiki extends LoggedUpdateMaintenance {
}
$maintClass = "FlowUpdateUserWiki";
-require_once( DO_MAINTENANCE );
+require_once DO_MAINTENANCE;
diff --git a/Flow/maintenance/FlowUpdateWorkflowPageId.php b/Flow/maintenance/FlowUpdateWorkflowPageId.php
index 7ff32a12..a7aad9a2 100644
--- a/Flow/maintenance/FlowUpdateWorkflowPageId.php
+++ b/Flow/maintenance/FlowUpdateWorkflowPageId.php
@@ -2,14 +2,15 @@
use Flow\Container;
use Flow\Model\UUID;
+use Flow\Model\Workflow;
use Flow\OccupationController;
$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
- $IP = dirname( __FILE__ ) . '/../../..';
+ $IP = __DIR__ . '/../../..';
}
-require_once( "$IP/maintenance/Maintenance.php" );
-require_once __DIR__ . "/../../Echo/includes/BatchRowUpdate.php";
+require_once "$IP/maintenance/Maintenance.php";
+require_once "$IP/includes/utils/RowUpdateGenerator.php";
/**
* In some cases we have created workflow instances before the related Title
@@ -21,6 +22,7 @@ class FlowUpdateWorkflowPageId extends LoggedUpdateMaintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Update workflow_page_id with the page id of its specified ns/title";
+ $this->requireExtension( 'Flow' );
$this->setBatchSize( 300 );
}
@@ -33,20 +35,20 @@ class FlowUpdateWorkflowPageId extends LoggedUpdateMaintenance {
$dbw = Container::get( 'db.factory' )->getDB( DB_MASTER );
- $it = new EchoBatchRowIterator(
+ $it = new BatchRowIterator(
$dbw,
'flow_workflow',
'workflow_id',
$this->mBatchSize
);
- $it->setFetchColumns( array( '*' ) );
- $it->addConditions( array(
- 'workflow_wiki' => wfWikiId(),
- ) );
+ $it->setFetchColumns( [ '*' ] );
+ $it->addConditions( [
+ 'workflow_wiki' => wfWikiID(),
+ ] );
$gen = new WorkflowPageIdUpdateGenerator( $wgLang );
- $writer = new EchoBatchRowWriter( $dbw, 'flow_workflow', $wgFlowCluster );
- $updater = new EchoBatchRowUpdate( $it, $writer, $gen );
+ $writer = new BatchRowWriter( $dbw, 'flow_workflow', $wgFlowCluster );
+ $updater = new BatchRowUpdate( $it, $writer, $gen );
$updater->execute();
@@ -64,13 +66,14 @@ class FlowUpdateWorkflowPageId extends LoggedUpdateMaintenance {
* Looks at rows from the flow_workflow table and returns an update
* for the workflow_page_id field if necessary.
*/
-class WorkflowPageIdUpdateGenerator implements EchoRowUpdateGenerator {
+class WorkflowPageIdUpdateGenerator implements RowUpdateGenerator {
/**
* @var Language|StubUserLang
*/
protected $lang;
protected $fixedCount = 0;
- protected $failed = array();
+ protected $failures = [];
+ protected $warnings = [];
/**
* @param Language|StubUserLang $lang
@@ -93,48 +96,66 @@ class WorkflowPageIdUpdateGenerator implements EchoRowUpdateGenerator {
// at some point, we failed to create page entries for new workflows: only
// create that page if the workflow was stored with a 0 page id (otherwise,
// we could mistake the $title for a deleted page)
- if ( $row->workflow_page_id === 0 && $title->getArticleID() === 0 ) {
- // build workflow object (yes, loading them piecemeal is suboptimal, but
- // this is just a one-time script; considering the alternative is
- // creating a derivative EchoBatchRowIterator that returns workflows,
- // it doesn't really matter)
- $storage = Container::get( 'storage' );
- $workflow = $storage->get( 'Workflow', UUID::create( $row->workflow_id ) );
-
- try {
- /** @var OccupationController $occupationController */
- $occupationController = Container::get( 'occupation_controller' );
- $occupationController->allowCreation( $title, $occupationController->getTalkpageManager() );
- $occupationController->ensureFlowRevision( new Article( $title ), $workflow );
-
- // force article id to be refetched from db
- $title->getArticleID( Title::GAID_FOR_UPDATE );
- } catch ( \Exception $e ) {
- // catch all exception to keep going with the rest we want to
- // iterate over, we'll report on the failed entries at the end
- $this->failed[] = $row;
+ if ( (int)$row->workflow_page_id === 0 && $title->getArticleID() === 0 ) {
+ $workflow = Workflow::fromStorageRow( (array)$row );
+ $status = $this->createPage( $title, $workflow );
+ if ( !$status->isGood() ) {
+ // just warn when we failed to create the page, but keep this code
+ // going and see if we manage to associate the workflow anyways
+ // (or if that fails, we'll also get an error there)
+ $this->warnings[] = $status->getMessage()->text();
}
}
// re-associate the workflow with the correct page; only if a page exists
- if ( $title->getArticleID() !== 0 && $title->getArticleID() !== (int) $row->workflow_page_id ) {
+ if ( $title->getArticleID() !== 0 && $title->getArticleID() !== (int)$row->workflow_page_id ) {
// This makes the assumption the page has not moved or been deleted?
++$this->fixedCount;
- return array(
+ return [
'workflow_page_id' => $title->getArticleID(),
- );
+ ];
} elseif ( !$row->workflow_page_id ) {
- // No id exists for this workflow?
- $this->failed[] = $row;
+ // No id exists for this workflow? (reason should likely show up in $this->warnings)
+ $this->failures[] = $row;
}
- return array();
+ return [];
+ }
+
+ /**
+ * @param Title $title
+ * @param Workflow $workflow
+ * @return Status
+ */
+ protected function createPage( Title $title, $workflow ) {
+ /** @var OccupationController $occupationController */
+ $occupationController = Container::get( 'occupation_controller' );
+
+ try {
+ $status = $occupationController->safeAllowCreation( $title, $occupationController->getTalkpageManager() );
+ $status2 = $occupationController->ensureFlowRevision( new Article( $title ), $workflow );
+
+ $status->merge( $status2 );
+ } catch ( \Exception $e ) {
+ // "convert" exception into Status
+ $message = new RawMessage( $e->getMessage() );
+ $status = Status::newFatal( $message );
+ }
+
+ if ( $status->isGood() ) {
+ // force article id to be refetched from db
+ $title->getArticleID( Title::GAID_FOR_UPDATE );
+ }
+
+ return $status;
}
public function report() {
- return "Updated {$this->fixedCount} workflows\nFailed: " . count( $this->failed ) . "\n\n" . print_r( $this->failed, true );
+ return "Updated {$this->fixedCount} workflows\n\n" .
+ "Warnings: " . count( $this->warnings ) . "\n" . print_r( $this->warnings, true ) . "\n\n" .
+ "Failed: " . count( $this->failures ) . "\n" . print_r( $this->failures, true );
}
}
$maintClass = "FlowUpdateWorkflowPageId";
-require_once( DO_MAINTENANCE );
+require_once DO_MAINTENANCE;
diff --git a/Flow/maintenance/MaintenanceDebugLogger.php b/Flow/maintenance/MaintenanceDebugLogger.php
index 375f537a..e45cefc1 100644
--- a/Flow/maintenance/MaintenanceDebugLogger.php
+++ b/Flow/maintenance/MaintenanceDebugLogger.php
@@ -23,7 +23,7 @@ class MaintenanceDebugLogger extends Psr\Log\AbstractLogger {
public function __construct( Maintenance $maintenance ) {
$this->maintenance = $maintenance;
- $this->logLevelPosition = array(
+ $this->logLevelPosition = [
LogLevel::EMERGENCY => 1,
LogLevel::ALERT => 2,
LogLevel::CRITICAL => 3,
@@ -32,10 +32,9 @@ class MaintenanceDebugLogger extends Psr\Log\AbstractLogger {
LogLevel::NOTICE => 6,
LogLevel::INFO => 7,
LogLevel::DEBUG => 8
- );
+ ];
}
-
/**
* @param string $level A LogLevel constant. Logged messages less
* severe than this level will not be output.
@@ -50,7 +49,7 @@ class MaintenanceDebugLogger extends Psr\Log\AbstractLogger {
/**
* {@inheritDoc}
*/
- public function log( $level, $message, array $context = array() ) {
+ public function log( $level, $message, array $context = [] ) {
$position = $this->logLevelPosition[$level];
if ( $position > $this->maxLevel ) {
return;
diff --git a/Flow/maintenance/benchUuidTimestampConversion.php b/Flow/maintenance/benchUuidTimestampConversion.php
index b0450388..cd408f19 100644
--- a/Flow/maintenance/benchUuidTimestampConversion.php
+++ b/Flow/maintenance/benchUuidTimestampConversion.php
@@ -23,65 +23,65 @@ class BenchUuidConversions extends \Benchmarker {
// benchmarker requires we pass an object
$id = UUID::create();
- $this->bench( array(
- array(
- 'function' => array( $id, 'bin2hex' ),
- 'args' => array( $binary ),
- ),
- array(
- 'function' => array( $id, 'alnum2hex' ),
- 'args' => array( $alpha ),
- ),
- array(
- 'function' => array( $id, 'hex2bin' ),
- 'args' => array( $hex ),
- ),
- array(
- 'function' => array( $id, 'hex2alnum' ),
- 'args' => array( $hex ),
- ),
- array(
- 'function' => array( $id, 'hex2timestamp' ),
- 'args' => array( $hex ),
- ),
- array(
- 'function' => array( $this, 'oldhex2timestamp' ),
- 'args' => array( $hex ),
- ),
- array(
- 'function' => array( $this, 'oldalphadecimal2timestamp' ),
- 'args' => array( $alpha ),
- ),
- array(
- 'function' => array( $this, 'case1' ),
- 'args' => array( $binary ),
- ),
- array(
- 'function' => array( $this, 'case2' ),
- 'args' => array( $binary ),
- ),
- array(
- 'function' => array( $this, 'case3' ),
- 'args' => array( $alpha ),
- ),
- array(
- 'function' => array( $this, 'case4' ),
- 'args' => array( $alpha ),
- ),
- ) );
+ $this->bench( [
+ [
+ 'function' => [ $id, 'bin2hex' ],
+ 'args' => [ $binary ],
+ ],
+ [
+ 'function' => [ $id, 'alnum2hex' ],
+ 'args' => [ $alpha ],
+ ],
+ [
+ 'function' => [ $id, 'hex2bin' ],
+ 'args' => [ $hex ],
+ ],
+ [
+ 'function' => [ $id, 'hex2alnum' ],
+ 'args' => [ $hex ],
+ ],
+ [
+ 'function' => [ $id, 'hex2timestamp' ],
+ 'args' => [ $hex ],
+ ],
+ [
+ 'function' => [ $this, 'oldhex2timestamp' ],
+ 'args' => [ $hex ],
+ ],
+ [
+ 'function' => [ $this, 'oldalphadecimal2timestamp' ],
+ 'args' => [ $alpha ],
+ ],
+ [
+ 'function' => [ $this, 'case1' ],
+ 'args' => [ $binary ],
+ ],
+ [
+ 'function' => [ $this, 'case2' ],
+ 'args' => [ $binary ],
+ ],
+ [
+ 'function' => [ $this, 'case3' ],
+ 'args' => [ $alpha ],
+ ],
+ [
+ 'function' => [ $this, 'case4' ],
+ 'args' => [ $alpha ],
+ ],
+ ] );
$this->output( $this->getFormattedResults() );
}
public function oldhex2timestamp( $hex ) {
- $bits = wfBaseConvert( $hex, 16, 2, 88 );
- $msTimestamp = wfBaseConvert( substr( $bits, 0, 46 ), 2, 10 );
+ $bits = \Wikimedia\base_convert( $hex, 16, 2, 88 );
+ $msTimestamp = \Wikimedia\base_convert( substr( $bits, 0, 46 ), 2, 10 );
return intval( $msTimestamp / 1000 );
}
public function oldalphadecimal2timestamp( $alpha ) {
- $bits = wfBaseConvert( $alpha, 36, 2, 88 );
- $msTimestamp = wfBaseConvert( substr( $bits, 0, 46 ), 2, 10 );
+ $bits = \Wikimedia\base_convert( $alpha, 36, 2, 88 );
+ $msTimestamp = \Wikimedia\base_convert( substr( $bits, 0, 46 ), 2, 10 );
return intval( $msTimestamp / 1000 );
}
diff --git a/Flow/maintenance/compileLightncandy.php b/Flow/maintenance/compileLightncandy.php
index 86f4a1b3..211fa927 100644
--- a/Flow/maintenance/compileLightncandy.php
+++ b/Flow/maintenance/compileLightncandy.php
@@ -2,9 +2,9 @@
use Flow\TemplateHelper;
-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';
/**
* Populate the *_user_ip fields within flow. This only updates
@@ -17,6 +17,12 @@ class CompileLightncandy extends Maintenance {
/** @var Flow\TemplateHelper */
protected $lightncandy;
+ public function __construct() {
+ parent::__construct();
+
+ $this->requireExtension( 'Flow' );
+ }
+
public function execute() {
$dir = __DIR__ . '/../handlebars';
$this->lightncandy = new TemplateHelper( $dir, /* $forceRecompile = */ true );
@@ -59,4 +65,4 @@ class CompileLightncandy extends Maintenance {
}
$maintClass = 'CompileLightncandy'; // Tells it to run the class
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/convertAllLqtPages.php b/Flow/maintenance/convertAllLqtPages.php
index 2e75b70a..02898a59 100644
--- a/Flow/maintenance/convertAllLqtPages.php
+++ b/Flow/maintenance/convertAllLqtPages.php
@@ -1,16 +1,17 @@
<?php
use Flow\Container;
-use Flow\Import\FileImportSourceStore;
+use Flow\Import\SourceStore\FileImportSourceStore;
+use Flow\Import\SourceStore\FlowRevisionsDb as FlowRevisionsDBImportSourceStore;
use Flow\Import\LiquidThreadsApi\ConversionStrategy;
use Flow\Import\LiquidThreadsApi\LocalApiBackend;
use Flow\Utils\NamespaceIterator;
use Flow\Utils\PagesWithPropertyIterator;
use Psr\Log\LogLevel;
-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';
/**
* Converts all LiquidThreads pages on a wiki to Flow. When using the logfile
@@ -21,11 +22,27 @@ class ConvertAllLqtPages extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Converts LiquidThreads data to Flow data";
- $this->addOption( 'logfile', 'File to read and store associations between imported items and their sources. This is required for the import to be idempotent.', true, true );
+ $this->addOption( 'logfile', 'File to read and store associations between imported items and their sources. This is required for the import to be idempotent.', false, true );
+ $this->addOption( 'force-recovery-conversion', 'If a previous logfile was lost, this option can be set to attempt to map threads to topics that have already been imported to prevent doubles.' );
$this->addOption( 'debug', 'Include debug information with progress report' );
+ $this->requireExtension( 'Flow' );
}
public function execute() {
+ $logfile = $this->getOption( 'logfile' );
+ if ( $logfile ) {
+ $sourceStore = new FileImportSourceStore( $logfile );
+ } elseif ( $this->getOption( 'force-recovery-conversion' ) ) {
+ // fallback: if we don't have a sourcestore to go on, at least look
+ // at DB to figure out what's already imported...
+ $dbr = Container::get( 'db.factory' )->getDB( DB_SLAVE );
+ $sourceStore = new FlowRevisionsDBImportSourceStore( $dbr );
+ } else {
+ $this->error( 'Param logfile or force-recovery-conversion required!' );
+ $this->maybeHelp( true );
+ die( 1 );
+ }
+
$logger = new MaintenanceDebugLogger( $this );
if ( $this->getOption( 'debug' ) ) {
$logger->setMaximumLevel( LogLevel::DEBUG );
@@ -39,7 +56,7 @@ class ConvertAllLqtPages extends Maintenance {
$dbw = wfGetDB( DB_MASTER );
$strategy = new ConversionStrategy(
$dbw,
- new FileImportSourceStore( $this->getOption( 'logfile' ) ),
+ $sourceStore,
new LocalApiBackend( $talkpageManagerUser ),
Container::get( 'url_generator' ),
$talkpageManagerUser,
@@ -88,4 +105,4 @@ class ConvertAllLqtPages extends Maintenance {
}
$maintClass = "ConvertAllLqtPages";
-require_once ( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/convertLqtPageFromRemoteApiForTesting.php b/Flow/maintenance/convertLqtPageFromRemoteApiForTesting.php
index 25bdee97..8bdd7808 100644
--- a/Flow/maintenance/convertLqtPageFromRemoteApiForTesting.php
+++ b/Flow/maintenance/convertLqtPageFromRemoteApiForTesting.php
@@ -1,18 +1,13 @@
<?php
-use Flow\Import\FileImportSourceStore;
-use Flow\Import\LiquidThreadsApi\BaseConversionStrategy as LiquidThreadsApiBaseConversionStrategy;
-use Flow\Import\LiquidThreadsApi\RemoteConversionStrategy as LiquidThreadsApiRemoteConversionStrategy;
-use Flow\Import\LiquidThreadsApi\LocalApiBackend;
+use Flow\Import\SourceStore\FileImportSourceStore;
use Flow\Import\LiquidThreadsApi\RemoteApiBackend;
use Flow\Import\LiquidThreadsApi\ImportSource as LiquidThreadsApiImportSource;
-use Flow\Import\Postprocessor\LqtRedirector;
-use Flow\Import\Postprocessor\LqtNotifications;
use Psr\Log\LogLevel;
-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';
/**
* This is *only* for use in testing, not production. The primary purpose is to exercise
@@ -30,6 +25,7 @@ class ConvertLqtPageFromRemoteApiForTesting extends Maintenance {
$this->addOption( 'cacheremoteapidir', 'Cache remote api calls to the specified directory', true, true );
$this->addOption( 'logfile', 'File to read and store associations between imported items and their sources', true, true );
$this->addOption( 'debug', 'Include debug information to progress report' );
+ $this->requireExtension( 'Flow' );
}
public function execute() {
@@ -79,11 +75,11 @@ class ConvertLqtPageFromRemoteApiForTesting extends Maintenance {
$logger->info( "Starting LQT conversion of page $srcPageName" );
- $importer->import( $source, $dstTitle, $sourceStore );
+ $importer->import( $source, $dstTitle, $talkPageManagerUser, $sourceStore );
$logger->info( "Finished LQT conversion of page $srcPageName" );
}
}
$maintClass = "ConvertLqtPageFromRemoteApiForTesting";
-require_once ( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/convertLqtPageOnLocalWiki.php b/Flow/maintenance/convertLqtPageOnLocalWiki.php
index 3009c0da..98e90da0 100644
--- a/Flow/maintenance/convertLqtPageOnLocalWiki.php
+++ b/Flow/maintenance/convertLqtPageOnLocalWiki.php
@@ -1,19 +1,14 @@
<?php
use Flow\Container;
-use Flow\Import\FileImportSourceStore;
-use Flow\Import\NullImportSourceStore;
+use Flow\Import\SourceStore\FileImportSourceStore;
use Flow\Import\LiquidThreadsApi\ConversionStrategy as LiquidThreadsApiConversionStrategy;
use Flow\Import\LiquidThreadsApi\LocalApiBackend;
-use Flow\Import\LiquidThreadsApi\RemoteApiBackend;
-use Flow\Import\LiquidThreadsApi\ImportSource as LiquidThreadsApiImportSource;
-use Flow\Import\Postprocessor\LqtRedirector;
-use Flow\Import\Postprocessor\LqtNotifications;
use Psr\Log\LogLevel;
-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';
/**
* This is intended for use both in testing and in production. It converts a single LQT
@@ -26,13 +21,14 @@ class ConvertLqtPageOnLocalWiki extends Maintenance {
$this->addOption( 'srcpage', 'Page name of the source page to import from.', true, true );
$this->addOption( 'logfile', 'File to read and store associations between imported items and their sources', true, true );
$this->addOption( 'debug', 'Include debug information to progress report' );
+ $this->requireExtension( 'Flow' );
}
public function execute() {
$container = Container::getContainer();
// Workaround to try to help with memory problems (T108601). The extend is
// so all uses of memcache.local_buffered pick up the same alternative.
- $container->extend( 'memcache.local_buffered', function( $mlb, $c ) {
+ $container->extend( 'memcache.local_buffered', function ( $mlb, $c ) {
return $c['memcache.non_local_buffered'];
} );
@@ -79,13 +75,13 @@ class ConvertLqtPageOnLocalWiki extends Maintenance {
$logger->info( "Starting LQT conversion of page $srcPageName" );
$srcTitle = \Title::newFromText( $srcPageName );
- $converter->convertAll( array(
+ $converter->convertAll( [
$srcTitle,
- ) );
+ ] );
$logger->info( "Finished LQT conversion of page $srcPageName" );
}
}
$maintClass = "ConvertLqtPageOnLocalWiki";
-require_once ( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/convertNamespaceFromWikitext.php b/Flow/maintenance/convertNamespaceFromWikitext.php
index a8d6d72f..b070274a 100644
--- a/Flow/maintenance/convertNamespaceFromWikitext.php
+++ b/Flow/maintenance/convertNamespaceFromWikitext.php
@@ -1,11 +1,10 @@
<?php
use Flow\Utils\NamespaceIterator;
-use Psr\Log\NullLogger;
-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';
/**
* Converts a single namespace from wikitext talk pages to flow talk pages. Does not
@@ -16,7 +15,7 @@ class ConvertNamespaceFromWikitext extends Maintenance {
public function __construct() {
parent::__construct();
$this->mDescription = "Converts a single namespace of wikitext talk pages to Flow";
- $this->addArg( 'namespace', 'Name of the namespace to convert' );
+ $this->addArg( 'namespaceName', 'Name of the namespace to convert' );
$this->addOption(
'no-convert-templates',
'Comma-separated list of templates that indicate a page should not be converted',
@@ -25,12 +24,13 @@ class ConvertNamespaceFromWikitext extends Maintenance {
't'
);
$this->addOption(
- 'archive-pattern',
- 'Naming pattern for archive pages; %s for page title, %d for sequence number',
+ 'header-suffix',
+ 'Wikitext to add to the end of the header',
false, // not required
true, // takes argument
'a'
);
+ $this->requireExtension( 'Flow' );
}
public function execute() {
@@ -51,9 +51,9 @@ class ConvertNamespaceFromWikitext extends Maintenance {
}
$noConvertTemplates = explode( ',', $this->getOption( 'no-convert-templates', '' ) );
- if ( $noConvertTemplates === array( '' ) ) {
+ if ( $noConvertTemplates === [ '' ] ) {
// explode( ',', '' ) returns array( '' )
- $noConvertTemplates = array();
+ $noConvertTemplates = [];
}
// Convert to Title objects
foreach ( $noConvertTemplates as &$template ) {
@@ -69,17 +69,20 @@ class ConvertNamespaceFromWikitext extends Maintenance {
$logger = new MaintenanceDebugLogger( $this );
$dbw = wfGetDB( DB_MASTER );
+ $talkpageManager = FlowHooks::getOccupationController()->getTalkpageManager();
$converter = new \Flow\Import\Converter(
$dbw,
Flow\Container::get( 'importer' ),
$logger,
- FlowHooks::getOccupationController()->getTalkpageManager(),
+ $talkpageManager,
+
new Flow\Import\Wikitext\ConversionStrategy(
$wgParser,
- new Flow\Import\NullImportSourceStore(),
+ new Flow\Import\SourceStore\NullImportSourceStore(),
$logger,
+ $talkpageManager,
$noConvertTemplates,
- $this->getOption( 'archive-pattern', null )
+ $this->getOption( 'header-suffix', null )
)
);
@@ -98,4 +101,4 @@ class ConvertNamespaceFromWikitext extends Maintenance {
}
$maintClass = "ConvertNamespaceFromWikitext";
-require_once ( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/convertToText.php b/Flow/maintenance/convertToText.php
index 5a5b2236..8cff171d 100644
--- a/Flow/maintenance/convertToText.php
+++ b/Flow/maintenance/convertToText.php
@@ -1,10 +1,13 @@
<?php
-use Flow\Parsoid\Utils;
+use Flow\Model\AbstractRevision;
+use Flow\Import\LiquidThreadsApi\ApiBackend;
+use Flow\Import\LiquidThreadsApi\RemoteApiBackend;
+use Flow\Import\LiquidThreadsApi\LocalApiBackend;
-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';
class ConvertToText extends Maintenance {
/**
@@ -12,102 +15,136 @@ class ConvertToText extends Maintenance {
*/
protected $pageTitle;
+ /**
+ * @var ApiBackend
+ */
+ protected $api;
+
public function __construct() {
parent::__construct();
$this->mDescription = "Converts a specific Flow page to text";
- $this->addArg( 'page', 'The page to convert', true /*required*/ );
+ $this->addOption( 'page', 'The page to convert', true /*required*/ );
+ $this->addOption( 'remoteapi', 'The api of the wiki to convert the page from (or nothing, for local wiki)', false /*required*/ );
+
+ $this->requireExtension( 'Flow' );
}
public function execute() {
- $pageName = $this->getArg( 0 );
+ $pageName = $this->getOption( 'page' );
$this->pageTitle = Title::newFromText( $pageName );
- if ( ! $this->pageTitle ) {
+ if ( !$this->pageTitle ) {
$this->error( 'Invalid page title', true );
}
- $continue = true;
- $pagerParams = array( 'vtllimit' => 1 );
- $topics = array();
- $headerContent = '';
-
- $headerData = $this->flowApi( $this->pageTitle, 'view-header', array( 'vhformat' => 'wikitext' ), 'header' );
-
- $headerRevision = $headerData['header']['revision'];
- if ( isset( $headerRevision['content'] ) ) {
- $headerContent = $headerRevision['content'];
+ if ( $this->getOption( 'remoteapi' ) ) {
+ $this->api = new RemoteApiBackend( $this->getOption( 'remoteapi' ) );
+ } else {
+ $this->api = new LocalApiBackend();
}
- while( $continue ) {
+ $headerContent = $this->processHeader();
+
+ $continue = true;
+ $pagerParams = [ 'vtllimit' => 1 ];
+ $topics = [];
+ while ( $continue ) {
$continue = false;
- $flowData = $this->flowApi( $this->pageTitle, 'view-topiclist', $pagerParams, 'topiclist' );
+ $flowData = $this->flowApi(
+ $this->pageTitle,
+ 'view-topiclist',
+ $pagerParams + [ 'vtlformat' => 'wikitext', 'vtlsortby' => 'newest' ],
+ 'topiclist'
+ );
$topicListBlock = $flowData['topiclist'];
- foreach( $topicListBlock['roots'] as $rootPostId ) {
+ foreach ( $topicListBlock['roots'] as $rootPostId ) {
$revisionId = reset( $topicListBlock['posts'][$rootPostId] );
$revision = $topicListBlock['revisions'][$revisionId];
- $topicOutput = '==' . $revision['content']['content'] . '==' . "\n";
- $topicOutput .= $this->processPostCollection( $topicListBlock, $revision['replies'] );
-
- $topics[] = $topicOutput;
+ $topics[] = $this->processTopic( $topicListBlock, $revision );
}
- $paginationLinks = $topicListBlock['links']['pagination'];
- if ( isset( $paginationLinks['fwd'] ) ) {
- list( $junk, $query ) = explode( '?', $paginationLinks['fwd']['url'] );
- $queryParams = wfCGIToArray( $query );
-
- $pagerParams = array(
- 'vtloffset-id' => $queryParams['topiclist_offset-id'],
- 'vtloffset-dir' => 'fwd',
- 'vtloffset-limit' => '1',
- );
- $continue = true;
+ if ( isset( $topicListBlock['links']['pagination'] ) ) {
+ $paginationLinks = $topicListBlock['links']['pagination'];
+ if ( isset( $paginationLinks['fwd'] ) ) {
+ list( $junk, $query ) = explode( '?', $paginationLinks['fwd']['url'] );
+ $queryParams = wfCgiToArray( $query );
+
+ $pagerParams = [
+ 'vtloffset-id' => $queryParams['topiclist_offset-id'],
+ 'vtloffset-dir' => 'fwd',
+ 'vtloffset-limit' => '1',
+ ];
+ $continue = true;
+ }
}
}
- print $headerContent . implode( "\n", array_reverse( $topics ) );
+ print $headerContent . "\n\n" . implode( "\n", array_reverse( $topics ) );
}
/**
* @param Title $title
* @param string $submodule
* @param array $request
- * @param bool $requiredBlock
* @return array
* @throws MWException
*/
- public function flowApi( Title $title, $submodule, array $request, $requiredBlock = false ) {
- $request = new FauxRequest( $request + array(
+ protected function flowApi( Title $title, $submodule, array $request ) {
+ $result = $this->api->apiCall( $request + [
'action' => 'flow',
'submodule' => $submodule,
'page' => $title->getPrefixedText(),
- ) );
+ ] );
- $api = new ApiMain( $request );
- $api->execute();
+ return $result['flow'][$submodule]['result'];
+ }
- $flowData = $api->getResult()->getResultData( array( 'flow', $submodule, 'result' ) );
- if ( $flowData === null ) {
- throw new MWException( "API response has no Flow data" );
+ protected function processTopic( array $context, array $revision ) {
+ $topicOutput = $this->processTopicTitle( $revision );
+ $summaryOutput = isset( $revision['summary'] ) ? $this->processSummary( $context, $revision['summary'] ) : '';
+ $postsOutput = $this->processPostCollection( $context, $revision['replies'] ) . "\n\n";
+ $resolved = isset( $revision['moderateState'] ) && $revision['moderateState'] === AbstractRevision::MODERATED_LOCKED;
+
+ // check if "resolved" templates exist
+ $archiveTemplates = $this->pageExists( 'Template:Archive_top' ) && $this->pageExists( 'Template:Archive_bottom' );
+ $hatnoteTemplate = $this->pageExists( 'Template:Hatnote' );
+
+ if ( $archiveTemplates && $resolved ) {
+ return '{{Archive top|result=' . $summaryOutput . "|status=resolved}}\n\n" .
+ $topicOutput . $postsOutput . "{{Archive bottom}}\n\n";
+ } elseif ( $hatnoteTemplate && $summaryOutput ) {
+ return $topicOutput . '{{Hatnote|' . $summaryOutput . "}}\n\n" . $postsOutput;
+ } else {
+ // italicize summary, if there is any, to set it apart from posts
+ $summaryOutput = $summaryOutput ? "''" . $summaryOutput . "''\n\n" : '';
+ return $topicOutput . $summaryOutput . $postsOutput;
}
- $flowData = ApiResult::stripMetadata( $flowData );
+ }
- if( $requiredBlock !== false && ! isset( $flowData[$requiredBlock] ) ) {
- throw new MWException( "No $requiredBlock block in API response" );
- }
+ protected function loadUser( $id, $name ) {
+ $row = new stdClass;
+ $row->user_name = $name;
+ $row->user_id = $id;
+
+ return User::newFromRow( $row );
+ }
- return $flowData;
+ protected function processSummary( array $context, array $summary ) {
+ $topicTitle = Title::newFromText( $summary[ 'revision' ][ 'articleTitle' ] );
+ return $this->processMultiRevisions(
+ $this->getAllRevisions( $topicTitle, 'view-topic-summary', 'vts', 'topicsummary' )
+ );
}
- public function processPostCollection( array $context, array $collection, $indentLevel = 0 ) {
+ protected function processPostCollection( array $context, array $collection, $indentLevel = 0 ) {
$indent = str_repeat( ':', $indentLevel );
$output = '';
- foreach( $collection as $postId ) {
+ foreach ( $collection as $postId ) {
$revisionId = reset( $context['posts'][$postId] );
$revision = $context['revisions'][$revisionId];
@@ -116,23 +153,12 @@ class ConvertToText extends Maintenance {
continue;
}
- $user = User::newFromName( $revision['author']['name'], false );
- $postId = Flow\Model\UUID::create( $postId );
-
- $content = $revision['content']['content'];
- $contentFormat = $revision['content']['format'];
-
- if ( $contentFormat !== 'wikitext' ) {
- $content = Utils::convert( $contentFormat, 'wikitext', $content, $this->pageTitle );
- }
-
- $thisPost = $indent . trim( $content ) . ' ' .
- $this->getSignature( $user, $postId->getTimestamp() ) . "\n";
+ $thisPost = $indent . $this->processPost( $revision );
if ( $indentLevel > 0 ) {
- $thisPost = preg_replace( "/\n+/", "\n", $thisPost );
+ $thisPost = preg_replace( "/\n+/", "\n$indent", $thisPost );
}
- $output .= str_replace( "\n", "\n$indent", trim( $thisPost ) ) . "\n";
+ $output .= $thisPost . "\n";
if ( isset( $revision['replies'] ) ) {
$output .= $this->processPostCollection( $context, $revision['replies'], $indentLevel + 1 );
@@ -146,12 +172,44 @@ class ConvertToText extends Maintenance {
return $output;
}
- public function getSignature( $user, $timestamp ) {
- global $wgContLang, $wgParser;
+ protected function getSignature( array $user, $timestamp = false ) {
+ global $wgParser;
// Force unstub
StubObject::unstub( $wgParser );
+ if ( $user ) {
+ // create a bogus user for whom username & id is known, so we
+ // can generate a correct signature
+ $user = $this->loadUser( $user['id'], $user['name'] );
+
+ // nickname & fancysig are user options: unless we're on local wiki,
+ // we don't know these & can't load them to generate the signature
+ $nickname = $this->getOption( 'remoteapi' ) ? null : false;
+ $fancysig = $this->getOption( 'remoteapi' ) ? false : null;
+
+ // Parser::getUserSig can end calling `getCleanSignatures` on
+ // mOptions, which may not be set. Set a dummy options object so it
+ // doesn't fail (it'll initialise the requested value from a global
+ // anyway)
+ $options = new ParserOptions();
+ $old = $wgParser->Options( $options );
+ $wgParser->startExternalParse( $this->pageTitle, $options, Parser::OT_WIKI );
+ $signature = $wgParser->getUserSig( $user, $nickname, $fancysig );
+ $signature = $wgParser->mStripState->unstripBoth( $signature );
+ if ( $timestamp ) {
+ $signature .= ' ' . $this->formatTimestamp( $timestamp );
+ }
+ $wgParser->Options( $old );
+ return $signature;
+ } else {
+ return "[Unknown user]" . $timestamp ? ' ' . $this->formatTimestamp( $timestamp ) : '';
+ }
+ }
+
+ private function formatTimestamp( $timestamp ) {
+ global $wgContLang;
+
$timestamp = MWTimestamp::getLocalInstance( $timestamp );
$ts = $timestamp->format( 'YmdHis' );
$tzMsg = $timestamp->format( 'T' ); # might vary on DST changeover!
@@ -165,15 +223,115 @@ class ConvertToText extends Maintenance {
$tzMsg = $msg->text();
}
- $d = $wgContLang->timeanddate( $ts, false, false ) . " ($tzMsg)";
+ return $wgContLang->timeanddate( $ts, false, false ) . " ($tzMsg)";
+ }
- if ( $user ) {
- return $wgParser->getUserSig( $user, false, false ) . ' ' . $d;
- } else {
- return "[Unknown user] $d";
+ protected function pageExists( $pageName ) {
+ static $pages = [];
+ if ( !isset( $pages[$pageName] ) ) {
+ $result = $this->api->apiCall( [ 'action' => 'query', 'titles' => $pageName ] );
+ $pages[$pageName] = !isset( $result['query']['pages'][-1] );
+ }
+
+ return $pages[$pageName];
+ }
+
+ private function getAllRevisions( Title $pageTitle, $submodule, $prefix, $responseRoot, $params = [] ) {
+ $headerRevisions = [];
+ $revId = false;
+ do {
+ $params[ $prefix . 'format' ] = 'wikitext';
+ if ( $revId ) {
+ $params[ $prefix . 'revId' ] = $revId;
+ }
+ $headerData = $this->flowApi(
+ $pageTitle,
+ $submodule,
+ $params
+ );
+ if ( isset( $headerData[ $responseRoot ][ 'revision' ][ 'revisionId' ] ) ) {
+ $headerRevisions[] = $headerRevision = $headerData[ $responseRoot ][ 'revision' ];
+ $revId = $headerRevision[ 'previousRevisionId' ];
+ } else {
+ $revId = false;
+ }
+ } while ( $revId );
+ return $headerRevisions;
+ }
+
+ private function processHeader() {
+ return $this->processMultiRevisions(
+ $this->getAllRevisions( $this->pageTitle, 'view-header', 'vh', 'header' ),
+ false,
+ 'flow-edited-by-header'
+ );
+ }
+ private function processMultiRevisions(
+ $allRevisions, $sigForFirstAuthor = true, $msg = 'flow-edited-by',
+ $glueAfterContent = '', $glueBeforeAuthors = ' '
+ ) {
+ global $wgContLang;
+ if ( count( $allRevisions ) ) {
+ $firstRevision = end( $allRevisions );
+ $latestRevision = reset( $allRevisions );
+
+ // take the content from the first (most recent) revision
+ $content = $latestRevision['content']['content'];
+ $firstContributor = $firstRevision['author'];
+
+ // deduplicate authors
+ $otherContributors = [];
+ foreach ( $allRevisions as $revision ) {
+ $name = $revision['author']['name'];
+ $otherContributors[ $name ] = $revision['author'];
+ }
+
+ $formattedAuthors = '';
+ if ( $sigForFirstAuthor ) {
+ $formattedAuthors .= $this->getSignature( $firstContributor, $firstRevision['timestamp'] );
+ // remove first contributor from list of previous contributors
+ if ( isset( $otherContributors[ $firstContributor['name'] ] ) ) {
+ unset( $otherContributors[ $firstContributor['name'] ] );
+ }
+ }
+
+ if (
+ count( $otherContributors ) > 0 &&
+ ( count( $otherContributors ) > 1 || !isset( $otherContributors[ $firstContributor['name'] ] ) )
+ ) {
+ $signatures = array_map( [ $this, 'getSignature' ], $otherContributors );
+ $formattedAuthors .= ( $sigForFirstAuthor ? ' ' : '' ) . '(' .
+ wfMessage( $msg )->inContentLanguage()->params(
+ $wgContLang->commaList( $signatures )
+ )->text() . ')';
+ }
+
+ return $content . $glueAfterContent . ( $formattedAuthors === '' ? '' : $glueBeforeAuthors . $formattedAuthors );
}
+ return '';
}
+
+ private function getAllPostRevisions( $revision ) {
+ $topicTitle = Title::newFromText( $revision[ 'articleTitle' ] );
+ $response = $this->flowApi( $topicTitle, 'view-post-history', [ 'vphpostId' => $revision['postId'], 'vphformat' => 'wikitext' ] );
+ return $response['topic']['revisions'];
+ }
+
+ private function processPost( $revision ) {
+ return $this->processMultiRevisions( $this->getAllPostRevisions( $revision ) );
+ }
+
+ private function processTopicTitle( $revision ) {
+ return '==' . $this->processMultiRevisions(
+ $this->getAllPostRevisions( $revision ),
+ false,
+ 'flow-edited-by-topic-title',
+ '==',
+ "\n\n"
+ ) . "\n\n";
+ }
+
}
$maintClass = "ConvertToText";
-require_once( RUN_MAINTENANCE_IF_MAIN );
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/dumpBackup.php b/Flow/maintenance/dumpBackup.php
new file mode 100644
index 00000000..3115e983
--- /dev/null
+++ b/Flow/maintenance/dumpBackup.php
@@ -0,0 +1,130 @@
+<?php
+
+use Flow\Container;
+use Flow\Dump\Exporter;
+
+$maintPath = ( getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance'
+ : __DIR__ . '/../../../maintenance' );
+require_once $maintPath . '/Maintenance.php';
+require_once $maintPath . '/backup.inc';
+
+class FlowDumpBackup extends BackupDumper {
+ public function __construct( $args = null ) {
+ parent::__construct();
+
+ $this->addDescription( <<<TEXT
+This script dumps the Flow discussion database into an
+XML interchange wrapper format for export.
+
+It can either export only the current revision, or full history.
+
+Although the --full will export all public revisions, non-public revisions
+are removed, and the remaining revisions are renormalized to accomodate this.
+It is recommended that you keep database backups as well.
+
+XML output is sent to stdout; progress reports are sent to stderr.
+TEXT
+ );
+
+ $this->addOption( 'full', 'Dump all revisions of every description/post/summary' );
+ $this->addOption( 'current', 'Dump only the latest revision of every description/post/summary' );
+ $this->addOption( 'pagelist', 'Dump only pages of which the title is included in the file', false, true );
+
+ $this->addOption( 'start', 'Start from page_id n', false, true );
+ $this->addOption( 'end', 'Stop before page_id n (exclusive)', false, true );
+ $this->addOption( 'skip-header', 'Don\'t output the <mediawiki> header' );
+ $this->addOption( 'skip-footer', 'Don\'t output the </mediawiki> footer' );
+
+ $this->requireExtension( 'Flow' );
+
+ if ( $args ) {
+ $this->loadWithArgv( $args );
+ $this->processOptions();
+ }
+ }
+
+ public function execute() {
+ // Stop if Flow not enabled on the wiki
+ if ( !class_exists( 'FlowHooks' ) ) {
+ echo "Flow isn't enabled on this wiki.\n";
+ die( 1 );
+ }
+
+ $this->processOptions();
+
+ if ( $this->hasOption( 'full' ) ) {
+ $this->dump( WikiExporter::FULL );
+ } elseif ( $this->hasOption( 'current' ) ) {
+ $this->dump( WikiExporter::CURRENT );
+ } else {
+ $this->error( 'No valid action specified.', 1 );
+ }
+ }
+
+ /**
+ * @param int $history WikiExporter::FULL or WikiExporter::CURRENT
+ * @param int $text Unused, but exists for compat with parent
+ */
+ public function dump( $history, $text = WikiExporter::TEXT ) {
+ # Notice messages will foul up your XML output even if they're
+ # relatively harmless.
+ if ( ini_get( 'display_errors' ) ) {
+ ini_set( 'display_errors', 'stderr' );
+ }
+
+ $db = Container::get( 'db.factory' )->getDB( DB_SLAVE );
+ $exporter = new Exporter( $db, $history, Exporter::STREAM, Exporter::TEXT );
+ $exporter->setOutputSink( $this->sink );
+
+ if ( !$this->skipHeader ) {
+ $exporter->openStream();
+ }
+
+ $workflowIterator = $exporter->getWorkflowIterator( $this->pages, $this->startId, $this->endId );
+
+ $exporter->dump( $workflowIterator );
+
+ if ( !$this->skipFooter ) {
+ $exporter->closeStream();
+ }
+
+ $this->report( true );
+ }
+
+ public function processOptions() {
+ parent::processOptions();
+
+ // Evaluate options specific to this class
+ $this->reporting = !$this->hasOption( 'quiet' );
+
+ if ( $this->hasOption( 'pagelist' ) ) {
+ $filename = $this->getOption( 'pagelist' );
+ $pages = file( $filename );
+ if ( $pages === false ) {
+ $this->fatalError( "Unable to open file {$filename}\n" );
+ }
+ $pages = array_map( 'trim', $pages );
+ $this->pages = array_filter(
+ $pages,
+ function ( $x ) {
+ return $x !== '';
+ }
+ );
+ }
+
+ if ( $this->hasOption( 'start' ) ) {
+ $this->startId = intval( $this->getOption( 'start' ) );
+ }
+
+ if ( $this->hasOption( 'end' ) ) {
+ $this->endId = intval( $this->getOption( 'end' ) );
+ }
+
+ $this->skipHeader = $this->hasOption( 'skip-header' );
+ $this->skipFooter = $this->hasOption( 'skip-footer' );
+ }
+}
+
+$maintClass = 'FlowDumpBackup';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/maintenance/repair_missing_from_csv.php b/Flow/maintenance/repair_missing_from_csv.php
index 54c36c96..ce58756c 100644
--- a/Flow/maintenance/repair_missing_from_csv.php
+++ b/Flow/maintenance/repair_missing_from_csv.php
@@ -1,5 +1,10 @@
<?php
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
require_once "$IP/maintenance/commandLine.inc";
require_once "$IP/extensions/Flow/FlowActions.php";
@@ -10,11 +15,10 @@ if ( !is_file( $argv[1] ) ) {
die( 'Provided CSV file does not exist' );
}
$csv = fopen( $argv[1], "r" );
-if ( fgetcsv( $csv ) !== array( 'uuid', 'esurl', 'flags' ) ) {
+if ( fgetcsv( $csv ) !== [ 'uuid', 'esurl', 'flags' ] ) {
die( 'Provided CSV file does not have the expected header' );
}
-
$fixed = 0;
$dbw = Flow\Container::get( 'db.factory' )->getDB( DB_MASTER );
while ( $row = fgetcsv( $csv ) ) {
@@ -30,16 +34,15 @@ while ( $row = fgetcsv( $csv ) ) {
$uuid = Flow\Model\UUID::create( $uuid );
$dbw->update(
/* table */'flow_revision',
- /* set */ array(
+ /* set */ [
'rev_content' => $esUrl,
'rev_flags' => $flags,
- ),
- /* where */ array(
+ ],
+ /* where */ [
'rev_id' => $uuid->getBinary()
- )
+ ]
);
++$fixed;
}
echo "Updated $fixed revisions\n\n";
-
diff --git a/Flow/maintenance/repair_missing_revision_content.php b/Flow/maintenance/repair_missing_revision_content.php
index 90bf6db4..184f26ba 100644
--- a/Flow/maintenance/repair_missing_revision_content.php
+++ b/Flow/maintenance/repair_missing_revision_content.php
@@ -1,9 +1,14 @@
<?php
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
require_once "$IP/maintenance/commandLine.inc";
require_once "$IP/extensions/Flow/FlowActions.php";
-$moderationChangeTypes = array(
+$moderationChangeTypes = [
'hide-post',
'hide-topic',
'delete-post',
@@ -13,27 +18,27 @@ $moderationChangeTypes = array(
'lock-topic',
'restore-post',
'restore-topic',
-);
+];
-$plaintextChangeTypes = array(
+$plaintextChangeTypes = [
'edit-title',
'new-topic',
-);
+];
-$csvOutput = fopen( 'repair_results_' . wfWikiId() . '.csv', 'w' );
+$csvOutput = fopen( 'repair_results_' . wfWikiID() . '.csv', 'w' );
if ( !$csvOutput ) {
die( "Could not open results file\n" );
}
-fputcsv( $csvOutput, array( "uuid", "esurl", "flags" ) );
+fputcsv( $csvOutput, [ "uuid", "esurl", "flags" ] );
-$it = new EchoBatchRowIterator(
+$it = new BatchRowIterator(
Flow\Container::get( 'db.factory' )->getDB( DB_SLAVE ),
'flow_revision',
- array( 'rev_id' ),
+ [ 'rev_id' ],
10
);
-$it->addConditions( array( 'rev_user_wiki' => wfWikiId() ) );
-$it->setFetchColumns( array( 'rev_content', 'rev_content_length', 'rev_change_type', 'rev_parent_id' ) );
+$it->addConditions( [ 'rev_user_wiki' => wfWikiID() ] );
+$it->setFetchColumns( [ 'rev_content', 'rev_content_length', 'rev_change_type', 'rev_parent_id' ] );
$dbr = wfGetDB( DB_SLAVE );
$totalMissingConsidered = 0;
@@ -57,7 +62,7 @@ foreach ( $it as $batch ) {
$tsEscaped = $dbr->addQuotes( $uuid->getTimestamp( TS_MW ) );
$changeType = $rev->rev_change_type;
- while( is_string( $wgFlowActions[$changeType] ) ) {
+ while ( is_string( $wgFlowActions[$changeType] ) ) {
$changeType = $wgFlowActions[$changeType];
}
if ( in_array( $changeType, $moderationChangeTypes ) ) {
@@ -73,8 +78,8 @@ foreach ( $it as $batch ) {
$last = end( $after );
echo "Considering core revisions from " . $first->rev_timestamp . " to " . $last->rev_timestamp . "\n";
- $esIdsForCluster = array();
- foreach ( array( $before, $after ) as $results ) {
+ $esIdsForCluster = [];
+ foreach ( [ $before, $after ] as $results ) {
foreach ( $results as $row ) {
$parts = explode( '/', $row->old_text );
if ( isset( $parts[4] ) ) {
@@ -89,7 +94,7 @@ foreach ( $it as $batch ) {
}
// find any gaps in ES within this area
- $matches = $lengths = array();
+ $matches = $lengths = [];
$invalid = false;
$flags = 'utf-8,gzip,external';
@@ -103,7 +108,6 @@ foreach ( $it as $batch ) {
sort( $esIdsForCluster[$cluster] );
$lastId = reset( $esIdsForCluster[$cluster] );
-
foreach ( $esIdsForCluster[$cluster] as $id ) {
if ( $id === $lastId || $id === $lastId + 1 ) {
$lastId = $id;
@@ -120,11 +124,16 @@ foreach ( $it as $batch ) {
foreach ( $range as $possible ) {
$url = "DB://$cluster/$possible";
$content = gzinflate( ExternalStore::fetchFromURL( $url ) );
- if ( false !== @unserialize( $content ) ) {
+ MediaWiki\suppressWarnings();
+ $unserializedContent = unserialize( $content );
+ MediaWiki\restoreWarnings();
+ if ( false !== $unserializedContent ) {
// if it unserializes, its not our content
continue;
}
- $json = @json_decode( $content, true );
+ MediaWiki\suppressWarnings();
+ $json = json_decode( $content, true );
+ MediaWiki\restoreWarnings();
if ( $json && count( $json ) === 1 && isset( $json['flow-workflow'] ) ) {
// while technically possible to be a topic title, i'm almost
// certain this is a core revisions inserted by flow in the form
@@ -147,7 +156,7 @@ foreach ( $it as $batch ) {
}
}
if ( $doAppend ) {
- $matches[] = array( $url, $content, $flags );
+ $matches[] = [ $url, $content, $flags ];
}
} else {
$lengths[] = $len;
@@ -168,7 +177,7 @@ foreach ( $it as $batch ) {
list( $url, $content, $flags ) = reset( $matches );
echo "SINGLE DIRECT MATCH: $url : " . truncate( $content, 1024 ) . "\n";
++$totalCompleteMatch;
- fputcsv( $csvOutput, array( $uuid->getAlphadecimal(), $url, $flags ) );
+ fputcsv( $csvOutput, [ $uuid->getAlphadecimal(), $url, $flags ] );
} else {
echo "MULTIPLE POTENTIAL MATCHES:\n";
++$totalMultipleMatches;
@@ -188,9 +197,9 @@ if ( $multipleMatches ) {
// Grab the first key/value pair from $multipleMatches as our
// first matching group
$current = reset( $multipleMatches );
- $group = array(
+ $group = [
key( $multipleMatches ) => $current,
- );
+ ];
array_shift( $multipleMatches );
// Look for other revisions in $multipleMatches that matched at least
// one of the same pieces of ExternalStore data.
@@ -240,7 +249,7 @@ if ( $multipleMatches ) {
foreach ( array_keys( $group ) as $uuid ) {
$match = array_shift( $expectedMatches );
list( $url, $content, $flags ) = $match;
- fputcsv( $csvOutput, array( $uuid, $url, $flags ) );
+ fputcsv( $csvOutput, [ $uuid, $url, $flags ] );
--$totalMultipleMatches;
++$totalResolvedMultipleMatches;
}
@@ -260,39 +269,35 @@ echo "Found a match but invalid due to size of es gaps for $totalMatchButInvalid
echo "Resolved $totalResolvedMultipleMatches multiple matches (" . number_format( 100 * $totalResolvedMultipleMatches / $totalMissingConsidered ) . "%)\n";
function query_revisions( $dbr, $op, $tsEscaped ) {
-
$direction = $op[0] === '>' ? 'ASC' : 'DESC';
- $sql =
- "SELECT revision.rev_timestamp, text.old_text
- FROM revision
- JOIN text ON revision.rev_text_id = old_id
- LEFT JOIN revision parent ON parent.rev_id = revision.rev_parent_id
- WHERE revision.rev_timestamp $op $tsEscaped
- AND revision.rev_text_id <> parent.rev_text_id
- ORDER BY revision.rev_timestamp $direction
- LIMIT 10";
+ $sql = "SELECT revision.rev_timestamp, text.old_text " .
+ " FROM revision " .
+ " JOIN text ON revision.rev_text_id = old_id " .
+ "LEFT JOIN revision parent ON parent.rev_id = revision.rev_parent_id " .
+ " WHERE revision.rev_timestamp $op $tsEscaped " .
+ " AND revision.rev_text_id <> parent.rev_text_id " .
+ " ORDER BY revision.rev_timestamp $direction " .
+ " LIMIT 10";
$res = $dbr->query( $sql, __METHOD__ );
-return iterator_to_array( $res );
+ return iterator_to_array( $res );
}
-
function parsoid_to_wikitext( $content, $retry = 3 ) {
- static $cache = array();
+ static $cache = [];
$hash = md5( $content );
if ( isset( $cache[$hash] ) ) {
return $cache[$hash];
}
try {
- $wikitext = Flow\Parsoid\Utils::convert( 'html', 'wt', $content, Title::newMainPage() );
+ $wikitext = Flow\Conversion\Utils::convert( 'html', 'wt', $content, Title::newMainPage() );
return $cache[$hash] = $wikitext;
- } catch ( Flow\Exception\NoParsoidException $e ) {
+ } catch ( Flow\Exception\NoParserException $e ) {
echo "failed to convert to wikitext: " . truncate( $content, 1024 ) . "\n";
return $cache[$hash] = $content;
}
}
-
function truncate( $string, $length ) {
if ( strlen( $string ) > $length ) {
return substr( $string, 0, $length ) . '...';
diff --git a/Flow/maintenance/repair_missing_revision_content_from_parent.php b/Flow/maintenance/repair_missing_revision_content_from_parent.php
index e0537348..999d42fd 100644
--- a/Flow/maintenance/repair_missing_revision_content_from_parent.php
+++ b/Flow/maintenance/repair_missing_revision_content_from_parent.php
@@ -1,35 +1,40 @@
<?php
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+
require_once "$IP/maintenance/commandLine.inc";
require_once "$IP/extensions/Flow/FlowActions.php";
-$moderationChangeTypes = array(
- 'hide-post',
- 'hide-topic',
- 'delete-post',
- 'delete-topic',
- 'suppress-post',
- 'suppress-topic',
- 'lock-topic',
- 'restore-post',
- 'restore-topic',
-);
+$moderationChangeTypes = [
+ 'hide-post',
+ 'hide-topic',
+ 'delete-post',
+ 'delete-topic',
+ 'suppress-post',
+ 'suppress-topic',
+ 'lock-topic',
+ 'restore-post',
+ 'restore-topic',
+];
-$csvOutput = fopen( 'repair_results_from_parent_' . wfWikiId() . '.csv', 'w' );
+$csvOutput = fopen( 'repair_results_from_parent_' . wfWikiID() . '.csv', 'w' );
if ( !$csvOutput ) {
die( "Could not open results file\n" );
}
-fputcsv( $csvOutput, array( "uuid", "esurl", "flags" ) );
+fputcsv( $csvOutput, [ "uuid", "esurl", "flags" ] );
$dbr = Flow\Container::get( 'db.factory' )->getDB( DB_SLAVE );
-$it = new EchoBatchRowIterator(
+$it = new BatchRowIterator(
$dbr,
'flow_revision',
- array( 'rev_id' ),
+ [ 'rev_id' ],
10
);
-$it->addConditions( array( 'rev_user_wiki' => wfWikiId() ) );
-$it->setFetchColumns( array( 'rev_change_type', 'rev_parent_id' ) );
+$it->addConditions( [ 'rev_user_wiki' => wfWikiID() ] );
+$it->setFetchColumns( [ 'rev_change_type', 'rev_parent_id' ] );
$totalNullContentWithParent = 0;
$totalNullParentContent = 0;
@@ -44,7 +49,7 @@ foreach ( $it as $batch ) {
}
$changeType = $rev->rev_change_type;
- while( is_string( $wgFlowActions[$changeType] ) ) {
+ while ( is_string( $wgFlowActions[$changeType] ) ) {
$changeType = $wgFlowActions[$changeType];
}
if ( !in_array( $changeType, $moderationChangeTypes ) ) {
@@ -58,10 +63,10 @@ foreach ( $it as $batch ) {
++$totalNullContentWithParent;
$res = iterator_to_array( $dbr->select(
/* from */ 'flow_revision',
- /* select */ array( 'rev_content', 'rev_flags' ),
- /* where */ array(
+ /* select */ [ 'rev_content', 'rev_flags' ],
+ /* where */ [
'rev_id' => new \Flow\Model\UUIDBlob( $rev->rev_parent_id ),
- ),
+ ],
__FILE__
) );
// not likely ... but lets be careful
@@ -69,7 +74,7 @@ foreach ( $it as $batch ) {
echo "No parent found?\n";
$totalBadQueryResult++;
continue;
- } elseif ( count ( $res ) > 1 ) {
+ } elseif ( count( $res ) > 1 ) {
echo "Multiple parents found?\n";
$totalBadQueryResult++;
continue;
@@ -79,7 +84,7 @@ foreach ( $it as $batch ) {
$parentItem = ExternalStore::fetchFromURL( $parent->rev_content );
if ( $parentItem ) {
echo "MATCHED\n";
- fputcsv( $csvOutput, array( $uuid->getAlphadecimal(), $parent->rev_content, $parent->rev_flags ) );
+ fputcsv( $csvOutput, [ $uuid->getAlphadecimal(), $parent->rev_content, $parent->rev_flags ] );
++$totalMatched;
} else {
echo "Parent item is null\n";
@@ -88,7 +93,6 @@ foreach ( $it as $batch ) {
}
}
-
echo "Considered $totalNullContentWithParent revisions with parents and no content\n";
if ( $totalNullContentWithParent > 0 ) {
echo "Could not fix $totalNullParentContent (" . number_format( 100 * $totalNullParentContent / $totalNullContentWithParent ) . "%) due to parent not having content\n";
diff --git a/Flow/modules/contributions/base.js b/Flow/modules/contributions/base.js
index b2d44867..b56f7c04 100644
--- a/Flow/modules/contributions/base.js
+++ b/Flow/modules/contributions/base.js
@@ -19,13 +19,13 @@
// If that failed still run the onComplete, it will not trigger
// our handler and be a normal click this time.
mw.loader.using(
- [ 'ext.flow', 'ext.flow.mediawiki.ui.modal', 'mediawiki.ui.input' ],
+ [ 'ext.flow', 'mediawiki.ui.input' ],
onComplete,
onComplete
);
}
- $( document ).ready( function () {
+ $( function () {
$( '#bodyContent' ).one( 'click', '.flow-click-interactive', clickedFlowLink );
} );
-} )( jQuery, mediaWiki );
+}( jQuery, mediaWiki ) );
diff --git a/Flow/modules/editor/editors/ext.flow.editors.none.js b/Flow/modules/editor/editors/ext.flow.editors.none.js
index e42a6504..80589da5 100644
--- a/Flow/modules/editor/editors/ext.flow.editors.none.js
+++ b/Flow/modules/editor/editors/ext.flow.editors.none.js
@@ -11,17 +11,16 @@
* @param {string} [content='']
*/
mw.flow.editors.none = function ( $node, content ) {
+ var $editor = $node.closest( '.flow-editor' );
+
// Parent constructor
mw.flow.editors.none.parent.call( this );
- var $editor = $node.closest( '.flow-editor' );
-
// node the editor is associated with.
this.$node = $node;
- this.widget = new OO.ui.TextInputWidget( {
+ this.widget = new OO.ui.MultilineTextInputWidget( {
value: content || '',
- multiline: true,
autosize: true,
maxRows: 999,
placeholder: this.$node.attr( 'placeholder' )
diff --git a/Flow/modules/editor/editors/visualeditor/ext.flow.editors.visualeditor.js b/Flow/modules/editor/editors/visualeditor/ext.flow.editors.visualeditor.js
index e33d6284..2bff44d4 100644
--- a/Flow/modules/editor/editors/visualeditor/ext.flow.editors.visualeditor.js
+++ b/Flow/modules/editor/editors/visualeditor/ext.flow.editors.visualeditor.js
@@ -1,4 +1,4 @@
-( function ( $, mw, OO, ve ) {
+( function ( $, mw, OO ) {
'use strict';
/**
@@ -9,6 +9,8 @@
* @param {string} [content='']
*/
mw.flow.editors.visualeditor = function ( $node, content ) {
+ var modules;
+
// Parent constructor
mw.flow.editors.visualeditor.parent.call( this );
@@ -22,8 +24,12 @@
.prop( 'disabled', true )
.addClass( 'oo-ui-texture-pending' );
+ modules = [ 'ext.flow.visualEditor' ].concat(
+ mw.config.get( 'wgVisualEditorConfig' ).pluginModules.filter( mw.loader.getState )
+ );
+
// load dependencies & init editor
- mw.loader.using( 'ext.flow.visualEditor', $.proxy( this.init, this, content || '' ) );
+ mw.loader.using( modules, $.proxy( this.init, this, content || '' ) );
};
OO.inheritClass( mw.flow.editors.visualeditor, mw.flow.editors.AbstractEditor );
@@ -47,15 +53,15 @@
content = content || '';
// add i18n messages to VE
- ve.init.platform.addMessages( mw.messages.values );
+ ve.init.platform.addMessages( mw.messages.get() );
- this.target = new mw.flow.ve.Target();
+ this.target = ve.init.mw.targetFactory.create( 'flow' );
// Fix missing base URL
htmlDoc = ve.createDocumentFromHtml( content ); // HTMLDocument
- ve.init.mw.Target.static.fixBase( htmlDoc );
+ ve.init.mw.ArticleTarget.static.fixBase( htmlDoc );
- // Based on ve.init.mw.Target.prototype.setupSurface
+ // Based on ve.init.mw.ArticleTarget.prototype.setupSurface
this.dmDoc = ve.dm.converter.getModelFromDom( htmlDoc, {
lang: mw.config.get( 'wgVisualEditor' ).pageLanguageCode,
dir: mw.config.get( 'wgVisualEditor' ).pageLanguageDir
@@ -162,6 +168,8 @@
};
mw.flow.editors.visualeditor.prototype.moveCursorToEnd = function () {
+ var data, cursorPos;
+
if ( !this.target ) {
this.initCallbacks.push( function () {
this.moveCursorToEnd();
@@ -169,8 +177,8 @@
return;
}
- var data = this.target.surface.getModel().getDocument().data,
- cursorPos = data.getNearestContentOffset( data.getLength(), -1 );
+ data = this.target.surface.getModel().getDocument().data;
+ cursorPos = data.getNearestContentOffset( data.getLength(), -1 );
this.target.surface.getModel().setSelection( new ve.Range( cursorPos ) );
};
@@ -196,23 +204,13 @@
mw.flow.editors.visualeditor.static.isSupported = function () {
var isMobileTarget = ( mw.config.get( 'skin' ) === 'minerva' );
+ /* global VisualEditorSupportCheck */
return !!(
!isMobileTarget &&
-
- // ES5 support, from es5-skip.js
- ( function () {
- // This test is based on 'use strict',
- // which is inherited from the top-level function.
- return !this && !!Function.prototype.bind;
- }() ) &&
-
- // Since VE commit e2fab2f1ebf2a28f18b8ead08c478c4fc95cd64e, SVG is required
- document.createElementNS &&
- document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect &&
-
- // ve needs to be turned on as a valid editor
- mw.config.get( 'wgFlowEditorList' ).indexOf( 'visualeditor' ) !== -1
+ mw.loader.getState( 'ext.visualEditor.core' ) &&
+ mw.config.get( 'wgFlowEditorList' ).indexOf( 'visualeditor' ) !== -1 &&
+ window.VisualEditorSupportCheck && VisualEditorSupportCheck()
);
};
-}( jQuery, mediaWiki, OO, ve ) );
+}( jQuery, mediaWiki, OO ) );
diff --git a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js
index 4a6ba6a8..6a8c73d4 100644
--- a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js
+++ b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.CommandRegistry.js
@@ -23,7 +23,7 @@
new ve.ui.Command(
'flowSwitchEditor',
'flowSwitchEditor',
- 'switch', // method to call on action
+ 'switch', // method to call on action
{ args: [] } // arguments to pass to action
)
);
diff --git a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.js b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.js
index 159ef2f3..62d5c58b 100644
--- a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.js
+++ b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.js
@@ -9,24 +9,27 @@
* Flow-specific target, inheriting from the stand-alone target
*
* @class
- * @extends ve.init.sa.DesktopTarget
+ * @extends ve.init.mw.Target
*/
mw.flow.ve.Target = function FlowVeTarget() {
- mw.flow.ve.Target.parent.call(
- this,
- { toolbarConfig: { floatable: false } }
- );
+ mw.flow.ve.Target.parent.call( this, {
+ toolbarConfig: { actions: true, position: 'bottom' }
+ } );
+
+ // HACK: stop VE's education popups from appearing (T116643)
+ this.dummyToolbar = true;
};
- OO.inheritClass( mw.flow.ve.Target, ve.init.sa.DesktopTarget );
+ OO.inheritClass( mw.flow.ve.Target, ve.init.mw.Target );
// Static
+ mw.flow.ve.Target.static.name = 'flow';
+
mw.flow.ve.Target.static.toolbarGroups = [
{
type: 'list',
icon: 'textStyle',
- indicator: 'down',
title: OO.ui.deferMsg( 'visualeditor-toolbar-style-tooltip' ),
include: [ 'bold', 'italic' ],
forceExpand: [ 'bold', 'italic' ]
@@ -37,32 +40,55 @@
{ include: [ 'flowMention' ] }
];
- // FIXME this isn't supposed to be a global state thing, it's supposed to be
- // variable per EditorWidget instance
- if ( mw.flow.ui.WikitextEditorWidget.static.isSupported() ) {
- mw.flow.ve.Target.static.actionGroups = [
- { include: [ 'flowSwitchEditor' ] }
- ];
- }
+ // Allow pasting links
+ mw.flow.ve.Target.static.importRules = ve.copy( mw.flow.ve.Target.static.importRules );
+ mw.flow.ve.Target.static.importRules.external.blacklist = OO.simpleArrayDifference(
+ mw.flow.ve.Target.static.importRules.external.blacklist,
+ [ 'link/mwExternal' ]
+ );
+
+ // Static Methods
+ mw.flow.ve.Target.static.setSwitchable = function ( switchable ) {
+ // FIXME this isn't supposed to be a global state thing, it's supposed to be
+ // variable per EditorWidget instance
+
+ if ( switchable ) {
+ ve.ui.toolFactory.register( mw.flow.ui.MWEditModeVisualTool );
+ ve.ui.toolFactory.register( mw.flow.ui.MWEditModeSourceTool );
+ mw.flow.ve.Target.static.actionGroups = [ {
+ type: 'list',
+ icon: 'edit',
+ title: mw.msg( 'visualeditor-mweditmode-tooltip' ),
+ include: [ 'editModeVisual', 'editModeSource' ]
+ } ];
+ } else {
+ mw.flow.ve.Target.static.actionGroups = [];
+ }
+ };
// Methods
+ mw.flow.ve.Target.prototype.loadHtml = function ( html ) {
+ var doc = this.constructor.static.parseDocument( html );
+ this.documentReady( doc );
+ };
+
+ // These tools aren't available so don't bother generating them
+ mw.flow.ve.Target.prototype.generateCitationFeatures = function () {};
+
mw.flow.ve.Target.prototype.attachToolbar = function () {
- // HACK ve.ui.Surface appends a debugBar *after* itself instead of putting it
- // inside itself (T106927)
- // Work around this by appending the toolbar after the debugBar if it's there, and
- // after the surface otherwise.
- var surface = this.getToolbar().getSurface();
- ( surface.debugBar || surface ).$element.after( this.getToolbar().$element );
+ this.$element.after( this.getToolbar().$element );
};
mw.flow.ve.Target.prototype.setDisabled = function ( disabled ) {
- // TODO upstream this to ve.init.Target
var i, len;
for ( i = 0, len = this.surfaces.length; i < len; i++ ) {
- // T106908: ve.ui.Surface doesn't support setDisabled()
- this.surfaces[ i ][ disabled ? 'disable' : 'enable' ]();
+ this.surfaces[ i ].setDisabled( disabled );
}
};
+ // Registration
+
+ ve.init.mw.targetFactory.register( mw.flow.ve.Target );
+
}( mediaWiki, OO, ve ) );
diff --git a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.less b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.less
index 419df2ab..2f75f534 100644
--- a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.less
+++ b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.Target.less
@@ -1,17 +1,12 @@
@import 'mediawiki.mixins';
@import 'mediawiki.ui/variables';
-@import 'flow.variables';
+@import '../../../styles/flow.variables';
// TODO most of this should move to VisualEditorWidget.less once the old editor system
// has been removed
.flow-component {
.ve-init-target {
- border: 1px solid #CCC;
-
- &.flow-ui-focused {
- border-color: @colorProgressive;
- box-shadow: inset 0 0 0 2px @colorProgressive;
- }
+ border: 1px solid #c8ccd1;
}
.ve-ce-documentNode,
@@ -24,22 +19,13 @@
box-sizing: border-box;
}
- .ve-ui-surface {
- // This creates a space for the toolbar, a matching negative margin-top
- // shifts the toolbar into this location.
- // @todo where did this 40 come from, could it be calculated?
- padding-bottom: @editorToolbarHeight;
- }
-
.ve-ui-debugBar {
- /* Move above bottom toolbar */
- margin: -@editorToolbarHeight 0 @editorToolbarHeight;
padding: 4px 8px;
/* Make sure the surface doesn't overlay */
position: relative;
}
- .ve-ui-surface-placeholder {
- font-style: italic;
+ .ve-ui-overlay {
+ line-height: normal;
}
}
diff --git a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.UserCache.js b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.UserCache.js
index 2aa104c6..36e1716d 100644
--- a/Flow/modules/editor/editors/visualeditor/mw.flow.ve.UserCache.js
+++ b/Flow/modules/editor/editors/visualeditor/mw.flow.ve.UserCache.js
@@ -46,12 +46,13 @@
);
return xhr
.then( function ( data ) {
+ // The parent class wants data like { query: { pages: { userid: { data } } } }
+ var i, len, user, newData = {};
+
if ( !data.query || !data.query.users ) {
return data;
}
- // The parent class wants data like { query: { pages: { userid: { data } } } }
- var i, len, user, newData = {};
for ( i = 0, len = data.query.users.length; i < len; i++ ) {
user = data.query.users[ i ];
// Parent class needs .title
@@ -78,10 +79,10 @@
* @param {string|string[]} usernames One or more user names
*/
mw.flow.ve.UserCache.prototype.setAsExisting = function ( usernames ) {
+ var i, len, cacheData = {};
if ( typeof usernames === 'string' ) {
usernames = [ usernames ];
}
- var i, len, cacheData = {};
for ( i = 0, len = usernames.length; i < len; i++ ) {
cacheData[ usernames[ i ] ] = { missing: false, invalid: false };
}
diff --git a/Flow/modules/editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js b/Flow/modules/editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js
index 74d20786..b611ae50 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js
+++ b/Flow/modules/editor/editors/visualeditor/ui/actions/mw.flow.ve.ui.SwitchEditorAction.js
@@ -1,60 +1,60 @@
( function ( mw, OO, ve ) {
-/**
- * Action to switch from VisualEditor to the Wikitext editing interface
- * within Flow.
- *
- * @class
- * @extends ve.ui.Action
- *
- * @constructor
- * @param {ve.ui.Surface} surface Surface to act on
- */
-mw.flow.ve.ui.SwitchEditorAction = function MwFlowVeUiSwitchEditorAction( surface ) {
- // Parent constructor
- ve.ui.Action.call( this, surface );
-};
-
-/* Inheritance */
-
-OO.inheritClass( mw.flow.ve.ui.SwitchEditorAction, ve.ui.Action );
-
-/* Static Properties */
-
-/**
- * Name of this action
- *
- * @static
- * @property
- */
-mw.flow.ve.ui.SwitchEditorAction.static.name = 'flowSwitchEditor';
-
-/**
- * List of allowed methods for the action.
- *
- * @static
- * @property
- */
-mw.flow.ve.ui.SwitchEditorAction.static.methods = [ 'switch' ];
-
-/* Methods */
-
-/**
- * Switch to wikitext editing.
- *
- * @method
- */
-mw.flow.ve.ui.SwitchEditorAction.prototype.switch = function () {
- var $editor = this.surface.$element.closest( '.flow-editor' );
- if ( $editor.length ) {
- // Old editor
- mw.flow.editor.switchEditor( $editor.find( 'textarea' ), 'none' );
- } else {
- // New editor
- this.surface.emit( 'switchEditor' );
- }
-};
-
-ve.ui.actionFactory.register( mw.flow.ve.ui.SwitchEditorAction );
+ /**
+ * Action to switch from VisualEditor to the Wikitext editing interface
+ * within Flow.
+ *
+ * @class
+ * @extends ve.ui.Action
+ *
+ * @constructor
+ * @param {ve.ui.Surface} surface Surface to act on
+ */
+ mw.flow.ve.ui.SwitchEditorAction = function MwFlowVeUiSwitchEditorAction( surface ) {
+ // Parent constructor
+ ve.ui.Action.call( this, surface );
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.flow.ve.ui.SwitchEditorAction, ve.ui.Action );
+
+ /* Static Properties */
+
+ /**
+ * Name of this action
+ *
+ * @static
+ * @property
+ */
+ mw.flow.ve.ui.SwitchEditorAction.static.name = 'flowSwitchEditor';
+
+ /**
+ * List of allowed methods for the action.
+ *
+ * @static
+ * @property
+ */
+ mw.flow.ve.ui.SwitchEditorAction.static.methods = [ 'switch' ];
+
+ /* Methods */
+
+ /**
+ * Switch to wikitext editing.
+ *
+ * @method
+ */
+ mw.flow.ve.ui.SwitchEditorAction.prototype.switch = function () {
+ var $editor = this.surface.$element.closest( '.flow-editor' );
+ if ( $editor.length ) {
+ // Old editor
+ mw.flow.editor.switchEditor( $editor.find( 'textarea' ), 'none' );
+ } else {
+ // New editor
+ this.surface.emit( 'switchEditor' );
+ }
+ };
+
+ ve.ui.actionFactory.register( mw.flow.ve.ui.SwitchEditorAction );
}( mediaWiki, OO, ve ) );
diff --git a/Flow/modules/editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js b/Flow/modules/editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js
index 906a67eb..5e73bdfe 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js
+++ b/Flow/modules/editor/editors/visualeditor/ui/contextitem/mw.flow.ve.ui.MentionContextItem.js
@@ -44,7 +44,7 @@
/**
* Returns a short description emphasizing the relevant data (currently just the user name)
*
- * @return string User name
+ * @return {string} User name
*/
mw.flow.ve.ui.MentionContextItem.prototype.getDescription = function () {
var key = mw.flow.ve.ui.MentionInspector.static.templateParameterKey;
diff --git a/Flow/modules/editor/editors/visualeditor/ui/images/icons/flow-mention.svg b/Flow/modules/editor/editors/visualeditor/ui/images/icons/flow-mention.svg
index b5a70dbb..61ff7e90 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/images/icons/flow-mention.svg
+++ b/Flow/modules/editor/editors/visualeditor/ui/images/icons/flow-mention.svg
@@ -1,83 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- width="24"
- height="24"
- id="svg2">
- <defs
- id="defs4" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- transform="translate(0,-1028.3622)"
- id="layer1">
- <g
- transform="translate(0,-4)"
- id="g3048">
- <g
- transform="translate(-0.263648,0)"
- id="g3061">
- <g
- transform="translate(-13.472704,1038.1992)"
- id="g3">
- <polygon
- points="20,11 20,7 24,7 24,5 20,5 20,1 18,1 18,5 14,5 14,7 18,7 18,11 "
- id="polygon5" />
- </g>
- <g
- transform="translate(7.5,1035.8622)"
- id="g5-1">
- <g
- id="g7"
- style="fill:#000000;fill-opacity:1">
- <g
- id="g9"
- style="fill:#000000;fill-opacity:1">
- <g
- id="g11"
- style="fill:#000000;fill-opacity:1">
- <path
- d="M 9,9 C 6.7,9 4.8,7.1 4.8,4.7 4.8,2.3 6.7,0.5 9,0.5 c 2.3,0 4.2,1.9 4.2,4.2 C 13.2,7 11.4,9 9,9 z"
- id="path13"
- style="fill:#000000;fill-opacity:1" />
- </g>
- </g>
- </g>
- <g
- id="g15"
- style="fill:#000000;fill-opacity:1">
- <g
- id="g17"
- style="fill:#000000;fill-opacity:1">
- <g
- id="g19"
- style="fill:#000000;fill-opacity:1">
- <path
- d="m 16.5,16.5 -15,0 0,-0.6 c 0,-1.1 0.2,-2 0.5,-2.8 0.3,-0.8 0.8,-1.4 1.4,-2 C 4,10.6 4.8,10.2 5.7,9.9 L 6,9.8 6.4,10 c 0.8,0.5 1.7,0.8 2.7,0.8 0.9,0 1.9,-0.3 2.7,-0.8 L 12,9.8 12.3,9.9 c 0.9,0.3 1.6,0.7 2.3,1.2 0.6,0.5 1.1,1.2 1.4,2 0.3,0.8 0.5,1.7 0.5,2.8 z"
- id="path21"
- style="fill:#000000;fill-opacity:1" />
- </g>
- </g>
- </g>
- </g>
- </g>
- </g>
- </g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
+ <path d="M6.264 16.837v-4h4v-2h-4v-4h-2v4h-4v2h4v4zM16.236 12.5c-2.3 0-4.2-1.9-4.2-4.3s1.9-4.2 4.2-4.2c2.3 0 4.2 1.9 4.2 4.2 0 2.3-1.8 4.3-4.2 4.3zM23.736 20h-15v-.6c0-1.1.2-2 .5-2.8.3-.8.8-1.4 1.4-2 .6-.5 1.4-.9 2.3-1.2l.3-.1.4.2c.8.5 1.7.8 2.7.8.9 0 1.9-.3 2.7-.8l.2-.2.3.1c.9.3 1.6.7 2.3 1.2.6.5 1.1 1.2 1.4 2 .3.8.5 1.7.5 2.8z"/>
</svg>
diff --git a/Flow/modules/editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js b/Flow/modules/editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js
index 40f1cb48..562c073e 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js
+++ b/Flow/modules/editor/editors/visualeditor/ui/inspectors/mw.flow.ve.ui.MentionInspector.js
@@ -35,7 +35,7 @@
// Static
mw.flow.ve.ui.MentionInspector.static.name = 'flowMention';
- mw.flow.ve.ui.MentionInspector.static.icon = 'flow-mention';
+ mw.flow.ve.ui.MentionInspector.static.size = 'medium';
mw.flow.ve.ui.MentionInspector.static.title = OO.ui.deferMsg( 'flow-ve-mention-inspector-title' );
mw.flow.ve.ui.MentionInspector.static.modelClasses = [ ve.dm.MWTransclusionNode ];
@@ -214,7 +214,7 @@
if ( !inspector.selectedAt ) {
inspector.fragment = inspector.getFragment().collapseToEnd();
}
- inspector.transclusionModel.insertTransclusionNode( inspector.getFragment() );
+ inspector.transclusionModel.insertTransclusionNode( inspector.getFragment(), 'inline' );
// After insertion move cursor to end of template
inspector.fragment.collapseToEnd().select();
}
@@ -229,14 +229,7 @@
return new OO.ui.Process( deferred.promise() );
} else if ( action === 'remove' ) {
return new OO.ui.Process( function () {
- var doc, nodeRange;
-
- doc = surfaceModel.getDocument();
- nodeRange = this.selectedNode.getOuterRange();
-
- surfaceModel.change(
- ve.dm.Transaction.newFromRemoval( doc, nodeRange )
- );
+ this.getFragment().removeContent();
this.close( { action: action } );
}, this );
@@ -276,6 +269,7 @@
*
* @param {Object} [data] Inspector initial data
* @param {boolean} [data.selectAt] Select the '@' symbol to the left of the fragment
+ * @return {OO.ui.Process}
*/
mw.flow.ve.ui.MentionInspector.prototype.getSetupProcess = function ( data ) {
return mw.flow.ve.ui.MentionInspector.parent.prototype.getSetupProcess.call( this, data )
diff --git a/Flow/modules/editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less b/Flow/modules/editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less
index 7312a4c3..99b0bc03 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less
+++ b/Flow/modules/editor/editors/visualeditor/ui/mw.flow.ve.ui.Icons.less
@@ -1,5 +1,5 @@
@import 'mediawiki.mixins';
.oo-ui-icon-flow-mention {
- .background-image('images/icons/flow-mention.svg');
+ .background-image( 'images/icons/flow-mention.svg' );
}
diff --git a/Flow/modules/editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js b/Flow/modules/editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js
index 45d9d27e..d7464728 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js
+++ b/Flow/modules/editor/editors/visualeditor/ui/tools/mw.flow.ve.ui.MentionInspectorTool.js
@@ -29,7 +29,8 @@
/**
* Checks whether the model represents a user mention
*
- * @return boolean
+ * @param {ve.dm.Model} model
+ * @return {boolean}
*/
mw.flow.ve.ui.MentionInspectorTool.static.isCompatibleWith = function ( model ) {
return model instanceof ve.dm.MWTransclusionNode &&
diff --git a/Flow/modules/editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js b/Flow/modules/editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js
index 70c2689c..55b9c6c9 100644
--- a/Flow/modules/editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js
+++ b/Flow/modules/editor/editors/visualeditor/ui/widgets/mw.flow.ve.ui.MentionTargetInputWidget.js
@@ -1,4 +1,4 @@
-( function ( $, mw, OO, ve ) {
+( function ( $, mw, OO ) {
'use strict';
/**
@@ -6,7 +6,7 @@
*
* @class
* @extends OO.ui.TextInputWidget
- * @mixins OO.ui.LookupElement
+ * @mixins OO.ui.mixin.LookupElement
*
* @constructor
* @param {Object} [config] Configuration options
@@ -23,7 +23,7 @@
);
// Mixin constructor
- OO.ui.LookupElement.call( this, $.extend( { allowSuggestionsWhenEmpty: true }, config ) );
+ OO.ui.mixin.LookupElement.call( this, $.extend( { allowSuggestionsWhenEmpty: true }, config ) );
// Properties
this.username = null;
@@ -41,7 +41,7 @@
OO.inheritClass( mw.flow.ve.ui.MentionTargetInputWidget, OO.ui.TextInputWidget );
- OO.mixinClass( mw.flow.ve.ui.MentionTargetInputWidget, OO.ui.LookupElement );
+ OO.mixinClass( mw.flow.ve.ui.MentionTargetInputWidget, OO.ui.mixin.LookupElement );
/**
* Check if the value of the input corresponds to a username that exists.
@@ -63,7 +63,7 @@
// Then check the user exists
return mw.flow.ve.userCache.get( this.value ).then(
function ( user ) {
- return !user.missing;
+ return !user.missing && !user.invalid;
},
function () {
// If the API is down or behaving strangely, we shouldn't prevent
@@ -138,7 +138,7 @@
item = this.lookupMenu.getSelectedItem();
if ( !item ) {
- OO.ui.LookupElement.prototype.initializeLookupMenuSelection.call( this );
+ OO.ui.mixin.LookupElement.prototype.initializeLookupMenuSelection.call( this );
}
item = this.lookupMenu.getSelectedItem();
@@ -146,4 +146,4 @@
this.username = item.getData();
}
};
-}( jQuery, mediaWiki, OO, ve ) );
+}( jQuery, mediaWiki, OO ) );
diff --git a/Flow/modules/editor/ext.flow.editor.js b/Flow/modules/editor/ext.flow.editor.js
index 1a627495..76aae693 100644
--- a/Flow/modules/editor/ext.flow.editor.js
+++ b/Flow/modules/editor/ext.flow.editor.js
@@ -27,7 +27,7 @@
init: function () {
var editorList = mw.config.get( 'wgFlowEditorList' ),
- index = editorList.indexOf( mw.user.options.get( 'flow-editor' ) );
+ index = editorList.indexOf( 'none' );
// determine editor instance to use, depending on availability
mw.flow.editor.loadEditor( index );
@@ -50,6 +50,9 @@
editor = 'none';
}
+ // The following modules can be requested here:
+ // * ext.flow.editors.visualeditor
+ // * ext.flow.editors.none
mw.loader.using( 'ext.flow.editors.' + editor, function () {
// Some editors only work under certain circumstances
if ( !mw.flow.editors[ editor ].static.isSupported() ) {
@@ -66,14 +69,13 @@
* @return {jQuery.Promise} Will resolve once editor instance is loaded
*/
load: function ( $node, content ) {
- /**
- * When calling load(), loadEditor() may not yet have completed loading the
- * dependencies. To make sure it doesn't break, this will in interval,
- * check for it and only start loading once initialization is complete.
- *
- * @private
- */
- var tryLoad = function ( $node, content ) {
+ var interval,
+ deferred = $.Deferred();
+
+ // When calling load(), loadEditor() may not yet have completed loading the
+ // dependencies. To make sure it doesn't break, this will in interval,
+ // check for it and only start loading once initialization is complete.
+ function tryLoad( $node, content ) {
if ( mw.flow.editor.editor === null ) {
return;
} else {
@@ -86,8 +88,8 @@
}
deferred.resolve();
- },
- deferred = $.Deferred(),
+ }
+
interval = setInterval( $.proxy( tryLoad, this, $node, content ), 10 );
return deferred.promise();
@@ -155,6 +157,7 @@
$node.data( 'flow-editor', mw.flow.editor.editors.length )
.closest( '.flow-editor' ).addClass( 'flow-editor-' + mw.flow.editor.editor.static.name );
+ // eslint-disable-next-line new-cap
mw.flow.editor.editors.push( new mw.flow.editor.editor( $node, content ) );
return mw.flow.editor.getEditor( $node );
},
@@ -221,16 +224,20 @@
markPending( true );
+ // The following modules can be requested here:
+ // * ext.flow.editors.visualeditor
+ // * ext.flow.editors.none
return mw.loader.using( 'ext.flow.editors.' + desiredEditor )
.then( function () {
+ var content, oldFormat, newFormat;
+
if ( !mw.flow.editors[ desiredEditor ].static.isSupported() ) {
return $.Deferred().reject( 'editor-not-supported' );
}
- var content = editor.getRawContent(),
- oldFormat = editor.constructor.static.format,
- newFormat;
+ content = editor.getRawContent();
+ oldFormat = editor.constructor.static.format;
mw.flow.editor.editor = mw.flow.editors[ desiredEditor ];
newFormat = mw.flow.editor.editor.static.format;
diff --git a/Flow/modules/engine/components/board/base/flow-board-api-events.js b/Flow/modules/engine/components/board/base/flow-board-api-events.js
index f229c011..c00d06cf 100644
--- a/Flow/modules/engine/components/board/base/flow-board-api-events.js
+++ b/Flow/modules/engine/components/board/base/flow-board-api-events.js
@@ -10,7 +10,7 @@
* @constructor
* @param {jQuery} $container
*/
- function FlowBoardComponentApiEventsMixin( $container ) {
+ function FlowBoardComponentApiEventsMixin() {
// Bind event callbacks
this.bindNodeHandlers( FlowBoardComponentApiEventsMixin.UI.events );
}
@@ -99,40 +99,6 @@
} );
};
- /** @class FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers */
-
- /**
- * Before activating header, sends an overrideObject to the API to modify the request params.
- * @param {Event} event
- * @param {Object} info
- * @param {Object} queryMap
- * @return {Object}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditHeader = function ( event, info, queryMap ) {
- return $.extend( {}, queryMap, {
- submodule: 'view-header', // href submodule is edit-header
- vhformat: mw.flow.editor.getFormat() // href does not have this param
- } );
- };
-
- /**
- * Before activating topic, sends an overrideObject to the API to modify the request params.
- *
- * @param {Event} event
- * @param {Object} info
- * @param {Object} queryMap
- * @return {Object}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateEditTitle = function ( event, info, queryMap ) {
- // Use view-post API for topic as well; we only want this on
- // particular (title) post revision, not the full topic
- return $.extend( {}, queryMap, {
- submodule: 'view-post',
- vppostId: $( this ).closest( '.flow-topic' ).data( 'flow-id' ),
- vpformat: mw.flow.editor.getFormat()
- } );
- };
-
/**
* Adjusts query params to use global watch action, and specifies it should use a watch token.
* @param {Event} event
@@ -155,30 +121,6 @@
return params;
};
- /**
- * Before activating summarize topic, sends an overrideObject to the
- * API to modify the request params.
- * @param {Event} event
- * @param {Object} info
- * @param {Object} queryMap
- * @return {Object}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiPreHandlers.activateSummarizeTopic = function ( event, info, queryMap ) {
- if ( info.$target.find( 'form' ).length ) {
- // Form already open; cancel the old form
- var flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) );
- flowBoard.emitWithReturn( 'cancelForm', info.$target );
- return false;
- }
-
- return $.extend( {}, queryMap, {
- // href submodule is edit-topic-summary
- submodule: 'view-topic-summary',
- // href does not have this param
- vtsformat: mw.flow.editor.getFormat()
- } );
- };
-
//
// api callback handlers
//
@@ -194,7 +136,7 @@
* @param {jqXHR} jqxhr
* @return {jQuery.Promise}
*/
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.board = function ( info, data, jqxhr ) {
+ FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.board = function ( info, data ) {
var $rendered,
flowBoard = info.component,
dfd = $.Deferred();
@@ -223,146 +165,6 @@
};
/**
- * Renders the editable board header with the given API response.
- * @param {Object} info
- * @param {string} info.status "done" or "fail"
- * @param {jQuery} info.$target
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.activateEditHeader = function ( info, data, jqxhr ) {
- var $rendered,
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) ),
- $oldBoardNodes;
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default & edit conflict handled, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- // Change "header" to "header_edit" so that it loads up flow_block_header_edit
- data.flow[ 'view-header' ].result.header.type = 'header_edit';
-
- $rendered = $(
- flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
- 'flow_block_loop',
- { blocks: data.flow[ 'view-header' ].result }
- )
- ).children();
-
- // Set the cancel callback on this form so that it returns the old content back if needed
- flowBoard.emitWithReturn( 'addFormCancelCallback', $rendered.find( 'form' ), function () {
- flowBoard.reinitializeContainer( $oldBoardNodes );
- } );
-
- // Reinitialize the whole board with these nodes, and hold onto the replaced header
- $oldBoardNodes = flowBoard.reinitializeContainer( $rendered );
-
- mw.flow.editor.focus( $rendered.find( 'textarea' ) );
-
- return $.Deferred().resolve().promise();
- };
-
- /**
- * After submit of the board header edit form, process the new header data.
- * @param {Object} info (status:done|fail, $target: jQuery)
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.submitHeader = function ( info, data, jqxhr ) {
- var $rendered,
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) );
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default & edit conflict handled, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- return flowBoard.Api.apiCall( {
- action: 'flow',
- submodule: 'view-header',
- page: mw.config.get( 'wgPageName' )
- } ).done( function ( result ) {
- // SUPERHACK: Add an indicator for handlebars to know to load the partial from
- // the "old" system. This will go away when the OOUI widget in JS is operational
- result.flow[ 'view-header' ].result.header.oldSystem = true;
-
- // Render
- $rendered = $(
- flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
- 'flow_block_loop',
- { blocks: result.flow[ 'view-header' ].result }
- )
- ).children();
-
- // Reinitialize the whole board with these nodes
- flowBoard.reinitializeContainer( $rendered );
- } );
- };
-
- /**
- * Lock/unlock a topic, update the UI and trigger summarize.
- * @param {string} status
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.lockAndSummarizeTopic = function ( info, data ) {
- var flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) ),
- workflowId = $( this ).closest( '.flow-topic' ).data( 'flow-id' );
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default & edit conflict handled, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- function summarize( result ) {
- var root = result.topic.roots[ 0 ],
- revId = result.topic.posts[ root ][ 0 ],
- topic = result.topic.revisions[ revId ];
-
- return flowBoard.Api.apiCall( {
- action: 'flow',
- submodule: 'view-topic-summary',
- // Flow topic title, in Topic:<topicId> format (2600 is topic namespace id)
- page: ( new mw.Title( workflowId, 2600 ) ).getPrefixedDb(),
- vtsformat: mw.flow.editor.getFormat()
- } ).then( function ( data ) {
- var topicSummary = data.flow[ 'view-topic-summary' ].result.topicsummary;
-
- // skip summarize step when a topic with NO summary has been reopened
- if ( !topic.isLocked && !_hasSummary( topicSummary ) ) {
- return $.Deferred().resolve().promise();
- }
-
- return _activateSummarizeTopic(
- result.$topic.find( '.flow-topic-titlebar .flow-topic-summary-container' ),
- flowBoard,
- topicSummary,
- topic.isLocked ? 'lock' : 'unlock'
- );
- } );
- }
-
- return _flowBoardComponentRefreshTopic( info.$target, workflowId ).then( summarize );
- };
-
- /**
- * Checks if a topic summary object actually contains a summary.
- * @param topicSummary
- * @return {boolean}
- * @private
- */
- function _hasSummary( topicSummary ) {
- return !!( topicSummary &&
- topicSummary.revision &&
- topicSummary.revision.content &&
- topicSummary.revision.content.content );
- }
-
- /**
* @param {Object} info
* @param {string} info.status "done" or "fail"
* @param {jQuery} info.$target
@@ -370,7 +172,7 @@
* @param {jqXHR} jqxhr
* @return {jQuery.Promise}
*/
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.submitTopicTitle = function ( info, data, jqxhr ) {
+ FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.submitTopicTitle = function ( info, data ) {
if ( info.status !== 'done' ) {
// Error will be displayed by default & edit conflict handled, nothing else to wrap up
return $.Deferred().resolve().promise();
@@ -384,7 +186,6 @@
};
/**
- * After submitting a new topic, process the response.
* @param {Object} info
* @param {string} info.status "done" or "fail"
* @param {jQuery} info.$target
@@ -392,68 +193,7 @@
* @param {jqXHR} jqxhr
* @return {jQuery.Promise}
*/
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.newTopic = function ( info, data, jqxhr ) {
- var schemaName = $( this ).data( 'flow-eventlog-schema' ),
- funnelId = $( this ).data( 'flow-eventlog-funnel-id' ),
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) ),
- $stub;
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- flowBoard.logEvent( schemaName, { action: 'save-success', funnelId: funnelId } );
-
- flowBoard.emitWithReturn( 'cancelForm', $( this ).closest( 'form' ) );
-
- // remove focus - title input field may still have focus
- // (submitted via enter key), which it needs to lose:
- // the form will only re-activate if re-focused
- document.activeElement.blur();
-
- // _flowBoardComponentRefreshTopic relies on finding a .flow-topic node
- // to replace, so let's pretend to have one here!
- $stub = $( '<div class="flow-topic"><div></div></div>' ).prependTo( flowBoard.$container.find( '.flow-topics' ) );
- return _flowBoardComponentRefreshTopic( $stub.find( 'div' ), data.flow[ 'new-topic' ].committed.topiclist[ 'topic-id' ] );
- };
-
- /**
- * @param {Object} info (status:done|fail, $target: jQuery)
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.submitReply = function ( info, data, jqxhr ) {
- var $form = $( this ).closest( 'form' ),
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $form ),
- schemaName = $( this ).data( 'flow-eventlog-schema' ),
- funnelId = $( this ).data( 'flow-eventlog-funnel-id' );
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- flowBoard.logEvent( schemaName, { action: 'save-success', funnelId: funnelId } );
-
- // Execute cancel callback to destroy form
- flowBoard.emitWithReturn( 'cancelForm', $form );
-
- // Target should be flow-topic
- // @todo: add 3rd argument (target selector); there's no need to refresh entire topic
- return _flowBoardComponentRefreshTopic( info.$target, data.flow.reply.workflow );
- };
-
- /**
- * @param {Object} info
- * @param {string} info.status "done" or "fail"
- * @param {jQuery} info.$target
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.watchItem = function ( info, data, jqxhr ) {
+ FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.watchItem = function ( info, data ) {
var watchUrl, unwatchUrl,
watchType, watchLinkTemplate, $newLink,
$target = $( this ),
@@ -500,115 +240,18 @@
if ( data.watch[ 0 ].watched !== undefined ) {
// Successful watch: show tooltip
- flowBoard.emitWithReturn( 'showSubscribedTooltip', $newLink.find( '.mw-ui-icon' ), watchType );
+ flowBoard.emitWithReturn(
+ 'showSubscribedTooltip',
+ $newLink.find( '.mw-ui-anchor' ),
+ watchType,
+ $newLink.css( 'direction' ) === 'ltr' ? 'left' : 'right'
+ );
}
return $.Deferred().resolve().promise();
};
/**
- * Activate the editable summarize topic form with given api request
- * @param {Object} info (status:done|fail, $target: jQuery)
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.activateSummarizeTopic = function ( info, data, jqxhr ) {
- var flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $( this ) );
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- return _activateSummarizeTopic(
- info.$target,
- flowBoard,
- data.flow[ 'view-topic-summary' ].result.topicsummary,
- 'summarize'
- );
- };
-
- /**
- * After submit of the summarize topic edit form, process the new topic summary data.
- * @param {Object} info
- * @param {string} info.status "done" or "fail"
- * @param {jQuery} info.$target
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.summarizeTopic = function ( info, data, jqxhr ) {
- if ( info.status !== 'done' ) {
- // Error will be displayed by default, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- return _flowBoardComponentRefreshTopic(
- info.$target,
- data.flow[ 'edit-topic-summary' ].workflow,
- '.flow-topic-titlebar'
- );
- };
-
- /**
- * Shows the form for editing a topic title, it's not already showing.
- *
- * @param {Object} info (status:done|fail, $target: jQuery)
- * @param {Object} data
- * @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
- */
- FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.activateEditTitle = function ( info, data, jqxhr ) {
- var flowBoard, $form, cancelCallback,
- $link = $( this ),
- activeClass = 'flow-topic-title-activate-edit',
- rootBlock = data.flow[ 'view-post' ].result.topic,
- revision = rootBlock.revisions[ rootBlock.posts[ rootBlock.roots[ 0 ] ] ];
-
- if ( info.status !== 'done' ) {
- // Error will be displayed by default, nothing else to wrap up
- return $.Deferred().resolve().promise();
- }
-
- $form = info.$target.find( 'form' );
-
- if ( $form.length === 0 ) {
- // Add class to identify title is being edited (so we can hide the
- // current title in CSS)
- info.$target.addClass( activeClass );
-
- cancelCallback = function () {
- $form.remove();
- info.$target.removeClass( activeClass );
- };
-
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $link );
- $form = $( flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
- 'flow_edit_topic_title.partial',
- {
- actions: {
- edit: {
- url: $link.attr( 'href' )
- }
- },
- content: {
- content: revision.content.content
- },
- revisionId: revision.revisionId
- }
- ) ).children();
-
- flowBoard.emitWithReturn( 'addFormCancelCallback', $form, cancelCallback );
- $form.prependTo( info.$target );
- }
-
- $form.find( '.mw-ui-input' ).focus();
-
- return $.Deferred().resolve().promise();
- };
-
- /**
* Callback from the topic moderation dialog.
*/
FlowBoardComponentApiEventsMixin.UI.events.apiHandlers.moderateTopic = _genModerateHandler(
@@ -678,17 +321,19 @@
* @return {jQuery.Promise} return.return
*/
function _genModerateHandler( action, successCallback ) {
- return function ( info, data, jqxhr ) {
+ return function ( info, data ) {
+ var $form, revisionId, $target, flowBoard,
+ $this = $( this );
+
if ( info.status !== 'done' ) {
// Error will be displayed by default, nothing else to wrap up
return $.Deferred().resolve().promise();
}
- var $this = $( this ),
- $form = $this.closest( 'form' ),
- revisionId = data.flow[ action ].committed.topic[ 'post-revision-id' ],
- $target = $form.data( 'flow-dialog-owner' ) || $form,
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $this );
+ $form = $this.closest( 'form' );
+ revisionId = data.flow[ action ].committed.topic[ 'post-revision-id' ];
+ $target = $form.data( 'flow-dialog-owner' ) || $form;
+ flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $this );
// @todo: add 3rd argument (target selector); there's no need to refresh entire topic if only post was moderated
return _flowBoardComponentRefreshTopic( $target, data.flow[ action ].workflow )
@@ -758,31 +403,6 @@
// HACK expose this so flow-initialize.js can rerender topics when it needs to
FlowBoardComponentApiEventsMixin.prototype.flowBoardComponentRefreshTopic = _flowBoardComponentRefreshTopic;
- function _activateSummarizeTopic( $target, flowBoard, topicSummary, action ) {
- var $old = $target;
-
- // Create the new flow_block_topicsummary_edit template
- $target = $( flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
- 'flow_block_topicsummary_edit',
- $.extend( topicSummary, { action: action } )
- ) ).children();
-
- // On cancel, put the old topicsummary back
- flowBoard.emitWithReturn( 'addFormCancelCallback', $target.find( 'form' ), function () {
- $target.before( $old ).remove();
- } );
-
- // Replace the old one
- $old.before( $target ).detach();
-
- flowBoard.emitWithReturn( 'makeContentInteractive', $target );
-
- // Focus on first form field
- $target.find( 'input, textarea' ).filter( ':visible:first' ).focus();
-
- return $.Deferred().resolve().promise();
- }
-
// Mixin to FlowBoardComponent
mw.flow.mixinComponent( 'board', FlowBoardComponentApiEventsMixin );
}( jQuery, mediaWiki ) );
diff --git a/Flow/modules/engine/components/board/base/flow-board-interactive-events.js b/Flow/modules/engine/components/board/base/flow-board-interactive-events.js
index b9602da7..9bba1974 100644
--- a/Flow/modules/engine/components/board/base/flow-board-interactive-events.js
+++ b/Flow/modules/engine/components/board/base/flow-board-interactive-events.js
@@ -9,7 +9,7 @@
* @extends FlowComponent
* @constructor
*/
- function FlowBoardComponentInteractiveEventsMixin( $container ) {
+ function FlowBoardComponentInteractiveEventsMixin() {
this.bindNodeHandlers( FlowBoardComponentInteractiveEventsMixin.UI.events );
}
OO.initClass( FlowBoardComponentInteractiveEventsMixin );
@@ -28,6 +28,7 @@
* Toggles collapse state
*
* @param {Event} event
+ * @return {jQuery.Promise}
*/
FlowBoardComponentInteractiveEventsMixin.UI.events.interactiveHandlers.collapserCollapsibleToggle = function ( event ) {
var $target = $( this ).closest( '.flow-element-collapsible' ),
@@ -58,159 +59,6 @@
return $deferred.resolve().promise();
};
- /**
- * @param {Event} event
- * @return {jQuery.Promise}
- */
- FlowBoardComponentInteractiveEventsMixin.UI.events.interactiveHandlers.activateReplyTopic = function ( event ) {
- var $topic = $( this ).closest( '.flow-topic' ),
- topicId = $topic.data( 'flow-id' ),
- component;
-
- // The reply form is used in multiple places. This will check if it was
- // triggered from inside the topic reply form.
- if ( $( this ).closest( '#flow-reply-' + topicId ).length === 0 ) {
- // Not in topic reply form
- return $.Deferred().reject();
- }
-
- // Only if the textarea is compressed, is it being activated. Otherwise,
- // it has already expanded and this focus is now just re-focussing the
- // already active form
- if ( !$( this ).hasClass( 'flow-input-compressed' ) ) {
- // Form already activated
- return $.Deferred().reject();
- }
-
- component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $( this ) );
- component.logEvent(
- 'FlowReplies',
- // log data
- {
- entrypoint: 'reply-bottom',
- action: 'initiate'
- },
- // nodes to forward funnel to
- $( this ).findWithParent(
- '< .flow-reply-form [data-role="cancel"],' +
- '< .flow-reply-form [data-role="submit"]'
- )
- );
-
- return $.Deferred().resolve();
- };
-
- /**
- * @param {Event} event
- */
- FlowBoardComponentInteractiveEventsMixin.UI.events.interactiveHandlers.activateNewTopic = function ( event ) {
- var $form = $( this ).closest( '.flow-newtopic-form' ),
- component;
-
- // Only if the textarea is compressed, is it being activated. Otherwise,
- // it has already expanded and this focus is now just re-focussing the
- // already active form
- if ( $form.find( '.flow-input-compressed' ).length === 0 ) {
- // Form already activated
- return $.Deferred().reject();
- }
-
- component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $( this ) );
- component.logEvent(
- 'FlowReplies',
- // log data
- {
- entrypoint: 'new-topic',
- action: 'initiate'
- },
- // nodes to forward funnel to
- $( this ).findWithParent(
- '< .flow-newtopic-form [data-role="cancel"],' +
- '< .flow-newtopic-form [data-role="submit"]'
- )
- );
-
- return $.Deferred().resolve();
- };
-
- /**
- * @param {Event} event
- */
- FlowBoardComponentInteractiveEventsMixin.UI.events.interactiveHandlers.activateReplyPost = function ( event ) {
- event.preventDefault();
-
- var $form,
- $this = $( this ),
- topicId = $this.closest( '.flow-topic' ).data( 'flow-id' ),
- flowBoard = mw.flow.getPrototypeMethod( 'board', 'getInstanceByElement' )( $this ),
- $post = $this.closest( '.flow-post' ),
- href = $this.attr( 'href' ),
- uri = new mw.Uri( href ),
- postId = uri.query.topic_postId,
- $targetPost = $( '#flow-post-' + postId ),
- topicTitle = $post.closest( '.flow-topic' ).find( '.flow-topic-title' ).text(),
- replyToContent = $post.find( '.flow-post-content' ).filter( ':first' ).text() || topicTitle,
- author = $.trim( $post.find( '.flow-author' ).filter( ':first' ).find( '.mw-userlink' ).text() ),
- $deferred = $.Deferred();
-
- if ( $targetPost.length === 0 ) {
- $targetPost = $( '#flow-topic-' + postId );
- }
-
- // forward all top level replys to the topic reply box
- if ( $targetPost.is( '.flow-topic' ) ) {
- $targetPost.find( '#flow-post-' + postId + '-form-content' ).trigger( 'focus' );
- return $deferred.resolve().promise();
- }
-
- // Check if reply form has already been opened
- if ( $post.data( 'flow-replying' ) ) {
- return $deferred.reject().promise();
- }
- $post.data( 'flow-replying', true );
-
- $form = $( flowBoard.constructor.static.TemplateEngine.processTemplateGetFragment(
- 'flow_reply_form.partial',
- // arguments can be empty: we just want an empty reply form
- {
- actions: {
- reply: {
- url: href,
- text: mw.msg( 'flow-reply-link', author )
- }
- },
- postId: postId,
- author: {
- name: author
- },
- // text for flow-reply-topic-title-placeholder placeholder
- properties: {
- 'topic-of-post': $.trim( replyToContent ).substr( 0, 200 )
- },
- // Topic:UUID
- articleTitle: mw.config.get( 'wgFormattedNamespaces' )[ 2600 ] + ':' + topicId[ 0 ].toUpperCase() + topicId.slice( 1 )
- }
- ) ).children();
-
- // Set the cancel callback on this form so that it gets rid of the form.
- // We have to make sure the data attribute is added to the form; the
- // addBack is failsafe for when form is actually the root node in $form
- // already (there may or may not be parent containers)
- flowBoard.emitWithReturn( 'addFormCancelCallback', $form.find( 'form' ).addBack( 'form' ), function () {
- $post.removeData( 'flow-replying' );
- $form.remove();
- } );
-
- // Add reply form below the post being replied to (WRT max depth)
- $targetPost.children( '.flow-replies' ).append( $form );
- $form.conditionalScrollIntoView();
-
- // focus the input
- $form.find( 'textarea' ).focus();
-
- return $deferred.resolve().promise();
- };
-
// @todo remove these data-flow handler forwarder callbacks when data-mwui handlers are implemented
$( [ 'close', 'prevOrClose', 'nextOrSubmit', 'prev', 'next' ] ).each( function ( i, fn ) {
// Assigns each handler with the prefix 'modal', eg. 'close' becomes 'modalClose'
diff --git a/Flow/modules/engine/components/board/base/flow-board-load-events.js b/Flow/modules/engine/components/board/base/flow-board-load-events.js
index 06634137..a5092d7d 100644
--- a/Flow/modules/engine/components/board/base/flow-board-load-events.js
+++ b/Flow/modules/engine/components/board/base/flow-board-load-events.js
@@ -9,7 +9,7 @@
* @extends FlowComponent
* @constructor
*/
- function FlowBoardComponentLoadEventsMixin( $container ) {
+ function FlowBoardComponentLoadEventsMixin() {
this.bindNodeHandlers( FlowBoardComponentLoadEventsMixin.UI.events );
}
OO.initClass( FlowBoardComponentLoadEventsMixin );
diff --git a/Flow/modules/engine/components/board/base/flow-boardandhistory-base.js b/Flow/modules/engine/components/board/base/flow-boardandhistory-base.js
index 20c3a4b1..494cbf37 100644
--- a/Flow/modules/engine/components/board/base/flow-boardandhistory-base.js
+++ b/Flow/modules/engine/components/board/base/flow-boardandhistory-base.js
@@ -4,12 +4,14 @@
*/
( function ( $, mw ) {
+ var inTopicNamespace = mw.config.get( 'wgNamespaceNumber' ) === mw.config.get( 'wgNamespaceIds' ).topic;
+
/**
*
* @param {jQuery} $container
* @constructor
*/
- function FlowBoardAndHistoryComponentBase( $container ) {
+ function FlowBoardAndHistoryComponentBase() {
this.bindNodeHandlers( FlowBoardAndHistoryComponentBase.UI.events );
}
OO.initClass( FlowBoardAndHistoryComponentBase );
@@ -124,25 +126,6 @@
} );
};
- /**
- * Adds a hardcoded moderation reason to the request when resolving and reopening a topic.
- * @param {Event} event
- * @param {Object} info
- * @param {Object} queryMap
- * @return {Object}
- */
- function addLockRestoreReason( event, info, queryMap ) {
- var msgKey = queryMap.cotmoderationState === 'lock' ?
- 'flow-rev-message-lock-topic-reason' :
- 'flow-rev-message-restore-topic-reason',
- msg = mw.msg( msgKey );
- return $.extend( {}, queryMap, {
- cotreason: msg
- } );
- }
- FlowBoardAndHistoryComponentBase.UI.events.apiPreHandlers.lockAndSummarizeTopic = addLockRestoreReason;
- FlowBoardAndHistoryComponentBase.UI.events.apiPreHandlers.lockTopic = addLockRestoreReason;
-
//
// Interactive handlers
//
@@ -175,7 +158,7 @@
// Render the modal itself with mw-ui-modal
modal = mw.Modal( {
- open: $( mw.flow.TemplateEngine.processTemplateGetFragment( template, params ) ).children(),
+ open: $( mw.flow.TemplateEngine.processTemplateGetFragment( template, params ) ).children(),
disableCloseOnOutsideClick: true
} );
@@ -218,7 +201,7 @@
// Only log cancel attempt if it was user-initiated, not when the cancel
// was triggered by code (as part of a post-submit form destroy)
- if ( event.which ) {
+ if ( event.which && schemaName ) {
flowComponent.logEvent( schemaName, { action: 'cancel-attempt', funnelId: funnelId } );
}
@@ -232,10 +215,16 @@
// Only log if user had already entered text (= confirmation was requested)
if ( changedFieldCount ) {
+ // TODO: Use an OOUI dialog
+ // eslint-disable-next-line no-alert
if ( confirm( flowComponent.constructor.static.TemplateEngine.l10n( 'flow-cancel-warning' ) ) ) {
- flowComponent.logEvent( schemaName, { action: 'cancel-success', funnelId: funnelId } );
+ if ( schemaName ) {
+ flowComponent.logEvent( schemaName, { action: 'cancel-success', funnelId: funnelId } );
+ }
} else {
- flowComponent.logEvent( schemaName, { action: 'cancel-abort', funnelId: funnelId } );
+ if ( schemaName ) {
+ flowComponent.logEvent( schemaName, { action: 'cancel-abort', funnelId: funnelId } );
+ }
// User aborted cancel, quit this function & don't destruct the form!
return $deferred.reject().promise();
@@ -276,6 +265,4 @@
return inTopicNamespace && ( !$el || $el.closest( '.flow-post' ).length === 0 );
}
FlowBoardAndHistoryComponentBase.static.inTopicNamespace = flowBoardInTopicNamespace;
-
- var inTopicNamespace = mw.config.get( 'wgNamespaceNumber' ) === mw.config.get( 'wgNamespaceIds' ).topic;
}( jQuery, mediaWiki ) );
diff --git a/Flow/modules/engine/components/board/features/flow-board-loadmore.js b/Flow/modules/engine/components/board/features/flow-board-loadmore.js
index 9ef1acd3..32e65451 100644
--- a/Flow/modules/engine/components/board/features/flow-board-loadmore.js
+++ b/Flow/modules/engine/components/board/features/flow-board-loadmore.js
@@ -9,7 +9,7 @@
* @this FlowBoardComponent
* @constructor
*/
- function FlowBoardComponentLoadMoreFeatureMixin( $container ) {
+ function FlowBoardComponentLoadMoreFeatureMixin() {
/** Stores a reference to each topic element currently on the page */
this.renderedTopics = {};
/** Stores a list of all topics titles by ID */
@@ -86,7 +86,8 @@
// 2a. Topic is not rendered; do we know about this topic ID?
if ( flowBoard.topicTitlesById[ topicId ] === undefined ) {
// We don't. Abort!
- return flowBoard.debug( 'Unknown topicId', arguments );
+ flowBoard.debug( 'Unknown topicId', arguments );
+ return;
}
// 2b. Load that topic and jump to it
@@ -132,7 +133,7 @@
_scrollWithoutInfinite();
} )
// On fail, render an error
- .fail( function ( code, data ) {
+ .fail( function ( code ) {
flowBoard.debug( true, 'Failed to load topics: ' + code );
// Failed fetching the new data to be displayed.
// @todo render the error at topic position and scroll to it
@@ -159,7 +160,7 @@
* @param {Object} queryMap
* @param {FlowBoardComponent} info.component
*/
- function flowBoardComponentLoadMoreFeatureBoardApiPreHandler( event, info, queryMap ) {
+ function flowBoardComponentLoadMoreFeatureBoardApiPreHandler( event, info ) {
// Backup the topic data
info.component.renderedTopicsBackup = info.component.renderedTopics;
info.component.topicTitlesByIdBackup = info.component.topicTitlesById;
@@ -181,9 +182,8 @@
* @param {FlowBoardComponent} info.component
* @param {Object} data
* @param {jqXHR} jqxhr
- * @return {jQuery.Promise}
*/
- function flowBoardComponentLoadMoreFeatureBoardApiCallback( info, data, jqxhr ) {
+ function flowBoardComponentLoadMoreFeatureBoardApiCallback( info ) {
if ( info.status !== 'done' ) {
// Failed; restore the topic data
info.component.renderedTopics = info.component.renderedTopicsBackup;
@@ -204,20 +204,25 @@
* @param {FlowBoardComponent} info.component
* @param {Object} data
* @param {jqXHR} jqxhr
+ * @return {jQuery.Promise}
*/
- function flowBoardComponentLoadMoreFeatureTopicsApiCallback( info, data, jqxhr ) {
+ function flowBoardComponentLoadMoreFeatureTopicsApiCallback( info, data ) {
+ var scrollTarget,
+ $scrollContainer,
+ topicsData,
+ readingTopicPosition,
+ $this = $( this ),
+ $target = info.$target,
+ flowBoard = info.component;
+
if ( info.status !== 'done' ) {
// Error will be displayed by default, nothing else to wrap up
return $.Deferred().resolve().promise();
}
- var $this = $( this ),
- $target = info.$target,
- flowBoard = info.component,
- scrollTarget = $this.data( 'flow-scroll-target' ),
- $scrollContainer = $.findWithParent( $this, $this.data( 'flow-scroll-container' ) ),
- topicsData = data.flow[ 'view-topiclist' ].result.topiclist,
- readingTopicPosition;
+ scrollTarget = $this.data( 'flow-scroll-target' );
+ $scrollContainer = $.findWithParent( $this, $this.data( 'flow-scroll-container' ) );
+ topicsData = data.flow[ 'view-topiclist' ].result.topiclist;
if ( scrollTarget === 'window' && flowBoard.readingTopicId ) {
// Store the current position of the topic you are reading
@@ -321,7 +326,7 @@
} );
} else {
$target = $.findWithParent( $button, scrollTargetSelector );
- $target.on( 'scroll.flow-load-more', $.throttle( 50, function ( evt ) {
+ $target.on( 'scroll.flow-load-more', $.throttle( 50, function () {
_flowBoardComponentLoadMoreFeatureInfiniteScrollCheck.call( board, $scrollContainer, $target );
} ) );
}
@@ -415,15 +420,15 @@
* @param {jQuery} $calculationContainer Container to do scroll calculations on (height, scrollTop, offset, etc.)
*/
function _flowBoardComponentLoadMoreFeatureInfiniteScrollCheck( $searchContainer, $calculationContainer ) {
+ var calculationContainerHeight, calculationContainerScroll;
if ( this.infiniteScrollDisabled ) {
// This happens when the topic navigation is used to jump to a topic
// We should not infinite-load anything when we are scrolling to a topic
return;
}
- var calculationContainerHeight = $calculationContainer.height(),
- calculationContainerScroll = $calculationContainer.scrollTop(),
- calculationContainerThreshold = ( $calculationContainer.offset() || { top: calculationContainerScroll } ).top;
+ calculationContainerHeight = $calculationContainer.height();
+ calculationContainerScroll = $calculationContainer.scrollTop();
// Find load more buttons within our search container, and they must be visible
$searchContainer.find( this.$loadMoreNodes ).filter( ':visible' ).each( function () {
@@ -432,7 +437,7 @@
nodeHeight = $this.outerHeight( true );
// First, is this element above or below us?
- if ( nodeOffset <= calculationContainerThreshold ) {
+ if ( nodeOffset <= calculationContainerScroll ) {
// Top of element is above the viewport; don't use it.
return;
}
@@ -441,7 +446,7 @@
// also shouldn't be triggered if it's still behind TOC!
// Is this element in the viewport?
- if ( nodeOffset - nodeHeight <= calculationContainerThreshold + calculationContainerHeight ) {
+ if ( nodeOffset - nodeHeight <= calculationContainerScroll + calculationContainerHeight ) {
// Element is almost in viewport, click it.
$( this ).trigger( 'click' );
}
@@ -460,14 +465,20 @@
* @private
*/
function _flowBoardComponentLoadMoreFeatureRenderTopics( flowBoard, topicsData, forceShowLoadMore, $insertAt, scrollTarget, scrollContainer, scrollTemplate ) {
+ var i, j, $topic, topicId,
+ $allRendered = $( [] ),
+ toInsert = [];
+
if ( !topicsData.roots.length ) {
flowBoard.debug( 'No topics returned from API', arguments );
return;
}
- /** @private
- */
function _createRevPagination( $target ) {
+ // FIXME reverse pagination is broken in the backend, don't use it
+ return;
+
+ // eslint-disable-next-line no-unreachable
if ( !topicsData.links.pagination.fwd && !topicsData.links.pagination.rev ) {
return;
}
@@ -494,8 +505,6 @@
);
}
- /** @private
- */
function _createFwdPagination( $target ) {
if ( forceShowLoadMore || topicsData.links.pagination.fwd ) {
// Add the load more to the end of the stack
@@ -543,10 +552,6 @@
return $newTopics;
}
- var i, j, $topic, topicId,
- $allRendered = $( [] ),
- toInsert = [];
-
for ( i = 0; i < topicsData.roots.length; i++ ) {
topicId = topicsData.roots[ i ];
@@ -587,6 +592,10 @@
// Put the new topic after the found topic above it
if ( j >= 0 ) {
+ // If there is a load-more here, insert after that as well
+ if ( $topic.next().hasClass( 'flow-load-more' ) ) {
+ $topic = $topic.next();
+ }
$topic.after( flowBoard.renderedTopics[ flowBoard.orderedTopicIds[ i ] ] );
}
}
diff --git a/Flow/modules/engine/components/board/features/flow-board-navigation.js b/Flow/modules/engine/components/board/features/flow-board-navigation.js
index 0b65358e..9dfb1e27 100644
--- a/Flow/modules/engine/components/board/features/flow-board-navigation.js
+++ b/Flow/modules/engine/components/board/features/flow-board-navigation.js
@@ -10,7 +10,7 @@
* @param {jQuery} $container
* @this FlowComponent
*/
- function FlowBoardComponentBoardHeaderFeatureMixin( $container ) {
+ function FlowBoardComponentBoardHeaderFeatureMixin() {
// Bind element handlers
this.bindNodeHandlers( FlowBoardComponentBoardHeaderFeatureMixin.UI.events );
diff --git a/Flow/modules/engine/components/board/features/flow-board-side-rail.js b/Flow/modules/engine/components/board/features/flow-board-side-rail.js
index d80a9969..2342f0a8 100644
--- a/Flow/modules/engine/components/board/features/flow-board-side-rail.js
+++ b/Flow/modules/engine/components/board/features/flow-board-side-rail.js
@@ -9,7 +9,7 @@
* @this FlowComponent
* @constructor
*/
- function FlowBoardComponentSideRailFeatureMixin( $container ) {
+ function FlowBoardComponentSideRailFeatureMixin() {
// Bind element handlers
this.bindNodeHandlers( FlowBoardComponentSideRailFeatureMixin.UI.events );
}
@@ -33,7 +33,7 @@
*
* @param {Event} event
*/
- function FlowBoardComponentSideRailFeatureMixinLoadCallback( event ) {
+ function FlowBoardComponentSideRailFeatureMixinLoadCallback() {
if ( mw.user.options.get( 'flow-side-rail-state' ) === 'collapsed' ) {
$( '.flow-component' ).addClass( 'expanded' );
}
@@ -49,7 +49,7 @@
*
* @param {Event} event
*/
- function FlowBoardComponentSideRailFeatureMixinToggleCallback( event ) {
+ function FlowBoardComponentSideRailFeatureMixinToggleCallback() {
var boardIsExpanded = $( '.flow-component' ).toggleClass( 'expanded' ).hasClass( 'expanded' ),
sideRailState = boardIsExpanded ? 'collapsed' : 'expanded';
diff --git a/Flow/modules/engine/components/board/features/flow-board-switcheditor.js b/Flow/modules/engine/components/board/features/flow-board-switcheditor.js
index bc6b5742..056d32e4 100644
--- a/Flow/modules/engine/components/board/features/flow-board-switcheditor.js
+++ b/Flow/modules/engine/components/board/features/flow-board-switcheditor.js
@@ -10,7 +10,7 @@
* @this FlowComponent
* @constructor
*/
- function FlowBoardComponentSwitchEditorFeatureMixin( $container ) {
+ function FlowBoardComponentSwitchEditorFeatureMixin() {
// Bind element handlers
this.bindNodeHandlers( FlowBoardComponentSwitchEditorFeatureMixin.UI.events );
}
diff --git a/Flow/modules/engine/components/board/features/flow-board-visualeditor.js b/Flow/modules/engine/components/board/features/flow-board-visualeditor.js
index 0fcb319a..83dbff3d 100644
--- a/Flow/modules/engine/components/board/features/flow-board-visualeditor.js
+++ b/Flow/modules/engine/components/board/features/flow-board-visualeditor.js
@@ -8,9 +8,8 @@
*
* @this FlowBoardComponent
* @constructor
- *
*/
- function FlowBoardComponentVisualEditorFeatureMixin( $container ) {
+ function FlowBoardComponentVisualEditorFeatureMixin() {
}
// This is not really VE-specific, but I'm not sure where best to put it.
@@ -18,7 +17,8 @@
/**
* Finds topic authors for the given node
*
- * @return Array List of usernames
+ * @param {jQuery} $node
+ * @return {string[]} List of usernames
*/
function flowVisualEditorGetTopicPosters( $node ) {
var $topic = $node.closest( '.flow-topic' ),
diff --git a/Flow/modules/engine/components/board/flow-board.js b/Flow/modules/engine/components/board/flow-board.js
index b239ec84..93d32e57 100644
--- a/Flow/modules/engine/components/board/flow-board.js
+++ b/Flow/modules/engine/components/board/flow-board.js
@@ -23,7 +23,8 @@
*/
function FlowBoardComponent( $container ) {
var uri = new mw.Uri( location.href ),
- uid = String( location.hash.match( /[0-9a-z]{16,19}$/i ) || '' );
+ anchorUid = String( location.hash.match( /[0-9a-z]{16,19}$/i ) || '' ),
+ highlightUid;
// Default API submodule for FlowBoard URLs is to fetch a topiclist
this.Api.setDefaultSubmodule( 'view-topiclist' );
@@ -34,18 +35,21 @@
return false;
}
- // Handle URL parameters
- if ( uid ) {
+ // Handle URL parameters. If topic_showPostId is used, there should also be an
+ // anchor.
+ if ( anchorUid ) {
if ( uri.query.fromnotif ) {
- _flowHighlightPost( $container, uid, 'newer' );
+ highlightUid = uri.query.topic_showPostId;
+ _flowHighlightPost( $container, highlightUid, 'newer' );
} else {
- _flowHighlightPost( $container, uid );
+ highlightUid = anchorUid;
+ _flowHighlightPost( $container, highlightUid );
}
} else {
// There is a weird bug with url ending with #flow-post-xxxx
// and full height side rail.
// We only enable the full height when we don't have such url.
- $container.addClass( 'full-height-side-rail' );
+ $container.addClass( 'flow-full-height-side-rail' );
}
_overrideWatchlistNotification();
@@ -66,17 +70,19 @@
* @return {boolean|jQuery}
*/
function flowBoardComponentReinitializeContainer( $container ) {
+ var $retObj, $header, $boardNavigation, $board;
+
if ( $container === false ) {
return false;
}
// Trigger this on FlowBoardAndHistoryComponentBase
// @todo use EventEmitter to do this?
- var $retObj = FlowBoardComponent.parent.prototype.reinitializeContainer.call( this, $container ),
+ $retObj = FlowBoardComponent.parent.prototype.reinitializeContainer.call( this, $container );
// Find any new (or previous) elements
- $header = $container.find( '.flow-board-header' ).addBack().filter( '.flow-board-header:first' ),
- $boardNavigation = $container.find( '.flow-board-navigation' ).addBack().filter( '.flow-board-navigation:first' ),
- $board = $container.find( '.flow-board' ).addBack().filter( '.flow-board:first' );
+ $header = $container.find( '.flow-board-header' ).addBack().filter( '.flow-board-header:first' );
+ $boardNavigation = $container.find( '.flow-board-navigation' ).addBack().filter( '.flow-board-navigation:first' );
+ $board = $container.find( '.flow-board' ).addBack().filter( '.flow-board:first' );
if ( $retObj === false ) {
return false;
@@ -145,8 +151,9 @@
/**
* Helper receives
* @param {jQuery} $container
- * @param {string} uid
- * @param {string} option
+ * @param {string} uid Anchor to scroll to
+ * @param {string} [option] 'newer' if all posts equal to or newer than uid should be
+ * highlighted. Otherwise, it will only highlight that post itself.
* @return {jQuery}
*/
function _flowHighlightPost( $container, uid, option ) {
diff --git a/Flow/modules/engine/components/board/flow-boardhistory.js b/Flow/modules/engine/components/board/flow-boardhistory.js
index 0e8df7cc..7e863982 100644
--- a/Flow/modules/engine/components/board/flow-boardhistory.js
+++ b/Flow/modules/engine/components/board/flow-boardhistory.js
@@ -1,7 +1,3 @@
-/*!
- *
- */
-
( function ( $, mw ) {
/**
*
@@ -12,7 +8,7 @@
* @constructor
* @param {jQuery} $container
*/
- function FlowBoardHistoryComponent( $container ) {
+ function FlowBoardHistoryComponent() {
this.bindNodeHandlers( FlowBoardHistoryComponent.UI.events );
}
OO.initClass( FlowBoardHistoryComponent );
@@ -39,13 +35,15 @@
* @param {jqXHR} jqxhr
* @return {jQuery.Promise}
*/
- function flowBoardHistoryModerationCallback( info, data, jqxhr ) {
+ function flowBoardHistoryModerationCallback( info ) {
+ var flowBoardHistory;
+
if ( info.status !== 'done' ) {
// Error will be displayed by default, nothing else to wrap up
return $.Deferred().resolve().promise();
}
- var flowBoardHistory = mw.flow.getPrototypeMethod( 'boardHistory', 'getInstanceByElement' )( $( this ) );
+ flowBoardHistory = mw.flow.getPrototypeMethod( 'boardHistory', 'getInstanceByElement' )( $( this ) );
// Clear the form so we can refresh without the confirmation dialog
flowBoardHistory.emitWithReturn( 'cancelForm', $( this ).closest( 'form' ) );
@@ -65,7 +63,7 @@
* @param {Object} data
* @return {jQuery.Promise}
*/
- FlowBoardHistoryComponent.UI.events.apiHandlers.lockTopic = function ( info, data ) {
+ FlowBoardHistoryComponent.UI.events.apiHandlers.lockTopic = function ( info ) {
if ( info.status !== 'done' ) {
// Error will be displayed by default & edit conflict handled, nothing else to wrap up
return $.Deferred().resolve().promise();
diff --git a/Flow/modules/engine/components/common/flow-component-engines.js b/Flow/modules/engine/components/common/flow-component-engines.js
index 7c8cac4e..2008bdcd 100644
--- a/Flow/modules/engine/components/common/flow-component-engines.js
+++ b/Flow/modules/engine/components/common/flow-component-engines.js
@@ -1,33 +1,27 @@
/*!
- * Initializes StorageEngine (Storer), TemplateEngine (Handlebars), and API (FlowApi).
+ * Initializes TemplateEngine (Handlebars), and API (FlowApi).
*/
-( function ( $, mw, initStorer ) {
+( function ( $, mw ) {
/**
- * Initializes Storer, Handlebars, and FlowApi.
+ * Initializes Handlebars and FlowApi.
* @constructor
*/
function FlowComponentEnginesMixin() {}
OO.initClass( FlowComponentEnginesMixin );
/**
- * Contains Storer.js's (fallback) storage engines.
- * @type {Object} { cookieStorage: Storer.cookieStorage, memoryStorage: Storer.memoryStorage, sessionStorage: Storer.sessionStorage, localStorage: Storer.localStorage }}
- */
- mw.flow.StorageEngine = FlowComponentEnginesMixin.static.StorageEngine = initStorer( { prefix: '_WMFLOW_' } );
-
- /**
* Contains the Flow templating engine translation class (in case we change templating engines).
* @type {FlowHandlebars}
*/
- mw.flow.TemplateEngine = FlowComponentEnginesMixin.static.TemplateEngine = new mw.flow.FlowHandlebars( FlowComponentEnginesMixin.static.StorageEngine );
+ mw.flow.TemplateEngine = FlowComponentEnginesMixin.static.TemplateEngine = new mw.flow.FlowHandlebars();
/**
* Flow API singleton
* @type {FlowApi}
*/
- mw.flow.Api = new mw.flow.FlowApi( FlowComponentEnginesMixin.static.StorageEngine );
+ mw.flow.Api = new mw.flow.FlowApi();
// Copy static and prototype from mixin to main class
mw.flow.mixinComponent( 'component', FlowComponentEnginesMixin );
-}( jQuery, mediaWiki, mediaWiki.flow.vendor.initStorer ) );
+}( jQuery, mediaWiki ) );
diff --git a/Flow/modules/engine/components/common/flow-component-events.js b/Flow/modules/engine/components/common/flow-component-events.js
index 782c6307..1684a74b 100644
--- a/Flow/modules/engine/components/common/flow-component-events.js
+++ b/Flow/modules/engine/components/common/flow-component-events.js
@@ -13,6 +13,7 @@
* @class
* @extends OO.EventEmitter
* @constructor
+ * @param {jQuery} $container Container
*/
function FlowComponentEventsMixin( $container ) {
var self = this;
@@ -229,7 +230,7 @@
*
* @param {string} code
* @param {Object} result
- * @return string
+ * @return {string}
*/
function flowGetApiErrorMessage( code, result ) {
if ( result.error && result.error.info ) {
@@ -427,6 +428,8 @@
* @todo Perhaps use name="flow-load-handler" for performance in older browsers
*/
function flowMakeContentInteractiveCallback( $container ) {
+ var component;
+
if ( !$container.jquery ) {
$container = $container.$container;
}
@@ -437,7 +440,7 @@
}
// Get the FlowComponent
- var component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $container );
+ component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $container );
// Find all load-handlers and trigger them
$container.find( '.flow-load-interactive' ).add( $container.filter( '.flow-load-interactive' ) ).each( function () {
@@ -481,9 +484,7 @@
}
FlowComponentEventsMixin.eventHandlers.makeContentInteractive = flowMakeContentInteractiveCallback;
- /**
- * Triggers load handlers.
- */
+ // Triggers load handlers
function flowLoadHandlerCallback( handlerName, args, context ) {
args = $.isArray( args ) ? args : ( args ? [ args ] : [] );
context = context || this;
@@ -531,30 +532,35 @@
/**
* Triggers both API and interactive handlers.
* To manually trigger a handler on an element, you can use extraParameters via $el.trigger.
+ *
* @param {Event} event
* @param {Object} [extraParameters]
* @param {string} [extraParameters.interactiveHandler]
* @param {string} [extraParameters.apiHandler]
*/
function flowInteractiveHandlerCallback( event, extraParameters ) {
+ var args, $context, interactiveHandlerName, apiHandlerName;
+
// Only trigger with enter key & no modifier keys, if keypress
if ( event.type === 'keypress' && ( event.charCode !== 13 || event.metaKey || event.shiftKey || event.ctrlKey || event.altKey ) ) {
return;
}
- var args = Array.prototype.slice.call( arguments, 0 ),
- $context = $( event.currentTarget || event.delegateTarget || event.target ),
- // Have either of these been forced via trigger extraParameters?
- interactiveHandlerName = ( extraParameters || {} ).interactiveHandler || $context.data( 'flow-interactive-handler' ),
- apiHandlerName = ( extraParameters || {} ).apiHandler || $context.data( 'flow-api-handler' );
+ args = Array.prototype.slice.call( arguments, 0 );
+ $context = $( event.currentTarget || event.delegateTarget || event.target );
+ // Have either of these been forced via trigger extraParameters?
+ interactiveHandlerName = ( extraParameters || {} ).interactiveHandler || $context.data( 'flow-interactive-handler' );
+ apiHandlerName = ( extraParameters || {} ).apiHandler || $context.data( 'flow-api-handler' );
- return flowExecuteInteractiveHandler.call( this, args, $context, interactiveHandlerName, apiHandlerName );
+ flowExecuteInteractiveHandler.call( this, args, $context, interactiveHandlerName, apiHandlerName );
}
FlowComponentEventsMixin.eventHandlers.interactiveHandler = flowInteractiveHandlerCallback;
FlowComponentEventsMixin.eventHandlers.apiRequest = flowInteractiveHandlerCallback;
/**
* Triggers both API and interactive handlers, on focus.
+ *
+ * @param {Event} event
*/
function flowInteractiveHandlerFocusCallback( event ) {
var args = Array.prototype.slice.call( arguments, 0 ),
@@ -562,7 +568,7 @@
interactiveHandlerName = $context.data( 'flow-interactive-handler-focus' ),
apiHandlerName = $context.data( 'flow-api-handler-focus' );
- return flowExecuteInteractiveHandler.call( this, args, $context, interactiveHandlerName, apiHandlerName );
+ flowExecuteInteractiveHandler.call( this, args, $context, interactiveHandlerName, apiHandlerName );
}
FlowComponentEventsMixin.eventHandlers.interactiveHandlerFocus = flowInteractiveHandlerFocusCallback;
@@ -585,19 +591,22 @@
*
* Additionally:
* * data-flow-eventlog-forward: Selectors to forward funnel data to
+ *
+ * @param {Event} event
*/
function flowEventLogCallback( event ) {
+ var $context, data, component, $promise, eventInstance, key, value;
+
// Only trigger with enter key & no modifier keys, if keypress
if ( event.type === 'keypress' && ( event.charCode !== 13 || event.metaKey || event.shiftKey || event.ctrlKey || event.altKey ) ) {
return;
}
- var $context = $( event.currentTarget ),
- data = $context.data(),
- component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $context ),
- $promise = data.flowInteractiveHandlerPromise || $.Deferred().resolve().promise(),
- eventInstance = {},
- key, value;
+ $context = $( event.currentTarget );
+ data = $context.data();
+ component = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $context );
+ $promise = data.flowInteractiveHandlerPromise || $.Deferred().resolve().promise();
+ eventInstance = {};
// Fetch loggable data: everything prefixed flowEventlog except
// flowEventLogForward and flowEventLogSchema
@@ -636,7 +645,7 @@
* When the whole class has been instantiated fully (after every constructor has been called).
* @param {FlowComponent} component
*/
- function flowEventsMixinInstantiationComplete( component ) {
+ function flowEventsMixinInstantiationComplete() {
$( window ).trigger( 'scroll.flow-window-scroll' );
}
FlowComponentEventsMixin.eventHandlers.instantiationComplete = flowEventsMixinInstantiationComplete;
@@ -806,7 +815,7 @@
* to this topic|board
* @param {jQuery} $tooltipTarget Element to attach tooltip to.
* @param {string} type 'topic' or 'board'
- * @param {string} dir Direction to point the pointer. 'left' or 'up'
+ * @param {string} dir Direction to point the pointer. 'left', 'right', 'up' or 'down'
*/
function flowEventsMixinShowSubscribedTooltip( $tooltipTarget, type, dir ) {
dir = dir || 'left';
@@ -814,7 +823,8 @@
mw.tooltip.show(
$tooltipTarget,
// tooltipTarget will not always be part of a FlowBoardComponent
- $( mw.flow.TemplateEngine.processTemplateGetFragment(
+ $(
+ mw.flow.TemplateEngine.processTemplateGetFragment(
'flow_tooltip_subscribed.partial',
{
unsubscribe: false,
@@ -869,7 +879,7 @@
*
* @param {jQuery} $node
* @param {string} selector
- * @return jQuery
+ * @return {jQuery}
*/
function _flowFindUpward( $node, selector ) {
// first check if result can already be found inside $node
diff --git a/Flow/modules/engine/components/common/flow-component-menus.js b/Flow/modules/engine/components/common/flow-component-menus.js
index 45ec3628..82b97a89 100644
--- a/Flow/modules/engine/components/common/flow-component-menus.js
+++ b/Flow/modules/engine/components/common/flow-component-menus.js
@@ -93,6 +93,7 @@
* Allows you to open a flow-menu from a secondary click handler elsewhere.
* Uses data-flow-menu-target="< foo .flow-menu"
* @param {Event} event
+ * @return {jQuery.Promise}
*/
function flowComponentMenusFeatureElementMenuToggleCallback( event ) {
var $this = $( this ),
diff --git a/Flow/modules/engine/components/flow-component.js b/Flow/modules/engine/components/flow-component.js
index a0f55d8e..bb0a1b45 100644
--- a/Flow/modules/engine/components/flow-component.js
+++ b/Flow/modules/engine/components/flow-component.js
@@ -35,7 +35,7 @@
}
// Give this board its own API instance @todo do this with OOjs
- this.Api = new mw.flow.FlowApi( FlowComponent.static.StorageEngine, this.id );
+ this.Api = new mw.flow.FlowApi( this.id );
// Keep this in the registry to find it by other means
while ( parent ) {
@@ -55,8 +55,10 @@
* @param {boolean} [isError=true]
*/
mw.flow.debug = FlowComponent.prototype.debug = function ( isError ) {
+ var args;
+ /* eslint-disable no-console */
if ( window.console ) {
- var args = Array.prototype.slice.call( arguments, 0 );
+ args = Array.prototype.slice.call( arguments, 0 );
if ( typeof isError === 'boolean' ) {
args.shift();
@@ -68,12 +70,13 @@
if ( isError && console.error ) {
// If console.error is supported, send that, because it gives a stack trace
- return console.error.apply( console, args );
+ console.error.apply( console, args );
}
// Otherwise, use console.log
console.log.apply( console, args );
}
+ /* eslint-enable no-console */
};
/**
@@ -175,13 +178,14 @@
'*',
{ flowSpawnedBy: this.$container, flowSpawnedFrom: $el },
function ( event ) {
+ var i, $nodes;
// Let's forward these events in an unusual way, similar to how jQuery propagates events...
// First, only take the very first, top-level event, as the rest of the propagation is handled elsewhere
if ( event.target === this ) {
// Get all the parent nodes of our target,
// but do not include any nodes we will already be bubbling up to (eg. body)
- var $nodes = $eventTarget.parents().addBack().not( $( this ).parents().addBack() ),
- i = $nodes.length;
+ $nodes = $eventTarget.parents().addBack().not( $( this ).parents().addBack() );
+ i = $nodes.length;
// For every node between $eventTarget and window that was not filtered out above...
while ( i-- ) {
@@ -212,14 +216,15 @@
* @private
*/
function _eventForwardDispatch( event, container ) {
+ var i, ret, handleObj, matched, j,
+ args, handlers, special,
+ handlerQueue = [];
+
// Make a writable jQuery.Event from the native event object
event = jQuery.event.fix( event );
-
- var i, ret, handleObj, matched, j,
- handlerQueue = [],
- args = Array.prototype.slice.call( arguments, 0 ),
- handlers = ( jQuery._data( this, 'events' ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
+ args = Array.prototype.slice.call( arguments, 0 );
+ handlers = ( jQuery._data( this, 'events' ) || {} )[ event.type ] || [];
+ special = jQuery.event.special[ event.type ] || {};
// Use the fix-ed jQuery.Event rather than the (read-only) native event
args[ 0 ] = event;
diff --git a/Flow/modules/engine/components/flow-registry.js b/Flow/modules/engine/components/flow-registry.js
index 946b77dc..80e96649 100644
--- a/Flow/modules/engine/components/flow-registry.js
+++ b/Flow/modules/engine/components/flow-registry.js
@@ -8,11 +8,11 @@
*/
( function ( $, mw ) {
+ var _componentRegistry = new OO.Registry();
+
/** @class mw.flow */
mw.flow = mw.flow || {}; // create mw.flow globally
- var _componentRegistry = new OO.Registry();
-
/**
* Instantiate one or more new FlowComponents.
* Uses data-flow-component to find the right class, and returns that new instance.
diff --git a/Flow/modules/engine/components/flow-undo-page.js b/Flow/modules/engine/components/flow-undo-page.js
index f91c6a5e..6e7da90c 100644
--- a/Flow/modules/engine/components/flow-undo-page.js
+++ b/Flow/modules/engine/components/flow-undo-page.js
@@ -1,9 +1,9 @@
( function ( $, mw ) {
- $( document ).ready( function () {
+ $( function () {
$( 'form[method=POST]' ).each( function ( index, form ) {
- $( form ).submit( function ( event ) {
+ $( form ).submit( function () {
var $textarea = $( form ).find( 'textarea.flow-editor-initialized' ),
moduleName = $( form ).data( 'module' ),
editorExist = mw.flow.editor.exists( $textarea ),
@@ -26,4 +26,4 @@
} );
-} )( jQuery, mediaWiki );
+}( jQuery, mediaWiki ) );
diff --git a/Flow/modules/engine/misc/flow-api.js b/Flow/modules/engine/misc/flow-api.js
index 8be7159e..898b0175 100644
--- a/Flow/modules/engine/misc/flow-api.js
+++ b/Flow/modules/engine/misc/flow-api.js
@@ -1,6 +1,4 @@
( function ( mw, $ ) {
- mw.flow = mw.flow || {}; // create mw.flow globally
-
var apiTransformMap = {
// Map of API submodule name, block name, and prefix name
'moderate-post': [ 'topic_', 'mp' ],
@@ -19,16 +17,17 @@
'edit-topic-summary': [ 'topicsummary_', 'ets' ]
};
+ mw.flow = mw.flow || {}; // create mw.flow globally
+
/**
* Handles Flow API calls. Each FlowComponent has its own instance of FlowApi as component.Api,
* so that it can store a workflowId and pageName permanently for simplicity.
+ *
+ * @constructor
* @param {string} [workflowId]
* @param {string} [pageName]
- * @return {FlowApi}
- * @constructor
*/
- function FlowApi( storageEngine, workflowId, pageName ) {
- this.StorageEngine = storageEngine;
+ function FlowApi( workflowId, pageName ) {
this.workflowId = workflowId;
this.pageName = pageName;
@@ -77,7 +76,7 @@
if ( params._internal && params._internal.tokenType ) {
tokenType = params._internal.tokenType;
} else {
- tokenType = 'edit';
+ tokenType = 'csrf';
}
delete params._internal;
@@ -93,8 +92,6 @@
this.apiCall = flowApiCall;
}
- /** @type {Storer} */
- FlowApi.prototype.StorageEngine = null;
/** @type {string} */
FlowApi.prototype.pageName = null;
/** @type {string} */
@@ -289,7 +286,7 @@
* @param {Object} queryMap
* @return {jQuery.Promise}
*/
- function flowApiRequestFromNode( node, queryMap ) {
+ function flowApiRequestFromNode( node ) {
var $node = $( node );
if ( $node.is( 'a' ) ) {
@@ -312,15 +309,16 @@
* @return {undefined|jQuery.Promise}
*/
function flowApiAbortOldRequestFromNode( $node, queryMap, startNewMethod ) {
+ var str, prevApiCall, newApiCall;
+
$node = $( $node );
// transform flow_* params into (nt_*, rep_*, ...)
queryMap = flowApiTransformMap( queryMap );
// If this anchor already has a request in flight, abort it
- var str = 'flow-api-query-temp-' + queryMap.action + '-' + queryMap.submodule,
- prevApiCall = $node.data( str ),
- newApiCall;
+ str = 'flow-api-query-temp-' + queryMap.action + '-' + queryMap.submodule;
+ prevApiCall = $node.data( str );
// If a previous API call was found, let's abort it
if ( prevApiCall ) {
diff --git a/Flow/modules/engine/misc/flow-eventlog.js b/Flow/modules/engine/misc/flow-eventlog.js
index a1024452..14e12d51 100644
--- a/Flow/modules/engine/misc/flow-eventlog.js
+++ b/Flow/modules/engine/misc/flow-eventlog.js
@@ -1,9 +1,13 @@
( function ( mw, $ ) {
+ var FlowEventLogRegistry = {
+ funnels: {},
+ generateFunnelId: mw.user.generateRandomSessionId
+ };
+
/**
+ * @constructor
* @param {string} schemaName Canonical schema name.
* @param {Object} [eventInstance] Shared event instance data.
- * @return {FlowEventLog}
- * @constructor
*/
function FlowEventLog( schemaName, eventInstance ) {
this.schemaName = schemaName;
@@ -12,33 +16,16 @@
/**
* @param {Object} eventInstance Additional event instance data for this
* particular event.
- * @return {jQuery.Promise}
*/
function logEvent( eventInstance ) {
- // Ensure eventLog & this schema exist, or return a stub deferred
- if ( !mw.eventLog || !mw.eventLog.schemas[ this.schemaName ] ) {
- return $.Deferred().promise();
- }
-
- return mw.eventLog.logEvent(
- this.schemaName,
+ mw.track(
+ 'event.' + this.schemaName,
$.extend( this.eventInstance, eventInstance )
);
}
this.logEvent = logEvent;
}
- var FlowEventLogRegistry = {
- funnels: {},
-
- /**
- * Generates a unique id.
- *
- * @return {string}
- */
- generateFunnelId: mw.user.generateRandomSessionId
- };
-
// Export
/**
* EventLogging wrapper
diff --git a/Flow/modules/engine/misc/flow-handlebars.js b/Flow/modules/engine/misc/flow-handlebars.js
index 65c5ecc3..4cc5d673 100644
--- a/Flow/modules/engine/misc/flow-handlebars.js
+++ b/Flow/modules/engine/misc/flow-handlebars.js
@@ -3,21 +3,20 @@
*/
( function ( mw, $, moment, Handlebars ) {
- mw.flow = mw.flow || {}; // create mw.flow globally
-
var _tplcache = {},
_timestamp = {
- list: [],
- currentIndex: 0
- };
+ list: [],
+ currentIndex: 0
+ };
+
+ mw.flow = mw.flow || {}; // create mw.flow globally
/**
* Instantiates a FlowHandlebars instance for TemplateEngine.
- * @param {Object} FlowStorageEngine
* @return {FlowHandlebars}
* @constructor
*/
- function FlowHandlebars( FlowStorageEngine ) {
+ function FlowHandlebars() {
return this;
}
@@ -86,10 +85,10 @@
/**
* A method to call helper functions from outside templates. This removes Handlebars.SafeString wrappers.
* @param {string} helperName
- * @param {...*} [args]
- * @return mixed
+ * @param {...Mixed} [args]
+ * @return {Mixed}
*/
- FlowHandlebars.prototype.callHelper = function ( helperName, args ) {
+ FlowHandlebars.prototype.callHelper = function ( helperName ) {
var result = this[ helperName ].apply( this, Array.prototype.slice.call( arguments, 1 ) );
if ( result && result.string ) {
return result.string;
@@ -189,7 +188,7 @@
* @param {Object} [options]
* @return {string}
*/
- FlowHandlebars.prototype.l10n = function ( str /*, args..., options */ ) {
+ FlowHandlebars.prototype.l10n = function ( str /* , args..., options */ ) {
// chop off str and options leaving just args
var args = flowNormalizeL10nParameters( Array.prototype.slice.call( arguments, 1, -1 ) );
@@ -198,9 +197,11 @@
/**
* HTML-safe version of l10n.
+ *
+ * @param {string} str
* @return {string|Handlebars.SafeString}
*/
- FlowHandlebars.prototype.l10nParse = function ( str /*, args..., options */ ) {
+ FlowHandlebars.prototype.l10nParse = function ( str /* , args..., options */ ) {
var args = flowNormalizeL10nParameters( Array.prototype.slice.call( arguments, 1, -1 ) );
return FlowHandlebars.prototype.html(
@@ -232,13 +233,14 @@
* @return {string}
*/
FlowHandlebars.prototype.timestamp = function ( timestamp ) {
+ var guid, formatter;
+
if ( isNaN( timestamp ) ) {
mw.flow.debug( '[timestamp] Invalid arguments', arguments );
return;
}
- var guid,
- formatter = moment( timestamp );
+ formatter = moment( timestamp );
// Generate a GUID for this element to find it later
guid = ( Math.random() + 1 ).toString( 36 ).substring( 2 );
@@ -326,7 +328,7 @@
setTimeout( timestampAutoUpdate, 100 );
}
- $( document ).ready( timestampAutoUpdate );
+ $( timestampAutoUpdate );
/**
* Do not escape HTML string. Used as a Handlebars helper.
@@ -348,7 +350,7 @@
* @param {Object} options
* @return {string}
*/
- FlowHandlebars.prototype.workflowBlock = function ( context, options ) {
+ FlowHandlebars.prototype.workflowBlock = function ( context ) {
return FlowHandlebars.prototype.html( FlowHandlebars.prototype.processTemplate(
'flow_block_' + context.type + ( context[ 'block-action-template' ] || '' ),
context
@@ -362,7 +364,7 @@
* @param {Object} options
* @return {string}
*/
- FlowHandlebars.prototype.postBlock = function ( context, revision, options ) {
+ FlowHandlebars.prototype.postBlock = function ( context, revision ) {
return FlowHandlebars.prototype.html( FlowHandlebars.prototype.processTemplate(
'flow_post',
{
@@ -423,6 +425,7 @@
}
return FlowHandlebars.prototype.html(
+ // eslint-disable-next-line no-useless-concat
'<scr' + 'ipt' +
' type="text/x-handlebars-template-progressive-enhancement"' +
' data-type="' + hash.type + '"' +
@@ -430,15 +433,16 @@
( hash.id ? ' id="' + hash.id + '"' : '' ) +
'>' +
inner +
+ // eslint-disable-next-line no-useless-concat
'</scr' + 'ipt>'
);
};
/**
* Runs a callback when user is anonymous
- * @param array $options which must contain fn and inverse key mapping to functions.
*
- * @return mixed result of callback
+ * @param {Object} options which must contain fn and inverse key mapping to functions.
+ * @return {Mixed} result of callback
*/
FlowHandlebars.prototype.ifAnonymous = function ( options ) {
if ( mw.user.isAnon() ) {
@@ -449,9 +453,9 @@
/**
* Adds returnto parameter pointing to given Title to an existing URL
- * @param string $title
*
- * @return string modified url
+ * @param {string} title
+ * @return {string} modified url
*/
FlowHandlebars.prototype.linkWithReturnTo = function ( title ) {
return mw.util.getUrl( title, {
@@ -476,7 +480,7 @@
* @return {string}
*/
FlowHandlebars.prototype.escapeContent = function ( contentType, content ) {
- if ( contentType === 'html' || contentType === 'fixed-html' ) {
+ if ( contentType === 'html' || contentType === 'fixed-html' || contentType === 'topic-title-html' ) {
return FlowHandlebars.prototype.html( content );
}
return content;
@@ -534,6 +538,8 @@
* @param {string} value
* @param {string} operator supported values: 'or'
* @param {string} value2
+ * @param {Object} options
+ * @return {string}
*/
FlowHandlebars.prototype.ifCond = function ( value, operator, value2, options ) {
if ( operator === 'or' ) {
@@ -558,8 +564,8 @@
};
// Load partials
- $.each( mw.templates.values, function ( moduleName ) {
- $.each( this, function ( name ) {
+ $.each( mw.templates.get(), function ( moduleName, moduleTemplates ) {
+ $.each( moduleTemplates, function ( name ) {
// remove extension
var partialMatch, partialName;
diff --git a/Flow/modules/engine/misc/jquery.conditionalScroll.js b/Flow/modules/engine/misc/jquery.conditionalScroll.js
index 3a25abdf..b09f871e 100644
--- a/Flow/modules/engine/misc/jquery.conditionalScroll.js
+++ b/Flow/modules/engine/misc/jquery.conditionalScroll.js
@@ -6,6 +6,7 @@
* 2. If el ends below viewport and fits into viewport, scrolls to put bottom of el at bottom of viewport.
* 3. If el ends below viewport but is taller than the viewport, scrolls to put top of el at top of viewport.
* @param {string|number} [speed='fast']
+ * @return {jQuery}
*/
$.fn.conditionalScrollIntoView = function ( speed ) {
speed = speed !== undefined ? speed : 'fast';
diff --git a/Flow/modules/engine/misc/mw-ui.enhance.js b/Flow/modules/engine/misc/mw-ui.enhance.js
index e82aab12..4478c90d 100644
--- a/Flow/modules/engine/misc/mw-ui.enhance.js
+++ b/Flow/modules/engine/misc/mw-ui.enhance.js
@@ -12,7 +12,7 @@ mw.flow.ui.enhance = {};
* This will make unhovered and unfocused sibling buttons become faded and blurred
* Usage: Buttons must be in a form, or in a parent with mw-ui-button-container, or they must be siblings
*/
- $( document ).ready( function () {
+ $( function () {
function onMwUiButtonFocus( event ) {
var $el, $form, $siblings;
@@ -43,14 +43,14 @@ mw.flow.ui.enhance = {};
}
function onMwUiButtonBlur( event ) {
+ var $el, $form, $siblings, $focused;
+
if ( event.target.className.indexOf( 'mw-ui-button' ) === -1 ) {
// Not a button event
return;
}
- var $el = $( event.target ),
- $form, $siblings, $focused;
-
+ $el = $( event.target );
$form = $el.closest( 'form, .mw-ui-button-container' );
if ( $form.length ) {
// If this button is in a form, apply this to all the form's buttons.
@@ -122,7 +122,7 @@ mw.flow.ui.enhance = {};
* Disable / enable submit buttons without/with text in field.
* Usage: field needs required attribute
*/
- $( document ).ready( function () {
+ $( function () {
// We should probably not use this change detection method for VE
//
// Also, consider using the input event (which I think can replace all of these
@@ -147,7 +147,7 @@ mw.flow.ui.enhance = {};
* mw-ui-tooltip
* Renders tooltips on over, and also via mw.tooltip.
*/
- $( document ).ready( function () {
+ $( function () {
var _$tooltip = $(
'<span class="flow-ui-tooltip flow-ui-tooltip-left">' +
'<span class="flow-ui-tooltip-content"></span>' +
@@ -162,7 +162,7 @@ mw.flow.ui.enhance = {};
* Renders a tooltip at target.
* Options (either given as param, or fetched from target as data-tooltip-x params):
* tooltipSize=String (small,large,block)
- * tooltipContext=String (constructive,destructive,progressive,regressive)
+ * tooltipContext=String (progressive,destructive)
* tooltipPointing=String (up,down,left,right)
* tooltipClosable=Boolean
* tooltipContentCallback=Function
@@ -171,6 +171,7 @@ mw.flow.ui.enhance = {};
* @param {jQuery|HTMLElement|string} [content] A jQuery set, an element, or a string of
* HTML. If omitted, first tries tooltipContentCallback, then target.title
* @param {Object} [options]
+ * @return {jQuery}
*/
function mwUiTooltipShow( target, content, options ) {
var $target = $( target ),
@@ -252,8 +253,6 @@ mw.flow.ui.enhance = {};
if ( !optionsUnreferenced.tooltipContext ) {
if ( $target.hasClass( 'mw-ui-progressive' ) ) {
optionsUnreferenced.tooltipContext = 'progressive';
- } else if ( $target.hasClass( 'mw-ui-constructive' ) ) {
- optionsUnreferenced.tooltipContext = 'constructive';
} else if ( $target.hasClass( 'mw-ui-destructive' ) ) {
optionsUnreferenced.tooltipContext = 'destructive';
}
@@ -262,9 +261,8 @@ mw.flow.ui.enhance = {};
$tooltip
// Add the content to it
.find( '.flow-ui-tooltip-content' )
- .empty()
- [ insertFn ]( content )
- .end()
+ .empty()[ insertFn ]( content );
+ $tooltip
// Move this off-page before rendering it, so that we can calculate its real dimensions
// @todo use .parent() loop to check for z-index and + that to this if needed
.css( { position: 'absolute', zIndex: 1000, top: 0, left: '-999em' } )
@@ -274,7 +272,7 @@ mw.flow.ui.enhance = {};
// Tooltip style context
if ( optionsUnreferenced.tooltipContext ) {
- $tooltip.removeClass( 'mw-ui-progressive mw-ui-constructive mw-ui-destructive' );
+ $tooltip.removeClass( 'mw-ui-progressive mw-ui-destructive' );
$tooltip.addClass( 'mw-ui-' + optionsUnreferenced.tooltipContext );
}
@@ -425,17 +423,17 @@ mw.flow.ui.enhance = {};
/**
* Event handler for mouse entering on a .flow-ui-tooltip-target
- * @param {Event} event
+ * @param {jQuery.Event} event
*/
- function onMwUiTooltipFocus( event ) {
+ function onMwUiTooltipFocus() {
mw.tooltip.show( this );
}
/**
* Event handler for mouse leaving a .flow-ui-tooltip-target
- * @param {Event} event
+ * @param {jQuery.Event} event
*/
- function onMwUiTooltipBlur( event ) {
+ function onMwUiTooltipBlur() {
mw.tooltip.hide( this );
}
@@ -444,35 +442,4 @@ mw.flow.ui.enhance = {};
.on( 'mouseenter.mw-ui-enhance focus.mw-ui-enhance', '.flow-ui-tooltip-target', onMwUiTooltipFocus )
.on( 'mouseleave.mw-ui-enhance blur.mw-ui-enhance click.mw-ui-enhance', '.flow-ui-tooltip-target', onMwUiTooltipBlur );
} );
-
- /**
- * Ask a user to confirm navigating away from a page when they have entered unsubmitted changes to a form.
- */
- var _oldOnBeforeUnload = window.onbeforeunload;
- window.onbeforeunload = function () {
- var uncommitted,
- hasValue, currentValue, defaultValue, placeholderText;
-
- $( 'input, textarea' ).filter( '.mw-ui-input:visible' ).each( function () {
- hasValue = !!$.trim( this.value );
- currentValue = this.value;
- defaultValue = this.defaultValue;
- placeholderText = $( this ).attr( 'placeholder' );
-
- if ( hasValue && currentValue !== defaultValue && currentValue !== placeholderText ) {
- uncommitted = true;
- return false;
- }
- } );
-
- // Ask the user if they want to navigate away
- if ( uncommitted ) {
- return mw.msg( 'mw-ui-unsubmitted-confirm' );
- }
-
- // Run the old on beforeunload fn if it exists
- if ( _oldOnBeforeUnload ) {
- return _oldOnBeforeUnload();
- }
- };
}( mw, jQuery ) );
diff --git a/Flow/modules/engine/misc/mw-ui.modal.js b/Flow/modules/engine/misc/mw-ui.modal.js
index 6085e5ce..c851b6cd 100644
--- a/Flow/modules/engine/misc/mw-ui.modal.js
+++ b/Flow/modules/engine/misc/mw-ui.modal.js
@@ -77,12 +77,12 @@
'<div class="flow-ui-modal-layout">' +
'<div class="flow-ui-modal-heading">' +
'<a href="#" class="mw-ui-anchor mw-ui-quiet mw-ui-destructive flow-ui-modal-heading-prev" data-flow-interactive-handler="modalPrevOrClose"><span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-close"></span></a>' +
- '<a href="#" class="mw-ui-anchor mw-ui-quiet mw-ui-constructive flow-ui-modal-heading-next" data-flow-interactive-handler="modalNextOrSubmit"><span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check"></span></a>' +
- // title
+ '<a href="#" class="mw-ui-anchor mw-ui-quiet mw-ui-progressive flow-ui-modal-heading-next" data-flow-interactive-handler="modalNextOrSubmit"><span class="mw-ui-icon mw-ui-icon-before mw-ui-icon-check"></span></a>' +
+ // title
'</div>' +
'<div class="flow-ui-modal-content">' +
- // content
+ // content
'</div>' +
'</div>' +
'</div>';
@@ -179,11 +179,12 @@
return this;
};
+ // eslint-disable-next-line valid-jsdoc
/**
* Changes the title of the modal.
*
* @param {string|null} title
- * @return MwUiModal
+ * @return {MwUiModal}
*/
MwUiModal.prototype.setTitle = function ( title ) {
var $heading = this.getNode().find( this.headingSelector ),
@@ -213,6 +214,7 @@
/**
* @todo Implement data-mwui handlers, currently using data-flow
+ * @return {boolean}
*/
MwUiModal.prototype.setInteractiveHandler = function () {
return false;
@@ -220,6 +222,8 @@
/**
* Returns modal name.
+ *
+ * @return {string}
*/
MwUiModal.prototype.getName = function () {
return this.name;
@@ -274,7 +278,7 @@
* @param {Object|HTMLElement|HTMLElement[]|jQuery|string} contents
* @return {MwUiModal}
*/
- MwUiModal.prototype.addSteps = function ( contents ) {
+ MwUiModal.prototype.addSteps = function () {
return false;
};
@@ -289,7 +293,7 @@
* @param {HTMLElement|jQuery|string} contents
* @return {MwUiModal}
*/
- MwUiModal.prototype.setStep = function ( to, contents ) {
+ MwUiModal.prototype.setStep = function () {
return false;
};
@@ -300,7 +304,7 @@
*
* @return {Object}
*/
- MwUiModal.prototype.getSteps = function ( to, contents ) {
+ MwUiModal.prototype.getSteps = function () {
return {};
};
@@ -367,7 +371,7 @@
* @param {number|string} to
* @return {MwUiModal|boolean} false if invalid step, MwUiModal on success
*/
- MwUiModal.prototype.go = function ( to ) {
+ MwUiModal.prototype.go = function () {
return false;
};
diff --git a/Flow/modules/flow-initialize.js b/Flow/modules/flow-initialize.js
index 1f13d44f..7a83b5b7 100644
--- a/Flow/modules/flow-initialize.js
+++ b/Flow/modules/flow-initialize.js
@@ -1,366 +1,75 @@
/*!
* Runs Flow code, using methods in FlowUI.
*/
-
( function ( $ ) {
// Pretend we got some data and run with it
/*
* Now do stuff
* @todo not like this
*/
- $( document ).ready( function () {
- var dataBlob, navWidget, flowBoard, dmBoard, newTopicWidget, sidebarExpandWidget, descriptionWidget,
- siderailCollapsed = mw.user.options.get( 'flow-side-rail-state' ) === 'collapsed',
- pageTitle = mw.Title.newFromText( mw.config.get( 'wgPageName' ) ),
+ $( function () {
+ var flowBoard,
$component = $( '.flow-component' ),
$board = $( '.flow-board' ),
- preloadTopic, preloadContent, preloadFormat,
- finishLoading = function () {
- $component.addClass( 'flow-component-ready' );
- $( '.flow-ui-load-overlay' ).hide();
- };
-
- // HACK: If there is no component, we are not on a flow
- // board at all, and there's no need to load anything.
- // This is especially true for tests, though we should
- // fix this by telling ResourceLoader to not load
- // flow-initialize at all on tests.
- if ( $component.length === 0 ) {
- finishLoading();
- return;
- }
-
- mw.flow.initComponent( $component );
+ pageTitle = mw.Title.newFromText( mw.config.get( 'wgPageName' ) ),
+ initializer = new mw.flow.Initializer( {
+ pageTitle: pageTitle,
+ $component: $component,
+ $board: $board
+ } );
- // HACK: Similarly to the above hack, if there is no board
- // we shouldn't proceed. This is true mainly to history pages
- // that have the component but not the board DOM element.
- if ( $board.length === 0 ) {
- finishLoading();
+ // Set component
+ if ( !initializer.setComponentDom( $component ) ) {
+ initializer.finishLoading();
return;
}
- // Set up window overlay
- $( 'body' ).append( mw.flow.ui.windowOverlay.$element );
- mw.flow.ui.windowOverlay.$element.append( mw.flow.ui.windowManager.$element );
-
- flowBoard = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $board );
-
- if (
- $component.hasClass( 'topic-page' ) &&
- $( 'body' ).hasClass( 'action-view' )
- ) {
- $board
- .toggleClass( 'flow-board-expanded', siderailCollapsed );
- // We are in single-topic view. Initialize the sidebar expand widget
- sidebarExpandWidget = new mw.flow.ui.SidebarExpandWidget( {
- collapsed: siderailCollapsed,
- expandedButtonTitle: mw.msg( 'flow-topic-collapse-siderail' ),
- collapsedButtonTitle: mw.msg( 'flow-topic-expand-siderail' )
+ // Initialize old system
+ initializer.initOldComponent();
+ // Initialize board
+ if ( initializer.setBoardDom( $board ) ) {
+ // Set up flowBoard
+ flowBoard = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $board );
+ initializer.setBoardObject( flowBoard );
+
+ // Initialize DM system and board
+ initializer.initDataModel( {
+ pageTitle: pageTitle,
+ tocPostsLimit: 50,
+ renderedTopics: $( '.flow-topic' ).length,
+ boardId: $component.data( 'flow-id' ),
+ defaultSort: $board.data( 'flow-sortby' )
} );
- sidebarExpandWidget.$element.insertAfter( $board );
- sidebarExpandWidget.on( 'toggle', function ( collapsed ) {
- $board.toggleClass( 'flow-board-expanded', collapsed );
- } );
- }
-
- // Load data model
- mw.flow.system = new mw.flow.dm.System( {
- pageTitle: pageTitle,
- tocPostsLimit: 50,
- renderedTopics: $( '.flow-topic' ).length,
- boardId: $component.data( 'flow-id' ),
- defaultSort: $board.data( 'flow-sortby' )
- } );
-
- dmBoard = mw.flow.system.getBoard();
- dmBoard.on( 'add', function ( newItems ) {
- var i, len, item, itemId;
-
- for ( i = 0, len = newItems.length; i < len; i++ ) {
- item = newItems[ i ];
- itemId = item.getId();
-
- if ( $.inArray( itemId, flowBoard.orderedTopicIds ) === -1 ) {
- flowBoard.orderedTopicIds.push( itemId );
- }
-
- flowBoard.topicTitlesById[ itemId ] = item.getContent();
- flowBoard.updateTimestampsByTopicId[ itemId ] = item.getLastUpdate();
- }
- flowBoard.sortTopicIds( flowBoard );
- } );
-
- // E.g. on topic re-order, before re-population.
- dmBoard.on( 'clear', function () {
- flowBoard.orderedTopicIds = [];
- flowBoard.topicTitlesById = {};
- } );
- // We shouldn't have to worry about 'remove', since by the time we have filtering,
- // orderedTopicIds should be gone.
-
- // Initialize the old system to accept the default
- // 'newest' order for the topic order widget
- // Get the current default sort
- flowBoard.topicIdSort = mw.flow.system.getBoard().getSortOrder();
-
- /* UI Widgets */
- navWidget = new mw.flow.ui.NavigationWidget( mw.flow.system, {
- defaultSort: flowBoard.topicIdSort
- } );
- $( '.flow-board-navigation' ).append( navWidget.$element );
-
- // Board description widget
- descriptionWidget = new mw.flow.ui.BoardDescriptionWidget( dmBoard, {
- $existing: $( '.flow-ui-boardDescriptionWidget-content' ).contents()
- } );
- $( '.flow-ui-boardDescriptionWidget' ).replaceWith( descriptionWidget.$element );
-
- // HACK: These event handlers should be in the prospective widgets
- // they will move once we have Board UI and Topic UI widgets
- mw.flow.system.on( 'resetBoardStart', function () {
- $component.addClass( 'flow-api-inprogress' );
- // Before we reinitialize the board we have to detach
- // the navigation widget. This should not be necessary when
- // the board and topics are OOUI widgets
- navWidget.$element.detach();
- } );
-
- mw.flow.system.on( 'resetBoardEnd', function ( data ) {
- var $rendered;
-
- // HACK: Trim the data for only the rendered topics
- // We can't have the API request use a limit because when we
- // rebuild the board (when we reorder) we want the full 50
- // topics for the ToC widget. When the topic- and board-widget
- // are operational, we should render properly without using this
- // hack.
- data.topiclist.roots = data.topiclist.roots.splice( 0, mw.flow.system.getRenderedTopics() );
-
- $rendered = $(
- mw.flow.TemplateEngine.processTemplateGetFragment(
- 'flow_block_loop',
- { blocks: data }
- )
- ).children();
- // Run this on a short timeout so that the other board handler in FlowBoardComponentLoadMoreFeatureMixin can run
- // TODO: Using a timeout doesn't seem like the right way to do this.
- setTimeout( function () {
- // Reinitialize the whole board with these nodes
- // flowBoard.reinitializeContainer( $rendered );
- $board.empty().append( $rendered[ 1 ] );
-
- // Since we've replaced the entire board, we need to reinitialize
- // it. This also takes away the original navWidget, so we need to
- // make sure it's reinitialized too
- flowBoard.reinitializeContainer( $rendered );
- $( '.flow-board-navigation' ).append( navWidget.$element );
-
- $component.removeClass( 'flow-api-inprogress' );
- }, 50 );
-
- } );
-
- // HACK: On load more, populate the board dm
- flowBoard.on( 'loadmore', function ( topiclist ) {
- // Add to the DM board
- mw.flow.system.populateBoardTopicsFromJson( topiclist );
- } );
- // HACK: Update the DM when topic is refreshed
- flowBoard.on( 'refreshTopic', function ( workflowId, topicData ) {
- var revisionId, revision,
- topic = dmBoard.getItemById( workflowId ),
- data = topicData.flow[ 'view-topic' ].result.topic;
+ // For reference and debugging
+ mw.flow.system = initializer.getDataModelSystem();
- if ( !topic ) {
- // New topic
- mw.flow.system.populateBoardTopicsFromJson( data, 0 );
+ if ( initializer.isUndoForm() ) {
+ // Setup undo pages
+ initializer.setupUndoPage();
} else {
- // Topic already exists. Repopulate
- revisionId = data.posts[ workflowId ];
- revision = data.revisions[ revisionId ];
- topic.populate( revision );
- }
-
- replaceReplyForms( topicData.$topic );
- deactivateReplyLinks( topicData.$topic );
-
- // Cancel the interactive handler so "old" system doesn't get triggered for internal replies
- $( '[data-flow-interactive-handler="activateReplyPost"]' ).attr( 'data-flow-interactive-handler', '' );
- } );
-
- // Load a topic from the ToC that isn't rendered on
- // the page yet. This will be gone once board, topic
- // and post are widgetized.
- navWidget.on( 'loadTopic', function ( topicId ) {
- flowBoard.jumpToTopic( topicId );
- } );
- navWidget.on( 'reorderTopics', function ( newOrder ) {
- flowBoard.topicIdSort = newOrder;
- } );
-
- // Replace reply inputs with the editor widget
- function replaceReplyForms( $element ) {
- $element.find( '.flow-post.flow-reply-form' ).each( function () {
- var $topic = $( this ).parent(),
- placeholder = mw.msg( 'flow-reply-topic-title-placeholder', $topic.find( '.flow-topic-title' ).text().trim() ),
- replyTo = $( this ).find( 'input[name="topic_replyTo"]' ).val(),
- replyWidget = new mw.flow.ui.ReplyWidget( $topic.data( 'flowId' ), replyTo, {
- placeholder: placeholder
- } );
-
- replyWidget.on( 'saveContent', function ( workflow ) {
- replyWidget.destroy();
- replyWidget.$element.remove();
-
- // HACK get the old system to rerender the topic
- return flowBoard.flowBoardComponentRefreshTopic(
- $topic,
- workflow
- );
- } );
- replyWidget.$element.data( 'self', replyWidget );
-
- // Replace the reply form with the new editor widget
- $( this ).replaceWith( replyWidget.$element );
- } );
- }
- replaceReplyForms( $board );
-
- // Replace the 'reply' buttons so they all produce replyWidgets rather
- // than the reply forms from the API
- $board
- .on( 'click', '.flow-ui-reply-link-trigger', function () {
- var replyWidget,
- $topic = $( this ).closest( '.flow-topic' ),
- placeholder = mw.msg( 'flow-reply-topic-title-placeholder', $topic.find( '.flow-topic-title' ).text().trim() ),
- replyTo = $( this ).data( 'postId' ),
- // replyTo can refer to a post ID or a topic ID
- // For posts, the ReplyWidget should go in .flow-replies
- // For topics, it's directly inside the topic
- $targetContainer = $( '#flow-post-' + replyTo + ' > .flow-replies, #flow-topic-' + replyTo ),
- $existingWidget = $targetContainer.children( '.flow-ui-replyWidget' );
-
- // Check that there's not already a reply widget existing in the same place
- if ( $existingWidget.length > 0 ) {
- // Focus the existing reply widget
- $existingWidget.data( 'self' ).activateEditor();
- $existingWidget.data( 'self' ).focus();
- return false;
- }
-
- replyWidget = new mw.flow.ui.ReplyWidget( $topic.data( 'flowId' ), replyTo, {
- placeholder: placeholder,
- expandable: false
- } );
- // Create a reference so we can call it from the DOM above
- replyWidget.$element.data( 'self', replyWidget );
-
- // Add reply form below the post being replied to (WRT max depth)
- $targetContainer.append( replyWidget.$element );
- replyWidget.activateEditor();
-
- replyWidget
- .on( 'saveContent', function ( workflow ) {
- replyWidget.destroy();
- replyWidget.$element.remove();
+ // Replace the no-js editor if we are editing in a
+ // new page
+ initializer.replaceNoJSEditor( $( '.flow-edit-post-form' ) );
- // HACK get the old system to rerender the topic
- return flowBoard.flowBoardComponentRefreshTopic(
- $topic,
- workflow
- );
- } )
- .on( 'cancel', function () {
- replyWidget.destroy();
- replyWidget.$element.remove();
- } );
+ // Create and replace UI widgets
+ initializer.initializeWidgets();
- return false;
- } );
-
- function deactivateReplyLinks( $element ) {
- // Cancel the interactive handler so "old" system doesn't get triggered for internal replies
- $element.find( '[data-flow-interactive-handler="activateReplyPost"]' ).each( function () {
- // Store the needed details so we can get rid of the URL in JS mode
- var href = $( this ).attr( 'href' ),
- uri = new mw.Uri( href ),
- postId = uri.query.topic_postId;
-
- $( this )
- .data( 'postId', postId )
- .attr( 'data-flow-interactive-handler', '' )
- .attr( 'href', '' )
- .addClass( 'flow-ui-reply-link-trigger' );
- } );
- }
- deactivateReplyLinks( $board );
-
- // New topic form
- newTopicWidget = new mw.flow.ui.NewTopicWidget( pageTitle.getPrefixedDb() );
- newTopicWidget.on( 'save', function ( newTopicId ) {
- // Display the new topic with the old system
- var $stub = $( '<div class="flow-topic"><div></div></div>' ).prependTo( flowBoard.$container.find( '.flow-topics' ) );
- return flowBoard.flowBoardComponentRefreshTopic( $stub.find( 'div' ), newTopicId );
- } );
- $( 'form.flow-newtopic-form' ).replaceWith( newTopicWidget.$element );
-
- $board.on( 'click', '.flow-ui-edit-post-link', function ( event ) {
- var editPostWidget,
- $topic = $( this ).closest( '.flow-topic' ),
- topicId = $topic.data( 'flow-id' ),
- $post = $( this ).closest( '.flow-post' ),
- $postMain = $post.children( '.flow-post-main' ),
- postId = $post.data( 'flow-id' ),
- $board = $( '.flow-board' ),
- flowBoard = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $board );
-
- editPostWidget = new mw.flow.ui.EditPostWidget( topicId, postId );
- editPostWidget
- .on( 'saveContent', function ( workflow ) {
- editPostWidget.destroy();
- editPostWidget.$element.remove();
-
- // HACK get the old system to rerender the topic
- return flowBoard.flowBoardComponentRefreshTopic(
- $topic,
- workflow
- );
- } )
- .on( 'cancel', function () {
- editPostWidget.$element.replaceWith( $postMain );
- editPostWidget.destroy();
- } );
-
- $postMain.replaceWith( editPostWidget.$element );
-
- event.preventDefault();
- } );
-
- // Fall back to mw.flow.data, which was used until September 2015
- dataBlob = mw.config.get( 'wgFlowData' ) || ( mw.flow && mw.flow.data );
- if ( dataBlob && dataBlob.blocks ) {
- // Populate the rendered topics or topic (if we are in a single-topic view)
- mw.flow.system.populateBoardTopicsFromJson( dataBlob.blocks.topiclist || dataBlob.blocks.topic );
- // Populate header
- mw.flow.system.populateBoardDescriptionFromJson( dataBlob.blocks.header || {} );
- // Populate the ToC topics
- if ( dataBlob.toc ) {
- mw.flow.system.populateBoardTopicsFromJson( dataBlob.toc );
+ // Fall back to mw.flow.data, which was used until September 2015
+ // NOTICE: This block must be after the initialization of the ui widgets so
+ // they can populate themselves according to the events.
+ initializer.populateDataModel( mw.config.get( 'wgFlowData' ) || ( mw.flow && mw.flow.data ) );
}
} else {
- mw.flow.system.populateBoardFromApi();
- }
-
- preloadTopic = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'topic' );
- preloadContent = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'content' );
- preloadFormat = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'format' );
- if ( preloadTopic || preloadContent ) {
- newTopicWidget.preload( preloadTopic, preloadContent, preloadFormat );
+ // Editing summary in a separate window. That has no
+ // flow-board, but we should still replace the widget
+ initializer.startEditTopicSummary(
+ false,
+ $component.data( 'flow-id' )
+ );
}
// Show the board
- finishLoading();
+ initializer.finishLoading();
} );
}( jQuery ) );
diff --git a/Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js b/Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js
index 4be0210f..84c446e8 100644
--- a/Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js
+++ b/Flow/modules/flow/dm/api/mw.flow.dm.APIHandler.js
@@ -27,7 +27,8 @@
this.setCurrentRevision( config.currentRevision );
this.requestParams = $.extend( {
- action: 'flow'
+ action: 'flow',
+ uselang: mw.config.get( 'wgUserLanguage' )
}, config.requestParams );
};
@@ -73,13 +74,58 @@
mw.flow.dm.APIHandler.prototype.postEdit = function ( submodule, requestParams ) {
var params = $.extend( { submodule: submodule }, this.requestParams, requestParams );
- return ( new mw.Api() ).postWithToken( 'edit', params );
+ return ( new mw.Api() ).postWithToken( 'csrf', params );
+ };
+
+ /**
+ * Get page categories. This will recursively continue to fetch results
+ * until all page categories are fetched.
+ *
+ * @return {jQuery.Promise} Promise that is resolved when the API request
+ * is done, with the API result.
+ */
+ mw.flow.dm.APIHandler.prototype.getCategories = function () {
+ var params = {
+ action: 'query',
+ titles: this.page,
+ generator: 'categories',
+ gcllimit: 'max'
+ };
+
+ return ( new mw.Api() ).get( $.extend( {}, this.requestParams, params ) )
+ .then( function ( response ) {
+ return OO.getProp( response, 'query', 'pages' );
+ } );
+ };
+
+ /**
+ * Gets the reason the page was protected
+ *
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {string} return.done.reason Reason, as HTML
+ */
+ mw.flow.dm.APIHandler.prototype.getProtectionReason = function () {
+ var params = {
+ action: 'query',
+ list: 'logevents',
+ leprop: 'parsedcomment',
+ leaction: 'protect/protect',
+ letitle: this.page,
+ lelimit: 1
+ };
+
+ return ( new mw.Api() ).get( $.extend( {}, this.requestParams, params ) )
+ .then( function ( response ) {
+ return OO.getProp( response, 'query', 'logevents', 0, 'parsedcomment' );
+ } );
};
/**
* Send a request to get topic list
*
* @param {string} orderType Sort order type, 'newest' or 'updated'
+ * @param {Object} config Configuration
* @cfg {string} [offset] Topic offset id or timestamp offset
* if given, the topic list will be returned with topics that
* are after (and including) the topic with the given uuid or
@@ -97,6 +143,7 @@
params.vtltoconly = !!config.toconly;
params.vtllimit = config.toconly ? 50 : 10;
+ params.vtlsortby = orderType;
if ( orderType === 'newest' ) {
params[ 'vtloffset-id' ] = config.offset;
@@ -114,9 +161,10 @@
/**
* Adds CAPTCHA to parameters if applicable
*
- * @param {Object} captcha CAPTCHA object
- * @param {string} id CAPTCHA ID
- * @param {string} answer CAPTCHA answer (user-provided)
+ * @param {Object} params API Parameters to add CAPTCHA information to
+ * @param {Object|null} captcha CAPTCHA object
+ * @param {string} captcha.id CAPTCHA ID
+ * @param {string} captcha.answer CAPTCHA answer (user-provided)
*/
mw.flow.dm.APIHandler.prototype.addCaptcha = function ( params, captcha ) {
// TODO: Find a better way to plug this in.
@@ -159,7 +207,7 @@
this.addCaptcha( params, captcha );
- return ( new mw.Api() ).postWithToken( 'edit', params )
+ return ( new mw.Api() ).postWithToken( 'csrf', $.extend( {}, this.requestParams, params ) )
.then( function ( data ) {
return data.flow.reply.workflow;
} );
@@ -176,7 +224,6 @@
*/
mw.flow.dm.APIHandler.prototype.saveNewTopic = function ( title, content, format, captcha ) {
var params = {
- action: 'flow',
submodule: 'new-topic',
page: this.page,
nttopic: title,
@@ -186,7 +233,7 @@
this.addCaptcha( params, captcha );
- return ( new mw.Api() ).postWithToken( 'edit', params )
+ return ( new mw.Api() ).postWithToken( 'csrf', $.extend( {}, this.requestParams, params ) )
.then( function ( response ) {
return OO.getProp( response.flow, 'new-topic', 'committed', 'topiclist', 'topic-id' );
} );
@@ -215,7 +262,7 @@
*
* @param {string} content Header content
* @param {string} format Content format for board description
- * @param {string} [captcha] CAPTCHA information
+ * @param {Object} [captcha] CAPTCHA information
* @return {jQuery.Promise} Promise that is resolved with the saved header revision id
*/
mw.flow.dm.APIHandler.prototype.saveDescription = function ( content, format, captcha ) {
@@ -229,7 +276,6 @@
this.addCaptcha( params, captcha );
- // return ( new mw.Api() ).postWithToken( 'edit', params )
xhr = this.postEdit( 'edit-header', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-header', 'committed', 'header', 'header-revision-id' );
@@ -241,6 +287,7 @@
/**
* Get a post.
*
+ * @param {string} topicId
* @param {string} postId
* @param {string} format
* @return {jQuery.Promise} Promise that is resolved with the post revision data
@@ -261,6 +308,7 @@
/**
* Save a post.
*
+ * @param {string} topicId
* @param {string} postId
* @param {string} content
* @param {string} format
@@ -268,23 +316,128 @@
* @return {jQuery.Promise} Promise that is resolved with the saved post revision id
*/
mw.flow.dm.APIHandler.prototype.savePost = function ( topicId, postId, content, format, captcha ) {
- var xhr,
- params = {
- page: this.getTopicTitle( topicId ),
- epcontent: content,
- epformat: format,
- epprev_revision: this.currentRevision,
- eppostId: postId
- };
+ var params = {
+ page: this.getTopicTitle( topicId ),
+ epcontent: content,
+ epformat: format,
+ epprev_revision: this.currentRevision,
+ eppostId: postId
+ };
this.addCaptcha( params, captcha );
- xhr = this.postEdit( 'edit-post', params )
+ return this.postEdit( 'edit-post', params )
.then( function ( data ) {
return OO.getProp( data.flow, 'edit-post', 'workflow' );
} );
+ };
- return xhr.promise( { abort: xhr.abort } );
+ /**
+ * Get a topic summary.
+ *
+ * @param {string} topicId
+ * @param {string} format
+ * @return {jQuery.Promise} Promise that is resolved with the topic summary revision
+ */
+ mw.flow.dm.APIHandler.prototype.getTopicSummary = function ( topicId, format ) {
+ var params = {
+ page: this.getTopicTitle( topicId ),
+ vtsformat: format || 'html'
+ };
+
+ return this.get( 'view-topic-summary', params )
+ .then( function ( data ) {
+ return data.topicsummary.revision;
+ } );
+ };
+
+ /**
+ * Save a topic summary.
+ *
+ * @param {string} topicId
+ * @param {string} content
+ * @param {string} format
+ * @param {Object} captcha
+ * @return {jQuery.Promise} Promise that is resolved with workflow id
+ */
+ mw.flow.dm.APIHandler.prototype.saveTopicSummary = function ( topicId, content, format, captcha ) {
+ var params = {
+ page: this.getTopicTitle( topicId ),
+ etssummary: content,
+ etsformat: format,
+ etsprev_revision: this.currentRevision
+ };
+
+ this.addCaptcha( params, captcha );
+
+ return this.postEdit( 'edit-topic-summary', params )
+ .then( function ( data ) {
+ return OO.getProp( data.flow, 'edit-topic-summary', 'workflow' );
+ } );
+ };
+
+ /**
+ * Save a topic title.
+ *
+ * @param {string} topicId
+ * @param {string} content
+ * @param {Object} captcha
+ * @return {jQuery.Promise} Promise that is resolved with workflow id
+ */
+ mw.flow.dm.APIHandler.prototype.saveTopicTitle = function ( topicId, content, captcha ) {
+ var params = {
+ page: this.getTopicTitle( topicId ),
+ etcontent: content,
+ etprev_revision: this.currentRevision
+ };
+
+ this.addCaptcha( params, captcha );
+
+ return this.postEdit( 'edit-title', params )
+ .then( function ( data ) {
+ return OO.getProp( data.flow, 'edit-title', 'workflow' );
+ } );
+ };
+
+ /**
+ * Execute the 'lock-topic' moderation action against a topic. Can be used to resolve or reopen a topic.
+ *
+ * @param {string} topicId Id of the topic to moderate
+ * @param {string} moderationState Can be 'lock' or 'unlock'
+ * @param {string} reasonMsgKey Message key for the moderation reason
+ * @return {jQuery.Promise} Promise that is resolved with workflow id
+ */
+ mw.flow.dm.APIHandler.prototype.lockTopic = function ( topicId, moderationState, reasonMsgKey ) {
+ var params = {
+ page: this.getTopicTitle( topicId ),
+ cotmoderationState: moderationState,
+ cotreason: mw.msg( reasonMsgKey )
+ };
+
+ return this.postEdit( 'lock-topic', params )
+ .then( function ( data ) {
+ return OO.getProp( data.flow, 'lock-topic', 'workflow' );
+ } );
+ };
+
+ /**
+ * Resolve a topic.
+ *
+ * @param {string} topicId
+ * @return {jQuery.Promise} Promise that is resolved with workflow id
+ */
+ mw.flow.dm.APIHandler.prototype.resolveTopic = function ( topicId ) {
+ return this.lockTopic( topicId, 'lock', 'flow-rev-message-lock-topic-reason' );
+ };
+
+ /**
+ * Reopen a topic.
+ *
+ * @param {string} topicId
+ * @return {jQuery.Promise} Promise that is resolved with workflow id
+ */
+ mw.flow.dm.APIHandler.prototype.reopenTopic = function ( topicId ) {
+ return this.lockTopic( topicId, 'unlock', 'flow-rev-message-restore-topic-reason' );
};
}( jQuery ) );
diff --git a/Flow/modules/flow/dm/mixins/mw.flow.dm.List.js b/Flow/modules/flow/dm/mixins/mw.flow.dm.List.js
index fd8c268a..f0c7ff4d 100644
--- a/Flow/modules/flow/dm/mixins/mw.flow.dm.List.js
+++ b/Flow/modules/flow/dm/mixins/mw.flow.dm.List.js
@@ -6,12 +6,8 @@
* @mixin
* @abstract
* @constructor
- * @param {Object} config Configuration options
*/
- mw.flow.dm.List = function mwFlowDmList( config ) {
- // Configuration initialization
- config = config || {};
-
+ mw.flow.dm.List = function mwFlowDmList() {
this.items = [];
// Store references to items by their ids
@@ -138,6 +134,7 @@
}
};
+ // eslint-disable-next-line valid-jsdoc
/**
* Add items
*
@@ -196,6 +193,7 @@
return this;
};
+ // eslint-disable-next-line valid-jsdoc
/**
* Remove items
*
@@ -236,9 +234,11 @@
return this;
};
+ // eslint-disable-next-line valid-jsdoc
/**
* Clear all items
*
+ * @chainable
* @fires clear
*/
mw.flow.dm.List.prototype.clearItems = function () {
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Board.js b/Flow/modules/flow/dm/mw.flow.dm.Board.js
index 7784861b..eb7db0e1 100644
--- a/Flow/modules/flow/dm/mw.flow.dm.Board.js
+++ b/Flow/modules/flow/dm/mw.flow.dm.Board.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Flow Board
*
@@ -21,7 +21,9 @@
mw.flow.dm.Board.parent.call( this, config );
// Mixin constructor
- mw.flow.dm.List.call( this, config );
+ mw.flow.dm.List.call( this );
+
+ this.categories = new mw.flow.dm.Categories();
// TODO: Fill this stuff in properly
this.setId( data.id );
@@ -30,7 +32,13 @@
this.sort = data.defaultSort || 'newest';
this.description = new mw.flow.dm.BoardDescription();
+ // Events
this.aggregate( { contentChange: 'topicContentChange' } );
+ this.categories.connect( this, {
+ add: [ 'emit', 'addCategories' ],
+ remove: [ 'emit', 'removeCategories' ],
+ clear: [ 'emit', 'clearCategories' ]
+ } );
};
/* Initialization */
@@ -69,18 +77,78 @@
* @inheritdoc
*/
mw.flow.dm.Board.prototype.getHashObject = function () {
- return $.extend( {
- isDeleted: this.isDeleted(),
- pagePrefixedDb: this.getPageTitle().getPrefixedDb(),
- topicCount: this.getItemCount(),
- description: this.getDescription() && this.getDescription().getHashObject()
- },
+ return $.extend(
+ {
+ isDeleted: this.isDeleted(),
+ pagePrefixedDb: this.getPageTitle().getPrefixedDb(),
+ topicCount: this.getItemCount(),
+ description: this.getDescription() && this.getDescription().getHashObject()
+ },
// Parent
mw.flow.dm.Board.parent.prototype.getHashObject.call( this )
);
};
/**
+ * Add raw categories from the initial board api response
+ * @param {Object} categories Categories object
+ */
+ mw.flow.dm.Board.prototype.setCategoriesFromObject = function ( categories ) {
+ var cat,
+ categoryDMs = [];
+
+ // Add
+ for ( cat in categories ) {
+ categoryDMs.push( new mw.flow.dm.CategoryItem( cat, {
+ exists: !!categories[ cat ].exists
+ } ) );
+ }
+ this.addCategories( categoryDMs );
+ };
+
+ /**
+ * Add categories to the board
+ *
+ * @param {mw.flow.dm.CategoryItem[]} categories An array of category items
+ */
+ mw.flow.dm.Board.prototype.addCategories = function ( categories ) {
+ this.categories.addItems( categories );
+ };
+
+ /**
+ * Get board categories
+ *
+ * @return {mw.flow.dm.Categories} An array of category items
+ */
+ mw.flow.dm.Board.prototype.getCategories = function () {
+ return this.categories;
+ };
+
+ /**
+ * Remove board categories
+ *
+ * @param {mw.flow.dm.CategoryItem[]} categories An array of category items
+ */
+ mw.flow.dm.Board.prototype.removeCategories = function ( categories ) {
+ this.categories.removeItems( categories );
+ };
+
+ /**
+ * Clear the categories of this board
+ */
+ mw.flow.dm.Board.prototype.clearCategories = function () {
+ this.categories.clearItems();
+ };
+
+ /**
+ * Check whether the board has any categories
+ * @return {boolean} Board has categories
+ */
+ mw.flow.dm.Board.prototype.hasCategories = function () {
+ return !!this.categories.getItemCount();
+ };
+
+ /**
* Check if the board is in a deleted page
*
* @return {boolean} Board is in a deleted page
@@ -110,7 +178,7 @@
/**
* Set board description
*
- * @param {mw.flow.dm.BoardDescription} Board description
+ * @param {mw.flow.dm.BoardDescription} desc Board description
* @fires descriptionChange
*/
mw.flow.dm.Board.prototype.setDescription = function ( desc ) {
@@ -145,7 +213,7 @@
/**
* Set board sort order, 'newest' or 'updated'
*
- * @param {string} Board sort order
+ * @param {string} order Board sort order
* @fires sortOrderChange
*/
mw.flow.dm.Board.prototype.setSortOrder = function ( order ) {
@@ -157,6 +225,8 @@
/**
* Get the last offset for the API's offsetId
+ *
+ * @return {string}
*/
mw.flow.dm.Board.prototype.getOffsetId = function () {
var topics = this.getItems();
@@ -168,6 +238,8 @@
/**
* Get the last offset for the API's offset timestamp
+ *
+ * @return {number}
*/
mw.flow.dm.Board.prototype.getOffset = function () {
var topics = this.getItems();
@@ -187,4 +259,4 @@
this.clearItems();
this.emit( 'reset', order );
};
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Captcha.js b/Flow/modules/flow/dm/mw.flow.dm.Captcha.js
new file mode 100644
index 00000000..1151b475
--- /dev/null
+++ b/Flow/modules/flow/dm/mw.flow.dm.Captcha.js
@@ -0,0 +1,70 @@
+( function () {
+ /**
+ * Data model for a (potential) CAPTCHA. This is always used; it will just return false for
+ * isRequired() if no user interaction is required.
+ *
+ * @class
+ *
+ * @constructor
+ */
+ mw.flow.dm.Captcha = function mwFlowDmCaptcha() {
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+ };
+
+ /* Setup */
+
+ OO.initClass( mw.flow.dm.Captcha );
+
+ /* Inheritance */
+
+ OO.mixinClass( mw.flow.dm.Captcha, OO.EventEmitter );
+
+ /* Events */
+ /**
+ * Update to CAPTCHA information
+ *
+ * @event update
+ * @param {boolean} isRequired Whether CAPTCHA is now required
+ * @param {OO.ui.HtmlSnippet|null} content Content of CAPTCHA, or null
+ */
+
+ /* Methods */
+
+ /**
+ * Updates based on server-provided error information
+ *
+ * @param {string} errorCode Server-provided error code
+ * @param {Object} errorObj Server-provided error object
+ */
+ mw.flow.dm.Captcha.prototype.update = function ( errorCode, errorObj ) {
+ this.required = /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter.messageKey === 'flow-spam-confirmedit-form';
+
+ this.renderingInformation = null;
+ if ( this.required ) {
+ this.renderingInformation = errorObj.error.spamfilter.details;
+ this.renderingInformation.html = new OO.ui.HtmlSnippet( this.renderingInformation.html );
+ }
+
+ this.emit( 'update', this.required, this.renderingInformation );
+ };
+
+ /**
+ * Checks whether the CAPTCHA is required
+ *
+ * @return {boolean} True if the user must fill in a CAPTCHA
+ */
+ mw.flow.dm.Captcha.prototype.isRequired = function () {
+ return this.required;
+ };
+
+ /**
+ * Gets the CAPTCHA rendering information. This is in the data model because it's
+ * server-generated.
+ *
+ * @return {OO.ui.HtmlSnippet} HTML snippet for CAPTCHA, or null if there is none.
+ */
+ mw.flow.dm.Captcha.prototype.getRenderingInformation = function () {
+ return this.renderingInformation;
+ };
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Categories.js b/Flow/modules/flow/dm/mw.flow.dm.Categories.js
new file mode 100644
index 00000000..063356e0
--- /dev/null
+++ b/Flow/modules/flow/dm/mw.flow.dm.Categories.js
@@ -0,0 +1,26 @@
+( function () {
+ /**
+ * Flow Board
+ *
+ * @class
+ * @mixins mw.flow.dm.List
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ mw.flow.dm.Categories = function mwFlowDmCategories( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this, config );
+
+ // Mixin constructor
+ mw.flow.dm.List.call( this );
+ };
+
+ /* Initialization */
+
+ OO.mixinClass( mw.flow.dm.Categories, OO.EventEmitter );
+ OO.mixinClass( mw.flow.dm.Categories, mw.flow.dm.List );
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.CategoryItem.js b/Flow/modules/flow/dm/mw.flow.dm.CategoryItem.js
new file mode 100644
index 00000000..2fa577d2
--- /dev/null
+++ b/Flow/modules/flow/dm/mw.flow.dm.CategoryItem.js
@@ -0,0 +1,43 @@
+( function () {
+ /**
+ * Flow Board
+ *
+ * @class
+ * @extends mw.flow.dm.Item
+ *
+ * @constructor
+ * @param {string} name Category name
+ * @param {Object} [config] Configuration options
+ */
+ mw.flow.dm.CategoryItem = function mwFlowDmCategoryItem( name, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.flow.dm.CategoryItem.parent.call( this, config );
+
+ this.setId( name );
+ this.setExists( !!config.exists );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.dm.CategoryItem, mw.flow.dm.Item );
+
+ /**
+ * Set exist status for this category in this wiki.
+ *
+ * @param {boolean} exists Category page exists in this wiki
+ */
+ mw.flow.dm.CategoryItem.prototype.setExists = function ( exists ) {
+ this.categoryExists = exists;
+ };
+
+ /**
+ * Set exist status for this category in this wiki.
+ *
+ * @return {boolean} Category page exists in this wiki
+ */
+ mw.flow.dm.CategoryItem.prototype.exists = function () {
+ return this.categoryExists;
+ };
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Content.js b/Flow/modules/flow/dm/mw.flow.dm.Content.js
new file mode 100644
index 00000000..9af85275
--- /dev/null
+++ b/Flow/modules/flow/dm/mw.flow.dm.Content.js
@@ -0,0 +1,81 @@
+( function () {
+ /**
+ * Flow Content class
+ *
+ * @class
+ *
+ * @constructor
+ * @param {Object} [representations]
+ * {
+ * content: "content in the default format",
+ * format: "name of the default format",
+ * "(other format name 1)": "content in the specified format"
+ * "(other format name n)": "content in the specified format"
+ * }
+ */
+ mw.flow.dm.Content = function mwFlowContent( representations ) {
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ // Initialize properties
+ this.set( representations );
+ };
+
+ /* Inheritance */
+
+ OO.mixinClass( mw.flow.dm.Content, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * Change of content
+ *
+ * @event contentChange
+ */
+
+ /* Methods */
+
+ /**
+ * Get content representation for the specified format or the default format if none is specified.
+ *
+ * @param {string} [format=this.defaultFormat]; can be wikitext, html, fixed-html, topic-title-wikitext, topic-title-html, plaintext
+ * @return {string} Content
+ */
+ mw.flow.dm.Content.prototype.get = function ( format ) {
+ if ( !this.contentRepresentations ) {
+ return null;
+ }
+
+ format = format || this.defaultFormat;
+
+ if ( this.contentRepresentations.hasOwnProperty( format ) ) {
+ return this.contentRepresentations[ format ];
+ }
+ return null;
+ };
+
+ /**
+ * Set content representations
+ *
+ * @param {Object} [representations]
+ * @fires contentChange
+ */
+ mw.flow.dm.Content.prototype.set = function ( representations ) {
+ var format;
+ this.defaultFormat = null;
+ this.contentRepresentations = {};
+
+ if ( representations ) {
+ this.defaultFormat = representations.format;
+ this.contentRepresentations[ this.defaultFormat ] = representations.content;
+
+ for ( format in representations ) {
+ if ( representations.hasOwnProperty( format ) ) {
+ this.contentRepresentations[ format ] = representations[ format ];
+ }
+ }
+ }
+
+ this.emit( 'contentChange' );
+ };
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Post.js b/Flow/modules/flow/dm/mw.flow.dm.Post.js
index 7080af30..5668a104 100644
--- a/Flow/modules/flow/dm/mw.flow.dm.Post.js
+++ b/Flow/modules/flow/dm/mw.flow.dm.Post.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Flow Post
*
@@ -18,7 +18,7 @@
mw.flow.dm.Post.parent.call( this, config );
// Mixin constructor
- mw.flow.dm.List.call( this, config );
+ mw.flow.dm.List.call( this );
this.setId( id );
this.populate( revisionData );
@@ -97,4 +97,4 @@
return this.replyIds;
};
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.RevisionedContent.js b/Flow/modules/flow/dm/mw.flow.dm.RevisionedContent.js
index e350ead6..fdb3e7a2 100644
--- a/Flow/modules/flow/dm/mw.flow.dm.RevisionedContent.js
+++ b/Flow/modules/flow/dm/mw.flow.dm.RevisionedContent.js
@@ -17,8 +17,7 @@
mw.flow.dm.RevisionedContent.parent.call( this, config );
// Initialize properties
- this.content = null;
- this.contentFormat = null;
+ this.content = new mw.flow.dm.Content();
this.author = null;
this.creator = null;
this.lastUpdate = null;
@@ -30,8 +29,13 @@
this.originalContent = true;
this.watched = false;
this.watchable = true;
+ this.editable = true;
this.lastEditId = null;
this.lastEditUser = null;
+
+ this.content.connect( this, {
+ contentChange: [ 'emit', 'contentChange' ]
+ } );
};
/* Inheritance */
@@ -43,8 +47,6 @@
* Change of content in this revision
*
* @event contentChange
- * @param {string} content Content
- * @param {string} format Content format
*/
/**
@@ -68,6 +70,13 @@
* @param {boolean} originalContent Revision is original content, and was never edited
*/
+ /**
+ * Change of editable status
+ *
+ * @event editableChange
+ * @param {boolean} editable The revision is editable
+ */
+
/* Methods */
/**
@@ -76,7 +85,6 @@
mw.flow.dm.RevisionedContent.prototype.getHashObject = function () {
return $.extend( {
content: this.getContent(),
- contentFormat: this.getContentFormat(),
author: this.getAuthor(),
creator: this.getCreator(),
lastUpdate: this.getLastUpdate(),
@@ -88,7 +96,8 @@
previousRevisionId: this.getPreviousRevisionId(),
originalContent: this.isOriginalContent(),
watched: this.isWatched(),
- watchable: this.isWatchable()
+ watchable: this.isWatchable(),
+ editable: this.isEditable()
}, mw.flow.dm.RevisionedContent.parent.prototype.getHashObject.call( this ) );
};
@@ -101,10 +110,7 @@
* @param {Object} data API data
*/
mw.flow.dm.RevisionedContent.prototype.populate = function ( data ) {
- var content = data.content || {};
-
- this.setContent( content.content );
- this.setContentFormat( content.format );
+ this.setContent( data.content );
this.setAuthor( data.author );
this.setCreator( data.creator );
this.setLastUpdate( data.last_updated );
@@ -117,11 +123,11 @@
this.toggleOriginalContent(
data.isOriginalContent !== undefined ?
- data.isOriginalContent :
- // If 'isOriginalContent' isn't at all defined, we will
- // define it by whether there is a previous revision id
- // present
- !this.getPreviousRevisionId()
+ data.isOriginalContent :
+ // If 'isOriginalContent' isn't at all defined, we will
+ // define it by whether there is a previous revision id
+ // present
+ !this.getPreviousRevisionId()
);
this.setLastEditId( data.lastEditId );
@@ -131,6 +137,10 @@
if ( data.watchable !== undefined ) {
this.toggleWatchable( !!data.watchable );
}
+
+ this.toggleEditable( !!( data.actions && data.actions.edit ) );
+
+ this.actions = data.actions;
};
/**
@@ -174,59 +184,20 @@
};
/**
- * Get content
- *
- * @return {string} Content; can be in wikitext, html, fixed-html
- * or plaintext format.
- * See #getContentFormat for the format of the given content.
+ * @see mw.flow.dm.Content
+ * @param {string} format
+ * @return {string}
*/
- mw.flow.dm.RevisionedContent.prototype.getContent = function () {
- return this.content;
+ mw.flow.dm.RevisionedContent.prototype.getContent = function ( format ) {
+ return this.content.get( format );
};
/**
- * Set content
- *
- * @param {string} content Content
- * @fires contentChange
- */
- mw.flow.dm.RevisionedContent.prototype.setContent = function ( content ) {
- var wasUnset = this.content === null;
- if ( content !== undefined && this.content !== content ) {
- this.content = content;
- if ( !wasUnset ) {
- this.emit( 'contentChange', this.content, this.contentFormat );
- }
- }
- };
-
- /**
- * Get content format
- * Possible formats are:
- * - 'wikitext' for unparsed wikitext content
- * - 'html' for full html content
- * - 'fixed-html' for parsoid html content
- * - 'plaintext' for plaintext content
- *
- * @return {string} Content format.
+ * @see mw.flow.dm.Content
+ * @param {Object} representations
*/
- mw.flow.dm.RevisionedContent.prototype.getContentFormat = function () {
- return this.contentFormat;
- };
-
- /**
- * Set content format. See #getContentFormat for available formats
- *
- * @param {string} contentFormat Content format
- */
- mw.flow.dm.RevisionedContent.prototype.setContentFormat = function ( contentFormat ) {
- var wasUnset = this.contentFormat === null;
- if ( contentFormat !== undefined && this.contentFormat !== contentFormat ) {
- this.contentFormat = contentFormat;
- if ( !wasUnset ) {
- this.emit( 'contentChange', this.content, this.contentFormat );
- }
- }
+ mw.flow.dm.RevisionedContent.prototype.setContent = function ( representations ) {
+ this.content.set( representations );
};
/**
@@ -272,7 +243,7 @@
/**
* Set the revision change type
*
- * @param {string} Revision change type
+ * @param {string} type Revision change type
*/
mw.flow.dm.RevisionedContent.prototype.setChangeType = function ( type ) {
if ( type !== undefined && this.changeType !== type ) {
@@ -453,4 +424,27 @@
this.emit( 'watchableChange', this.watchable );
};
+
+ /**
+ * Toggle the editability state of this revision
+ * @param {boolean} [editable] The revision is editable
+ * @fires editableChange
+ */
+ mw.flow.dm.RevisionedContent.prototype.toggleEditable = function ( editable ) {
+ editable = editable !== undefined ? !!editable : !this.editable;
+
+ if ( this.editable !== editable ) {
+ this.editable = editable;
+ this.emit( 'editableChange', this.editable );
+ }
+ };
+
+ /**
+ * Check topic editable status
+ *
+ * @return {boolean} Revision is editable
+ */
+ mw.flow.dm.RevisionedContent.prototype.isEditable = function () {
+ return this.editable;
+ };
}( jQuery ) );
diff --git a/Flow/modules/flow/dm/mw.flow.dm.System.js b/Flow/modules/flow/dm/mw.flow.dm.System.js
index 58528e05..e03ec4d1 100644
--- a/Flow/modules/flow/dm/mw.flow.dm.System.js
+++ b/Flow/modules/flow/dm/mw.flow.dm.System.js
@@ -125,6 +125,7 @@
return this.moreTopicsExistInApi;
};
+ // TODO: This should be merged with mw.flow.dm.APIHandler.getTopicList.
/**
* Populate the board by querying the Api
*
@@ -307,6 +308,8 @@
* When we scroll down or load a topic, this is the number that defines the
* batch of topics to be loaded and rendered.
*
+ * This does not affect the number of topics loaded when the sort order changes.
+ *
* @return {number} Rendered topics
*/
mw.flow.dm.System.prototype.getRenderedTopics = function () {
diff --git a/Flow/modules/flow/dm/mw.flow.dm.Topic.js b/Flow/modules/flow/dm/mw.flow.dm.Topic.js
index 080febc7..fe1f16b5 100644
--- a/Flow/modules/flow/dm/mw.flow.dm.Topic.js
+++ b/Flow/modules/flow/dm/mw.flow.dm.Topic.js
@@ -18,7 +18,7 @@
mw.flow.dm.Topic.parent.call( this, config );
// Mixin constructor
- mw.flow.dm.List.call( this, config );
+ mw.flow.dm.List.call( this );
this.setId( id );
this.populate( revisionData );
@@ -158,9 +158,9 @@
};
/**
- * Get the topic summary
+ * Set the topic summary
*
- * @param {string} Topic summary
+ * @param {string} summary Topic summary
* @fires summary
*/
mw.flow.dm.Topic.prototype.setSummary = function ( summary ) {
diff --git a/Flow/modules/flow/ui/mw.flow.ui.CancelConfirmDialog.js b/Flow/modules/flow/ui/mw.flow.ui.CancelConfirmDialog.js
index 42205d6a..3297cb57 100644
--- a/Flow/modules/flow/ui/mw.flow.ui.CancelConfirmDialog.js
+++ b/Flow/modules/flow/ui/mw.flow.ui.CancelConfirmDialog.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Dialog for confirming with the user if they reall want to cancel
* the edit.
@@ -43,4 +43,4 @@
mw.flow.ui.windowFactory.register( mw.flow.ui.CancelConfirmDialog );
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/ui/mw.flow.ui.js b/Flow/modules/flow/ui/mw.flow.ui.js
index 6649dee7..657402cd 100644
--- a/Flow/modules/flow/ui/mw.flow.ui.js
+++ b/Flow/modules/flow/ui/mw.flow.ui.js
@@ -2,4 +2,3 @@ mw.flow.ui = {};
mw.flow.ui.windowFactory = new OO.Factory();
mw.flow.ui.windowManager = new OO.ui.WindowManager( { factory: mw.flow.ui.windowFactory } );
-
diff --git a/Flow/modules/flow/ui/tools/mw.flow.ui.MWEditModeTool.js b/Flow/modules/flow/ui/tools/mw.flow.ui.MWEditModeTool.js
new file mode 100644
index 00000000..9a5437b3
--- /dev/null
+++ b/Flow/modules/flow/ui/tools/mw.flow.ui.MWEditModeTool.js
@@ -0,0 +1,69 @@
+/*!
+ * VisualEditor MediaWiki UserInterface edit mode tool classes.
+ *
+ * @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * MediaWiki UserInterface edit mode tool.
+ *
+ * @class
+ * @abstract
+ */
+mw.flow.ui.MWEditModeTool = function VeUiMWEditModeTool() {
+};
+
+/* Inheritance */
+
+OO.initClass( mw.flow.ui.MWEditModeTool );
+
+/* Methods */
+
+// Inherits from mw.libs.ve.MWEditModeTool
+mw.flow.ui.MWEditModeTool.prototype.getMode = function () {
+ return this.toolbar.surface ? 'visual' : 'source';
+};
+
+/**
+ * MediaWiki UserInterface edit mode source tool.
+ *
+ * @class
+ * @extends mw.libs.ve.MWEditModeSourceTool
+ * @mixins mw.flow.ui.MWEditModeTool
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Config options
+ */
+mw.flow.ui.MWEditModeSourceTool = function VeUiMWEditModeSourceTool() {
+ // Parent constructor
+ mw.flow.ui.MWEditModeSourceTool.parent.apply( this, arguments );
+ // Mixin constructor
+ mw.flow.ui.MWEditModeTool.call( this );
+};
+OO.inheritClass( mw.flow.ui.MWEditModeSourceTool, mw.libs.ve.MWEditModeSourceTool );
+OO.mixinClass( mw.flow.ui.MWEditModeSourceTool, mw.flow.ui.MWEditModeTool );
+mw.flow.ui.MWEditModeSourceTool.prototype.onSelect = function () {
+ if ( this.getMode() === 'visual' ) {
+ this.toolbar.surface.executeCommand( 'flowSwitchEditor' );
+ }
+};
+
+/**
+ * MediaWiki UserInterface edit mode visual tool.
+ *
+ * @class
+ * @extends mw.libs.ve.MWEditModeVisualTool
+ * @mixins mw.flow.ui.MWEditModeTool
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Config options
+ */
+mw.flow.ui.MWEditModeVisualTool = function VeUiMWEditModeVisualTool() {
+ // Parent constructor
+ mw.flow.ui.MWEditModeVisualTool.parent.apply( this, arguments );
+ // Mixin constructor
+ mw.flow.ui.MWEditModeTool.call( this );
+};
+OO.inheritClass( mw.flow.ui.MWEditModeVisualTool, mw.libs.ve.MWEditModeVisualTool );
+OO.mixinClass( mw.flow.ui.MWEditModeVisualTool, mw.flow.ui.MWEditModeTool );
diff --git a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js
index 6b4b106a..31daaeff 100644
--- a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.AbstractEditorWidget.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Flow abstract editor widget.
*
@@ -6,7 +6,7 @@
* - Set #static-name
* - Implement #getRawContent and #reloadContent
* - Emit #event-change and #event-switch
- * - Respect config.switchable
+ * - Respect static.switchable
*
* Subclasses probably need to:
* - Set #static-format
@@ -20,7 +20,6 @@
*
* @constructor
* @param {Object} [config] Configuration options
- * @cfg {boolean} [switchable=false] Whether a tool to switch editors should be displayed
* @cfg {string} [placeholder] Placeholder text for the edit area
*/
mw.flow.ui.AbstractEditorWidget = function mwFlowUiAbstractEditorWidget( config ) {
@@ -51,12 +50,28 @@
* name is passed in, or if there is no editor by the given name, EditorSwitcherWidget
* will decide which editor to switch to.
*
- * Should not be emitted if config.switchable is false.
+ * Should not be emitted if static.switchable is false.
*/
/* Static Methods */
/**
+ * Sets whether the user can switch to another editor
+ *
+ * @param {boolean} switchable
+ */
+ mw.flow.ui.AbstractEditorWidget.static.setSwitchable = function ( switchable ) {
+ this.switchable = switchable;
+ };
+
+ /* Static Properties */
+
+ /**
+ * Whether the user can switch to another editor type
+ */
+ mw.flow.ui.AbstractEditorWidget.static.switchable = false;
+
+ /**
* Type of content to use
*
* @static
@@ -191,4 +206,4 @@
return this.initialContent !== this.getContent();
};
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js
index fb5d9502..4f42383b 100644
--- a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.VisualEditorWidget.js
@@ -14,7 +14,6 @@
// Parent constructor
mw.flow.ui.VisualEditorWidget.parent.call( this, config );
- this.switchable = config.switchable;
this.placeholder = config.placeholder;
this.loadPromise = null;
@@ -43,21 +42,12 @@
mw.flow.ui.VisualEditorWidget.static.isSupported = function () {
var isMobileTarget = ( mw.config.get( 'skin' ) === 'minerva' );
+ /* global VisualEditorSupportCheck */
return !!(
!isMobileTarget &&
-
- // ES5 support, from es5-skip.js
- ( function () {
- 'use strict';
- return !this && !!Function.prototype.bind;
- }() ) &&
-
- // ContentEditable support
- 'contentEditable' in document.createElement( 'div' ) &&
-
- // Since VE commit e2fab2f1ebf2a28f18b8ead08c478c4fc95cd64e, SVG is required
- document.createElementNS &&
- document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ).createSVGRect
+ mw.loader.getState( 'ext.visualEditor.core' ) &&
+ mw.config.get( 'wgFlowEditorList' ).indexOf( 'visualeditor' ) !== -1 &&
+ window.VisualEditorSupportCheck && VisualEditorSupportCheck()
);
};
@@ -72,14 +62,19 @@
* @return {jQuery.Promise} Promise resolved when this.target has been created.
*/
mw.flow.ui.VisualEditorWidget.prototype.load = function () {
- var widget = this;
+ var modules, widget = this;
if ( !this.loadPromise ) {
- this.loadPromise = mw.loader.using( 'ext.flow.visualEditor' )
+ modules = [ 'ext.flow.visualEditor' ].concat(
+ mw.config.get( 'wgVisualEditorConfig' ).pluginModules.filter( mw.loader.getState )
+ );
+ this.loadPromise = mw.loader.using( modules )
.then( function () {
// HACK add i18n messages to VE
- ve.init.platform.addMessages( mw.messages.values );
+ ve.init.platform.addMessages( mw.messages.get() );
- widget.target = new mw.flow.ve.Target();
+ mw.flow.ve.Target.static.setSwitchable( mw.flow.ui.VisualEditorWidget.static.switchable );
+
+ widget.target = ve.init.mw.targetFactory.create( 'flow' );
widget.$element.append( widget.target.$element );
} );
}
@@ -88,27 +83,26 @@
/**
* Create a VE surface with the provided content in it.
- * @param {string} content HTML to put in the surface
+ *
+ * @param {string} content HTML to put in the surface (body only)
+ * @return {jQuery.Promise} Promise which resolves when the surface is ready
*/
mw.flow.ui.VisualEditorWidget.prototype.createSurface = function ( content ) {
- var dmDoc,
- htmlDoc = ve.createDocumentFromHtml( content );
- ve.init.mw.Target.static.fixBase( htmlDoc );
- dmDoc = ve.dm.converter.getModelFromDom( htmlDoc, {
- lang: mw.config.get( 'wgVisualEditor' ).pageLanguageCode,
- dir: mw.config.get( 'wgVisualEditor' ).pageLanguageDir
+ var widget = this,
+ deferred = $.Deferred();
+
+ // loadHtml expects a full document, but we were only given the body content
+ this.target.loadHtml( '<body>' + content + '</body>' );
+ this.target.once( 'surfaceReady', function () {
+ var surface = widget.target.getSurface();
+
+ surface.setPlaceholder( widget.placeholder );
+ // Relay events
+ surface.getModel().connect( widget, { documentUpdate: [ 'emit', 'change' ] } );
+ surface.connect( widget, { switchEditor: [ 'emit', 'switch' ] } );
+ deferred.resolve();
} );
- this.surface = this.target.addSurface( dmDoc, { placeholder: this.placeholder } );
- // afterAttach() calls setSurface
-
- // Add directionality class
- this.surface.getView().getDocument().getDocumentNode().$element.addClass(
- 'mw-content-' + mw.config.get( 'wgVisualEditor' ).pageLanguageDir
- );
-
- // Relay events
- this.surface.getModel().connect( this, { documentUpdate: [ 'emit', 'change' ] } );
- this.surface.connect( this, { switchEditor: [ 'emit', 'switch' ] } );
+ return deferred.promise();
};
/**
@@ -121,13 +115,6 @@
/**
* @inheritdoc
*/
- mw.flow.ui.VisualEditorWidget.prototype.afterAttach = function () {
- this.target.setSurface( this.surface );
- };
-
- /**
- * @inheritdoc
- */
mw.flow.ui.VisualEditorWidget.prototype.teardown = function () {
this.target.clearSurfaces();
return $.Deferred().resolve().promise();
@@ -137,7 +124,7 @@
* @inheritdoc
*/
mw.flow.ui.VisualEditorWidget.prototype.focus = function () {
- if ( this.target ) {
+ if ( this.target && this.target.getSurface() ) {
this.target.getSurface().getView().focus();
}
};
@@ -146,15 +133,8 @@
* @inheritdoc
*/
mw.flow.ui.VisualEditorWidget.prototype.moveCursorToEnd = function () {
- if ( !this.target ) {
- return;
- }
-
- var data = this.target.surface.getModel().getDocument().data,
- cursorPos = data.getNearestContentOffset( data.getLength(), -1 );
-
- if ( cursorPos !== -1 ) {
- this.target.surface.getModel().setLinearSelection( new ve.Range( cursorPos ) );
+ if ( this.target && this.target.getSurface() ) {
+ this.target.getSurface().getModel().selectLastContentOffset();
}
};
@@ -165,7 +145,7 @@
var doc, html;
// If we haven't fully loaded yet, just return nothing.
- if ( !this.target ) {
+ if ( !this.target || !this.target.getSurface() ) {
return '';
}
@@ -183,13 +163,15 @@
mw.flow.ui.VisualEditorWidget.prototype.setContent = function ( content ) {
this.target.clearSurfaces();
this.createSurface( content );
- this.target.setSurface( this.surface );
};
/**
* @inheritdoc
*/
mw.flow.ui.VisualEditorWidget.prototype.isEmpty = function () {
+ if ( !this.target || !this.target.getSurface() ) {
+ return true;
+ }
return !this.target.getSurface().getModel().getDocument().data.hasContent();
};
@@ -200,7 +182,7 @@
*/
mw.flow.ui.VisualEditorWidget.prototype.hasBeenChanged = function () {
// If we haven't fully loaded yet, just return false
- if ( !this.target ) {
+ if ( !this.target || !this.target.getSurface() ) {
return false;
}
diff --git a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js
index c9af1fad..7195efdf 100644
--- a/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.js
@@ -18,12 +18,16 @@
mw.flow.ui.WikitextEditorWidget.parent.call( this, config );
// Main textarea
- this.input = new OO.ui.TextInputWidget( {
- multiline: true,
+ this.input = new OO.ui.MultilineTextInputWidget( {
autosize: true,
maxRows: 999,
placeholder: config.placeholder,
- classes: [ 'flow-ui-wikitextEditorWidget-input' ]
+ // The following classes can be used here:
+ // * mw-editfont-default
+ // * mw-editfont-monospace
+ // * mw-editfont-sans-serif
+ // * mw-editfont-serif
+ classes: [ 'flow-ui-wikitextEditorWidget-input', 'mw-editfont-' + mw.user.options.get( 'editfont' ) ]
} );
// Label and switcher
@@ -33,15 +37,7 @@
.attr( 'target', '_blank' )
.end();
- if ( config.switchable ) {
- // Toolbar
- this.toolFactory = new OO.ui.ToolFactory();
- this.toolFactory.register( mw.flow.ui.SwitchToVeTool );
- this.toolGroupFactory = new OO.ui.ToolGroupFactory();
- this.toolbar = new OO.ui.Toolbar( this.toolFactory, this.toolGroupFactory );
- this.toolbar.setup( [ { include: [ 'flowSwitchEditor' ] } ] );
- this.initializedToolbar = false;
-
+ if ( mw.flow.ui.WikitextEditorWidget.static.switchable ) {
$preview = $( '<a>' )
.attr( 'href', '#' )
.addClass( 'flow-ui-wikitextEditorWidget-label-preview' )
@@ -53,14 +49,40 @@
$preview[ 0 ].outerHTML
] ).parse()
);
-
- // Events
- this.toolbar.connect( this, { switchEditor: [ 'emit', 'switch' ] } );
$message.find( '.flow-ui-wikitextEditorWidget-label-preview' )
.on( 'click', function () {
widget.emit( 'switch' );
return false;
} );
+
+ mw.loader.using( 'ext.flow.switching', function () {
+ // Toolbar
+ var toolFactory = new OO.ui.ToolFactory(),
+ toolGroupFactory = new OO.ui.ToolGroupFactory();
+
+ toolFactory.register( mw.flow.ui.MWEditModeVisualTool );
+ toolFactory.register( mw.flow.ui.MWEditModeSourceTool );
+
+ widget.toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory, { position: 'bottom' } );
+ // HACK: Disable narrow mode
+ widget.toolbar.narrowThreshold = 0;
+ widget.toolbar.setup( [ {
+ type: 'list',
+ icon: 'edit',
+ title: mw.msg( 'visualeditor-mweditmode-tooltip' ),
+ include: [ 'editModeVisual', 'editModeSource' ]
+ } ] );
+ widget.toolbar.emit( 'updateState' );
+
+ widget.$element.append( widget.toolbar.$element );
+
+ // Events
+ widget.toolbar.on( 'switchEditor', function ( mode ) {
+ if ( mode === 'visual' ) {
+ widget.emit( 'switch' );
+ }
+ } );
+ } );
} else {
$message = $( '<span>' ).append(
mw.message( 'flow-wikitext-editor-help' ).params( [
@@ -81,10 +103,9 @@
// Initialize
this.$element
.addClass( 'flow-ui-wikitextEditorWidget' )
- .append(
+ .prepend(
this.input.$element,
- label.$element,
- this.toolbar ? this.toolbar.$element : []
+ label.$element
);
};
@@ -158,10 +179,9 @@
* @inheritdoc
*/
mw.flow.ui.WikitextEditorWidget.prototype.afterAttach = function () {
- if ( this.toolbar && !this.initializedToolbar ) {
+ if ( this.toolbar ) {
this.toolbar.initialize();
- // Prevent double initialization; will not be needed with OOjs UI >=0.12.8
- this.initializedToolbar = true;
+ this.toolbar.emit( 'updateState' );
}
};
diff --git a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js
index d88f0e5c..09f73f75 100644
--- a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.AnonWarningWidget.js
@@ -7,19 +7,29 @@
*
* @constructor
* @param {Object} [config] Configuration options
+ * @cfg {boolean} [isProbablyEditable=true] Whether the content seems to be editable
*/
- mw.flow.ui.AnonWarningWidget = function mwFlowUiEditorControlsWidget( config ) {
- var returnTo, labelHtml,
- isAnon = mw.user.isAnon();
+ mw.flow.ui.AnonWarningWidget = function mwFlowUiAnonWarningWidget( config ) {
+ var returnTo, labelHtml, isProbablyEditable,
+ shouldDisplay;
config = config || {};
+ if ( config.isProbablyEditable !== undefined ) {
+ isProbablyEditable = config.isProbablyEditable;
+ } else {
+ isProbablyEditable = true;
+ }
+
+ // If it's not editable, we'll display CanNotEditWidget instead
+ shouldDisplay = isProbablyEditable && mw.user.isAnon();
+
// Parent constructor
mw.flow.ui.AnonWarningWidget.parent.call( this, config );
this.label = new OO.ui.LabelWidget();
- if ( isAnon ) {
+ if ( shouldDisplay ) {
returnTo = {
returntoquery: encodeURIComponent( window.location.search ),
returnto: mw.config.get( 'wgPageName' )
@@ -39,7 +49,7 @@
this.label.$element
)
.addClass( 'flow-ui-anonWarningWidget' )
- .toggleClass( 'flow-ui-anonWarningWidget-active', isAnon );
+ .toggleClass( 'flow-ui-anonWarningWidget-active', shouldDisplay );
};
/* Initialization */
diff --git a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.CanNotEditWidget.js b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.CanNotEditWidget.js
new file mode 100644
index 00000000..85fa27ac
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.CanNotEditWidget.js
@@ -0,0 +1,173 @@
+( function ( mw, $ ) {
+ // Should be refined later to handle different scenarios (block/protect/etc.) explicitly.
+ /**
+ * Flow error widget for when the user can not edit/post/etc.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.flow.dm.APIHandler} api API handler
+ * @param {Object} [config] Configuration options
+ * @cfg {Array} [userGroups=[]] Current user's groups
+ * @cfg {Array} [restrictionEdit] List of groups that are allowed to edit, or empty
+ * array for no restrictions.
+ * @cfg {boolean} [isProbablyEditable=true] Whether the user probably has the right to
+ * edit this page. If true, they may be able to post. If false, they can not.
+ * For performance reasons to avoid pre-computing with 100% accuracy.
+ */
+ mw.flow.ui.CanNotEditWidget = function mwFlowUiCanNotEditWidget( api, config ) {
+ var widget = this;
+
+ this.api = api;
+
+ config = config || {};
+
+ if ( config.isProbablyEditable !== undefined ) {
+ this.isProbablyEditable = config.isProbablyEditable;
+ } else {
+ this.isProbablyEditable = true;
+ }
+
+ this.userGroups = config.userGroups || [];
+
+ // Empty array means "no protection restrictions on edit", so we'll treat it as a generic permissions
+ // error.
+ this.restrictionEdit = config.restrictionEdit || [];
+
+ this.label = new OO.ui.LabelWidget();
+
+ // Parent constructor
+ mw.flow.ui.CanNotEditWidget.parent.call( widget, config );
+
+ // Initialize
+ widget.$element
+ .append(
+ widget.label.$element
+ )
+ .addClass( 'flow-ui-canNotEditWidget' )
+ .toggleClass( 'flow-ui-canNotEditWidget-active', !this.isProbablyEditable );
+
+ if ( !this.isProbablyEditable ) {
+ // Initial generic message, which the real one loads
+ this.label.setLabel( $( $.parseHTML( this.getGenericMessage().parse() ) ) );
+
+ this.getMessage().done( function ( message ) {
+ // 'blocked' is never triggered by the quick check, so that is not
+ // mentioned in the message. So it could be 'protected' (which is specially
+ // handled), but could also be lack of 'createtalk', etc.
+ var labelHtml = message.parse();
+ widget.label.setLabel( $( $.parseHTML( labelHtml ) ) );
+ } );
+ }
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.CanNotEditWidget, OO.ui.Widget );
+
+ /* Static */
+ // Cache message per page load, since it may require AJAX
+ mw.flow.ui.CanNotEditWidget.static.getMessagePromise = null;
+
+ /* Methods */
+
+ /**
+ * Gets message explaining why the user can not edit the page. This should only
+ * be called if the page is (probably) not editable.
+ *
+ * @return {jQuery.Promise} Promise resolving with message to use for error
+ * @return {Function} return.done
+ * @return {mw.Message} return.done.message
+ */
+ mw.flow.ui.CanNotEditWidget.prototype.getMessage = function () {
+ var message, messageKey, isStandardProtection, dfd;
+
+ if ( mw.flow.ui.CanNotEditWidget.static.getMessagePromise !== null ) {
+ return mw.flow.ui.CanNotEditWidget.static.getMessagePromise;
+ }
+
+ dfd = $.Deferred();
+ mw.flow.ui.CanNotEditWidget.static.getMessagePromise = dfd.promise();
+
+ if ( !this.isProbablyEditable ) {
+ // Check if there is standard protection
+
+ if ( this.isMissingRequiredGroup( 'autoconfirmed' ) ) {
+ messageKey = mw.user.isAnon() ?
+ 'flow-error-protected-autoconfirmed-logged-out' :
+ 'flow-error-protected-autoconfirmed-logged-in';
+
+ isStandardProtection = true;
+ } else if ( this.isMissingRequiredGroup( 'sysop' ) ) {
+ messageKey = mw.user.isAnon() ?
+ 'flow-error-protected-sysop-logged-out' :
+ 'flow-error-protected-sysop-logged-in';
+
+ isStandardProtection = true;
+ }
+
+ if ( isStandardProtection ) {
+ this.api.getProtectionReason().done( function ( reason ) {
+ // Includes empty string
+ if ( !reason ) {
+ reason = mw.message( 'flow-error-protected-unknown-reason' ).text();
+ }
+
+ message = mw.message( messageKey, reason );
+
+ dfd.resolve( message );
+ } ).fail( function () {
+ message = mw.message( messageKey, mw.message( 'flow-error-protected-unknown-reason' ).text() );
+
+ dfd.resolve( message );
+ } );
+ } else {
+ dfd.resolve( this.getGenericMessage() );
+ }
+ }
+
+ return mw.flow.ui.CanNotEditWidget.static.getMessagePromise;
+ };
+
+ /**
+ * Gets generic message when the user can not edit, but we can not say exactly why
+ *
+ * @return {mw.Message} Message to use for error
+ */
+ mw.flow.ui.CanNotEditWidget.prototype.getGenericMessage = function () {
+ var messageKey = mw.user.isAnon() ? 'flow-error-can-not-edit-logged-out' : 'flow-error-can-not-edit-logged-in';
+ return mw.message( messageKey, mw.user );
+ };
+
+ /**
+ * Check if the specified group is required to edit and they lack it.
+ *
+ * @param {string} groupName
+ * @return {boolean} The group is both required to edit and missing
+ */
+ mw.flow.ui.CanNotEditWidget.prototype.isMissingRequiredGroup = function ( groupName ) {
+ var isGroupRequired = $.inArray( groupName, this.restrictionEdit ) !== -1,
+ acceptableGroups, i;
+
+ if ( isGroupRequired ) {
+ acceptableGroups = [ groupName ];
+
+ if ( groupName === 'autoconfirmed' ) {
+ // Hack: 'confirmed' is equivalent to 'autoconfirmed', except assigned manually.
+ // Both groups normally have the 'autoconfirmed' right, but rights are not available without an AJAX request.
+ acceptableGroups.push( 'confirmed' );
+ }
+
+ for ( i = 0; i < acceptableGroups.length; i++ ) {
+ if ( $.inArray( acceptableGroups[ i ], this.userGroups ) !== -1 ) {
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ };
+}( mediaWiki, jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js
index cf376807..83ed4576 100644
--- a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorControlsWidget.js
@@ -10,6 +10,7 @@
* @cfg {string} [termsMsgKey='flow-terms-of-use-edit'] i18n message key for the footer message
* @cfg {string} [saveMsgKey='flow-newtopic-save'] i18n message key for the save button
* @cfg {string} [cancelMsgKey='flow-cancel'] i18n message key for the cancel button
+ * @cfg {boolean} [saveable=true] Initial state of saveable flag
*/
mw.flow.ui.EditorControlsWidget = function mwFlowUiEditorControlsWidget( config ) {
var $buttons = $( '<div>' )
@@ -26,7 +27,7 @@
} );
this.saveButton = new OO.ui.ButtonWidget( {
- flags: [ 'primary', 'constructive' ],
+ flags: [ 'primary', 'progressive' ],
label: mw.msg( config.saveMsgKey || 'flow-newtopic-save' ),
classes: [ 'flow-ui-editorControlsWidget-saveButton' ]
} );
@@ -48,7 +49,7 @@
this.cancelButton.connect( this, { click: [ 'emit', 'cancel' ] } );
// Initialize
- this.toggleSaveable( true );
+ this.toggleSaveable( config.saveable !== undefined ? config.saveable : true );
this.$element
.append(
this.termsLabel.$element,
diff --git a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js
index 79711946..5362c06e 100644
--- a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorSwitcherWidget.js
@@ -14,6 +14,7 @@
* will be the first one in wgFlowEditorList that matches the format of the provided
* content (if any)
* @cfg {boolean} [autoFocus=true] Automatically focus after switching editors
+ * @cfg {boolean} [saveable=true] Initial state of saveable flag
*/
mw.flow.ui.EditorSwitcherWidget = function mwFlowUiEditorSwitcherWidget( config ) {
var widget = this;
@@ -38,17 +39,18 @@
return editor === 'none' ? 'wikitext' : editor;
} );
this.availableEditors = this.allEditors
- .filter( function ( editor ) {
- return widget.constructor.static.editorDefinitions[ editor ].static.isSupported();
+ .filter( function ( editor, i, arr ) {
+ return widget.constructor.static.editorDefinitions[ editor ].static.isSupported() &&
+ // remove all but the first occurence
+ arr.indexOf( editor ) === i;
} );
this.initialEditorName =
( config.initialEditor === 'none' ? 'wikitext' : config.initialEditor ) ||
- this.getInitialEditorName();
+ this.getPreferredEditorName();
this.switchingPromise = null;
this.settingPromise = null;
- this.placeholderInput = new OO.ui.TextInputWidget( {
- multiline: true,
+ this.placeholderInput = new OO.ui.MultilineTextInputWidget( {
placeholder: this.placeholder,
classes: [ 'flow-ui-editorSwitcherWidget-placeholder-input' ]
} );
@@ -70,6 +72,8 @@
this.$element
.append( this.error.$element, this.placeholderInput.$element )
.addClass( 'flow-ui-editorSwitcherWidget' );
+
+ this.toggleSaveable( config.saveable !== undefined ? config.saveable : true );
};
/* Initialization */
@@ -156,7 +160,7 @@
];
};
- mw.flow.ui.EditorSwitcherWidget.prototype.getInitialEditorName = function () {
+ mw.flow.ui.EditorSwitcherWidget.prototype.getPreferredEditorName = function () {
var i, len;
if ( this.initialContent !== '' ) {
// Find the first editor that matches this.contentFormat
@@ -192,8 +196,8 @@
*/
mw.flow.ui.EditorSwitcherWidget.prototype.getEditor = function ( name ) {
if ( !this.editors[ name ] ) {
+ this.constructor.static.editorDefinitions[ name ].static.setSwitchable( this.isSwitchable() );
this.editors[ name ] = new this.constructor.static.editorDefinitions[ name ]( {
- switchable: this.isSwitchable(),
placeholder: this.placeholder
} );
this.editors[ name ].connect( this, {
@@ -216,6 +220,11 @@
* @fires switch
*/
mw.flow.ui.EditorSwitcherWidget.prototype.switchEditor = function ( name ) {
+ var promise, switchingDeferred,
+ oldName, oldEditor, oldContent, oldFormat,
+ newEditor, newFormat,
+ widget = this;
+
if ( !this.isEditorAvailable( name ) ) {
return $.Deferred().reject().promise();
}
@@ -238,15 +247,13 @@
return $.Deferred().reject().promise();
}
- var promise,
- switchingDeferred = $.Deferred(),
- oldName = this.activeEditorName,
- oldEditor = this.getActiveEditor(),
- oldContent = oldEditor && oldEditor.getContent() || this.initialContent,
- oldFormat = this.contentFormat,
- newEditor = this.getEditor( name ),
- newFormat = newEditor.getFormat(),
- widget = this;
+ switchingDeferred = $.Deferred();
+ oldName = this.activeEditorName;
+ oldEditor = this.getActiveEditor();
+ oldContent = oldEditor && oldEditor.getContent() || this.initialContent;
+ oldFormat = this.contentFormat;
+ newEditor = this.getEditor( name );
+ newFormat = newEditor.getFormat();
this.switchingPromise = promise = switchingDeferred.promise();
this.switchingPromise.newEditorName = name;
@@ -263,9 +270,8 @@
return newEditor.setup( newContent );
} )
.then( function () {
- // Hide and detach the current editor if it exists
+ // Detach the current editor if it exists
if ( oldEditor ) {
- oldEditor.toggle( false );
return oldEditor.teardown()
.then( function () {
oldEditor.$element.detach();
@@ -285,15 +291,18 @@
widget.placeholderInput.$element.detach();
widget.$element.append( newEditor.$element );
- newEditor.toggle( true );
newEditor.afterAttach();
switchingDeferred.resolve();
widget.switchingPromise = null;
if ( shouldFocus ) {
- newEditor.focus();
- newEditor.moveCursorToEnd();
+ // Defer in case user event which triggered switch is
+ // a focus-stealing one.
+ setTimeout( function () {
+ newEditor.focus();
+ newEditor.moveCursorToEnd();
+ } );
}
} )
.fail( function ( error ) {
@@ -385,6 +394,9 @@
* @return {jQuery.Promise} Promise resolved when new content has been set
*/
mw.flow.ui.EditorSwitcherWidget.prototype.setContent = function ( content, contentFormat ) {
+ var promise, settingDeferred,
+ widget = this;
+
if ( this.settingPromise ) {
// TODO handle this more gracefully
return $.Deferred().reject();
@@ -398,9 +410,7 @@
return $.Deferred().resolve().promise();
}
- var promise,
- settingDeferred = $.Deferred(),
- widget = this;
+ settingDeferred = $.Deferred();
// Setting this.settingPromise prevents switchEditor() from changing the active editor
// while we convert
@@ -425,6 +435,20 @@
};
/**
+ * Clear the content of the current editor without triggering
+ * a change to the 'flow-editor' user preference.
+ */
+ mw.flow.ui.EditorSwitcherWidget.prototype.clearContent = function () {
+ var editor = this.getActiveEditor(),
+ oldActiveEditorName = this.activeEditorName;
+
+ // hack: blanking activeEditorName so the change event is ignored
+ this.activeEditorName = null;
+ editor.setContent( '' );
+ this.activeEditorName = oldActiveEditorName;
+ };
+
+ /**
* Toggle whether the editor is automatically focused after switching.
* @param {boolean} [autoFocus] Whether to focus automatically; if unset, flips current value
*/
@@ -446,6 +470,8 @@
return;
}
+ this.emit( 'change' );
+
// Normalize 'none' to 'wikitext'
if ( currentPref === 'none' ) {
currentPref = 'wikitext';
@@ -467,8 +493,6 @@
// Ensure we also see that preference in the current page
mw.user.options.set( 'flow-editor', name );
}
-
- this.emit( 'change' );
};
/**
@@ -518,12 +542,13 @@
* @return {boolean} Editors are switchable
*/
mw.flow.ui.EditorSwitcherWidget.prototype.isSwitchable = function () {
- return this.availableEditors.length > 1;
+ return mw.config.get( 'wgIsProbablyEditable' ) && this.availableEditors.length > 1;
};
mw.flow.ui.EditorSwitcherWidget.prototype.isDisabled = function () {
- // Auto-disable when pending
+ // Auto-disable when pending or not saveable
return this.isPending() ||
+ !this.isSaveable() ||
// Parent method
mw.flow.ui.EditorSwitcherWidget.parent.prototype.isDisabled.apply( this, arguments );
};
@@ -547,6 +572,27 @@
}
};
+ /**
+ * Check whether editor is saveable
+ *
+ * @return {boolean} Whether the user can save their content
+ */
+ mw.flow.ui.EditorSwitcherWidget.prototype.isSaveable = function () {
+ return this.saveable;
+ };
+
+ /**
+ * Toggle whether the editor is saveable
+ *
+ * @param {boolean} [saveable] Whether the editor is saveable
+ */
+ mw.flow.ui.EditorSwitcherWidget.prototype.toggleSaveable = function ( saveable ) {
+ this.saveable = saveable === undefined ? !this.saveable : !!saveable;
+
+ // Disabled state depends on saveable state
+ this.updateDisabled();
+ };
+
mw.flow.ui.EditorSwitcherWidget.prototype.pushPending = function () {
// Parent method
OO.ui.mixin.PendingElement.prototype.pushPending.apply( this, arguments );
diff --git a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js
index 00e69659..7649df71 100644
--- a/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js
+++ b/Flow/modules/flow/ui/widgets/editor/mw.flow.ui.EditorWidget.js
@@ -7,8 +7,6 @@
*
* @constructor
* @param {Object} [config] Configuration options
- * @cfg {string} [editor] The initial editor to load. Defaults to the editor
- * set in the user's preferences.
* @cfg {string} [content] An initial content for the textarea
* @cfg {string} [contentFormat] Format of config.content
* @cfg {string} [placeholder] Placeholder text to use for the editor when empty
@@ -19,6 +17,11 @@
* @cfg {boolean} [cancelOnEscape=true] Emit 'cancel' when Esc is pressed
* @cfg {boolean} [confirmCancel=true] Pop up a confirmation dialog if the user attempts
* to cancel when there are changes in the editor.
+ * @cfg {boolean} [confirmLeave=true] Pop up a confirmation dialog if the user attempts
+ * to navigate away when there are changes in the editor.
+ * @cfg {Function} [leaveCallback] Function to call when the user attempts to navigate away.
+ * If this function returns false, a confirmation dialog will be popped up.
+ * @cfg {boolean} [saveable=true] Initial state of whether editor is saveable
*/
mw.flow.ui.EditorWidget = function mwFlowUiEditorWidget( config ) {
var widget = this;
@@ -31,20 +34,25 @@
// Mixin constructors
OO.ui.mixin.PendingElement.call( this, config );
- this.initialEditor = config.editor;
this.confirmCancel = !!config.confirmCancel || config.cancelOnEscape === undefined;
+ this.confirmLeave = !!config.confirmLeave || config.confirmLeave === undefined;
+ this.leaveCallback = config.leaveCallback;
+
+ this.saveable = config.saveable !== undefined ? config.saveable : true;
this.editorControlsWidget = new mw.flow.ui.EditorControlsWidget( {
termsMsgKey: config.termsMsgKey || 'flow-terms-of-use-edit',
saveMsgKey: config.saveMsgKey || 'flow-newtopic-save',
- cancelMsgKey: config.cancelMsgKey || 'flow-cancel'
+ cancelMsgKey: config.cancelMsgKey || 'flow-cancel',
+ saveable: this.saveable
} );
this.editorSwitcherWidget = new mw.flow.ui.EditorSwitcherWidget( {
autoFocus: config.autoFocus,
content: config.content,
contentFormat: config.contentFormat,
- placeholder: config.placeholder
+ placeholder: config.placeholder,
+ saveable: this.saveable
} );
this.setPendingElement( this.editorSwitcherWidget.$element );
@@ -123,17 +131,16 @@
var widget = this;
if ( this.confirmCancel && this.editorSwitcherWidget.hasBeenChanged() ) {
- mw.flow.ui.windowManager.openWindow( 'cancelconfirm' )
- .then( function ( opened ) {
- opened.then( function ( closing, data ) {
- if ( data && data.action === 'discard' ) {
- // Remove content
- widget.setContent( '', 'wikitext' );
- widget.emit( 'cancel' );
- }
- } );
- } );
+ mw.flow.ui.windowManager.openWindow( 'cancelconfirm' ).closed.then( function ( data ) {
+ if ( data && data.action === 'discard' ) {
+ // Remove content
+ widget.setContent( '', 'wikitext' );
+ widget.unbindBeforeUnloadHandler();
+ widget.emit( 'cancel' );
+ }
+ } );
} else {
+ this.unbindBeforeUnloadHandler();
this.emit( 'cancel' );
}
};
@@ -181,18 +188,18 @@
*
* @return {string} Name of initial editor that will be used
*/
- mw.flow.ui.EditorWidget.prototype.getInitialEditorName = function () {
- return this.initialEditor || mw.user.options.get( 'flow-editor' );
+ mw.flow.ui.EditorWidget.prototype.getPreferredEditorName = function () {
+ return mw.user.options.get( 'flow-editor' );
};
/**
* Get the format of the editor that would be loaded if this widget were to be
* activated right now.
* @return {string|null} Format used by initial editor, or null if no editor is active
- * @see #getInitialEditorName
+ * @see #getPreferredEditorName
*/
- mw.flow.ui.EditorWidget.prototype.getInitialFormat = function () {
- return this.editorSwitcherWidget.getEditorFormat( this.getInitialEditorName() );
+ mw.flow.ui.EditorWidget.prototype.getPreferredFormat = function () {
+ return this.editorSwitcherWidget.getEditorFormat( this.getPreferredEditorName() );
};
/**
@@ -232,6 +239,7 @@
* @fires saveContent
*/
mw.flow.ui.EditorWidget.prototype.onEditorControlsWidgetSave = function () {
+ this.unbindBeforeUnloadHandler();
this.emit(
'saveContent',
this.editorSwitcherWidget.getActiveEditor().getContent(),
@@ -240,26 +248,62 @@
};
/**
+ * Bind the beforeunload handler, if needed and if not already bound.
+ */
+ mw.flow.ui.EditorWidget.prototype.bindBeforeUnloadHandler = function () {
+ if ( !this.beforeUnloadHandler && ( this.confirmLeave || this.leaveCallback ) ) {
+ this.beforeUnloadHandler = this.onBeforeUnload.bind( this );
+ $( window ).on( 'beforeunload', this.beforeUnloadHandler );
+ }
+ };
+
+ /**
+ * Unbind the beforeunload handler if it is bound.
+ */
+ mw.flow.ui.EditorWidget.prototype.unbindBeforeUnloadHandler = function () {
+ if ( this.beforeUnloadHandler ) {
+ $( window ).off( 'beforeunload', this.beforeUnloadHandler );
+ this.beforeUnloadHandler = null;
+ }
+ };
+
+ /**
+ * Respond to beforeunload event.
+ *
+ * @private
+ * @return {string|undefined}
+ */
+ mw.flow.ui.EditorWidget.prototype.onBeforeUnload = function () {
+ if ( this.leaveCallback && this.leaveCallback() === false ) {
+ return mw.msg( 'flow-cancel-warning' );
+ }
+ if ( this.confirmLeave && !this.isEmpty() ) {
+ return mw.msg( 'flow-cancel-warning' );
+ }
+ };
+
+ /**
* Activate the first editor, if not already active.
* @return {jQuery.Promise} Promise resolved when editor switch is done
*/
mw.flow.ui.EditorWidget.prototype.activate = function () {
- if ( this.isActive() ) {
- return $.Deferred().resolve().promise();
- }
+ var switchPromise,
+ editor = this.getPreferredEditorName(),
+ widget = this;
- // Doesn't call editorSwitcherWidget.activate() because we want to
- // evaluate the user preference as late as possible
- var editor = this.initialEditor || mw.user.options.get( 'flow-editor' );
if ( editor === 'none' ) {
editor = 'wikitext';
}
if ( this.editorSwitcherWidget.isEditorAvailable( editor ) ) {
- return this.editorSwitcherWidget.switchEditor( editor );
+ switchPromise = this.editorSwitcherWidget.switchEditor( editor );
+ } else {
+ // If the editor we want isn't available, let EditorSwitcherWidget decide which editor to use
+ switchPromise = this.editorSwitcherWidget.activate();
}
- // If the editor we want isn't available, let EditorSwitcherWidget decide which editor to use
- return this.editorSwitcherWidget.activate();
+ return switchPromise.then( function () {
+ widget.bindBeforeUnloadHandler();
+ } );
};
mw.flow.ui.EditorWidget.prototype.isDisabled = function () {
@@ -279,6 +323,22 @@
}
};
+ /**
+ * Toggle whether the editor is saveable
+ *
+ * This is different from setDisabled because that will also disable the cancel button.
+ * We want to allow them to click 'cancel' so they can collapse the editor again after
+ * seeing that editing is disabled.
+ *
+ * @param {boolean} [saveable] Whether the editor is saveable
+ */
+ mw.flow.ui.EditorWidget.prototype.toggleSaveable = function ( saveable ) {
+ this.saveable = saveable === undefined ? !this.saveable : !!saveable;
+
+ this.editorSwitcherWidget.toggleSaveable( this.saveable );
+ this.editorControlsWidget.toggleSaveable( this.saveable );
+ };
+
mw.flow.ui.EditorWidget.prototype.pushPending = function () {
// Parent method
OO.ui.mixin.PendingElement.prototype.pushPending.apply( this, arguments );
@@ -308,4 +368,8 @@
mw.flow.ui.EditorWidget.prototype.destroy = function () {
this.editorSwitcherWidget.destroy();
};
+
+ mw.flow.ui.EditorWidget.prototype.clearContent = function () {
+ this.editorSwitcherWidget.clearContent();
+ };
}( jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js
index f97ec270..10fb39d2 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.BoardDescriptionWidget.js
@@ -8,7 +8,10 @@
* @constructor
* @param {mw.flow.dm.Board} boardModel The board model
* @param {Object} [config]
- * @cfg {jQuery} $existing A jQuery object of the existing contents of the board description
+ * @cfg {jQuery} [$existing] A jQuery object of the existing contents of the board description
+ * @cfg {string} [specialPageCategoryLink] Link to the localized Special:Categories page
+ * @cfg {jQuery} [$categories] A jQuery object of the existing board categories
+ * @cfg {Object} [editor] Config options to pass to mw.flow.ui.EditorWidget
*/
mw.flow.ui.BoardDescriptionWidget = function mwFlowUiBoardDescriptionWidget( boardModel, config ) {
var $content = $();
@@ -18,7 +21,8 @@
// Parent constructor
mw.flow.ui.BoardDescriptionWidget.parent.call( this, config );
- this.attachModel( boardModel.getDescription() );
+ this.board = boardModel;
+ this.attachModel( this.board.getDescription() );
// Since the content is already displayed, we will "steal" the already created
// node to avoid having to render it twice.
@@ -30,20 +34,20 @@
}
this.$content = $( '<div>' )
- .addClass( 'flow-ui-boardDescriptionWidget-content' )
+ .addClass( 'flow-ui-boardDescriptionWidget-content mw-parser-output' )
.append( $content );
this.api = new mw.flow.dm.APIHandler(
- boardModel.getPageTitle().getPrefixedDb(),
+ this.board.getPageTitle().getPrefixedDb(),
{
currentRevision: this.model.getRevisionId()
}
);
- this.editor = new mw.flow.ui.EditorWidget( {
+ this.editor = new mw.flow.ui.EditorWidget( $.extend( {
saveMsgKey: mw.user.isAnon() ? 'flow-edit-header-submit-anonymously' : 'flow-edit-header-submit',
classes: [ 'flow-ui-boardDescriptionWidget-editor' ]
- } );
+ }, config.editor ) );
this.editor.toggle( false );
this.anonWarning = new mw.flow.ui.AnonWarningWidget();
@@ -54,6 +58,9 @@
} );
this.error.toggle( false );
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
+
this.button = new OO.ui.ButtonWidget( {
label: mw.msg( 'flow-edit-header-link' ),
framed: false,
@@ -62,20 +69,52 @@
classes: [ 'flow-ui-boardDescriptionWidget-editButton' ]
} );
+ if ( !this.model.isEditable() ) {
+ this.button.toggle( false );
+ }
+
+ this.categoriesWidget = new mw.flow.ui.CategoriesWidget( this.board, {
+ specialPageCategoryLink: config.specialPageCategoryLink
+ } );
+ if ( config.$categories ) {
+ this.addCategoriesFromDom( config.$categories );
+ }
+
// Events
this.button.connect( this, { click: 'onEditButtonClick' } );
this.editor.connect( this, {
saveContent: 'onEditorSaveContent',
cancel: 'onEditorCancel'
} );
+
+ // NOTE: Unlike other widgets, in the board description widget there is
+ // no use listening to change events in the content, because:
+ // 1. Any time the model changes, the widget must re-request the content
+ // in fixed-html format.
+ // 2. Due to the above, we initialize the widget already with the content
+ // from the DOM, and assume that all other changes to the content happen
+ // from the widget itself, which would run its own api request for the
+ // content in the proper format.
+ //
+ // The events below are specific listeners for specific behaviors identified
+ // as necessary.
+ this.model.connect( this, { editableChange: 'onModelEditableChange' } );
+
+ this.$messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' );
+
// Initialize
this.$element
.append(
- this.error.$element,
- this.anonWarning.$element,
- this.button.$element,
- this.$content,
- this.editor.$element
+ this.$messages.append(
+ this.error.$element,
+ this.captchaWidget.$element,
+ this.anonWarning.$element,
+ // Ensure inline button is on its own line, and is :first-child, T175683
+ $( '<div>' ).append( this.button.$element ),
+ this.$content
+ ),
+ this.editor.$element,
+ this.categoriesWidget.$element
)
.addClass( 'flow-ui-boardDescriptionWidget' );
};
@@ -84,18 +123,40 @@
OO.inheritClass( mw.flow.ui.BoardDescriptionWidget, OO.ui.Widget );
+ /* Events */
+
+ /**
+ * @event saveContent
+ * The content of the description was saved
+ */
+
+ /**
+ * @event cancel
+ * The edit operation on the description was canceled
+ */
+
/* Methods */
/**
+ * Respond to changes in the model's editable status
+ *
+ * @param {boolean} editable Description is editable
+ */
+ mw.flow.ui.BoardDescriptionWidget.prototype.onModelEditableChange = function ( editable ) {
+ this.button.toggle( editable && !this.editor.isVisible() );
+ };
+
+ /**
* Respond to edit button click. Switch to the editor widget
*/
mw.flow.ui.BoardDescriptionWidget.prototype.onEditButtonClick = function () {
var widget = this,
- contentFormat = this.editor.getInitialFormat() || 'wikitext';
+ contentFormat = this.editor.getPreferredFormat() || 'wikitext';
// Hide the edit button, any errors, and the content
this.button.toggle( false );
this.error.toggle( false );
+ this.categoriesWidget.toggle( false );
this.$content.addClass( 'oo-ui-element-hidden' );
this.editor.toggle( true );
@@ -141,36 +202,35 @@
/**
* Respond to an editor cancel event
+ * @fires cancel
*/
mw.flow.ui.BoardDescriptionWidget.prototype.onEditorCancel = function () {
this.showContent( true );
+ this.emit( 'cancel' );
};
/**
* Respond to editor save event. Save the content and display the new description.
*
* @param {string} content Content to save
- * @param {string} contentFormat Format of content
+ * @param {string} format Format of content
+ * @fires saveContent
*/
mw.flow.ui.BoardDescriptionWidget.prototype.onEditorSaveContent = function ( content, format ) {
var widget = this,
- $captchaField, captcha;
+ captchaResponse;
this.editor.pushPending();
- $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' );
- if ( $captchaField.length > 0 ) {
- captcha = {
- id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(),
- answer: $captchaField.val()
- };
- }
+ captchaResponse = this.captchaWidget.getResponse();
this.error.setLabel( '' );
this.error.toggle( false );
- this.api.saveDescription( content, format, captcha )
+ this.api.saveDescription( content, format, captchaResponse )
.then( function ( newRevisionId ) {
+ widget.captchaWidget.toggle( false );
+
// Update revisionId in the API
widget.api.setCurrentRevision( newRevisionId );
// Get the new header to update the dm.BoardDescription
@@ -185,26 +245,60 @@
.then( function ( desc ) {
// Change the actual content
widget.$content.empty().append( $.parseHTML( desc.content.content ) );
- widget.showContent( true );
+ widget.emit( 'saveContent' );
} )
.then( null, function ( errorCode, errorObj ) {
- if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) {
- widget.error.setLabel(
- // CAPTCHA form
- new OO.ui.HtmlSnippet( errorObj.error.info )
- );
- } else {
- widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception );
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
}
-
- widget.error.toggle( true );
} )
+ // Get the new categories
+ .then( this.api.getCategories.bind( this.api ) )
+ .then( function ( catObject ) {
+ var cat, title,
+ categories = {};
+
+ for ( cat in catObject ) {
+ title = mw.Title.newFromText( catObject[ cat ].title );
+ categories[ title.getName() ] = { exists: catObject[ cat ].missing === undefined };
+ }
+ // Update the board data model
+ widget.board.clearCategories();
+ widget.board.setCategoriesFromObject( categories );
+ } )
+ // Remove the editor and show content
+ .then( function () {
+ widget.showContent( true );
+ } )
+ // Always pop pending for the editor
.always( function () {
widget.editor.popPending();
} );
};
/**
+ * Add categories from a jQuery object. This is so that we can feed categories from the
+ * nojs rendering of the page without having the widget to ask the API for the categories
+ * when it just loads.
+ *
+ * @param {jQuery} [$categoriesWrapper] Categories div wrapper
+ */
+ mw.flow.ui.BoardDescriptionWidget.prototype.addCategoriesFromDom = function ( $categoriesWrapper ) {
+ var categories = {};
+
+ $categoriesWrapper.find( '.flow-board-header-category-item a' ).each( function () {
+ categories[ $( this ).text() ] = {
+ exists: !$( this ).hasClass( 'new' )
+ };
+ } );
+
+ this.board.setCategoriesFromObject( categories );
+ this.categoriesWidget.toggle( this.board.hasCategories() );
+ };
+
+ /**
* Show the content instead of the editor
*
* @param {boolean} [hideErrors] Hide error bar
@@ -222,6 +316,7 @@
// Display the edit button and the content
this.button.toggle( true );
this.$content.removeClass( 'oo-ui-element-hidden' );
+ this.categoriesWidget.toggle( this.board.hasCategories() );
};
/**
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.CaptchaWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.CaptchaWidget.js
new file mode 100644
index 00000000..4b90ce1e
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.CaptchaWidget.js
@@ -0,0 +1,85 @@
+( function ( $ ) {
+ /**
+ * This implements the UI portion of the CAPTCHA.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.flow.dm.Captcha} model
+ * @param {Object} [config]
+ */
+ mw.flow.ui.CaptchaWidget = function mwFlowUiCaptchaWidget( model, config ) {
+ mw.flow.ui.CaptchaWidget.parent.call( this, config );
+
+ this.toggle( false );
+
+ this.model = model;
+ this.model.connect( this, {
+ update: 'onUpdate'
+ } );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.CaptchaWidget, OO.ui.LabelWidget );
+
+ /* Methods */
+
+ /**
+ * Gets the CAPTCHA information, if any.
+ *
+ * @return {Object|null} captcha CAPTCHA information
+ * @return {string} captcha.id CAPTCHA ID
+ * @return {string} captcha.answer CAPTCHA answer (user-provided)
+ */
+ mw.flow.ui.CaptchaWidget.prototype.getResponse = function () {
+ var $captchaField = this.$element.find( '[name="wpCaptchaWord"]' ),
+ captcha = null;
+
+ if ( $captchaField.length > 0 ) {
+ captcha = {
+ id: this.$element.find( '[name="wpCaptchaId"]' ).val(),
+ answer: $captchaField.val()
+ };
+ }
+
+ return captcha;
+ };
+
+ /**
+ * Updates the widget in response to event
+ *
+ * @param {boolean} isRequired Whether a CAPTCHA is required
+ * @param {Object} renderingInformation Information needed to render CAPTCHA
+ * @param {string} renderingInformation.html Main HTML
+ * @param {Array} [renderingInformation.modules] Array of ResourceLoader module names
+ * @param {Array} [renderingInformation.modulestyles] Array of ResourceLoader module names to be
+ * included as style-only modules.
+ * @param {Array} [renderingInformation.headitems] Array of head items (see OutputPage::addHeadItems) (raw HTML
+ * strings)
+ */
+ mw.flow.ui.CaptchaWidget.prototype.onUpdate = function ( isRequired, renderingInformation ) {
+ var modules, moduleStyles, allModules;
+
+ if ( isRequired ) {
+ if ( renderingInformation.headitems ) {
+ $( 'head' ).append( renderingInformation.headitems.join( '' ) );
+ }
+
+ moduleStyles = renderingInformation.modulestyles || [];
+ modules = renderingInformation.modules || [];
+
+ allModules = moduleStyles.concat( modules );
+ mw.loader.using( allModules ).fail( function () {
+ OO.ui.alert( mw.message( 'flow-spam-confirmedit-using-failure' ).text() );
+ } ).always( function () {
+ this.setLabel( renderingInformation.html );
+ this.toggle( true );
+ }.bind( this ) );
+ } else {
+ this.toggle( false );
+ this.setLabel( '' );
+ }
+ };
+}( jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoriesWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoriesWidget.js
new file mode 100644
index 00000000..d53ac8ab
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoriesWidget.js
@@ -0,0 +1,114 @@
+( function ( $ ) {
+ /**
+ * Flow board categories widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {mw.flow.dm.Board} model Board model
+ * @param {Object} [config]
+ */
+ mw.flow.ui.CategoriesWidget = function mwFlowUiCategoriesWidget( model, config ) {
+ var $categoryList = $( '<ul>' )
+ .addClass( 'flow-board-header-category-list' ),
+ categoriesTitle = mw.Title.newFromText( 'Special:Categories' );
+
+ config = config || {};
+
+ // Parent constructor
+ mw.flow.ui.CategoriesWidget.parent.call( this, config );
+
+ // Mixin constructor
+ OO.ui.mixin.GroupElement.call( this, $.extend( { $group: $categoryList }, config ) );
+
+ this.model = model;
+ this.model.connect( this, {
+ addCategories: 'onModelAddCategories',
+ removeCategories: 'onModelRemoveCategories',
+ clearCategories: 'onModelClearCategories'
+ } );
+
+ this.$categoriesLabel = $( '<a>' )
+ .prop( 'href', config.specialPageCategoryLink || categoriesTitle.getUrl() );
+ this.updateCategoriesLabel();
+
+ // Initialize
+ this.$element
+ // Mimic the same structure as mediawiki category
+ // and the nojs version
+ .addClass( 'catlinks flow-board-header-category-view-js flow-ui-categoriesWidget' )
+ .prop( 'id', 'catlinks' )
+ .append(
+ $( '<div>' )
+ .prop( 'id', 'mw-normal-catlinks' )
+ .append(
+ this.$categoriesLabel,
+ mw.msg( 'colon-separator' ),
+ this.$group
+ )
+ .addClass( 'mw-normal-catlinks flow-board-header-category-view' )
+ );
+
+ this.toggle( this.model.hasCategories() );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.CategoriesWidget, OO.ui.Widget );
+ OO.mixinClass( mw.flow.ui.CategoriesWidget, OO.ui.mixin.GroupElement );
+
+ /**
+ * Respond to a change of categories in the board model
+ *
+ * @param {mw.flow.dm.CategoryItem[]} categories Added categories
+ */
+ mw.flow.ui.CategoriesWidget.prototype.onModelAddCategories = function ( categories ) {
+ var i, len,
+ widgets = [];
+
+ for ( i = 0, len = categories.length; i < len; i++ ) {
+ widgets.push( new mw.flow.ui.CategoryItemWidget( categories[ i ] ) );
+ }
+
+ this.addItems( widgets );
+ this.updateCategoriesLabel();
+ this.toggle( this.model.hasCategories() );
+ };
+
+ /**
+ * Respond to removing categories from the model
+ *
+ * @param {mw.flow.dm.CategoryItem[]} categories Removed categories
+ */
+ mw.flow.ui.CategoriesWidget.prototype.onModelRemoveCategories = function ( categories ) {
+ var i, len,
+ widgets = [];
+
+ for ( i = 0, len = categories.length; i < len; i++ ) {
+ widgets.push( this.getItemFromData( categories[ i ].getId() ) );
+ }
+
+ this.removeItems( widgets );
+ this.updateCategoriesLabel();
+ this.toggle( this.model.hasCategories() );
+ };
+
+ /**
+ * Respond to clearing all categories from the model
+ */
+ mw.flow.ui.CategoriesWidget.prototype.onModelClearCategories = function () {
+ this.clearItems();
+ };
+
+ /**
+ * Update the category label according to the number of available items
+ */
+ mw.flow.ui.CategoriesWidget.prototype.updateCategoriesLabel = function () {
+ this.$categoriesLabel.text(
+ // FIXME: this.model should be an instance of dm.Categories, not dm.Board
+ mw.msg( 'pagecategories', this.model.getCategories().getItemCount() )
+ );
+ };
+}( jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoryItemWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoryItemWidget.js
new file mode 100644
index 00000000..cec1eb18
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.CategoryItemWidget.js
@@ -0,0 +1,53 @@
+( function ( $ ) {
+ /**
+ * Flow board categories widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixin OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {mw.flow.dm.CategoryItem} categoryModel Category item model
+ * @param {Object} [config]
+ * @cfg {boolean} [exists] Category page exists on this wiki
+ */
+ mw.flow.ui.CategoryItemWidget = function mwFlowUiCategoryItemWidget( categoryModel, config ) {
+ var prefixedCleanName, $link;
+
+ config = config || {};
+
+ // Parent constructor
+ mw.flow.ui.CategoryItemWidget.parent.call( this, config );
+
+ this.model = categoryModel;
+ this.name = this.model.getId();
+ this.title = mw.Title.newFromText( this.name, mw.config.get( 'wgNamespaceIds' ).category );
+ this.exists = this.model.exists();
+ prefixedCleanName = this.title && this.title.getPrefixedText() || this.name;
+
+ $link = $( '<a>' )
+ .attr( 'href', mw.util.getUrl( this.title && this.title.getPrefixedDb() || this.name ) )
+ .attr( 'title', this.exists ? prefixedCleanName : mw.msg( 'red-link-title', prefixedCleanName ) )
+ .text( this.title && this.title.getNameText() || this.name )
+ .toggleClass( 'new', !this.exists );
+
+ this.$element
+ .addClass( 'flow-ui-categoryItemWidget flow-board-header-category-item' )
+ .append( $link );
+ };
+
+ OO.inheritClass( mw.flow.ui.CategoryItemWidget, OO.ui.Widget );
+
+ /* Static Properties */
+
+ mw.flow.ui.CategoryItemWidget.static.tagName = 'li';
+
+ /**
+ * Get the category data
+ *
+ * @return {string} Category name
+ */
+ mw.flow.ui.CategoryItemWidget.prototype.getData = function () {
+ return this.name;
+ };
+}( jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.EditPostWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.EditPostWidget.js
index 656d35b3..2f3f100f 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.EditPostWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.EditPostWidget.js
@@ -6,8 +6,10 @@
* @extends OO.ui.Widget
*
* @constructor
+ * @param {string} topicId The id of the topic
* @param {string} postId The id of the post to edit
* @param {Object} [config] Configuration object
+ * @cfg {Object} [editor] Config options to pass to mw.flow.ui.EditorWidget
*/
mw.flow.ui.EditPostWidget = function mwFlowUiEditPostWidget( topicId, postId, config ) {
config = config || {};
@@ -18,10 +20,10 @@
// Parent constructor
mw.flow.ui.EditPostWidget.parent.call( this, config );
- this.editor = new mw.flow.ui.EditorWidget( {
+ this.editor = new mw.flow.ui.EditorWidget( $.extend( {
saveMsgKey: mw.user.isAnon() ? 'flow-post-action-edit-post-submit-anonymously' : 'flow-post-action-edit-post-submit',
classes: [ 'flow-ui-editPostWidget-editor' ]
- } );
+ }, config.editor ) );
this.editor.toggle( true );
this.anonWarning = new mw.flow.ui.AnonWarningWidget();
@@ -32,6 +34,9 @@
} );
this.error.toggle( false );
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
+
this.api = new mw.flow.dm.APIHandler(
'Topic:' + topicId
);
@@ -42,23 +47,51 @@
cancel: 'onEditorCancel'
} );
+ this.$messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' );
+
this.$element
.addClass( 'flow-ui-editPostWidget' )
.append(
- this.anonWarning.$element,
- this.error.$element,
+ this.$messages.append(
+ this.anonWarning.$element,
+ this.error.$element,
+ this.captchaWidget.$element
+ ),
this.editor.$element
);
- // Load the editor
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.EditPostWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * Save the content of the reply
+ * @event saveContent
+ * @param {string} workflow The workflow this reply was saved under
+ * @param {string} content The content of the reply
+ * @param {string} contentFormat The format of the content of this reply
+ */
+
+ /* Methods */
+
+ /**
+ * Activate the widget. These needs to be called when it's visible and in the body.
+ */
+ mw.flow.ui.EditPostWidget.prototype.activate = function () {
+ var widget, contentFormat;
+
this.editor.pushPending();
this.editor.activate();
// Get the post from the API
- var widget = this,
- contentFormat = this.editor.getContentFormat();
+ widget = this;
+ contentFormat = this.editor.getContentFormat();
- this.api.getPost( topicId, postId, contentFormat ).then(
+ this.api.getPost( this.topicId, this.postId, contentFormat ).then(
function ( post ) {
var content = OO.getProp( post, 'content', 'content' ),
format = OO.getProp( post, 'content', 'format' );
@@ -84,25 +117,8 @@
// Focus again: pending editors are disabled and can't be focused
widget.editor.focus();
} );
-
};
- /* Initialization */
-
- OO.inheritClass( mw.flow.ui.EditPostWidget, OO.ui.Widget );
-
- /* Events */
-
- /**
- * Save the content of the reply
- * @event saveContent
- * @param {string} workflow The workflow this reply was saved under
- * @param {string} content The content of the reply
- * @param {string} contentFormat The format of the content of this reply
- */
-
- /* Methods */
-
/**
* Respond to editor cancel
*/
@@ -112,38 +128,32 @@
/**
* Respond to editor save
+ *
+ * @param {string} content Content
+ * @param {string} format Format
*/
mw.flow.ui.EditPostWidget.prototype.onEditorSaveContent = function ( content, format ) {
var widget = this,
- $captchaField, captcha;
+ captchaResponse;
- $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' );
- if ( $captchaField.length > 0 ) {
- captcha = {
- id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(),
- answer: $captchaField.val()
- };
- }
+ captchaResponse = this.captchaWidget.getResponse();
this.error.setLabel( '' );
this.error.toggle( false );
this.editor.pushPending();
- this.api.savePost( this.topicId, this.postId, content, format, captcha )
+ this.api.savePost( this.topicId, this.postId, content, format, captchaResponse )
.then( function ( workflow ) {
+ widget.captchaWidget.toggle( false );
+
widget.emit( 'saveContent', workflow, content, format );
} )
.then( null, function ( errorCode, errorObj ) {
- if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) {
- widget.error.setLabel(
- // CAPTCHA form
- new OO.ui.HtmlSnippet( errorObj.error.info )
- );
- } else {
- widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception );
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
}
-
- widget.error.toggle( true );
} )
.always( function () {
widget.editor.popPending();
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js
new file mode 100644
index 00000000..c982a7c3
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.EditTopicSummaryWidget.js
@@ -0,0 +1,176 @@
+( function ( $ ) {
+ /**
+ * Flow edit topic summary widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {string} topicId The id of the topic that has the summary we want to edit
+ * @param {Object} [config] Configuration object
+ * @cfg {Object} [editor] Config options to pass to mw.flow.ui.EditorWidget
+ */
+ mw.flow.ui.EditTopicSummaryWidget = function mwFlowUiEditTopicSummaryWidget( topicId, config ) {
+ config = config || {};
+
+ this.topicId = topicId;
+
+ // Parent constructor
+ mw.flow.ui.EditTopicSummaryWidget.parent.call( this, config );
+
+ this.editor = new mw.flow.ui.EditorWidget( $.extend( {
+ saveMsgKey: 'flow-topic-action-update-topic-summary',
+ classes: [ 'flow-ui-editTopicSummaryWidget-editor' ],
+ placeholder: mw.msg( 'flow-edit-summary-placeholder' )
+ }, config.editor ) );
+ this.editor.toggle( true );
+
+ this.anonWarning = new mw.flow.ui.AnonWarningWidget();
+ this.anonWarning.toggle( true );
+
+ this.error = new OO.ui.LabelWidget( {
+ classes: [ 'flow-ui-editTopicSummaryWidget-error flow-errors errorbox' ]
+ } );
+ this.error.toggle( false );
+
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
+
+ this.api = new mw.flow.dm.APIHandler(
+ 'Topic:' + topicId
+ );
+
+ // Events
+ this.editor.connect( this, {
+ saveContent: 'onEditorSaveContent',
+ cancel: 'onEditorCancel'
+ } );
+
+ this.$messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' );
+
+ this.$element
+ .addClass( 'flow-ui-editTopicSummaryWidget' )
+ .append(
+ this.$messages.append(
+ this.anonWarning.$element,
+ this.error.$element,
+ this.captchaWidget.$element
+ ),
+ this.editor.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.EditTopicSummaryWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * Save the content of the reply
+ * @event saveContent
+ * @param {string} workflow The workflow this reply was saved under
+ * @param {string} content The content of the reply
+ * @param {string} contentFormat The format of the content of this reply
+ */
+
+ /* Methods */
+
+ /**
+ * Activate the widget. These needs to be called when it's visible and in the body.
+ */
+ mw.flow.ui.EditTopicSummaryWidget.prototype.activate = function () {
+ var widget, contentFormat;
+
+ // Load the editor
+ this.editor.pushPending();
+ this.editor.activate();
+
+ // Get the post from the API
+ widget = this;
+ contentFormat = this.editor.getContentFormat();
+
+ this.api.getTopicSummary( this.topicId, contentFormat ).then(
+ function ( topicSummary ) {
+ var content = OO.getProp( topicSummary, 'content', 'content' ),
+ format = OO.getProp( topicSummary, 'content', 'format' );
+
+ if ( content !== undefined && format !== undefined ) {
+ // Give it to the editor
+ widget.editor.setContent( content, format );
+
+ // Update revisionId in the API
+ widget.api.setCurrentRevision( topicSummary.revisionId );
+ }
+
+ },
+ // Error fetching description
+ function ( error ) {
+ // Display error
+ widget.error.setLabel( mw.msg( 'flow-error-external', error ) );
+ widget.error.toggle( true );
+ }
+ ).always( function () {
+ // Unset pending editor
+ widget.editor.popPending();
+ // Focus again: pending editors are disabled and can't be focused
+ widget.editor.focus();
+ } );
+ };
+
+ /**
+ * Respond to editor cancel
+ */
+ mw.flow.ui.EditTopicSummaryWidget.prototype.onEditorCancel = function () {
+ this.emit( 'cancel' );
+ };
+
+ /**
+ * Respond to editor save
+ *
+ * @param {string} content Content
+ * @param {string} format Format
+ */
+ mw.flow.ui.EditTopicSummaryWidget.prototype.onEditorSaveContent = function ( content, format ) {
+ var widget = this,
+ captchaResponse;
+
+ captchaResponse = this.captchaWidget.getResponse();
+
+ this.error.setLabel( '' );
+ this.error.toggle( false );
+
+ this.editor.pushPending();
+ this.api.saveTopicSummary( this.topicId, content, format, captchaResponse )
+ .then( function ( workflow ) {
+ widget.captchaWidget.toggle( false );
+
+ widget.emit( 'saveContent', workflow, content, format );
+ } )
+ .then( null, function ( errorCode, errorObj ) {
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
+ }
+ } )
+ .always( function () {
+ widget.editor.popPending();
+ } );
+ };
+
+ /**
+ * Focus the reply widget on the editor
+ */
+ mw.flow.ui.EditTopicSummaryWidget.prototype.focus = function () {
+ this.editor.focus();
+ };
+
+ /**
+ * Destroy the widget
+ */
+ mw.flow.ui.EditTopicSummaryWidget.prototype.destroy = function () {
+ this.editor.destroy();
+ };
+
+}( jQuery ) );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.NavigationWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.NavigationWidget.js
index 8edc8c0f..4d5ee834 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.NavigationWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.NavigationWidget.js
@@ -119,7 +119,7 @@
if ( isScrolledDown ) {
// TODO use binary search
- $( '.flow-topic' ).each( function ( index, element ) {
+ $( '.flow-topic' ).each( function () {
if ( isElementInView( $( this ) ) ) {
topicId = $( this ).data( 'flowId' );
return false;
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js
index 6247307a..652e3839 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.NewTopicWidget.js
@@ -1,6 +1,6 @@
( function ( $ ) {
/**
- * Flow reply widget
+ * Flow new topic widget
*
* @class
* @extends OO.ui.Widget
@@ -9,45 +9,72 @@
* @param {string} page The page name, including namespace, that the
* board of this topic belongs to.
* @param {Object} [config] Configuration object
+ * @cfg {Object} [editor] Config options to pass to mw.flow.ui.EditorWidget
*/
mw.flow.ui.NewTopicWidget = function mwFlowUiNewTopicWidget( page, config ) {
- var widget = this;
+ var title,
+ widget = this;
config = config || {};
// Parent constructor
mw.flow.ui.NewTopicWidget.parent.call( this, config );
- this.page = page;
+ this.isProbablyEditable = mw.config.get( 'wgIsProbablyEditable' );
+
+ title = mw.Title.newFromText( page );
+ if ( title !== null ) {
+ this.page = title.getPrefixedText();
+ } else {
+ this.page = page;
+ }
+
this.expanded = false;
- this.anonWarning = new mw.flow.ui.AnonWarningWidget();
+ this.api = new mw.flow.dm.APIHandler( this.page );
+
+ this.anonWarning = new mw.flow.ui.AnonWarningWidget( {
+ isProbablyEditable: this.isProbablyEditable
+ } );
this.anonWarning.toggle( false );
+ this.canNotEdit = new mw.flow.ui.CanNotEditWidget( this.api, {
+ userGroups: mw.config.get( 'wgUserGroups' ),
+ restrictionEdit: mw.config.get( 'wgRestrictionEdit' ),
+ isProbablyEditable: this.isProbablyEditable
+ } );
+ this.canNotEdit.toggle( false );
+
this.title = new OO.ui.TextInputWidget( {
placeholder: mw.msg( 'flow-newtopic-start-placeholder' ),
- multiline: false,
classes: [ 'flow-ui-newTopicWidget-title' ]
} );
- this.editor = new mw.flow.ui.EditorWidget( {
+ this.editor = new mw.flow.ui.EditorWidget( $.extend( {
placeholder: mw.msg( 'flow-newtopic-content-placeholder', this.page ),
saveMsgKey: mw.user.isAnon() ? 'flow-newtopic-save-anonymously' : 'flow-newtopic-save',
autoFocus: false,
- classes: [ 'flow-ui-newTopicWidget-editor' ]
- } );
+ classes: [ 'flow-ui-newTopicWidget-editor' ],
+ saveable: mw.config.get( 'wgIsProbablyEditable' ),
+ leaveCallback: function () {
+ if ( widget.title.getValue() !== '' ) {
+ return false;
+ }
+ }
+ }, config.editor ) );
this.editor.toggle( false );
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
+
this.error = new OO.ui.LabelWidget( {
classes: [ 'flow-ui-newTopicWidget-error flow-errors errorbox' ]
} );
this.error.toggle( false );
- this.api = new mw.flow.dm.APIHandler( this.page );
-
// Events
this.editor.connect( this, {
- change: 'updateSaveButtonState',
+ change: 'updateFormState',
saveContent: 'onEditorSaveContent',
cancel: 'onEditorCancel'
} );
@@ -61,19 +88,25 @@
} );
this.title.connect( this, {
- change: 'updateSaveButtonState'
+ change: 'updateFormState'
} );
this.title.$element.on( 'focusin', this.onTitleFocusIn.bind( this ) );
this.title.$element.on( 'keydown', this.onTitleKeydown.bind( this ) );
// Initialization
- this.updateSaveButtonState();
+ this.updateFormState();
+
+ this.$messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' );
this.$element
.addClass( 'flow-ui-newTopicWidget' )
.append(
- this.anonWarning.$element,
- this.error.$element,
+ this.$messages.append(
+ this.anonWarning.$element,
+ this.canNotEdit.$element,
+ this.error.$element,
+ this.captchaWidget.$element
+ ),
this.title.$element,
this.editor.$element
);
@@ -84,11 +117,17 @@
OO.inheritClass( mw.flow.ui.NewTopicWidget, OO.ui.Widget );
/**
- * Update the state of the save button.
+ * Update the state of the form.
* @private
*/
- mw.flow.ui.NewTopicWidget.prototype.updateSaveButtonState = function () {
+ mw.flow.ui.NewTopicWidget.prototype.updateFormState = function () {
+ var isDisabled = this.isExpanded() && !this.isProbablyEditable;
+
+ this.title.setDisabled( isDisabled );
+ this.editor.editorSwitcherWidget.setDisabled( isDisabled );
+
this.editor.editorControlsWidget.toggleSaveable(
+ this.isProbablyEditable &&
this.title.getValue() &&
!this.editor.isEmpty()
);
@@ -106,11 +145,16 @@
* Expand the widget and make it ready to create a new topic
*/
mw.flow.ui.NewTopicWidget.prototype.activate = function () {
+ var widget = this;
if ( !this.isExpanded() ) {
// Expand the editor
this.toggleExpanded( true );
- this.editor.activate();
- this.title.focus();
+ this.editor.toggleAutoFocus( false );
+ this.editor.activate().then( function () {
+ widget.updateFormState();
+ widget.title.focus();
+ widget.editor.toggleAutoFocus( true );
+ } );
}
};
@@ -126,7 +170,7 @@
this.title.setValue( title );
if ( content && format ) {
- this.editor.setContent( content, format ).then( this.updateSaveButtonState.bind( this ) );
+ this.editor.setContent( content, format ).then( this.updateFormState.bind( this ) );
}
};
@@ -151,40 +195,30 @@
mw.flow.ui.NewTopicWidget.prototype.onEditorSaveContent = function ( content, format ) {
var widget = this,
title = this.title.getValue(),
- $captchaField,
- captcha;
+ captchaResponse;
this.editor.pushPending();
this.title.pushPending();
this.title.setDisabled( true );
- $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' );
- if ( $captchaField.length > 0 ) {
- captcha = {
- id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(),
- answer: $captchaField.val()
- };
- }
+ captchaResponse = this.captchaWidget.getResponse();
this.error.setLabel( '' );
this.error.toggle( false );
- this.api.saveNewTopic( title, content, format, captcha )
+ this.api.saveNewTopic( title, content, format, captchaResponse )
.then( function ( topicId ) {
+ widget.captchaWidget.toggle( false );
+
widget.toggleExpanded( false );
widget.emit( 'save', topicId );
} )
.then( null, function ( errorCode, errorObj ) {
- if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) {
- widget.error.setLabel(
- // CAPTCHA form
- new OO.ui.HtmlSnippet( errorObj.error.info )
- );
- } else {
- widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception );
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
}
-
- widget.error.toggle( true );
} )
.always( function () {
widget.editor.popPending();
@@ -194,8 +228,8 @@
.done( function () {
// Clear for next use
widget.title.setValue( '' );
- widget.editor.setContent( '', 'html' );
- widget.updateSaveButtonState();
+ widget.editor.clearContent();
+ widget.updateFormState();
} );
};
@@ -207,6 +241,8 @@
this.toggleExpanded( false );
// Take focus away from the title input, if it was focused (T109353)
this.title.blur();
+
+ this.updateFormState();
};
/**
@@ -224,8 +260,10 @@
mw.flow.ui.NewTopicWidget.prototype.toggleExpanded = function ( expanded ) {
this.expanded = expanded !== undefined ? expanded : !this.expanded;
+ this.$element.toggleClass( 'flow-ui-newTopicWidget-expanded', this.expanded );
this.editor.toggle( this.expanded );
this.anonWarning.toggle( this.expanded );
+ this.canNotEdit.toggle( this.expanded );
// Hide errors
this.error.toggle( false );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js
index 0531b68c..c3a5ebca 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.ReplyWidget.js
@@ -9,8 +9,9 @@
* @param {string} topicId The id of the topic this reply belongs to
* @param {string} replyTo The id this reply is a child of
* @param {Object} [config] Configuration object
- * @cfg {boolean} [expandable=true] Initialize the widget with the editor
- * already expanded. Otherwise, the widget is initialized with a trigger input.
+ * @cfg {boolean} [expandable=true] Initialize the widget with a trigger input. Otherwise,
+ * the widget will be initialized with the editor already open.
+ * @cfg {Object} [editor] Config options to pass to mw.flow.ui.EditorWidget
*/
mw.flow.ui.ReplyWidget = function mwFlowUiReplyWidget( topicId, replyTo, config ) {
config = config || {};
@@ -19,51 +20,62 @@
this.topicId = topicId;
this.expandable = config.expandable === undefined ? true : config.expandable;
this.expanded = !this.expandable;
+ this.placeholder = config.placeholder;
+ this.editorOptions = config.editor;
// Parent constructor
mw.flow.ui.ReplyWidget.parent.call( this, config );
- if ( this.expandable ) {
- this.triggerInput = new OO.ui.TextInputWidget( {
- multiline: false,
- classes: [ 'flow-ui-replyWidget-trigger-input' ],
- placeholder: config.placeholder
- } );
- this.triggerInput.$element.on( 'focusin', this.onTriggerFocusIn.bind( this ) );
- this.$element.append( this.triggerInput.$element );
- }
+ this.api = new mw.flow.dm.APIHandler();
- this.editor = new mw.flow.ui.EditorWidget( {
- placeholder: config.placeholder,
- saveMsgKey: mw.user.isAnon() ? 'flow-reply-link-anonymously' : 'flow-reply-link',
- classes: [ 'flow-ui-replyWidget-editor' ]
+ this.anonWarning = new mw.flow.ui.AnonWarningWidget( {
+ isProbablyEditable: mw.config.get( 'wgIsProbablyEditable' )
} );
- this.editor.toggle( !this.expandable );
-
- this.anonWarning = new mw.flow.ui.AnonWarningWidget();
this.anonWarning.toggle( !this.expandable );
+ this.canNotEdit = new mw.flow.ui.CanNotEditWidget( this.api, {
+ userGroups: mw.config.get( 'wgUserGroups' ),
+ restrictionEdit: mw.config.get( 'wgRestrictionEdit' ),
+ isProbablyEditable: mw.config.get( 'wgIsProbablyEditable' )
+ } );
+ this.canNotEdit.toggle( !this.expandable );
+
this.error = new OO.ui.LabelWidget( {
classes: [ 'flow-ui-replyWidget-error flow-errors errorbox' ]
} );
this.error.toggle( false );
- this.api = new mw.flow.dm.APIHandler();
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
- // Events
- this.editor.connect( this, {
- saveContent: 'onEditorSaveContent',
- cancel: 'onEditorCancel'
- } );
+ this.$messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' );
+ this.$editorContainer = $( '<div>' ).addClass( 'flow-ui-replyWidget-editor-container' );
this.$element
.addClass( 'flow-ui-replyWidget' )
.append(
- this.anonWarning.$element,
- this.error.$element,
- this.editor.$element
+ this.$messages.append(
+ this.anonWarning.$element,
+ this.canNotEdit.$element,
+ this.error.$element,
+ this.captchaWidget.$element
+ ),
+ this.$editorContainer
);
+ if ( this.expandable ) {
+ this.triggerInput = new OO.ui.TextInputWidget( {
+ classes: [ 'flow-ui-replyWidget-trigger-input' ],
+ placeholder: config.placeholder
+ } );
+ this.triggerInput.$element.on( 'focusin', this.onTriggerFocusIn.bind( this ) );
+ this.$element.append( this.triggerInput.$element );
+ } else {
+ // Only initialize the editor if we are not in 'expandable' mode
+ // Otherwise, the editor is lazy-loaded
+ this.initializeEditor();
+ this.editor.toggle( true );
+ }
};
/* Initialization */
@@ -97,6 +109,7 @@
this.error.toggle( false );
this.editor.toggle( false );
this.anonWarning.toggle( false );
+ this.canNotEdit.toggle( false );
this.triggerInput.toggle( true );
this.expanded = false;
} else {
@@ -106,44 +119,40 @@
/**
* Respond to editor save
+ *
+ * @param {string} content Content
+ * @param {string} format Format
*/
mw.flow.ui.ReplyWidget.prototype.onEditorSaveContent = function ( content, format ) {
var widget = this,
- $captchaField, captcha;
-
- $captchaField = this.error.$label.find( '[name="wpCaptchaWord"]' );
- if ( $captchaField.length > 0 ) {
- captcha = {
- id: this.error.$label.find( '[name="wpCaptchaId"]' ).val(),
- answer: $captchaField.val()
- };
- }
+ captchaResponse;
+
+ captchaResponse = this.captchaWidget.getResponse();
this.error.setLabel( '' );
this.error.toggle( false )
;
this.editor.pushPending();
- this.api.saveReply( this.topicId, this.replyTo, content, format, captcha )
+ this.api.saveReply( this.topicId, this.replyTo, content, format, captchaResponse )
.then( function ( workflow ) {
+ widget.captchaWidget.toggle( false );
+
if ( widget.expandable ) {
widget.triggerInput.toggle( true );
widget.editor.toggle( false );
widget.anonWarning.toggle( false );
+ widget.canNotEdit.toggle( false );
widget.expanded = false;
}
widget.emit( 'saveContent', workflow, content, format );
} )
.then( null, function ( errorCode, errorObj ) {
- if ( /spamfilter$/.test( errorCode ) && errorObj.error.spamfilter === 'flow-spam-confirmedit-form' ) {
- widget.error.setLabel(
- // CAPTCHA form
- new OO.ui.HtmlSnippet( errorObj.error.info )
- );
- } else {
- widget.error.setLabel( errorObj.error && errorObj.error.info || errorObj.exception );
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
}
- widget.error.toggle( true );
} )
.always( function () {
widget.editor.popPending();
@@ -151,7 +160,31 @@
};
/**
+ * Initialize the editor
+ */
+ mw.flow.ui.ReplyWidget.prototype.initializeEditor = function () {
+ if ( !this.editor ) {
+ this.editor = new mw.flow.ui.EditorWidget( $.extend( {
+ placeholder: this.placeholder,
+ saveMsgKey: mw.user.isAnon() ? 'flow-reply-link-anonymously' : 'flow-reply-link',
+ classes: [ 'flow-ui-replyWidget-editor' ],
+ saveable: mw.config.get( 'wgIsProbablyEditable' )
+ }, this.editorOptions ) );
+
+ this.$editorContainer.append( this.editor.$element );
+
+ // Events
+ this.editor.connect( this, {
+ saveContent: 'onEditorSaveContent',
+ cancel: 'onEditorCancel'
+ } );
+ }
+ };
+
+ /**
* Check if the widget is expandable
+ *
+ * @return {boolean}
*/
mw.flow.ui.ReplyWidget.prototype.isExpandable = function () {
return this.expandable;
@@ -159,6 +192,8 @@
/**
* Check if the widget is expanded
+ *
+ * @return {boolean}
*/
mw.flow.ui.ReplyWidget.prototype.isExpanded = function () {
return this.expanded;
@@ -174,6 +209,8 @@
}
this.toggle( true );
this.anonWarning.toggle( true );
+ this.canNotEdit.toggle( true );
+ this.initializeEditor();
this.editor.toggle( true );
this.editor.activate();
// If the editor was already active, focus it
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js
index ebe66792..d5c00811 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.SidebarExpandWidget.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Flow sidebar expand widget
*
@@ -64,7 +64,7 @@
// Change the preference
siderailState = this.collapsed ? 'collapsed' : 'expanded';
- if ( !mw.user.isAnon() && mw.user.options.get( 'flow-side-rail-state' ) !== siderailState ) {
+ if ( !mw.user.isAnon() && mw.user.options.get( 'flow-side-rail-state' ) !== siderailState ) {
// update the user preferences; no preferences for anons
new mw.Api().saveOption( 'flow-side-rail-state', siderailState );
@@ -84,4 +84,4 @@
mw.flow.ui.SidebarExpandWidget.prototype.isCollapsed = function () {
return this.collapsed;
};
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.ToCWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.ToCWidget.js
index 6a21cfcd..1e8920a9 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.ToCWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.ToCWidget.js
@@ -97,7 +97,7 @@
*/
mw.flow.ui.ToCWidget.prototype.updateSelection = function ( topicId ) {
var item = this.board.getItemById( topicId ),
- label = item && item.getContent();
+ label = item && item.getContent( 'plaintext' );
this.topicSelect.selectItemByData( item );
this.updateLabel( label );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js
index f4df00ec..9f5369cb 100644
--- a/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicMenuSelectWidget.js
@@ -1,4 +1,4 @@
-( function ( $ ) {
+( function () {
/**
* Flow topic list widget
*
@@ -64,19 +64,20 @@
* Respond to model topic content change and update the ToC content
*
* @param {mw.flow.dm.Topic} topic Topic
- * @param {string} content Content
*/
- mw.flow.ui.TopicMenuSelectWidget.prototype.onTopicContentChange = function ( topic, content ) {
+ mw.flow.ui.TopicMenuSelectWidget.prototype.onTopicContentChange = function ( topic ) {
var topicWidget = this.topics[ topic.getId() ];
if ( topicWidget ) {
- topicWidget.setLabel( content );
+ topicWidget.setLabel( topic.getContent( 'plaintext' ) );
}
};
/**
* Respond to scrolling of the menu. If we are close to the
* bottom, call for more topics.
+ *
+ * @return {boolean} False to prevent default event
*/
mw.flow.ui.TopicMenuSelectWidget.prototype.onMenuScroll = function () {
var actualHeight, naturalHeight, scrollTop, isNearBottom;
@@ -123,7 +124,7 @@
var widget = this;
this.loadingMoreTopics = true;
- this.system.fetchMoreTopics()
+ return this.system.fetchMoreTopics()
.then( function ( hasMoreTopicsInApi ) {
widget.noMoreTopics = !hasMoreTopicsInApi;
if ( widget.noMoreTopics ) {
@@ -151,7 +152,7 @@
if ( !optionWidget ) {
optionWidget = new OO.ui.MenuOptionWidget( {
data: items[ i ],
- label: items[ i ].getContent(),
+ label: items[ i ].getContent( 'plaintext' ),
classes: items[ i ].getModerationState() === 'lock' ?
[ 'flow-ui-topicMenuSelectWidget-locked' ] :
[]
@@ -231,4 +232,4 @@
mw.flow.ui.TopicMenuSelectWidget.parent.prototype.removeItems.call( this, items );
};
-}( jQuery ) );
+}() );
diff --git a/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js b/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js
new file mode 100644
index 00000000..2320c238
--- /dev/null
+++ b/Flow/modules/flow/ui/widgets/mw.flow.ui.TopicTitleWidget.js
@@ -0,0 +1,164 @@
+( function ( $ ) {
+ /**
+ * Topic title widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {string} topicId
+ * @param {Object} [config]
+ */
+ mw.flow.ui.TopicTitleWidget = function mwFlowUiTopicTitleWidget( topicId, config ) {
+ var widget = this;
+ config = config || {};
+ mw.flow.ui.TopicTitleWidget.parent.call( this, config );
+
+ this.topicId = topicId;
+ this.api = new mw.flow.dm.APIHandler(
+ 'Topic:' + topicId
+ );
+
+ this.anonWarning = new mw.flow.ui.AnonWarningWidget();
+ this.anonWarning.toggle( true );
+
+ this.error = new OO.ui.LabelWidget( {
+ classes: [ 'flow-ui-topicTitleWidget-error flow-errors errorbox' ]
+ } );
+ this.error.toggle( false );
+
+ this.captcha = new mw.flow.dm.Captcha();
+ this.captchaWidget = new mw.flow.ui.CaptchaWidget( this.captcha );
+
+ this.input = new OO.ui.TextInputWidget( {
+ classes: [ 'flow-ui-topicTitleWidget-titleInput' ],
+ autofocus: true
+ } );
+
+ this.termsLabel = new OO.ui.LabelWidget( {
+ classes: [ 'flow-ui-topicTitleWidget-termsLabel' ],
+ label: $( $.parseHTML( mw.message( 'flow-terms-of-use-edit' ).parse() ) )
+ } );
+
+ this.$controls = $( '<div>' ).addClass( 'flow-ui-topicTitleWidget-controls' );
+ this.$buttons = $( '<div>' ).addClass( 'flow-ui-topicTitleWidget-buttons' );
+ this.saveButton = new OO.ui.ButtonWidget( {
+ flags: [ 'primary', 'progressive' ],
+ label: mw.msg( 'flow-edit-title-submit' ),
+ classes: [ 'flow-ui-topicTitleWidget-saveButton' ]
+ } );
+
+ this.cancelButton = new OO.ui.ButtonWidget( {
+ flags: 'destructive',
+ framed: false,
+ label: mw.msg( 'flow-cancel' ),
+ classes: [ 'flow-ui-topicTitleWidget-cancelButton' ]
+ } );
+ this.$buttons.append(
+ this.cancelButton.$element,
+ this.saveButton.$element
+ );
+ this.$controls.append(
+ this.termsLabel.$element,
+ this.$buttons,
+ $( '<div>' ).css( 'clear', 'both' )
+ );
+
+ // Events
+ this.saveButton.connect( this, { click: [ 'onSaveButtonClick' ] } );
+ this.cancelButton.connect( this, { click: [ 'emit', 'cancel' ] } );
+
+ this.$element
+ .addClass( 'flow-ui-topicTitleWidget' )
+ .append(
+ this.anonWarning.$element,
+ this.error.$element,
+ this.captchaWidget.$element,
+ this.input.$element,
+ this.$controls
+ );
+
+ this.pushPending();
+ this.api.getPost( topicId, topicId, 'wikitext' ).then(
+ function ( topic ) {
+ var content = OO.getProp( topic, 'content', 'content' ),
+ currentRevisionId = topic.revisionId;
+
+ widget.api.setCurrentRevision( currentRevisionId );
+ widget.input.setValue( content );
+ },
+ function ( error ) {
+ widget.error.setLabel( mw.msg( 'flow-error-external', error ) );
+ widget.error.toggle( true );
+ }
+ ).always(
+ function () {
+ widget.popPending();
+ }
+ );
+
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.flow.ui.TopicTitleWidget, OO.ui.Widget );
+
+ /* Methods */
+
+ mw.flow.ui.TopicTitleWidget.prototype.onSaveButtonClick = function () {
+ var content = this.input.getValue(),
+ captcha = this.captchaWidget.getResponse(),
+ widget = this;
+
+ widget.pushPending();
+ this.api.saveTopicTitle( this.topicId, content, captcha ).then(
+ function ( workflowId ) {
+ widget.emit( 'saveContent', workflowId );
+ },
+ function ( errorCode, errorObj ) {
+ widget.captcha.update( errorCode, errorObj );
+ if ( !widget.captcha.isRequired() ) {
+ widget.error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ widget.error.toggle( true );
+ }
+ }
+ ).always(
+ function () {
+ widget.popPending();
+ }
+ );
+ };
+
+ mw.flow.ui.TopicTitleWidget.prototype.isDisabled = function () {
+ // Auto-disable when pending
+ return ( this.input && this.input.isPending() ) ||
+ // Parent method
+ mw.flow.ui.TopicTitleWidget.parent.prototype.isDisabled.apply( this, arguments );
+ };
+
+ mw.flow.ui.TopicTitleWidget.prototype.setDisabled = function ( disabled ) {
+ // Parent method
+ mw.flow.ui.TopicTitleWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if ( this.input && this.saveButton && this.cancelButton ) {
+ this.input.setDisabled( this.isDisabled() );
+ this.saveButton.setDisabled( this.isDisabled() );
+ this.cancelButton.setDisabled( this.isDisabled() );
+ }
+ };
+
+ mw.flow.ui.TopicTitleWidget.prototype.pushPending = function () {
+ this.input.pushPending();
+
+ // Disabled state depends on pending state
+ this.updateDisabled();
+ };
+
+ mw.flow.ui.TopicTitleWidget.prototype.popPending = function () {
+ this.input.popPending();
+
+ // Disabled state depends on pending state
+ this.updateDisabled();
+ };
+
+}( jQuery ) );
diff --git a/Flow/modules/messagePoster/ext.flow.messagePoster.js b/Flow/modules/messagePoster/ext.flow.messagePoster.js
index e365ad01..382680d2 100644
--- a/Flow/modules/messagePoster/ext.flow.messagePoster.js
+++ b/Flow/modules/messagePoster/ext.flow.messagePoster.js
@@ -13,13 +13,14 @@
* @extends mw.messagePoster.MessagePoster
*
* @param {mw.Title} title Title of Flow board
+ * @param {mw.Api} api mw.Api instance to use
*/
- mw.flow.MessagePoster = function MwFlowMessagePoster( title ) {
+ mw.flow.MessagePoster = function MwFlowMessagePoster( title, api ) {
// I considered using FlowApi, but most of that functionality is about mapping <form>
// or <a> tags to AJAX, which is not applicable. This allows us to keep
// mediawiki.messagePoster.flow-board light-weight.
- this.api = new mw.Api();
+ this.api = api;
this.title = title;
};
@@ -31,7 +32,7 @@
mw.flow.MessagePoster.prototype.post = function ( subject, body ) {
mw.flow.MessagePoster.parent.prototype.post.call( this, subject, body );
- return this.api.postWithToken( 'edit', {
+ return this.api.postWithToken( 'csrf', {
action: 'flow',
submodule: 'new-topic',
page: this.title.getPrefixedDb(),
diff --git a/Flow/modules/mw.flow.Initializer.js b/Flow/modules/mw.flow.Initializer.js
new file mode 100644
index 00000000..72acbb2b
--- /dev/null
+++ b/Flow/modules/mw.flow.Initializer.js
@@ -0,0 +1,991 @@
+( function ( $ ) {
+ /**
+ * Initializer object for flow-initialize
+ * @class
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ */
+ mw.flow.Initializer = function ( config ) {
+ config = config || {};
+
+ this.$component = null;
+ this.$board = null;
+ this.siderailCollapsed = mw.user.options.get( 'flow-side-rail-state' ) === 'collapsed';
+ this.pageTitle = config.pageTitle || mw.Title.newFromText( mw.config.get( 'wgPageName' ) );
+
+ this.system = null;
+ this.board = null;
+ this.navWidget = null;
+ };
+
+ /* Inheritance */
+
+ OO.initClass( mw.flow.Initializer );
+
+ /**
+ * Sets the DOM element that is the flow component
+ *
+ * @param {jQuery} $component The DOM element that is the component
+ * @return {boolean} The component DOM element exists and is set
+ */
+ mw.flow.Initializer.prototype.setComponentDom = function ( $component ) {
+ if ( !$component || !$component.length ) {
+ return false;
+ }
+ this.$component = $component;
+ return true;
+ };
+
+ /**
+ * Sets the DOM element that is the flow board
+ *
+ * @param {jQuery} $board The DOM element that is the board
+ * @return {boolean} The board DOM element exists and is set
+ */
+ mw.flow.Initializer.prototype.setBoardDom = function ( $board ) {
+ if ( !$board || !$board.length ) {
+ return false;
+ }
+ this.$board = $board;
+ return true;
+ };
+
+ /**
+ * Set the flowBoard object representing the 'old' Flow system board
+ *
+ * @param {Object} board flowBoard _RecursiveConstructor
+ */
+ mw.flow.Initializer.prototype.setBoardObject = function ( board ) {
+ var self = this;
+
+ this.flowBoard = board;
+
+ this.flowBoard.connect( this, {
+ loadmore: function ( topiclist ) {
+ // Add to dm board
+ if ( self.system ) {
+ self.system.populateBoardTopicsFromJson( topiclist );
+ }
+
+ // Replace reply forms
+ self.replaceReplyForms( self.$board );
+ },
+ // HACK: Update the DM when topic is refreshed
+ refreshTopic: function ( workflowId, topicData ) {
+ var revisionId, revision,
+ topic = self.board.getItemById( workflowId ),
+ data = topicData.flow[ 'view-topic' ].result.topic;
+
+ if ( !topic ) {
+ // New topic
+ mw.flow.system.populateBoardTopicsFromJson( data, 0 );
+ } else {
+ // Topic already exists. Repopulate
+ revisionId = data.posts[ workflowId ];
+ revision = data.revisions[ revisionId ];
+
+ topic.populate( revision );
+ }
+
+ // Replace reply forms
+ self.replaceReplyForms( topicData.$topic );
+ }
+ } );
+ };
+
+ /**
+ * Set up the window overlay
+ */
+ mw.flow.Initializer.prototype.setupWindowOverlay = function () {
+ // Set up window overlay
+ $( 'body' ).append( mw.flow.ui.windowOverlay.$element );
+ mw.flow.ui.windowOverlay.$element.append( mw.flow.ui.windowManager.$element );
+ };
+
+ /**
+ * Set up the sidebar widget if needed
+ */
+ mw.flow.Initializer.prototype.setupSidebarWidget = function () {
+ var sidebarExpandWidget,
+ self = this;
+
+ if (
+ this.$component.hasClass( 'flow-topic-page' ) &&
+ $( 'body' ).hasClass( 'action-view' )
+ ) {
+ this.$board.toggleClass( 'flow-board-expanded', this.siderailCollapsed );
+
+ // We are in single-topic view. Initialize the sidebar expand widget
+ sidebarExpandWidget = new mw.flow.ui.SidebarExpandWidget( {
+ collapsed: this.siderailCollapsed,
+ expandedButtonTitle: mw.msg( 'flow-topic-collapse-siderail' ),
+ collapsedButtonTitle: mw.msg( 'flow-topic-expand-siderail' )
+ } );
+ sidebarExpandWidget.$element.insertAfter( this.$board );
+
+ // Events
+ sidebarExpandWidget.on( 'toggle', function ( collapsed ) {
+ self.$board.toggleClass( 'flow-board-expanded', collapsed );
+ } );
+ }
+ };
+
+ /**
+ * Initialize the UI widgets
+ */
+ mw.flow.Initializer.prototype.initializeWidgets = function () {
+ // Set up window overlay
+ this.setupWindowOverlay();
+
+ // Set up sidebar widget if it needs to be there
+ this.setupSidebarWidget();
+
+ // Set up navigation widget
+ this.setupNavigationWidget( $( '.flow-board-navigation' ) );
+
+ // Set up new topic widget
+ this.setupNewTopicWidget( $( 'form.flow-newtopic-form' ) );
+
+ // Set up description widget
+ this.setupDescriptionWidget( $( '.flow-ui-boardDescriptionWidget' ) );
+
+ // Replace reply forms on the board
+ this.replaceReplyForms( this.$board );
+
+ /* Take over click actions */
+ this.setupReplyLinkActions();
+ this.setupEditPostAction();
+ this.setupEditTopicSummaryAction();
+ this.setupEditTopicTitleAction();
+ };
+
+ /**
+ * Initialize the 'old' Flow ui component
+ */
+ mw.flow.Initializer.prototype.initOldComponent = function () {
+ if ( this.$component ) {
+ mw.flow.initComponent( this.$component );
+ }
+ };
+
+ /**
+ * Initialize the data model objects
+ * @param {Object} config Configuration options for the mw.flow.dm.System
+ */
+ mw.flow.Initializer.prototype.initDataModel = function ( config ) {
+ var self = this;
+
+ this.system = new mw.flow.dm.System( config );
+ this.board = this.system.getBoard();
+ // Initialize the old system to accept the default
+ // order for the topic order widget
+ this.flowBoard.topicIdSort = this.board.getSortOrder();
+
+ // Events
+ this.board.connect( this, {
+ add: function ( newItems ) {
+ var i, len, item, itemId;
+
+ for ( i = 0, len = newItems.length; i < len; i++ ) {
+ item = newItems[ i ];
+ itemId = item.getId();
+
+ if ( $.inArray( itemId, self.flowBoard.orderedTopicIds ) === -1 ) {
+ self.flowBoard.orderedTopicIds.push( itemId );
+ }
+
+ self.flowBoard.topicTitlesById[ itemId ] = item.getContent();
+ self.flowBoard.updateTimestampsByTopicId[ itemId ] = item.getLastUpdate();
+ }
+ self.flowBoard.sortTopicIds( self.flowBoard );
+ },
+ // E.g. on topic re-order, before re-population.
+ clear: function () {
+ self.flowBoard.orderedTopicIds = [];
+ self.flowBoard.topicTitlesById = {};
+ }
+ // We shouldn't have to worry about 'remove', since by the time we have filtering,
+ // orderedTopicIds should be gone.
+ } );
+ };
+
+ /**
+ * Get the data model system
+ *
+ * @return {mw.flow.dm.System} DM system
+ */
+ mw.flow.Initializer.prototype.getDataModelSystem = function () {
+ return this.system;
+ };
+
+ /**
+ * Populate the data model
+ *
+ * @param {Object} dataBlob Data blob to populate the system with
+ */
+ mw.flow.Initializer.prototype.populateDataModel = function ( dataBlob ) {
+ var preloadTopic = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'topic' ),
+ preloadContent = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'content' ),
+ preloadFormat = OO.getProp( dataBlob, 'blocks', 'topiclist', 'submitted', 'format' );
+
+ if ( dataBlob && dataBlob.blocks ) {
+ // Populate the rendered topics or topic (if we are in a single-topic view)
+ this.system.populateBoardTopicsFromJson( dataBlob.blocks.topiclist || dataBlob.blocks.topic );
+ // Populate header
+ this.system.populateBoardDescriptionFromJson( dataBlob.blocks.header || {} );
+ // Populate the ToC topics
+ if ( dataBlob.toc ) {
+ this.system.populateBoardTopicsFromJson( dataBlob.toc );
+ }
+ } else {
+ this.system.populateBoardFromApi();
+ }
+ if ( preloadTopic || preloadContent ) {
+ this.newTopicWidget.preload( preloadTopic, preloadContent, preloadFormat );
+ }
+ };
+
+ /**
+ * Set up the navigation widget and its events
+ *
+ * @param {jQuery} $navDom Navigation widget DOM element
+ */
+ mw.flow.Initializer.prototype.setupNavigationWidget = function ( $navDom ) {
+ var self = this;
+
+ if ( !$navDom.length ) {
+ return;
+ }
+
+ this.navWidget = new mw.flow.ui.NavigationWidget( this.system, {
+ defaultSort: this.flowBoard.topicIdSort
+ } );
+ $navDom.append( this.navWidget.$element );
+
+ // Events
+ // Load a topic from the ToC that isn't rendered on
+ // the page yet. This will be gone once board, topic
+ // and post are widgetized.
+ this.navWidget.connect( this, {
+ loadTopic: function ( topicId ) {
+ self.flowBoard.jumpToTopic( topicId );
+ },
+ reorderTopics: function ( newOrder ) {
+ self.flowBoard.topicIdSort = newOrder;
+ }
+ } );
+
+ // Connect to system events
+
+ // HACK: These event handlers should be in the prospective widgets
+ // they will move once we have Board UI and Topic UI widgets
+ this.system.connect( this, {
+ resetBoardStart: function () {
+ self.$component.addClass( 'flow-api-inprogress' );
+ // Before we reinitialize the board we have to detach
+ // the navigation widget. This should not be necessary when
+ // the board and topics are OOUI widgets
+ self.navWidget.$element.detach();
+ },
+ resetBoardEnd: function ( data ) {
+ var $rendered;
+
+ // populateBoardFromApi uses the larger TOC limit so the TOC can
+ // be fully populated on re-sort. To avoid two requests
+ // (TOC and full topics) with different limits, we do a single
+ // full-topic request with that limit.
+ //
+ // However, this is inconsistent with the number of topics
+ // we show at page load.
+ //
+ // This could be addressed by either showing the larger number of
+ // topics on page load, doing two separate requests (might still be
+ // faster considering the backend doesn't have to get full data for
+ // many topics), or filtering the topic list on render.
+ //
+ // The latter (filter on render) could be done when the topic- and
+ // board-widget are operational using some sort of computed subset
+ // data model.
+ $rendered = $(
+ mw.flow.TemplateEngine.processTemplateGetFragment(
+ 'flow_block_loop',
+ { blocks: data }
+ )
+ ).children();
+ // Run this on a short timeout so that the other board handler in FlowBoardComponentLoadMoreFeatureMixin can run
+ // TODO: Using a timeout doesn't seem like the right way to do this.
+ setTimeout( function () {
+ var boardEl = $rendered[ 1 ];
+
+ // Since we've replaced the entire board, we need to reinitialize
+ // it. This also takes away the original navWidget, so we need to
+ // make sure it's reinitialized too
+ self.flowBoard.reinitializeContainer( $rendered );
+ $( '.flow-board-navigation' ).append( self.navWidget.$element );
+
+ self.setBoardDom( $( boardEl ) );
+
+ self.replaceReplyForms( self.$board );
+
+ self.setupNewTopicWidget( $( 'form.flow-newtopic-form' ) );
+
+ self.$component.removeClass( 'flow-api-inprogress' );
+ }, 50 );
+ }
+ } );
+ };
+
+ /**
+ * Set up the new topic widget and its events
+ *
+ * @param {jQuery} $form New topic form DOM element
+ */
+ mw.flow.Initializer.prototype.setupNewTopicWidget = function ( $form ) {
+ var self = this;
+
+ this.newTopicWidget = new mw.flow.ui.NewTopicWidget( this.pageTitle.getPrefixedDb(), {
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+
+ // Events
+ this.newTopicWidget.connect( this, {
+ save: function ( newTopicId ) {
+ // Display the new topic with the old system
+ var $stub = $( '<div class="flow-topic"><div></div></div>' ).prependTo( self.flowBoard.$container.find( '.flow-topics' ) );
+ return this.flowBoard.flowBoardComponentRefreshTopic( $stub.find( 'div' ), newTopicId );
+ }
+ } ).once( 'save', this.reloadOnCreate ); // Reload page if board is new so we get page actions at top
+
+ $form.replaceWith( this.newTopicWidget.$element );
+ };
+
+ /**
+ * Set up the description widget and its events
+ *
+ * @param {jQuery} $element Description DOM element
+ */
+ mw.flow.Initializer.prototype.setupDescriptionWidget = function ( $element ) {
+ var descriptionWidget;
+
+ if ( !$element.length ) {
+ return;
+ }
+
+ descriptionWidget = new mw.flow.ui.BoardDescriptionWidget( this.board, {
+ $existing: $( '.flow-ui-boardDescriptionWidget-content' ).contents(),
+ $categories: $( '.flow-board-header-category-view-nojs' ).contents(),
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } ).once( 'saveContent', this.reloadOnCreate ); // Reload page if board is new so we get page actions at top
+
+ // The category widget is inside the board description widget.
+ // Remove it from the nojs version here
+ $( '.flow-board-header-category-view-nojs' ).detach();
+ // HACK: Remove the MW page categories
+ $( '.catlinks:not(.flow-ui-categoriesWidget)' ).detach();
+
+ $element.replaceWith( descriptionWidget.$element );
+ };
+
+ /**
+ * If the board page is being saved for the first time, reload the page
+ * to show actions like History, Move, Protect, etc.
+ */
+ mw.flow.Initializer.prototype.reloadOnCreate = function () {
+ if ( mw.config.get( 'wgArticleId' ) === 0 ) {
+ location.reload();
+ }
+ };
+
+ /**
+ * Replace the reply forms given by the php version with js editors
+ *
+ * @param {jQuery} $element The element to conduct the replacements in
+ */
+ mw.flow.Initializer.prototype.replaceReplyForms = function ( $element ) {
+ var self = this;
+
+ if ( !$element || !$element.length ) {
+ return;
+ }
+
+ $element.find( '.flow-post.flow-reply-form' ).each( function () {
+ var $topic = $( this ).parent(),
+ placeholder = mw.msg( 'flow-reply-topic-title-placeholder', $topic.find( '.flow-topic-title' ).text().trim() ),
+ replyTo = $( this ).find( 'input[name="topic_replyTo"]' ).val(),
+ replyWidget = new mw.flow.ui.ReplyWidget( $topic.data( 'flowId' ), replyTo, {
+ placeholder: placeholder,
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+
+ replyWidget.on( 'saveContent', function ( workflow ) {
+ replyWidget.destroy();
+ replyWidget.$element.remove();
+
+ // HACK: get the old system to rerender the topic
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } );
+ replyWidget.$element.data( 'self', replyWidget );
+
+ // Replace the reply form with the new editor widget
+ $( this ).replaceWith( replyWidget.$element );
+ } );
+ };
+
+ /**
+ * Take over the action of the 'edit post' links
+ * This is delegated, so it applies to all future links as well.
+ */
+ mw.flow.Initializer.prototype.setupEditPostAction = function () {
+ this.$component.on( 'click', '.flow-ui-edit-post-link', function ( event ) {
+ var editPostWidget,
+ $topic = $( this ).closest( '.flow-topic' ),
+ topicId = $topic.data( 'flow-id' ),
+ $post = $( this ).closest( '.flow-post' ),
+ $postMain = $post.children( '.flow-post-main' ),
+ postId = $post.data( 'flow-id' ),
+ $board = $( '.flow-board' ),
+ flowBoard = mw.flow.getPrototypeMethod( 'component', 'getInstanceByElement' )( $board );
+
+ editPostWidget = new mw.flow.ui.EditPostWidget( topicId, postId, {
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+ editPostWidget
+ .on( 'saveContent', function ( workflow ) {
+ editPostWidget.destroy();
+ editPostWidget.$element.remove();
+
+ // HACK get the old system to rerender the topic
+ return flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } )
+ .on( 'cancel', function () {
+ editPostWidget.destroy();
+ editPostWidget.$element.replaceWith( $postMain );
+ } );
+
+ $postMain.replaceWith( editPostWidget.$element );
+ editPostWidget.activate();
+
+ event.preventDefault();
+ } );
+ };
+
+ /**
+ * Take over the action of the 'edit topic summary' links
+ * This is delegated, so it applies to all future links as well.
+ */
+ mw.flow.Initializer.prototype.setupEditTopicSummaryAction = function () {
+ var self = this;
+
+ this.$component
+ // Summarize action
+ .on( 'click', '.flow-ui-summarize-topic-link', function ( event ) {
+ var $topic = $( this ).closest( '.flow-topic' ),
+ topicId = $topic.data( 'flow-id' );
+
+ self.startEditTopicSummary( true, topicId );
+ event.preventDefault();
+ } )
+ // Lock action
+ .on( 'click', '.flow-ui-topicmenu-lock', function () {
+ var promise,
+ action = $( this ).data( 'role' ),
+ $topic = $( this ).closest( '.flow-topic' ),
+ topicId = $topic.data( 'flow-id' ),
+ api = new mw.flow.dm.APIHandler();
+
+ if ( action === 'lock' ) {
+ promise = api.resolveTopic( topicId );
+ } else {
+ promise = api.reopenTopic( topicId );
+ }
+
+ promise
+ .then( function ( workflow ) {
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } )
+ .then( function ( data ) {
+ var revisionId = data.topic.posts[ topicId ],
+ revision = data.topic.revisions[ revisionId ],
+ summaryContent = OO.getProp( revision, 'summary', 'revision', 'content', 'content' ),
+ skipSummarize = action === 'unlock' && !summaryContent;
+
+ if ( !skipSummarize ) {
+ self.startEditTopicSummary( true, topicId, action );
+ }
+ } );
+
+ // Prevent default
+ return false;
+ } );
+ };
+
+ /**
+ * Take over the action of the 'edit topic title' links
+ * This is delegated, so it applies to all future links as well.
+ */
+ mw.flow.Initializer.prototype.setupEditTopicTitleAction = function () {
+ var self = this;
+
+ this.$component
+ .on( 'click', 'a.flow-ui-edit-title-link', function ( event ) {
+ var $topic = $( this ).closest( '.flow-topic' ),
+ topicId = $topic.data( 'flow-id' ),
+ $container = $topic.find( '.flow-topic-titlebar-container' ),
+ $topicTitleViewMode = $container.find( 'h2.flow-topic-title' ),
+ $editForm = $topic.find( '.flow-ui-topicTitleWidget' ),
+ widget;
+
+ if ( $editForm.length ) {
+ event.preventDefault();
+ return false;
+ }
+
+ widget = new mw.flow.ui.TopicTitleWidget( topicId, {
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+ widget
+ .on( 'saveContent', function ( workflow ) {
+ widget.$element.remove();
+
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } )
+ .on( 'cancel', function () {
+ widget.$element.remove();
+ $container.prepend( $topicTitleViewMode );
+ } );
+
+ $topicTitleViewMode.remove();
+ $container.prepend( widget.$element );
+
+ event.preventDefault();
+ } );
+ };
+
+ /**
+ * Take over the action of the 'reply' links. This is delegated,
+ * so it applies to current and future links.
+ */
+ mw.flow.Initializer.prototype.setupReplyLinkActions = function () {
+ var self = this;
+
+ // Replace the handler used for reply links.
+ this.$component.on( 'click', 'a.flow-reply-link', function () {
+ // Store the needed details so we can get rid of the URL in JS mode
+ var replyWidget,
+ href = $( this ).attr( 'href' ),
+ uri = new mw.Uri( href ),
+ replyTo = uri.query.topic_postId,
+ $topic = $( this ).closest( '.flow-topic' ),
+ placeholder = mw.msg( 'flow-reply-topic-title-placeholder', $topic.find( '.flow-topic-title' ).text().trim() ),
+ // replyTo can refer to a post ID or a topic ID
+ // For posts, the ReplyWidget should go in .flow-replies
+ // For topics, it's directly inside the topic
+ $targetContainer = $( '#flow-post-' + replyTo + ' > .flow-replies, #flow-topic-' + replyTo ),
+ $existingWidget = $targetContainer.children( '.flow-ui-replyWidget' );
+
+ // Check that there's not already a reply widget existing in the same place
+ if ( $existingWidget.length > 0 ) {
+ // Focus the existing reply widget
+ $existingWidget.data( 'self' ).activateEditor();
+ $existingWidget.data( 'self' ).focus();
+ return false;
+ }
+
+ replyWidget = new mw.flow.ui.ReplyWidget( $topic.data( 'flowId' ), replyTo, {
+ placeholder: placeholder,
+ expandable: false,
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+ // Create a reference so we can call it from the DOM above
+ replyWidget.$element.data( 'self', replyWidget );
+
+ // Add reply form below the post being replied to (WRT max depth)
+ $targetContainer.append( replyWidget.$element );
+ replyWidget.activateEditor();
+
+ replyWidget
+ .on( 'saveContent', function ( workflow ) {
+ replyWidget.destroy();
+ replyWidget.$element.remove();
+
+ // HACK get the old system to rerender the topic
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } )
+ .on( 'cancel', function () {
+ replyWidget.destroy();
+ replyWidget.$element.remove();
+ } );
+
+ return false;
+ } );
+ };
+
+ /**
+ * Initialize the edit topic summary action
+ *
+ * @param {boolean} isFullBoard The page is a full board page
+ * @param {string} topicId Topic id
+ * @param {string} [action] Lock action 'lock' or 'unlock'. If not given, the action
+ * is assumed as summary only.
+ */
+ mw.flow.Initializer.prototype.startEditTopicSummary = function ( isFullBoard, topicId, action ) {
+ var editTopicSummaryWidget,
+ self = this,
+ $topic = $( '#flow-topic-' + topicId ),
+ $summaryContainer = $topic.find( '.flow-topic-summary-container' ),
+ $topicSummary = $summaryContainer.find( '.flow-topic-summary' ),
+ editorOptions = {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ },
+ pageName = mw.config.get( 'wgPageName' ),
+ title = mw.Title.newFromText( pageName );
+
+ if ( !$summaryContainer.length ) {
+ return;
+ }
+
+ // Don't launch a summary editor when there is one already
+ if ( $summaryContainer.find( '.flow-ui-editTopicSummaryWidget' ).length ) {
+ return;
+ }
+
+ // TODO: This should be managed by the EditTopicSummary widget
+ if ( action === 'lock' || action === 'unlock' ) {
+ editorOptions.cancelMsgKey = 'flow-skip-summary';
+ }
+
+ editTopicSummaryWidget = new mw.flow.ui.EditTopicSummaryWidget( topicId, { editor: editorOptions } );
+ editTopicSummaryWidget
+ .on( 'saveContent', function ( workflow ) {
+ editTopicSummaryWidget.destroy();
+ editTopicSummaryWidget.$element.remove();
+
+ if ( isFullBoard ) {
+ // HACK get the old system to rerender the topic
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ } else {
+ // HACK: redirect to topic view
+ window.location.href = title.getUrl();
+ }
+ } )
+ .on( 'cancel', function () {
+ editTopicSummaryWidget.destroy();
+ editTopicSummaryWidget.$element.remove();
+ if ( isFullBoard ) {
+ $summaryContainer.append( $topicSummary );
+ } else {
+ // HACK: redirect to topic view
+ window.location.href = title.getUrl();
+ }
+ } );
+
+ $topicSummary.remove();
+ $summaryContainer.append( editTopicSummaryWidget.$element );
+ editTopicSummaryWidget.activate();
+ };
+
+ /**
+ * Replace the editor in no-js pages, like editing in a separate window
+ *
+ * @param {jQuery} $element The element to conduct the replacements in
+ */
+ mw.flow.Initializer.prototype.replaceNoJSEditor = function ( $element ) {
+ var editPostWidget,
+ $post = $element.parent(),
+ $topic = $post.closest( '.flow-topic' ),
+ self = this;
+
+ function saveOrCancelHandler( workflow ) {
+ editPostWidget.destroy();
+ editPostWidget.$element.remove();
+
+ // HACK get the old system to rerender the topic
+ return self.flowBoard.flowBoardComponentRefreshTopic(
+ $topic,
+ workflow
+ );
+ }
+
+ if ( !$element.length ) {
+ return;
+ }
+
+ editPostWidget = new mw.flow.ui.EditPostWidget( $topic.data( 'flowId' ), $post.data( 'flowId' ), {
+ editor: {
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ }
+ } );
+
+ editPostWidget
+ .on( 'saveContent', saveOrCancelHandler )
+ // HACK: In this case, we are in an edge case where the topic already
+ // loaded with the editor open. We can't trust the content of the editor
+ // for displaying the post in case of a 'cancel' event and we don't have
+ // the actual content stored in the DOM anywhere else.
+ // We must reload the topic -- just like we do on save -- for a cancel
+ // event too.
+ .on( 'cancel', saveOrCancelHandler.bind( null, $topic.data( 'flowId' ) ) );
+
+ $element.replaceWith( editPostWidget.$element );
+ editPostWidget.activate();
+ };
+
+ /**
+ * Create an editor widget
+ *
+ * @param {jQuery} $domToReplace The element, usually a form, that the new editor replaces
+ * @param {string} [content] The content of the editing area
+ * @param {string} [saveMsgKey] The message key for the editor save button
+ * @return {mw.flow.ui.EditorWidget}
+ */
+ mw.flow.Initializer.prototype.createEditorWidget = function ( $domToReplace, content, saveMsgKey ) {
+ var $wrapper,
+ $messages = $( '<div>' ).addClass( 'flow-ui-editorContainerWidget-messages' ),
+ isProbablyEditable = mw.config.get( 'wgIsProbablyEditable' ),
+ anonWarning = new mw.flow.ui.AnonWarningWidget( {
+ isProbablyEditable: isProbablyEditable
+ } ),
+ canNotEdit = new mw.flow.ui.CanNotEditWidget( new mw.flow.dm.APIHandler(), {
+ userGroups: mw.config.get( 'wgUserGroups' ),
+ restrictionEdit: mw.config.get( 'wgRestrictionEdit' ),
+ isProbablyEditable: isProbablyEditable
+ } ),
+ captcha = new mw.flow.dm.Captcha(),
+ captchaWidget = new mw.flow.ui.CaptchaWidget( captcha ),
+ error = new OO.ui.LabelWidget( {
+ classes: [ 'flow-ui-boardDescriptionWidget-error flow-errors errorbox' ]
+ } ),
+ editor = new mw.flow.ui.EditorWidget( {
+ saveMsgKey: saveMsgKey,
+ confirmLeave: !!mw.user.options.get( 'useeditwarning' )
+ } );
+
+ function handleFailure( errorCode, errorObj ) {
+ captchaWidget.model.update( errorCode, errorObj );
+
+ if ( !captchaWidget.model.isRequired() ) {
+ error.setLabel( new OO.ui.HtmlSnippet( errorObj.error && errorObj.error.info || errorObj.exception ) );
+ error.toggle( true );
+ }
+
+ editor.popPending();
+ }
+
+ error.toggle( false );
+ editor.toggle( true );
+ anonWarning.toggle( mw.user.isAnon() );
+ canNotEdit.toggle( !isProbablyEditable );
+
+ $wrapper = $( '<div>' )
+ .append(
+ $messages.append(
+ error.$element,
+ captchaWidget.$element,
+ anonWarning.$element,
+ canNotEdit.$element
+ ),
+ editor.$element
+ );
+
+ $domToReplace.replaceWith( $wrapper );
+
+ // Prepare the editor
+ editor.pushPending();
+ editor.activate();
+
+ editor.setContent( content, 'wikitext' )
+ .then( function () {
+ editor.popPending();
+ } );
+
+ editor
+ .on( 'saveContent', function ( content, contentFormat ) {
+ var captchaResponse;
+
+ editor.pushPending();
+
+ captchaResponse = captchaWidget.getResponse();
+
+ error.setLabel( '' );
+ error.toggle( false );
+
+ // HACK: This is a cheat so that we can have a single function
+ // that creates the editor and a single error-handler, but multiple
+ // uses, especially for the APIhandler in different cases
+ editor.emit( 'afterSaveContent', content, contentFormat, captchaResponse, handleFailure );
+ } )
+ .on( 'cancel', function () {
+ editor.pushPending();
+ editor.emit( 'afterCancel' );
+ // returnToBoard();
+ } );
+
+ return editor;
+ };
+
+ /**
+ * Check whether we are on an undo form page
+ *
+ * @return {boolean} The page is an in-progress undo form
+ */
+ mw.flow.Initializer.prototype.isUndoForm = function () {
+ return !!( $( 'form[data-module="topic"]' ).length ||
+ $( 'form[data-module="header"]' ).length );
+ };
+
+ /**
+ * Set up editors in undo pages
+ */
+ mw.flow.Initializer.prototype.setupUndoPage = function () {
+ if ( $( 'form[data-module="topic"]' ).length ) {
+ this.replaceEditorInUndoEditPost( $( 'form[data-module="topic"]' ) );
+ } else if ( $( 'form[data-module="header"]' ).length ) {
+ this.replaceEditorInUndoHeaderPost( $( 'form[data-module="header"]' ) );
+ }
+ };
+
+ /**
+ * Replace the editor in undo edit post pages
+ *
+ * @param {jQuery} $form The form where the no-js editor exists to be replaced
+ */
+ mw.flow.Initializer.prototype.replaceEditorInUndoEditPost = function ( $form ) {
+ var apiHandler, content, postId, editor, prevRevId,
+ pageName = mw.config.get( 'wgPageName' ),
+ title = mw.Title.newFromText( pageName ),
+ topicId = title.getNameText(),
+ returnToTitle = function () {
+ // HACK: redirect to topic view
+ window.location.href = title.getUrl();
+ };
+
+ if ( !$form.length ) {
+ return;
+ }
+
+ postId = $form.find( 'input[name="topic_postId"]' ).val();
+ prevRevId = $form.find( 'input[name="topic_prev_revision"]' ).val();
+ content = $form.find( 'textarea' ).val();
+
+ apiHandler = new mw.flow.dm.APIHandler(
+ 'Topic:' + topicId,
+ {
+ currentRevision: prevRevId
+ }
+ );
+
+ // Create the editor
+ editor = this.createEditorWidget(
+ $form,
+ content,
+ mw.user.isAnon() ? 'flow-post-action-edit-post-submit-anonymously' : 'flow-post-action-edit-post-submit'
+ );
+
+ // Events
+ editor
+ .on( 'afterSaveContent', function ( content, contentFormat, captcha, handleFailure ) {
+ apiHandler.savePost( topicId, postId, content, contentFormat, captcha )
+ .then(
+ // Success
+ returnToTitle,
+
+ // Failure
+ handleFailure
+ );
+ } )
+ .on( 'afterCancel', returnToTitle );
+ };
+
+ /**
+ * Replace the editor in undo edit header pages
+ *
+ * @param {jQuery} $form The form where the no-js editor exists to be replaced
+ */
+ mw.flow.Initializer.prototype.replaceEditorInUndoHeaderPost = function ( $form ) {
+ var prevRevId, editor, content,
+ apiHandler,
+ pageName = mw.config.get( 'wgPageName' ),
+ title = mw.Title.newFromText( pageName ),
+ returnToBoard = function () {
+ window.location.href = title.getUrl();
+ };
+
+ if ( !$form.length ) {
+ return;
+ }
+
+ prevRevId = $form.find( 'input[name="header_prev_revision"]' ).val();
+ content = $form.find( 'textarea[name="header_content"]' ).val();
+
+ apiHandler = new mw.flow.dm.APIHandler(
+ title.getPrefixedDb(),
+ {
+ currentRevision: prevRevId
+ }
+ );
+
+ // Create the editor
+ editor = this.createEditorWidget(
+ $form,
+ content,
+ mw.user.isAnon() ? 'flow-edit-header-submit-anonymously' : 'flow-edit-header-submit'
+ );
+
+ // Events
+ editor
+ .on( 'afterSaveContent', function ( content, contentFormat, captcha, handleFailure ) {
+ apiHandler.saveDescription( content, contentFormat, captcha )
+ .then(
+ // Success
+ returnToBoard,
+
+ // Failure
+ handleFailure
+ );
+ } )
+ .on( 'afterCancel', function () {
+ returnToBoard();
+ } );
+ };
+
+ /**
+ * Finish the loading process
+ */
+ mw.flow.Initializer.prototype.finishLoading = function () {
+ if ( this.$component ) {
+ this.$component.addClass( 'flow-component-ready' );
+ }
+ $( '.flow-ui-load-overlay' ).addClass( 'oo-ui-element-hidden' );
+ };
+}( jQuery ) );
diff --git a/Flow/modules/notification/icon/flow-new-topic.svg b/Flow/modules/notification/icon/flow-new-topic.svg
new file mode 100644
index 00000000..fa2e5f9c
--- /dev/null
+++ b/Flow/modules/notification/icon/flow-new-topic.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="#00AF89" d="M18 14V9h-2v5h-5v2h5v5h2v-5h5v-2h-5zm7.5 12H0l4.5-4.5V5H30v16.5c0 2.55-1.95 4.5-4.5 4.5z" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/notification/icon/flow-post-edited.svg b/Flow/modules/notification/icon/flow-post-edited.svg
new file mode 100644
index 00000000..a4f563c7
--- /dev/null
+++ b/Flow/modules/notification/icon/flow-post-edited.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 d="M27.143 10.143V23L30 25.857H10V10.143h17.143zM2.857 3H20v5.714H8.57v10H0l2.857-2.857V3zm21.518 12.206c-.038-.66-.343-1.295-.8-1.803-.457-.52-1.104-.914-1.79-1.028a4900.443 4900.443 0 0 1-8.887 7.973l-.71 3.212 3.288-.356c1.777-1.6 6.88-6.183 8.9-7.998zm-9.852 6.08c-.253-.253-.47-.405-.76-.608l7.984-7.224c.267.09.648.305.762.61l-7.987 7.223z" fill="#36c" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/notification/icon/flow-topic-renamed.svg b/Flow/modules/notification/icon/flow-topic-renamed.svg
new file mode 100644
index 00000000..6d92462d
--- /dev/null
+++ b/Flow/modules/notification/icon/flow-topic-renamed.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 d="M25 22l4 4H2.99A1.99 1.99 0 0 1 1 24.01V4h24v18zm-3.875-11.216c-.05-.854-.443-1.674-1.034-2.33-.59-.673-1.426-1.18-2.312-1.33-2.608 2.347-9.204 8.27-11.484 10.304l-.92 4.15 4.25-.458c2.297-2.068 8.892-7.99 11.5-10.336zm-12.73 7.858c-.33-.328-.608-.525-.986-.787L17.73 8.52c.343.114.836.393.983.787l-10.32 9.335z" fill="#36c" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/notification/icon/flow-topic-reopened.svg b/Flow/modules/notification/icon/flow-topic-reopened.svg
new file mode 100644
index 00000000..f668548f
--- /dev/null
+++ b/Flow/modules/notification/icon/flow-topic-reopened.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 d="M25.5 26H0l4.5-4.5V5H30v16.5c0 2.55-1.95 4.5-4.5 4.5zm-12-11c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4 0-.5.2-1 .6-1.4.4-.4.9-.6 1.4-.6.5 0 1 .2 1.4.6.4.4.6.9.6 1.4zm6 0c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4 0-.5.2-1 .6-1.4.4-.4.9-.6 1.4-.6.5 0 1 .2 1.4.6.4.4.6.9.6 1.4zm6 0c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4 0-.5.2-1 .6-1.4.4-.4.9-.6 1.4-.6.5 0 1 .2 1.4.6.4.4.6.9.6 1.4z" fill="#36c" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/notification/icon/flow-topic-resolved.svg b/Flow/modules/notification/icon/flow-topic-resolved.svg
new file mode 100644
index 00000000..ec484318
--- /dev/null
+++ b/Flow/modules/notification/icon/flow-topic-resolved.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 d="M25.5 26H0l4.5-4.5V5H30v16.5c0 2.55-1.95 4.5-4.5 4.5zm-1.115-15.477l-8.718 8.718-4.36-4.358L10 16.19l5.667 5.666L27 10.523c-.697-.697-1.918-.697-2.615 0z" fill="#36c" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/notification/icon/flowusertalk-new-topic.svg b/Flow/modules/notification/icon/flowusertalk-new-topic.svg
new file mode 100644
index 00000000..2e1d2463
--- /dev/null
+++ b/Flow/modules/notification/icon/flowusertalk-new-topic.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 d="M25.5 26H0l4.5-4.5V5H30v16.5c0 2.55-1.95 4.5-4.5 4.5zm-6.05-7.2c-.63-.21-.63-.77-.7-1.4v-.07c.98-.84 1.75-2.24 1.75-3.78C20.5 10.26 19.1 9 17 9c-1.47 0-3.5.84-3.5 4.55 0 1.47.77 2.87 1.75 3.78v.07c0 .63-.07 1.19-.7 1.4 0 0-2.03.77-2.8 1.05-.91.28-1.75.7-1.75 1.75v.7h14v-.7c0-.84-.56-1.4-1.75-1.75-.84-.28-2.8-1.05-2.8-1.05z" fill="#00AF89" fill-rule="evenodd"/>
+</svg>
diff --git a/Flow/modules/styles/board/editor-switcher.less b/Flow/modules/styles/board/editor-switcher.less
index 44579813..a565b714 100644
--- a/Flow/modules/styles/board/editor-switcher.less
+++ b/Flow/modules/styles/board/editor-switcher.less
@@ -1,9 +1,9 @@
@import 'mediawiki.mixins';
@import 'mediawiki.ui/variables';
-@import 'flow.colors';
+@import '../flow.colors';
.flow-editor {
- background-color: white;
+ background-color: #fff;
// because we're attaching switcher controls below the textarea & we
// want them to look unified with the textarea, we'll have to take away
@@ -16,7 +16,7 @@
// div that contains textarea + legal text + switch button
&.flow-ui-focused {
border-color: @colorProgressive;
- box-shadow: inset 0 0 0 2px @colorProgressive;
+ box-shadow: inset 0 0 0 1px @colorProgressive;
}
.oo-ui-textInputWidget textarea {
border: 0;
@@ -27,20 +27,11 @@
box-shadow: none;
}
- // Comma-separating this rule doesn't work :(
- // Placeholder text styling must be set individually for each browser @winter
- &::-webkit-input-placeholder { // webkit
- font-style: italic;
- }
- &::-moz-placeholder { // FF 4-18
- font-style: italic;
- }
- &:-moz-placeholder { // FF >= 19
- font-style: italic;
- }
- &:-ms-input-placeholder { // IE >= 10
- font-style: italic;
- }
+ /* stylelint-disable indentation */
+ .mixin-placeholder( {
+ font-weight: normal;
+ } );
+ /* stylelint-enable indentation */
}
.flow-switcher-controls {
padding: 4px 6px 6px 6px;
@@ -53,7 +44,7 @@
}
}
- // would prefer textarea:not(.flow-input-compressed) above, but ie8 wont do it
+ // would prefer textarea:not( .flow-input-compressed ) above, but ie8 wont do it
// so here we re-apply the border from .mw-ui-input that was removed above.
textarea.flow-input-compressed {
border-bottom: 1px solid @colorFieldBorder;
@@ -63,7 +54,7 @@
// name for all but the float
.flow-wikitext-editor-help {
color: @colorTextLight;
- font-size: .75em;
+ font-size: 0.75em;
position: absolute;
bottom: 0;
}
diff --git a/Flow/modules/styles/board/form-actions.less b/Flow/modules/styles/board/form-actions.less
index 4dda53da..97aa7e06 100644
--- a/Flow/modules/styles/board/form-actions.less
+++ b/Flow/modules/styles/board/form-actions.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
.flow-form-collapsible.flow-form-collapsible-collapsed {
display: none;
@@ -12,9 +11,10 @@
position: relative;
margin-top: 8px;
- button.mw-ui-button, a.mw-ui-button {
+ button.mw-ui-button,
+ a.mw-ui-button {
float: right;
- margin-left: .25em;
+ margin-left: 0.25em;
}
}
@@ -34,7 +34,7 @@ textarea.mw-ui-input.flow-input-compressed {
width: 15em;
}
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
.flow-anon-warning-mobile {
display: none;
}
diff --git a/Flow/modules/styles/board/header.less b/Flow/modules/styles/board/header.less
index 586df78e..11eda496 100644
--- a/Flow/modules/styles/board/header.less
+++ b/Flow/modules/styles/board/header.less
@@ -1,11 +1,9 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
.flow-board-header {
word-break: break-word;
- width: 100%;
max-width: 700px;
padding-top: 10px;
padding-right: 15px;
@@ -24,7 +22,7 @@
// Top board header edit icon
.flow-board-header-icon {
- opacity: .33;
+ opacity: 0.33;
&:hover,
&:focus {
@@ -33,12 +31,12 @@
}
// need to be specific to override this h2
-div#content h2.flow-board-header-title {
+div#content h2.flow-board-header-title { /* stylelint-disable-line selector-no-id */
margin-right: 10px;
margin-top: 0;
margin-bottom: 10px;
- border-bottom: none;
+ border-bottom: 0;
font-family: sans-serif;
font-weight: bold;
font-size: 1.15em;
@@ -48,6 +46,22 @@ div#content h2.flow-board-header-title {
display: none;
}
+.flow-board-header-restricted {
+ font-weight: bold;
+ font-size: 1.15em;
+ opacity: 0.5;
+}
+
+// We must include a more specific rule for margin and padding
+// on the catlinks ul item, because there is a mw rule to 'correct'
+// ul that live inside .mw-content-ltr/rtl and defines a specific
+// margin value. We have to make this rule more specific so to
+// override that fix in this case.
+.mw-normal-catlinks ul.flow-board-header-category-list {
+ margin: 0;
+ padding: 0;
+}
+
.side-rail-toggle-button {
visibility: hidden;
position: absolute;
diff --git a/Flow/modules/styles/board/menu.less b/Flow/modules/styles/board/menu.less
index c7175937..72ebeee0 100644
--- a/Flow/modules/styles/board/menu.less
+++ b/Flow/modules/styles/board/menu.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.variables';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.variables';
+@import '../flow.colors';
// @todo document flow-menu
.flow-menu {
@@ -13,17 +12,18 @@
ul {
font-size: 0.75em;
}
+
li {
display: inline;
- text-align: left;
a {
font-weight: inherit;
+ text-align: left;
}
}
a:focus {
- outline: none;
+ outline: 0;
}
// Hide the menu trigger completely in no-js mode
@@ -59,7 +59,7 @@ div.flow-menu-inverted {
div > .flow-menu {
bottom: auto;
display: block;
- border: none;
+ border: 0;
&.flow-menu-inverted {
right: auto;
@@ -70,7 +70,6 @@ div > .flow-menu {
}
}
-
// the toc needs to retain display:block for purposes
// of triggering autoload eagerly behind the scenes.
// flow-menu-scrollable and flow-menu-hoverable cannot
@@ -82,8 +81,6 @@ div > .flow-menu {
}
}
-
-
&.flow-menu-hoverable:hover,
&.focus {
z-index: 2;
@@ -97,10 +94,9 @@ div > .flow-menu {
}
.flow-menu-js-drop a {
- outline: none;
border-color: transparent;
background: transparent;
- background: rgba(0,0,0,0.05);
+ background: rgba( 0, 0, 0, 0.05 );
.caret {
border-top-color: #000;
@@ -113,18 +109,24 @@ div > .flow-menu {
// itself is hidden
display: none;
font-size: 1em;
- box-shadow: 0 1px 2px @colorGrayLight;
background: #fff;
- border-radius: 2px;
+ border: 1px solid @colorGray10;
+ border-radius: @borderRadius;
+ box-shadow: 0 2px 2px 0 rgba( 0, 0, 0, 0.25 );
- > section:not(:first-of-type) > li:first-of-type,
- li.flow-menu-section:not(:first-of-type) {
- border-top: 1px solid @colorGrayLighter;
+ > section:not( :first-of-type ) > li:first-of-type,
+ li.flow-menu-section:not( :first-of-type ) {
+ border-top: 1px solid @colorGray12;
}
+ }
- li {
+ li {
+ display: block;
+ margin: 0;
+
+ a {
display: block;
- cursor: default;
+ text-align: left;
}
}
@@ -136,12 +138,15 @@ div > .flow-menu {
a {
display: inline-block;
- padding: 0 .5em;
- border: 1px solid @colorGrayLight;
- border-radius: 3px;
+ padding: 0 0.5em;
+ border-radius: @borderRadius;
border-width: 0;
color: @colorTextLight;
}
+
+ .mw-ui-icon.mw-ui-icon-before:before {
+ margin-right: 0;
+ }
}
// Correct positioning for ltr/rtl content direction
@@ -167,13 +172,12 @@ div > .flow-menu {
div.flow-post > .flow-menu {
.flow-menu-js-drop {
a {
- border-color: @colorGrayLightest;
border-width: 0;
}
}
}
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
// On desktop, the flow-menu is no longer inline
.flow-menu {
position: absolute;
diff --git a/Flow/modules/styles/board/moderated.less b/Flow/modules/styles/board/moderated.less
index 0e0f66eb..808fc7b0 100644
--- a/Flow/modules/styles/board/moderated.less
+++ b/Flow/modules/styles/board/moderated.less
@@ -1,6 +1,5 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.colors';
// Visually mark locked topics
.flow-topic-moderatestate-lock {
@@ -16,12 +15,12 @@
}
// hide posts of collapsed topics
-.board-page {
- .flow-board {
- .flow-element-collapsed {
- .flow-post {
- display: none;
- }
- }
+.client-js .flow-board-page .flow-board {
+ .flow-element-collapsed .flow-post {
+ display: none;
+ }
+
+ .flow-collapse-toggle {
+ cursor: pointer;
}
}
diff --git a/Flow/modules/styles/board/navigation.less b/Flow/modules/styles/board/navigation.less
index 2cfcda04..f8c189e1 100644
--- a/Flow/modules/styles/board/navigation.less
+++ b/Flow/modules/styles/board/navigation.less
@@ -1,38 +1,20 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
// Top board navigation bar
.flow-board-navigation {
- height: 2em;
+ height: 2.55em;
+ margin-bottom: 0.5em;
position: static;
padding: 0;
white-space: nowrap;
min-width: 14em;
clear: both;
- a:link, a:visited {
- padding: 0.2em 0.3em;
- }
-
- // We need these because CSSJanus will flip it in rtl
- a.flow-board-navigator-first {
- float: left;
- position: static;
- }
-
- a.flow-board-navigator-last {
- float: right;
- position: static;
- span {
- display: inline-block;
- }
- }
-
.flow-board-navigation-inner {
overflow: hidden;
- border-bottom: 1px solid @colorGrayLight;
+ border-bottom: 1px solid @colorGray12;
white-space: nowrap;
}
@@ -44,11 +26,14 @@
a {
display: inline-block;
- &:link, &:visited {
- padding: 0.25em .75em;
+ &:link,
+ &:visited {
+ padding: 0.25em 0.75em;
color: @colorTextLight;
}
- &:hover, &:focus, &.flow-board-navigator-link-highlight {
+ &:hover,
+ &:focus,
+ &.flow-board-navigator-link-highlight {
color: #000;
text-decoration: none;
}
@@ -56,15 +41,26 @@
&.flow-board-navigator-right {
float: right;
}
+
// The active menu item
&.flow-board-navigator-active {
font-weight: bold;
}
+
+ // We need these because CSSJanus will flip it in rtl
&.flow-board-navigator-first {
+ float: left;
+ position: static;
padding-left: 0;
}
+
&.flow-board-navigator-last {
+ float: right;
+ position: static;
padding-right: 0;
+ span {
+ display: inline-block;
+ }
}
}
@@ -74,7 +70,7 @@
z-index: 2;
top: 0;
width: 100%;
- background: @colorWhite;
+ background: #fff;
.flow-board-toc-menu {
.flow-list {
@@ -107,7 +103,7 @@
float: right;
width: 100%;
- font-size: .875em;
+ font-size: 0.875em;
// Make TOC wide
.flow-board-toc-menu {
@@ -138,9 +134,9 @@
}
// MEDIA QUERIES
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
html .flow-board-navigation {
font-size: 1.15em;
- padding-top: .5em;
+ margin-top: 0.5em;
}
}
diff --git a/Flow/modules/styles/board/replycount.less b/Flow/modules/styles/board/replycount.less
index 346021bd..877152b8 100644
--- a/Flow/modules/styles/board/replycount.less
+++ b/Flow/modules/styles/board/replycount.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
// Reply count (only visible in compact mode)
.flow-reply-count {
@@ -9,10 +8,10 @@
position: absolute;
top: 50%;
right: 1.5em;
- margin-top: -.55em;
- color: @colorGrayLighter;
+ margin-top: -0.55em;
+ color: @colorGray12;
font-size: 2em;
- opacity: .5;
+ opacity: 0.5;
.flow-reply-count-number {
.box-sizing( border-box );
@@ -20,10 +19,10 @@
position: absolute;
left: 0;
top: 0;
- padding-left: .25em;
+ padding-left: 0.25em;
width: 100%;
color: @colorTextLight;
- font-size: .5em;
+ font-size: 0.5em;
line-height: 2.25;
font-weight: bold;
text-align: center;
diff --git a/Flow/modules/styles/board/terms-of-use.less b/Flow/modules/styles/board/terms-of-use.less
index a092e6d0..a9daf529 100644
--- a/Flow/modules/styles/board/terms-of-use.less
+++ b/Flow/modules/styles/board/terms-of-use.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
// @todo: Give more generic name
// TOU should be tiny and grey
@@ -11,14 +10,14 @@
height: 3.6em;
vertical-align: middle;
color: @colorTextLight;
- font-size: .75em;
+ font-size: 0.75em;
line-height: 1.4;
// These two will flip in RTL interface
text-align: left;
direction: ltr;
}
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
.flow-terms-of-use {
clear: none;
}
diff --git a/Flow/modules/styles/board/timestamps.less b/Flow/modules/styles/board/timestamps.less
index 4289d103..7914fb7f 100644
--- a/Flow/modules/styles/board/timestamps.less
+++ b/Flow/modules/styles/board/timestamps.less
@@ -1,6 +1,5 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.colors';
.flow-timestamp {
.box-sizing( border-box );
@@ -40,13 +39,14 @@
}
a.flow-timestamp-anchor {
- &, &:visited {
+ &,
+ &:visited {
color: inherit;
}
}
// Colors are from mediawiki.skinning/elements.css
-// Could use a.flow-timestamp-anchor:not(:hover) to set color to gray
+// Could use a.flow-timestamp-anchor:not( :hover ) to set color to gray
// only when *not* hovering (and avoid the copied colors), but we can't
// use :not for now due to old IE.
a.flow-timestamp-anchor:hover {
diff --git a/Flow/modules/styles/board/topic/meta.less b/Flow/modules/styles/board/topic/meta.less
index 2edf09f1..7cd6d425 100644
--- a/Flow/modules/styles/board/topic/meta.less
+++ b/Flow/modules/styles/board/topic/meta.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../../flow.colors';
+@import '../../flow.variables';
// Topic metadata
.flow-topic-meta {
@@ -30,7 +29,7 @@
// and requires that you redefine :hover.
// I did know want to hard code the hover color
// from the theme we're using.
- a.expand-collapse-posts-link:not(:hover) {
+ a.expand-collapse-posts-link:not( :hover ) {
color: @colorTextLight;
}
}
diff --git a/Flow/modules/styles/board/topic/post.less b/Flow/modules/styles/board/topic/post.less
index fa5a91e7..2dcc3cbc 100644
--- a/Flow/modules/styles/board/topic/post.less
+++ b/Flow/modules/styles/board/topic/post.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../../flow.colors';
+@import '../../flow.variables';
@highlightedIndent: 0.2em;
@@ -13,7 +12,7 @@
// Comments
form.flow-post {
- margin-left: @topicIndent - (@textareaPadding * 2);
+ margin-left: @topicIndent - ( @textareaPadding * 2 );
}
.flow-post {
@@ -53,7 +52,7 @@ form.flow-post {
// Author link in post
.flow-author {
- font-size: .875em;
+ font-size: 0.875em;
line-height: 1.2;
display: inline-block;
color: @colorText;
@@ -65,7 +64,7 @@ form.flow-post {
.mw-usertoollinks {
opacity: 0;
- .transition( opacity .25s ease );
+ .transition( opacity 0.25s ease );
}
&:hover .mw-usertoollinks {
opacity: 1;
@@ -74,16 +73,16 @@ form.flow-post {
.mw-content-ltr & {
/* @noflip */
- margin: .5em 0 0 .75em;
+ margin: 0.5em 0 0 0.75em;
// Nested comments (replies & reply forms)
.flow-replies {
/* @noflip */
- margin-left: @topicIndent;
+ margin-left: @replyIndent;
/* @noflip */
padding-left: 0.5em;
/* @noflip */
- border-left: 1px solid @colorGrayLighter;
+ border-left: 1px solid @colorGray12;
}
&.flow-post-max-depth .flow-replies {
@@ -107,7 +106,7 @@ form.flow-post {
// Highlights a post (no IE6 support, but acceptable degradation)
&.flow-post-highlighted {
- > .flow-post-main {
+ > .flow-post-main {
/* @noflip */
@highlightedIndent: @topicIndent - 0.75em;
/* @noflip */
@@ -128,7 +127,7 @@ form.flow-post {
.mw-content-rtl & {
/* @noflip */
- margin: .5em 0.75em 0 0;
+ margin: 0.5em 0.75em 0 0;
// Nested comments (replies & reply forms)
.flow-replies {
@@ -137,7 +136,7 @@ form.flow-post {
/* @noflip */
padding-right: 0.5em;
/* @noflip */
- border-right: 1px solid @colorGrayLighter;
+ border-right: 1px solid @colorGray12;
}
&.flow-post-max-depth .flow-replies {
@@ -161,7 +160,7 @@ form.flow-post {
// Highlights a post (no IE6 support, but acceptable degradation)
&.flow-post-highlighted {
- > .flow-post-main {
+ > .flow-post-main {
/* @noflip */
@highlightedIndent: @topicIndent - 0.75em;
/* @noflip */
@@ -185,8 +184,8 @@ form.flow-post {
// Comment metadata
.flow-post-meta {
// @todo needs overflow: hidden but crops button border at bottom
- color: @colorGrayDark;
- font-size: .875em;
+ color: @colorGray7;
+ font-size: 0.875em;
.mw-content-ltr & {
/* @noflip */
@@ -211,34 +210,42 @@ form.flow-post {
}
a {
- &::after {
- content: "\2022";
+ &:after {
+ content: '\2022';
padding: 0 8px;
text-decoration: none;
display: inline-block;
- color: @colorGrayDark;
+ color: @colorGray7;
}
&:last-child {
- &::after {
- content: "";
+ &:after {
+ content: '';
}
}
}
}
// MEDIA QUERIES
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
.flow-post {
/* left margin provided by highlighting zone */
.mw-content-ltr & {
/* @noflip */
margin: 1em 0 0 @topicIndent;
}
+ .mw-content-ltr .flow-replies & {
+ /* @noflip */
+ margin-left: @replyIndent;
+ }
.mw-content-rtl & {
/* @noflip */
margin: 1em @topicIndent 0 0;
}
+ .mw-content-rtl .flow-replies & {
+ /* @noflip */
+ margin-right: @replyIndent;
+ }
padding: 0;
@@ -261,14 +268,14 @@ form.flow-post {
// What to do? vector changes this width on us from screen-hd.less with:
//
-// @media screen and (min-width: 982px)
+// @media screen and ( min-width: 982px )
// div#content {
// margin-left: 11em;
// padding: 1.25em 1.5em 1.5em 1.5em;
// }
//
// The standard padding for narrower screens is 1em all around.
-@media all and (min-width: 982px) {
+@media all and ( min-width: 982px ) {
.flow-post.flow-post-highlight-newer > .flow-post-main .flow-post-content {
.minimalPostHighlight( 1.8em );
}
diff --git a/Flow/modules/styles/board/topic/summary.less b/Flow/modules/styles/board/topic/summary.less
index cae1789b..ecf209a9 100644
--- a/Flow/modules/styles/board/topic/summary.less
+++ b/Flow/modules/styles/board/topic/summary.less
@@ -1,17 +1,17 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../../flow.colors';
+@import '../../flow.variables';
.flow-topic-summary-container {
- .flow-topic-summary {
- border-top: 1px solid @colorGray13;
- margin-top: .5em;
- padding-top: .5em;
+ .flow-topic-summary,
+ .flow-ui-editTopicSummaryWidget {
+ border-top: 1px solid @colorGray12;
+ margin-top: 0.5em;
+ padding-top: 0.5em;
.flow-topic-summary-author {
font-weight: bold;
- color: @colorTextLight
+ color: @colorTextLight;
}
.flow-topic-summary-content {
diff --git a/Flow/modules/styles/board/topic/titlebar.less b/Flow/modules/styles/board/topic/titlebar.less
index 5c8a6649..fb7ffc36 100644
--- a/Flow/modules/styles/board/topic/titlebar.less
+++ b/Flow/modules/styles/board/topic/titlebar.less
@@ -1,26 +1,47 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../../flow.colors';
+@import '../../flow.variables';
// Show that the topic titlebar is clickable
.flow-topic-titlebar {
position: relative;
- padding: .5em 0;
- background: @colorGrayLightest;
- border-radius: 3px;
- outline: none;
+ padding: 0.5em 0;
+ background-color: @colorGray14;
+ border-radius: @borderRadius;
+ outline: 0;
- // use child selector to block ie6
+ // use child selector to block IE 6
.flow-menu {
- top: 1.5em;
+ top: 2em;
+ }
+
+ @media all and ( min-width: @small ) {
+ .flow-topic-titlebar-container,
+ .flow-edit-title-form,
+ .flow-topic-summary,
+ .flow-ui-editTopicSummaryWidget {
+
+ .mw-content-ltr & {
+ /* @noflip */
+ padding-right: @topicIndent + 1;
+ /* @noflip */
+ padding-left: @topicIndent;
+ }
+
+ .mw-content-rtl & {
+ /* @noflip */
+ padding-right: @topicIndent;
+ /* @noflip */
+ padding-left: @topicIndent + 1;
+ }
+ }
}
}
// needs extra specificity to override `div#content h2` from vector
-div#content .flow-topic-title {
+div#content .flow-topic-title { /* stylelint-disable-line selector-no-id */
padding: 0;
- border-bottom: none;
+ border-bottom: 0;
font-family: sans-serif;
font-weight: bold;
word-break: break-word;
@@ -29,9 +50,9 @@ div#content .flow-topic-title {
}
// Correct positioning for ltr/rtl content direction
-div#content .mw-content-ltr .flow-topic-title {
+div#content .mw-content-ltr .flow-topic-title { /* stylelint-disable-line selector-no-id */
/* @noflip */
- margin: 0 2.5em .15em 0;
+ margin: 0 2.5em 0.15em 0;
.mw-ui-icon.mw-ui-icon-before:before {
/* @noflip */
@@ -44,9 +65,9 @@ div#content .mw-content-ltr .flow-topic-title {
}
// Correct positioning for ltr/rtl content direction
-div#content .mw-content-rtl .flow-topic-title {
+div#content .mw-content-rtl .flow-topic-title { /* stylelint-disable-line selector-no-id */
/* @noflip */
- margin: 0 0 .15em 2.5em;
+ margin: 0 0 0.15em 2.5em;
.mw-ui-icon.mw-ui-icon-before:before {
/* @noflip */
@@ -59,13 +80,13 @@ div#content .mw-content-rtl .flow-topic-title {
}
.flow-moderated-topic-title {
- margin-bottom: .33em;
+ margin-bottom: 0.33em;
color: @colorTextLight;
font-weight: bold;
}
// Override default Vector heading styles
-div#content h2.flow-topic-title {
+div#content h2.flow-topic-title { /* stylelint-disable-line selector-no-id */
font-size: 1.5em;
}
@@ -73,17 +94,25 @@ div#content h2.flow-topic-title {
.flow-notification-tooltip-topicsub {
width: 15em;
}
-.flow-notification-tooltip-icon {
- font-size: 2.5em;
- text-align: center;
+.flow-notification-tooltip-icon {
.mw-ui-icon {
- display: inline-block;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+
+ &.mw-ui-icon-star { // Overwrite default `.mw-ui-icon` properties
+ min-width: 32px;
+ width: 32px;
+ max-width: 32px;
+ min-height: 32px;
+ font-size: 32px;
+ line-height: 1;
+ }
}
}
.flow-notification-tooltip-title {
font-size: 1em;
- font-weight: bold;
}
.flow-undo {
@@ -95,30 +124,3 @@ div#content h2.flow-topic-title {
display: none;
}
}
-
-// MEDIA QUERIES
-@media all and (min-width: @small) {
- .flow-topic-titlebar {
- padding-top: 0.5em;
- padding-bottom: 0.5em;
-
- .flow-topic-titlebar-container,
- .flow-edit-title-form,
- .flow-topic-summary {
-
- .mw-content-ltr & {
- /* @noflip */
- padding-right: @topicIndent + 1;
- /* @noflip */
- padding-left: @topicIndent;
- }
-
- .mw-content-rtl & {
- /* @noflip */
- padding-right: @topicIndent;
- /* @noflip */
- padding-left: @topicIndent + 1;
- }
- }
- }
-}
diff --git a/Flow/modules/styles/board/topic/watchlist.less b/Flow/modules/styles/board/topic/watchlist.less
index b59fd3a0..a1cc833f 100644
--- a/Flow/modules/styles/board/topic/watchlist.less
+++ b/Flow/modules/styles/board/topic/watchlist.less
@@ -1,7 +1,6 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../../flow.colors';
+@import '../../flow.variables';
.flow-watch-link {
position: absolute;
@@ -28,7 +27,7 @@
display: inline-block;
*display: inline;
zoom: 1;
- padding: .25em .5em;
+ padding: 0.25em 0.5em;
// mw-ui-quiet is set when the topic is not watched
// FIXME: this is a hack, use a better-named class for this
@@ -44,6 +43,11 @@
}
}
+ // Overwrite `.mw-ui-icon.mw-ui-icon-before` styles
+ .mw-ui-icon.mw-ui-icon-before:before {
+ margin-right: 0;
+ }
+
// When watched, hide the watch icon and show the unwatch icon
.flow-watch {
display: none;
@@ -52,11 +56,15 @@
// HACK: mimic old mw-ui style (changing from #00af89 to #00f4bf on hover)
.flow-unwatch:hover {
// 0xf4/0xaf = 0xbf/0x89 = 1.394
- -webkit-filter: brightness(1.4);
- filter: brightness(1.4);
+ -webkit-filter: brightness( 1.4 );
+ filter: brightness( 1.4 );
}
}
+ .flow-unwatch.mw-ui-icon-unStar-progressive {
+ opacity: 1;
+ }
+
// Correct positioning for ltr/rtl content direction
.mw-content-ltr & {
/* @noflip */
@@ -77,7 +85,7 @@
}
}
-@media all and (min-width: @small) {
+@media all and ( min-width: @small ) {
.flow-topic-watchlist {
a {
font-size: inherit;
diff --git a/Flow/modules/styles/common.less b/Flow/modules/styles/common.less
index 1fd5eae3..6e34c402 100644
--- a/Flow/modules/styles/common.less
+++ b/Flow/modules/styles/common.less
@@ -1,6 +1,5 @@
@import 'mediawiki.mixins';
@import 'flow.colors';
-@import 'flow.helpers';
@import 'flow.variables';
.flow-component {
@@ -10,7 +9,7 @@
padding: 0;
li:hover {
- background: #eee;
+ background: @colorGray14;
}
}
}
@@ -26,7 +25,7 @@
// The whole board content wrapper
.flow-board {
.box-sizing( border-box );
- font-size: .875em;
+ font-size: 0.875em;
width: 100%;
padding-left: 0;
padding-top: 0;
@@ -37,14 +36,14 @@
padding-bottom: 24px;
}
-.board-page {
+.flow-board-page {
.flow-board-navigation,
.flow-board {
max-width: 700px;
}
}
-.topic-page {
+.flow-topic-page {
.flow-board {
max-width: 850px;
}
@@ -58,8 +57,8 @@
// Revision view
.flow-revision-content {
- background: none repeat scroll 0 0 #EDEDED;
- color: #777777;
+ background-color: @colorGray14;
+ color: @colorGray7;
margin-top: 20px;
padding: 10px;
}
@@ -68,15 +67,15 @@
.flow-no-more,
// "Undo" moderation link
.flow-undo {
- font-size: .875em;
- color: #777777;
+ font-size: 0.875em;
+ color: @colorGray7;
// These two will flip in RTL interface
text-align: left;
direction: ltr;
}
.flow-topic-meta {
- font-size: .875em;
+ font-size: 0.875em;
}
// Decorate as a pipelist, ex: (foo | bar | baz)
@@ -91,7 +90,20 @@
line-height: 0;
}
-@media all and (min-width: @small) {
+// This is to make sure there is enough space
+// at the bottom to display the last post's menu.
+.flow-bottom-spacer {
+ height: 100px;
+}
+
+// Override oojs-ui's frameless-buttons having
+// a white border inside the description area
+// (which has a grey background)
+.flow-ui-boardDescriptionWidget-editButton.oo-ui-widget.oo-ui-buttonElement .oo-ui-buttonElement-button {
+ border-color: transparent;
+}
+
+@media all and ( min-width: @small ) {
.flow-topic-meta {
font-size: 1em;
}
@@ -108,16 +120,16 @@
}
}
-@media all and (min-width: @medium) {
- .flow-component.board-page {
+@media all and ( min-width: @medium ) {
+ .flow-component.flow-board-page {
.flow-board-header {
padding-left: 10px;
float: right;
width: 34%;
min-height: 70vh;
box-sizing: border-box;
- background-color: @colorGrayLightest;
- box-shadow: -2px 0 0 0 rgba(0,0,0,0.10);
+ background-color: @colorGray14;
+ box-shadow: -2px 0 0 0 rgba( 0, 0, 0, 0.1 );
.flow-board-header-title {
display: block;
@@ -125,9 +137,7 @@
.side-rail-toggle-button {
visibility: visible;
- }
- .side-rail-toggle-button {
.collapse-button {
display: block;
}
@@ -149,17 +159,30 @@
}
}
- .flow-component.board-page.full-height-side-rail {
- overflow: hidden;
+ .flow-component.flow-board-page.flow-full-height-side-rail {
+ position: relative;
.flow-board-header {
- // this is a hack to make sure the side rail always
- // stretches all the way to the bottom of the page
- padding-bottom: 9999999px;
- margin-bottom: -9999999px;
+ position: static;
+ /* background and box-shadow are moved to :before for full height */
+ background: transparent;
+ box-shadow: none;
+ }
+ .flow-board-header:before {
+ content: '';
+ display: block;
+ position: absolute;
+ height: 100%;
+ top: 0;
+ right: 0;
+ z-index: -1;
+ width: 34%;
+ box-sizing: border-box;
+ background-color: @colorGray14;
+ box-shadow: -2px 0 0 0 rgba( 0, 0, 0, 0.1 );
}
}
- .flow-component.board-page.expanded {
+ .flow-component.flow-board-page.expanded {
padding-right: 30px;
.flow-board-header {
@@ -181,12 +204,17 @@
.flow-board-header-title,
.flow-board-header-detail-view,
+ .flow-board-header-restricted,
.flow-ui-boardDescriptionWidget,
.flow-board-header-footer {
display: none;
}
}
+ .flow-board-header:before {
+ width: 30px;
+ }
+
.flow-board-navigation,
.flow-board {
width: 100%;
@@ -194,7 +222,7 @@
}
}
- .flow-component.topic-page {
+ .flow-component.flow-topic-page {
.flow-board {
float: left;
width: 66%;
@@ -212,7 +240,8 @@
.flow-board-header-footer {
margin-top: 2em;
font-size: 0.85em;
- @media (min-width: @medium) {
+
+ @media ( min-width: @medium ) {
margin-top: 6em;
}
}
@@ -230,9 +259,9 @@
> section {
display: inline;
- &:not(:first-of-type) > li {
+ &:not( :first-of-type ) > li {
&:first-of-type {
- border-top: 0px;
+ border-top: 0;
&:before {
content: '(';
@@ -254,6 +283,7 @@
// vector theme overrides
// makes the layout more compact on Talk (ns-1) and User_Talk (ns-3)
+/* stylelint-disable selector-no-id */
body.ns-1,
body.ns-3 {
div#content.mw-body {
@@ -270,9 +300,10 @@ body.ns-3 {
}
}
}
+/* stylelint-enable selector-no-id */
span.mw-ui-icon {
- opacity: 0.7;
+ opacity: 0.87; // equals `#222` on background-color `#fff`
}
span.mw-ui-icon.mw-ui-icon-before:before {
diff --git a/Flow/modules/styles/errors.less b/Flow/modules/styles/errors.less
index 7419e618..913b03ef 100644
--- a/Flow/modules/styles/errors.less
+++ b/Flow/modules/styles/errors.less
@@ -2,9 +2,10 @@
.flow-errors.errorbox {
display: block; // overwrites core .errorbox's display: inline-block
margin: 1em 0 0;
+ direction: ltr;
.mw-warning-with-logexcerpt {
- border: none;
+ border: 0;
margin: 0;
padding: 0;
}
diff --git a/Flow/modules/styles/flow.colors.less b/Flow/modules/styles/flow.colors.less
new file mode 100644
index 00000000..c0ee3702
--- /dev/null
+++ b/Flow/modules/styles/flow.colors.less
@@ -0,0 +1,4 @@
+@import 'mediawiki.ui/variables';
+
+@colorHighlight: #00af89;
+@colorHighlightNewer: #0645ad;
diff --git a/Flow/modules/styles/flow.variables.less b/Flow/modules/styles/flow.variables.less
new file mode 100644
index 00000000..2765e4ea
--- /dev/null
+++ b/Flow/modules/styles/flow.variables.less
@@ -0,0 +1,12 @@
+@topicIndent: 1em;
+@replyIndent: 1.5em;
+@textareaPadding: 0.3em;
+@editorToolbarHeight: 40px;
+@editorMinHeight: 10em;
+
+// @todo: Use same variable as MobileFrontend
+
+@small: 768px;
+@medium: 1165px;
+@large: 1200px;
+@xlarge: 2000px;
diff --git a/Flow/modules/styles/flow/images/anon-user.svg b/Flow/modules/styles/flow/images/anon-user.svg
index 2e1ac9cf..9431933c 100644
--- a/Flow/modules/styles/flow/images/anon-user.svg
+++ b/Flow/modules/styles/flow/images/anon-user.svg
@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
- <g>
- <path d="M21 18.763c-1.44-.484-4.8-1.816-4.8-1.816-1.08-.363-1.08-1.33-1.2-2.42v-.122c1.68-1.452 3-3.873 3-6.537C18 2.178 15.6 0 12 0 9.48 0 6 1.453 6 7.868c0 2.543 1.32 4.964 3 6.537v.12c0 1.09-.12 2.06-1.2 2.422 0 0-3.48 1.332-4.8 1.816-1.56.484-3 1.21-3 3.026V23h24v-1.21c0-1.453-.96-2.422-3-3.027zm-9.92-6.59h2.054v1.92H11.08v-1.92zm-2.44-5.55c0-.563.084-1.074.253-1.534.17-.462.414-.855.736-1.182.32-.328.71-.58 1.165-.76.455-.18.964-.268 1.526-.268.47 0 .908.07 1.312.207.404.138.757.337 1.06.598.3.26.538.586.712.974.174.388.26.827.26 1.318 0 .358-.038.667-.115.928-.077.26-.18.486-.307.675-.128.19-.274.36-.437.507-.164.148-.328.294-.49.437-.195.164-.374.322-.538.476-.164.153-.307.324-.43.513-.122.19-.217.412-.283.668-.067.256-.1.568-.1.936H11.31c0-.45.022-.83.068-1.143.046-.31.12-.585.222-.82.102-.235.228-.442.376-.62.148-.18.324-.357.53-.53.163-.143.32-.276.467-.4.148-.122.28-.257.4-.406.116-.148.208-.314.275-.498.066-.185.1-.405.1-.66 0-.307-.054-.57-.162-.79-.107-.22-.237-.397-.39-.53-.154-.132-.318-.23-.492-.29-.173-.062-.327-.093-.46-.093-.634 0-1.1.207-1.403.62-.3.415-.452.97-.452 1.665H8.64z" id="anon-user" fill="#FFF"/>
- </g>
+ <path d="M21 18.763c-1.44-.484-4.8-1.816-4.8-1.816-1.08-.363-1.08-1.33-1.2-2.42v-.122c1.68-1.452 3-3.873 3-6.537C18 2.178 15.6 0 12 0 9.48 0 6 1.453 6 7.868c0 2.543 1.32 4.964 3 6.537v.12c0 1.09-.12 2.06-1.2 2.422 0 0-3.48 1.332-4.8 1.816-1.56.484-3 1.21-3 3.026V23h24v-1.21c0-1.453-.96-2.422-3-3.027zm-9.92-6.59h2.054v1.92H11.08v-1.92zm-2.44-5.55c0-.563.084-1.074.253-1.534.17-.462.414-.855.736-1.182.32-.328.71-.58 1.165-.76.455-.18.964-.268 1.526-.268.47 0 .908.07 1.312.207.404.138.757.337 1.06.598.3.26.538.586.712.974.174.388.26.827.26 1.318a3.3 3.3 0 0 1-.115.928 2.456 2.456 0 0 1-.744 1.182 59.86 59.86 0 0 1-.49.437c-.195.164-.374.322-.538.476a2.748 2.748 0 0 0-.43.513 2.28 2.28 0 0 0-.283.668 3.75 3.75 0 0 0-.1.936H11.31c0-.45.022-.83.068-1.143.046-.31.12-.585.222-.82.102-.235.228-.442.376-.62.148-.18.324-.357.53-.53.163-.143.32-.276.467-.4.148-.122.28-.257.4-.406a1.8 1.8 0 0 0 .275-.498c.066-.185.1-.405.1-.66 0-.307-.054-.57-.162-.79a1.519 1.519 0 0 0-.882-.82 1.39 1.39 0 0 0-.46-.093c-.634 0-1.1.207-1.403.62-.3.415-.452.97-.452 1.665H8.64z" fill="#fff"/>
</svg>
diff --git a/Flow/modules/styles/flow/images/lock-ltr.svg b/Flow/modules/styles/flow/images/lock-ltr.svg
new file mode 100644
index 00000000..a18b2c46
--- /dev/null
+++ b/Flow/modules/styles/flow/images/lock-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="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</svg>
diff --git a/Flow/modules/styles/flow/images/lock-rtl.svg b/Flow/modules/styles/flow/images/lock-rtl.svg
new file mode 100644
index 00000000..6c4a3c51
--- /dev/null
+++ b/Flow/modules/styles/flow/images/lock-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="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</svg>
diff --git a/Flow/modules/styles/flow/images/newest-topics.svg b/Flow/modules/styles/flow/images/newest-topics.svg
new file mode 100644
index 00000000..b9e3a612
--- /dev/null
+++ b/Flow/modules/styles/flow/images/newest-topics.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="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 12l-3-2-1 4-1-4-3 2 2-3-4-1 4-1-2-3 3 2 1-4 1 4 3-2-2 3 4 1-4 1 2 3z"/>
+</svg>
diff --git a/Flow/modules/styles/flow/images/topic-collapse-ltr.svg b/Flow/modules/styles/flow/images/topic-collapse-ltr.svg
index 397af177..f07cb076 100644
--- a/Flow/modules/styles/flow/images/topic-collapse-ltr.svg
+++ b/Flow/modules/styles/flow/images/topic-collapse-ltr.svg
@@ -1,13 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="20px" height="14px" viewBox="0 0 20 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
- <!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
- <title>topic-expand</title>
- <desc>Created with Sketch.</desc>
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
- <g id="topic-expand" sketch:type="MSLayerGroup" fill="#AAAAAA">
- <path d="M6.77248677,13.4920045 C6.77248677,12.8952577 6.28819411,12.4126984 5.69394914,12.4126984 L19.6393842,12.4126984 C19.0444667,12.4126984 18.5608466,12.8966853 18.5608466,13.4920045 L18.5608466,0.359847325 C18.5608466,0.956594147 19.0451392,1.43915344 19.6393842,1.43915344 L5.69394914,1.43915344 C6.28886663,1.43915344 6.77248677,0.955166578 6.77248677,0.359847325 L6.77248677,13.4920045 Z M0.360615802,0 L19.6393842,0 C19.8385468,0 20,0.160353096 20,0.359847325 L20,13.4920045 C20,13.6907427 19.8400541,13.8518519 19.6393842,13.8518519 L0.360615802,13.8518519 C0.161453194,13.8518519 0,13.6914988 0,13.4920045 L0,0.359847325 C0,0.161109135 0.159945931,0 0.360615802,0 Z" id="Shape" sketch:type="MSShapeGroup"></path>
- <path d="M13.6719577,4.01798942 L13.6719577,6.35767196 L8.26455026,6.33968254 L8.26455026,8.06455026 L13.6719577,8.06455026 L13.6719577,10.4042328 L17.2698413,7.34603175 L13.6719577,4.01798942 Z M11.3375661,7.16613757 L11.3375661,7.23809524 L11.2656085,7.23809524 L11.2656085,7.16613757 L11.3375661,7.16613757 L11.3375661,7.16613757 Z" id="Shape" sketch:type="MSShapeGroup"></path>
- </g>
+<svg width="20" height="14" viewBox="0 0 20 14" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#72777d" fill-rule="evenodd">
+ <path d="M6.772 13.492a1.08 1.08 0 0 0-1.078-1.08H19.64c-.596 0-1.08.485-1.08 1.08V.36c0 .597.485 1.08 1.08 1.08H5.693A1.08 1.08 0 0 0 6.77.36v13.132zM.362 0H19.64c.2 0 .36.16.36.36v13.132c0 .2-.16.36-.36.36H.36c-.2 0-.36-.16-.36-.36V.36C0 .16.16 0 .36 0z"/>
+ <path d="M13.672 4.018v2.34L8.265 6.34v1.725h5.407v2.34l3.598-3.06-3.598-3.327zm-2.334 3.148v.072h-.072v-.072h.072z"/>
</g>
-</svg> \ No newline at end of file
+</svg>
diff --git a/Flow/modules/styles/flow/images/topic-collapse-rtl.svg b/Flow/modules/styles/flow/images/topic-collapse-rtl.svg
index 2d7aae6c..756b8e6c 100644
--- a/Flow/modules/styles/flow/images/topic-collapse-rtl.svg
+++ b/Flow/modules/styles/flow/images/topic-collapse-rtl.svg
@@ -1,13 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="20px" height="14px" viewBox="0 0 20 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
- <!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
- <title>topic-collapse</title>
- <desc>Created with Sketch.</desc>
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
- <g id="topic-collapse" sketch:type="MSLayerGroup" fill="#999999">
- <path d="M6.77248677,13.4920045 C6.77248677,12.8952577 6.28819411,12.4126984 5.69394914,12.4126984 L19.6393842,12.4126984 C19.0444667,12.4126984 18.5608466,12.8966853 18.5608466,13.4920045 L18.5608466,0.359847325 C18.5608466,0.956594147 19.0451392,1.43915344 19.6393842,1.43915344 L5.69394914,1.43915344 C6.28886663,1.43915344 6.77248677,0.955166578 6.77248677,0.359847325 L6.77248677,13.4920045 Z M0.360615802,0 L19.6393842,0 C19.8385468,0 20,0.160353096 20,0.359847325 L20,13.4920045 C20,13.6907427 19.8400541,13.8518519 19.6393842,13.8518519 L0.360615802,13.8518519 C0.161453194,13.8518519 0,13.6914988 0,13.4920045 L0,0.359847325 C0,0.161109135 0.159945931,0 0.360615802,0 Z" id="Shape" sketch:type="MSShapeGroup"></path>
- <path d="M13.6719577,4.01798942 L13.6719577,6.35767196 L8.26455026,6.33968254 L8.26455026,8.06455026 L13.6719577,8.06455026 L13.6719577,10.4042328 L17.2698413,7.34603175 L13.6719577,4.01798942 Z M11.3375661,7.16613757 L11.3375661,7.23809524 L11.2656085,7.23809524 L11.2656085,7.16613757 L11.3375661,7.16613757 L11.3375661,7.16613757 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(12.767196, 7.211111) scale(-1, 1) translate(-12.767196, -7.211111) "></path>
- </g>
+<svg width="20" height="14" viewBox="0 0 20 14" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#72777d" fill-rule="evenodd">
+ <path d="M6.772 13.492a1.08 1.08 0 0 0-1.078-1.08H19.64c-.596 0-1.08.485-1.08 1.08V.36c0 .597.485 1.08 1.08 1.08H5.693A1.08 1.08 0 0 0 6.77.36v13.132zM.362 0H19.64c.2 0 .36.16.36.36v13.132c0 .2-.16.36-.36.36H.36c-.2 0-.36-.16-.36-.36V.36C0 .16.16 0 .36 0z"/>
+ <path d="M11.862 4.018v2.34l5.408-.018v1.725h-5.408v2.34l-3.597-3.06 3.597-3.327zm2.335 3.148v.072h.072v-.072h-.075z"/>
</g>
-</svg> \ No newline at end of file
+</svg>
diff --git a/Flow/modules/styles/flow/mw.flow.ui.Overlay.less b/Flow/modules/styles/flow/mw.flow.ui.Overlay.less
index 060ccfe9..5a6bdd81 100644
--- a/Flow/modules/styles/flow/mw.flow.ui.Overlay.less
+++ b/Flow/modules/styles/flow/mw.flow.ui.Overlay.less
@@ -5,6 +5,7 @@
right: 0;
left: 0;
z-index: 1;
+ font-size: 0.8em;
}
.flow-ui-overlay > * {
diff --git a/Flow/modules/styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less b/Flow/modules/styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less
index 2611e044..86b0dec1 100644
--- a/Flow/modules/styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less
+++ b/Flow/modules/styles/flow/widgets/editor/editors/mw.flow.ui.WikitextEditorWidget.less
@@ -1,40 +1,35 @@
-@import 'flow.colors';
-@import 'flow.variables';
+@import 'mediawiki.mixins';
+@import '../../../../flow.colors';
+@import '../../../../flow.variables';
.flow-ui-wikitextEditorWidget {
position: relative;
.oo-ui-textInputWidget {
max-width: none;
- padding-bottom: @editorToolbarHeight;
// Work around Chrome bug adding 5px below the textarea
line-height: 0;
textarea {
+ /* Re-apply system default after override by OOUI */
+ font-size: 13.3333px;
min-height: @editorMinHeight;
-webkit-appearance: none;
background: transparent;
- &, &:focus {
- border: none;
+ &,
+ &:focus {
+ border: 0;
box-shadow: none;
+ outline: 0;
}
- // Comma-separating this rule doesn't work :(
- // Placeholder text styling must be set individually for each browser
- &::-webkit-input-placeholder { // webkit
- font-style: italic;
- }
- &::-moz-placeholder { // FF 4-18
- font-style: italic;
- }
- &:-moz-placeholder { // FF >= 19
- font-style: italic;
- }
- &:-ms-input-placeholder { // IE >= 10
- font-style: italic;
- }
+ /* stylelint-disable indentation */
+ .mixin-placeholder( {
+ font-weight: normal;
+ } );
+ /* stylelint-enable indentation */
}
}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less
index 63ee3b72..bcaa12b4 100644
--- a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.AnonWarningWidget.less
@@ -1,30 +1,27 @@
-.flow-ui-anonWarningWidget{
- // The line-height is defined for all of flow-board class. However,
- // it has to be 0 in the case where the anonWarningWidget is empty
- // otherwise it has a visible height.
- line-height: 0;
+.flow-ui-anonWarningWidget {
+ // Hide when not active
+ display: none;
&-active {
+ background-color: #36c;
/* @embed */
background-image: url( ../../images/anon-user.svg );
- background-repeat: no-repeat;
- background-color: #347BFF;
background-position: 0.6em center;
-
- padding: 0.6em;
- padding-left: ~"calc(0.6em + 24px + 0.6em)";
-
- color: white;
+ background-repeat: no-repeat;
+ color: #fff;
display: block;
+ padding: 0.6em;
+ padding-left: ~'calc( 0.6em + 24px + 0.6em )';
line-height: 1.2em;
+ margin-bottom: 0.5em;
a {
- color: white;
+ color: #fff;
font-weight: bold;
}
body.rtl & {
- background-position: ~"calc(100% - 0.6em) center";
+ background-position: ~'calc( 100% - 0.6em ) center';
}
}
}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.CanNotEditWidget.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.CanNotEditWidget.less
new file mode 100644
index 00000000..228a78fc
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.CanNotEditWidget.less
@@ -0,0 +1,30 @@
+.flow-ui-canNotEditWidget {
+ // Hide when not active
+ display: none;
+
+ &-active {
+ /* @embed */
+ // From OOjs-UI
+ background-image: url( ../../images/lock-ltr.svg );
+ background-repeat: no-repeat;
+ background-color: #ffb50d;
+ background-position: 0.6em center;
+
+ padding: 0.6em;
+ padding-left: ~'calc( 0.6em + 24px + 0.6em )';
+
+ color: #000;
+ display: block;
+ line-height: 1.2em;
+ margin-bottom: 0.5em;
+
+ a {
+ color: #fff;
+ font-weight: bold;
+ }
+
+ body.rtl & {
+ background-position: ~'calc( 100% - 0.6em ) center';
+ }
+ }
+}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less
index 0a817fdf..aaf61648 100644
--- a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorControlsWidget.less
@@ -6,7 +6,7 @@
}
&-termsLabel {
- color: #666;
+ color: #54595d;
font-size: 0.75em;
}
}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less
index eaaf62fd..e4257f5d 100644
--- a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.EditorSwitcherWidget.less
@@ -1,9 +1,10 @@
-@import 'flow.colors';
-@import 'flow.variables';
+@import 'mediawiki.mixins';
+@import '../../../flow.colors';
+@import '../../../flow.variables';
.flow-ui-editorSwitcherWidget {
display: block;
- background-color: white;
+ background-color: #fff;
&-placeholder-input {
max-width: none;
@@ -16,42 +17,19 @@
// units (minHeight in em and toolbarHeight in px) which means we must
// use CSS's native calc() method.
// This escapes the calc() method while using LESS variables:
- min-height: ~"calc(@{editorMinHeight} + @{editorToolbarHeight})";
+ min-height: ~'calc( @{editorMinHeight} + @{editorToolbarHeight} )';
& textarea {
- border: none;
+ border: 0;
- // Comma-separating this rule doesn't work :(
- // Placeholder text styling must be set individually for each browser @winter
- &::-webkit-input-placeholder { // webkit
- font-style: italic;
- }
- &::-moz-placeholder { // FF 4-18
- font-style: italic;
- }
- &:-moz-placeholder { // FF >= 19
- font-style: italic;
- }
- &:-ms-input-placeholder { // IE >= 10
- font-style: italic;
- }
+ /* stylelint-disable indentation */
+ .mixin-placeholder( {
+ font-weight: normal;
+ } );
+ /* stylelint-enable indentation */
}
}
- // because we're attaching switcher controls below the textarea & we
- // want them to look unified with the textarea, we'll have to take away
- // it's border and re-apply on the parent node that contains both
- border: 1px solid @colorFieldBorder;
- -webkit-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- -moz-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- -o-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
-
- &-focused {
- border-color: @colorProgressive;
- box-shadow: inset 0 0 0 2px @colorProgressive;
- }
-
// Undo top margin on error box
&-error.flow-errors {
margin-top: 0;
@@ -59,6 +37,6 @@
// HACK: Undo border set by "old" editor CSS
> .flow-ui-visualEditorWidget > .ve-init-target {
- border: none;
+ border: 0;
}
}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-monobook.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-monobook.less
new file mode 100644
index 00000000..02089588
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-monobook.less
@@ -0,0 +1,82 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import '../../../flow.variables';
+@import '../../../flow.colors';
+
+.flow-component {
+ .ve-init-target {
+ &.flow-ui-focused {
+ outline: 0;
+ border-color: #a7dcff;
+ box-shadow: 0 0 0.3em #a7dcff, 0 0 0 #fff;
+ }
+ }
+
+ .ve-init-mw-target-surface,
+ .flow-ui-wikitextEditorWidget .oo-ui-textInputWidget {
+ padding-bottom: 44px;
+ }
+
+ // Undo .mw-body-content font-size (0.875em) and apply font-size matching OOUI theme (0.8em)
+ @uiFontSize: 0.8em/0.625/1.27; /* 0.8em / x-small / 127% */
+
+ .ve-ui-overlay {
+ font-size: @uiFontSize;
+ }
+
+ .flow-ui-wikitextEditorWidget,
+ .flow-ui-visualEditorWidget {
+ > .oo-ui-toolbar {
+ font-size: @uiFontSize;
+ margin-top: -44px;
+ }
+ }
+
+ .flow-ui-wikitextEditorWidget {
+ > .oo-ui-toolbar > .oo-ui-toolbar-bar {
+ /* Floating mini toolbar doesn't need drop shadow */
+ box-shadow: none;
+ }
+
+ .oo-ui-textInputWidget textarea {
+ /* Adjust min-height to new font size */
+ min-height: 10em * 12.7/13.3333;
+ }
+ }
+
+ .oo-ui-toolbar-bar {
+ // The default border is only appropriate in the default ve, with
+ // the toolbar above the editing surface.
+ border: 0;
+ // When we apply a pending texture to the editor, we don't want the toolbar to display
+ // in solid white on top of that.
+ background: transparent;
+ box-shadow: none;
+ }
+
+ .ve-ui-debugBar {
+ font-size: @uiFontSize;
+ &-selectionLabel {
+ min-width: 10em;
+ }
+ }
+}
+
+.flow-ui-newTopicWidget-title.oo-ui-textInputWidget input {
+ border-radius: 0.25em/1.5;
+}
+
+.flow-editor,
+.flow-ui-editorSwitcherWidget {
+ // Undo border & box-shadow on textarea and re-apply it on the
+ // div that contains textarea + legal text + switch button
+ border: 1px solid #c8ccd1;
+ border-radius: @borderRadius;
+}
+
+.flow-editor.flow-ui-focused,
+.flow-ui-editorSwitcherWidget-focused {
+ outline: 0;
+ border-color: #a7dcff;
+ box-shadow: 0 0 0.3em #a7dcff, 0 0 0 #fff;
+}
diff --git a/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-vector.less b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-vector.less
new file mode 100644
index 00000000..996c3bfc
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/editor/mw.flow.ui.editor-vector.less
@@ -0,0 +1,91 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import '../../../flow.variables';
+@import '../../../flow.colors';
+
+.flow-component {
+ .ve-init-target {
+ &.flow-ui-focused {
+ border-color: @colorProgressive;
+ box-shadow: inset 0 0 0 1px @colorProgressive;
+ }
+ }
+
+ .ve-init-mw-target-surface,
+ .flow-ui-wikitextEditorWidget .oo-ui-textInputWidget {
+ // This creates a space for the toolbar, a matching negative margin-top
+ // shifts the toolbar into this location.
+ // @todo This value is specific to MW theme, is different in Apex.
+ padding-bottom: @editorToolbarHeight + 1px;
+ }
+
+ // Undo .mw-body-content font-size (0.875em) and apply font-size matching OOUI theme (0.8em)
+ @uiFontSize: 0.8/0.875em;
+
+ .ve-ui-overlay {
+ font-size: @uiFontSize;
+ }
+
+ .flow-ui-wikitextEditorWidget,
+ .flow-ui-visualEditorWidget {
+ > .oo-ui-toolbar {
+ font-size: @uiFontSize;
+ // The 1px of positive margin gives room for the blue border
+ // of the TextInputWidget
+ margin: ( -@editorToolbarHeight - 1px ) 1px 1px 1px;
+ }
+ }
+
+ .flow-ui-wikitextEditorWidget {
+ .oo-ui-textInputWidget textarea {
+ /* Adjust min-height to new font size */
+ min-height: 10em * 14/13.3333;
+ }
+ }
+
+ .oo-ui-toolbar-bar {
+ // The default border is only appropriate in the default ve, with
+ // the toolbar above the editing surface.
+ border: 0;
+ box-shadow: none;
+ // When we apply a pending texture to the editor, we don't want the toolbar to display
+ // in solid white on top of that.
+ background: transparent;
+ }
+
+ .oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled.oo-ui-tool-active {
+ box-shadow: none;
+ }
+
+ .oo-ui-toolGroup {
+ border: 0;
+ }
+
+ .ve-ui-debugBar {
+ font-size: @uiFontSize;
+ &-selectionLabel {
+ min-width: 10em;
+ }
+ }
+}
+
+.flow-editor,
+.flow-ui-editorSwitcherWidget {
+ // because we're attaching switcher controls below the textarea & we
+ // want them to look unified with the textarea, we'll have to take away
+ // it's border and re-apply on the parent node that contains both
+ border: 1px solid @colorFieldBorder;
+ -webkit-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ -moz-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ -o-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ border-radius: @borderRadius;
+}
+
+.flow-editor.flow-ui-focused,
+.flow-ui-editorSwitcherWidget-focused {
+ // Undo border & box-shadow on textarea and re-apply it on the
+ // div that contains textarea + legal text + switch button
+ border-color: @colorProgressive;
+ box-shadow: inset 0 0 0 1px @colorProgressive;
+}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoriesWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoriesWidget.less
new file mode 100644
index 00000000..9dab1034
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoriesWidget.less
@@ -0,0 +1,10 @@
+.flow-ui-categoriesWidget {
+ .flow-board-header-category-list {
+ margin: 0.3em 0 0 0.3em;
+ display: inline;
+ }
+
+ .flow-board-header-category-title {
+ display: inline;
+ }
+}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less
new file mode 100644
index 00000000..00d164fa
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.CategoryItemWidget.less
@@ -0,0 +1,3 @@
+.flow-ui-categoryItemWidget {
+ padding-right: 0.2em;
+}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.NavigationWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.NavigationWidget.less
index 95404bc0..9608b2ef 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.NavigationWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.NavigationWidget.less
@@ -9,13 +9,13 @@
width: 100%;
z-index: 1;
position: relative;
- border-bottom: 1px solid #ccc;
+ border-bottom: 1px solid #c8ccd1;
&-affixed {
+ background: #fff;
position: fixed;
z-index: 2;
top: 0;
- background: white;
.flow-ui-tocWidget {
width: 100%;
@@ -37,8 +37,7 @@
.oo-ui-labelElement-label {
text-overflow: ellipsis;
overflow: hidden;
- // Prevent less compiler from precalculating this expression
- width: ~"calc(100% - 1.875em)";
+ width: 100%;
}
}
}
@@ -49,7 +48,7 @@
max-height: 400px;
/* Workaround for flicker and https://code.google.com/p/chromium/issues/detail?id=343244 */
- -webkit-transform: translateZ(0);
+ -webkit-transform: translateZ( 0 );
}
}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.NewTopicWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.NewTopicWidget.less
index c1d7ebad..41a3fce8 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.NewTopicWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.NewTopicWidget.less
@@ -1,50 +1,57 @@
+@import 'mediawiki.mixins';
+
.flow-ui-newTopicWidget {
clear: both;
- margin-top: 1.5em;
&-title.oo-ui-textInputWidget {
// OO.ui.TextInputWidget has a max-width: 50 by default
max-width: none;
input {
- // Reproduce mw-input-large
- font-size: 1.75em;
+ .flow-ui-newTopicWidget-expanded & {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+
+ // Match heading styles
+ font-size: 1.5em;
font-weight: bold;
line-height: 1.25em;
// Reproduce mw-input
-webkit-appearance: none;
- border: 1px solid #CCC;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
- padding: .3em .3em .3em .6em;
+ padding: 0.429em 0.381em 0.381em;
display: block;
vertical-align: middle;
- border-radius: 2px;
font-family: inherit;
- -webkit-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- -moz-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- -o-transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
- transition: border 0.2s cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 0.2s cubic-bezier(0.39, 0.575, 0.565, 1);
+ -webkit-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ -moz-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ -o-transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
+ transition: border 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 ), box-shadow 0.2s cubic-bezier( 0.39, 0.575, 0.565, 1 );
- &::-webkit-input-placeholder {
- font-style: italic;
- font-weight: normal;
- }
- &::-moz-placeholder {
- font-style: italic;
- font-weight: normal;
- }
- &:-moz-placeholder {
- font-style: italic;
+ /* stylelint-disable indentation */
+ .mixin-placeholder( {
font-weight: normal;
- }
- &:-ms-input-placeholder {
- font-style: italic;
- font-weight: normal;
- }
+ } );
+ /* stylelint-enable indentation */
+ }
+ }
+
+ &-editor {
+ .flow-editor,
+ .flow-ui-editorSwitcherWidget {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ }
+ .flow-editor.flow-ui-focused,
+ .flow-ui-editorSwitcherWidget-focused {
+ /* Force above the title widget so border isn't cropped */
+ position: relative;
}
}
}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less
index 4f459ef5..e08337e5 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.ReorderTopicsWidget.less
@@ -1,9 +1,21 @@
.flow-ui-reorderTopicsWidget {
- .oo-ui-menuOptionWidget {
- /* HACK: Override menuOptionWidget styles for T101560 */
- .oo-ui-iconElement-icon {
- display: block;
+ &-button {
+ margin-right: 0;
+ }
+
+ .skin-vector &,
+ .skin-minerva & {
+ &.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ padding-right: 2em;
+
+ > .oo-ui-indicatorElement-indicator {
+ right: 0.5em;
+ }
}
- padding: 0.5em 2em 0.5em 3em;
}
-} \ No newline at end of file
+
+ .oo-ui-icon-beta {
+ /* @embed */
+ background-image: url( ../images/newest-topics.svg );
+ }
+}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.ReplyWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.ReplyWidget.less
index 38908a82..5c917bdb 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.ReplyWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.ReplyWidget.less
@@ -1,5 +1,9 @@
+@import 'mediawiki.mixins';
+@import '../../flow.colors';
+@import '../../flow.variables';
+
.flow-ui-replyWidget {
- margin-left: 1.5em;
+ margin-left: @topicIndent;
margin-top: 1em;
&-trigger-input {
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less
index f9f3f719..01a52f01 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.SidebarExpandWidget.less
@@ -1,5 +1,4 @@
-@import 'flow.variables';
-
+@import '../../flow.variables';
.flow-ui-sidebarExpandWidget {
display: none;
@@ -7,7 +6,7 @@
// Needs text-align: right; in RTL
text-align: left;
- @media (min-width: @medium) {
+ @media ( min-width: @medium ) {
display: block;
float: right;
width: 34%;
@@ -17,7 +16,7 @@
}
&-collapsed {
- @media (min-width: @medium) {
+ @media ( min-width: @medium ) {
width: 24px;
margin-left: -24px;
}
@@ -25,10 +24,10 @@
.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon.oo-ui-icon-topic-collapse {
/* @embed */
- background: url( '../images/topic-collapse-ltr.svg' ) no-repeat;
+ background: url( ../images/topic-collapse-ltr.svg ) no-repeat;
}
.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon.oo-ui-icon-topic-expand {
/* @embed */
- background: url( '../images/topic-collapse-rtl.svg' ) no-repeat;
+ background: url( ../images/topic-collapse-rtl.svg ) no-repeat;
}
}
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less
index c51e6163..2e540959 100644
--- a/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicMenuSelectWidget.less
@@ -2,12 +2,13 @@
position: relative;
overflow-y: auto;
- &-locked, &-locked:hover {
- color: #999;
+ &-locked,
+ &-locked:hover {
+ color: #72777d;
}
// Override border-color and margin-top from OOUI MenuSelectWidget
- border-color: #ccc;
+ border-color: #c8ccd1;
margin-top: 0;
// Override hidden scrollbars configuration in OS X users
@@ -20,8 +21,8 @@
}
&::-webkit-scrollbar-thumb {
border-radius: 8px;
- border: 2px solid white; /* should match background, can't be transparent */
- background-color: rgba(0, 0, 0, .5);
+ border: 2px solid #fff; /* should match background, can't be transparent */
+ background-color: rgba( 0, 0, 0, 0.5 );
}
&::-webkit-scrollbar-track {
background-color: #fff;
diff --git a/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less b/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less
new file mode 100644
index 00000000..81bbef50
--- /dev/null
+++ b/Flow/modules/styles/flow/widgets/mw.flow.ui.TopicTitleWidget.less
@@ -0,0 +1,18 @@
+.flow-ui-topicTitleWidget {
+ &-controls {
+ margin-top: 8px;
+ }
+
+ &-buttons {
+ float: right;
+ }
+
+ &-termsLabel {
+ color: #54595d;
+ font-size: 0.75em;
+ }
+
+ &-titleInput {
+ max-width: none;
+ }
+}
diff --git a/Flow/modules/styles/js.less b/Flow/modules/styles/js.less
index 561b2d49..749352ca 100644
--- a/Flow/modules/styles/js.less
+++ b/Flow/modules/styles/js.less
@@ -1,66 +1,58 @@
@import 'mediawiki.mixins';
@import 'flow.colors';
-@import 'flow.helpers';
// @todo: Find better home for this css
.client-js {
- // Hide the component while it is loading if Javascript
- // is enabled.
- .flow-ui-load-overlay {
- z-index: 101;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- cursor: wait;
- }
+ .flow-action-view {
+ // Hide the component while it is loading if Javascript
+ // is enabled.
+ .flow-ui-load-overlay {
+ z-index: 101;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ cursor: wait;
+ }
- .flow-component {
- position: relative;
- opacity: 0.5;
+ .flow-component {
+ position: relative;
+ opacity: 0.5;
- &-ready {
- opacity: 1;
+ &-ready {
+ opacity: 1;
- -moz-transition: opacity 0.5s;
- -webkit-transition: opacity 0.5s;
- -o-transition: opacity 0.5s;
- transition: opacity 0.5s;
+ -moz-transition: opacity 0.5s;
+ -webkit-transition: opacity 0.5s;
+ -o-transition: opacity 0.5s;
+ transition: opacity 0.5s;
+ }
}
- }
- /*
- Fallback elements
+ /*
+ Fallback elements
- Fallback elements are invisible when JavaScript is enabled. They only exist when JavaScript does not run.
+ Fallback elements are invisible when JavaScript is enabled. They only exist when JavaScript does not run.
- Markup:
- <div class="flow-ui-fallback-element"></div>
+ Markup:
+ <div class="flow-ui-fallback-element"></div>
- Styleguide X.
- */
- .flow-ui-fallback-element {
- visibility: hidden;
- height: 0;
- }
+ Styleguide X.
+ */
+ .flow-ui-fallback-element {
+ visibility: hidden;
+ height: 0;
+ }
- // With JS, hide .flow-nojs & display .flow-js elements
- .flow-nojs {
- display: none;
- }
- .flow-js {
- display: block;
- }
-}
+ // With JS, hide .flow-nojs & display .flow-js elements
+ .flow-nojs {
+ display: none;
+ }
+ .flow-js {
+ display: block;
+ }
-.client-nojs {
- // Without JS, hide .flow-js & display .flow-nojs elements
- .flow-nojs {
- display: block;
- }
- .flow-js {
- display: none;
}
}
@@ -94,23 +86,49 @@
}
// Basic API interaction indicator
-div#content div#bodyContent .flow-api-inprogress {
+div#content div#bodyContent .flow-api-inprogress { /* stylelint-disable-line selector-no-id */
opacity: 0.5;
cursor: wait;
}
@-webkit-keyframes spin {
- 0% { -webkit-transform: rotate(0deg); opacity: .5; }
- 50% { opacity: .75; }
- 100% { -webkit-transform: rotate(360deg); opacity: .5; }
+ 0% {
+ -webkit-transform: rotate( 0deg );
+ opacity: 0.5;
+ }
+ 50% {
+ opacity: 0.75;
+ }
+ 100% {
+ -webkit-transform: rotate( 360deg );
+ opacity: 0.5;
+ }
}
+
@-moz-keyframes spin {
- 0% { -moz-transform: rotate(0deg); opacity: .5; }
- 50% { opacity: .75; }
- 100% { -moz-transform: rotate(360deg); opacity: .5; }
+ 0% {
+ -moz-transform: rotate( 0deg );
+ opacity: 0.5;
+ }
+ 50% {
+ opacity: 0.75;
+ }
+ 100% {
+ -moz-transform: rotate( 360deg );
+ opacity: 0.5;
+ }
}
+
@keyframes spin {
- 0% { transform:rotate(0deg); opacity: .5; }
- 50% { opacity: .75; }
- 100% { transform:rotate(360deg); opacity: .5; }
+ 0% {
+ transform: rotate( 0deg );
+ opacity: 0.5;
+ }
+ 50% {
+ opacity: 0.75;
+ }
+ 100% {
+ transform: rotate( 360deg );
+ opacity: 0.5;
+ }
}
diff --git a/Flow/modules/styles/mediawiki.ui/forms.less b/Flow/modules/styles/mediawiki.ui/forms.less
index 72e8c3be..9370af80 100644
--- a/Flow/modules/styles/mediawiki.ui/forms.less
+++ b/Flow/modules/styles/mediawiki.ui/forms.less
@@ -1,24 +1,26 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
-@import 'flow.variables';
+@import '../flow.colors';
+@import '../flow.variables';
// Form elements [Draft]
//
// Styleguide 4.
-.flow-ui-input-replacement-anchor {
+.flow-ui-input-replacement-anchor.mw-ui-input {
+ color: @colorGray7;
display: block;
- margin: 1em 0 0 .9em;
+ margin: 1em 0 0 @topicIndent;
+ width: auto;
+}
- // FIXME: It's a shame we have to duplicate css in mw-ui-input. Need saner way going forward. mw-ui-textarea ?
- &.mw-ui-input-large {
- margin: 0;
- font-size: 1.75em;
- font-style: italic;
- line-height: 1.25;
- color: @colorTextLight;
- }
+// FIXME: It's a shame we have to duplicate css in mw-ui-input. Need saner way going forward. mw-ui-textarea ?
+.flow-newtopic-form .mw-ui-input-large,
+.flow-ui-input-replacement-anchor.mw-ui-input-large {
+ margin: 0;
+ font-weight: normal;
+ font-size: 1.5em;
+ padding: 0.429em 0.381em 0.381em;
+ line-height: 1.25;
}
.client-nojs {
@@ -33,7 +35,7 @@
// Make all text fields 100% wide by default
.mw-ui-fieldtype-text,
.mw-ui-fieldtag-textarea {
- .box-sizing(border-box);
+ .box-sizing( border-box );
width: 100%;
}
@@ -55,21 +57,19 @@
.mw-ui-uls-icon:before {
//.glyphicon-globe
- content: "\e135";
+ content: '\e135';
opacity: 0.66;
}
-
/*
== MediaWiki UI Text Field Validation ==
=== Guidelines ===
-
=== Notes ===
Does not support IE7 nor IE8.
*/
-/*.flow-ui-validated */.mw-ui-field:not(.ie8WillIgnoreThis) {
+/*.flow-ui-validated */.mw-ui-field:not( .ie8WillIgnoreThis ) {
.mw-ui-field-icon {
.box-sizing( border-box );
white-space: nowrap;
@@ -88,9 +88,9 @@ Does not support IE7 nor IE8.
position: absolute;
top: 50%;
left: 0;
- margin-top: -.6em;
+ margin-top: -0.6em;
width: 2em;
- color: @colorGrayLight;
+ color: @colorGray12;
font-size: 1em;
line-height: 1;
text-align: center;
@@ -101,8 +101,9 @@ Does not support IE7 nor IE8.
}
.mw-ui-validation-icon {
- border-radius: 0 2px 2px 0;
- border: 1px solid @colorGrayDark;
+ border-color: @colorGray7;
+ border-radius: 0 @borderRadius @borderRadius 0;
+ border-style: solid;
border-width: 1px 1px 1px 0;
}
.mw-ui-validation-icon:before {
@@ -111,16 +112,27 @@ Does not support IE7 nor IE8.
.mw-ui-input {
// Hide the ULS icon because these elements have HTML5 controls
- &[type='date'], &[type='number'], &[type='search'], &[type='time'] {
+ &[type='date'],
+ &[type='number'],
+ &[type='search'],
+ &[type='time'] {
~ .mw-ui-uls-icon {
visibility: hidden;
}
}
&:valid {
- &[required], &[min], &[max], &[pattern],
- &[type='color'], &[type='date'], &[type='email'], &[type='number'],
- &[type='url'], &[type='range'], &[type='time'] {
+ &[required],
+ &[min],
+ &[max],
+ &[pattern],
+ &[type='color'],
+ &[type='date'],
+ &[type='email'],
+ &[type='number'],
+ &[type='url'],
+ &[type='range'],
+ &[type='time'] {
border-right-width: 2em;
~ .mw-ui-validation-icon {
@@ -128,12 +140,12 @@ Does not support IE7 nor IE8.
}
}
~ .mw-ui-validation-icon {
- background: #00B08A;
- background: rgba(0, 176, 138, .85);
+ background: #00b08a;
+ background: rgba( 0, 176, 138, 0.85 );
}
~ .mw-ui-validation-icon:before {
//.glyphicon-ok
- content: "\e013";
+ content: '\e013';
}
// Support up to two icons side by side
@@ -145,7 +157,8 @@ Does not support IE7 nor IE8.
right: 4em;
}
}
- &[type='number'], &[type='time'] {
+ &[type='number'],
+ &[type='time'] {
+ .mw-ui-validation-icon + .mw-ui-uls-icon {
right: 3em;
}
@@ -153,9 +166,17 @@ Does not support IE7 nor IE8.
}
&:invalid {
- &[required], &[min], &[max], &[pattern],
- &[type='color'], &[type='date'], &[type='email'], &[type='number'],
- &[type='url'], &[type='range'], &[type='time'] {
+ &[required],
+ &[min],
+ &[max],
+ &[pattern],
+ &[type='color'],
+ &[type='date'],
+ &[type='email'],
+ &[type='number'],
+ &[type='url'],
+ &[type='range'],
+ &[type='time'] {
border-right-width: 2em;
~ .mw-ui-validation-icon {
@@ -163,12 +184,12 @@ Does not support IE7 nor IE8.
}
}
~ .mw-ui-validation-icon {
- background: #D31300;
- background: rgba(211, 19, 0, .85);
+ background: #d31300;
+ background: rgba( 211, 19, 0, 0.85 );
}
~ .mw-ui-validation-icon:before {
//.glyphicon-remove
- content: "\e014";
+ content: '\e014';
}
// Support up to two icons side by side
@@ -185,17 +206,15 @@ Does not support IE7 nor IE8.
}
}
-
/*
== MediaWiki UI Radio and Checkbox ==
=== Guidelines ===
-
=== Notes ===
Does not support IE7 nor IE8.
*/
-.mw-ui-fieldtag-input:not(.ie8WillIgnoreThis) {
+.mw-ui-fieldtag-input:not( .ie8WillIgnoreThis ) {
cursor: pointer;
.mw-ui-radio:before,
@@ -217,28 +236,28 @@ Does not support IE7 nor IE8.
input[type='radio'] {
+ .mw-ui-radio:before {
//.glyphicon-dashboard
- content: "\e141";
+ content: '\e141';
}
&:checked + .mw-ui-radio:before {
//.glyphicon-record
text-shadow: none;
- content: "\e165";
+ content: '\e165';
}
}
input[type='checkbox'] {
+ .mw-ui-checkbox:before {
//.glyphicon-unchecked
- content: "\e157";
+ content: '\e157';
}
&:checked + .mw-ui-checkbox:before {
//.glyphicon-check
- content: "\e067";
+ content: '\e067';
}
}
}
input.mw-ui-input-large {
- padding-left: .75em;
+ padding-left: 0.75em;
}
textarea.mw-ui-input-large {
diff --git a/Flow/modules/styles/mediawiki.ui/modal.less b/Flow/modules/styles/mediawiki.ui/modal.less
index 463010ca..341f586b 100644
--- a/Flow/modules/styles/mediawiki.ui/modal.less
+++ b/Flow/modules/styles/mediawiki.ui/modal.less
@@ -1,9 +1,8 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.colors';
.flow-ui-modal {
- .box-sizing(border-box);
+ .box-sizing( border-box );
// make content centered
display: block; // nonflex
display: flex; // flexbox
@@ -18,11 +17,11 @@
// background styling
width: 100%;
height: 100%;
- background: fade( @colorWhite, 75% );
+ background: fade( #fff, 75% );
// fix content centering for nonflex
&:before {
- .box-sizing(border-box);
+ .box-sizing( border-box );
content: '';
display: inline-block;
height: 100%;
@@ -31,7 +30,7 @@
}
.flow-ui-modal-layout {
- .box-sizing(border-box);
+ .box-sizing( border-box );
// center in viewport
vertical-align: middle;
display: inline-block; // nonflex center fix
@@ -42,39 +41,39 @@
max-height: 97%;
// box styling
position: relative;
- background: @colorWhite;
- box-shadow: 0 4px 0 0 @colorGrayLighter, 0 0 0 1px @colorGrayLighter;
- border-radius: 3px;
+ background: #fff;
+ box-shadow: 0 4px 0 0 @colorGray12, 0 0 0 1px @colorGray12;
+ border-radius: @borderRadius;
color: @colorText;
text-align: left;
}
.flow-ui-modal-heading {
- .box-sizing(border-box);
- margin: .3em .3em 0;
- padding: 0 .3em;
+ .box-sizing( border-box );
+ margin: 0.3em 0.3em 0;
+ padding: 0 0.3em;
font-weight: bold;
color: @colorText;
line-height: 2.2;
- border-bottom: 1px solid @colorGrayLight;
+ border-bottom: 1px solid @colorGray12;
}
.flow-ui-modal-heading-prev {
float: left;
display: inline-block;
- padding: 0 .3em;
- margin: 0 .6em 0 -.3em;
+ padding: 0 0.3em;
+ margin: 0 0.6em 0 -0.3em;
height: 100%;
- border-right: 1px solid @colorGrayLight;
+ border-right: 1px solid @colorGray12;
color: @colorTextLight;
}
.flow-ui-modal-heading-next {
float: right;
display: inline-block;
- padding: 0 .3em;
- margin: 0 -.3em 0 .6em;
+ padding: 0 0.3em;
+ margin: 0 -0.3em 0 0.6em;
height: 100%;
- border-left: 1px solid @colorGrayLight;
+ border-left: 1px solid @colorGray12;
color: @colorTextLight;
}
diff --git a/Flow/modules/styles/mediawiki.ui/text.less b/Flow/modules/styles/mediawiki.ui/text.less
index 84a32281..7e18b604 100644
--- a/Flow/modules/styles/mediawiki.ui/text.less
+++ b/Flow/modules/styles/mediawiki.ui/text.less
@@ -1,6 +1,5 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.colors';
.flow-ui-text-truncated {
white-space: nowrap;
diff --git a/Flow/modules/styles/mediawiki.ui/tooltips.less b/Flow/modules/styles/mediawiki.ui/tooltips.less
index fa7a0941..9259ee2f 100644
--- a/Flow/modules/styles/mediawiki.ui/tooltips.less
+++ b/Flow/modules/styles/mediawiki.ui/tooltips.less
@@ -1,6 +1,5 @@
@import 'mediawiki.mixins';
-@import 'flow.colors';
-@import 'flow.helpers';
+@import '../flow.colors';
/*
Tooltips
@@ -17,30 +16,26 @@ This is intended to be used with JavaScript, but does not have to be. With JS, y
Styleguide 4.0.
*/
.flow-ui-tooltip {
+ background-color: #fff;
+ color: @colorText;
position: relative;
top: 1px;
display: inline-block;
- padding: .5em;
- background: @colorWhite;
- *background: @colorOffWhite; // ie6
- color: @colorText;
+ border-radius: @borderRadius;
+ padding: 0.571em 0.857em; // equals to ~8px ~12px with base `font-size`
+ .box-shadow( ~'0 2px 2px 0 rgba(0, 0, 0, 0.25)' );
+ font-size: 0.875em; // not inherited from div#bodyContent, as we insert at body
word-wrap: break-word;
- border-radius: 3px;
- .box-shadow( ~"0 2px 0 0 @{colorGrayLight}, 0 0 1px 0 @{colorGrayLight}" );
- opacity: .9;
z-index: 99;
a {
// FIXME: Due to the lack of a fix for bug 66746 this link is treated as an external link.
- // Yes Shahyar !important is bad
- // but the alternative css hacks that would be needed here are even more horrible.
- color: #fff !important;
+ // !important is bad but the alternative css hacks that would be needed here are even more horrible.
+ color: #fff !important; /* stylelint-disable-line declaration-no-important */
font-weight: bold;
}
- font-size: .875em; // not inherited from div#bodyContent, as we insert at body
-
- #bodyContent & {
+ #bodyContent & { /* stylelint-disable-line selector-no-id */
font-size: 1em;
}
@@ -55,30 +50,41 @@ Styleguide 4.0.
backface-visibility: hidden;
&:after {
- content: "";
+ content: '';
position: absolute;
z-index: 1;
width: 1em;
height: 1em;
- background: @colorWhite;
- *background: @colorOffWhite; //ie6
- transform: rotate(45deg);
- -webkit-transform: rotate(45deg);
+ background: #fff;
+ transform: rotate( 45deg );
+ -webkit-transform: rotate( 45deg );
}
}
// mw-ui-tooltip helpers to cleanly set triangle location
// The first four are because less.php doesn't support "@{var}: n" syntax
- .flow-ui-tooltip-triangle-location-horizontal( top ) { top: -1em; }
- .flow-ui-tooltip-triangle-location-horizontal( bottom ) { bottom: -1em; }
- .flow-ui-tooltip-triangle-location-vertical( left ) { left: -1em; }
- .flow-ui-tooltip-triangle-location-vertical( right ) { right: -1em; }
+ .flow-ui-tooltip-triangle-location-horizontal( top ) {
+ top: -1em;
+ }
+ .flow-ui-tooltip-triangle-location-horizontal( bottom ) {
+ bottom: -1em;
+ }
+ .flow-ui-tooltip-triangle-location-vertical( left ) {
+ /* @noflip */
+ left: -1em;
+ }
+ .flow-ui-tooltip-triangle-location-vertical( right ) {
+ /* @noflip */
+ right: -1em;
+ }
// up-down
.flow-ui-tooltip-triangle-location( horizontal, @location ) {
width: 2em;
height: 1em;
+ /* @noflip */
left: 50%;
.flow-ui-tooltip-triangle-location-horizontal( @location );
+ /* @noflip */
margin-left: -1em;
}
// left-right
@@ -92,62 +98,73 @@ Styleguide 4.0.
// triangle on top
&.flow-ui-tooltip-up {
- margin-top: .75em;
+ /* @noflip */
+ margin-top: 0.75em;
.flow-ui-tooltip-triangle {
.flow-ui-tooltip-triangle-location( horizontal, top );
&:after {
- top: .5em;
- left: .5em;
- .box-shadow( ~"0 0 1px 0 @{colorGrayLight}" );
+ top: 0.5em;
+ /* @noflip */
+ left: 0.5em;
+ /* @noflip */
+ .box-shadow( ~'0 0 1px 0 @{colorGray12}' );
}
}
}
// triangle on bottom
&.flow-ui-tooltip-down {
- margin-bottom: .75em;
+ margin-bottom: 0.75em;
.flow-ui-tooltip-triangle {
.flow-ui-tooltip-triangle-location( horizontal, bottom );
&:after {
- top: -.5em;
- left: .5em;
- .box-shadow( ~"0 -1.5px 0 1.5px @{colorGrayLight}, 0 0 1px 0 @{colorGrayLight}" );
+ top: -0.5em;
+ /* @noflip */
+ left: 0.5em;
+ /* @noflip */
+ .box-shadow( ~'0 -1.5px 0 1.5px @{colorGray12}, 0 0 1px 0 @{colorGray12}' );
}
}
}
// triangle at left
&.flow-ui-tooltip-left {
- margin-left: .75em;
+ /* @noflip */
+ margin-left: 0.75em;
.flow-ui-tooltip-triangle {
.flow-ui-tooltip-triangle-location( vertical, left );
&:after {
margin-top: -1px;
- top: .5em;
- right: -.5em;
- .box-shadow( ~"1.5px 0 0 1.5px @{colorGrayLight}, 0 0 1px 0 @{colorGrayLight}" );
+ top: 0.5em;
+ /* @noflip */
+ right: -0.5em;
+ /* @noflip */
+ .box-shadow( ~'1.5px 0 0 1.5px @{colorGray12}, 0 0 1px 0 @{colorGray12}' );
}
}
}
// triangle at right
&.flow-ui-tooltip-right {
- margin-left: -.75em;
+ /* @noflip */
+ margin-left: -0.75em;
.flow-ui-tooltip-triangle {
.flow-ui-tooltip-triangle-location( vertical, right );
&:after {
margin-top: -1px;
- top: .5em;
- left: -.5em;
- .box-shadow( ~"0 1.5px 0 1.5px @{colorGrayLight}, 0 0 1px 0 @{colorGrayLight}" );
+ top: 0.5em;
+ /* @noflip */
+ left: -0.5em;
+ /* @noflip */
+ .box-shadow( ~'0 1.5px 0 1.5px @{colorGray12}, 0 0 1px 0 @{colorGray12}' );
}
}
}
@@ -156,20 +173,24 @@ Styleguide 4.0.
@backgroundColorDarkened: darken( @backgroundColor, @colorDarkenPercentage );
background: @backgroundColor;
- .box-shadow( ~"0 2px 0 0 @{backgroundColorDarkened}" );
- color: @colorWhite;
+ /* @noflip */
+ .box-shadow( ~'0 2px 0 0 @{backgroundColorDarkened}' );
+ color: #fff;
.flow-ui-tooltip-triangle:after {
background: @backgroundColor;
}
&.flow-ui-tooltip-down .flow-ui-tooltip-triangle:after {
- .box-shadow( ~"0 -2px 0 2px @{backgroundColorDarkened}" );
+ /* @noflip */
+ .box-shadow( ~'0 -2px 0 2px @{backgroundColorDarkened}' );
}
&.flow-ui-tooltip-left .flow-ui-tooltip-triangle:after {
- .box-shadow( ~"2px 0 0 2px @{backgroundColorDarkened}" );
+ /* @noflip */
+ .box-shadow( ~'2px 0 0 2px @{backgroundColorDarkened}' );
}
&.flow-ui-tooltip-right .flow-ui-tooltip-triangle:after {
- .box-shadow( ~"0 2px 0 2px @{backgroundColorDarkened}" );
+ /* @noflip */
+ .box-shadow( ~'0 2px 0 2px @{backgroundColorDarkened}' );
}
}
@@ -187,20 +208,15 @@ Styleguide 4.0.
fill: @colorProgressive;
}
}
- &.mw-ui-constructive {
- .flow-ui-tooltip-color( @colorConstructive );
- .mw-ui-icon {
- fill: @colorConstructive;
- }
- }
&.mw-ui-destructive {
.flow-ui-tooltip-color( @colorDestructive );
- .mw-ui-button.mw-ui-destructive.mw-ui-quiet:hover, .mw-ui-button.mw-ui-destructive.mw-ui-quiet:focus span {
+ .mw-ui-button.mw-ui-destructive.mw-ui-quiet:hover,
+ .mw-ui-button.mw-ui-destructive.mw-ui-quiet:focus span {
fill: @colorDestructive;
}
}
&.flow-ui-tooltip-small {
- font-size: .75em;
+ font-size: 0.75em;
.flow-ui-tooltip-content {
max-width: 240px;
@@ -218,6 +234,6 @@ Styleguide 4.0.
// Block-level tooltip
.flow-ui-tooltip-block {
- .box-sizing(border-box);
+ .box-sizing( border-box );
width: 100%;
}
diff --git a/Flow/modules/styles/minerva/common.less b/Flow/modules/styles/minerva/common.less
index 782cd0dc..818d907c 100644
--- a/Flow/modules/styles/minerva/common.less
+++ b/Flow/modules/styles/minerva/common.less
@@ -1,4 +1,4 @@
// On mobile enable the talk page button when Flow is enabled
-.mw-mobile-mode.stable #ca-talk {
+.mw-mobile-mode.stable #ca-talk { /* stylelint-disable-line selector-no-id */
display: block;
}
diff --git a/Flow/modules/styles/nojs.less b/Flow/modules/styles/nojs.less
new file mode 100644
index 00000000..321fc378
--- /dev/null
+++ b/Flow/modules/styles/nojs.less
@@ -0,0 +1,9 @@
+.client-nojs {
+ // Without JS, hide .flow-js & display .flow-nojs elements
+ .flow-nojs {
+ display: block;
+ }
+ .flow-js {
+ display: none;
+ }
+}
diff --git a/Flow/modules/tours/flow-icon.svg b/Flow/modules/tours/flow-icon.svg
index 0b71cccd..a41942f1 100644
--- a/Flow/modules/tours/flow-icon.svg
+++ b/Flow/modules/tours/flow-icon.svg
@@ -1,33 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- version="1.1"
- width="100%"
- height="100%"
- viewBox="0 0 42 32"
- id="Layer_1"
- xml:space="preserve"><metadata
- id="metadata11"><rdf:RDF><cc:Work
- rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
- id="defs9" /><g
- transform="matrix(2,0,0,2,-2,-8)"
- id="g3777"><g
- transform="matrix(1,0,0,-1,0,1638)"
- id="g3"
- style="fill:#00af89;fill-opacity:1"><path
- d="m 3,1634 12,0 0,-4 -8,0 0,-7 -6,0 2,2 z"
- id="path5"
- style="fill:#00af89;fill-opacity:1" /></g><g
- transform="matrix(1,0,0,-1,-20,1638)"
- id="g3-3"
- style="fill:#347bff;fill-opacity:1"><path
- d="m 40,1629 0,-9 2,-2 -14,0 0,11 z"
- id="path5-9"
- style="fill:#347bff;fill-opacity:1" /></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 42 32" width="42" height="32">
+ <path d="M4 0h24v8H12v14H0l4-4z" fill="#00af89"/>
+ <path d="M38 10v18l4 4H14V10z" fill="#36c"/>
+</svg>
diff --git a/Flow/modules/tours/flowOptIn.js b/Flow/modules/tours/flowOptIn.js
index 1caefff0..c32b4d2b 100644
--- a/Flow/modules/tours/flowOptIn.js
+++ b/Flow/modules/tours/flowOptIn.js
@@ -2,6 +2,7 @@
var archiveLinkExists = $( '.flow-link-to-archive' ).length,
tour = new gt.TourBuilder( {
name: 'flowOptIn',
+ shouldLog: true,
isSinglePage: true
} ),
$firstStepDescription = $( '<div>' )
@@ -12,40 +13,43 @@
mw.msg( 'flow-guidedtour-optin-welcome-description' )
);
- tour.firstStep( {
- name: 'newTopic',
- titlemsg: 'flow-guidedtour-optin-welcome',
- description: $firstStepDescription[ 0 ].outerHTML,
- attachTo: '.flow-ui-newTopicWidget .flow-ui-newTopicWidget-title',
- position: 'bottom',
- autoFocus: true,
- closeOnClickOutside: false
- } )
- .next( archiveLinkExists ? 'findOldConversations' : 'feedback' );
-
- if ( archiveLinkExists ) {
- tour.step( {
- name: 'findOldConversations',
- titlemsg: 'flow-guidedtour-optin-find-old-conversations',
- descriptionmsg: 'flow-guidedtour-optin-find-old-conversations-description',
- attachTo: '.flow-ui-boardDescriptionWidget-content',
+ tour
+ .firstStep( {
+ name: 'newTopic',
+ titlemsg: 'flow-guidedtour-optin-welcome',
+ description: $firstStepDescription[ 0 ].outerHTML,
+ attachTo: '.flow-ui-newTopicWidget .flow-ui-newTopicWidget-title',
position: 'bottom',
autoFocus: true,
closeOnClickOutside: false
} )
- .next( 'feedback' )
- .back( 'newTopic' );
+ .next( archiveLinkExists ? 'findOldConversations' : 'feedback' );
+
+ if ( archiveLinkExists ) {
+ tour
+ .step( {
+ name: 'findOldConversations',
+ titlemsg: 'flow-guidedtour-optin-find-old-conversations',
+ descriptionmsg: 'flow-guidedtour-optin-find-old-conversations-description',
+ attachTo: '.flow-ui-boardDescriptionWidget-content',
+ position: 'bottom',
+ autoFocus: true,
+ closeOnClickOutside: false
+ } )
+ .next( 'feedback' )
+ .back( 'newTopic' );
}
- tour.step( {
- name: 'feedback',
- titlemsg: 'flow-guidedtour-optin-feedback',
- descriptionmsg: 'flow-guidedtour-optin-feedback-description',
- attachTo: '#pt-betafeatures',
- position: 'bottom',
- autoFocus: true,
- closeOnClickOutside: false
- } )
- .back( archiveLinkExists ? 'findOldConversations' : 'newTopic' );
+ tour
+ .step( {
+ name: 'feedback',
+ titlemsg: 'flow-guidedtour-optin-feedback',
+ descriptionmsg: 'flow-guidedtour-optin-feedback-description',
+ attachTo: '#pt-betafeatures',
+ position: 'bottom',
+ autoFocus: true,
+ closeOnClickOutside: false
+ } )
+ .back( archiveLinkExists ? 'findOldConversations' : 'newTopic' );
}( window, document, jQuery, mediaWiki, mediaWiki.guidedTour ) );
diff --git a/Flow/package.json b/Flow/package.json
index b8451278..48626ae5 100644
--- a/Flow/package.json
+++ b/Flow/package.json
@@ -8,14 +8,15 @@
"doc": "jsduck"
},
"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": "2.1.0",
- "grunt-jsonlint": "1.0.4",
- "grunt-tyops": "0.1.0"
+ "eslint-config-wikimedia": "0.5.0",
+ "grunt": "1.0.1",
+ "grunt-banana-checker": "0.5.0",
+ "grunt-contrib-watch": "1.0.0",
+ "grunt-eslint": "20.0.0",
+ "grunt-jsonlint": "1.1.0",
+ "grunt-stylelint": "0.8.0",
+ "grunt-tyops": "0.1.0",
+ "stylelint": "7.8.0",
+ "stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/Flow/phpcs.xml b/Flow/phpcs.xml
new file mode 100644
index 00000000..c45fa362
--- /dev/null
+++ b/Flow/phpcs.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
+ <exclude name="Generic.Files.LineLength.TooLong" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationProtected" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
+ <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.Commenting.FunctionComment.ParamNameNoMatch" />
+ <exclude name="MediaWiki.Commenting.FunctionComment.WrongStyle" />
+ <exclude name="MediaWiki.ControlStructures.AssignmentInControlStructures.AssignmentInControlStructures" />
+ <exclude name="MediaWiki.Files.ClassMatchesFilename.NotMatch" />
+ <exclude name="MediaWiki.Files.ClassMatchesFilename.WrongCase" />
+ <exclude name="MediaWiki.Files.OneClassPerFile.MultipleFound" />
+ <exclude name="MediaWiki.WhiteSpace.SpaceBeforeSingleLineComment.NewLineComment"/>
+ <exclude name="MediaWiki.Usage.DbrQueryUsage.DbrQueryFound"/>
+ <exclude name="MediaWiki.Usage.ExtendClassUsage.FunctionVarUsage"/>
+ </rule>
+ <rule ref="MediaWiki.NamingConventions.PrefixedGlobalFunctions">
+ <properties>
+ <property name="ignoreList" type="array" value="query_revisions,parsoid_to_wikitext,truncate" />
+ </properties>
+ </rule>
+ <file>.</file>
+ <arg name="extensions" value="php,php5,inc"/>
+ <arg name="encoding" value="UTF-8"/>
+ <exclude-pattern>handlebars</exclude-pattern>
+</ruleset>
diff --git a/Flow/scripts/gen-autoload.php b/Flow/scripts/gen-autoload.php
index 9ea48abe..83db166b 100644
--- a/Flow/scripts/gen-autoload.php
+++ b/Flow/scripts/gen-autoload.php
@@ -1,22 +1,41 @@
<?php
-require_once __DIR__ . '/../../../includes/utils/AutoloadGenerator.php';
+require_once getenv( 'MW_INSTALL_PATH' ) !== false
+ ? getenv( 'MW_INSTALL_PATH' ) . '/maintenance/Maintenance.php'
+ : __DIR__ . '/../../../maintenance/Maintenance.php';
-function main() {
- $base = dirname( __DIR__ );
- $generator = new AutoloadGenerator( $base );
- foreach ( array( 'includes', 'tests/phpunit', 'vendor' ) as $dir ) {
- $generator->readDir( $base . '/' . $dir );
- }
- foreach ( glob( $base . '/*.php' ) as $file ) {
- $generator->readFile( $file );
+/**
+ * Generates Flow autoload info
+ */
+
+class GenerateFlowAutoload extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Generates Flow autoload data';
}
- // read entire maint dir, move helper to includes? to core?
- $generator->readFile( $base . '/maintenance/MaintenanceDebugLogger.php' );
- $generator->generateAutoload( basename( __DIR__ ) . '/' . basename( __FILE__ ) );
+ public function execute() {
+ $base = dirname( __DIR__ );
+ $generator = new AutoloadGenerator( $base );
+ foreach ( [ 'includes', 'tests/phpunit', 'vendor' ] as $dir ) {
+ $generator->readDir( $base . '/' . $dir );
+ }
+ foreach ( glob( $base . '/*.php' ) as $file ) {
+ $generator->readFile( $file );
+ }
+ // read entire maint dir, move helper to includes? to core?
+ $generator->readFile( $base . '/maintenance/MaintenanceDebugLogger.php' );
+
+ $target = $generator->getTargetFileInfo();
- echo "Done.\n\n";
+ file_put_contents(
+ $target['filename'],
+ $generator->getAutoload( basename( __DIR__ ) . '/' . basename( __FILE__ ) )
+ );
+
+ echo "Done.\n\n";
+ }
}
-main();
+$maintClass = "GenerateFlowAutoload";
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/Flow/scripts/generatecss.php b/Flow/scripts/generatecss.php
index 22e2a28a..ec09d1c5 100644
--- a/Flow/scripts/generatecss.php
+++ b/Flow/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/Flow/scripts/hooks-shared.sh b/Flow/scripts/hooks-shared.sh
index 617b4a7b..2903bcd3 100644
--- a/Flow/scripts/hooks-shared.sh
+++ b/Flow/scripts/hooks-shared.sh
@@ -19,18 +19,22 @@ is_vagrant() {
make() {
if is_vagrant; then
- echo 'git hooks: Attempting to ssh into vagrant'
+ echo 'git hooks: Attempting to ssh into Vagrant'
vagrant ssh -- cd /vagrant/mediawiki/extensions/Flow '&&' /bin/echo 'git hooks: Running commands inside Vagrant' '&&' sudo -u www-data make $* || exit 1
else
/usr/bin/env make $* || exit 1
fi
}
+list_files_changed_in_commit() {
+ git diff --name-only --cached | grep -E "$1"
+}
+
file_changed_in_commit() {
- git diff --name-only --cached | grep -P "$1" 2>&1 >/dev/null
+ list_files_changed_in_commit "$1" 2>&1 > /dev/null
}
file_changed_in_head() {
- git diff-tree --no-commit-id --name-only -r HEAD | grep -P "$1" 2>&1 >/dev/null
+ git diff-tree --no-commit-id --name-only -r HEAD | grep -E "$1" 2>&1 >/dev/null
}
diff --git a/Flow/scripts/one-class-per-file.php b/Flow/scripts/one-class-per-file.php
index 276c4efa..5764c26f 100644
--- a/Flow/scripts/one-class-per-file.php
+++ b/Flow/scripts/one-class-per-file.php
@@ -4,12 +4,12 @@
// vendor manually
require __DIR__ . '/../vendor/PHP-Parser/lib/bootstrap.php';
-$wgAutoloadClasses = array();
+$wgAutoloadClasses = [];
require __DIR__ . '/../autoload.php';
class OneClassPerFile {
- public function __construct( PhpParser\Parser $parser) {
+ public function __construct( PhpParser\Parser $parser ) {
$this->parser = $parser;
}
@@ -36,7 +36,7 @@ class OneClassPerFile {
}
protected function getClasses( $stmt ) {
- $classes = array();
+ $classes = [];
foreach ( $stmt->stmts as $stmt ) {
if (
$stmt instanceof PhpParser\Node\Stmt\Interface_
@@ -74,12 +74,12 @@ class OneClassPerFile {
}
}
-$files = array();
+$files = [];
foreach ( $wgAutoloadClasses as $class => $file ) {
$files[$file][] = $class;
}
-$files = array_filter( $files, function( $classes ) {
+$files = array_filter( $files, function ( $classes ) {
return count( $classes ) > 1;
} );
diff --git a/Flow/scripts/pre-commit b/Flow/scripts/pre-commit
index a984fc21..44919fb5 100755
--- a/Flow/scripts/pre-commit
+++ b/Flow/scripts/pre-commit
@@ -18,7 +18,7 @@ if [ "$IGNORE_WHITESPACE" != "1" ]; then
git diff --cached --name-only | (while read f; do
ERROR=0
if grep -n '[[:space:]]$' "$f" ; then
- echo "'$f' has trailing whitespace\n" >&2
+ echo "'$f' has trailing whitespace\n" >&2
ERROR=1
fi
done; exit $ERROR)
@@ -39,7 +39,7 @@ fi
if file_changed_in_commit '\.js$'; then
if [ "$IGNORE_JSHINT" != "1" ]; then
- COMMANDS="grunt $COMMANDS"
+ COMMANDS="grunt jsduck $COMMANDS"
fi
fi
diff --git a/Flow/tests/browser/ci.yml b/Flow/tests/browser/ci.yml
new file mode 100644
index 00000000..c2eca934
--- /dev/null
+++ b/Flow/tests/browser/ci.yml
@@ -0,0 +1,9 @@
+BROWSER:
+ - chrome
+ - firefox
+
+MEDIAWIKI_ENVIRONMENT:
+ - beta
+
+PLATFORM:
+ - Linux
diff --git a/Flow/tests/browser/environments.yml b/Flow/tests/browser/environments.yml
index 98b76d39..d9d3880a 100644
--- a/Flow/tests/browser/environments.yml
+++ b/Flow/tests/browser/environments.yml
@@ -23,19 +23,19 @@ mw-vagrant-guest:
mediawiki_url: http://127.0.0.1/wiki/
local:
- mediawiki_user: Admin
+ mediawiki_user: Selenium Flow user
mediawiki_password: vagrant
mediawiki_user_b: Selenium Flow user 2
- mediawiki_url: http://127.0.0.1:8080/wiki/
+ mediawiki_url: http://dev.wiki.local.wmftest.net:8080/wiki/
beta:
- mediawiki_url: http://en.wikipedia.beta.wmflabs.org/wiki/
+ mediawiki_url: https://en.wikipedia.beta.wmflabs.org/wiki/
mediawiki_user: Selenium_user
mediawiki_user_b: Selenium Flow user 2
# mediawiki_password: SET THIS IN THE ENVIRONMENT!
test2:
- mediawiki_url: http://test2.wikipedia.org/wiki/
+ mediawiki_url: https://test2.wikipedia.org/wiki/
mediawiki_user: Selenium_user
# mediawiki_password: SET THIS IN THE ENVIRONMENT!
diff --git a/Flow/tests/browser/features/action_menu_permalink.feature b/Flow/tests/browser/features/action_menu_permalink.feature
index bd4fb843..f285f4d1 100644
--- a/Flow/tests/browser/features/action_menu_permalink.feature
+++ b/Flow/tests/browser/features/action_menu_permalink.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Actions menu Permalink
Background:
diff --git a/Flow/tests/browser/features/anon_interface.feature b/Flow/tests/browser/features/anon_interface.feature
index 25b20493..63651406 100644
--- a/Flow/tests/browser/features/anon_interface.feature
+++ b/Flow/tests/browser/features/anon_interface.feature
@@ -1,10 +1,8 @@
-@chrome @firefox @internet_explorer_10
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox
Feature: Check the interface for anonymous users
Scenario: Anon does not see block or actions
- Given there is a new topic
+ Given there is a new topic
When I am on Flow page
Then I see a flow creator element
And the block author link should not be visible
diff --git a/Flow/tests/browser/features/categories.feature b/Flow/tests/browser/features/categories.feature
new file mode 100644
index 00000000..74854acc
--- /dev/null
+++ b/Flow/tests/browser/features/categories.feature
@@ -0,0 +1,22 @@
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
+Feature: Categories
+
+ Assumes Flow is enabled for the Flow_test_talk namespace.
+
+ Background:
+ Given I am on a new board
+
+ Scenario: Add a category to new board
+ When I add category "Footegory" to the description
+ Then the categories contain "Footegory"
+
+ Scenario: Add multiple categories to new board
+ When I add categories "Footegory" and "Mootegory" to the description
+ Then the categories contain "Footegory"
+ And the categories contain "Mootegory"
+
+ Scenario: Remove categories from a new board
+ Given the board contains categories "Footegory" and "Mootegory"
+ When I remove category "Footegory" from the description
+ Then the categories do not contain "Footegory"
+ And the categories contain "Mootegory"
diff --git a/Flow/tests/browser/features/description.feature b/Flow/tests/browser/features/description.feature
index cdc19764..f4152c74 100644
--- a/Flow/tests/browser/features/description.feature
+++ b/Flow/tests/browser/features/description.feature
@@ -1,5 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Board description
Assumes Flow is enabled for the Flow_test_talk namespace.
@@ -14,6 +13,7 @@ Feature: Board description
When I set the description to "first version"
Then the description should be "first version"
+ @integration
Scenario: Edit the description on an existing board
Given I set the description to "first version"
When I set the description to "second version"
diff --git a/Flow/tests/browser/features/edit_existing.feature b/Flow/tests/browser/features/edit_existing.feature
index 5c1282ab..97852db6 100644
--- a/Flow/tests/browser/features/edit_existing.feature
+++ b/Flow/tests/browser/features/edit_existing.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Edit existing title
Background:
diff --git a/Flow/tests/browser/features/flow_in_recent_changes.feature b/Flow/tests/browser/features/flow_in_recent_changes.feature
index 6858665d..52790fb4 100644
--- a/Flow/tests/browser/features/flow_in_recent_changes.feature
+++ b/Flow/tests/browser/features/flow_in_recent_changes.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Flow updates are in Recent Changes
Background:
diff --git a/Flow/tests/browser/features/flow_logged_in.feature b/Flow/tests/browser/features/flow_logged_in.feature
index c0f925db..2c51795d 100644
--- a/Flow/tests/browser/features/flow_logged_in.feature
+++ b/Flow/tests/browser/features/flow_logged_in.feature
@@ -1,6 +1,4 @@
-@chrome @firefox
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Create new topic logged in
It requires the cldr extension, a "Flow QA" page, and a "Selenium user" who has
diff --git a/Flow/tests/browser/features/flow_no_javascript.feature b/Flow/tests/browser/features/flow_no_javascript.feature
index 9932bc98..71390ff4 100644
--- a/Flow/tests/browser/features/flow_no_javascript.feature
+++ b/Flow/tests/browser/features/flow_no_javascript.feature
@@ -1,9 +1,8 @@
-@firefox
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Basic site for legacy devices
Background:
- Given I am using user agent "Mozilla/4.0 (compatible; MSIE 5.5b1; Mac_PowerPC)"
+ Given I am using a nojs browser
And I am on a Flow page without JavaScript
Scenario: I post a new topic without JavaScript
diff --git a/Flow/tests/browser/features/moderation.feature b/Flow/tests/browser/features/moderation.feature
index 67114901..39caf126 100644
--- a/Flow/tests/browser/features/moderation.feature
+++ b/Flow/tests/browser/features/moderation.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Moderation
Background:
diff --git a/Flow/tests/browser/features/new_topic.feature b/Flow/tests/browser/features/new_topic.feature
index 2eef3630..37d0111b 100644
--- a/Flow/tests/browser/features/new_topic.feature
+++ b/Flow/tests/browser/features/new_topic.feature
@@ -1,11 +1,15 @@
-@chrome @firefox @internet_explorer_10
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Creating a new topic
- Background:
- Given I am on Flow page
-
Scenario: Add new Flow topic as anonymous user
When I have created a Flow topic with title "Anonymous user topic creation"
Then the top post should have a heading which contains "Anonymous user topic creation"
And the top post should have content which contains "Anonymous user topic creation"
+
+ Scenario: Add new Flow topic with topic-title-wikitext
+ Given I am logged in
+ And I am on a new board
+ When I have created a Flow topic containing the wikitext "[[Main Page]] [[Red link cIIBeqoNg8Bxo]] [[Media:Earth.jpg]] [http://example.com Example]"
+ Then the top post should have a heading which contains "\[http://example.com Example\]"
+ And there should be a link to the main page in the first topic title
+ And there should be a red link in the first topic title
diff --git a/Flow/tests/browser/features/opt_in.feature b/Flow/tests/browser/features/opt_in.feature
index f8ddd0a0..2e36b5ee 100644
--- a/Flow/tests/browser/features/opt_in.feature
+++ b/Flow/tests/browser/features/opt_in.feature
@@ -1,6 +1,4 @@
-@chrome @firefox
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Opt-in Flow beta feature
Depends on having $wgFlowEnableOptInBetaFeature = true
@@ -14,11 +12,13 @@ Feature: Opt-in Flow beta feature
Then my talk page is a Flow board
And a notification tells me about it
+ @integration
Scenario: Opt-in: I have a wikitext talk page
- Given my talk page has wiktext content
+ Given my talk page has wikitext content
When I enable Flow beta feature
Then my talk page is a Flow board
And my flow board contains a link to my archived talk page
+ And the board description contains the templates from my talk page
And my previous talk page is archived
Scenario: Opt-out: I didn't have a talk page
@@ -28,7 +28,7 @@ Feature: Opt-in Flow beta feature
And my talk page is deleted without redirect
Scenario: Opt-out: I had a wikitext talk page
- Given my talk page has wiktext content
+ Given my talk page has wikitext content
And I have Flow beta feature enabled
When I disable Flow beta feature
Then my wikitext talk page is restored
diff --git a/Flow/tests/browser/features/post_links.feature b/Flow/tests/browser/features/post_links.feature
index 54cbe52f..91b7bc23 100644
--- a/Flow/tests/browser/features/post_links.feature
+++ b/Flow/tests/browser/features/post_links.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Follow user links
Background:
@@ -9,4 +7,4 @@ Feature: Follow user links
Scenario: User links takes me to the user page
Given I am on Flow page
When I click the flow creator element
- Then I am on my user page \ No newline at end of file
+ Then I am on my user page
diff --git a/Flow/tests/browser/features/preload.feature b/Flow/tests/browser/features/preload.feature
index 7d7de47d..29aa412f 100644
--- a/Flow/tests/browser/features/preload.feature
+++ b/Flow/tests/browser/features/preload.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: preload
Background:
diff --git a/Flow/tests/browser/features/reopen_topic.feature b/Flow/tests/browser/features/reopen_topic.feature
index e64556e6..9a499d35 100644
--- a/Flow/tests/browser/features/reopen_topic.feature
+++ b/Flow/tests/browser/features/reopen_topic.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Reopen a resolved topic
Background:
@@ -8,10 +6,11 @@ Feature: Reopen a resolved topic
And I am logged in
And I am on Flow page
+ @integration
Scenario: Reopening a resolved topic and changing the summary
Given I mark the first topic as resolved
And I summarize as "answer when resolving"
When I reopen the first topic
And I summarize as "answer when reopening"
Then the first topic is open
- And the first topic is summarized as "answer when reopening" \ No newline at end of file
+ And the first topic is summarized as "answer when reopening"
diff --git a/Flow/tests/browser/features/reply.feature b/Flow/tests/browser/features/reply.feature
index b3614b92..70fb3976 100644
--- a/Flow/tests/browser/features/reply.feature
+++ b/Flow/tests/browser/features/reply.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Replying
Scenario: I can reply
diff --git a/Flow/tests/browser/features/reply_moderation.feature b/Flow/tests/browser/features/reply_moderation.feature
index d872112a..23d1830b 100644
--- a/Flow/tests/browser/features/reply_moderation.feature
+++ b/Flow/tests/browser/features/reply_moderation.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Reply moderation
Background:
diff --git a/Flow/tests/browser/features/resolve_topic.feature b/Flow/tests/browser/features/resolve_topic.feature
new file mode 100644
index 00000000..16df2acb
--- /dev/null
+++ b/Flow/tests/browser/features/resolve_topic.feature
@@ -0,0 +1,30 @@
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
+Feature: Mark topic as resolved
+
+ Background:
+ Given there is a new topic
+ And I am logged in
+ And I am on Flow page
+
+ Scenario: Resolving a topic without a summary
+ When I mark the first topic as resolved
+ And I skip the summary
+ Then the first topic is resolved
+
+ Scenario: Resolving a topic and adding a summary
+ When I mark the first topic as resolved
+ And I summarize as "the answer is 42"
+ Then the first topic is resolved with summary "the answer is 42"
+
+ Scenario: Resolving a topic and keeping the summary
+ Given I summarize the first topic as "this answer should be kept"
+ When I mark the first topic as resolved
+ And I keep the summary
+ Then the first topic is resolved with summary "this answer should be kept"
+
+ @integration
+ Scenario: Resolving a topic and updating the summary
+ Given I summarize the first topic as "this answer should be changed"
+ When I mark the first topic as resolved
+ And I summarize as "this is the new answer"
+ Then the first topic is resolved with summary "this is the new answer"
diff --git a/Flow/tests/browser/features/sorting_topics.feature b/Flow/tests/browser/features/sorting_topics.feature
index 929faaae..35c68b57 100644
--- a/Flow/tests/browser/features/sorting_topics.feature
+++ b/Flow/tests/browser/features/sorting_topics.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10 @phantomjs
-@clean
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox
Feature: Sorting topics
Background:
diff --git a/Flow/tests/browser/features/special_enableflow.feature b/Flow/tests/browser/features/special_enableflow.feature
index d8425126..a272a27a 100644
--- a/Flow/tests/browser/features/special_enableflow.feature
+++ b/Flow/tests/browser/features/special_enableflow.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Flow Special:EnableFlow enables new flow boards
Assumes Template:Wikitext_talk_page_converted_to_Flow exists
@@ -23,11 +21,13 @@ Feature: Flow Special:EnableFlow enables new flow boards
And The page I am on is a Flow board
And I see the custom header
+ @integration
Scenario: Enabling a Flow page on existing page
Given I have an existing talk page
When I enable a new Flow board on the talk page
Then I get confirmation for enabling a new Flow board
And I click on the new Flow board link
And The page I am on is a Flow board
+ And the board description contains the templates from my talk page
And I click the archive link
And The archive contains the original text
diff --git a/Flow/tests/browser/features/step_definitions/categories_steps.rb b/Flow/tests/browser/features/step_definitions/categories_steps.rb
new file mode 100644
index 00000000..739673b3
--- /dev/null
+++ b/Flow/tests/browser/features/step_definitions/categories_steps.rb
@@ -0,0 +1,47 @@
+When(/^I add category "(.*?)" to the description$/) do |category_text|
+ on(FlowPage) do |page|
+ page.description.edit
+ page.description.editor_element.when_present.send_keys '[[Category:' + category_text + ']]'
+ page.description.save
+ page.description.categories_element.when_present
+ end
+end
+
+When(/^I add categories "(.*?)" and "(.*?)" to the description$/) do |cat1, cat2|
+ on(FlowPage) do |page|
+ page.description.edit
+ page.description.editor_element.when_present.send_keys '[[Category:' +
+ cat1 + ']]' + "\n" \
+ '[[Category:' + cat2 + ']]'
+ page.description.save
+ page.description.categories_element.when_present
+ end
+end
+
+When(/^I remove category "(.*?)" from the description$/) do |category_text|
+ on(FlowPage) do |page|
+ page.description.edit
+ text = page.description.editor_element.when_present.text
+ text.slice! "[[Category:#{category_text}]]"
+ page.description.editor_element.when_present.clear
+ page.description.editor_element.when_present.send_keys text
+ page.description.save
+ page.description.categories_element.when_present
+ end
+end
+
+When(/^the board contains categories "(.*?)" and "(.*?)"$/) do |cat1, cat2|
+ step "I add categories \"#{cat1}\" and \"#{cat2}\" to the description"
+end
+
+When(/^the categories contain "(.*?)"$/) do |category_text|
+ on(FlowPage) do |page|
+ page.description.category_item(category_text).exists?
+ end
+end
+
+When(/^the categories do not contain "(.*?)"$/) do |category_text|
+ on(FlowPage) do |page|
+ expect(page.description.category_item(category_text)).not_to exist
+ end
+end
diff --git a/Flow/tests/browser/features/step_definitions/edit_existing_steps.rb b/Flow/tests/browser/features/step_definitions/edit_existing_steps.rb
index a9d9bc8c..213545c9 100644
--- a/Flow/tests/browser/features/step_definitions/edit_existing_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/edit_existing_steps.rb
@@ -26,8 +26,8 @@ When(/^I edit the title field with "(.+)"$/) do |edited_title|
on(FlowPage) do |page|
@edited_topic_string = edited_title + @random_string
# Take focus away from menu
- page.title_edit_element.when_present.click
- page.title_edit_element.when_present.send_keys(@edited_topic_string)
+ page.title_edit_element.when_present.when_enabled.click
+ page.title_edit = @edited_topic_string
end
end
diff --git a/Flow/tests/browser/features/step_definitions/flow_in_recent_changes_steps.rb b/Flow/tests/browser/features/step_definitions/flow_in_recent_changes_steps.rb
index 7828377b..4b55c50e 100644
--- a/Flow/tests/browser/features/step_definitions/flow_in_recent_changes_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/flow_in_recent_changes_steps.rb
@@ -3,9 +3,13 @@ When(/^I navigate to the Recent Changes page$/) do
end
Then(/^the new topic should be in the Recent Changes page$/) do
- expect(on(RecentChangesPage).recent_changes_element.when_present.text).to match @topic_string
+ on(RecentChangesPage) do |page|
+ page.refresh_until { page.recent_changes.match @topic_string }
+ end
end
Then(/^the new title should be in the Recent Changes page$/) do
- expect(on(RecentChangesPage).recent_changes_element.when_present.text).to match @edited_topic_string
+ on(RecentChangesPage) do |page|
+ page.refresh_until { page.recent_changes.match @edited_topic_string }
+ end
end
diff --git a/Flow/tests/browser/features/step_definitions/flow_no_javascript_steps.rb b/Flow/tests/browser/features/step_definitions/flow_no_javascript_steps.rb
index 4cc5a43a..21b07cdd 100644
--- a/Flow/tests/browser/features/step_definitions/flow_no_javascript_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/flow_no_javascript_steps.rb
@@ -7,8 +7,11 @@ Given(/^I am on a Flow page without JavaScript$/) do
visit(FlowPage)
end
-Given(/^I am using user agent "(.+)"$/) do |user_agent|
- browser_factory.override(browser_user_agent: user_agent)
+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
When(/^I click Add topic no javascript$/) do
diff --git a/Flow/tests/browser/features/step_definitions/flow_steps.rb b/Flow/tests/browser/features/step_definitions/flow_steps.rb
index 36590e68..940fb9b6 100644
--- a/Flow/tests/browser/features/step_definitions/flow_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/flow_steps.rb
@@ -52,6 +52,8 @@ When(/^I click New topic save$/) do
end
end
+# This will only work for titles without wikitext
+# due to topic_with_title
When(/^topic "(.+)" is saved$/) do |title|
on(FlowPage) do |page|
page.new_topic_save_element.when_not_visible(10)
@@ -180,8 +182,10 @@ end
Then(/^the top post should have a heading which contains "(.+)"$/) do |text|
on(FlowPage) do |page|
- page.flow_first_topic_heading_element.when_present
- expect(page.flow_first_topic_heading).to match(text)
+ page.wait_until do
+ actual_text = page.flow_first_topic_heading_element.when_present.text
+ actual_text.match text
+ end
end
end
diff --git a/Flow/tests/browser/features/step_definitions/new_topic_steps.rb b/Flow/tests/browser/features/step_definitions/new_topic_steps.rb
new file mode 100644
index 00000000..aa96db0a
--- /dev/null
+++ b/Flow/tests/browser/features/step_definitions/new_topic_steps.rb
@@ -0,0 +1,20 @@
+# This is like 'I have created a Flow topic with title', but doesn't
+# expect the input to be a one-to-one mapping to the output. The
+# problematic sub-step of that is "topic \"#{title}\" is saved"
+Given(/^I have created a Flow topic containing the wikitext "(.+)"$/) do |title|
+ step "I type \"#{title}\" into the new topic title field"
+ step "I type \"#{title}\" into the new topic content field"
+ step "I click New topic save"
+end
+
+Then(/^there should be a link to the main page in the first topic title$/) do
+ on(FlowPage) do |page|
+ page.flow_first_topic_main_page_link_element.when_present
+ end
+end
+
+Then(/^there should be a red link in the first topic title$/) do
+ on(FlowPage) do |page|
+ page.flow_first_topic_red_link_element.when_present
+ end
+end
diff --git a/Flow/tests/browser/features/step_definitions/opt_in_steps.rb b/Flow/tests/browser/features/step_definitions/opt_in_steps.rb
index 5adb12e8..600c5a0e 100644
--- a/Flow/tests/browser/features/step_definitions/opt_in_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/opt_in_steps.rb
@@ -17,14 +17,18 @@ end
Then(/^my talk page is a Flow board$/) do
visit(UserTalkPage, using_params: { username: @username }) do |page|
- page.flow.board_element.when_present
+ page.refresh_until { page.flow.board_element.visible? }
end
end
-Given(/^my talk page has wiktext content$/) do
+Given(/^my talk page has wikitext content$/) do
talk_page = "User_talk:#{@username}"
- @talk_page_content = 'this is the content of my talk page'
- api.create_page talk_page, @talk_page_content
+ @talk_page_content = "this is the content of my talk page"
+ content = @talk_page_content
+ content += "\n{{template_before_first_heading}}"
+ content += "\n== this is the first section =="
+ content += "\n{{template_after_first_heading}}"
+ api.create_page talk_page, content
end
Then(/^my previous talk page is archived$/) do
@@ -33,6 +37,9 @@ Then(/^my previous talk page is archived$/) do
visit(WikiPage, using_params: { page: archive_name }) do |page|
expect(page.content_element.when_present.text).to match @talk_page_content
expect(page.content_element.when_present.text).to match archive_template
+
+ expect(page.content).to match 'This page is an archive.'
+ expect(page.content).to_not match 'Previous discussion was archived at'
end
end
@@ -50,43 +57,53 @@ When(/^I disable Flow beta feature$/) do
end
Then(/^my wikitext talk page is restored$/) do
- talk_page_link = "User_talk:#{@username}".gsub '_', ' '
+ flow_archive_link = "User_talk:#{@username}/Flow_Archive_1".tr '_', ' '
visit(UserTalkPage, using_params: { username: @username }) do |page|
- page.content_element.when_present
- expect(page.content).to match @talk_page_content
- expect(page.content).to_not match talk_page_link
+ page.refresh_until do
+ page.content.match @talk_page_content
+ end
+ expect(page.content).to_not match 'This page is an archive.'
+ expect(page.content).to match 'Previous discussion was archived at'
+ expect(page.content).to match flow_archive_link
end
end
Then(/^my Flow board is archived$/) do
flow_archive_name = "./User_talk:#{@username}/Flow_Archive_1"
- talk_page_link = "User_talk:#{@username}".gsub '_', ' '
visit(WikiPage, using_params: { page: flow_archive_name }) do |page|
+ page.refresh_until { page.flow.board_element.visible? }
page.flow.board_element.when_present
- expect(page.flow.header).to_not match talk_page_link
+ expect(page.flow.header).to match 'This page is an archive.'
+ expect(page.flow.header).to_not match 'Previous discussion was archived at'
end
end
Given(/^I have used the Flow beta feature before$/) do
- step 'my talk page has wiktext content'
+ step 'my talk page has wikitext content'
step 'I enable Flow beta feature'
+ step 'my talk page is a Flow board'
@topic_title = @data_manager.get 'title'
api.action('flow', submodule: 'new-topic', page: "User_talk:#{@username}", nttopic: @topic_title, ntcontent: 'created via API')
step 'I disable Flow beta feature'
+ step 'my wikitext talk page is restored'
end
Then(/^my talk page is my old Flow board$/) do
- archive_name = "User_talk:#{@username}/Archive_1".gsub '_', ' '
- visit(UserTalkPage, using_params: { username: @username }) do |page|
- expect(page.content_element.when_present.text).to match @topic_title
+ archive_name = "User_talk:#{@username}/Archive_1".tr '_', ' '
+ visit(WikiPage, using_params: { page: "./User_talk:#{@username}" }) do |page|
+ page.refresh_until { page.flow.board_element.visible? }
+ page.flow.board_element.when_present
+
expect(page.flow.header).to match archive_name
+ expect(page.flow.header).to match 'Previous discussion was archived at'
+ expect(page.flow.header).to_not match 'This page is an archive.'
end
end
Then(/^my flow board contains a link to my archived talk page$/) do
- archive_name = "User_talk:#{@username}/Archive_1".gsub '_', ' '
+ archive_name = "User_talk:#{@username}/Archive_1".tr '_', ' '
visit(UserTalkPage, using_params: { username: @username }) do |page|
- page.flow.board_element.when_present
+ page.refresh_until { page.flow.board_element.visible? }
expect(page.flow.header).to match archive_name
end
end
diff --git a/Flow/tests/browser/features/step_definitions/resolve_reopen_steps.rb b/Flow/tests/browser/features/step_definitions/resolve_reopen_steps.rb
index 1b3235aa..3f0c681d 100644
--- a/Flow/tests/browser/features/step_definitions/resolve_reopen_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/resolve_reopen_steps.rb
@@ -65,6 +65,14 @@ When(/^I click the summarize menu item$/) do
end
end
+When(/^I click the edit summary menu item$/) do
+ on(FlowPage) do |page|
+ menu = page.topic_actions_link_element
+ option = page.topic_edit_summary_button_element
+ page.select_menu_option menu, option
+ end
+end
+
Then(/^the first topic is summarized as "(.*?)"$/) do |summary_text|
on(FlowPage) do |page|
expect(page.summary_content_element.when_present.text).to eq(summary_text)
@@ -88,6 +96,12 @@ Given(/^I summarize the first topic as "(.*?)"$/) do |summary_text|
step 'I click the update summary button'
end
+Given(/^I re-summarize the first topic as "(.*?)"$/) do |summary_text|
+ step 'I click the edit summary menu item'
+ step "I enter \"#{summary_text}\" as summary"
+ step 'I click the update summary button'
+end
+
When(/^I summarize as "(.*?)"$/) do |summary_text|
step "I enter \"#{summary_text}\" as summary"
step 'I click the update summary button'
diff --git a/Flow/tests/browser/features/step_definitions/special_enable_flow_steps.rb b/Flow/tests/browser/features/step_definitions/special_enable_flow_steps.rb
index 82c392d0..662510e7 100644
--- a/Flow/tests/browser/features/step_definitions/special_enable_flow_steps.rb
+++ b/Flow/tests/browser/features/step_definitions/special_enable_flow_steps.rb
@@ -4,7 +4,11 @@ end
Given(/^I have an existing talk page$/) do
@new_board_page = @data_manager.get_talk 'Test_Prefilled_Random_Board'
- api.create_page @new_board_page, '<p class="flow-test-archive-content">Some wikitext here.</p>'
+ content = "<p class=\"flow-test-archive-content\">Some wikitext here.</p>"
+ content += "\n\n{{template_before_first_heading}}"
+ content += "\n\n== this is the first section =="
+ content += "\n\n{{template_after_first_heading}}"
+ api.create_page @new_board_page, content
end
When(/^I enable a new Flow board on the talk page$/) do
@@ -19,7 +23,7 @@ end
When(/^I enable a new Flow board on article (.*?)$/) do |article|
on(EnableFlowPage) do |page|
page.page_name_element.when_present.send_keys article
- page.submit
+ page.submit_element.when_present.click
end
end
@@ -64,3 +68,12 @@ Then(/^I see the custom header$/) do
page.description.content_element.when_present.text.should match @custom_header
end
end
+
+Then(/^the board description contains the templates from my talk page$/) do
+ on(AbstractFlowPage) do |page|
+ page.refresh_until { page.description.content_element.visible? }
+ description = page.description.content_element.when_present.text
+ expect(description).to match 'Template:Template before first heading'
+ expect(description).to_not match 'Template:Template after first heading'
+ end
+end
diff --git a/Flow/tests/browser/features/step_definitions/undo_actions.rb b/Flow/tests/browser/features/step_definitions/undo_actions.rb
new file mode 100644
index 00000000..95bc7cb3
--- /dev/null
+++ b/Flow/tests/browser/features/step_definitions/undo_actions.rb
@@ -0,0 +1,79 @@
+Given(/^I am on a Flow board "(.+)"$/) do |board_title|
+ visit(NewFlowPage, using_params: { pagetitle: board_title })
+end
+
+Given(/^I am on a new Flow board with description "(.*?)"$/) do |content|
+ @board_title = @data_manager.get 'Board_for_undo_actions'
+ api.action('flow',
+ submodule: 'edit-header',
+ page: 'Flow_test_talk:New_page_' + @board_title,
+ ehcontent: content,
+ ehformat: 'wikitext')
+ visit(NewFlowPage, using_params: { pagetitle: @board_title })
+end
+
+Given(/^I am on a new Flow board with topic content \"(.*?)\"$/) do |content|
+ @board_title = @data_manager.get 'Board_for_undo_actions'
+ topic_title = @data_manager.get 'Title_for_undo_actions'
+ api.action('flow',
+ submodule: 'new-topic',
+ page: 'Flow_test_talk:New_page_' + @board_title,
+ nttopic: topic_title,
+ ntcontent: content)
+ step "I am on a Flow board \"#{@board_title}\""
+ on(NewFlowPage) do |page|
+ page.refresh_until { page.topic_with_title(topic_title) }
+ end
+end
+
+When(/^I visit the new board history page$/) do
+ visit(BoardHistoryPage, using_params: { pagetitle: 'Flow_test_talk:New_page_' + @board_title })
+ on(BoardHistoryPage).flow_board_history_element.when_present
+end
+
+Given(/^I edit the topic with \"(.*?)\"$/) do |content|
+ step "I select Edit post"
+ step "I edit the post field with \"#{content}\""
+ step "I save the new post"
+end
+
+When(/^I click undo$/) do
+ on(TopicHistoryPage) do |page|
+ page.undo_link_element.when_present.click
+ end
+end
+
+When(/^I am on a Flow page$/) do
+ on(AbstractFlowPage) do |page|
+ page.description.content_element.when_present
+ end
+end
+
+When(/^I am on a Flow diff page$/) do
+ on(FlowDiffPage) do |page|
+ page.editor_element.when_present
+ end
+end
+
+When(/^I undo the latest action$/) do
+ step "I click undo"
+ step "I am on a Flow diff page"
+ step "I save the undo post"
+end
+
+When(/^I am on a Flow topic page$/) do
+ on(AbstractFlowPage) do |page|
+ page.flow_first_topic_element.when_present
+ end
+end
+
+When(/^I save the undo post/) do
+ on(FlowDiffPage) do |page|
+ page.undo_post_save_element.when_present.click
+ page.undo_post_save_element.when_not_present
+ end
+end
+
+Then(/^the saved undo post should contain "(.+)"$/) do |undo_text|
+ expect(on(FlowPage).flow_first_topic_body_element.when_present.text).to match(undo_text)
+end
diff --git a/Flow/tests/browser/features/summarize.feature b/Flow/tests/browser/features/summarize.feature
new file mode 100644
index 00000000..eaa93d7f
--- /dev/null
+++ b/Flow/tests/browser/features/summarize.feature
@@ -0,0 +1,13 @@
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
+Feature: Summarize
+
+ Background:
+ Given there is a new topic
+ And I am logged in
+ And I am on Flow page
+
+ Scenario: Summarize a topic
+ When I summarize the first topic as "first summary version"
+ Then the first topic is summarized as "first summary version"
+ When I re-summarize the first topic as "second summary version"
+ Then the first topic is summarized as "second summary version"
diff --git a/Flow/tests/browser/features/support/components/board_description.rb b/Flow/tests/browser/features/support/components/board_description.rb
index a4565336..e56b6f37 100644
--- a/Flow/tests/browser/features/support/components/board_description.rb
+++ b/Flow/tests/browser/features/support/components/board_description.rb
@@ -11,16 +11,21 @@ class BoardDescription
a(:toggle, class: "side-rail-toggle-button")
div(:editor_widget, class: 'flow-ui-boardDescriptionWidget-editor')
+ div(:categories, class: 'flow-ui-categoriesWidget')
def editor_element
visualeditor_or_textarea editor_widget_element
end
+ def category_item(itemName)
+ categories_element.link_element(text: itemName)
+ end
+
link(:save, text: /Save description.*/)
# If page has an archive template from a flow conversion
# find the link
link(:archive_link) do
- content_element.link_element
+ content_element.link_element(text: /Archive/)
end
end
diff --git a/Flow/tests/browser/features/support/env.rb b/Flow/tests/browser/features/support/env.rb
index 8e9b3f53..18ce345f 100644
--- a/Flow/tests/browser/features/support/env.rb
+++ b/Flow/tests/browser/features/support/env.rb
@@ -1,9 +1,10 @@
require 'mediawiki_selenium'
-require 'mediawiki_selenium/support'
+require 'mediawiki_selenium/cucumber'
+require 'mediawiki_selenium/pages'
require 'mediawiki_selenium/step_definitions'
-require_relative 'div_extension'
+require_relative 'extensions'
def env_or_default(key, default)
ENV[key].nil? ? default : ENV[key].to_i
diff --git a/Flow/tests/browser/features/support/extensions.rb b/Flow/tests/browser/features/support/extensions.rb
new file mode 100644
index 00000000..10ef890a
--- /dev/null
+++ b/Flow/tests/browser/features/support/extensions.rb
@@ -0,0 +1,48 @@
+require "watir/wait"
+
+module Watir
+ class Div
+ def clear
+ send_keys [:command, 'a'], :backspace
+ send_keys [:control, 'a'], :backspace
+ end
+ end
+
+ class TextArea
+ def enabled?
+ !disabled?
+ end
+
+ def text
+ value
+ end
+ end
+end
+
+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
+
+module PageObject
+ module Elements
+ class TextArea
+ def when_enabled
+ wait_until { enabled? }
+ self
+ end
+ end
+
+ class TextField
+ def when_enabled
+ wait_until { enabled? }
+ self
+ end
+ end
+ end
+end
diff --git a/Flow/tests/browser/features/support/pages/abstract_flow_page.rb b/Flow/tests/browser/features/support/pages/abstract_flow_page.rb
index 28c615b7..f1d9fd80 100644
--- a/Flow/tests/browser/features/support/pages/abstract_flow_page.rb
+++ b/Flow/tests/browser/features/support/pages/abstract_flow_page.rb
@@ -6,6 +6,7 @@ class AbstractFlowPage
def select_menu_option(menu, option)
menu.when_present.click
+ wait_until { option.exists? }
option.scroll_into_view
menu.when_present.click
option.when_present.click
@@ -29,7 +30,7 @@ class AbstractFlowPage
# Dialogs
div(:dialog, css: ".flow-ui-modal")
- textarea(:dialog_input, name: "topic_reason")
+ text_field(:dialog_input, name: "topic_reason")
button(:dialog_cancel, css: "a.mw-ui-destructive:nth-child(2)")
button(:dialog_submit_delete, text: "Delete")
button(:dialog_submit_hide, text: "Hide")
@@ -54,6 +55,15 @@ class AbstractFlowPage
page.flow_first_topic_element.div_element(css: "div.flow-topic-titlebar div.flow-moderated-topic-title")
end
+ ## First post with link HTML in topic title
+ a(:flow_first_topic_main_page_link) do
+ h2_element(css: ".flow-topic-title", index: 0).link_element(href: %r{/wiki/Main_Page})
+ end
+
+ a(:flow_first_topic_red_link) do
+ h2_element(css: ".flow-topic-title", index: 0).link_element(class: 'new')
+ end
+
div(:flow_first_topic_original_post, css: ".flow-post", index: 0)
a(:flow_first_topic_original_post_edit) do |page|
page.flow_first_topic_original_post_element.link_element(text: "Edit")
@@ -66,7 +76,7 @@ class AbstractFlowPage
### Hover over username behaviour
span(:usertools, css: '.mw-usertoollinks')
a(:usertools_talk_link) do |page|
- page.usertools_element.link_element(text: 'Talk')
+ page.usertools_element.link_element(text: 'talk')
end
a(:usertools_block_user_link) do |page|
page.usertools_element.link_element(text: 'block')
@@ -124,10 +134,13 @@ class AbstractFlowPage
a(:topic_summarize_button) do |page|
page.topic_actions_menu_element.link_element(text: "Summarize")
end
+ a(:topic_edit_summary_button) do |page|
+ page.topic_actions_menu_element.link_element(text: "Edit the topic summary")
+ end
### Editing title of first topic
- text_field(:title_edit, css: ".flow-topic-titlebar form .mw-ui-input", index: 0)
- button(:change_title_save, css: ".flow-topic-titlebar form .mw-ui-constructive")
+ text_field(:title_edit, css: ".flow-ui-topicTitleWidget-titleInput input", index: 0)
+ a(:change_title_save, css: ".flow-ui-topicTitleWidget-saveButton a")
### Post meta actions
span(:post_meta_actions, css: ".flow-post .flow-post-meta-actions", index: 0)
@@ -145,17 +158,14 @@ class AbstractFlowPage
div(:summary_content) do |page|
page.summary_element.div_element(css: '.flow-topic-summary-content')
end
- button(:skip_summary_button) do |page|
- page.summary_element.button_element(text: 'Skip summary')
- end
- button(:cancel_summary_button) do |page|
- page.summary_element.button_element(text: 'Cancel')
- end
- button(:update_summary_button) do |page|
- page.summary_element.button_element(text: 'Update summary')
+ link(:skip_summary_button, text: 'Skip summary')
+ link(:cancel_summary_button) do |page|
+ page.summary_element.link_element(text: 'Cancel')
end
+ link(:update_summary_button, text: 'Update summary')
def edit_summary_element
- visualeditor_or_textarea '.flow-edit-form'
+ edit_summary_widget = div_element(class: 'flow-ui-editTopicSummaryWidget')
+ visualeditor_or_textarea edit_summary_widget
end
span(:first_topic_resolved_mark) do |page|
page.flow_first_topic_heading_element.span_element(css: '.mw-ui-icon-check')
@@ -168,16 +178,16 @@ class AbstractFlowPage
page.post_actions_menu_element.link_element(text: "Permalink")
end
a(:hide_button) do |page|
- page.post_actions_menu_element.link_element(title: "Hide")
+ page.post_actions_menu_element.link_element(text: "Hide")
end
a(:delete_button) do |page|
- page.post_actions_menu_element.link_element(title: "Delete")
+ page.post_actions_menu_element.link_element(text: "Delete")
end
a(:suppress_button) do |page|
- page.post_actions_menu_element.link_element(title: "Suppress")
+ page.post_actions_menu_element.link_element(text: "Suppress")
end
a(:edit_post_button) do |page|
- page.post_actions_menu_element.link_element(title: "Edit")
+ page.post_actions_menu_element.link_element(text: "Edit")
end
### Replies to top post
diff --git a/Flow/tests/browser/features/support/pages/board_history_page.rb b/Flow/tests/browser/features/support/pages/board_history_page.rb
index febd08ec..0cbcbd3e 100644
--- a/Flow/tests/browser/features/support/pages/board_history_page.rb
+++ b/Flow/tests/browser/features/support/pages/board_history_page.rb
@@ -1,7 +1,13 @@
class BoardHistoryPage
include PageObject
- page_url "Talk:Flow_QA?action=history"
+ page_url "./<%=params[:pagetitle] ? params[:pagetitle] + '?action=history' : 'Talk:Flow_QA?action=history' %>"
div(:flow_board_history, class: 'flow-board-history')
+
+ ul(:flow_board_history_moderation, class: 'flow-history-moderation-menu')
+
+ link(:undo_link) do
+ flow_board_history_moderation_element.link_element(text: /undo/)
+ end
end
diff --git a/Flow/tests/browser/features/support/pages/flow_diff_page.rb b/Flow/tests/browser/features/support/pages/flow_diff_page.rb
new file mode 100644
index 00000000..cfb36d2c
--- /dev/null
+++ b/Flow/tests/browser/features/support/pages/flow_diff_page.rb
@@ -0,0 +1,14 @@
+class FlowDiffPage
+ include PageObject
+ include FlowEditor
+
+ div(:editor_widget, class: 'flow-ui-editorWidget')
+
+ def editor_element
+ visualeditor_or_textarea editor_widget_element
+ end
+
+ button(:undo_post_save) do
+ editor_widget_element.link_element(css: '.flow-ui-editorControlsWidget-saveButton a')
+ end
+end
diff --git a/Flow/tests/browser/features/support/pages/flow_page.rb b/Flow/tests/browser/features/support/pages/flow_page.rb
index 9dbb7ce9..33b94763 100644
--- a/Flow/tests/browser/features/support/pages/flow_page.rb
+++ b/Flow/tests/browser/features/support/pages/flow_page.rb
@@ -1,4 +1,4 @@
class FlowPage < AbstractFlowPage
page_url 'Talk:Flow_QA'
- # MEDIAWIKI_URL must have this in $wgFlowOccupyNamespaces.
+ # MEDIAWIKI_URL must have this page as Flow.
end
diff --git a/Flow/tests/browser/features/support/pages/new_flow_page.rb b/Flow/tests/browser/features/support/pages/new_flow_page.rb
index e5fae180..0582e6b1 100644
--- a/Flow/tests/browser/features/support/pages/new_flow_page.rb
+++ b/Flow/tests/browser/features/support/pages/new_flow_page.rb
@@ -1,6 +1,7 @@
-class NewFlowPage
+class NewFlowPage < AbstractFlowPage
include PageObject
- # MEDIAWIKI_URL must have Flow_test_talk in $wgFlowOccupyNamespaces.
- page_url './Flow_test_talk:New_page_' + Random.srand.to_s
+
+ # MEDIAWIKI_URL must have Flow_test_talk as Flow in $wgNamespaceContentModels.
+ page_url "./Flow_test_talk:New_page_<%= params[:pagetitle] ? params[:pagetitle] : Random.srand.to_s %>"
end
diff --git a/Flow/tests/browser/features/support/pages/special_notifications_page.rb b/Flow/tests/browser/features/support/pages/special_notifications_page.rb
index 42166e87..c477d251 100644
--- a/Flow/tests/browser/features/support/pages/special_notifications_page.rb
+++ b/Flow/tests/browser/features/support/pages/special_notifications_page.rb
@@ -3,5 +3,5 @@ class SpecialNotificationsPage
page_url "Special:Notifications"
- div(:first_notification, class: 'mw-echo-content', index: 0)
+ div(:first_notification, class: 'mw-echo-ui-notificationItemWidget', index: 0)
end
diff --git a/Flow/tests/browser/features/support/pages/special_preferences_page.rb b/Flow/tests/browser/features/support/pages/special_preferences_page.rb
index 84445f10..928bbcca 100644
--- a/Flow/tests/browser/features/support/pages/special_preferences_page.rb
+++ b/Flow/tests/browser/features/support/pages/special_preferences_page.rb
@@ -5,7 +5,7 @@ class SpecialPreferencesPage
link(:beta_features, id: 'preftab-betafeatures')
- checkbox(:flow_beta_feature, id: 'mw-input-wpbeta-feature-flow-user-talk-page')
+ checkbox(:flow_beta_feature, name: 'wpbeta-feature-flow-user-talk-page')
button(:save_preferences, id: 'prefcontrol')
diff --git a/Flow/tests/browser/features/support/pages/topic_history_page.rb b/Flow/tests/browser/features/support/pages/topic_history_page.rb
index 875465af..c1b18a33 100644
--- a/Flow/tests/browser/features/support/pages/topic_history_page.rb
+++ b/Flow/tests/browser/features/support/pages/topic_history_page.rb
@@ -2,4 +2,10 @@ class TopicHistoryPage
include PageObject
div(:flow_topic_history, class: 'flow-topic-histories')
+
+ ul(:flow_history_moderation, class: 'flow-history-moderation-menu')
+
+ link(:undo_link) do
+ flow_history_moderation_element.link_element(text: /undo/)
+ end
end
diff --git a/Flow/tests/browser/features/suppress.feature b/Flow/tests/browser/features/suppress.feature
index 628146dc..23310a23 100644
--- a/Flow/tests/browser/features/suppress.feature
+++ b/Flow/tests/browser/features/suppress.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Suppress
Assumes Flow is enabled on Talk:Flow_QA
@@ -30,6 +28,8 @@ Feature: Suppress
Then I see the following entries in board history
|action |topic |
|suppressed the topic|suppress-not-in-history|
+ And I do not see the following entries in board history
+ |action |topic |
|commented on |suppress-not-in-history|
When I log out
And I visit the board history page
diff --git a/Flow/tests/browser/features/thank.feature b/Flow/tests/browser/features/thank.feature
index 697de9dd..84404332 100644
--- a/Flow/tests/browser/features/thank.feature
+++ b/Flow/tests/browser/features/thank.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Thank author of a Flow post
Scenario: Anon does not see Thank button
@@ -8,7 +6,6 @@ Feature: Thank author of a Flow post
When I am on Flow page
Then I should not see a Thank button
- @login
Scenario: Thank the user
Given I am logged in
And the most recent topic on "Talk:Flow QA" is written by another user
@@ -16,7 +13,6 @@ Feature: Thank author of a Flow post
When I click on the Thank button
Then I should see the Thank button be replaced with Thanked button
- @login
Scenario: I cannot thank my own post
Given there is a new topic created by me
And I am logged in
diff --git a/Flow/tests/browser/features/undo.feature b/Flow/tests/browser/features/undo.feature
new file mode 100644
index 00000000..05366c63
--- /dev/null
+++ b/Flow/tests/browser/features/undo.feature
@@ -0,0 +1,21 @@
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
+Feature: Undoing edits
+
+ Background:
+ Given I am logged in
+
+ Scenario: Undo an edit to a post
+ Given I am on a new Flow board with topic content "This is the original content"
+ And I edit the topic with "This is the edited content"
+ When I visit the topic history page
+ And I undo the latest action
+ Then I am on a Flow topic page
+ And the saved undo post should contain "This is the original content"
+
+ Scenario: Undo an edit to the description
+ Given I am on a new Flow board with description "This is the original content"
+ And I set the description to "This is the edited content"
+ And I visit the new board history page
+ When I undo the latest action
+ Then I am on a Flow page
+ And the description should be "This is the original content"
diff --git a/Flow/tests/browser/features/watch.feature b/Flow/tests/browser/features/watch.feature
index 7937e00a..d8d9e583 100644
--- a/Flow/tests/browser/features/watch.feature
+++ b/Flow/tests/browser/features/watch.feature
@@ -1,6 +1,4 @@
-@chrome @firefox @internet_explorer_10
-@clean @login
-@en.wikipedia.beta.wmflabs.org
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @skip
Feature: Watching/Unwatching Boards and Topics
Background:
diff --git a/Flow/tests/phpunit/Block/TopicListTest.php b/Flow/tests/phpunit/Block/TopicListTest.php
index 723835a8..22d5752e 100644
--- a/Flow/tests/phpunit/Block/TopicListTest.php
+++ b/Flow/tests/phpunit/Block/TopicListTest.php
@@ -30,36 +30,36 @@ class TopicListTest extends \MediaWikiTestCase {
$block = new TopicListBlock( $workflow, Container::get( 'storage' ) );
$block->init( $ctx, 'view' );
- $res = $block->renderApi( array(
- ) );
+ $res = $block->renderApi( [
+ ] );
$this->assertEquals( 'newest', $res['sortby'], 'With no sortby defaults to newest' );
- $res = $block->renderApi( array(
+ $res = $block->renderApi( [
'sortby' => 'foo',
- ) );
+ ] );
$this->assertEquals( 'newest', $res['sortby'], 'With invalid sortby defaults to newest' );
- $res = $block->renderApi( array(
+ $res = $block->renderApi( [
'sortby' => 'updated',
- ) );
+ ] );
$this->assertEquals( 'updated', $res['sortby'], 'With sortby updated output changes to updated' );
- $res = $block->renderApi( array(
- ) );
+ $res = $block->renderApi( [
+ ] );
$this->assertEquals( 'newest', $res['sortby'], 'Sort still defaults to newest' );
- $res = $block->renderApi( array(
+ $res = $block->renderApi( [
'sortby' => 'updated',
'savesortby' => '1',
- ) );
+ ] );
$this->assertEquals( 'updated', $res['sortby'], 'Request saving sortby option' );
- $res = $block->renderApi( array(
- ) );
+ $res = $block->renderApi( [
+ ] );
$this->assertEquals( 'updated', $res['sortby'], 'Default sortby now changed to updated' );
- $res = $block->renderApi( array(
+ $res = $block->renderApi( [
'sortby' => '',
- ) );
+ ] );
$this->assertEquals( 'updated', $res['sortby'], 'Default sortby with blank sortby still uses user default' );
}
}
diff --git a/Flow/tests/phpunit/BlockFactoryTest.php b/Flow/tests/phpunit/BlockFactoryTest.php
index 199feda1..7f1889ef 100644
--- a/Flow/tests/phpunit/BlockFactoryTest.php
+++ b/Flow/tests/phpunit/BlockFactoryTest.php
@@ -2,9 +2,7 @@
namespace Flow\Tests;
-use Flow\Container;
use Flow\BlockFactory;
-use Flow\NotificationController;
/**
* @group Flow
@@ -12,10 +10,10 @@ use Flow\NotificationController;
class BlockFactoryTest extends FlowTestCase {
public function provideDataCreateBlocks() {
- return array (
- array( 'discussion', array( 'Flow\Block\HeaderBlock', 'Flow\Block\TopicListBlock', 'Flow\Block\BoardHistoryBlock' ) ),
- array( 'topic', array( 'Flow\Block\TopicBlock', 'Flow\Block\TopicSummaryBlock' ) ),
- );
+ return [
+ [ 'discussion', [ 'Flow\Block\HeaderBlock', 'Flow\Block\TopicListBlock', 'Flow\Block\BoardHistoryBlock' ] ],
+ [ 'topic', [ 'Flow\Block\TopicBlock', 'Flow\Block\TopicSummaryBlock' ] ],
+ ];
}
/**
@@ -28,7 +26,7 @@ class BlockFactoryTest extends FlowTestCase {
$blocks = $factory->createBlocks( $workflow );
$this->assertEquals( count( $blocks ), count( $expectedResults ) );
- $results = array();
+ $results = [];
foreach ( $blocks as $obj ) {
$results[] = get_class( $obj );
}
@@ -36,12 +34,12 @@ class BlockFactoryTest extends FlowTestCase {
}
/**
- * @expectedException \Flow\Exception\InvalidInputException
+ * @expectedException \Flow\Exception\DataModelException
*/
public function testCreateBlocksWithInvalidInputException() {
$factory = $this->createBlockFactory();
$workflow = $this->mockWorkflow( 'a-bad-database-flow-workflow' );
- // Trigger InvalidInputException
+ // Trigger DataModelException
$factory->createBlocks( $workflow );
}
@@ -54,7 +52,7 @@ class BlockFactoryTest extends FlowTestCase {
->disableOriginalConstructor()
->getMock();
- return new BlockFactory( $storage, $rootPostLoader, Container::get( 'flow_actions' ) );
+ return new BlockFactory( $storage, $rootPostLoader );
}
protected function mockWorkflow( $type ) {
diff --git a/Flow/tests/phpunit/Collection/PostCollectionTest.php b/Flow/tests/phpunit/Collection/PostCollectionTest.php
index 629f48a9..556c06f6 100644
--- a/Flow/tests/phpunit/Collection/PostCollectionTest.php
+++ b/Flow/tests/phpunit/Collection/PostCollectionTest.php
@@ -13,7 +13,7 @@ class PostCollectionTest extends PostRevisionTestCase {
/**
* @var array
*/
- protected $tablesUsed = array( 'flow_revision', 'flow_tree_revision' );
+ protected $tablesUsed = [ 'flow_revision', 'flow_tree_revision' ];
protected function setUp() {
parent::setUp();
@@ -22,27 +22,27 @@ class PostCollectionTest extends PostRevisionTestCase {
$this->clearExtraLifecycleHandlers();
// generate a post with multiple revisions
- $revision = $this->generateObject( array(
+ $revision = $this->generateObject( [
'rev_content' => 'first revision',
- ) );
+ ] );
$this->store( $revision );
- $revision = $this->generateObject( array(
+ $revision = $this->generateObject( [
'rev_content' => 'second revision',
'rev_change_type' => 'edit-post',
'rev_parent_id' => $revision->getRevisionId()->getBinary(),
'tree_rev_descendant_id' => $revision->getPostId()->getBinary(),
'rev_type_id' => $revision->getPostId()->getBinary(),
- ) );
+ ] );
$this->store( $revision );
- $revision = $this->generateObject( array(
+ $revision = $this->generateObject( [
'rev_content' => 'third revision',
'rev_change_type' => 'edit-post',
'rev_parent_id' => $revision->getRevisionId()->getBinary(),
'tree_rev_descendant_id' => $revision->getPostId()->getBinary(),
'rev_type_id' => $revision->getPostId()->getBinary(),
- ) );
+ ] );
$this->store( $revision );
}
diff --git a/Flow/tests/phpunit/Collection/RevisionCollectionPermissionsTest.php b/Flow/tests/phpunit/Collection/RevisionCollectionPermissionsTest.php
index 0734d35e..2bfb6882 100644
--- a/Flow/tests/phpunit/Collection/RevisionCollectionPermissionsTest.php
+++ b/Flow/tests/phpunit/Collection/RevisionCollectionPermissionsTest.php
@@ -27,23 +27,42 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
*
* @var array
*/
- protected $moderation = array(
+ protected $moderation = [
'restore-post' => AbstractRevision::MODERATED_NONE,
'hide-post' => AbstractRevision::MODERATED_HIDDEN,
'delete-post' => AbstractRevision::MODERATED_DELETED,
'suppress-post' => AbstractRevision::MODERATED_SUPPRESSED,
- );
+ ];
/**
* @var User
*/
- protected
- $blockedUser,
- $anonUser,
- $unconfirmedUser,
- $confirmedUser,
- $sysopUser,
- $oversightUser;
+ protected $blockedUser;
+
+ /**
+ * @var User
+ */
+ protected $anonUser;
+
+ /**
+ * @var User
+ */
+ protected $unconfirmedUser;
+
+ /**
+ * @var User
+ */
+ protected $confirmedUser;
+
+ /**
+ * @var User
+ */
+ protected $sysopUser;
+
+ /**
+ * @var User
+ */
+ protected $oversightUser;
/**
* @var Block
@@ -57,13 +76,7 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
// We don't want local config getting in the way of testing whether or
// not our permissions implementation works well.
- // This will load default $wgGroupPermissions + Flow settings, so we can
- // test if permissions work well, regardless of any custom config.
- global $IP, $wgFlowGroupPermissions;
- $wgGroupPermissions = array();
- require "$IP/includes/DefaultSettings.php";
- $wgGroupPermissions = array_merge_recursive( $wgGroupPermissions, $wgFlowGroupPermissions );
- $this->setMwGlobals( 'wgGroupPermissions', $wgGroupPermissions );
+ $this->resetPermissions();
// When external store is used, data is written to "blobs" table, which
// by default doesn't exist - let's just not use externalstorage in test
@@ -74,10 +87,10 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
// block a user
$blockedUser = $this->blockedUser();
- $this->block = new Block( array(
+ $this->block = new Block( [
'address' => $blockedUser->getName(),
'user' => $blockedUser->getID()
- ) );
+ ] );
$this->block->insert();
// ensure that block made it into the database
wfGetDB( DB_MASTER )->commit( __METHOD__, 'flush' );
@@ -94,10 +107,10 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
* @return array
*/
public function permissionsProvider() {
- return array(
+ return [
// irregardless of current status, if a user has no permissions for
// a specific revision, he can't see it
- array( $this->confirmedUser(), 'view', array(
+ [ $this->confirmedUser(), 'view', [
// Key is the moderation action; value is the 'view' permission
// for that corresponding revision after all moderation is done.
// In this case, a post will be created with 3 revisions:
@@ -107,41 +120,41 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
// [1] should be visible (this + last rev not suppressed)
// [2] should not (was suppressed)
// [3] should be visible again (undid suppression)
- array( 'new-post' => true ),
- array( 'suppress-post' => false ),
- array( 'restore-post' => true ),
- ) ),
- array( $this->oversightUser(), 'view', array(
- array( 'new-post' => true ),
- array( 'suppress-post' => true ),
- array( 'restore-post' => true ),
- ) ),
+ [ 'new-post' => true ],
+ [ 'suppress-post' => false ],
+ [ 'restore-post' => true ],
+ ] ],
+ [ $this->oversightUser(), 'view', [
+ [ 'new-post' => true ],
+ [ 'suppress-post' => true ],
+ [ 'restore-post' => true ],
+ ] ],
// last moderation status should always bubble down to previous revs
- array( $this->confirmedUser(), 'view', array(
- array( 'new-post' => false ),
- array( 'suppress-post' => false ),
- array( 'restore-post' => false ),
- array( 'suppress-post' => false ),
- ) ),
- array( $this->oversightUser(), 'view', array(
- array( 'new-post' => true ),
- array( 'suppress-post' => true ),
- array( 'restore-post' => true ),
- array( 'suppress-post' => true ),
- ) ),
+ [ $this->confirmedUser(), 'view', [
+ [ 'new-post' => false ],
+ [ 'suppress-post' => false ],
+ [ 'restore-post' => false ],
+ [ 'suppress-post' => false ],
+ ] ],
+ [ $this->oversightUser(), 'view', [
+ [ 'new-post' => true ],
+ [ 'suppress-post' => true ],
+ [ 'restore-post' => true ],
+ [ 'suppress-post' => true ],
+ ] ],
// bug 61715
- array( $this->confirmedUser(), 'history', array(
- array( 'new-post' => false ),
- array( 'suppress-post' => false ),
- ) ),
- array( $this->confirmedUser(), 'history', array(
- array( 'new-post' => true ),
- array( 'suppress-post' => false ),
- array( 'restore-post' => false ),
- ) ),
- );
+ [ $this->confirmedUser(), 'history', [
+ [ 'new-post' => false ],
+ [ 'suppress-post' => false ],
+ ] ],
+ [ $this->confirmedUser(), 'history', [
+ [ 'new-post' => true ],
+ [ 'suppress-post' => false ],
+ [ 'restore-post' => false ],
+ ] ],
+ ];
}
/**
@@ -153,8 +166,8 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
// we'll have to process this in 2 steps: first do all of the actions,
// so we have a full tree of moderated revisions
$revision = null;
- $revisions = array();
- $debug = array();
+ $revisions = [];
+ $debug = [];
foreach ( $actions as $action ) {
$expect = current( $action );
$action = key( $action );
@@ -243,7 +256,7 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
* @param array $overrides
* @return PostRevision
*/
- public function generateRevision( $action, AbstractRevision $parent = null, array $overrides = array() ) {
+ public function generateRevision( $action, AbstractRevision $parent = null, array $overrides = [] ) {
$overrides['rev_change_type'] = $action;
if ( $parent ) {
@@ -254,25 +267,25 @@ class RevisionCollectionPermissionsTest extends PostRevisionTestCase {
switch ( $action ) {
case 'restore-post':
- $overrides += array(
+ $overrides += [
'rev_mod_state' => $this->moderation[$action], // AbstractRevision::MODERATED_NONE
'rev_mod_user_id' => null,
'rev_mod_user_ip' => null,
'rev_mod_timestamp' => null,
'rev_mod_reason' => 'unit test',
- );
+ ];
break;
case 'hide-post':
case 'delete-post':
case 'suppress-post':
- $overrides += array(
+ $overrides += [
'rev_mod_state' => $this->moderation[$action], // AbstractRevision::MODERATED_(HIDDEN|DELETED|SUPPRESSED)
'rev_mod_user_id' => 1,
'rev_mod_user_ip' => null,
'rev_mod_timestamp' => wfTimestampNow(),
'rev_mod_reason' => 'unit test',
- );
+ ];
break;
default:
diff --git a/Flow/tests/phpunit/ContainerTest.php b/Flow/tests/phpunit/ContainerTest.php
index 9dc7a1d8..121fe74c 100644
--- a/Flow/tests/phpunit/ContainerTest.php
+++ b/Flow/tests/phpunit/ContainerTest.php
@@ -19,9 +19,9 @@ class ContainerTest extends FlowTestCase {
}
public function objectManagerKeyProvider() {
- $tests = array();
+ $tests = [];
foreach ( array_unique( Container::get( 'storage.manager_list' ) ) as $key ) {
- $tests[] = array( $key );
+ $tests[] = [ $key ];
}
return $tests;
}
diff --git a/Flow/tests/phpunit/Conversion/UtilsTest.php b/Flow/tests/phpunit/Conversion/UtilsTest.php
new file mode 100644
index 00000000..3d51d591
--- /dev/null
+++ b/Flow/tests/phpunit/Conversion/UtilsTest.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace Flow\Tests\Conversion;
+
+use Flow\Exception\WikitextException;
+use Flow\Conversion\Utils;
+use Flow\Tests\FlowTestCase;
+use Title;
+
+/**
+ * @group Flow
+ */
+class ConversionUtilsTest extends FlowTestCase {
+
+ public static function createDomProvider() {
+ return [
+ [
+ 'A document with multiple matching ids is valid parser output',
+ '<body><a id="foo">foo</a><a id="foo">bar</a></body>'
+ ],
+ [
+ 'HTML5 tags, such as figcaption, are valid html',
+ '<body><figcaption /></body>'
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider createDomProvider
+ */
+ public function testCreateDomErrorModes( $message, $content ) {
+ $this->assertInstanceOf( 'DOMDocument', Utils::createDOM( $content ), $message );
+ }
+
+ public static function createRelativeTitleProvider() {
+ return [
+ [
+ 'strips leading ./ and treats as non-relative',
+ // expect
+ Title::newFromText( 'File:Foo.jpg' ),
+ // input text
+ './File:Foo.jpg',
+ // relative to title
+ Title::newMainPage()
+ ],
+
+ [
+ 'two level upwards traversal',
+ // expect
+ Title::newFromText( 'File:Bar.jpg' ),
+ // input text
+ '../../File:Bar.jpg',
+ // relative to title
+ Title::newFromText( 'Main_Page/And/Subpage' ),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider createRelativeTitleProvider
+ */
+ public function testResolveSubpageTraversal( $message, $expect, $text, Title $title ) {
+ $result = Utils::createRelativeTitle( $text, $title );
+
+ if ( $expect === null ) {
+ $this->assertNull( $expect, $message );
+ } elseif ( $expect instanceof Title ) {
+ $this->assertInstanceOf( 'Title', $result, $message );
+ $this->assertEquals( $expect->getPrefixedText(), $result->getPrefixedText(), $message );
+ } else {
+ $this->assertEquals( $expect, $result, $message );
+ }
+ }
+
+ public static function wikitextRoundtripProvider() {
+ return [
+ [
+ 'italic text',
+ // text & expect
+ "''italic text''",
+ // title
+ Title::newMainPage(),
+ ],
+ [
+ 'bold text',
+ // text & expect
+ "'''bold text'''",
+ // title
+ Title::newMainPage(),
+ ],
+ ];
+ }
+
+ /**
+ * Test full roundtrip (wikitext -> html -> wikitext)
+ *
+ * It doesn't make sense to test only a specific path, since Parsoid's HTML
+ * may change beyond our control & it doesn't really matter to us what
+ * exactly the HTML looks like, as long as Parsoid is able to understand it.
+ *
+ * @dataProvider wikitextRoundtripProvider
+ */
+ public function testwikitextRoundtrip( $message, $expect, Title $title ) {
+ // Check for Parsoid
+ try {
+ $html = Utils::convert( 'wikitext', 'html', $expect, $title );
+ $wikitext = Utils::convert( 'html', 'wikitext', $html, $title );
+ $this->assertEquals( $expect, trim( $wikitext ), $message );
+ } catch ( WikitextException $excep ) {
+ $this->markTestSkipped( 'Parsoid not enabled' );
+ }
+ }
+
+ /**
+ * Test topic-title-plaintext
+ *
+ * @dataProvider topicTitleProvider
+ */
+ public function testTopicTitle( $message, $wikitext, $expectedHtml, $expectedPlaintext ) {
+ $this->setMwGlobals( 'wgScript', '/w/index.php' );
+
+ $html = Utils::convert( 'topic-title-wikitext', 'topic-title-html', $wikitext, Title::newMainPage() );
+ $this->assertEquals( $expectedHtml, $html, "$message: html" );
+
+ $plaintext = Utils::convert( 'topic-title-wikitext', 'topic-title-plaintext', $wikitext, Title::newMainPage() );
+ $this->assertEquals( $expectedPlaintext, $plaintext, "$message: plaintext" );
+ }
+
+ public static function topicTitleProvider() {
+ return [
+ [
+ 'External links not processed',
+ '[http://example.com Example]',
+ '[http://example.com Example]',
+ '[http://example.com Example]',
+ ],
+ [
+ 'Bold and italics not processed',
+ "'''Bold''' and ''italics''",
+ "&#039;&#039;&#039;Bold&#039;&#039;&#039; and &#039;&#039;italics&#039;&#039;",
+ "'''Bold''' and ''italics''",
+ ],
+ [
+ 'Script tags are treated as text',
+ '<script>alert(\'Test\');</script>',
+ '&lt;script&gt;alert(&#039;Test&#039;);&lt;/script&gt;',
+ '<script>alert(\'Test\');</script>',
+ ],
+ [
+ 'Entities processed',
+ '&amp;&#x27;',
+ '&amp;&#039;',
+ '&\'',
+ ],
+ [
+ 'Internal links are converted to plaintext',
+ '[[asdfasdferqwer389]] is a place',
+ '<a href="/w/index.php?title=Asdfasdferqwer389&amp;action=edit&amp;redlink=1" class="new" title="Asdfasdferqwer389 (page does not exist)">asdfasdferqwer389</a> is a place',
+ 'asdfasdferqwer389 is a place',
+ ],
+ [
+ 'Quotes are preserved',
+ '\'Single quotes\' "Double quotes"',
+ '&#039;Single quotes&#039; &quot;Double quotes&quot;',
+ '\'Single quotes\' "Double quotes"',
+ ],
+ ];
+ }
+}
diff --git a/Flow/tests/phpunit/Data/CachingObjectMapperTest.php b/Flow/tests/phpunit/Data/CachingObjectMapperTest.php
index 3c7ec013..bbd6fb49 100644
--- a/Flow/tests/phpunit/Data/CachingObjectMapperTest.php
+++ b/Flow/tests/phpunit/Data/CachingObjectMapperTest.php
@@ -12,24 +12,26 @@ class CachingObjectManagerTest extends FlowTestCase {
public function testReturnsSameObject() {
$mapper = $this->createMapper();
- $object = $mapper->fromStorageRow( array( 'id' => 1 ) );
- $this->assertSame( $object, $mapper->fromStorageRow( array( 'id' => 1 ) ) );
+ $object = $mapper->fromStorageRow( [ 'id' => 1 ] );
+ $this->assertSame( $object, $mapper->fromStorageRow( [ 'id' => 1 ] ) );
}
public function testAllowsNullPkOnPut() {
- $this->createMapper()->toStorageRow( (object)array( 'id' => null ) );
+ $this->createMapper()->toStorageRow( (object)[ 'id' => null ] );
$this->assertTrue( true );
}
protected function createMapper() {
- $toStorageRow = function( $object ) { return (array)$object; };
- $fromStorageRow = function( array $row, $object ) {
+ $toStorageRow = function ( $object ) {
+ return (array)$object;
+ };
+ $fromStorageRow = function ( array $row, $object ) {
if ( $object === null ) {
return (object)$row;
} else {
return (object)( $row + (array)$object );
}
};
- return new CachingObjectMapper( $toStorageRow, $fromStorageRow, array( 'id' ) );
+ return new CachingObjectMapper( $toStorageRow, $fromStorageRow, [ 'id' ] );
}
}
diff --git a/Flow/tests/phpunit/Data/IndexTest.php b/Flow/tests/phpunit/Data/IndexTest.php
index d9665fc9..65d42f65 100644
--- a/Flow/tests/phpunit/Data/IndexTest.php
+++ b/Flow/tests/phpunit/Data/IndexTest.php
@@ -3,8 +3,6 @@
namespace Flow\Tests\Data;
use Flow\Container;
-use Flow\Data\BagOStuff\BufferedBagOStuff;
-use Flow\Data\BufferedCache;
use Flow\Data\Index\FeatureIndex;
use Flow\Data\Index\TopKIndex;
use Flow\Data\Index\UniqueFeatureIndex;
@@ -16,10 +14,7 @@ use Flow\Tests\FlowTestCase;
class IndexTest extends FlowTestCase {
public function testShallow() {
- global $wgFlowCacheTime;
-
- $bag = new BufferedBagOStuff( new \HashBagOStuff );
- $cache = new BufferedCache( $bag, $wgFlowCacheTime );
+ $cache = $this->getCache();
// fake ObjectMapper that doesn't roundtrip to- & fromStorageRow
$mapper = $this->getMockBuilder( 'Flow\Data\Mapper\BasicObjectMapper' )
@@ -35,44 +30,41 @@ class IndexTest extends FlowTestCase {
$unique = new UniqueFeatureIndex(
$cache, $storage, $mapper, 'unique',
- array( 'id' )
+ [ 'id' ]
);
$secondary = new TopKIndex(
$cache, $storage, $mapper, 'secondary',
- array( 'name' ), // keys indexed in this array
- array(
+ [ 'name' ], // keys indexed in this array
+ [
'shallow' => $unique,
'sort' => 'id',
- )
+ ]
);
$db = FeatureIndex::cachedDbId();
$v = Container::get( 'cache.version' );
- $bag->set( "$db:unique:1:$v", array( array( 'id' => 1, 'name' => 'foo', 'other' => 'ppp' ) ) );
- $bag->set( "$db:unique:2:$v", array( array( 'id' => 2, 'name' => 'foo', 'other' => 'qqq' ) ) );
- $bag->set( "$db:unique:3:$v", array( array( 'id' => 3, 'name' => 'baz', 'other' => 'lll' ) ) );
-
- $bag->set( "$db:secondary:foo:$v", array( array( 'id' => 1 ), array( 'id' => 2 ) ) );
- $bag->set( "$db:secondary:baz:$v", array( array( 'id' => 3 ) ) );
-
- $expect = array(
- array( 'id' => 1, 'name' => 'foo', 'other' => 'ppp', ),
- array( 'id' => 2, 'name' => 'foo', 'other' => 'qqq', ),
- );
- $this->assertEquals( $expect, $secondary->find( array( 'name' => 'foo' ) ) );
-
- $expect = array(
- array( 'id' => 3, 'name' => 'baz', 'other' => 'lll' ),
- );
- $this->assertEquals( $expect, $secondary->find( array( 'name' => 'baz' ) ) );
+ $cache->set( "$db:unique:" . md5( '1' ) . ":$v", [ [ 'id' => 1, 'name' => 'foo', 'other' => 'ppp' ] ] );
+ $cache->set( "$db:unique:" . md5( '2' ) . ":$v", [ [ 'id' => 2, 'name' => 'foo', 'other' => 'qqq' ] ] );
+ $cache->set( "$db:unique:" . md5( '3' ) . ":$v", [ [ 'id' => 3, 'name' => 'baz', 'other' => 'lll' ] ] );
+
+ $cache->set( "$db:secondary:" . md5( 'foo' ) . ":$v", [ [ 'id' => 1 ], [ 'id' => 2 ] ] );
+ $cache->set( "$db:secondary:" . md5( 'baz' ) . ":$v", [ [ 'id' => 3 ] ] );
+
+ $expect = [
+ [ 'id' => 1, 'name' => 'foo', 'other' => 'ppp', ],
+ [ 'id' => 2, 'name' => 'foo', 'other' => 'qqq', ],
+ ];
+ $this->assertEquals( $expect, $secondary->find( [ 'name' => 'foo' ] ) );
+
+ $expect = [
+ [ 'id' => 3, 'name' => 'baz', 'other' => 'lll' ],
+ ];
+ $this->assertEquals( $expect, $secondary->find( [ 'name' => 'baz' ] ) );
}
public function testCompositeShallow() {
- global $wgFlowCacheTime;
-
- $bag = new BufferedBagOStuff( new \HashBagOStuff );
- $cache = new BufferedCache( $bag, $wgFlowCacheTime );
+ $cache = $this->getCache();
$storage = $this->getMock( 'Flow\\Data\\ObjectStorage' );
// fake ObjectMapper that doesn't roundtrip to- & fromStorageRow
@@ -85,43 +77,43 @@ class IndexTest extends FlowTestCase {
$unique = new UniqueFeatureIndex(
$cache, $storage, $mapper, 'unique',
- array( 'id', 'ot' )
+ [ 'id', 'ot' ]
);
$secondary = new TopKIndex(
$cache, $storage, $mapper, 'secondary',
- array( 'name' ), // keys indexed in this array
- array(
+ [ 'name' ], // keys indexed in this array
+ [
'shallow' => $unique,
'sort' => 'id',
- )
+ ]
);
// remember: unique index still stores an array of results to be consistent with other indexes
// even though, due to uniqueness, there is only one value per set of keys
$db = FeatureIndex::cachedDbId();
$v = Container::get( 'cache.version' );
- $bag->set( "$db:unique:1:9:$v", array( array( 'id' => 1, 'ot' => 9, 'name' => 'foo' ) ) );
- $bag->set( "$db:unique:1:8:$v", array( array( 'id' => 1, 'ot' => 8, 'name' => 'foo' ) ) );
- $bag->set( "$db:unique:3:7:$v", array( array( 'id' => 3, 'ot' => 7, 'name' => 'baz' ) ) );
-
- $bag->set( "$db:secondary:foo:$v", array(
- array( 'id' => 1, 'ot' => 9 ),
- array( 'id' => 1, 'ot' => 8 ),
- ) );
- $bag->set( "$db:secondary:baz:$v", array(
- array( 'id' => 3, 'ot' => 7 ),
- ) );
-
- $expect = array(
- array( 'id' => 1, 'ot' => 9, 'name' => 'foo' ),
- array( 'id' => 1, 'ot' => 8, 'name' => 'foo' ),
- );
- $this->assertEquals( $expect, $secondary->find( array( 'name' => 'foo' ) ) );
-
- $expect = array(
- array( 'id' => 3, 'ot' => 7, 'name' => 'baz' ),
- );
- $this->assertEquals( $expect, $secondary->find( array( 'name' => 'baz' ) ) );
+ $cache->set( "$db:unique:" . md5( '1:9' ) . ":$v", [ [ 'id' => 1, 'ot' => 9, 'name' => 'foo' ] ] );
+ $cache->set( "$db:unique:" . md5( '1:8' ) . ":$v", [ [ 'id' => 1, 'ot' => 8, 'name' => 'foo' ] ] );
+ $cache->set( "$db:unique:" . md5( '3:7' ) . ":$v", [ [ 'id' => 3, 'ot' => 7, 'name' => 'baz' ] ] );
+
+ $cache->set( "$db:secondary:" . md5( 'foo' ) . ":$v", [
+ [ 'id' => 1, 'ot' => 9 ],
+ [ 'id' => 1, 'ot' => 8 ],
+ ] );
+ $cache->set( "$db:secondary:" . md5( 'baz' ). ":$v", [
+ [ 'id' => 3, 'ot' => 7 ],
+ ] );
+
+ $expect = [
+ [ 'id' => 1, 'ot' => 9, 'name' => 'foo' ],
+ [ 'id' => 1, 'ot' => 8, 'name' => 'foo' ],
+ ];
+ $this->assertEquals( $expect, $secondary->find( [ 'name' => 'foo' ] ) );
+
+ $expect = [
+ [ 'id' => 3, 'ot' => 7, 'name' => 'baz' ],
+ ];
+ $this->assertEquals( $expect, $secondary->find( [ 'name' => 'baz' ] ) );
}
}
diff --git a/Flow/tests/phpunit/Data/Listener/RecentChangesListenerTest.php b/Flow/tests/phpunit/Data/Listener/RecentChangesListenerTest.php
index 0a9e8cb9..2393f2a5 100644
--- a/Flow/tests/phpunit/Data/Listener/RecentChangesListenerTest.php
+++ b/Flow/tests/phpunit/Data/Listener/RecentChangesListenerTest.php
@@ -15,16 +15,16 @@ use User;
class RecentChangesListenerTest extends \MediaWikiTestCase {
public function somethingProvider() {
- return array(
- array(
+ return [
+ [
'Reply recent change goes to the topic',
NS_TOPIC,
- function( $workflow, $user ) {
- $first = PostRevision::create( $workflow, $user, 'blah blah', 'wikitext' );
+ function ( $workflow, $user ) {
+ $first = PostRevision::createTopicPost( $workflow, $user, 'blah blah' );
return $first->reply( $workflow, $user, 'fofofo', 'wikitext' );
},
- ),
- );
+ ],
+ ];
}
/**
@@ -46,7 +46,7 @@ class RecentChangesListenerTest extends \MediaWikiTestCase {
$change = $this->getMock( 'RecentChange' );
$rcFactory->expects( $this->once() )
->method( 'newFromRow' )
- ->will( $this->returnCallback( function( $obj ) use ( &$ref, $change ) {
+ ->will( $this->returnCallback( function ( $obj ) use ( &$ref, $change ) {
$ref = $obj;
return $change;
} ) );
@@ -59,8 +59,8 @@ class RecentChangesListenerTest extends \MediaWikiTestCase {
$rc->onAfterInsert(
$revision,
- array( 'rev_user_id' => 0, 'rev_user_ip' => '127.0.0.1' ),
- array( 'workflow' => $workflow )
+ [ 'rev_user_id' => 0, 'rev_user_ip' => '127.0.0.1' ],
+ [ 'workflow' => $workflow ]
);
$this->assertNotNull( $ref );
$this->assertEquals( $expect, $ref->rc_namespace, $message );
diff --git a/Flow/tests/phpunit/Data/ManagerGroupTest.php b/Flow/tests/phpunit/Data/ManagerGroupTest.php
index dfbe5086..413f42ac 100644
--- a/Flow/tests/phpunit/Data/ManagerGroupTest.php
+++ b/Flow/tests/phpunit/Data/ManagerGroupTest.php
@@ -17,15 +17,15 @@ class ManagerGroupTest extends \MediaWikiTestCase {
->getMock();
}
- $storage = new ManagerGroup( $container, array(
+ $storage = new ManagerGroup( $container, [
'A' => 'A',
'B' => 'B',
'C' => 'C',
'D' => 'D',
'stdClass' => 'D',
- ) );
+ ] );
- return array( $storage, $container );
+ return [ $storage, $container ];
}
public function testClearOnlyCallsRequestedManagers() {
@@ -63,4 +63,3 @@ class ManagerGroupTest extends \MediaWikiTestCase {
$storage->cachePurge( $object );
}
}
-
diff --git a/Flow/tests/phpunit/Data/NothingTest.php b/Flow/tests/phpunit/Data/NothingTest.php
index 4cec1671..509f4fc8 100644
--- a/Flow/tests/phpunit/Data/NothingTest.php
+++ b/Flow/tests/phpunit/Data/NothingTest.php
@@ -11,49 +11,49 @@ use Flow\Tests\FlowTestCase;
class FlowNothingTest extends FlowTestCase {
public function sortArrayByKeysProvider() {
- return array(
+ return [
- array(
+ [
'Basic one key sort',
// keys to sort by
- array( 'id' ),
+ [ 'id' ],
// array to sort
- array(
- array( 'id' => 5 ),
- array( 'id' => 7 ),
- array( 'id' => 6 ),
- ),
+ [
+ [ 'id' => 5 ],
+ [ 'id' => 7 ],
+ [ 'id' => 6 ],
+ ],
// expected result
- array(
- array( 'id' => 5 ),
- array( 'id' => 6 ),
- array( 'id' => 7 ),
- ),
- ),
+ [
+ [ 'id' => 5 ],
+ [ 'id' => 6 ],
+ [ 'id' => 7 ],
+ ],
+ ],
- array(
+ [
'Multi-key sort',
// keys to sort by
- array( 'id', 'qq' ),
+ [ 'id', 'qq' ],
// array to sort
- array(
- array( 'id' => 5, 'qq' => 4 ),
- array( 'id' => 5, 'qq' => 2 ),
- array( 'id' => 7, 'qq' => 1 ),
- array( 'id' => 6, 'qq' => 3 ),
- array( 'qq' => 9, 'id' => 4 ),
- ),
+ [
+ [ 'id' => 5, 'qq' => 4 ],
+ [ 'id' => 5, 'qq' => 2 ],
+ [ 'id' => 7, 'qq' => 1 ],
+ [ 'id' => 6, 'qq' => 3 ],
+ [ 'qq' => 9, 'id' => 4 ],
+ ],
// expected result
- array(
- array( 'qq' => 9, 'id' => 4 ),
- array( 'id' => 5, 'qq' => 2 ),
- array( 'id' => 5, 'qq' => 4 ),
- array( 'id' => 6, 'qq' => 3 ),
- array( 'id' => 7, 'qq' => 1 ),
- ),
- ),
+ [
+ [ 'qq' => 9, 'id' => 4 ],
+ [ 'id' => 5, 'qq' => 2 ],
+ [ 'id' => 5, 'qq' => 4 ],
+ [ 'id' => 6, 'qq' => 3 ],
+ [ 'id' => 7, 'qq' => 1 ],
+ ],
+ ],
- );
+ ];
}
/**
diff --git a/Flow/tests/phpunit/Data/ObjectLocatorTest.php b/Flow/tests/phpunit/Data/ObjectLocatorTest.php
index 59dc508a..74008173 100644
--- a/Flow/tests/phpunit/Data/ObjectLocatorTest.php
+++ b/Flow/tests/phpunit/Data/ObjectLocatorTest.php
@@ -12,13 +12,14 @@ class ObjectLocatorTest extends FlowTestCase {
public function testUselessTest() {
$mapper = $this->getMock( 'Flow\Data\ObjectMapper' );
$storage = $this->getMock( 'Flow\Data\ObjectStorage' );
+ $dbFactory = $this->getMock( 'Flow\DbFactory' );
- $locator = new \Flow\Data\ObjectLocator( $mapper, $storage );
+ $locator = new \Flow\Data\ObjectLocator( $mapper, $storage, $dbFactory );
$storage->expects( $this->any() )
->method( 'findMulti' )
- ->will( $this->returnValue( array( array( null, null ) ) ) );
+ ->will( $this->returnValue( [ [ null, null ] ] ) );
- $this->assertEquals( array(), $locator->findMulti( array( array( 'foo' => 'random crap' ) ) ) );
+ $this->assertEquals( [], $locator->findMulti( [ [ 'foo' => 'random crap' ] ] ) );
}
}
diff --git a/Flow/tests/phpunit/Data/Pager/PagerTest.php b/Flow/tests/phpunit/Data/Pager/PagerTest.php
index b24f436b..f99b5f14 100644
--- a/Flow/tests/phpunit/Data/Pager/PagerTest.php
+++ b/Flow/tests/phpunit/Data/Pager/PagerTest.php
@@ -2,12 +2,8 @@
namespace Flow\Tests\Data\Pager;
-use Flow\Data\BagOStuff;
-use Flow\Data\BagOStuff\LocalBufferedBagOStuff;
-use Flow\Data\BufferedCache;
-use Flow\Data\Index\TopKIndex;
use Flow\Data\Pager\Pager;
-use stdClass;
+use Flow\Model\UUID;
/**
* @group Flow
@@ -15,97 +11,99 @@ use stdClass;
class PagerTest extends \MediaWikiTestCase {
public static function getPageResultsProvider() {
- $objs = array();
+ $objs = [];
foreach ( range( 'A', 'J' ) as $letter ) {
- $objs[$letter] = (object)array( 'foo' => $letter );
+ $objs[$letter] = (object)[ 'foo' => $letter ];
}
- return array(
- array(
+ return [
+ [
'Gracefully returns nothing',
// expect
- array(),
+ [],
// find results
- array(),
+ [],
// query options,
- array(),
+ [],
// filter
null
- ),
+ ],
- array(
+ [
'Returns found objects',
// expect
- array( $objs['A'], $objs['B'] ),
+ [ $objs['A'], $objs['B'] ],
// find results
- array(
- array( $objs['A'], $objs['B'] ),
- ),
+ [
+ [ $objs['A'], $objs['B'] ],
+ ],
// query options
- array( 'pager-limit' => 10 ),
+ [ 'pager-limit' => 10 ],
// filter
null
- ),
+ ],
- array(
+ [
'Applies filter',
// expect
- array( $objs['A'] ),
+ [ $objs['A'] ],
// find results
- array(
- array( $objs['A'], $objs['B'] )
- ),
+ [
+ [ $objs['A'], $objs['B'] ]
+ ],
// query options
- array( 'pager-limit' => 10 ),
+ [ 'pager-limit' => 10 ],
// filter
- function( $found ) {
- return array_filter( $found, function( $obj ) { return $obj->foo !== 'B'; } );
+ function ( $found ) {
+ return array_filter( $found, function ( $obj ) {
+ return $obj->foo !== 'B';
+ } );
},
- ),
+ ],
- array(
+ [
'Repeats query when filtered',
// expect
- array( $objs['A'], $objs['D'] ),
+ [ $objs['A'], $objs['D'] ],
// find results
- array(
- array( $objs['A'], $objs['B'], $objs['C'] ),
- array( $objs['D'], $objs['E'] ),
- ),
+ [
+ [ $objs['A'], $objs['B'], $objs['C'] ],
+ [ $objs['D'], $objs['E'] ],
+ ],
// query options
- array( 'pager-limit' => 2 ),
+ [ 'pager-limit' => 2 ],
// query filter
- function( $found ) {
- return array_filter( $found, function( $obj ) {
+ function ( $found ) {
+ return array_filter( $found, function ( $obj ) {
return $obj->foo !== 'B' && $obj->foo !== 'C';
} );
},
- ),
+ ],
- array(
+ [
'Reverse pagination with filter',
// expect
- array( $objs['B'], $objs['F'], $objs['I'] ),
+ [ $objs['B'], $objs['F'], $objs['I'] ],
// find results
- array(
+ [
// note thate feature index will return these in the normal
// forward sort order, the provided direction just means to
// get items before rather than after the offset.
// verified at FeatureIndexTest::testReversePagination()
- array( $objs['G'], $objs['H'], $objs['I'], $objs['J'] ),
- array( $objs['C'], $objs['D'], $objs['E'], $objs['F'] ),
- array( $objs['A'], $objs['B'] ),
- ),
+ [ $objs['G'], $objs['H'], $objs['I'], $objs['J'] ],
+ [ $objs['C'], $objs['D'], $objs['E'], $objs['F'] ],
+ [ $objs['A'], $objs['B'] ],
+ ],
// query options
- array( 'pager-limit' => 3, 'pager-dir' => 'rev', 'pager-offset' => 'K' ),
+ [ 'pager-limit' => 3, 'pager-dir' => 'rev', 'pager-offset' => 'K' ],
// query filter
- function( $found ) {
- return array_filter( $found, function( $obj ) {
- return in_array( $obj->foo, array( 'I', 'F', 'B', 'A' ) );
+ function ( $found ) {
+ return array_filter( $found, function ( $obj ) {
+ return in_array( $obj->foo, [ 'I', 'F', 'B', 'A' ] );
} );
},
- ),
- );
+ ],
+ ];
}
/**
@@ -114,7 +112,7 @@ class PagerTest extends \MediaWikiTestCase {
public function testGetPageResults( $message, $expect, $found, array $options, $filter ) {
$pager = new Pager(
$this->mockObjectManager( $found ),
- array( 'otherthing' => 42 ),
+ [ 'otherthing' => 42 ],
$options
);
$page = $pager->getPage( $filter );
@@ -122,133 +120,136 @@ class PagerTest extends \MediaWikiTestCase {
$this->assertEquals( $expect, $page->getResults(), $message );
}
-
public static function getPagingLinkOptionsProvider() {
- $objs = array();
+ $objs = [];
foreach ( range( 'A', 'G' ) as $letter ) {
- $objs[$letter] = (object)array( 'foo' => $letter );
+ $objs[$letter] = (object)[ 'foo' => $letter ];
}
- return array(
- array(
+ return [
+ [
'Gracefully returns nothing',
// expect
- array(),
+ [],
// find results
- array(),
+ [],
// pager options
- array(),
+ [],
// filter
null
- ),
+ ],
- array(
+ [
'No next page with exact number of results',
// expect
- array(),
+ [],
// find results
- array(
- array( $objs['A'], $objs['B'] ),
- ),
+ [
+ [ $objs['A'], $objs['B'] ],
+ ],
// pager options
- array( 'pager-limit' => 2 ),
+ [ 'pager-limit' => 2 ],
// filter
null
- ),
+ ],
- array(
+ [
'Forward pagination when direction forward and extra result',
// expect
- array(
- 'fwd' => array(
+ [
+ 'fwd' => [
'offset-dir' => 'fwd',
'limit' => 2,
'offset' => 'serialized-B',
- ),
- ),
+ ],
+ ],
// find results
- array(
- array( $objs['A'], $objs['B'], $objs['C'] ),
- ),
+ [
+ [ $objs['A'], $objs['B'], $objs['C'] ],
+ ],
// pager options
- array( 'pager-limit' => 2 ),
+ [ 'pager-limit' => 2 ],
// filter
null
- ),
+ ],
- array(
+ [
'Forward pagination when multi-query filtered',
// expect
- array(
- 'fwd' => array(
+ [
+ 'fwd' => [
'offset-dir' => 'fwd',
'limit' => 2,
'offset' => 'serialized-D',
- ),
- ),
+ ],
+ ],
// find results
- array(
- array( $objs['A'], $objs['B'], $objs['C'] ),
- array( $objs['D'], $objs['E'] ),
- ),
+ [
+ [ $objs['A'], $objs['B'], $objs['C'] ],
+ [ $objs['D'], $objs['E'] ],
+ ],
// pager options
- array( 'pager-limit' => 2 ),
+ [ 'pager-limit' => 2 ],
// filter
- function( $found ) {
- return array_filter( $found, function( $obj ) { return $obj->foo > 'B'; } );
+ function ( $found ) {
+ return array_filter( $found, function ( $obj ) {
+ return $obj->foo > 'B';
+ } );
},
- ),
+ ],
- array(
+ [
'Multi-query edge case must issue second query',
// expect
- array(
- 'fwd' => array(
+ [
+ 'fwd' => [
'offset-dir' => 'fwd',
'limit' => 2,
'offset' => 'serialized-C',
- ),
- ),
- array(
- array( $objs['A'], $objs['B'], $objs['C'] ),
- array( $objs['D'], $objs['E'], $objs['F'] ),
- ),
- array( 'pager-limit' => 2 ),
+ ],
+ ],
+ [
+ [ $objs['A'], $objs['B'], $objs['C'] ],
+ [ $objs['D'], $objs['E'], $objs['F'] ],
+ ],
+ [ 'pager-limit' => 2 ],
// filter
- function( $found ) {
- return array_filter( $found, function( $obj ) { return $obj->foo !== 'A'; } );
+ function ( $found ) {
+ return array_filter( $found, function ( $obj ) {
+ return $obj->foo !== 'A';
+ } );
},
- ),
+ ],
- array(
- 'Reverse pagination when offset-id is present in options',
+ [
+ 'Reverse pagination when offset is present in options',
// expect
- array(
- 'rev' => array(
+ [
+ 'rev' => [
'offset-dir' => 'rev',
'limit' => 2,
'offset' => 'serialized-B',
- ),
- 'fwd' => array(
+ ],
+ 'fwd' => [
'offset-dir' => 'fwd',
'limit' => 2,
'offset' => 'serialized-C',
- ),
- ),
+ ],
+ ],
// find results
- array(
- array( $objs['B'], $objs['C'], $objs['D'] ),
- ),
+ [
+ [ $objs['B'], $objs['C'], $objs['D'] ],
+ ],
// pager options
- array(
+ [
'pager-limit' => 2,
'pager-offset' => 'serialized-A',
'pager-dir' => 'fwd',
- ),
+ ],
// filter
null,
- ),
- );
+ ],
+ ];
}
/**
@@ -257,7 +258,7 @@ class PagerTest extends \MediaWikiTestCase {
public function testGetPagingLinkOptions( $message, $expect, $found, array $options, $filter ) {
$pager = new Pager(
$this->mockObjectManager( $found ),
- array( 'otherthing' => 42 ),
+ [ 'otherthing' => 42 ],
$options
);
$page = $pager->getPage( $filter );
@@ -266,73 +267,73 @@ class PagerTest extends \MediaWikiTestCase {
}
public static function optionsPassedToObjectManagerFindProvider() {
- return array(
- array(
+ return [
+ [
'Requests one more object than pagination is for',
// expect
- array( 'limit' => 3 ),
+ [ 'limit' => 3 ],
// pager options
- array(
+ [
'pager-limit' => 2,
- )
- ),
+ ]
+ ],
- array(
+ [
'Pager limit cannot be negative',
// expect
- array( 'limit' => 2 ),
+ [ 'limit' => 2 ],
// pager options
- array( 'pager-limit' => -99 ),
- ),
+ [ 'pager-limit' => -99 ],
+ ],
- array(
+ [
'Pager limit cannot exceed 500',
// expect
- array( 'limit' => 2 ),
+ [ 'limit' => 2 ],
// pager options
- array( 'pager-limit' => 501 ),
- ),
+ [ 'pager-limit' => 501 ],
+ ],
- array(
+ [
'Offset dir defaults to fwd',
// expect
- array( 'offset-dir' => 'fwd' ),
+ [ 'offset-dir' => 'fwd' ],
// pager options
- array(),
- ),
+ [],
+ ],
- array(
+ [
'Offset dir can be reversed',
// expect
- array( 'offset-dir' => 'rev' ),
+ [ 'offset-dir' => 'rev' ],
// pager options
- array( 'pager-dir' => 'rev' ),
- ),
+ [ 'pager-dir' => 'rev' ],
+ ],
- array(
+ [
'Gracefully handles unknown offset dir',
// expect
- array( 'offset-dir' => 'fwd' ),
+ [ 'offset-dir' => 'fwd' ],
// pager options
- array( 'pager-dir' => 'yabba dabba do' ),
- ),
+ [ 'pager-dir' => 'yabba dabba do' ],
+ ],
- array(
- 'offset-id defaults to null',
+ [
+ 'offset-value defaults to null',
// expect
- array( 'offset-id' => null ),
+ [ 'offset-value' => null ],
// pager options
- array()
- ),
+ []
+ ],
- array(
- 'initial offset-id is set by providing pager-offset',
+ [
+ 'initial offset-value is set by providing pager-offset',
// expect
- array( 'offset-id' => 'echo and flow' ),
+ [ 'offset-value' => 'echo and flow' ],
// pager options
- array( 'pager-offset' => 'echo and flow' ),
- ),
- );
+ [ 'pager-offset' => 'echo and flow' ],
+ ],
+ ];
}
/**
@@ -349,7 +350,7 @@ class PagerTest extends \MediaWikiTestCase {
$pager = new Pager(
$om,
- array( 'otherthing' => 42 ),
+ [ 'otherthing' => 42 ],
$options
);
$page = $pager->getPage();
@@ -362,139 +363,11 @@ class PagerTest extends \MediaWikiTestCase {
}
}
- public function includeOffsetProvider() {
- return array(
- array(
- '',
- // expected returned series of 'bar' values
- array( 5, 4, 3, 2, 1 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => true,
- ),
- ),
- array(
- '',
- // expected returned series of 'bar' values
- array( 4, 3, 2, 1 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => false,
- ),
- ),
- array(
- '',
- // expected returned series of 'bar' values
- array( 9, 8, 7, 6, 5 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => true,
- 'offset-dir' => 'rev',
- 'offset-elastic' => false,
- ),
- ),
- array(
- '',
- // expected returned series of 'bar' values
- array( 9, 8, 7, 6 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => false,
- 'offset-dir' => 'rev',
- 'offset-elastic' => false,
- ),
- ),
- array(
- '',
- // expected returned series of 'bar' values
- array( 9, 8, 7, 6, 5, 4, 3, 2, 1 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => true,
- 'offset-dir' => 'rev',
- 'offset-elastic' => true,
- ),
- ),
- array(
- '',
- // expected returned series of 'bar' values
- array( 9, 8, 7, 6, 5, 4, 3, 2, 1 ),
- // query options
- array(
- 'offset-id' => 5,
- 'include-offset' => false,
- 'offset-dir' => 'rev',
- 'offset-elastic' => true,
- ),
- ),
-
- );
- }
-
- /**
- * @dataProvider includeOffsetProvider
- */
- public function testIncludeOffset( $message, $expect, $queryOptions ) {
- global $wgFlowCacheVersion;
-
- $bag = new \HashBagOStuff();
- $innerCache = new LocalBufferedBagOStuff( $bag );
- $cache = new BufferedCache( $innerCache );
-
- // preload our answer
- $bag->set( wfWikiId() . ":prefix:1:$wgFlowCacheVersion", array(
- array( 'foo' => 1, 'bar' => 9 ),
- array( 'foo' => 1, 'bar' => 8 ),
- array( 'foo' => 1, 'bar' => 7 ),
- array( 'foo' => 1, 'bar' => 6 ),
- array( 'foo' => 1, 'bar' => 5 ),
- array( 'foo' => 1, 'bar' => 4 ),
- array( 'foo' => 1, 'bar' => 3 ),
- array( 'foo' => 1, 'bar' => 2 ),
- array( 'foo' => 1, 'bar' => 1 ),
- ) );
-
- $storage = $this->getMock( 'Flow\Data\ObjectStorage' );
- // fake ObjectMapper that doesn't roundtrip to- & fromStorageRow
- $mapper = $this->getMockBuilder( 'Flow\Data\Mapper\BasicObjectMapper' )
- ->disableOriginalConstructor()
- ->getMock();
- $mapper->expects( $this->any() )
- ->method( 'normalizeRow' )
- ->will( $this->returnArgument( 0 ) );
-
- $index = new TopKIndex(
- $cache,
- $storage,
- $mapper,
- 'prefix',
- array( 'foo' ),
- array(
- 'sort' => 'bar',
- )
- );
-
- $result = $index->find( array( 'foo' => '1' ), $queryOptions );
- foreach ( $result as $row ) {
- $found[] = $row['bar'];
- }
-
- $this->assertEquals(
- $expect,
- $found
- );
- }
-
- protected function mockObjectManager( array $found = array() ) {
+ protected function mockObjectManager( array $found = [] ) {
$index = $this->getMock( 'Flow\Data\Index' );
$index->expects( $this->any() )
->method( 'getSort' )
- ->will( $this->returnValue( array( 'something' ) ) );
+ ->will( $this->returnValue( [ 'something' ] ) );
$om = $this->getMockBuilder( 'Flow\Data\ObjectManager' )
->disableOriginalConstructor()
->getMock();
@@ -503,7 +376,7 @@ class PagerTest extends \MediaWikiTestCase {
->will( $this->returnValue( $index ) );
$om->expects( $this->any() )
->method( 'serializeOffset' )
- ->will( $this->returnCallback( function( $obj, $sort ) {
+ ->will( $this->returnCallback( function ( $obj, $sort ) {
return 'serialized-' . $obj->foo;
} ) );
@@ -511,11 +384,102 @@ class PagerTest extends \MediaWikiTestCase {
$om->expects( $this->any() )
->method( 'find' )
->will( call_user_func_array(
- array( $this, 'onConsecutiveCalls' ),
- array_map( array( $this, 'returnValue' ), $found )
+ [ $this, 'onConsecutiveCalls' ],
+ array_map( [ $this, 'returnValue' ], $found )
) );
}
return $om;
}
+
+ public function provideDataMakePagingLink() {
+ return [
+ [
+ $this->mockStorage(
+ [
+ $this->mockTopicListEntry(),
+ $this->mockTopicListEntry(),
+ $this->mockTopicListEntry()
+ ],
+ UUID::create(),
+ [ 'topic_id' ]
+ ),
+ [ 'topic_list_id' => '123456' ],
+ [ 'pager-limit' => 2, 'order' => 'desc', 'sort' => 'topic_id' ],
+ 'offset-id'
+ ],
+ [
+ $this->mockStorage(
+ [
+ $this->mockTopicListEntry(),
+ $this->mockTopicListEntry()
+ ],
+ UUID::create(),
+ [ 'workflow_last_update_timestamp' ]
+ ),
+ [ 'topic_list_id' => '123456' ],
+ [ 'pager-limit' => 1, 'order' => 'desc', 'sort' => 'workflow_last_update_timestamp', 'sortby' => 'updated' ],
+ 'offset'
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider provideDataMakePagingLink
+ */
+ public function testMakePagingLink( $storage, $query, $options, $offsetKey ) {
+ $pager = new Pager( $storage, $query, $options );
+ $page = $pager->getPage();
+ $pagingOption = $page->getPagingLinksOptions();
+ foreach ( $pagingOption as $option ) {
+ $this->assertArrayHasKey( $offsetKey, $option );
+ $this->assertArrayHasKey( 'offset-dir', $option );
+ $this->assertArrayHasKey( 'limit', $option );
+ if ( isset( $options['sortby'] ) ) {
+ $this->assertArrayHasKey( 'sortby', $option );
+ }
+ }
+ }
+
+ /**
+ * Mock the storage
+ */
+ protected function mockStorage( $return, $offset, $sort ) {
+ $storage = $this->getMockBuilder( 'Flow\Data\ObjectManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $storage->expects( $this->any() )
+ ->method( 'find' )
+ ->will( $this->returnValue( $return ) );
+ $storage->expects( $this->any() )
+ ->method( 'serializeOffset' )
+ ->will( $this->returnValue( $offset ) );
+ $storage->expects( $this->any() )
+ ->method( 'getIndexFor' )
+ ->will( $this->returnValue( $this->mockIndex( $sort ) ) );
+ return $storage;
+ }
+
+ /**
+ * Mock TopicListEntry
+ */
+ protected function mockTopicListEntry() {
+ $entry = $this->getMockBuilder( 'Flow\Model\TopicListEntry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ return $entry;
+ }
+
+ /**
+ * Mock TopKIndex
+ */
+ protected function mockIndex( $sort ) {
+ $index = $this->getMockBuilder( 'Flow\Data\Index\TopKIndex' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $index->expects( $this->any() )
+ ->method( 'getSort' )
+ ->will( $this->returnValue( $sort ) );
+ return $index;
+ }
}
diff --git a/Flow/tests/phpunit/Data/Storage/RevisionStorageTest.php b/Flow/tests/phpunit/Data/Storage/RevisionStorageTest.php
index 05513a07..59c95e8a 100644
--- a/Flow/tests/phpunit/Data/Storage/RevisionStorageTest.php
+++ b/Flow/tests/phpunit/Data/Storage/RevisionStorageTest.php
@@ -12,53 +12,53 @@ use Flow\Tests\FlowTestCase;
* @group Flow
*/
class RevisionStorageTest extends FlowTestCase {
- protected $BEFORE_WITHOUT_CONTENT_CHANGE = array(
+ protected $BEFORE_WITHOUT_CONTENT_CHANGE = [
'rev_content_url' => 'FlowMock://345',
'rev_content' => 'Hello, world!',
'rev_type' => 'reply',
'rev_mod_user_wiki' => 'devwiki',
- );
+ ];
- protected $AFTER_WITHOUT_CONTENT_CHANGE = array(
+ protected $AFTER_WITHOUT_CONTENT_CHANGE = [
'rev_content_url' => 'FlowMock://345',
'rev_content' => 'Hello, world!',
'rev_type' => 'reply',
'rev_mod_user_wiki' => 'testwiki',
- );
+ ];
- protected $WITHOUT_CONTENT_CHANGE_DIFF = array(
+ protected $WITHOUT_CONTENT_CHANGE_DIFF = [
'rev_mod_user_wiki' => 'testwiki',
- );
+ ];
- protected $BEFORE_WITH_CONTENT_CHANGE = array(
+ protected $BEFORE_WITH_CONTENT_CHANGE = [
'rev_content_url' => 'FlowMock://249',
'rev_content' => 'Hello, world!<span onclick="alert(\'Hacked\');">Test</span>',
'rev_type' => 'reply',
'rev_mod_user_wiki' => 'devwiki',
- );
+ ];
- protected $AFTER_WITH_CONTENT_CHANGE = array(
+ protected $AFTER_WITH_CONTENT_CHANGE = [
// URL is deliberately stale here; since the column diff shows a content
// change, processExternalContent is in charge of updating the URL.
'rev_content_url' => 'FlowMock://249',
'rev_content' => 'Hello, world!<span>Test</span>',
'rev_type' => 'reply',
'rev_mod_user_wiki' => 'devwiki',
- );
+ ];
- protected $WITH_CONTENT_CHANGE_DIFF = array(
+ protected $WITH_CONTENT_CHANGE_DIFF = [
'rev_content' => 'FlowMock://1',
'rev_flags' => 'external',
- );
+ ];
- protected $MOCK_EXTERNAL_STORE_CONFIG = array(
+ protected $MOCK_EXTERNAL_STORE_CONFIG = [
'FlowMock://',
- );
+ ];
- public function setup() {
- $this->setMwGlobals( array(
- 'wgExternalStores' => array( 'FlowMock' ),
- ) );
+ protected function setUp() {
+ $this->setMwGlobals( [
+ 'wgExternalStores' => [ 'FlowMock' ],
+ ] );
\ExternalStoreFlowMock::$isUsed = false;
@@ -99,7 +99,6 @@ class RevisionStorageTest extends FlowTestCase {
$diff,
'When content changes are allowed, and there is a content change, the diff shows the updated URL'
);
-
}
public function testCalcUpdatesWithoutContentChangeWhenNotAllowed() {
@@ -176,9 +175,9 @@ class RevisionStorageTest extends FlowTestCase {
->with(
$this->equalTo( 'flow_revision' ),
$this->equalTo( $expectedUpdateValues ),
- $this->equalTo( array(
+ $this->equalTo( [
'rev_id' => $id->getBinary(),
- ) )
+ ] )
)
->will( $this->returnValue( true ) );
$dbw->expects( $this->any() )
@@ -197,14 +196,13 @@ class RevisionStorageTest extends FlowTestCase {
$old,
$new
);
-
}
public function isUpdatingExistingRevisionContentAllowedProvider() {
- return array(
- array( true ),
- array( false )
- );
+ return [
+ [ true ],
+ [ false ]
+ ];
}
/**
@@ -224,7 +222,7 @@ class RevisionStorageTest extends FlowTestCase {
*
* @return HeaderRevisionStorage
*/
- protected function getRevisionStorageWithMockExternalStore( $allowContentUpdates) {
+ protected function getRevisionStorageWithMockExternalStore( $allowContentUpdates ) {
$revisionStorage = new HeaderRevisionStorage(
Container::get( 'db.factory' ),
$this->MOCK_EXTERNAL_STORE_CONFIG
@@ -234,19 +232,19 @@ class RevisionStorageTest extends FlowTestCase {
return $revisionStorage;
}
- protected function setWhetherContentUpdatingAllowed( $revisionStorage, $allowContentUpdates) {
+ protected function setWhetherContentUpdatingAllowed( $revisionStorage, $allowContentUpdates ) {
$klass = new \ReflectionClass( 'Flow\Data\Storage\HeaderRevisionStorage' );
$allowedUpdateColumnsProp = $klass->getProperty( 'allowedUpdateColumns' );
$allowedUpdateColumnsProp->setAccessible( true );
$allowedUpdateColumns = $allowedUpdateColumnsProp->getValue( $revisionStorage );
- $requiredContentColumns = array(
+ $requiredContentColumns = [
'rev_content',
'rev_content_length',
'rev_flags',
'rev_previous_content_length',
- );
+ ];
if ( $allowContentUpdates ) {
$allowedUpdateColumns = array_merge(
@@ -264,65 +262,65 @@ class RevisionStorageTest extends FlowTestCase {
public function testUpdateConvertsPrimaryKeyToBinary() {
$this->helperToTestUpdating(
- array(
+ [
'rev_mod_user_id' => 0,
- ),
- array(
+ ],
+ [
'rev_mod_user_id' => 42,
- ),
- array(
+ ],
+ [
'rev_mod_user_id' => 42,
- ),
+ ],
false
);
}
public static function issuesQueryCountProvider() {
- return array(
- array(
+ return [
+ [
'Query by rev_id issues one query',
// db queries issued
1,
// queries
- array(
- array( 'rev_id' => 1 ),
- array( 'rev_id' => 8 ),
- array( 'rev_id' => 3 ),
- ),
+ [
+ [ 'rev_id' => 1 ],
+ [ 'rev_id' => 8 ],
+ [ 'rev_id' => 3 ],
+ ],
// query options
- array( 'LIMIT' => 1 )
- ),
+ [ 'LIMIT' => 1 ]
+ ],
- array(
+ [
'Query by rev_id issues one query with string limit',
// db queries issued
1,
// queries
- array(
- array( 'rev_id' => 1 ),
- array( 'rev_id' => 8 ),
- array( 'rev_id' => 3 ),
- ),
+ [
+ [ 'rev_id' => 1 ],
+ [ 'rev_id' => 8 ],
+ [ 'rev_id' => 3 ],
+ ],
// query options
- array( 'LIMIT' => '1' )
- ),
+ [ 'LIMIT' => '1' ]
+ ],
- array(
+ [
'Query for most recent revision issues two queries',
// db queries issued
2,
// queries
- array(
- array( 'rev_type_id' => 19 ),
- array( 'rev_type_id' => 22 ),
- array( 'rev_type_id' => 4 ),
- array( 'rev_type_id' => 44 ),
- ),
+ [
+ [ 'rev_type_id' => 19 ],
+ [ 'rev_type_id' => 22 ],
+ [ 'rev_type_id' => 4 ],
+ [ 'rev_type_id' => 44 ],
+ ],
// query options
- array( 'LIMIT' => 1, 'ORDER BY' => array( 'rev_id DESC' ) ),
- ),
+ [ 'LIMIT' => 1, 'ORDER BY' => [ 'rev_id DESC' ] ],
+ ],
- );
+ ];
}
/**
@@ -336,11 +334,11 @@ class RevisionStorageTest extends FlowTestCase {
$this->fail( '<= 2 queries always issues the same number of queries' );
}
- $result = array();
+ $result = [];
foreach ( $queries as $query ) {
// this is not in any way a real result, but enough to get through
// the result processing
- $result[] = (object)( $query + array( 'rev_id' => 42, 'tree_rev_id' => 42, 'rev_flags' => '' ) );
+ $result[] = (object)( $query + [ 'rev_id' => 42, 'tree_rev_id' => 42, 'rev_flags' => '' ] );
}
$treeRepo = $this->getMockBuilder( 'Flow\Repository\TreeRepository' )
@@ -364,27 +362,27 @@ class RevisionStorageTest extends FlowTestCase {
$factory = $this->mockDbFactory();
$factory->getDB( null )->expects( $this->once() )
->method( 'select' )
- ->will( $this->returnValue( array(
- (object)array( 'rev_id' => 42, 'rev_flags' => '' )
- ) ) );
+ ->will( $this->returnValue( [
+ (object)[ 'rev_id' => 42, 'rev_flags' => '' ]
+ ] ) );
$storage = new PostRevisionStorage( $factory, false, $treeRepo );
$res = $storage->findMulti(
- array(
- array( 'rev_id' => 12 ),
- array( 'rev_id' => 42 ),
- array( 'rev_id' => 17 ),
- ),
- array( 'LIMIT' => 1 )
+ [
+ [ 'rev_id' => 12 ],
+ [ 'rev_id' => 42 ],
+ [ 'rev_id' => 17 ],
+ ],
+ [ 'LIMIT' => 1 ]
);
$this->assertSame(
- array(
+ [
null,
- array( array( 'rev_id' => 42, 'rev_flags' => '', 'rev_content_url' => null ) ),
+ [ [ 'rev_id' => 42, 'rev_flags' => '', 'rev_content_url' => null ] ],
null,
- ),
+ ],
$res,
'Unfound items must be represented with null in the result array'
);
diff --git a/Flow/tests/phpunit/Data/UserNameBatchTest.php b/Flow/tests/phpunit/Data/UserNameBatchTest.php
index 24fc06bc..c62b3e9b 100644
--- a/Flow/tests/phpunit/Data/UserNameBatchTest.php
+++ b/Flow/tests/phpunit/Data/UserNameBatchTest.php
@@ -18,13 +18,13 @@ class UserNameBatchTest extends FlowTestCase {
$this->assertEquals( 'Whale', $batch->get( 'fakewiki', 42 ) );
}
- static public function acceptsStringOrIntIdsProvider() {
- return array(
- array( 42, 42 ),
- array( 42, '42' ),
- array( '42', 42 ),
- array( '42', '42' ),
- );
+ public static function acceptsStringOrIntIdsProvider() {
+ return [
+ [ 42, 42 ],
+ [ 42, '42' ],
+ [ '42', 42 ],
+ [ '42', '42' ],
+ ];
}
/**
@@ -40,7 +40,7 @@ class UserNameBatchTest extends FlowTestCase {
$query = $this->getMock( 'Flow\Repository\UserName\UserNameQuery' );
$query->expects( $this->once() )
->method( 'execute' )
- ->with( 'fakewiki', array( 12, 27, 18 ) );
+ ->with( 'fakewiki', [ 12, 27, 18 ] );
$batch = new UserNameBatch( $query );
$batch->add( 'fakewiki', 12 );
@@ -53,7 +53,7 @@ class UserNameBatchTest extends FlowTestCase {
$query = $this->getMock( 'Flow\Repository\UserName\UserNameQuery' );
$query->expects( $this->once() )
->method( 'execute' )
- ->with( 'fakewiki', array( 42 ) );
+ ->with( 'fakewiki', [ 42 ] );
$batch = new UserNameBatch( $query );
$this->assertEquals( false, $batch->get( 'fakewiki', 42 ) );
@@ -63,10 +63,10 @@ class UserNameBatchTest extends FlowTestCase {
$query = $this->getMock( 'Flow\Repository\UserName\\UserNameQuery' );
$query->expects( $this->once() )
->method( 'execute' )
- ->with( 'fakewiki', array( 610, 408 ) )
- ->will( $this->returnValue( array(
- (object)array( 'user_id' => '408', 'user_name' => 'chuck' )
- ) ) );
+ ->with( 'fakewiki', [ 610, 408 ] )
+ ->will( $this->returnValue( [
+ (object)[ 'user_id' => '408', 'user_name' => 'chuck' ]
+ ] ) );
$batch = new UserNameBatch( $query );
$batch->add( 'fakewiki', 610 );
diff --git a/Flow/tests/phpunit/Data/UserNameListenerTest.php b/Flow/tests/phpunit/Data/UserNameListenerTest.php
index 216afac0..6f76ae2c 100644
--- a/Flow/tests/phpunit/Data/UserNameListenerTest.php
+++ b/Flow/tests/phpunit/Data/UserNameListenerTest.php
@@ -15,13 +15,17 @@ use Flow\Tests\FlowTestCase;
class UserNameListenerTest extends FlowTestCase {
public function onAfterLoadDataProvider() {
- return array (
- array( array( 'user_id' => '1', 'user_wiki' => 'frwiki' ), array( 'user_id' => 'user_wiki' ), 'frwiki', 'enwiki' ),
- array( array( 'user_id' => '2' ), array( 'user_id' => null ), 'enwiki', 'enwiki' ),
- array( array( 'user_id' => '3' ), array( 'user_id' => 'user_wiki' ), null ),
- // Use closure because wfWikiId() in testxxx() functions appends -unittest_ at the end
- array( array( 'user_id' => '4' ), array( 'user_id' => null ), function() { return wfWikiId(); } ),
- );
+ return [
+ [ [ 'user_id' => '1', 'user_wiki' => 'frwiki' ], [ 'user_id' => 'user_wiki' ], 'frwiki', 'enwiki' ],
+ [ [ 'user_id' => '2' ], [ 'user_id' => null ], 'enwiki', 'enwiki' ],
+ [ [ 'user_id' => '3' ], [ 'user_id' => 'user_wiki' ], null ],
+ // Use closure because wfWikiID() in testxxx() functions appends -unittest_ at the end
+ [ [ 'user_id' => '4' ], [ 'user_id' => null ],
+ function () {
+ return wfWikiID();
+ }
+ ],
+ ];
}
/**
diff --git a/Flow/tests/phpunit/FlowActionsTest.php b/Flow/tests/phpunit/FlowActionsTest.php
index 5a29435a..e3454691 100644
--- a/Flow/tests/phpunit/FlowActionsTest.php
+++ b/Flow/tests/phpunit/FlowActionsTest.php
@@ -10,12 +10,12 @@ use Flow\FlowActions;
class FlowActionsTest extends \MediaWikiTestCase {
public function testAliasedTopLevelValues() {
- $actions = new FlowActions( array(
+ $actions = new FlowActions( [
'something' => 'aliased',
- 'aliased' => array(
+ 'aliased' => [
'real' => 'value',
- ),
- ) );
+ ],
+ ] );
$this->assertEquals( 'value', $actions->getValue( 'something', 'real' ) );
}
diff --git a/Flow/tests/phpunit/FlowTestCase.php b/Flow/tests/phpunit/FlowTestCase.php
index decc326c..122cfbcd 100644
--- a/Flow/tests/phpunit/FlowTestCase.php
+++ b/Flow/tests/phpunit/FlowTestCase.php
@@ -2,10 +2,13 @@
namespace Flow\Tests;
-use Status;
-
+use EventRelayerNull;
+use ExtensionRegistry;
use Flow\Container;
+use Flow\Data\FlowObjectCache;
use Flow\Model\UUID;
+use HashBagOStuff;
+use WANObjectCache;
class FlowTestCase extends \MediaWikiTestCase {
protected function setUp() {
@@ -26,4 +29,25 @@ class FlowTestCase extends \MediaWikiTestCase {
return parent::dataToString( $data );
}
+
+ protected function getCache() {
+ global $wgFlowCacheTime;
+ $wanCache = new WANObjectCache( [
+ 'cache' => new HashBagOStuff(),
+ 'pool' => 'testcache-hash',
+ 'relayer' => new EventRelayerNull( [] )
+ ] );
+
+ return new FlowObjectCache( $wanCache, Container::get( 'db.factory' ), $wgFlowCacheTime );
+ }
+
+ protected function resetPermissions() {
+ $registry = new ExtensionRegistry();
+ $data = $registry->readFromQueue( [ __DIR__ . '/../../extension.json' => 1 ] );
+ $perms = $data['globals']['wgGroupPermissions'];
+ unset( $perms[$registry::MERGE_STRATEGY] );
+ $this->stashMwGlobals( [ 'wgGroupPermissions' ] );
+ global $wgGroupPermissions;
+ $wgGroupPermissions = wfArrayPlus2d( $perms, $wgGroupPermissions );
+ }
}
diff --git a/Flow/tests/phpunit/Formatter/FormatterTest.php b/Flow/tests/phpunit/Formatter/FormatterTest.php
index e1e544ae..62b62e93 100644
--- a/Flow/tests/phpunit/Formatter/FormatterTest.php
+++ b/Flow/tests/phpunit/Formatter/FormatterTest.php
@@ -15,32 +15,32 @@ use Title;
*/
class FormatterTest extends FlowTestCase {
- static public function checkUserProvider() {
+ public static function checkUserProvider() {
$topicId = UUID::create();
$revId = UUID::create();
$postId = UUID::create();
- return array(
- array(
+ return [
+ [
'With only a topicId reply should not fail',
// result must contain
- function( $test, $message, $result ) {
+ function ( $test, $message, $result ) {
$test->assertNotNull( $result );
$test->assertArrayHasKey( 'links', $result, $message );
},
// cuc_comment parameters
'reply', $topicId, $revId, null
- ),
+ ],
- array(
+ [
'With topicId and postId should not fail',
- function( $test, $message, $result ) {
+ function ( $test, $message, $result ) {
$test->assertNotNull( $result );
$test->assertArrayHasKey( 'links', $result, $message );
},
'reply', $topicId, $revId, $postId,
- ),
- );
+ ],
+ ];
}
/**
@@ -70,9 +70,9 @@ class FormatterTest extends FlowTestCase {
// Code uses wfWarn as a louder wfDebugLog in error conditions.
// but phpunit considers a warning a fail.
- wfSuppressWarnings();
+ \MediaWiki\suppressWarnings();
$links = $this->createFormatter( 'Flow\Formatter\CheckUserFormatter' )->format( $row, $ctx );
- wfRestoreWarnings();
+ \MediaWiki\restoreWarnings();
$test( $this, $message, $links );
}
diff --git a/Flow/tests/phpunit/Formatter/RevisionFormatterTest.php b/Flow/tests/phpunit/Formatter/RevisionFormatterTest.php
index 34bba91b..572d3e79 100644
--- a/Flow/tests/phpunit/Formatter/RevisionFormatterTest.php
+++ b/Flow/tests/phpunit/Formatter/RevisionFormatterTest.php
@@ -2,11 +2,14 @@
namespace Flow\Tests\Formatter;
+use Flow\Exception\FlowException;
use Flow\FlowActions;
use Flow\Formatter\FormatterRow;
use Flow\Formatter\RevisionFormatter;
use Flow\Model\PostRevision;
+use Flow\Model\UUID;
use Flow\Model\Workflow;
+use Flow\Tests\PostRevisionTestCase;
use RequestContext;
use Title;
use User;
@@ -14,29 +17,227 @@ use User;
/**
* @group Flow
*/
-class RevisionFormatterTest extends \MediaWikiTestCase {
+class RevisionFormatterTest extends PostRevisionTestCase {
protected $user;
- public function setUp() {
+ protected $topicTitleRevisionUnspecified;
+
+ protected $topicTitleRevisionSpecified;
+
+ protected $postRevisionUnspecified;
+
+ protected $postRevisionSpecified;
+
+ protected function setUp() {
parent::setUp();
+
$this->user = User::newFromName( '127.0.0.1', false );
+
+ // These tests don't provide sufficient data to properly run all listeners
+ $this->clearExtraLifecycleHandlers();
+ }
+
+ /**
+ * @dataProvider decideContentFormatProvider
+ */
+ public function testDecideContentFormat( $expectedFormat, $setContentRequestedFormat, $setContentRevisionId, $revision ) {
+ list( $formatter ) = $this->makeFormatter();
+ $formatter->setContentFormat( $setContentRequestedFormat, $setContentRevisionId );
+
+ $this->assertEquals(
+ $expectedFormat,
+ $formatter->decideContentFormat( $revision )
+ );
+ }
+
+ public function decideContentFormatProvider() {
+ $topicTitleRevisionUnspecified = $this->mockTopicTitleRevision();
+ $topicTitleRevisionSpecified = $this->mockTopicTitleRevision();
+
+ $postRevisionUnspecified = $this->mockPostRevision();
+ $postRevisionSpecified = $this->mockPostRevision();
+
+ return [
+ [
+ 'topic-title-html',
+ 'fixed-html',
+ null,
+ $topicTitleRevisionUnspecified,
+ ],
+ // Specified for a different revision, so uses canonicalized
+ // version of class default (fixed-html => topic-title-html).
+ [
+ 'topic-title-html',
+ 'topic-title-wikitext',
+ $topicTitleRevisionSpecified->getRevisionId(),
+ $topicTitleRevisionUnspecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ 'html',
+ null,
+ $topicTitleRevisionUnspecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ 'wikitext',
+ null,
+ $topicTitleRevisionUnspecified,
+ ],
+ [
+ 'fixed-html',
+ 'fixed-html',
+ null,
+ $postRevisionUnspecified,
+ ],
+ // We've specified it, but for another rev ID, so it uses the class default
+ // of fixed-html.
+ [
+ 'fixed-html',
+ 'wikitext',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionUnspecified,
+ ],
+ [
+ 'html',
+ 'html',
+ null,
+ $postRevisionUnspecified,
+ ],
+ [
+ 'wikitext',
+ 'wikitext',
+ null,
+ $postRevisionUnspecified,
+ ],
+ [
+ 'topic-title-html',
+ 'topic-title-html',
+ null,
+ $topicTitleRevisionUnspecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ 'topic-title-wikitext',
+ null,
+ $topicTitleRevisionUnspecified,
+ ],
+ [
+ 'topic-title-html',
+ 'topic-title-html',
+ $topicTitleRevisionSpecified->getRevisionId(),
+ $topicTitleRevisionSpecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ 'topic-title-wikitext',
+ $topicTitleRevisionSpecified->getRevisionId(),
+ $topicTitleRevisionSpecified,
+ ],
+ [
+ 'fixed-html',
+ 'fixed-html',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionSpecified,
+ ],
+ [
+ 'html',
+ 'html',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionSpecified,
+ ],
+ [
+ 'wikitext',
+ 'wikitext',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionSpecified,
+ ],
+ ];
+ }
+
+ /**
+ * @expectedException \Flow\Exception\FlowException
+ * @dataProvider decideContentInvalidFormatProvider
+ */
+ public function testDecideContentInvalidFormat( $setContentRequestedFormat, $setContentRevisionId, $revision ) {
+ list( $formatter ) = $this->makeFormatter();
+ $formatter->setContentFormat( $setContentRequestedFormat, $setContentRevisionId );
+ $formatter->decideContentFormat( $revision );
+ }
+
+ public function decideContentInvalidFormatProvider() {
+ $topicTitleRevisionSpecified = $this->mockTopicTitleRevision();
+ $postRevisionSpecified = $this->mockPostRevision();
+ $postRevisionUnspecified = $this->mockPostRevision();
+
+ return [
+ [
+ 'wikitext',
+ $topicTitleRevisionSpecified->getRevisionId(),
+ $topicTitleRevisionSpecified,
+ ],
+ [
+ 'topic-title-html',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionSpecified,
+ ],
+ [
+ 'topic-title-html',
+ null,
+ $postRevisionUnspecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ $postRevisionSpecified->getRevisionId(),
+ $postRevisionSpecified,
+ ],
+ [
+ 'topic-title-wikitext',
+ null,
+ $postRevisionUnspecified,
+ ],
+ ];
+ }
+
+ /**
+ * @expectedException \Flow\Exception\FlowException
+ * @dataProvider setContentFormatInvalidProvider
+ */
+ public function testSetContentFormatInvalidProvider( $requestedFormat, $revisionId ) {
+ list( $formatter ) = $this->makeFormatter();
+ $formatter->setContentFormat( $requestedFormat, $revisionId );
+ }
+
+ public function setContentFormatInvalidProvider() {
+ $postRevisionSpecified = $this->mockPostRevision();
+
+ return [
+ [
+ 'fake-format',
+ null
+ ],
+ [
+ 'another-fake-format',
+ $postRevisionSpecified->getRevisionId()
+ ],
+ ];
}
public function testMockFormatterBasicallyWorks() {
- list( $formatter, $ctx ) = $this->mockFormatter();
- $result = $formatter->formatApi( $this->generateRow( 'my new topic' ), $ctx );
+ list( $formatter, $ctx ) = $this->makeFormatter();
+ $result = $formatter->formatApi( $this->generateFormatterRow( 'my new topic' ), $ctx );
$this->assertEquals( 'new-post', $result['changeType'] );
$this->assertEquals( 'my new topic', $result['content']['content'] );
}
public function testFormattingEditedTitle() {
- list( $formatter, $ctx ) = $this->mockFormatter();
- $row = $this->generateRow();
+ list( $formatter, $ctx ) = $this->makeFormatter();
+ $row = $this->generateFormatterRow();
$row->previousRevision = $row->revision;
$row->revision = $row->revision->newNextRevision(
$this->user,
'replacement content',
- 'wikitext',
+ 'topic-title-wikitext',
'edit-title',
$row->workflow->getArticleTitle()
);
@@ -49,9 +250,9 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
$content = 'something something';
$nextContent = 'ברוכים הבאים לוויקיפדיה!';
- list( $formatter, $ctx, $permissions, $templating, $usernames, $actions ) = $this->mockFormatter( true );
+ list( $formatter, $ctx, $permissions, $templating, $usernames, $actions ) = $this->makeFormatter( true );
- $row = $this->generateRow( $content );
+ $row = $this->generateFormatterRow( $content );
$result = $formatter->formatApi( $row, $ctx );
$this->assertEquals(
strlen( $content ),
@@ -69,7 +270,7 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
$row->revision = $row->currentRevision = $row->revision->newNextRevision(
$this->user,
$nextContent,
- 'wikitext',
+ 'topic-title-wikitext',
'edit-title',
$row->workflow->getArticleTitle()
);
@@ -86,11 +287,15 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
);
}
- public function generateRow( $plaintext = 'titlebar content' ) {
+ public function generateFormatterRow( $wikitext = 'titlebar content' ) {
$row = new FormatterRow;
+
$row->workflow = Workflow::create( 'topic', Title::newMainPage() );
- $row->rootPost = PostRevision::create( $row->workflow, $this->user, $plaintext, 'wikitext' );
+ $this->workflows[$row->workflow->getId()->getAlphadecimal()] = $row->workflow;
+
+ $row->rootPost = PostRevision::createTopicPost( $row->workflow, $this->user, $wikitext );
$row->revision = $row->currentRevision = $row->rootPost;
+ $this->store( $row->revision );
return $row;
}
@@ -118,6 +323,17 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
return $permissions;
}
+ protected function mockPostRevision() {
+ $postRevision = $this->getMockBuilder( 'Flow\Model\PostRevision' )->getMock();
+ $postRevision->expects( $this->any() )
+ ->method( 'isTopicTitle' )
+ ->will( $this->returnValue( false ) );
+ $postRevision->expects( $this->any() )
+ ->method( 'getRevisionId' )
+ ->will( $this->returnValue( UUID::create() ) );
+ return $postRevision;
+ }
+
protected function mockTemplating() {
$templating = $this->getMockBuilder( 'Flow\Templating' )
->disableOriginalConstructor()
@@ -127,21 +343,31 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
->will( $this->returnArgument( 0 ) );
$templating->expects( $this->any() )
->method( 'getContent' )
- ->will( $this->returnCallback( function( $revision, $contentFormat ) {
+ ->will( $this->returnCallback( function ( $revision, $contentFormat ) {
return $revision->getContent( $contentFormat );
} ) );
return $templating;
}
+ protected function mockTopicTitleRevision() {
+ $topicTitleRevision = $this->getMockBuilder( 'Flow\Model\PostRevision' )->getMock();
+ $topicTitleRevision->expects( $this->any() )
+ ->method( 'isTopicTitle' )
+ ->will( $this->returnValue( true ) );
+ $topicTitleRevision->expects( $this->any() )
+ ->method( 'getRevisionId' )
+ ->will( $this->returnValue( UUID::create() ) );
+ return $topicTitleRevision;
+ }
+
protected function mockUserNameBatch() {
return $this->getMockBuilder( 'Flow\Repository\UserNameBatch' )
->disableOriginalConstructor()
->getMock();
}
- // @todo name seems wrong, the Formatter is real everything else is mocked
- public function mockFormatter( $returnAll = false ) {
+ public function makeFormatter( $returnAll = false ) {
$actions = $this->mockActions();
$permissions = $this->mockPermissions( $actions );
// formatting only proceedes when this is true
@@ -155,11 +381,10 @@ class RevisionFormatterTest extends \MediaWikiTestCase {
$ctx = RequestContext::getMain();
$ctx->setUser( $this->user );
-
if ( $returnAll ) {
- return array( $formatter, $ctx, $permissions, $templating, $usernames, $actions );
+ return [ $formatter, $ctx, $permissions, $templating, $usernames, $actions ];
} else {
- return array( $formatter, $ctx );
+ return [ $formatter, $ctx ];
}
}
}
diff --git a/Flow/tests/phpunit/Handlebars/FlowPostMetaActionsTest.php b/Flow/tests/phpunit/Handlebars/FlowPostMetaActionsTest.php
index 124f4493..4aa7322d 100644
--- a/Flow/tests/phpunit/Handlebars/FlowPostMetaActionsTest.php
+++ b/Flow/tests/phpunit/Handlebars/FlowPostMetaActionsTest.php
@@ -3,7 +3,6 @@
namespace Flow\Tests\Handlebars;
use Flow\Container;
-use Flow\TemplateHelper;
use LightnCandy;
use Symfony\Component\DomCrawler\Crawler;
diff --git a/Flow/tests/phpunit/HookTest.php b/Flow/tests/phpunit/HookTest.php
index b3cf4cf6..17abd33d 100644
--- a/Flow/tests/phpunit/HookTest.php
+++ b/Flow/tests/phpunit/HookTest.php
@@ -18,7 +18,7 @@ use User;
* @group Flow
*/
class HookTest extends \MediaWikiTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'flow_revision',
'flow_topic_list',
'flow_tree_node',
@@ -26,55 +26,56 @@ class HookTest extends \MediaWikiTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
- static public function onIRCLineURLProvider() {
+ public static function onIRCLineURLProvider() {
// data providers do not run in the same context as the actual test, as such we
// can't create Title objects because they can have the wrong wikiID. Instead we
// pass closures into the test that create the objects within the correct context.
- $newHeader = function( User $user ) {
+ $newHeader = function ( User $user ) {
$title = Title::newFromText( 'Talk:Hook_test' );
$workflow = Container::get( 'factory.loader.workflow' )
->createWorkflowLoader( $title )
->getWorkflow();
$header = Header::create( $workflow, $user, 'header content', 'wikitext' );
- $metadata = array(
+ $metadata = [
'workflow' => $workflow,
'revision' => $header,
- );
+ ];
/** @var OccupationController $occupationController */
$occupationController = Container::get( 'occupation_controller' );
// make sure user has rights to create board
- $user->mRights = array_merge( $user->getRights(), array( 'flow-create-board' ) );
- $occupationController->allowCreation( $title, $user );
+ $user->mRights = array_merge( $user->getRights(), [ 'flow-create-board' ] );
+ $occupationController->safeAllowCreation( $title, $user );
$occupationController->ensureFlowRevision( new \Article( $title ), $workflow );
Container::get( 'storage' )->put( $workflow, $metadata );
return $metadata;
};
- $freshTopic = function( User $user ) {
+ $freshTopic = function ( User $user ) {
$title = Title::newFromText( 'Talk:Hook_test' );
$boardWorkflow = Container::get( 'factory.loader.workflow' )
->createWorkflowLoader( $title )
->getWorkflow();
$topicWorkflow = Workflow::create( 'topic', $boardWorkflow->getArticleTitle() );
$topicList = TopicListEntry::create( $boardWorkflow, $topicWorkflow );
- $topicTitle = PostRevision::create( $topicWorkflow, $user, 'some content', 'wikitext' );
- $metadata = array(
+ $topicTitle = PostRevision::createTopicPost( $topicWorkflow, $user, 'some content' );
+ $metadata = [
'workflow' => $topicWorkflow,
'board-workflow' => $boardWorkflow,
'topic-title' => $topicTitle,
'revision' => $topicTitle,
- );
+ ];
/** @var OccupationController $occupationController */
$occupationController = Container::get( 'occupation_controller' );
// make sure user has rights to create board
- $user->mRights = array_merge( $user->getRights(), array( 'flow-create-board' ) );
- $occupationController->allowCreation( $title, $user );
+ $user->mRights = array_merge( $user->getRights(), [ 'flow-create-board' ] );
+ $occupationController->safeAllowCreation( $title, $user );
$occupationController->ensureFlowRevision( new \Article( $title ), $boardWorkflow );
$storage = Container::get( 'storage' );
@@ -85,118 +86,118 @@ class HookTest extends \MediaWikiTestCase {
return $metadata;
};
- $replyToTopic = function( User $user ) use( $freshTopic ) {
+ $replyToTopic = function ( User $user ) use( $freshTopic ) {
$metadata = $freshTopic( $user );
$firstPost = $metadata['topic-title']->reply( $metadata['workflow'], $user, 'ffuts dna ylper', 'wikitext' );
- $metadata = array(
+ $metadata = [
'first-post' => $firstPost,
'revision' => $firstPost,
- ) + $metadata;
+ ] + $metadata;
Container::get( 'storage.post' )->put( $firstPost, $metadata );
return $metadata;
};
- return array(
- array(
+ return [
+ [
// test message
'Freshly created topic',
// flow-workflow-change attribute within rc_params
$freshTopic,
// expected query parameters
- array(
+ [
'action' => 'history',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Reply to topic',
$replyToTopic,
- array(
+ [
'action' => 'history',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Edit topic title',
- function( $user ) use( $freshTopic ) {
+ function ( $user ) use( $freshTopic ) {
$metadata = $freshTopic( $user );
$title = $metadata['workflow']->getArticleTitle();
- return array(
- 'revision' => $metadata['revision']->newNextRevision( $user, 'gnihtemos gnihtemos', 'wikitext', 'edit-title', $title ),
- ) + $metadata;
+ return [
+ 'revision' => $metadata['revision']->newNextRevision( $user, 'gnihtemos gnihtemos', 'topic-title-wikitext', 'edit-title', $title ),
+ ] + $metadata;
},
- array(
+ [
'action' => 'compare-post-revisions',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Edit post',
- function( $user ) use( $replyToTopic ) {
+ function ( $user ) use( $replyToTopic ) {
$metadata = $replyToTopic( $user );
$title = $metadata['workflow']->getArticleTitle();
- return array(
+ return [
'revision' => $metadata['revision']->newNextRevision( $user, 'IT\'S CAPS LOCKS DAY!', 'wikitext', 'edit-post', $title ),
- ) + $metadata;
+ ] + $metadata;
},
- array(
+ [
'action' => 'compare-post-revisions',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Edit board header',
- function( $user ) use ( $newHeader ) {
+ function ( $user ) use ( $newHeader ) {
$metadata = $newHeader( $user );
$title = $metadata['workflow']->getArticleTitle();
- return array(
+ return [
'revision' => $metadata['revision']->newNextRevision( $user, 'STILL CAPS LOCKS DAY!', 'wikitext', 'edit-header', $title ),
- ) + $metadata;
+ ] + $metadata;
},
- array(
+ [
'action' => 'compare-header-revisions',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Moderate a post',
- function( $user ) use ( $replyToTopic ) {
+ function ( $user ) use ( $replyToTopic ) {
$metadata = $replyToTopic( $user );
- return array(
+ return [
'revision' => $metadata['revision']->moderate(
$user,
$metadata['revision']::MODERATED_DELETED,
'delete-post',
'something about cruise control'
),
- ) + $metadata;
+ ] + $metadata;
},
- array(
+ [
'action' => 'history',
- ),
- ),
+ ],
+ ],
- array(
+ [
'Moderate a topic',
- function( $user ) use ( $freshTopic ) {
+ function ( $user ) use ( $freshTopic ) {
$metadata = $freshTopic( $user );
- return array(
+ return [
'revision' => $metadata['revision']->moderate(
$user,
$metadata['revision']::MODERATED_HIDDEN,
'hide-topic',
'adorable kittens'
),
- ) + $metadata;
+ ] + $metadata;
},
- array(
+ [
'action' => 'history',
- ),
- ),
- );
+ ],
+ ],
+ ];
}
/**
@@ -213,11 +214,11 @@ class HookTest extends \MediaWikiTestCase {
$container['user'] = $user;
$rc = new RecentChange;
- $rc->mAttribs = array(
+ $rc->mAttribs = [
'rc_namespace' => 0,
'rc_title' => 'Main Page',
'rc_source' => RecentChangesListener::SRC_FLOW,
- );
+ ];
$metadata = $metadataGen( $user );
Container::get( 'formatter.irclineurl' )->associate( $rc, $metadata );
diff --git a/Flow/tests/phpunit/Import/ArchiveNameHelperTest.php b/Flow/tests/phpunit/Import/ArchiveNameHelperTest.php
index 1ccef033..ecbaee10 100644
--- a/Flow/tests/phpunit/Import/ArchiveNameHelperTest.php
+++ b/Flow/tests/phpunit/Import/ArchiveNameHelperTest.php
@@ -1,53 +1,53 @@
<?php
namespace Flow\Tests\Import;
+
use Title;
use Flow\Import\ArchiveNameHelper;
-
/**
* @group Flow
*/
class ArchiveNameHelperTest extends \MediaWikiTestCase {
public function decideArchiveTitleProvider() {
- return array(
- array(
+ return [
+ [
'Selects the first pattern if n=1 does exist',
// expect
'Talk:Flow/Archive 1',
// source title
Title::newFromText( 'Talk:Flow' ),
// formats
- array( '%s/Archive %d', '%s/Archive%d' ),
+ [ '%s/Archive %d', '%s/Archive%d' ],
// existing titles
- array(),
- ),
+ [],
+ ],
- array(
+ [
'Selects n=2 when n=1 exists',
// expect
'Talk:Flow/Archive 2',
// source title
Title::newFromText( 'Talk:Flow' ),
// formats
- array( '%s/Archive %d' ),
+ [ '%s/Archive %d' ],
// existing titles
- array( 'Talk:Flow/Archive 1' ),
- ),
+ [ 'Talk:Flow/Archive 1' ],
+ ],
- array(
+ [
'Selects the second pattern if n=1 exists',
// expect
'Talk:Flow/Archive2',
// source title
Title::newFromText( 'Talk:Flow' ),
// formats
- array( '%s/Archive %d', '%s/Archive%d' ),
+ [ '%s/Archive %d', '%s/Archive%d' ],
// existing titles
- array( 'Talk:Flow/Archive1' ),
- ),
- );
+ [ 'Talk:Flow/Archive1' ],
+ ],
+ ];
}
/**
* @dataProvider decideArchiveTitleProvider
@@ -59,7 +59,7 @@ class ArchiveNameHelperTest extends \MediaWikiTestCase {
$titleRepo = $this->getMock( 'Flow\Repository\TitleRepository' );
$titleRepo->expects( $this->any() )
->method( 'exists' )
- ->will( $this->returnCallback( function( Title $title ) use ( $existsByKey ) {
+ ->will( $this->returnCallback( function ( Title $title ) use ( $existsByKey ) {
return isset( $existsByKey[$title->getPrefixedText()] );
} ) );
@@ -69,32 +69,32 @@ class ArchiveNameHelperTest extends \MediaWikiTestCase {
}
public function findLatestArchiveTitleProvider() {
- return array(
- array(
+ return [
+ [
'Returns false if no archive exist',
// expect
false,
// source title
Title::newFromText( 'Talk:Flow' ),
// formats
- array( '%s/Archive %d', '%s/Archive%d' ),
+ [ '%s/Archive %d', '%s/Archive%d' ],
// existing titles
- array(),
- ),
+ [],
+ ],
- array(
+ [
'Selects n=2 when n=2 exists',
// expect
'Talk:Flow/Archive 2',
// source title
Title::newFromText( 'Talk:Flow' ),
// formats
- array( '%s/Archive %d' ),
+ [ '%s/Archive %d' ],
// existing titles
- array( 'Talk:Flow/Archive 1', 'Talk:Flow/Archive 2' ),
- ),
+ [ 'Talk:Flow/Archive 1', 'Talk:Flow/Archive 2' ],
+ ],
- );
+ ];
}
/**
* @dataProvider findLatestArchiveTitleProvider
@@ -106,7 +106,7 @@ class ArchiveNameHelperTest extends \MediaWikiTestCase {
$titleRepo = $this->getMock( 'Flow\Repository\TitleRepository' );
$titleRepo->expects( $this->any() )
->method( 'exists' )
- ->will( $this->returnCallback( function( Title $title ) use ( $existsByKey ) {
+ ->will( $this->returnCallback( function ( Title $title ) use ( $existsByKey ) {
return isset( $existsByKey[$title->getPrefixedText()] );
} ) );
diff --git a/Flow/tests/phpunit/Import/HistoricalUIDGeneratorTest.php b/Flow/tests/phpunit/Import/HistoricalUIDGeneratorTest.php
index 798c1812..fa143684 100644
--- a/Flow/tests/phpunit/Import/HistoricalUIDGeneratorTest.php
+++ b/Flow/tests/phpunit/Import/HistoricalUIDGeneratorTest.php
@@ -13,10 +13,10 @@ class HistoricalUIDGeneratorTest extends \MediaWikiTestCase {
public function roundTripProvider() {
$now = time();
- return array(
- array( $now - 86400 ),
- array( $now - ( 365 * 86400 ) ),
- );
+ return [
+ [ $now - 86400 ],
+ [ $now - ( 365 * 86400 ) ],
+ ];
}
/**
diff --git a/Flow/tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php b/Flow/tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php
index 9f46162a..d51a8eea 100644
--- a/Flow/tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php
+++ b/Flow/tests/phpunit/Import/LiquidThreadsApi/ConversionStrategyTest.php
@@ -5,8 +5,8 @@ namespace Flow\Tests\Import\LiquidThreadsApi;
use DatabaseBase;
use DateTime;
use DateTimeZone;
-use Flow\Import\ImportSourceStore;
-use Flow\Import\NullImportSourceStore;
+use Flow\Import\SourceStore\SourceStoreInterface as ImportSourceStore;
+use Flow\Import\SourceStore\NullImportSourceStore;
use Flow\Import\LiquidThreadsApi\ConversionStrategy;
use Flow\Import\LiquidThreadsApi\ApiBackend;
use Title;
@@ -16,7 +16,7 @@ use WikitextContent;
* @group Flow
*/
class ConversionStrategyTest extends \MediaWikiTestCase {
- public function setUp() {
+ protected function setUp() {
parent::setUp();
// Stash existing $wgEchoNotifications and provide a dummy for these
@@ -59,7 +59,7 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
public function testReturnsValidSourceStore() {
$this->assertInstanceOf(
- 'Flow\Import\ImportSourceStore',
+ 'Flow\Import\SourceStore\SourceStoreInterface',
$this->createStrategy()->getSourceStore()
);
}
@@ -81,23 +81,23 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
$now = new DateTime( "now", new DateTimeZone( "GMT" ) );
$date = $now->format( 'Y-m-d' );
- return array(
- array(
+ return [
+ [
'Blank input page',
// expect
"{{Archive for converted LQT page|from=Talk:Blue birds|date=$date}}\n\n{{#useliquidthreads:0}}\n\n",
// input content
'',
- ),
- array(
+ ],
+ [
'Page containing lqt magic word',
// expect
"{{Archive for converted LQT page|from=Talk:Blue birds|date=$date}}\n\n{{#useliquidthreads:0}}\n\n",
// input content
'{{#useliquidthreads:1}}',
- ),
+ ],
- array(
+ [
'Page containing some stuff and the lqt magic word',
// expect
<<<EOD
@@ -120,8 +120,8 @@ dedicated to the proposition that all men are created equal.
1
}}
EOD
- ),
- );
+ ],
+ ];
}
/**
@@ -129,7 +129,7 @@ EOD
* @param string $content
*/
public function testCreateArchiveCleanupRevisionContent( $message, $expect, $content ) {
- if( !class_exists( 'LqtDispatch' ) ) {
+ if ( !class_exists( 'LqtDispatch' ) ) {
$this->markTestSkipped( 'LiquidThreads not enabled' );
}
@@ -150,7 +150,6 @@ EOD
);
}
-
protected function createStrategy(
DatabaseBase $dbr = null,
ImportSourceStore $sourceStore = null,
diff --git a/Flow/tests/phpunit/Import/PageImportStateTest.php b/Flow/tests/phpunit/Import/PageImportStateTest.php
index bceaf55d..9f99a31a 100644
--- a/Flow/tests/phpunit/Import/PageImportStateTest.php
+++ b/Flow/tests/phpunit/Import/PageImportStateTest.php
@@ -2,7 +2,7 @@
namespace Flow\Tests\Import;
-use Flow\Import\NullImportSourceStore;
+use Flow\Import\SourceStore\NullImportSourceStore;
use Flow\Import\PageImportState;
use Flow\Import\Postprocessor\ProcessorGroup;
use Flow\Model\PostRevision;
@@ -32,9 +32,6 @@ class PageImportStateTest extends \MediaWikiTestCase {
$storage,
new NullImportSourceStore(),
new NullLogger(),
- $this->getMockBuilder( 'Flow\Data\BufferedCache' )
- ->disableOriginalConstructor()
- ->getMock(),
$this->getMockBuilder( 'Flow\DbFactory' )
->disableOriginalConstructor()
->getMock(),
@@ -42,7 +39,7 @@ class PageImportStateTest extends \MediaWikiTestCase {
new SplQueue
);
if ( $returnAll ) {
- return array( $state, $workflow, $storage );
+ return [ $state, $workflow, $storage ];
} else {
return $state;
}
@@ -73,11 +70,10 @@ class PageImportStateTest extends \MediaWikiTestCase {
'topic',
Title::newMainPage()
);
- $topicTitle = PostRevision::create(
+ $topicTitle = PostRevision::createTopicPost(
$topicWorkflow,
User::newFromName( '127.0.0.1', false ),
- 'sing song',
- 'wikitext'
+ 'sing song'
);
$now = time();
@@ -97,7 +93,7 @@ class PageImportStateTest extends \MediaWikiTestCase {
$user = User::newFromName( '127.0.0.1', false );
$title = Title::newMainPage();
$topicWorkflow = Workflow::create( 'topic', $title );
- $topicTitle = PostRevision::create( $topicWorkflow, $user, 'sing song', 'wikitext' );
+ $topicTitle = PostRevision::createTopicPost( $topicWorkflow, $user, 'sing song' );
$reply = $topicTitle->reply( $topicWorkflow, $user, 'fantastic!', 'wikitext' );
$now = time();
diff --git a/Flow/tests/phpunit/Import/TalkpageImportOperationTest.php b/Flow/tests/phpunit/Import/TalkpageImportOperationTest.php
index c56e4f1c..df9d43d0 100644
--- a/Flow/tests/phpunit/Import/TalkpageImportOperationTest.php
+++ b/Flow/tests/phpunit/Import/TalkpageImportOperationTest.php
@@ -3,7 +3,7 @@
namespace Flow\Tests\Import;
use Flow\Container;
-use Flow\Import\NullImportSourceStore;
+use Flow\Import\SourceStore\NullImportSourceStore;
use Flow\Import\PageImportState;
use Flow\Import\Postprocessor\ProcessorGroup;
use Flow\Import\TalkpageImportOperation;
@@ -28,14 +28,15 @@ use User;
* @group Database
*/
class TalkpageImportOperationTest extends \MediaWikiTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
// importer will ensureFlowRevision(), which will insert into these core tables
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
- public function setUp() {
+ protected function setUp() {
parent::setUp();
// reset flow state, so everything ($container['permissions'])
@@ -58,71 +59,74 @@ class TalkpageImportOperationTest extends \MediaWikiTestCase {
$storage = $this->getMockBuilder( 'Flow\Data\ManagerGroup' )
->disableOriginalConstructor()
->getMock();
- $stored = array();
+ $stored = [];
$storage->expects( $this->any() )
->method( 'put' )
- ->will( $this->returnCallback( function( $obj ) use( &$stored ) {
+ ->will( $this->returnCallback( function ( $obj ) use( &$stored ) {
$stored[] = $obj;
} ) );
$storage->expects( $this->any() )
->method( 'multiPut' )
- ->will( $this->returnCallback( function( $objs ) use( &$stored ) {
+ ->will( $this->returnCallback( function ( $objs ) use( &$stored ) {
$stored = array_merge( $stored, $objs );
} ) );
$now = time();
$source = new MockImportSource(
- new MockImportHeader( array(
+ new MockImportHeader( [
// header revisions
- new MockImportRevision( array( 'createdTimestamp' => $now ) ),
- ) ),
- array(
+ new MockImportRevision( [ 'createdTimestamp' => $now ] ),
+ ] ),
+ [
new MockImportTopic(
- new MockImportSummary( array(
- new MockImportRevision( array( 'createdTimestamp' => $now - 250 ) ),
- ) ),
- array(
+ new MockImportSummary( [
+ new MockImportRevision( [ 'createdTimestamp' => $now - 250 ] ),
+ ] ),
+ [
// topic title revisions
- new MockImportRevision( array( 'createdTimestamp' => $now - 1000 ) ),
- ),
- array(
- //replies
+ new MockImportRevision( [ 'createdTimestamp' => $now - 1000 ] ),
+ ],
+ [
+ // replies
new MockImportPost(
- array(
+ [
// revisions
- new MockImportRevision( array( 'createdTimestmap' => $now - 1000 ) ),
- ),
- array(
+ new MockImportRevision( [ 'createdTimestmap' => $now - 1000 ] ),
+ ],
+ [
// replies
new MockImportPost(
- array(
+ [
// revisions
- new MockImportRevision( array(
+ new MockImportRevision( [
'createdTimestmap' => $now - 500,
'user' => User::newFromNAme( '10.0.0.2', false ),
- ) ),
- ),
- array(
+ ] ),
+ ],
+ [
// replies
- )
+ ]
),
- )
+ ]
),
- )
+ ]
)
- )
+ ]
+ );
+
+ $occupationController = Container::get( 'occupation_controller' );
+ $op = new TalkpageImportOperation(
+ $source,
+ $occupationController->getTalkpageManager(),
+ $occupationController
);
- $op = new TalkpageImportOperation( $source, Container::get( 'occupation_controller' ) );
$store = new NullImportSourceStore;
$op->import( new PageImportState(
$workflow,
$storage,
$store,
new NullLogger(),
- $this->getMockBuilder( 'Flow\Data\BufferedCache' )
- ->disableOriginalConstructor()
- ->getMock(),
Container::get( 'db.factory' ),
new ProcessorGroup,
new SplQueue
diff --git a/Flow/tests/phpunit/Import/TemplateHelperTest.php b/Flow/tests/phpunit/Import/TemplateHelperTest.php
index f6a9ff44..c486760e 100644
--- a/Flow/tests/phpunit/Import/TemplateHelperTest.php
+++ b/Flow/tests/phpunit/Import/TemplateHelperTest.php
@@ -7,28 +7,28 @@ use Flow\Import\TemplateHelper;
class TemplateHelperTest extends \MediaWikiTestCase {
public function removeFromHtmlDataProvider() {
- return array(
- array( // the template is NOT in the html
+ return [
+ [ // the template is NOT in the html
'<body data-parsoid="{stuff}"><p name="asdf">hi there</p></body>',
'I am not a real template',
'<body data-parsoid="{stuff}"><p name="asdf">hi there</p></body>'
- ),
- array( // the template IS in the html ONCE
+ ],
+ [ // the template IS in the html ONCE
'<body data-parsoid="{stuff}"><p>hi there<span typeof="mw:Transclusion" data-mw=\'{"parts":[{"template":{"target":{"wt":"I am a template","href":"./Template:I_am_a_template"}}}]}\'></span></p></body>',
'I am a template',
'<body data-parsoid="{stuff}"><p>hi there</p></body>'
- ),
- array( // the template IS in the html MANY TIMES
+ ],
+ [ // the template IS in the html MANY TIMES
'<body data-parsoid="{stuff}"><p>a<span typeof="mw:Transclusion" data-mw=\'{"parts":[{"template":{"target":{"wt":"I am a template","href":"./Template:I_am_a_template"}}}]}\'></span>b<span typeof="mw:Transclusion" data-mw=\'{"parts":[{"template":{"target":{"wt":"I am a template","href":"./Template:I_am_a_template"}}}]}\'></span>c</p></body>',
'I am a template',
'<body data-parsoid="{stuff}"><p>abc</p></body>'
- ),
- array( // somewhat malformed data-mw
+ ],
+ [ // somewhat malformed data-mw
'<body data-parsoid="{stuff}"><p>hi there<span typeof="mw:Transclusion" data-mw=\'{"parts":[{}]}\'></span></p></body>',
'Template name',
'<body data-parsoid="{stuff}"><p>hi there<span typeof="mw:Transclusion" data-mw=\'{"parts":[{}]}\'></span></p></body>'
- ),
- array( // multinode template using 'about' attribute
+ ],
+ [ // multinode template using 'about' attribute
'<body data-parsoid="{stuff}">' .
'<p>hi there</p>' .
'<span typeof="mw:Transclusion" about="#mwt5" data-mw=\'{"parts":[{"template":{"target":{"wt":"I am a template","href":"./Template:I_am_a_template"}}}]}\'></span>' .
@@ -37,8 +37,8 @@ class TemplateHelperTest extends \MediaWikiTestCase {
'</body>',
'I am a template',
'<body data-parsoid="{stuff}"><p>hi there</p></body>'
- )
- );
+ ]
+ ];
}
/**
@@ -51,4 +51,4 @@ class TemplateHelperTest extends \MediaWikiTestCase {
$actualHTML );
}
-} \ No newline at end of file
+}
diff --git a/Flow/tests/phpunit/Import/Wikitext/ConversionStrategyTest.php b/Flow/tests/phpunit/Import/Wikitext/ConversionStrategyTest.php
index 293bc7f0..baaa181c 100644
--- a/Flow/tests/phpunit/Import/Wikitext/ConversionStrategyTest.php
+++ b/Flow/tests/phpunit/Import/Wikitext/ConversionStrategyTest.php
@@ -5,8 +5,8 @@ namespace Flow\Tests\Import\Wikitext;
use Flow\Container;
use DateTime;
use DateTimeZone;
-use Flow\Import\ImportSourceStore;
-use Flow\Import\NullImportSourceStore;
+use Flow\Import\SourceStore\SourceStoreInterface as ImportSourceStore;
+use Flow\Import\SourceStore\NullImportSourceStore;
use Flow\Import\Wikitext\ConversionStrategy;
use LinkCache;
use Parser;
@@ -51,7 +51,7 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
public function testReturnsValidSourceStore() {
$this->assertInstanceOf(
- 'Flow\Import\ImportSourceStore',
+ 'Flow\Import\SourceStore\SourceStoreInterface',
$this->createStrategy()->getSourceStore()
);
}
@@ -85,17 +85,17 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
}
public function testShouldConvertLqt() {
- if( !class_exists( 'LqtDispatch' ) ) {
+ if ( !class_exists( 'LqtDispatch' ) ) {
$this->markTestSkipped( 'LiquidThreads not enabled' );
}
$strategy = $this->createStrategy();
$lqtPagesName = 'Talk:Some ConversionStrategyTest LQT page';
- $this->setMwGlobals( array(
- 'wgLqtNamespaces' => array( NS_HELP_TALK ),
- 'wgLqtPages' => array( $lqtPagesName ),
- ) );
+ $this->setMwGlobals( [
+ 'wgLqtNamespaces' => [ NS_HELP_TALK ],
+ 'wgLqtPages' => [ $lqtPagesName ],
+ ] );
// Not subpage, not LQT
$nonLqtTitle = Title::newFromText( 'Talk:Some ConversionStrategyTest page' );
@@ -121,8 +121,8 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
$strategy->shouldConvert( $lqtPagesTitle ),
'LQT wgLqtPages talk page should not be converted'
);
-
}
+
/**
* @dataProvider provideMeetsSubpageRequirements
*/
@@ -150,32 +150,32 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
}
public function provideMeetsSubpageRequirements() {
- return array(
- array(
+ return [
+ [
'Talk:Some ConversionStrategyTest page',
true,
true, // Shouldn't matter
'Non-subpage talk page',
- ),
- array(
+ ],
+ [
'Talk:Some/ConversionStrategyTest subpage 1',
true,
true,
'Talk subpage where subject exists',
- ),
- array(
+ ],
+ [
'Talk:Some/ConversionStrategyTest subpage 2',
false,
false,
'Talk subpage where subject doesn\'t exist',
- ),
- array(
+ ],
+ [
'User:Some/ConversionStrategyTest subpage',
false,
true,
'Existing subpage in subject namespace'
- ),
- );
+ ],
+ ];
}
protected function createStrategy(
@@ -187,7 +187,8 @@ class ConversionStrategyTest extends \MediaWikiTestCase {
return new ConversionStrategy(
$parser ?: $wgParser,
$sourceStore ?: new NullImportSourceStore,
- Container::get( 'default_logger' )
+ Container::get( 'default_logger' ),
+ Container::get( 'occupation_controller' )->getTalkpageManager()
);
}
}
diff --git a/Flow/tests/phpunit/Import/Wikitext/ImportSourceTest.php b/Flow/tests/phpunit/Import/Wikitext/ImportSourceTest.php
index 8c1db610..e8dc09f3 100644
--- a/Flow/tests/phpunit/Import/Wikitext/ImportSourceTest.php
+++ b/Flow/tests/phpunit/Import/Wikitext/ImportSourceTest.php
@@ -4,9 +4,10 @@ namespace Flow\Tests\Import\Wikitext;
use DateTime;
use DateTimeZone;
+use Flow\Container;
use Flow\Exception\WikitextException;
use Flow\Import\Wikitext\ImportSource;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Parser;
use Title;
use WikiPage;
@@ -18,9 +19,9 @@ use WikitextContent;
*/
class ImportSourceTest extends \MediaWikiTestCase {
- protected $tablesUsed = array( 'page', 'revision' );
+ protected $tablesUsed = [ 'page', 'revision', 'ip_changes' ];
- public function setUp() {
+ protected function setUp() {
parent::setUp();
// Check for Parsoid
@@ -34,7 +35,9 @@ class ImportSourceTest extends \MediaWikiTestCase {
/**
* @dataProvider getHeaderProvider
*/
- public function testGetHeader( $content, $expect ) {
+ public function testGetHeader( $content, $expectText ) {
+ $user = Container::get( 'occupation_controller' )->getTalkpageManager();
+
// create a page with some content
$status = WikiPage::factory( Title::newMainPage() )
->doEditContent(
@@ -45,7 +48,12 @@ class ImportSourceTest extends \MediaWikiTestCase {
$this->fail( $status->getMessage()->plain() );
}
- $source = new ImportSource( Title::newMainPage(), new Parser );
+ $source = new ImportSource(
+ Title::newMainPage(),
+ new Parser,
+ $user
+ );
+
$header = $source->getHeader();
$this->assertNotNull( $header );
$this->assertGreaterThan( 1, strlen( $header->getObjectKey() ) );
@@ -55,52 +63,53 @@ class ImportSourceTest extends \MediaWikiTestCase {
$revision = reset( $revisions );
$this->assertInstanceOf( 'Flow\Import\IObjectRevision', $revision );
- $this->assertEquals( $expect, $revision->getText() );
+ $this->assertEquals( $expectText, $revision->getText() );
+ $this->assertEquals( $user->getName(), $revision->getAuthor() );
}
public function getHeaderProvider() {
$now = new DateTime( "now", new DateTimeZone( "GMT" ) );
$date = $now->format( 'Y-m-d' );
- return array(
- array(
+ return [
+ [
// original page content
"This is some content\n",
// content to be stored to header
"\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"{{tpl}}\n",
"{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"{{tpl}}\nNon-template text\n",
"{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"Non-template text\n{{tpl}}\n",
"{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"Non-template text\n{{tpl}}\nNon-template text\n",
"{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"{{tpl}}\nNon-template text\n{{tpl}}\nNon-template text\n{{tpl}}\n",
"{{tpl}}\n{{tpl}}\n{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"{{tpl\n|key=value}}\n",
"{{tpl\n|key=value}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}"
- ),
- array(
+ ],
+ [
"{{multiple issues|\n{{copyedit}}\n{{cleanup tone}}\n}}\n",
"{{multiple issues|\n{{copyedit}}\n{{cleanup tone}}\n}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}",
- ),
- array(
+ ],
+ [
"{{multiple issues|\n{{copyedit}}\n{{cleanup tone}}\n}}\nNon-template text\n{{tpl}}\n",
"{{multiple issues|\n{{copyedit}}\n{{cleanup tone}}\n}}\n{{tpl}}\n\n{{Wikitext talk page converted to Flow|archive=Main Page|date=$date}}",
- ),
- );
+ ],
+ ];
}
}
diff --git a/Flow/tests/phpunit/LinksTableTest.php b/Flow/tests/phpunit/LinksTableTest.php
index 376e0c6e..e3b34f7c 100644
--- a/Flow/tests/phpunit/LinksTableTest.php
+++ b/Flow/tests/phpunit/LinksTableTest.php
@@ -13,7 +13,7 @@ use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\Parsoid\ReferenceExtractor;
use Flow\Parsoid\ReferenceFactory;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use ParserOutput;
use Title;
@@ -25,7 +25,7 @@ class LinksTableTest extends PostRevisionTestCase {
/**
* @var array
*/
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'flow_ext_ref',
'flow_revision',
'flow_topic_list',
@@ -35,8 +35,9 @@ class LinksTableTest extends PostRevisionTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
/**
* @var ManagerGroup
@@ -68,7 +69,7 @@ class LinksTableTest extends PostRevisionTestCase {
*/
protected $revision;
- public function setUp() {
+ protected function setUp() {
parent::setUp();
// create a workflow & revision associated with it
@@ -99,7 +100,7 @@ class LinksTableTest extends PostRevisionTestCase {
*/
protected function generatePost( $overrides ) {
$uuid = UUID::create();
- return $this->generateObject( $overrides + array(
+ return $this->generateObject( $overrides + [
'rev_change_type' => 'reply',
// generate new post id
@@ -108,7 +109,7 @@ class LinksTableTest extends PostRevisionTestCase {
// make sure it's a reply to $this->revision
'tree_parent_id' => $this->revision->getPostId(),
- ) );
+ ] );
}
protected static function getTestTitle() {
@@ -116,73 +117,73 @@ class LinksTableTest extends PostRevisionTestCase {
}
public static function provideGetReferencesFromRevisionContent() {
- return array(
- array(
+ return [
+ [
'[[Foo]]',
- array(
- array(
+ [
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Foo',
- ),
- ),
- ),
- array(
+ ],
+ ],
+ ],
+ [
'[http://www.google.com Foo]',
- array(
- array(
+ [
+ [
'factoryMethod' => 'createUrlReference',
'refType' => 'link',
'value' => 'http://www.google.com',
- ),
- ),
- ),
- array(
+ ],
+ ],
+ ],
+ [
'[[File:Foo.jpg]]',
- array(
- array(
+ [
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'file',
'value' => 'File:Foo.jpg',
- ),
- ),
- ),
- array(
+ ],
+ ],
+ ],
+ [
'{{Foo}}',
- array(
- array(
+ [
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'template',
'value' => 'Template:Foo',
- ),
- ),
- ),
- array(
+ ],
+ ],
+ ],
+ [
'{{Foo}} [[Foo]] [[File:Foo.jpg]] {{Foo}} [[Bar]]',
- array(
- array(
+ [
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'template',
'value' => 'Template:Foo',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Foo',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'file',
'value' => 'File:Foo.jpg',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Bar',
- ),
- ),
- )
- );
+ ],
+ ],
+ ]
+ ];
}
/**
@@ -190,7 +191,7 @@ class LinksTableTest extends PostRevisionTestCase {
*/
public function testGetReferencesFromRevisionContent( $content, $expectedReferences ) {
$content = Utils::convert( 'wikitext', 'html', $content, $this->workflow->getOwnerTitle() );
- $revision = $this->generatePost( array( 'rev_content' => $content ) );
+ $revision = $this->generatePost( [ 'rev_content' => $content ] );
$expectedReferences = $this->expandReferences( $this->workflow, $revision, $expectedReferences );
@@ -204,7 +205,7 @@ class LinksTableTest extends PostRevisionTestCase {
*/
public function testGetReferencesAfterRevisionInsert( $content, $expectedReferences ) {
$content = Utils::convert( 'wikitext', 'html', $content, $this->workflow->getOwnerTitle() );
- $revision = $this->generatePost( array( 'rev_content' => $content ) );
+ $revision = $this->generatePost( [ 'rev_content' => $content ] );
// Save to storage to test if ReferenceRecorder listener picks this up
$this->store( $this->revision );
@@ -222,32 +223,32 @@ class LinksTableTest extends PostRevisionTestCase {
}
public static function provideGetExistingReferences() {
- return array( /* list of test runs */
- array( /* list of arguments */
- array( /* list of references */
- array( /* list of parameters */
+ return [ /* list of test runs */
+ [ /* list of arguments */
+ [ /* list of references */
+ [ /* list of parameters */
'factoryMethod' => 'createWikiReference',
'refType' => 'template',
'value' => 'Template:Foo',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Foo',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'file',
'value' => 'File:Foo.jpg',
- ),
- array(
+ ],
+ [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Bar',
- ),
- ),
- ),
- );
+ ],
+ ],
+ ],
+ ];
}
/**
@@ -269,79 +270,79 @@ class LinksTableTest extends PostRevisionTestCase {
public static function provideReferenceDiff() {
$references = self::getSampleReferences();
- return array(
+ return [
// Just adding a few
- array(
- array(),
- array(
+ [
+ [],
+ [
$references['fooLink'],
$references['barLink']
- ),
- array(
+ ],
+ [
$references['fooLink'],
$references['barLink'],
- ),
- array(),
- ),
+ ],
+ [],
+ ],
// Removing one
- array(
- array(
+ [
+ [
$references['fooLink'],
$references['barLink']
- ),
- array(
+ ],
+ [
$references['fooLink'],
- ),
- array(
- ),
- array(
+ ],
+ [
+ ],
+ [
$references['barLink'],
- ),
- ),
+ ],
+ ],
// Equality robustness
- array(
- array(
+ [
+ [
$references['fooLink'],
- ),
- array(
+ ],
+ [
$references['FooLink'],
- ),
- array(
- ),
- array(
- ),
- array( // test is only valid if Foo and foo are same page
+ ],
+ [
+ ],
+ [
+ ],
+ [ // test is only valid if Foo and foo are same page
'wgCapitalLinks' => true,
- )
- ),
+ ]
+ ],
// Inequality robustness
- array(
- array(
+ [
+ [
$references['fooLink'],
- ),
- array(
+ ],
+ [
$references['barLink'],
- ),
- array(
+ ],
+ [
$references['barLink'],
- ),
- array(
+ ],
+ [
$references['fooLink'],
- ),
- ),
- );
+ ],
+ ],
+ ];
}
/**
* @dataProvider provideReferenceDiff
*/
- public function testReferenceDiff( $old, $new, $expectedAdded, $expectedRemoved, $globals = array() ) {
+ public function testReferenceDiff( $old, $new, $expectedAdded, $expectedRemoved, $globals = [] ) {
if ( $globals ) {
$this->setMwGlobals( $globals );
}
list( $workflow, $revision, $title ) = $this->getBlandTestObjects();
- foreach( array( 'old', 'new', 'expectedAdded', 'expectedRemoved' ) as $varName ) {
+ foreach ( [ 'old', 'new', 'expectedAdded', 'expectedRemoved' ] as $varName ) {
$$varName = $this->expandReferences( $workflow, $revision, $$varName );
}
@@ -354,41 +355,41 @@ class LinksTableTest extends PostRevisionTestCase {
public static function provideMutateParserOutput() {
$references = self::getSampleReferences();
- return array(
- array(
- array( // references
+ return [
+ [
+ [ // references
$references['fooLink'],
$references['fooTemplate'],
$references['googleLink'],
$references['fooImage'],
- ),
- array(
- 'getLinks' => array(
- NS_MAIN => array( 'Foo' => 0, ),
- ),
- 'getTemplates' => array(
- NS_TEMPLATE => array( 'Foo' => 0, ),
- ),
- 'getImages' => array(
+ ],
+ [
+ 'getLinks' => [
+ NS_MAIN => [ 'Foo' => 0, ],
+ ],
+ 'getTemplates' => [
+ NS_TEMPLATE => [ 'Foo' => 0, ],
+ ],
+ 'getImages' => [
'Foo.jpg' => true,
- ),
- 'getExternalLinks' => array(
+ ],
+ 'getExternalLinks' => [
'http://www.google.com' => true,
- ),
- ),
- ),
- array(
- array(
+ ],
+ ],
+ ],
+ [
+ [
$references['subpageLink'],
- ),
- array(
- 'getLinks' => array(
+ ],
+ [
+ 'getLinks' => [
// NS_MAIN is the namespace of static::getTestTitle()
- NS_MAIN => array( static::getTestTitle()->getDBkey() . '/Subpage' => 0, )
- ),
- ),
- ),
- );
+ NS_MAIN => [ static::getTestTitle()->getDBkey() . '/Subpage' => 0, ]
+ ],
+ ],
+ ],
+ ];
}
/**
@@ -417,30 +418,30 @@ class LinksTableTest extends PostRevisionTestCase {
$parserOutput = new \ParserOutput;
// Clear the LinksUpdate to allow clean testing
- foreach( array_keys( $expectedItems ) as $fieldName ) {
- $parserOutput->$fieldName = array();
+ foreach ( array_keys( $expectedItems ) as $fieldName ) {
+ $parserOutput->$fieldName = [];
}
$this->updater->mutateParserOutput( $title, $parserOutput, $references );
- foreach( $expectedItems as $method => $content ) {
+ foreach ( $expectedItems as $method => $content ) {
$this->assertEquals( $content, $parserOutput->$method(), $method );
}
}
protected function getBlandTestObjects() {
- return array(
+ return [
/* workflow = */ $this->workflow,
/* revision = */ $this->revision,
/* title = */ $this->workflow->getArticleTitle(),
- );
+ ];
}
protected function expandReferences( Workflow $workflow, AbstractRevision $revision, array $references ) {
- $referenceObjs = array();
+ $referenceObjs = [];
$factory = new ReferenceFactory( $workflow, $revision->getRevisionType(), $revision->getCollectionId() );
- foreach( $references as $ref ) {
+ foreach ( $references as $ref ) {
$referenceObjs[] = $factory->{$ref['factoryMethod']}( $ref['refType'], $ref['value'] );
}
@@ -448,54 +449,54 @@ class LinksTableTest extends PostRevisionTestCase {
}
protected static function getSampleReferences() {
- return array(
- 'fooLink' => array(
+ return [
+ 'fooLink' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Foo',
- ),
- 'subpageLink' => array(
+ ],
+ 'subpageLink' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => '/Subpage',
- ),
- 'FooLink' => array(
+ ],
+ 'FooLink' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'foo',
- ),
- 'barLink' => array(
+ ],
+ 'barLink' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Bar',
- ),
- 'fooTemplate' => array(
+ ],
+ 'fooTemplate' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'template',
'value' => 'Template:Foo',
- ),
- 'googleLink' => array(
+ ],
+ 'googleLink' => [
'factoryMethod' => 'createUrlReference',
'refType' => 'link',
'value' => 'http://www.google.com'
- ),
- 'fooImage' => array(
+ ],
+ 'fooImage' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'file',
'value' => 'File:Foo.jpg',
- ),
- 'foreignFoo' => array(
+ ],
+ 'foreignFoo' => [
'factoryMethod' => 'createWikiReference',
'refType' => 'link',
'value' => 'Foo',
- ),
- );
+ ],
+ ];
}
protected function flattenReferenceList( $input ) {
- $list = array();
+ $list = [];
- foreach( $input as $reference ) {
+ foreach ( $input as $reference ) {
$list[$reference->getUniqueIdentifier()] = $reference;
}
diff --git a/Flow/tests/phpunit/Mock/MockImportPost.php b/Flow/tests/phpunit/Mock/MockImportPost.php
index f9e1a4c6..c8200c58 100644
--- a/Flow/tests/phpunit/Mock/MockImportPost.php
+++ b/Flow/tests/phpunit/Mock/MockImportPost.php
@@ -5,7 +5,6 @@ namespace Flow\Tests\Mock;
use ArrayIterator;
use Flow\Import\IImportPost;
use Flow\Import\IObjectRevision;
-use User;
class MockImportPost implements IImportPost {
/**
diff --git a/Flow/tests/phpunit/Mock/MockImportRevision.php b/Flow/tests/phpunit/Mock/MockImportRevision.php
index 1a55a29c..a658ca58 100644
--- a/Flow/tests/phpunit/Mock/MockImportRevision.php
+++ b/Flow/tests/phpunit/Mock/MockImportRevision.php
@@ -14,12 +14,12 @@ class MockImportRevision implements IObjectRevision {
/**
* @param array $attribs
*/
- public function __construct( array $attribs = array() ) {
- $this->attribs = $attribs + array(
+ public function __construct( array $attribs = [] ) {
+ $this->attribs = $attribs + [
'text' => 'dvorak',
'timestamp' => time(),
'author' => User::newFromName( '127.0.0.1', false ),
- );
+ ];
}
/**
diff --git a/Flow/tests/phpunit/Mock/MockImportSource.php b/Flow/tests/phpunit/Mock/MockImportSource.php
index c9514675..3a3c90a3 100644
--- a/Flow/tests/phpunit/Mock/MockImportSource.php
+++ b/Flow/tests/phpunit/Mock/MockImportSource.php
@@ -13,7 +13,7 @@ class MockImportSource implements IImportSource {
protected $topics;
/**
- * @var IImportHeader|null $header
+ * @var IImportHeader|null
*/
protected $header;
@@ -21,7 +21,7 @@ class MockImportSource implements IImportSource {
* @param IImportHeader|null $header
* @param IImportTopic[]
*/
- public function __construct( MockImportHeader $header = null, array $topics = array() ) {
+ public function __construct( MockImportHeader $header = null, array $topics = [] ) {
$this->topics = $topics;
$this->header = $header;
}
diff --git a/Flow/tests/phpunit/Mock/MockImportSummary.php b/Flow/tests/phpunit/Mock/MockImportSummary.php
index 608183d9..bd837c42 100644
--- a/Flow/tests/phpunit/Mock/MockImportSummary.php
+++ b/Flow/tests/phpunit/Mock/MockImportSummary.php
@@ -5,7 +5,6 @@ namespace Flow\Tests\Mock;
use ArrayIterator;
use Flow\Import\IObjectRevision;
use Flow\Import\IImportSummary;
-use User;
class MockImportSummary implements IImportSummary {
/**
@@ -16,7 +15,7 @@ class MockImportSummary implements IImportSummary {
/**
* @param IObjectRevision[] $revisions
*/
- public function __construct( array $revisions = array() ) {
+ public function __construct( array $revisions = [] ) {
$this->revisions = $revisions;
}
diff --git a/Flow/tests/phpunit/Mock/MockImportTopic.php b/Flow/tests/phpunit/Mock/MockImportTopic.php
index 7ff79a75..b227a051 100644
--- a/Flow/tests/phpunit/Mock/MockImportTopic.php
+++ b/Flow/tests/phpunit/Mock/MockImportTopic.php
@@ -40,7 +40,7 @@ class MockImportTopic extends MockImportPost implements IImportTopic {
* {@inheritDoc}
*/
public function getLogParameters() {
- return array();
+ return [];
}
/**
diff --git a/Flow/tests/phpunit/Model/PostRevisionTest.php b/Flow/tests/phpunit/Model/PostRevisionTest.php
index ce8849bc..1fd3e2d4 100644
--- a/Flow/tests/phpunit/Model/PostRevisionTest.php
+++ b/Flow/tests/phpunit/Model/PostRevisionTest.php
@@ -42,11 +42,11 @@ class PostRevisionTest extends PostRevisionTestCase {
$user = User::newFromName( '127.0.0.1', false );
$workflow = Workflow::create( 'topic', $title );
- $topic = PostRevision::create( $workflow, $user, $content, 'wikitext' );
+ $topic = PostRevision::createTopicPost( $workflow, $user, $content );
$this->assertEquals( 0, $topic->getPreviousContentLength() );
$this->assertEquals( mb_strlen( $content ), $topic->getContentLength() );
- $next = $topic->newNextRevision( $user, $nextContent, 'wikitext', 'edit-title', $title );
+ $next = $topic->newNextRevision( $user, $nextContent, 'topic-title-wikitext', 'edit-title', $title );
$this->assertEquals( mb_strlen( $content ), $next->getPreviousContentLength() );
$this->assertEquals( mb_strlen( $nextContent ), $next->getContentLength() );
}
diff --git a/Flow/tests/phpunit/Model/UUIDTest.php b/Flow/tests/phpunit/Model/UUIDTest.php
index 8a3c8d33..af81578c 100644
--- a/Flow/tests/phpunit/Model/UUIDTest.php
+++ b/Flow/tests/phpunit/Model/UUIDTest.php
@@ -15,10 +15,10 @@ class UUIDTest extends FlowTestCase {
$uuid = UUID::create();
$serialized = serialize( $uuid );
// We are targeting this portion of the serialized string:
- // s:16:"s3xyjucl93jtq2ci"
+ // s:16:"s3xyjucl93jtq2ci"
$broken = preg_replace_callback(
'/(s:16:")([a-z0-9])/',
- function( $matches ) {
+ function ( $matches ) {
return $matches[1] . strtoupper( $matches[2] );
},
$serialized
@@ -32,41 +32,37 @@ class UUIDTest extends FlowTestCase {
public function invalidInputProvider() {
$valid = UUID::create()->getAlphadecimal();
- return array(
- array( '' ),
- array( strtoupper( $valid ) ),
- array( strtoupper( UUID::alnum2hex( $valid ) ) ),
- array( ucfirst( $valid ) ),
- );
+ return [
+ [ '' ],
+ [ strtoupper( $valid ) ],
+ [ strtoupper( UUID::alnum2hex( $valid ) ) ],
+ [ ucfirst( $valid ) ],
+ ];
}
/**
* @dataProvider invalidInputProvider
- * @expectedException Flow\Exception\InvalidInputException
+ * @expectedException \Flow\Exception\InvalidInputException
*/
public function testInvalidInputOnCreate( $invalidInput ) {
UUID::create( $invalidInput );
}
- static public function uuidConversionProvider() {
- $dbr = wfGetDB( DB_SLAVE );
-
+ public static function uuidConversionProvider() {
// sample uuid from UIDGenerator::newTimestampedUID128()
$numeric_128 = '6709199728898751234959525538795913762';
- $hex_128 = wfBaseConvert( $numeric_128, 10, 16, 32 );
- $bin_128 = new UUIDBlob( pack( 'H*', $hex_128 ) );
- $pretty_128 = wfBaseConvert( $numeric_128, 10, 36 );
+ $hex_128 = \Wikimedia\base_convert( $numeric_128, 10, 16, 32 );
// Conversion from 128 bit to 88 bit takes the left
// most 88 bits.
- $bits_88 = substr( wfBaseConvert( $numeric_128, 10, 2, 128 ), 0, 88 );
- $numeric_88 = wfBaseConvert( $bits_88, 2, 10 );
- $hex_88 = wfBaseConvert( $numeric_88, 10, 16, 22 );
+ $bits_88 = substr( \Wikimedia\base_convert( $numeric_128, 10, 2, 128 ), 0, 88 );
+ $numeric_88 = \Wikimedia\base_convert( $bits_88, 2, 10 );
+ $hex_88 = \Wikimedia\base_convert( $numeric_88, 10, 16, 22 );
$bin_88 = new UUIDBlob( pack( 'H*', $hex_88 ) );
- $pretty_88 = wfBaseConvert( $numeric_88, 10, 36 );
+ $pretty_88 = \Wikimedia\base_convert( $numeric_88, 10, 36 );
- return array(
- array(
+ return [
+ [
'128 bit hex input must be truncated to 88bit output',
// input
$hex_128,
@@ -76,9 +72,9 @@ class UUIDTest extends FlowTestCase {
$hex_88,
// base36 output
$pretty_88,
- ),
+ ],
- array(
+ [
'88 bit binary input',
// input
$bin_88,
@@ -88,9 +84,9 @@ class UUIDTest extends FlowTestCase {
$hex_88,
// pretty
$pretty_88,
- ),
+ ],
- array(
+ [
'88 bit numeric input',
// input
$numeric_88,
@@ -100,9 +96,9 @@ class UUIDTest extends FlowTestCase {
$hex_88,
// pretty
$pretty_88,
- ),
+ ],
- array(
+ [
'88 bit hex input',
// input
$hex_88,
@@ -112,9 +108,9 @@ class UUIDTest extends FlowTestCase {
$hex_88,
// pretty
$pretty_88,
- ),
+ ],
- array(
+ [
'88 bit pretty input',
// input
$pretty_88,
@@ -124,9 +120,9 @@ class UUIDTest extends FlowTestCase {
$hex_88,
// pretty
$pretty_88,
- ),
+ ],
- );
+ ];
}
/**
@@ -136,17 +132,17 @@ class UUIDTest extends FlowTestCase {
$uuid = UUID::create( $input );
$this->assertEquals( $binary, $uuid->getBinary(), "Compare binary: $msg" );
- //$this->assertEquals( $hex, $uuid->getHex(), "Compare hex: $msg" );
+ // $this->assertEquals( $hex, $uuid->getHex(), "Compare hex: $msg" );
$this->assertEquals( $pretty, $uuid->getAlphadecimal(), "Compare pretty: $msg" );
}
- static public function prettyProvider() {
- return array(
+ public static function prettyProvider() {
+ return [
// maximal base 36 value ( 2^88 )
- array( '12vwzoefjlykjgcnwf' ),
+ [ '12vwzoefjlykjgcnwf' ],
// current unpadded values from uidgenerator
- array( 'rlnn1941hqtdtn8a' ),
- );
+ [ 'rlnn1941hqtdtn8a' ],
+ ];
}
/**
@@ -159,4 +155,48 @@ class UUIDTest extends FlowTestCase {
public function testConversionToTimestamp() {
$this->assertEquals( '20150303221220', UUID::create( 'scv3pvbt40kcyy4g' )->getTimestamp() );
}
+
+ public function testCreateLowNumber() {
+ $this->assertEquals( UUID::create( 10 )->getAlphadecimal(), '000000000000000a' );
+ }
+
+ public static function uuidProvider() {
+ return [
+ [ UUID::create() ],
+ [ UUID::getComparisonUUID( 1 ) ],
+ ];
+ }
+
+ /**
+ * @dataProvider uuidProvider
+ * @param UUID $uuid
+ */
+ public function testAlphadecimalRoundtrip( UUID $uuid ) {
+ $expect = $uuid->getAlphadecimal();
+ $new = UUID::create( $expect );
+
+ $this->assertEquals( $expect, $new->getAlphadecimal() );
+ }
+
+ /**
+ * @dataProvider uuidProvider
+ * @param UUID $uuid
+ */
+ public function testHexRoundtrip( UUID $uuid ) {
+ $expect = $uuid->getHex();
+ $new = UUID::create( $expect );
+
+ $this->assertEquals( $expect, $new->getHex() );
+ }
+
+ /**
+ * @dataProvider uuidProvider
+ * @param UUID $uuid
+ */
+ public function testBinaryRoundtrip( UUID $uuid ) {
+ $expect = $uuid->getBinary();
+ $new = UUID::create( $expect );
+
+ $this->assertEquals( $expect->fetch(), $new->getBinary()->fetch() );
+ }
}
diff --git a/Flow/tests/phpunit/Model/UserTupleTest.php b/Flow/tests/phpunit/Model/UserTupleTest.php
index fc14453b..26570158 100644
--- a/Flow/tests/phpunit/Model/UserTupleTest.php
+++ b/Flow/tests/phpunit/Model/UserTupleTest.php
@@ -10,15 +10,15 @@ use Flow\Model\UserTuple;
class UserTupleTest extends \MediaWikiTestCase {
public function invalidInputProvider() {
- return array(
- array( 'foo', 0, ''),
- array( 'foo', 1234, '127.0.0.1' ),
- array( '', 0, '127.0.0.1' ),
- array( 'foo', -25, '' ),
- array( 'foo', null, '127.0.0.1' ),
- array( null, 55, '' ),
- array( 'foo', 0, null ),
- );
+ return [
+ [ 'foo', 0, '' ],
+ [ 'foo', 1234, '127.0.0.1' ],
+ [ '', 0, '127.0.0.1' ],
+ [ 'foo', -25, '' ],
+ [ 'foo', null, '127.0.0.1' ],
+ [ null, 55, '' ],
+ [ 'foo', 0, null ],
+ ];
}
/**
@@ -30,12 +30,12 @@ class UserTupleTest extends \MediaWikiTestCase {
}
public function validInputProvider() {
- return array(
- array( 'foo', 42, null ),
- array( 'foo', 42, '' ),
- array( 'foo', 0, '127.0.0.1' ),
- array( 'foo', '0', '10.1.2.3' ),
- );
+ return [
+ [ 'foo', 42, null ],
+ [ 'foo', 42, '' ],
+ [ 'foo', 0, '127.0.0.1' ],
+ [ 'foo', '0', '10.1.2.3' ],
+ ];
}
/**
diff --git a/Flow/tests/phpunit/Notifications/NotificationControllerTest.php b/Flow/tests/phpunit/Notifications/NotificationControllerTest.php
new file mode 100644
index 00000000..452181ea
--- /dev/null
+++ b/Flow/tests/phpunit/Notifications/NotificationControllerTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace Flow\Tests;
+
+use Flow\Container;
+use Flow\Model\UUID;
+use Wikimedia\TestingAccessWrapper;
+
+// See also NotitifiedUsersTest
+/**
+ * @group Flow
+ */
+class NotificationControllerTest extends \MediaWikiTestCase {
+ protected $notificationController;
+
+ protected function setUp() {
+ $this->notificationController = Container::get( 'controller.notification' );
+
+ parent::setUp();
+ }
+
+ public static function getDeepestCommonRootProvider() {
+ return [
+ [
+ UUID::create( 't2f2m1hexpxgi9oy' ),
+ 'Siblings, same length',
+ [
+ 't2f2m1hexpxgi9oy' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2m1hexpxgi9oy' ),
+ UUID::create( 't2f2n66t66w0j636' ),
+ ],
+ 't2f2mruymt1k4wia' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2m1hexpxgi9oy' ),
+ UUID::create( 't2f2nio0fzrqybo2' )
+ ],
+ ]
+ ],
+ [
+ UUID::create( 't2et6t35psmz1ac2' ),
+ 'First shorter',
+ [
+ 't2f2mdjbw1dcfkia' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2mdjbw1dcfkia' ),
+ ],
+ 't2f2n66t66w0j636' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2m1hexpxgi9oy' ),
+ UUID::create( 't2f2n66t66w0j636' )
+ ],
+ ],
+ ],
+ [
+ UUID::create( 't2f2re4e901we1zm' ),
+ 'First longer, second truncated version of first',
+ [
+ 't2feoifdgpa2rt02' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2mdjbw1dcfkia' ),
+ UUID::create( 't2f2re4e901we1zm' ),
+ UUID::create( 't2feoifdgpa2rt02' ),
+ ],
+ 't2f2re4e901we1zm' => [
+ UUID::create( 't2et4aiiijstihea' ),
+ UUID::create( 't2et4aiwjnpnk5ua' ),
+ UUID::create( 't2et6t35psmz1ac2' ),
+ UUID::create( 't2f2mdjbw1dcfkia' ),
+ UUID::create( 't2f2re4e901we1zm' ),
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider getDeepestCommonRootProvider
+ */
+ public function testGetDeepestCommonRoot( $expectedDeepest, $message, $rootPaths ) {
+ $actualDeepest = TestingAccessWrapper::newFromObject( $this->notificationController )->getDeepestCommonRoot( $rootPaths );
+ $this->assertEquals( $expectedDeepest, $actualDeepest, $message );
+ }
+
+ public static function getFirstPreorderDepthFirstProvider() {
+ // This isn't necessarily the actual structure returned by
+ // fetchSubtreeIdentityMap. It's the part we use
+ $tree = [
+ 't2et6t35psmz1ac2' => [
+ 'children' => [
+ 't2f2m1hexpxgi9oy' => &$tree['t2f2m1hexpxgi9oy'],
+ 't2f2mdjbw1dcfkia' => &$tree['t2f2mdjbw1dcfkia'],
+ 't2f2mruymt1k4wia' => &$tree['t2f2mruymt1k4wia'],
+ ],
+ ],
+ 't2f2m1hexpxgi9oy' => [
+ 'children' => [
+ 't2f2n66t66w0j636' => &$tree['t2f2n66t66w0j636'],
+ 't2f2nio0fzrqybo2' => &$tree['t2f2nio0fzrqybo2'],
+ ],
+ ],
+ 't2f2mdjbw1dcfkia' => [
+ 'children' => [
+ 't2f2re4e901we1zm' => &$tree['t2f2re4e901we1zm'],
+ ],
+ ],
+ 't2f2mruymt1k4wia' => [
+ 'children' => [],
+ ],
+
+ 't2f2n66t66w0j636' => [
+ 'children' => [],
+ ],
+
+ 't2f2nio0fzrqybo2' => [
+ 'children' => [],
+ ],
+
+ 't2f2re4e901we1zm' => [
+ 'children' => [],
+ ],
+ ];
+
+ $treeRoot = UUID::create( 't2et6t35psmz1ac2' );
+
+ return [
+ [
+ $treeRoot,
+ 'Topmost is root',
+ [
+ 't2et6t35psmz1ac2' => $treeRoot,
+ 't2f2mruymt1k4wia' => UUID::create( 't2f2mruymt1k4wia' ),
+ 't2f2nio0fzrqybo2' => UUID::create( 't2f2nio0fzrqybo2' ),
+ 't2f2re4e901we1zm' => UUID::create( 't2f2re4e901we1zm' ),
+ ],
+ $treeRoot,
+ $tree,
+ ],
+ [
+ UUID::create( 't2f2n66t66w0j636' ),
+ 'Topmost is not root',
+ [
+ 't2f2mdjbw1dcfkia' => UUID::create( 't2f2mdjbw1dcfkia' ),
+ 't2f2n66t66w0j636' => UUID::create( 't2f2n66t66w0j636' ),
+ 't2f2re4e901we1zm' => UUID::create( 't2f2re4e901we1zm' ),
+ ],
+ $treeRoot,
+ $tree,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider getFirstPreorderDepthFirstProvider
+ */
+ public function testGetFirstPreorderDepthFirst( UUID $expectedFirst, $message, array $relevantPostIds, UUID $root, array $tree ) {
+ $actualFirst = TestingAccessWrapper::newFromObject( $this->notificationController )->getFirstPreorderDepthFirst( $relevantPostIds, $root, $tree );
+ $this->assertEquals( $expectedFirst, $actualFirst, $message );
+ }
+}
diff --git a/Flow/tests/phpunit/Notifications/NotifiedUsersTest.php b/Flow/tests/phpunit/Notifications/NotifiedUsersTest.php
index bb71022b..f8a4cc71 100644
--- a/Flow/tests/phpunit/Notifications/NotifiedUsersTest.php
+++ b/Flow/tests/phpunit/Notifications/NotifiedUsersTest.php
@@ -5,17 +5,17 @@ namespace Flow\Tests;
use Flow\Container;
use Flow\Model\PostRevision;
use Flow\Model\UserTuple;
+use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\NotificationController;
use EchoNotificationController;
use User;
-use WatchedItem;
/**
* @group Flow
*/
class NotifiedUsersTest extends PostRevisionTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'echo_event',
'echo_notification',
'flow_revision',
@@ -25,10 +25,11 @@ class NotifiedUsersTest extends PostRevisionTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
- public function setUp() {
+ protected function setUp() {
parent::setUp();
if ( !class_exists( 'EchoEvent' ) ) {
@@ -36,6 +37,7 @@ class NotifiedUsersTest extends PostRevisionTestCase {
return;
}
}
+
public function testWatchingTopic() {
$data = $this->getTestData();
if ( !$data ) {
@@ -43,19 +45,21 @@ class NotifiedUsersTest extends PostRevisionTestCase {
return;
}
- WatchedItem::fromUserTitle( $data['user'], $data['topicWorkflow']->getArticleTitle() )->addWatch();
+ /** @var User $user */
+ $user = $data['user'];
+ $user->addWatch( $data['topicWorkflow']->getArticleTitle() );
$events = $data['notificationController']->notifyPostChange( 'flow-post-reply',
- array(
+ [
'topic-workflow' => $data['topicWorkflow'],
'title' => $data['boardWorkflow']->getOwnerTitle(),
'user' => $data['agent'],
'reply-to' => $data['topic'],
'topic-title' => $data['topic'],
- 'revision' => $data['post'],
- ) );
+ 'revision' => $data['post-2'],
+ ] );
- $this->assertNotifiedUser( $events, $data['user'], $data['agent'] );
+ $this->assertNotifiedUser( $events, $user, $data['agent'] );
}
public function testWatchingBoard() {
@@ -65,30 +69,37 @@ class NotifiedUsersTest extends PostRevisionTestCase {
return;
}
- WatchedItem::fromUserTitle( $data['user'], $data['boardWorkflow']->getArticleTitle() )->addWatch();
+ /** @var User $user */
+ $user = $data['user'];
+ $user->addWatch( $data['boardWorkflow']->getArticleTitle() );
- $events = $data['notificationController']->notifyNewTopic( array(
+ $events = $data['notificationController']->notifyNewTopic( [
'board-workflow' => $data['boardWorkflow'],
'topic-workflow' => $data['topicWorkflow'],
'topic-title' => $data['topic'],
'first-post' => $data['post'],
'user' => $data['agent'],
- ) );
+ ] );
- $this->assertNotifiedUser( $events, $data['user'], $data['agent'] );
+ $this->assertNotifiedUser( $events, $user, $data['agent'] );
}
protected function assertNotifiedUser( array $events, User $notifiedUser, User $notNotifiedUser ) {
- $users = array();
- foreach( $events as $event ) {
+ $users = [];
+ foreach ( $events as $event ) {
$iterator = EchoNotificationController::getUsersToNotifyForEvent( $event );
- foreach( $iterator as $user ) {
+ foreach ( $iterator as $user ) {
$users[] = $user;
}
}
// convert user objects back into user ids to simplify assertion
- $users = array_map( function( $user ) { return $user->getId(); }, $users );
+ $users = array_map(
+ function ( $user ) {
+ return $user->getId();
+ },
+ $users
+ );
$this->assertContains( $notifiedUser->getId(), $users );
$this->assertNotContains( $notNotifiedUser->getId(), $users );
@@ -115,14 +126,14 @@ class NotifiedUsersTest extends PostRevisionTestCase {
$agent->addToDatabase();
$tuple = UserTuple::newFromUser( $agent );
- $topicTitle = $this->generateObject( array(
+ $topicTitle = $this->generateObject( [
'rev_user_wiki' => $tuple->wiki,
'rev_user_id' => $tuple->id,
'rev_user_ip' => $tuple->ip,
'rev_flags' => 'wikitext',
'rev_content' => 'some content',
- ) );
+ ] );
/*
* We don't really *have* to store everything for this test. We could
@@ -141,14 +152,29 @@ class NotifiedUsersTest extends PostRevisionTestCase {
$firstPost = $topicTitle->reply( $topicWorkflow, $agent, 'ffuts dna ylper', 'wikitext' );
$this->store( $firstPost );
- return array(
+ /*
+ * Generation of the 2nd post will be a bit hacky: there's some code to ensure
+ * that first replies are ignored when sending notifications, and that is done
+ * by checking timestamps. We want our tests to run fast so I won't sleep for
+ * a second. Instead, I'll just inject the new timestamp (which is 2 seconds
+ * in the future) in there.
+ */
+ $secondPost = $topicTitle->reply( $topicWorkflow, $agent, 'lorem ipsum', 'wikitext' );
+ $newId = UUID::getComparisonUUID( (int)$secondPost->getPostId()->getTimestamp( TS_UNIX ) + 2 );
+ $reflection = new \ReflectionProperty( $secondPost, 'postId' );
+ $reflection->setAccessible( true );
+ $reflection->setValue( $secondPost, $newId );
+ $this->store( $secondPost );
+
+ return [
'boardWorkflow' => $boardWorkflow,
'topicWorkflow' => $topicWorkflow,
'post' => $firstPost,
+ 'post-2' => $secondPost,
'topic' => $topicTitle,
'user' => $user,
'agent' => $agent,
'notificationController' => Container::get( 'controller.notification' ),
- );
+ ];
}
}
diff --git a/Flow/tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php b/Flow/tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php
index e9781ea4..47c99948 100644
--- a/Flow/tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php
+++ b/Flow/tests/phpunit/Parsoid/Fixer/BadImageRemoverTest.php
@@ -4,7 +4,6 @@ namespace Flow\Tests\Parsoid;
use Flow\Parsoid\Fixer\BadImageRemover;
use Flow\Parsoid\ContentFixer;
-use Flow\Parsoid\Utils;
use Title;
/**
@@ -18,37 +17,43 @@ class BadImageRemoverTest extends \MediaWikiTestCase {
* test runner/
*/
public static function imageRemovalProvider() {
- return array(
- array(
+ return [
+ [
'Passes through allowed good images',
// expected html after filtering
'<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Image.jpg"><img resource="./File:Image.jpg" src="//upload.wikimedia.org/wikipedia/commons/7/78/Image.jpg" height="500" width="500"></a></span> and other stuff</p>',
// input html
'<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Image.jpg"><img resource="./File:Image.jpg" src="//upload.wikimedia.org/wikipedia/commons/7/78/Image.jpg" height="500" width="500"></a></span> and other stuff</p>',
// accept/decline callback
- function() { return false; }
- ),
+ function () {
+ return false;
+ }
+ ],
- array(
+ [
'Keeps unknown images',
// expected html after filtering
'<meta typeof="mw:Placeholder" data-parsoid="...">',
// input html
'<meta typeof="mw:Placeholder" data-parsoid="...">',
// accept/decline callback
- function() { return true; }
- ),
+ function () {
+ return true;
+ }
+ ],
- array(
+ [
'Strips declined images',
// expected html after filtering
'<p> and other stuff</p>',
// input html
'<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Image.jpg"><img resource="./File:Image.jpg" src="//upload.wikimedia.org/wikipedia/commons/7/78/Image.jpg" height="500" width="500"></a></span> and other stuff</p>',
// accept/decline callback
- function() { return true; }
- ),
- );
+ function () {
+ return true;
+ }
+ ],
+ ];
}
/**
* @dataProvider imageRemovalProvider
diff --git a/Flow/tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php b/Flow/tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php
index 1f3119a1..741efe69 100644
--- a/Flow/tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php
+++ b/Flow/tests/phpunit/Parsoid/Fixer/BaseHrefFixerTest.php
@@ -10,19 +10,19 @@ use Title;
* @group Flow
*/
class BaseHrefFixerTest extends \MediaWikiTestCase {
- public function setUp() {
+ protected function setUp() {
parent::setUp();
$this->setMwGlobals( 'wgServer', 'http://mywiki' );
}
public static function baseHrefProvider() {
- return array(
- array(
+ return [
+ [
'Rewrites href of link surrounding image',
'<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid=\'{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"[[test]] caption"}],"dsr":[0,43,2,2]}\'><a href="http://mywiki/wiki/./File:Example.jpg" data-parsoid=\'{"a":{"href":"./File:Example.jpg"},"sa":{},"dsr":[2,null,null,null]}\'><img resource="./File:Example.jpg" src="//upload.wikimedia.org/wikipedia/mediawiki/thumb/a/a9/Example.jpg/220px-Example.jpg" data-parsoid=\'{"a":{"resource":"./File:Example.jpg","height":"147","width":"220"},"sa":{"resource":"File:example.jpg"}}\' height="147" width="220"></a><figcaption data-parsoid=\'{"dsr":[null,41,null,null]}\'> caption</figcaption></figure>',
'<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid=\'{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"[[test]] caption"}],"dsr":[0,43,2,2]}\'><a href="./File:Example.jpg" data-parsoid=\'{"a":{"href":"./File:Example.jpg"},"sa":{},"dsr":[2,null,null,null]}\'><img resource="./File:Example.jpg" src="//upload.wikimedia.org/wikipedia/mediawiki/thumb/a/a9/Example.jpg/220px-Example.jpg" data-parsoid=\'{"a":{"resource":"./File:Example.jpg","height":"147","width":"220"},"sa":{"resource":"File:example.jpg"}}\' height="147" width="220"></a><figcaption data-parsoid=\'{"dsr":[null,41,null,null]}\'> caption</figcaption></figure>',
- ),
- );
+ ],
+ ];
}
/**
diff --git a/Flow/tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php b/Flow/tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php
index 308d8b23..84abb85d 100644
--- a/Flow/tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php
+++ b/Flow/tests/phpunit/Parsoid/Fixer/WikiLinkFixerTest.php
@@ -2,12 +2,9 @@
namespace Flow\Tests\Parsoid\Fixer;
-use Flow\Model\UUID;
use Flow\Parsoid\ContentFixer;
use Flow\Parsoid\Fixer\WikiLinkFixer;
-use Flow\Parsoid\Utils;
use Flow\Tests\PostRevisionTestCase;
-use Html;
use Title;
/**
@@ -15,43 +12,43 @@ use Title;
*/
class WikiLinkFixerTest extends PostRevisionTestCase {
- static public function redLinkProvider() {
- return array(
- array(
+ public static function redLinkProvider() {
+ return [
+ [
'Basic redlink application',
// html from parsoid for: [[Talk:Flow/Bugs]]
'<a rel="mw:WikiLink" href="./Talk:Flow/Bugs" data-parsoid=\'{"stx":"simple","a":{"href":"./Talk:Flow/Bugs"},"sa":{"href":"Talk:Flow/Bugs"},"dsr":[0,18,2,2]}\'>Talk:Flow/Bugs</a>',
// expect string
// @fixme easily breakable, depends on url order
htmlentities( 'Talk:Flow/Bugs&action=edit&redlink=1' ),
- ),
+ ],
- array(
+ [
'Subpage redlink application',
// html from parsoid for: [[/SubPage]]
'<a rel="mw:WikiLink" href=".//SubPage" data-parsoid=\'{"stx":"simple","a":{"href":".//SubPage"},"sa":{"href":"/SubPage"},"dsr":[0,12,2,2]}\'>/SubPage</a>',
// expect string
htmlentities( 'Main_Page/SubPage&action=edit&redlink=1' ),
- ),
+ ],
- array(
+ [
'Link containing html entities should be properly handled',
// html from parsoid for: [[Foo&Bar]]
'<a rel="mw:WikiLink" href="./Foo&amp;Bar" data-parsoid=\'{"stx":"simple","a":{"href":"./Foo&amp;Bar"},"sa":{"href":"Foo&amp;Bar"},"dsr":[0,11,2,2]}\'>Foo&amp;Bar</a>',
// expect string
'>Foo&amp;Bar</a>',
- ),
+ ],
- array(
+ [
'Link containing UTF-8 anchor content passes through as UTF-8',
// html from parsoid for: [[Foo|test – test]]
'<a rel="mw:WikiLink" href="./Foo" data-parsoid=\'{"stx":"piped","a":{"href":"./Foo"},"sa":{"href":"Foo"},"dsr":[0,19,6,2]}\'>test – test</a>',
// title text from parsoid
// expect string
'test – test',
- ),
+ ],
- array(
+ [
'Link containing urlencoded UTF-8 href works',
// html from parsoid for: [[Viquipèdia:La taverna/Tecnicismes/Arxius_2]]
'<a rel="mw:WikiLink" href="./Viquip%C3%A8dia:La_taverna/Tecnicismes/Arxius_2" title="Viquipdia:La taverna/Tecnicismes/Arxius 2" data-parsoid=\'{"stx":"simple","a":{"href":"./Viquipdia:La_taverna/Tecnicismes/Arxius_2"},"sa":{"href":"Viquipdia:La taverna/Tecnicismes/Arxius 2"},"dsr":[59,105,2,2]}\'>Viquipdia:La taverna/Tecnicismes/Arxius 2</a>',
@@ -59,8 +56,8 @@ class WikiLinkFixerTest extends PostRevisionTestCase {
// annoyingly we don't control Title::exists() so just assume redlink
// with index.php
'index.php?title=Viquip%C3%A8dia:La_taverna/Tecnicismes/Arxius_2'
- ),
- );
+ ],
+ ];
}
/**
@@ -80,7 +77,7 @@ class MethodReturnsConstraint extends \PHPUnit_Framework_Constraint {
}
protected function matches( $other ) {
- return $this->constraint->matches( call_user_func( array( $other, $this->method ) ) );
+ return $this->constraint->matches( call_user_func( [ $other, $this->method ] ) );
}
public function toString() {
diff --git a/Flow/tests/phpunit/Parsoid/ReferenceExtractorTest.php b/Flow/tests/phpunit/Parsoid/ReferenceExtractorTest.php
index b7af6509..d74b6870 100644
--- a/Flow/tests/phpunit/Parsoid/ReferenceExtractorTest.php
+++ b/Flow/tests/phpunit/Parsoid/ReferenceExtractorTest.php
@@ -6,7 +6,7 @@ use Flow\Container;
use Flow\Exception\WikitextException;
use Flow\Model\UUID;
use Flow\Parsoid\ReferenceFactory;
-use Flow\Parsoid\Utils;
+use Flow\Conversion\Utils;
use Flow\Tests\FlowTestCase;
use ReflectionMethod;
use Title;
@@ -16,7 +16,7 @@ use Title;
* @group Flow
*/
class ReferenceExtractorTestCase extends FlowTestCase {
- public function setUp() {
+ protected function setUp() {
parent::setUp();
// Check for Parsoid
@@ -28,8 +28,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
}
public static function referenceExtractorProvider() {
- return array(
- array(
+ return [
+ [
'Normal link',
// source wiki text
'[[My page]]',
@@ -39,8 +39,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'link',
// expected target
'title:My_page',
- ),
- array(
+ ],
+ [
'Link with URL encoding issues',
// source wiki text
'[[User talk:Werdna?]]',
@@ -50,8 +50,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'link',
// expected target
'title:User_talk:Werdna?',
- ),
- array(
+ ],
+ [
'Subpage link',
// source wiki text
'[[/Subpage]]',
@@ -63,8 +63,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'title:Talk:UTPage/Subpage',
// ???
'Talk:UTPage',
- ),
- array(
+ ],
+ [
'External link',
// source wiki text
'[http://www.google.com Google]',
@@ -74,8 +74,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'link',
// expected target
'url:http://www.google.com',
- ),
- array(
+ ],
+ [
'File',
// source wiki text
'[[File:Image.png]]',
@@ -85,8 +85,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'file',
// expected target
'title:File:Image.png',
- ),
- array(
+ ],
+ [
'File with parameters',
// source wiki text
'[[File:Image.png|25px]]',
@@ -96,8 +96,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'file',
// expected target
'title:File:Image.png',
- ),
- array(
+ ],
+ [
'File with encoding issues',
// source wiki text
'[[File:Image?.png]]',
@@ -107,8 +107,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'file',
// expected target
'title:File:Image?.png',
- ),
- array(
+ ],
+ [
'Template',
// source wiki text
'{{Foo}}',
@@ -118,9 +118,9 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'template',
// expected target
'title:Template:Foo',
- ),
+ ],
- array(
+ [
'Non-existent File',
// source wiki text
'[[File:Some/Files/Really/Should_Not_Ex/ist.png]]',
@@ -130,8 +130,8 @@ class ReferenceExtractorTestCase extends FlowTestCase {
'file',
// expected target
'title:File:Some/Files/Really/Should_Not_Ex/ist.png',
- )
- );
+ ]
+ ];
}
/**
diff --git a/Flow/tests/phpunit/PermissionsTest.php b/Flow/tests/phpunit/PermissionsTest.php
index b286f135..f33b4b74 100644
--- a/Flow/tests/phpunit/PermissionsTest.php
+++ b/Flow/tests/phpunit/PermissionsTest.php
@@ -7,7 +7,6 @@ use Flow\FlowActions;
use Flow\Model\AbstractRevision;
use Flow\Model\PostRevision;
use Flow\RevisionActionPermissions;
-use Block;
use User;
/**
@@ -18,7 +17,7 @@ class PermissionsTest extends PostRevisionTestCase {
/**
* @var array
*/
- protected $tablesUsed = array( 'user', 'user_groups' );
+ protected $tablesUsed = [ 'user', 'user_groups' ];
/**
* @var FlowActions
@@ -28,38 +27,74 @@ class PermissionsTest extends PostRevisionTestCase {
/**
* @var PostRevision
*/
- protected
- $topic,
- $hiddenTopic,
- $deletedTopic,
- $suppressedTopic,
- $post,
- $hiddenPost,
- $deletedPost,
- $suppressedPost;
+ protected $topic;
+
+ /**
+ * @var PostRevision
+ */
+ protected $hiddenTopic;
+
+ /**
+ * @var PostRevision
+ */
+ protected $deletedTopic;
+
+ /**
+ * @var PostRevision
+ */
+ protected $suppressedTopic;
+
+ /**
+ * @var PostRevision
+ */
+ protected $post;
+
+ /**
+ * @var PostRevision
+ */
+ protected $hiddenPost;
+
+ /**
+ * @var PostRevision
+ */
+ protected $deletedPost;
+
+ /**
+ * @var PostRevision
+ */
+ protected $suppressedPost;
+
+ /**
+ * @var User
+ */
+ protected $anonUser;
+
+ /**
+ * @var User
+ */
+ protected $unconfirmedUser;
+
+ /**
+ * @var User
+ */
+ protected $confirmedUser;
+
+ /**
+ * @var User
+ */
+ protected $sysopUser;
/**
* @var User
*/
- protected
- $anonUser,
- $unconfirmedUser,
- $confirmedUser,
- $sysopUser,
- $oversightUser;
+ protected $oversightUser;
protected function setUp() {
parent::setUp();
// We don't want local config getting in the way of testing whether or
// not our permissions implementation works well.
- // This will load default $wgGroupPermissions + Flow settings, so we can
- // test if permissions work well, regardless of any custom config.
- global $IP, $wgFlowGroupPermissions;
- $wgGroupPermissions = array();
- require "$IP/includes/DefaultSettings.php";
- $wgGroupPermissions = array_merge_recursive( $wgGroupPermissions, $wgFlowGroupPermissions );
- $this->setMwGlobals( 'wgGroupPermissions', $wgGroupPermissions );
+ $this->resetPermissions();
// load actions object
$this->actions = Container::get( 'flow_actions' );
@@ -89,130 +124,130 @@ class PermissionsTest extends PostRevisionTestCase {
* @return array
*/
public function permissionsProvider() {
- return array(
+ return [
// anon users can submit content, but not moderate
- array( $this->anonUser(), null, 'create-header', true ),
-// array( $this->anonUser(), $this->header(), 'edit-header', true ),
- array( $this->anonUser(), $this->topic(), 'edit-title', true ),
- array( $this->anonUser(), null, 'new-post', true ),
- array( $this->anonUser(), $this->post(), 'edit-post', false ),
- array( $this->anonUser(), $this->post(), 'hide-post', true ),
- array( $this->anonUser(), $this->topic(), 'hide-topic', true ),
- array( $this->anonUser(), $this->topic(), 'lock-topic', false ),
- array( $this->anonUser(), $this->post(), 'delete-post', false ),
- array( $this->anonUser(), $this->topic(), 'delete-topic', false ),
- array( $this->anonUser(), $this->post(), 'suppress-post', false ),
- array( $this->anonUser(), $this->topic(), 'suppress-topic', false ),
- array( $this->anonUser(), $this->post(), 'restore-post', false ),
- array( $this->anonUser(), $this->topic(), 'restore-topic', false ),
- array( $this->anonUser(), $this->post(), 'history', true ),
- array( $this->anonUser(), $this->post(), 'view', true ),
- array( $this->anonUser(), $this->post(), 'reply', true ),
+ [ $this->anonUser(), null, 'create-header', true ],
+ // array( $this->anonUser(), $this->header(), 'edit-header', true ),
+ [ $this->anonUser(), $this->topic(), 'edit-title', true ],
+ [ $this->anonUser(), null, 'new-post', true ],
+ [ $this->anonUser(), $this->post(), 'edit-post', false ],
+ [ $this->anonUser(), $this->post(), 'hide-post', true ],
+ [ $this->anonUser(), $this->topic(), 'hide-topic', true ],
+ [ $this->anonUser(), $this->topic(), 'lock-topic', false ],
+ [ $this->anonUser(), $this->post(), 'delete-post', false ],
+ [ $this->anonUser(), $this->topic(), 'delete-topic', false ],
+ [ $this->anonUser(), $this->post(), 'suppress-post', false ],
+ [ $this->anonUser(), $this->topic(), 'suppress-topic', false ],
+ [ $this->anonUser(), $this->post(), 'restore-post', false ],
+ [ $this->anonUser(), $this->topic(), 'restore-topic', false ],
+ [ $this->anonUser(), $this->post(), 'history', true ],
+ [ $this->anonUser(), $this->post(), 'view', true ],
+ [ $this->anonUser(), $this->post(), 'reply', true ],
// unconfirmed users can also hide posts...
- array( $this->unconfirmedUser(), null, 'create-header', true ),
-// array( $this->unconfirmedUser(), $this->header(), 'edit-header', true ),
- array( $this->unconfirmedUser(), $this->topic(), 'edit-title', true ),
- array( $this->unconfirmedUser(), null, 'new-post', true ),
- array( $this->unconfirmedUser(), $this->post(), 'edit-post', true ), // can edit own post
- array( $this->unconfirmedUser(), $this->post(), 'hide-post', true ),
- array( $this->unconfirmedUser(), $this->topic(), 'hide-topic', true ),
- array( $this->unconfirmedUser(), $this->topic(), 'lock-topic', true ),
- array( $this->unconfirmedUser(), $this->post(), 'delete-post', false ),
- array( $this->unconfirmedUser(), $this->topic(), 'delete-topic', false ),
- array( $this->unconfirmedUser(), $this->post(), 'suppress-post', false ),
- array( $this->unconfirmedUser(), $this->topic(), 'suppress-topic', false ),
- array( $this->unconfirmedUser(), $this->post(), 'restore-post', false ), // $this->post is not hidden
- array( $this->unconfirmedUser(), $this->topic(), 'restore-topic', false ), // $this->topic is not hidden
- array( $this->unconfirmedUser(), $this->post(), 'history', true ),
- array( $this->unconfirmedUser(), $this->post(), 'view', true ),
- array( $this->unconfirmedUser(), $this->post(), 'reply', true ),
+ [ $this->unconfirmedUser(), null, 'create-header', true ],
+ // array( $this->unconfirmedUser(), $this->header(), 'edit-header', true ),
+ [ $this->unconfirmedUser(), $this->topic(), 'edit-title', true ],
+ [ $this->unconfirmedUser(), null, 'new-post', true ],
+ [ $this->unconfirmedUser(), $this->post(), 'edit-post', true ], // can edit own post
+ [ $this->unconfirmedUser(), $this->post(), 'hide-post', true ],
+ [ $this->unconfirmedUser(), $this->topic(), 'hide-topic', true ],
+ [ $this->unconfirmedUser(), $this->topic(), 'lock-topic', true ],
+ [ $this->unconfirmedUser(), $this->post(), 'delete-post', false ],
+ [ $this->unconfirmedUser(), $this->topic(), 'delete-topic', false ],
+ [ $this->unconfirmedUser(), $this->post(), 'suppress-post', false ],
+ [ $this->unconfirmedUser(), $this->topic(), 'suppress-topic', false ],
+ [ $this->unconfirmedUser(), $this->post(), 'restore-post', false ], // $this->post is not hidden
+ [ $this->unconfirmedUser(), $this->topic(), 'restore-topic', false ], // $this->topic is not hidden
+ [ $this->unconfirmedUser(), $this->post(), 'history', true ],
+ [ $this->unconfirmedUser(), $this->post(), 'view', true ],
+ [ $this->unconfirmedUser(), $this->post(), 'reply', true ],
// ... as well as restore hidden posts
- array( $this->unconfirmedUser(), $this->hiddenPost(), 'restore-post', true ),
- array( $this->unconfirmedUser(), $this->hiddenTopic(), 'restore-topic', true ),
+ [ $this->unconfirmedUser(), $this->hiddenPost(), 'restore-post', true ],
+ [ $this->unconfirmedUser(), $this->hiddenTopic(), 'restore-topic', true ],
// ... but not restore deleted/suppressed posts
- array( $this->unconfirmedUser(), $this->deletedPost(), 'restore-post', false ),
- array( $this->unconfirmedUser(), $this->deletedTopic(), 'restore-topic', false ),
- array( $this->unconfirmedUser(), $this->suppressedPost(), 'restore-post', false ),
- array( $this->unconfirmedUser(), $this->suppressedTopic(), 'restore-topic', false ),
+ [ $this->unconfirmedUser(), $this->deletedPost(), 'restore-post', false ],
+ [ $this->unconfirmedUser(), $this->deletedTopic(), 'restore-topic', false ],
+ [ $this->unconfirmedUser(), $this->suppressedPost(), 'restore-post', false ],
+ [ $this->unconfirmedUser(), $this->suppressedTopic(), 'restore-topic', false ],
// confirmed users are the same as unconfirmed users, in terms of permissions
- array( $this->confirmedUser(), null, 'create-header', true ),
-// array( $this->confirmedUser(), $this->header(), 'edit-header', true ),
- array( $this->confirmedUser(), $this->topic(), 'edit-title', true ),
- array( $this->confirmedUser(), null, 'new-post', true ),
- array( $this->confirmedUser(), $this->post(), 'edit-post', false ),
- array( $this->confirmedUser(), $this->post(), 'hide-post', true ),
- array( $this->confirmedUser(), $this->topic(), 'hide-topic', true ),
- array( $this->confirmedUser(), $this->post(), 'delete-post', false ),
- array( $this->confirmedUser(), $this->topic(), 'delete-topic', false ),
- array( $this->confirmedUser(), $this->topic(), 'lock-topic', true ),
- array( $this->confirmedUser(), $this->post(), 'suppress-post', false ),
- array( $this->confirmedUser(), $this->topic(), 'suppress-topic', false ),
- array( $this->confirmedUser(), $this->post(), 'restore-post', false ), // $this->post is not hidden
- array( $this->confirmedUser(), $this->topic(), 'restore-topic', false ), // $this->topic is not hidden
- array( $this->confirmedUser(), $this->post(), 'history', true ),
- array( $this->confirmedUser(), $this->post(), 'view', true ),
- array( $this->confirmedUser(), $this->post(), 'reply', true ),
- array( $this->confirmedUser(), $this->hiddenPost(), 'restore-post', true ),
- array( $this->confirmedUser(), $this->hiddenTopic(), 'restore-topic', true ),
- array( $this->confirmedUser(), $this->deletedPost(), 'restore-post', false ),
- array( $this->confirmedUser(), $this->deletedTopic(), 'restore-topic', false ),
- array( $this->confirmedUser(), $this->suppressedPost(), 'restore-post', false ),
- array( $this->confirmedUser(), $this->suppressedTopic(), 'restore-topic', false ),
+ [ $this->confirmedUser(), null, 'create-header', true ],
+ // array( $this->confirmedUser(), $this->header(), 'edit-header', true ),
+ [ $this->confirmedUser(), $this->topic(), 'edit-title', true ],
+ [ $this->confirmedUser(), null, 'new-post', true ],
+ [ $this->confirmedUser(), $this->post(), 'edit-post', false ],
+ [ $this->confirmedUser(), $this->post(), 'hide-post', true ],
+ [ $this->confirmedUser(), $this->topic(), 'hide-topic', true ],
+ [ $this->confirmedUser(), $this->post(), 'delete-post', false ],
+ [ $this->confirmedUser(), $this->topic(), 'delete-topic', false ],
+ [ $this->confirmedUser(), $this->topic(), 'lock-topic', true ],
+ [ $this->confirmedUser(), $this->post(), 'suppress-post', false ],
+ [ $this->confirmedUser(), $this->topic(), 'suppress-topic', false ],
+ [ $this->confirmedUser(), $this->post(), 'restore-post', false ], // $this->post is not hidden
+ [ $this->confirmedUser(), $this->topic(), 'restore-topic', false ], // $this->topic is not hidden
+ [ $this->confirmedUser(), $this->post(), 'history', true ],
+ [ $this->confirmedUser(), $this->post(), 'view', true ],
+ [ $this->confirmedUser(), $this->post(), 'reply', true ],
+ [ $this->confirmedUser(), $this->hiddenPost(), 'restore-post', true ],
+ [ $this->confirmedUser(), $this->hiddenTopic(), 'restore-topic', true ],
+ [ $this->confirmedUser(), $this->deletedPost(), 'restore-post', false ],
+ [ $this->confirmedUser(), $this->deletedTopic(), 'restore-topic', false ],
+ [ $this->confirmedUser(), $this->suppressedPost(), 'restore-post', false ],
+ [ $this->confirmedUser(), $this->suppressedTopic(), 'restore-topic', false ],
// sysops can do all (incl. editing posts) but suppressing
- array( $this->sysopUser(), null, 'create-header', true ),
-// array( $this->sysopUser(), $this->header(), 'edit-header', true ),
- array( $this->sysopUser(), $this->topic(), 'edit-title', true ),
- array( $this->sysopUser(), null, 'new-post', true ),
- array( $this->sysopUser(), $this->post(), 'edit-post', true ),
- array( $this->sysopUser(), $this->post(), 'hide-post', true ),
- array( $this->sysopUser(), $this->topic(), 'hide-topic', true ),
- array( $this->sysopUser(), $this->topic(), 'lock-topic', true ),
- array( $this->sysopUser(), $this->post(), 'delete-post', true ),
- array( $this->sysopUser(), $this->topic(), 'delete-topic', true ),
- array( $this->sysopUser(), $this->post(), 'suppress-post', false ),
- array( $this->sysopUser(), $this->topic(), 'suppress-topic', false ),
- array( $this->sysopUser(), $this->post(), 'restore-post', false ), // $this->post is not hidden
- array( $this->sysopUser(), $this->topic(), 'restore-topic', false ), // $this->topic is not hidden
- array( $this->sysopUser(), $this->topic(), 'history', true ),
- array( $this->sysopUser(), $this->post(), 'view', true ),
- array( $this->sysopUser(), $this->post(), 'reply', true ),
- array( $this->sysopUser(), $this->hiddenPost(), 'restore-post', true ),
- array( $this->sysopUser(), $this->hiddenTopic(), 'restore-topic', true ),
- array( $this->sysopUser(), $this->deletedPost(), 'restore-post', true ),
- array( $this->sysopUser(), $this->deletedTopic(), 'restore-topic', true ),
- array( $this->sysopUser(), $this->suppressedPost(), 'restore-post', false ),
- array( $this->sysopUser(), $this->suppressedTopic(), 'restore-topic', false ),
+ [ $this->sysopUser(), null, 'create-header', true ],
+ // array( $this->sysopUser(), $this->header(), 'edit-header', true ),
+ [ $this->sysopUser(), $this->topic(), 'edit-title', true ],
+ [ $this->sysopUser(), null, 'new-post', true ],
+ [ $this->sysopUser(), $this->post(), 'edit-post', true ],
+ [ $this->sysopUser(), $this->post(), 'hide-post', true ],
+ [ $this->sysopUser(), $this->topic(), 'hide-topic', true ],
+ [ $this->sysopUser(), $this->topic(), 'lock-topic', true ],
+ [ $this->sysopUser(), $this->post(), 'delete-post', true ],
+ [ $this->sysopUser(), $this->topic(), 'delete-topic', true ],
+ [ $this->sysopUser(), $this->post(), 'suppress-post', false ],
+ [ $this->sysopUser(), $this->topic(), 'suppress-topic', false ],
+ [ $this->sysopUser(), $this->post(), 'restore-post', false ], // $this->post is not hidden
+ [ $this->sysopUser(), $this->topic(), 'restore-topic', false ], // $this->topic is not hidden
+ [ $this->sysopUser(), $this->topic(), 'history', true ],
+ [ $this->sysopUser(), $this->post(), 'view', true ],
+ [ $this->sysopUser(), $this->post(), 'reply', true ],
+ [ $this->sysopUser(), $this->hiddenPost(), 'restore-post', true ],
+ [ $this->sysopUser(), $this->hiddenTopic(), 'restore-topic', true ],
+ [ $this->sysopUser(), $this->deletedPost(), 'restore-post', true ],
+ [ $this->sysopUser(), $this->deletedTopic(), 'restore-topic', true ],
+ [ $this->sysopUser(), $this->suppressedPost(), 'restore-post', false ],
+ [ $this->sysopUser(), $this->suppressedTopic(), 'restore-topic', false ],
// oversighters can do everything + suppress (but not edit!)
- array( $this->oversightUser(), null, 'create-header', true ),
-// array( $this->oversightUser(), $this->header(), 'edit-header', true ),
- array( $this->oversightUser(), $this->topic(), 'edit-title', true ),
- array( $this->oversightUser(), null, 'new-post', true ),
- array( $this->oversightUser(), $this->post(), 'edit-post', false ),
- array( $this->oversightUser(), $this->post(), 'hide-post', true ),
- array( $this->oversightUser(), $this->topic(), 'hide-topic', true ),
- array( $this->oversightUser(), $this->topic(), 'lock-topic', true ),
- array( $this->oversightUser(), $this->post(), 'delete-post', true ),
- array( $this->oversightUser(), $this->topic(), 'delete-topic', true ),
- array( $this->oversightUser(), $this->post(), 'suppress-post', true ),
- array( $this->oversightUser(), $this->topic(), 'suppress-topic', true ),
- array( $this->oversightUser(), $this->post(), 'restore-post', false ), // $this->post is not hidden
- array( $this->oversightUser(), $this->topic(), 'restore-topic', false ), // $this->topic is not hidden
- array( $this->oversightUser(), $this->post(), 'history', true ),
- array( $this->oversightUser(), $this->post(), 'view', true ),
- array( $this->oversightUser(), $this->post(), 'reply', true ),
- array( $this->oversightUser(), $this->hiddenPost(), 'restore-post', true ),
- array( $this->oversightUser(), $this->hiddenTopic(), 'restore-topic', true ),
- array( $this->oversightUser(), $this->deletedPost(), 'restore-post', true ),
- array( $this->oversightUser(), $this->deletedTopic(), 'restore-topic', true ),
- array( $this->oversightUser(), $this->suppressedPost(), 'restore-post', true ),
- array( $this->oversightUser(), $this->suppressedTopic(), 'restore-topic', true ),
- );
+ [ $this->oversightUser(), null, 'create-header', true ],
+ // array( $this->oversightUser(), $this->header(), 'edit-header', true ),
+ [ $this->oversightUser(), $this->topic(), 'edit-title', true ],
+ [ $this->oversightUser(), null, 'new-post', true ],
+ [ $this->oversightUser(), $this->post(), 'edit-post', false ],
+ [ $this->oversightUser(), $this->post(), 'hide-post', true ],
+ [ $this->oversightUser(), $this->topic(), 'hide-topic', true ],
+ [ $this->oversightUser(), $this->topic(), 'lock-topic', true ],
+ [ $this->oversightUser(), $this->post(), 'delete-post', true ],
+ [ $this->oversightUser(), $this->topic(), 'delete-topic', true ],
+ [ $this->oversightUser(), $this->post(), 'suppress-post', true ],
+ [ $this->oversightUser(), $this->topic(), 'suppress-topic', true ],
+ [ $this->oversightUser(), $this->post(), 'restore-post', false ], // $this->post is not hidden
+ [ $this->oversightUser(), $this->topic(), 'restore-topic', false ], // $this->topic is not hidden
+ [ $this->oversightUser(), $this->post(), 'history', true ],
+ [ $this->oversightUser(), $this->post(), 'view', true ],
+ [ $this->oversightUser(), $this->post(), 'reply', true ],
+ [ $this->oversightUser(), $this->hiddenPost(), 'restore-post', true ],
+ [ $this->oversightUser(), $this->hiddenTopic(), 'restore-topic', true ],
+ [ $this->oversightUser(), $this->deletedPost(), 'restore-post', true ],
+ [ $this->oversightUser(), $this->deletedTopic(), 'restore-topic', true ],
+ [ $this->oversightUser(), $this->suppressedPost(), 'restore-post', true ],
+ [ $this->oversightUser(), $this->suppressedTopic(), 'restore-topic', true ],
+ ];
}
/**
@@ -281,10 +316,10 @@ class PermissionsTest extends PostRevisionTestCase {
protected function hiddenTopic() {
if ( !$this->hiddenTopic ) {
- $this->hiddenTopic = $this->generateObject( array(
+ $this->hiddenTopic = $this->generateObject( [
'rev_change_type' => 'hide-topic',
'rev_mod_state' => AbstractRevision::MODERATED_HIDDEN
- ) );
+ ] );
}
return $this->hiddenTopic;
@@ -292,10 +327,10 @@ class PermissionsTest extends PostRevisionTestCase {
protected function deletedTopic() {
if ( !$this->deletedTopic ) {
- $this->deletedTopic = $this->generateObject( array(
+ $this->deletedTopic = $this->generateObject( [
'rev_change_type' => 'delete-topic',
'rev_mod_state' => AbstractRevision::MODERATED_DELETED
- ) );
+ ] );
}
return $this->deletedTopic;
@@ -303,10 +338,10 @@ class PermissionsTest extends PostRevisionTestCase {
protected function suppressedTopic() {
if ( !$this->suppressedTopic ) {
- $this->suppressedTopic = $this->generateObject( array(
+ $this->suppressedTopic = $this->generateObject( [
'rev_change_type' => 'suppress-topic',
'rev_mod_state' => AbstractRevision::MODERATED_SUPPRESSED
- ) );
+ ] );
}
return $this->suppressedTopic;
@@ -314,16 +349,16 @@ class PermissionsTest extends PostRevisionTestCase {
protected function post() {
if ( !$this->post ) {
- $this->post = $this->generateObject( array(
+ $this->post = $this->generateObject( [
'tree_orig_user_id' => $this->unconfirmedUser()->getId(),
'tree_orig_user_ip' => '',
'tree_parent_id' => $this->topic()->getPostId()->getBinary()
- ), array(), 1 );
- $this->post->setRootPost( $this->generateObject( array(
+ ], [], 1 );
+ $this->post->setRootPost( $this->generateObject( [
'tree_orig_user_id' => $this->unconfirmedUser()->getId(),
'tree_orig_user_ip' => '',
'tree_parent_id' => $this->topic()->getPostId()->getBinary()
- ), array(), 1 ) );
+ ], [], 1 ) );
}
return $this->post;
@@ -331,13 +366,13 @@ class PermissionsTest extends PostRevisionTestCase {
protected function hiddenPost() {
if ( !$this->hiddenPost ) {
- $this->hiddenPost = $this->generateObject( array(
+ $this->hiddenPost = $this->generateObject( [
'tree_orig_user_id' => $this->unconfirmedUser()->getId(),
'tree_orig_user_ip' => '',
'tree_parent_id' => $this->topic()->getPostId()->getBinary(),
'rev_change_type' => 'hide-post',
'rev_mod_state' => AbstractRevision::MODERATED_HIDDEN
- ), array(), 1 );
+ ], [], 1 );
}
return $this->hiddenPost;
@@ -345,13 +380,13 @@ class PermissionsTest extends PostRevisionTestCase {
protected function deletedPost() {
if ( !$this->deletedPost ) {
- $this->deletedPost = $this->generateObject( array(
+ $this->deletedPost = $this->generateObject( [
'tree_orig_user_id' => $this->unconfirmedUser()->getId(),
'tree_orig_user_ip' => '',
'tree_parent_id' => $this->topic()->getPostId()->getBinary(),
'rev_change_type' => 'delete-post',
'rev_mod_state' => AbstractRevision::MODERATED_DELETED
- ), array(), 1 );
+ ], [], 1 );
}
return $this->deletedPost;
@@ -359,13 +394,13 @@ class PermissionsTest extends PostRevisionTestCase {
protected function suppressedPost() {
if ( !$this->suppressedPost ) {
- $this->suppressedPost = $this->generateObject( array(
+ $this->suppressedPost = $this->generateObject( [
'tree_orig_user_id' => $this->unconfirmedUser()->getId(),
'tree_orig_user_ip' => '',
'tree_parent_id' => $this->topic()->getPostId()->getBinary(),
'rev_change_type' => 'suppress-post',
'rev_mod_state' => AbstractRevision::MODERATED_SUPPRESSED
- ), array(), 1 );
+ ], [], 1 );
}
return $this->suppressedPost;
diff --git a/Flow/tests/phpunit/PostRevisionTestCase.php b/Flow/tests/phpunit/PostRevisionTestCase.php
index 81c8099b..0ef772b2 100644
--- a/Flow/tests/phpunit/PostRevisionTestCase.php
+++ b/Flow/tests/phpunit/PostRevisionTestCase.php
@@ -6,7 +6,6 @@ use DeferredUpdates;
use Flow\Collection\PostCollection;
use Flow\Container;
use Flow\Data\ManagerGroup;
-use Flow\Exception\DataModelException;
use Flow\Exception\FlowException;
use Flow\Model\AbstractRevision;
use Flow\Model\PostRevision;
@@ -23,7 +22,7 @@ use User;
* @group Database
*/
class PostRevisionTestCase extends FlowTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'flow_revision',
'flow_topic_list',
'flow_tree_node',
@@ -31,25 +30,26 @@ class PostRevisionTestCase extends FlowTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
/**
* @var PostRevision[]
*/
- protected $revisions = array();
+ protected $revisions = [];
/**
* @var Workflow[]
*/
- protected $workflows = array();
+ protected $workflows = [];
protected function setUp() {
parent::setUp();
// Revisions must be blanked here otherwise phpunit run with --repeat will remember
// ths revision list between multiple invocations of the test causing issues.
- $this->revisions = array();
+ $this->revisions = [];
}
/**
@@ -61,7 +61,7 @@ class PostRevisionTestCase extends FlowTestCase {
foreach ( $this->revisions as $revision ) {
try {
$workflow = $revision->getCollection()->getWorkflow();
- $this->getStorage()->multiRemove( array( $revision ), array( 'workflow' => $workflow ) );
+ $this->getStorage()->multiRemove( [ $revision ], [ 'workflow' => $workflow ] );
} catch ( \MWException $e ) {
// ignore - lifecyclehandlers may cause issues with tests, where
// not all related stuff is loaded
@@ -70,9 +70,9 @@ class PostRevisionTestCase extends FlowTestCase {
foreach ( $this->workflows as $workflow ) {
try {
- $this->getStorage()->multiRemove( array( $workflow ) );
+ $this->getStorage()->multiRemove( [ $workflow ] );
- $found = $this->getStorage()->find( 'TopicListEntry', array( 'topic_id' => $workflow->getId() ) );
+ $found = $this->getStorage()->find( 'TopicListEntry', [ 'topic_id' => $workflow->getId() ] );
if ( $found ) {
$this->getStorage()->multiRemove( $found );
}
@@ -103,14 +103,14 @@ class PostRevisionTestCase extends FlowTestCase {
* @param array[optional] $row DB row data (only specify override columns)
* @return array
*/
- protected function generateRow( array $row = array() ) {
- $workflow = $this->generateWorkflow( array( 'workflow_type' => 'topic' ) );
+ protected function generateRow( array $row = [] ) {
+ $workflow = $this->generateWorkflow( [ 'workflow_type' => 'topic' ] );
$uuidRevision = UUID::create();
$user = User::newFromName( 'UTSysop' );
$tuple = UserTuple::newFromUser( $user );
- return $row + array(
+ return $row + [
// flow_revision
'rev_id' => $uuidRevision->getBinary(),
'rev_type' => 'post',
@@ -142,7 +142,7 @@ class PostRevisionTestCase extends FlowTestCase {
'tree_orig_user_id' => $tuple->id,
'tree_orig_user_ip' => $tuple->ip,
'tree_parent_id' => null,
- );
+ ];
}
/**
@@ -151,11 +151,11 @@ class PostRevisionTestCase extends FlowTestCase {
* @param array $row
* @return Workflow
*/
- protected function generateWorkflow( $row = array() ) {
- $row = $row + array(
+ protected function generateWorkflow( $row = [] ) {
+ $row = $row + [
'workflow_id' => UUID::create()->getBinary(),
'workflow_type' => 'topic',
- 'workflow_wiki' => wfWikiId(),
+ 'workflow_wiki' => wfWikiID(),
// The test workflow has no real associated page, this is
// just a random page number
'workflow_page_id' => 1,
@@ -163,7 +163,7 @@ class PostRevisionTestCase extends FlowTestCase {
'workflow_title_text' => 'Test',
'workflow_lock_state' => 0,
'workflow_last_update_timestamp' => wfTimestampNow(),
- );
+ ];
$workflow = Workflow::fromStorageRow( $row );
// store workflow:
@@ -186,7 +186,7 @@ class PostRevisionTestCase extends FlowTestCase {
* @param int[optional] $depth Depth of the PostRevision object
* @return PostRevision
*/
- protected function generateObject( array $row = array(), $children = array(), $depth = 0 ) {
+ protected function generateObject( array $row = [], $children = [], $depth = 0 ) {
$row = $this->generateRow( $row );
$revision = PostRevision::fromStorageRow( $row );
@@ -216,15 +216,15 @@ class PostRevisionTestCase extends FlowTestCase {
->createWorkflowLoader( $topicWorkflow->getOwnerTitle() )
->getWorkflow();
- $metadata = array(
+ $metadata = [
'workflow' => $topicWorkflow,
'board-workflow' => $boardWorkflow,
// @todo: Topic.php also adds 'topic-title'
- );
+ ];
// check if this topic (+ workflow + board workflow + board page) have
// already been inserted or do so now
- $found = $this->getStorage()->find( 'TopicListEntry', array( 'topic_id' => $topicWorkflow->getId() ) );
+ $found = $this->getStorage()->find( 'TopicListEntry', [ 'topic_id' => $topicWorkflow->getId() ] );
if ( !$found ) {
$title = $boardWorkflow->getOwnerTitle();
$user = User::newFromName( '127.0.0.1', false );
@@ -232,8 +232,8 @@ class PostRevisionTestCase extends FlowTestCase {
/** @var OccupationController $occupationController */
$occupationController = Container::get( 'occupation_controller' );
// make sure user has rights to create board
- $user->mRights = array_merge( $user->getRights(), array( 'flow-create-board' ) );
- $occupationController->allowCreation( $title, $user );
+ $user->mRights = array_merge( $user->getRights(), [ 'flow-create-board' ] );
+ $occupationController->safeAllowCreation( $title, $user );
$occupationController->ensureFlowRevision( new \Article( $title ), $boardWorkflow );
$topicListEntry = TopicListEntry::create( $boardWorkflow, $topicWorkflow );
@@ -247,7 +247,7 @@ class PostRevisionTestCase extends FlowTestCase {
/** @var SplQueue $deferredQueue */
$deferredQueue = Container::get( 'deferred_queue' );
- while( !$deferredQueue->isEmpty() ) {
+ while ( !$deferredQueue->isEmpty() ) {
try {
DeferredUpdates::addCallableUpdate( $deferredQueue->dequeue() );
@@ -265,22 +265,22 @@ class PostRevisionTestCase extends FlowTestCase {
protected function clearExtraLifecycleHandlers() {
$container = Container::getContainer();
- foreach( array_unique( $container['storage.manager_list'] ) as $storage ) {
+ foreach ( array_unique( $container['storage.manager_list'] ) as $storage ) {
if ( !isset( $container["$storage.listeners"] ) ) {
continue;
}
- $container->extend( "$storage.listeners", function( $listeners ) {
+ $container->extend( "$storage.listeners", function ( $listeners ) {
unset(
// putting together the right metadata for a commit is beyond the
// scope of these tests
- $listeners['storage.post.listeners.notification'],
+ $listeners['listeners.notification'],
// Recent changes logging is outside the scope of tests, and
// causes interaction issues
$listeners['listener.recentchanges'],
// BoardHistory requires we also wire together TopicListEntry objects for
// each revision, but that's also beyond our scope.
- $listeners['storage.board_history.indexes.primary']
+ $listeners['storage.post_board_history.indexes.primary']
);
return $listeners;
diff --git a/Flow/tests/phpunit/Repository/TreeRepositoryDbTest.php b/Flow/tests/phpunit/Repository/TreeRepositoryDbTest.php
index a439b8a9..4d005827 100644
--- a/Flow/tests/phpunit/Repository/TreeRepositoryDbTest.php
+++ b/Flow/tests/phpunit/Repository/TreeRepositoryDbTest.php
@@ -3,8 +3,6 @@
namespace Flow\Tests\Repository;
use Flow\Container;
-use Flow\Data\BagOStuff\BufferedBagOStuff;
-use Flow\Data\BufferedCache;
use Flow\Model\UUID;
use Flow\Repository\TreeRepository;
use Flow\Tests\FlowTestCase;
@@ -14,20 +12,20 @@ use Flow\Tests\FlowTestCase;
* @group Database
*/
class TreeRepositorydbTest extends FlowTestCase {
- protected $tablesUsed = array( 'flow_tree_node' );
+ protected $tablesUsed = [ 'flow_tree_node' ];
public function testSomething() {
// meaningless set of ids used for repeatability
- $ids = array_map( array( 'Flow\Model\UUID', 'create' ), array(
+ $ids = array_map( [ 'Flow\Model\UUID', 'create' ], [
"s3z44zhp93j5vvc8", "s3z44zhqt7yt8220", "s46w00pmmw0otc0q",
"s3qvc7cnor86wvb4", "s3qvc7bbcxr3f340",
"s3gre9r27pobtg0n", "s3cdl3dfqf8brx18", "s3cdl3dhajnz43r0",
- ) );
+ ] );
// Use 2 repos with 2 caches, the one you insert with reads from cache
// the other reads from db due to different cache
- $cache[] = new BufferedCache( new BufferedBagOStuff( new \HashBagOStuff() ), 600 );
- $cache[] = new BufferedCache( new BufferedBagOStuff( new \HashBagOStuff() ), 600 );
+ $cache[] = $this->getCache();
+ $cache[] = $this->getCache();
$dbf = Container::get( 'db.factory' );
$repo[] = new TreeRepository( $dbf, $cache[0] );
$repo[] = new TreeRepository( $dbf, $cache[1] );
@@ -36,11 +34,11 @@ class TreeRepositorydbTest extends FlowTestCase {
wfDebugLog( 'Flow', "\n\n************** id0 as new root ************" );
$repo[0]->insert( $ids[0] );
$this->assertEquals(
- array( $ids[0] ),
+ [ $ids[0] ],
$repo[0]->findRootPath( $ids[0] )
);
$this->assertEquals(
- array( $ids[0] ),
+ [ $ids[0] ],
$repo[1]->findRootPath( $ids[0] )
);
@@ -48,11 +46,11 @@ class TreeRepositorydbTest extends FlowTestCase {
wfDebugLog( 'Flow', "\n\n************** id1 as child of id0 ************" );
$repo[0]->insert( $ids[1], $ids[0] );
$this->assertEquals(
- array( $ids[0], $ids[1] ),
+ [ $ids[0], $ids[1] ],
$repo[0]->findRootPath( $ids[1] )
);
$this->assertEquals(
- array( $ids[0], $ids[1] ),
+ [ $ids[0], $ids[1] ],
$repo[1]->findRootPath( $ids[1] )
);
@@ -60,11 +58,11 @@ class TreeRepositorydbTest extends FlowTestCase {
wfDebugLog( 'Flow', "\n\n************** id2 as child of id0 ************" );
$repo[0]->insert( $ids[2], $ids[0] );
$this->assertEquals(
- array( $ids[0], $ids[2] ),
+ [ $ids[0], $ids[2] ],
$repo[0]->findRootPath( $ids[2] )
);
$this->assertEquals(
- array( $ids[0], $ids[2] ),
+ [ $ids[0], $ids[2] ],
$repo[1]->findRootPath( $ids[2] )
);
@@ -72,11 +70,11 @@ class TreeRepositorydbTest extends FlowTestCase {
wfDebugLog( 'Flow', "\n\n************** id3 as child of id1 ************" );
$repo[0]->insert( $ids[3], $ids[1] );
$this->assertEquals(
- array( $ids[0], $ids[1], $ids[3] ),
+ [ $ids[0], $ids[1], $ids[3] ],
$repo[0]->findRootPath( $ids[3] )
);
$this->assertEquals(
- array( $ids[0], $ids[1], $ids[3] ),
+ [ $ids[0], $ids[1], $ids[3] ],
$repo[1]->findRootPath( $ids[3] )
);
}
diff --git a/Flow/tests/phpunit/Repository/TreeRepositoryTest.php b/Flow/tests/phpunit/Repository/TreeRepositoryTest.php
index 6c25d014..cfe9d723 100644
--- a/Flow/tests/phpunit/Repository/TreeRepositoryTest.php
+++ b/Flow/tests/phpunit/Repository/TreeRepositoryTest.php
@@ -2,12 +2,9 @@
namespace Flow\Tests\Repository;
-use Flow\Data\BagOStuff\BufferedBagOStuff;
-use Flow\Data\BufferedCache;
use Flow\Model\UUID;
use Flow\Repository\TreeRepository;
use Flow\Tests\FlowTestCase;
-use ReflectionClass;
/**
* @group Flow
@@ -17,48 +14,24 @@ class TreeRepositoryTest extends FlowTestCase {
protected $ancestor;
protected $descendant;
- public function setUp() {
+ protected function setUp() {
parent::setUp();
$this->ancestor = UUID::create( false );
$this->descendant = UUID::create( false );
}
public function testSuccessfulInsert() {
- global $wgFlowCacheTime;
- $cache = new BufferedCache( new BufferedBagOStuff( new \HashBagOStuff() ), $wgFlowCacheTime );
+ $cache = $this->getCache();
$treeRepository = new TreeRepository( $this->mockDbFactory( true ), $cache );
$this->assertTrue( $treeRepository->insert( $this->descendant, $this->ancestor ) );
-
- $reflection = new ReflectionClass( '\Flow\Repository\TreeRepository' );
- $method = $reflection->getMethod( 'cacheKey' );
- $method->setAccessible( true );
-
- $this->assertNotSame( $cache->get( $method->invoke( $treeRepository, 'subtree', $this->descendant ) ), false );
- $this->assertNotSame( $cache->get( $method->invoke( $treeRepository, 'rootpath', $this->descendant ) ), false );
- $this->assertNotSame( $cache->get( $method->invoke( $treeRepository, 'parent', $this->descendant ) ), false );
}
/**
* @expectedException \Flow\Exception\DataModelException
*/
public function testFailingInsert() {
- global $wgFlowCacheTime;
- // Catch the exception and test the cache result then re-throw the exception,
- // otherwise the exception would skip the cache result test
- $cache = new BufferedCache( new BufferedBagOStuff( new \HashBagOStuff() ), $wgFlowCacheTime );
- try {
- $treeRepository = new TreeRepository( $this->mockDbFactory( false ), $cache );
- $this->assertNull( $treeRepository->insert( $this->descendant, $this->ancestor ) );
- } catch ( \Exception $e ) {
- $reflection = new ReflectionClass( '\Flow\Repository\TreeRepository' );
- $method = $reflection->getMethod( 'cacheKey' );
- $method->setAccessible( true );
-
- $this->assertSame( $cache->get( $method->invoke( $treeRepository, 'rootpath', $this->descendant ) ), false );
- $this->assertSame( $cache->get( $method->invoke( $treeRepository, 'parent', $this->descendant ) ), false );
-
- throw $e;
- }
+ $treeRepository = new TreeRepository( $this->mockDbFactory( false ), $this->getCache() );
+ $treeRepository->insert( $this->descendant, $this->ancestor );
}
protected function mockDbFactory( $dbResult ) {
@@ -67,7 +40,7 @@ class TreeRepositoryTest extends FlowTestCase {
->getMock();
$dbFactory->expects( $this->any() )
->method( 'getDB' )
- ->will( $this->returnValue( $this->mockDb( $dbResult) ) );
+ ->will( $this->returnValue( $this->mockDb( $dbResult ) ) );
return $dbFactory;
}
diff --git a/Flow/tests/phpunit/SpamFilter/AbuseFilterTest.php b/Flow/tests/phpunit/SpamFilter/AbuseFilterTest.php
index c6a6a9e6..0c3fb7a5 100644
--- a/Flow/tests/phpunit/SpamFilter/AbuseFilterTest.php
+++ b/Flow/tests/phpunit/SpamFilter/AbuseFilterTest.php
@@ -13,6 +13,9 @@ use User;
* @group Flow
*/
class AbuseFilterTest extends PostRevisionTestCase {
+ const BAD_TOPIC_TITLE_TEXT = 'Topic:Tnprd6ksfu1v1nme';
+ const BAD_OWNER_TITLE_TEXT = 'BadBoard';
+
/**
* @var AbuseFilter
*/
@@ -21,38 +24,73 @@ class AbuseFilterTest extends PostRevisionTestCase {
/**
* @var array
*/
- protected $tablesUsed = array( 'abuse_filter', 'abuse_filter_action', 'abuse_filter_history', 'abuse_filter_log' );
+ protected $tablesUsed = [ 'abuse_filter', 'abuse_filter_action', 'abuse_filter_history', 'abuse_filter_log' ];
- protected $filters = array(
+ protected $filters = [
// no CSS screen hijack
'(new_wikitext rlike "position\s*:\s*(fixed|absolute)|style\s*=\s*\"[a-z0-9:;\s]*&|z-index\s*:\s*\d|\|([4-9]\d{3}|\d{5,})px")' => 'disallow',
- );
+ '(ARTICLE_PREFIXEDTEXT === "Topic:Tnprd6ksfu1v1nme")' => 'disallow',
+ '(BOARD_PREFIXEDTEXT === "BadBoard")' => 'disallow',
+ ];
public function spamProvider() {
- return array(
- array(
- // default new topic title revision - no spam
+ $goodTopicTitle = Title::newFromText( 'Topic:Tnpn1618hctgeguu' );
+ $goodOwnerTitle = Title::newFromText( 'UTPage' );
+
+ $badTopicTitle = Title::newFromText( self::BAD_TOPIC_TITLE_TEXT );
+ $badOwnerTitle = Title::newFromText( self::BAD_OWNER_TITLE_TEXT );
+
+ // This is a simplified test, just to cover the variables.
+ // For a new topic, they are actually both the board title.
+ return [
+ [
+ $goodTopicTitle,
+ $goodOwnerTitle,
+ // default new topic title revision, both good titles - no spam
$this->generateObject(),
null,
- true
- ),
- array(
+ true,
+ ],
+ [
+ $goodTopicTitle,
+ $goodOwnerTitle,
// revision with spam
// https://www.mediawiki.org/w/index.php?title=Talk:Sandbox&workflow=050bbdd07b64a1c028b2782bcb087b42#flow-post-050bbdd07b70a1c028b2782bcb087b42
- $this->generateObject( array( 'rev_content' => '<div style="background: yellow; position: fixed; top: 0; left: 0; width: 3000px; height: 3000px; z-index: 1111;">test</div>', 'rev_flags' => 'html' ) ),
+ $this->generateObject( [ 'rev_content' => '<div style="background: yellow; position: fixed; top: 0; left: 0; width: 3000px; height: 3000px; z-index: 1111;">test</div>', 'rev_flags' => 'html' ] ),
null,
- false
- ),
- );
+ false,
+ ],
+ [
+ $badTopicTitle,
+ $goodOwnerTitle,
+ $this->generateObject(),
+ // Topic title matches
+ null,
+ false,
+ ],
+ [
+ $goodTopicTitle,
+ $badOwnerTitle,
+ $this->generateObject(),
+ // Owner title matches
+ null,
+ false,
+ ],
+ ];
}
/**
* @dataProvider spamProvider
*/
- public function testSpam( PostRevision $newRevision, PostRevision $oldRevision = null, $expected ) {
- $title = Title::newFromText( 'UTPage' );
-
- $status = $this->spamFilter->validate( $this->getMock( 'IContextSource' ), $newRevision, $oldRevision, $title );
+ public function testSpam( $title, $ownerTitle, PostRevision $newRevision, PostRevision $oldRevision = null, $expected ) {
+ $context = $this->getMockBuilder( 'ContextSource' )
+ ->setMethods( [ 'getUser' ] )
+ ->getMock();
+ $context->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( User::newFromName( 'UTSysop' ) ) );
+
+ $status = $this->spamFilter->validate( $context, $newRevision, $oldRevision, $title, $ownerTitle );
$this->assertEquals( $expected, $status->isOK() );
}
@@ -70,17 +108,18 @@ class AbuseFilterTest extends PostRevisionTestCase {
\RequestContext::getMain()->setTitle( Title::newMainPage() );
$user = User::newFromName( 'UTSysop' );
+ \RequestContext::getMain()->setUser( $user );
- $this->spamFilter = new AbuseFilter( $user, $wgFlowAbuseFilterGroup );
+ $this->spamFilter = new AbuseFilter( $wgFlowAbuseFilterGroup );
if ( !$this->spamFilter->enabled() ) {
$this->markTestSkipped( 'AbuseFilter not enabled' );
}
- $this->spamFilter->setup( array(
+ $this->spamFilter->setup( [
'threshold' => $wgFlowAbuseFilterEmergencyDisableThreshold,
'count' => $wgFlowAbuseFilterEmergencyDisableCount,
'age' => $wgFlowAbuseFilterEmergencyDisableAge,
- ) );
+ ] );
foreach ( $this->filters as $pattern => $action ) {
$this->createFilter( $pattern, $action );
@@ -106,9 +145,9 @@ class AbuseFilterTest extends PostRevisionTestCase {
$this->db->replace(
'abuse_filter',
- array( 'af_id' ),
- array(
-// 'af_id',
+ [ 'af_id' ],
+ [
+ // 'af_id',
'af_pattern' => $pattern,
'af_user' => $user->getId(),
'af_user_text' => $user->getName(),
@@ -122,18 +161,18 @@ class AbuseFilterTest extends PostRevisionTestCase {
'af_deleted' => 0,
'af_actions' => $action,
'af_group' => $wgFlowAbuseFilterGroup,
- ),
+ ],
__METHOD__
);
$this->db->replace(
'abuse_filter_action',
- array( 'afa_filter' ),
- array(
+ [ 'afa_filter' ],
+ [
'afa_filter' => $this->db->insertId(),
'afa_consequence' => $action,
'afa_parameters' => '',
- ),
+ ],
__METHOD__
);
}
diff --git a/Flow/tests/phpunit/SpamFilter/ConfirmEditTest.php b/Flow/tests/phpunit/SpamFilter/ConfirmEditTest.php
index c66eea09..f90f33fa 100644
--- a/Flow/tests/phpunit/SpamFilter/ConfirmEditTest.php
+++ b/Flow/tests/phpunit/SpamFilter/ConfirmEditTest.php
@@ -2,7 +2,6 @@
namespace Flow\Tests\SpamFilter;
-
use Flow\Model\PostRevision;
use Flow\Model\Workflow;
use Flow\SpamFilter\ConfirmEdit;
@@ -18,11 +17,12 @@ class ConfirmEditTest extends \MediaWikiTestCase {
}
$user = User::newFromName( '127.0.0.1', false );
- $title = Title::newMainPage();
+ $title = Title::newFromText( 'Topic:Tnprd6ksfu1v1nme' );
+ $ownerTitle = Title::newMainPage();
$workflow = Workflow::create( 'topic', $title );
- $oldRevision = PostRevision::create( $workflow, $user, 'foo', 'wikitext' );
- $newRevision = $oldRevision->newNextRevision( $user, 'bar', 'wikitext', 'change-type', $title );
+ $oldRevision = PostRevision::createTopicPost( $workflow, $user, 'foo' );
+ $newRevision = $oldRevision->newNextRevision( $user, 'bar', 'topic-title-wikitext', 'edit-title', $title );
$request = $this->getMock( 'WebRequest' );
$request->expects( $this->any() )
@@ -39,7 +39,7 @@ class ConfirmEditTest extends \MediaWikiTestCase {
->method( 'getRequest' )
->will( $this->returnValue( $request ) );
- $status = $filter->validate( $context, $newRevision, $oldRevision, $title );
+ $status = $filter->validate( $context, $newRevision, $oldRevision, $title, $ownerTitle );
$this->assertInstanceOf( 'Status', $status );
$this->assertTrue( $status->isGood() );
}
diff --git a/Flow/tests/phpunit/SpamFilter/ContentLengthFilterTest.php b/Flow/tests/phpunit/SpamFilter/ContentLengthFilterTest.php
index bfa548cc..e8579736 100644
--- a/Flow/tests/phpunit/SpamFilter/ContentLengthFilterTest.php
+++ b/Flow/tests/phpunit/SpamFilter/ContentLengthFilterTest.php
@@ -18,8 +18,8 @@ class ContentLengthFilterTest extends \MediaWikiTestCase {
protected $spamFilter;
public function spamProvider() {
- return array(
- array(
+ return [
+ [
'With content shorter than max length allow through filter',
// expect
true,
@@ -27,9 +27,9 @@ class ContentLengthFilterTest extends \MediaWikiTestCase {
'blah',
// max length
100
- ),
+ ],
- array(
+ [
'With content longer than max length dissalow through filter',
// expect
false,
@@ -37,22 +37,23 @@ class ContentLengthFilterTest extends \MediaWikiTestCase {
'blah',
// max length
2
- ),
- );
+ ],
+ ];
}
/**
* @dataProvider spamProvider
*/
public function testSpam( $message, $expect, $content, $maxLength ) {
- $title = Title::newFromText( 'UTPage' );
+ $ownerTitle = Title::newFromText( 'UTPage' );
+ $title = Title::newFromText( 'Topic:Tnprd6ksfu1v1nme' );
$user = User::newFromName( '127.0.0.1', false );
$workflow = Workflow::create( 'topic', $title );
- $topic = PostRevision::create( $workflow, $user, 'title content', 'wikitext' );
+ $topic = PostRevision::createTopicPost( $workflow, $user, 'title content' );
$reply = $topic->reply( $workflow, $user, $content, 'wikitext' );
$spamFilter = new ContentLengthFilter( $maxLength );
- $status = $spamFilter->validate( $this->getMock( 'IContextSource' ), $reply, null, $title );
+ $status = $spamFilter->validate( $this->getMock( 'IContextSource' ), $reply, null, $title, $ownerTitle );
$this->assertEquals( $expect, $status->isOK() );
}
}
diff --git a/Flow/tests/phpunit/SpamFilter/SpamBlacklistTest.php b/Flow/tests/phpunit/SpamFilter/SpamBlacklistTest.php
index 599efaa7..3cbb37f1 100644
--- a/Flow/tests/phpunit/SpamFilter/SpamBlacklistTest.php
+++ b/Flow/tests/phpunit/SpamFilter/SpamBlacklistTest.php
@@ -18,39 +18,42 @@ class SpamBlacklistTest extends PostRevisionTestCase {
protected $spamFilter;
/**
- * Spam blacklist & whitelist regexes. Examples taken from:
+ * Spam blacklist regexes. Examples taken from:
*
* @see http://meta.wikimedia.org/wiki/Spam_blacklist
* @see http://en.wikipedia.org/wiki/MediaWiki:Spam-blacklist
+ *
+ * @var array
+ */
+ protected $blacklist = [ '\b01bags\.com\b', 'sytes\.net' ];
+
+ /**
+ * Spam whitelist regexes. Examples taken from:
+ *
* @see http://en.wikipedia.org/wiki/MediaWiki:Spam-whitelist
*
* @var array
*/
- protected
- $blacklist = array( '\b01bags\.com\b', 'sytes\.net' ),
- $whitelist = array( 'a5b\.sytes\.net' );
+ protected $whitelist = [ 'a5b\.sytes\.net' ];
public function spamProvider() {
- return array(
- array(
- // default new topic title revision - no spam
+ return [
+ 'default new topic title revision - no spam' => [
$this->generateObject(),
null,
true
- ),
- array(
- // revision with spam
- $this->generateObject( array( 'rev_content' => 'http://01bags.com', 'rev_flags' => 'html' ) ),
+ ],
+ 'revision with spam' => [
+ $this->generateObject( [ 'rev_content' => 'http://01bags.com', 'rev_flags' => 'html' ] ),
null,
false
- ),
- array(
- // revision with domain blacklisted as spam, but subdomain whitelisted
- $this->generateObject( array( 'rev_content' => 'http://a5b.sytes.net', 'rev_flags' => 'html' ) ),
+ ],
+ 'revision with domain blacklisted as spam, but subdomain whitelisted' => [
+ $this->generateObject( [ 'rev_content' => 'http://a5b.sytes.net', 'rev_flags' => 'html' ] ),
null,
true
- ),
- );
+ ],
+ ];
}
/**
@@ -59,7 +62,7 @@ class SpamBlacklistTest extends PostRevisionTestCase {
public function testSpam( PostRevision $newRevision, PostRevision $oldRevision = null, $expected ) {
$title = Title::newFromText( 'UTPage' );
- $status = $this->spamFilter->validate( $this->getMock( 'IContextSource' ), $newRevision, $oldRevision, $title );
+ $status = $this->spamFilter->validate( $this->getMock( 'IContextSource' ), $newRevision, $oldRevision, $title, $title );
$this->assertEquals( $expected, $status->isOK() );
}
@@ -72,9 +75,9 @@ class SpamBlacklistTest extends PostRevisionTestCase {
$this->markTestSkipped( 'SpamBlacklist not enabled' );
}
- $this->setMwGlobals( 'wgBlacklistSettings', array(
- 'files' => array(),
- ) );
+ $this->setMwGlobals( 'wgBlacklistSettings', [
+ 'files' => [],
+ ] );
\MessageCache::singleton()->enable();
$this->insertPage( 'MediaWiki:Spam-blacklist', implode( "\n", $this->blacklist ) );
diff --git a/Flow/tests/phpunit/SpamFilter/SpamRegexTest.php b/Flow/tests/phpunit/SpamFilter/SpamRegexTest.php
index 4537b08a..49cc844f 100644
--- a/Flow/tests/phpunit/SpamFilter/SpamRegexTest.php
+++ b/Flow/tests/phpunit/SpamFilter/SpamRegexTest.php
@@ -17,20 +17,20 @@ class SpamRegexTest extends PostRevisionTestCase {
protected $spamFilter;
public function spamProvider() {
- return array(
- array(
+ return [
+ [
// default new topic title revision - no spam
$this->generateObject(),
null,
true
- ),
- array(
+ ],
+ [
// revision with spam
- $this->generateObject( array( 'rev_content' => 'http://spam', 'rev_flags' => 'html' ) ),
+ $this->generateObject( [ 'rev_content' => 'http://spam', 'rev_flags' => 'html' ] ),
null,
false
- ),
- );
+ ],
+ ];
}
/**
@@ -39,7 +39,7 @@ class SpamRegexTest extends PostRevisionTestCase {
public function testSpam( PostRevision $newRevision, PostRevision $oldRevision = null, $expected ) {
$title = Title::newFromText( 'UTPage' );
- $status = $this->spamFilter->validate( $this->getMock( 'IContextSource' ), $newRevision, $oldRevision, $title );
+ $status = $this->spamFilter->validate( $this->getMock( 'IContextSource' ), $newRevision, $oldRevision, $title, $title );
$this->assertEquals( $expected, $status->isOK() );
}
@@ -47,7 +47,7 @@ class SpamRegexTest extends PostRevisionTestCase {
parent::setUp();
// create a dummy filter
- $this->setMwGlobals( 'wgSpamRegex', array( '/http:\/\/spam/' ) );
+ $this->setMwGlobals( 'wgSpamRegex', [ '/http:\/\/spam/' ] );
// create spam filter
$this->spamFilter = new SpamRegex;
diff --git a/Flow/tests/phpunit/TalkpageManagerTest.php b/Flow/tests/phpunit/TalkpageManagerTest.php
new file mode 100644
index 00000000..ea208b85
--- /dev/null
+++ b/Flow/tests/phpunit/TalkpageManagerTest.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace Flow\Tests;
+
+use Title;
+use User;
+use WikiPage;
+use WikitextContent;
+
+use Flow\Container;
+
+/**
+ * @group Flow
+ * @group Database
+ */
+class TalkpageManagerTest extends \MediaWikiTestCase {
+ /**
+ * @var TalkpageManager
+ */
+ protected $talkpageManager;
+
+ public function __construct() {
+ parent::__construct();
+ $this->talkpageManager = Container::get( 'occupation_controller' );
+
+ $this->tablesUsed = array_merge( $this->tablesUsed, [
+ 'page',
+ 'revision',
+ 'ip_changes',
+ ] );
+ }
+
+ public function testCheckIfCreationIsPossible() {
+ $this->setMwGlobals( 'wgContentHandlerUseDB', false );
+
+ $useDbFalseStatus = $this->talkpageManager->checkIfCreationIsPossible( Title::newFromText( 'Earth' ), true );
+ $this->assertTrue( $useDbFalseStatus->hasMessage( 'flow-error-allowcreation-no-usedb' ), 'Error for wrong $wgContentHandlerUseDB setting' );
+ $this->assertFalse( $useDbFalseStatus->isOK(), 'Error for wrong $wgContentHandlerUseDB setting' );
+
+ $this->setMwGlobals( 'wgContentHandlerUseDB', true );
+
+ $existentTitle = Title::newFromText( 'Exists' );
+ $status = WikiPage::factory( $existentTitle )
+ ->doEditContent(
+ new WikitextContent( 'This exists' ),
+ "with an edit summary"
+ );
+ if ( !$status->isGood() ) {
+ $this->fail( $status->getMessage()->plain() );
+ }
+
+ $existTrueStatus = $this->talkpageManager->checkIfCreationIsPossible( $existentTitle, /*mustNotExist*/ true );
+ $this->assertTrue( $existTrueStatus->hasMessage( 'flow-error-allowcreation-already-exists' ), 'Error when page already exists and mustNotExist true was passed' );
+ $this->assertFalse( $existTrueStatus->isOK(), 'Error when page already exists and mustNotExist true was passed' );
+
+ $existFalseStatus = $this->talkpageManager->checkIfCreationIsPossible( $existentTitle, /*mustNotExist*/ false );
+ $this->assertFalse( $existFalseStatus->hasMessage( 'flow-error-allowcreation-already-exists' ), 'No error when page already exists and mustNotExist false was passed' );
+ $this->assertTrue( $existFalseStatus->isOK(), 'No error when page already exists and mustNotExist false was passed' );
+ }
+
+ public function testCheckIfUserHasPermission() {
+ global $wgNamespaceContentModels;
+
+ $tempModels = $beforeModels = $wgNamespaceContentModels;
+ $tempModels[NS_USER_TALK] = CONTENT_MODEL_FLOW_BOARD;
+
+ $unconfirmedUser = User::newFromName( 'UTFlowUnconfirmed' );
+
+ $this->setMwGlobals( 'wgNamespaceContentModels', $tempModels );
+
+ $permissionStatus = $this->talkpageManager->checkIfUserHasPermission( Title::newFromText( 'User talk:Test123' ), $unconfirmedUser );
+ $this->assertTrue( $permissionStatus->isOK(), 'No error if user checks permissions for enabling Flow board in default-Flow namespace' );
+
+ $permissionStatus = $this->talkpageManager->checkIfUserHasPermission( Title::newFromText( 'User:Test123' ), $unconfirmedUser );
+ $this->assertFalse( $permissionStatus->isOK(), 'Error if user without flow-create-board enabling Flow board in default-Flow namespace' );
+ $this->assertTrue( $permissionStatus->hasMessage( 'flow-error-allowcreation-flow-create-board' ), 'Error if user without flow-create-board enabling Flow board in default-Flow namespace' );
+
+ $adminUser = $this->getMockBuilder( 'User' )
+ ->setMethods( [ 'isAllowed' ] )
+ ->getMock();
+
+ // Set up the expectation for the update() method
+ // to be called only once and with the string 'something'
+ // as its parameter.
+ $adminUser->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( 'flow-create-board' ) )
+ ->will( $this->returnValue( true ) );
+
+ $permissionStatus = $this->talkpageManager->checkIfUserHasPermission( Title::newFromText( 'User:Test123' ), $adminUser );
+ $this->assertTrue( $permissionStatus->isOK(), 'No if user without flow-create-board enabling Flow board in default-Flow namespace' );
+ }
+}
diff --git a/Flow/tests/phpunit/TemplateHelperTest.php b/Flow/tests/phpunit/TemplateHelperTest.php
index 4e6adfe6..78ef4417 100644
--- a/Flow/tests/phpunit/TemplateHelperTest.php
+++ b/Flow/tests/phpunit/TemplateHelperTest.php
@@ -11,16 +11,21 @@ use Flow\TemplateHelper;
class TemplateHelperTest extends \MediaWikiTestCase {
public function provideTraversalAttackFilenames() {
- return array_map( function( $x ) { return array( $x ); }, array(
- '.',
- '..',
- './foo',
- '../foo',
- 'foo/./bar',
- 'foo/../bar',
- 'foo/bar/.',
- 'foo/bar/..',
- ) );
+ return array_map(
+ function ( $x ) {
+ return [ $x ];
+ },
+ [
+ '.',
+ '..',
+ './foo',
+ '../foo',
+ 'foo/./bar',
+ 'foo/../bar',
+ 'foo/bar/.',
+ 'foo/bar/..',
+ ]
+ );
}
/**
@@ -36,8 +41,8 @@ class TemplateHelperTest extends \MediaWikiTestCase {
$code = TemplateHelper::compile( "{{#ifCond foo \"or\" bar}}Works{{/ifCond}}", '' );
$renderer = Lightncandy::prepare( $code );
- $this->assertEquals( 'Works', $renderer( array( 'foo' => true, 'bar' => false ) ) );
- $this->assertEquals( '', $renderer( array( 'foo' => false, 'bar' => false ) ) );
+ $this->assertEquals( 'Works', $renderer( [ 'foo' => true, 'bar' => false ] ) );
+ $this->assertEquals( '', $renderer( [ 'foo' => false, 'bar' => false ] ) );
/*
FIXME: Why won't this work!?
$code2 = TemplateHelper::compile( "{{#ifCond foo \"===\" bar}}Works{{/ifCond}}", '' );
diff --git a/Flow/tests/phpunit/TemplatingTest.php b/Flow/tests/phpunit/TemplatingTest.php
index 31167ea7..81edbfed 100644
--- a/Flow/tests/phpunit/TemplatingTest.php
+++ b/Flow/tests/phpunit/TemplatingTest.php
@@ -43,7 +43,7 @@ class TemplatingTest extends \MediaWikiTestCase {
$user = User::newFromName( '127.0.0.1', false );
$title = Title::newMainPage();
$workflow = Workflow::create( 'topic', $title );
- $topicTitle = PostRevision::create( $workflow, $user, 'some content', 'wikitext' );
+ $topicTitle = PostRevision::createTopicPost( $workflow, $user, 'some content' );
$hidden = $topicTitle->moderate(
$user,
diff --git a/Flow/tests/phpunit/UrlGeneratorTest.php b/Flow/tests/phpunit/UrlGeneratorTest.php
index 23ac087e..d726831b 100644
--- a/Flow/tests/phpunit/UrlGeneratorTest.php
+++ b/Flow/tests/phpunit/UrlGeneratorTest.php
@@ -19,28 +19,28 @@ class UrlGeneratorTest extends FlowTestCase {
}
public function provideDataBoardLink() {
- return array (
- array(
+ return [
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
'updated',
true
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
'updated',
false
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
'created',
true
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
'created',
false
- )
- );
+ ]
+ ];
}
/**
@@ -64,24 +64,24 @@ class UrlGeneratorTest extends FlowTestCase {
}
public function provideDataWatchTopicLink() {
- return array (
- array(
+ return [
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
UUID::create()
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
UUID::create()
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
UUID::create()
- ),
- array(
+ ],
+ [
Title::makeTitle( NS_MAIN, 'Test' ),
UUID::create()
- )
- );
+ ]
+ ];
}
/**
diff --git a/Flow/tests/phpunit/WatchedTopicItemsTest.php b/Flow/tests/phpunit/WatchedTopicItemsTest.php
index f6b5a62e..22a42ed6 100644
--- a/Flow/tests/phpunit/WatchedTopicItemsTest.php
+++ b/Flow/tests/phpunit/WatchedTopicItemsTest.php
@@ -14,19 +14,19 @@ class WatchedTopicItemTest extends FlowTestCase {
public function provideDataGetWatchStatus() {
// number of test cases
$testCount = 10;
- $tests = array();
+ $tests = [];
while ( $testCount > 0 ) {
$testCount--;
// number of uuid per test case
$uuidCount = 10;
- $uuids = $dbResult = $result = array();
- while( $uuidCount > 0 ) {
+ $uuids = $dbResult = $result = [];
+ while ( $uuidCount > 0 ) {
$uuidCount--;
$uuid = UUID::create()->getAlphadecimal();
$rand = rand( 0, 1 );
// put in the query result
if ( $rand ) {
- $dbResult[] = ( object )array( 'wl_title' => $uuid );
+ $dbResult[] = (object)[ 'wl_title' => $uuid ];
$result[$uuid] = true;
} else {
$result[$uuid] = false;
@@ -34,25 +34,24 @@ class WatchedTopicItemTest extends FlowTestCase {
$uuids[] = $uuid;
}
$dbResult = new \ArrayObject( $dbResult );
- $tests[] = array( $uuids, $dbResult->getIterator(), $result );
+ $tests[] = [ $uuids, $dbResult->getIterator(), $result ];
}
// attach empty uuids array to query
- $uuids = $dbResult = $result = array();
+ $uuids = $dbResult = $result = [];
$emptyCount = 10;
while ( $emptyCount > 0 ) {
$emptyCount--;
$uuid = UUID::create()->getAlphadecimal();
- $dbResult[] = ( object )array( 'wl_title' => $uuid );
+ $dbResult[] = (object)[ 'wl_title' => $uuid ];
}
$dbResult = new \ArrayObject( $dbResult );
- $tests[] = array( $uuids, $dbResult->getIterator(), $result );
+ $tests[] = [ $uuids, $dbResult->getIterator(), $result ];
return $tests;
}
/**
* @dataProvider provideDataGetWatchStatus
- *
*/
public function testGetWatchStatus( $uuids, $dbResult, $result ) {
// give it a fake user id
diff --git a/Flow/tests/phpunit/api/ApiFlowEditHeaderTest.php b/Flow/tests/phpunit/api/ApiFlowEditHeaderTest.php
index 9e5cf66d..da1a6766 100644
--- a/Flow/tests/phpunit/api/ApiFlowEditHeaderTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowEditHeaderTest.php
@@ -2,17 +2,35 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
+use Sanitizer;
/**
* @group Flow
* @group medium
*/
class ApiFlowEditHeaderTest extends ApiTestCase {
+
+ public function testCache() {
+ $this->expectCacheInvalidate();
+
+ $data = $this->doApiRequest( [
+ 'page' => 'Talk:Flow_QA',
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'edit-header',
+ 'ehprev_revision' => '',
+ 'ehcontent' => '(._.)',
+ 'ehformat' => 'wikitext',
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['edit-header']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['edit-header']['committed'], $debug );
+ }
+
public function testEditHeader() {
- $data = $this->doApiRequest( array(
+ // create header
+ $data = $this->doApiRequest( [
'page' => 'Talk:Flow_QA',
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -20,30 +38,59 @@ class ApiFlowEditHeaderTest extends ApiTestCase {
'ehprev_revision' => '',
'ehcontent' => '(._.)',
'ehformat' => 'wikitext',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['edit-header']['status'], $debug );
$this->assertCount( 1, $data[0]['flow']['edit-header']['committed'], $debug );
- $data = $this->doApiRequest( array(
+ // get header
+ $data = $this->doApiRequest( [
'page' => 'Talk:Flow_QA',
'action' => 'flow',
'submodule' => 'view-header',
'vhformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$result = $data[0]['flow']['view-header']['result']['header'];
$this->assertArrayHasKey( 'revision', $result, $debug );
$revision = $result['revision'];
+ $revisionId = $revision['revisionId'];
$this->assertArrayHasKey( 'changeType', $revision, $debug );
$this->assertEquals( 'create-header', $revision['changeType'], $debug );
$this->assertEquals(
'(._.)',
- trim( strip_tags( $revision['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $revision['content']['content'] ) ),
$debug
);
$this->assertEquals( 'html', $revision['content']['format'], $debug );
+
+ // update header (null edit)
+ $data = $this->doApiRequest( [
+ 'page' => 'Talk:Flow_QA',
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'edit-header',
+ 'ehprev_revision' => $revisionId,
+ 'ehcontent' => '(._.)',
+ 'ehformat' => 'wikitext',
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['edit-header']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['edit-header']['committed'], $debug );
+
+ // get header again
+ $data = $this->doApiRequest( [
+ 'page' => 'Talk:Flow_QA',
+ 'action' => 'flow',
+ 'submodule' => 'view-header',
+ 'vhformat' => 'html',
+ ] );
+
+ $newRevisionId = $data[0]['flow']['view-header']['result']['header']['revision']['revisionId'];
+
+ $this->assertEquals( $revisionId, $newRevisionId, $debug );
}
}
diff --git a/Flow/tests/phpunit/api/ApiFlowEditPostTest.php b/Flow/tests/phpunit/api/ApiFlowEditPostTest.php
index 311b6d6d..f159254f 100644
--- a/Flow/tests/phpunit/api/ApiFlowEditPostTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowEditPostTest.php
@@ -2,9 +2,7 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
+use Sanitizer;
/**
* @group Flow
@@ -14,7 +12,7 @@ class ApiFlowEditPostTest extends ApiTestCase {
public function testEditPost() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -23,7 +21,7 @@ class ApiFlowEditPostTest extends ApiTestCase {
'epprev_revision' => $topic['post-revision-id'],
'epcontent' => '⎛ ゚∩゚⎞⎛ ⍜⌒⍜⎞⎛ ゚⌒゚⎞',
'epformat' => 'wikitext',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['edit-post']['status'], $debug );
@@ -32,13 +30,13 @@ class ApiFlowEditPostTest extends ApiTestCase {
$replyPostId = $data[0]['flow']['edit-post']['committed']['topic']['post-id'];
$replyRevisionId = $data[0]['flow']['edit-post']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-post',
'vppostId' => $replyPostId,
'vpformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-post']['result']['topic']['revisions'][$replyRevisionId];
@@ -46,7 +44,7 @@ class ApiFlowEditPostTest extends ApiTestCase {
$this->assertEquals( 'edit-post', $revision['changeType'], $debug );
$this->assertEquals(
'⎛ ゚∩゚⎞⎛ ⍜⌒⍜⎞⎛ ゚⌒゚⎞',
- trim( strip_tags( $revision['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $revision['content']['content'] ) ),
$debug
);
$this->assertEquals( 'html', $revision['content']['format'], $debug );
diff --git a/Flow/tests/phpunit/api/ApiFlowEditTitleTest.php b/Flow/tests/phpunit/api/ApiFlowEditTitleTest.php
index 56c4cec1..b03072de 100644
--- a/Flow/tests/phpunit/api/ApiFlowEditTitleTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowEditTitleTest.php
@@ -2,10 +2,6 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
-
/**
* @group Flow
* @group medium
@@ -14,14 +10,14 @@ class ApiFlowEditTitleTest extends ApiTestCase {
public function testEditTitle() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
'submodule' => 'edit-title',
'etprev_revision' => $topic['topic-revision-id'],
'etcontent' => '(ノ◕ヮ◕)ノ*:・ ゚ ゚ ゚ ゚ ゚ ゚ ゚ ゚✧'
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['edit-title']['status'], $debug );
@@ -29,18 +25,18 @@ class ApiFlowEditTitleTest extends ApiTestCase {
$revisionId = $data[0]['flow']['edit-title']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
- 'vpformat' => 'html',
- ) );
+ 'vtformat' => 'wikitext',
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-topic']['result']['topic']['revisions'][$revisionId];
$this->assertArrayHasKey( 'changeType', $revision, $debug );
$this->assertEquals( 'edit-title', $revision['changeType'], $debug );
$this->assertEquals( '(ノ◕ヮ◕)ノ*:・ ゚ ゚ ゚ ゚ ゚ ゚ ゚ ゚✧', $revision['content']['content'], $debug );
- $this->assertEquals( 'plaintext', $revision['content']['format'], $debug );
+ $this->assertEquals( 'topic-title-wikitext', $revision['content']['format'], $debug );
}
}
diff --git a/Flow/tests/phpunit/api/ApiFlowEditTopicSummaryTest.php b/Flow/tests/phpunit/api/ApiFlowEditTopicSummaryTest.php
index d0ca6cfd..15c99601 100644
--- a/Flow/tests/phpunit/api/ApiFlowEditTopicSummaryTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowEditTopicSummaryTest.php
@@ -2,9 +2,7 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
+use Sanitizer;
/**
* @group Flow
@@ -16,7 +14,7 @@ class ApiFlowEditTopicSummaryTest extends ApiTestCase {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -24,18 +22,18 @@ class ApiFlowEditTopicSummaryTest extends ApiTestCase {
'etsprev_revision' => '',
'etssummary' => $summaryText,
'etsformat' => 'wikitext',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['edit-topic-summary']['status'], $debug );
$this->assertCount( 1, $data[0]['flow']['edit-topic-summary']['committed'], $debug );
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic-summary',
'vtsformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-topic-summary']['result']['topicsummary']['revision'];
@@ -43,16 +41,16 @@ class ApiFlowEditTopicSummaryTest extends ApiTestCase {
$this->assertEquals( 'create-topic-summary', $revision['changeType'], $debug );
$this->assertEquals(
$summaryText,
- trim( strip_tags( $revision['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $revision['content']['content'] ) ),
$debug
);
$this->assertEquals( 'html', $revision['content']['format'], $debug );
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
- ) );
+ ] );
$topicData = $data[0]['flow']['view-topic']['result']['topic'];
$rootPostId = $topicData['roots'][0];
@@ -61,7 +59,7 @@ class ApiFlowEditTopicSummaryTest extends ApiTestCase {
$this->assertEquals(
$summaryText,
- trim( strip_tags( $topicRevision['summary']['revision']['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $topicRevision['summary']['revision']['content']['content'] ) ),
'Summary content present with correct structure in view-topic response'
);
}
diff --git a/Flow/tests/phpunit/api/ApiFlowLockTopicTest.php b/Flow/tests/phpunit/api/ApiFlowLockTopicTest.php
index f7a99187..3a4f3d27 100644
--- a/Flow/tests/phpunit/api/ApiFlowLockTopicTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowLockTopicTest.php
@@ -2,10 +2,6 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
-
/**
* @group Flow
* @group medium
@@ -14,7 +10,7 @@ class ApiFlowLockTopicTest extends ApiTestCase {
public function testLockTopic() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -22,7 +18,7 @@ class ApiFlowLockTopicTest extends ApiTestCase {
'cotmoderationState' => 'lock',
'cotreason' => 'fiddle faddle',
'cotprev_revision' => null,
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['lock-topic']['status'], $debug );
@@ -30,12 +26,12 @@ class ApiFlowLockTopicTest extends ApiTestCase {
$revisionId = $data[0]['flow']['lock-topic']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
'vpformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-topic']['result']['topic']['revisions'][$revisionId];
@@ -55,27 +51,27 @@ class ApiFlowLockTopicTest extends ApiTestCase {
public function testUnlockTopic() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
'submodule' => 'lock-topic',
'cotmoderationState' => 'lock',
'cotreason' => 'fiddle faddle',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['lock-topic']['status'], $debug );
$this->assertCount( 1, $data[0]['flow']['lock-topic']['committed'], $debug );
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
'submodule' => 'lock-topic',
'cotmoderationState' => 'unlock',
'cotreason' => 'Ether',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['lock-topic']['status'], $debug );
@@ -83,12 +79,12 @@ class ApiFlowLockTopicTest extends ApiTestCase {
$revisionId = $data[0]['flow']['lock-topic']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
'vpformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-topic']['result']['topic']['revisions'][$revisionId];
diff --git a/Flow/tests/phpunit/api/ApiFlowModeratePostTest.php b/Flow/tests/phpunit/api/ApiFlowModeratePostTest.php
index b5cab678..2a7f05ac 100644
--- a/Flow/tests/phpunit/api/ApiFlowModeratePostTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowModeratePostTest.php
@@ -2,10 +2,7 @@
namespace Flow\Tests\Api;
-use Flow\Container;
use Flow\Model\AbstractRevision;
-use FlowHooks;
-use User;
/**
* @group Flow
@@ -15,7 +12,7 @@ class ApiFlowModeratePostTest extends ApiTestCase {
public function testModeratePost() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -23,7 +20,7 @@ class ApiFlowModeratePostTest extends ApiTestCase {
'mpmoderationState' => AbstractRevision::MODERATED_HIDDEN,
'mppostId' => $topic['post-id'],
'mpreason' => '<>&{};'
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['moderate-post']['status'], $debug );
@@ -32,13 +29,13 @@ class ApiFlowModeratePostTest extends ApiTestCase {
$postId = $data[0]['flow']['moderate-post']['committed']['topic']['post-id'];
$revisionId = $data[0]['flow']['moderate-post']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-post',
'vppostId' => $postId,
'vpformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-post']['result']['topic']['revisions'][$revisionId];
@@ -56,4 +53,35 @@ class ApiFlowModeratePostTest extends ApiTestCase {
$this->assertArrayHasKey( 'format', $revision['moderateReason'], $debug );
$this->assertEquals( 'plaintext', $revision['moderateReason']['format'], $debug );
}
+
+ public function testModeratePostInLockedTopic() {
+ $topic = $this->createTopic();
+
+ $data = $this->doApiRequest( [
+ 'page' => $topic['topic-page'],
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'lock-topic',
+ 'cotmoderationState' => AbstractRevision::MODERATED_LOCKED,
+ 'cotreason' => '<>&{};'
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['lock-topic']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['lock-topic']['committed'], $debug );
+
+ $data = $this->doApiRequest( [
+ 'page' => $topic['topic-page'],
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'moderate-post',
+ 'mpmoderationState' => AbstractRevision::MODERATED_HIDDEN,
+ 'mppostId' => $topic['post-id'],
+ 'mpreason' => '<>&{};'
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['moderate-post']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['moderate-post']['committed'], $debug );
+ }
}
diff --git a/Flow/tests/phpunit/api/ApiFlowModerateTopicTest.php b/Flow/tests/phpunit/api/ApiFlowModerateTopicTest.php
index f0eaf0fe..35d09d79 100644
--- a/Flow/tests/phpunit/api/ApiFlowModerateTopicTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowModerateTopicTest.php
@@ -2,20 +2,16 @@
namespace Flow\Tests\Api;
-use Flow\Container;
use Flow\Model\AbstractRevision;
-use FlowHooks;
-use User;
/**
* @group Flow
* @group medium
*/
class ApiFlowModerateTopicTest extends ApiTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'flow_ext_ref',
'flow_revision',
- 'flow_subscription',
'flow_topic_list',
'flow_tree_node',
'flow_tree_revision',
@@ -23,21 +19,22 @@ class ApiFlowModerateTopicTest extends ApiTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
'logging',
- );
+ ];
public function testModerateTopic() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
'submodule' => 'moderate-topic',
'mtmoderationState' => AbstractRevision::MODERATED_DELETED,
'mtreason' => '<>&{};'
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['moderate-topic']['status'], $debug );
@@ -45,12 +42,14 @@ class ApiFlowModerateTopicTest extends ApiTestCase {
$revisionId = $data[0]['flow']['moderate-topic']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ // need to reset the container and set the current user here
+ $this->setCurrentUser( self::$users['sysop']->getUser() );
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
- 'vpformat' => 'html',
- ) );
+ 'vtformat' => 'html',
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-topic']['result']['topic']['revisions'][$revisionId];
@@ -69,15 +68,45 @@ class ApiFlowModerateTopicTest extends ApiTestCase {
$this->assertEquals( 'plaintext', $revision['moderateReason']['format'], $debug );
// make sure our moderated topic made it into Special:Log
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'action' => 'query',
'list' => 'logevents',
'rawcontinue' => 1,
- ) );
+ ] );
$debug = json_encode( $data );
$logEntry = $data[0]['query']['logevents'][0];
$logParams = isset( $logEntry['params'] ) ? $logEntry['params'] : $logEntry;
$this->assertArrayHasKey( 'topicId', $logParams, $debug );
$this->assertEquals( $topic['topic-id'], $logParams['topicId'], $debug );
}
+
+ public function testModerateLockedTopic() {
+ $topic = $this->createTopic();
+
+ $data = $this->doApiRequest( [
+ 'page' => $topic['topic-page'],
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'lock-topic',
+ 'cotmoderationState' => AbstractRevision::MODERATED_LOCKED,
+ 'cotreason' => '<>&{};'
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['lock-topic']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['lock-topic']['committed'], $debug );
+
+ $data = $this->doApiRequest( [
+ 'page' => $topic['topic-page'],
+ 'token' => $this->getEditToken(),
+ 'action' => 'flow',
+ 'submodule' => 'moderate-topic',
+ 'mtmoderationState' => AbstractRevision::MODERATED_DELETED,
+ 'mtreason' => '<>&{};'
+ ] );
+
+ $debug = json_encode( $data );
+ $this->assertEquals( 'ok', $data[0]['flow']['moderate-topic']['status'], $debug );
+ $this->assertCount( 1, $data[0]['flow']['moderate-topic']['committed'], $debug );
+ }
}
diff --git a/Flow/tests/phpunit/api/ApiFlowReplyTest.php b/Flow/tests/phpunit/api/ApiFlowReplyTest.php
index 02e27adb..2e1c1539 100644
--- a/Flow/tests/phpunit/api/ApiFlowReplyTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowReplyTest.php
@@ -2,9 +2,7 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
+use Sanitizer;
/**
* @group Flow
@@ -14,7 +12,7 @@ class ApiFlowReplyTest extends ApiTestCase {
public function testTopLevelReply() {
$topic = $this->createTopic();
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -22,7 +20,7 @@ class ApiFlowReplyTest extends ApiTestCase {
'repreplyTo' => $topic['topic-id'],
'repcontent' => '⎛ ゚∩゚⎞⎛ ⍜⌒⍜⎞⎛ ゚⌒゚⎞',
'repformat' => 'wikitext',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['reply']['status'], $debug );
@@ -31,13 +29,13 @@ class ApiFlowReplyTest extends ApiTestCase {
$replyPostId = $data[0]['flow']['reply']['committed']['topic']['post-id'];
$replyRevisionId = $data[0]['flow']['reply']['committed']['topic']['post-revision-id'];
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-post',
'vppostId' => $replyPostId,
'vpformat' => 'html',
- ) );
+ ] );
$debug = json_encode( $data );
$revision = $data[0]['flow']['view-post']['result']['topic']['revisions'][$replyRevisionId];
@@ -45,7 +43,7 @@ class ApiFlowReplyTest extends ApiTestCase {
$this->assertEquals( 'reply', $revision['changeType'], $debug );
$this->assertEquals(
'⎛ ゚∩゚⎞⎛ ⍜⌒⍜⎞⎛ ゚⌒゚⎞',
- trim( strip_tags( $revision['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $revision['content']['content'] ) ),
$debug
);
$this->assertEquals( 'html', $revision['content']['format'], $debug );
diff --git a/Flow/tests/phpunit/api/ApiFlowViewHeaderTest.php b/Flow/tests/phpunit/api/ApiFlowViewHeaderTest.php
index fbfa0d0c..a77ebac0 100644
--- a/Flow/tests/phpunit/api/ApiFlowViewHeaderTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowViewHeaderTest.php
@@ -2,9 +2,7 @@
namespace Flow\Tests\Api;
-use Flow\Container;
-use FlowHooks;
-use User;
+use Sanitizer;
/**
* @group Flow
@@ -12,11 +10,11 @@ use User;
*/
class ApiFlowViewHeaderTest extends ApiTestCase {
public function testViewEmptyHeader() {
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => "Talk:Flow_QA",
'action' => 'flow',
'submodule' => 'view-header',
- ) );
+ ] );
$result = $data[0]['flow']['view-header']['result']['header'];
$debug = json_encode( $result );
@@ -27,12 +25,12 @@ class ApiFlowViewHeaderTest extends ApiTestCase {
$this->assertArrayHasKey( 'revision', $result, $debug );
$revision = $result['revision'];
$this->assertEmpty( $revision['links'], $debug );
- $this->assertEquals( array( 'edit' ), array_keys( $revision['actions'] ), $debug );
+ $this->assertEquals( [ 'edit' ], array_keys( $revision['actions'] ), $debug );
$this->assertArrayNotHasKey( 'content', $revision );
}
public function testViewHeader() {
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => 'Talk:Flow_QA',
'token' => $this->getEditToken(),
'action' => 'flow',
@@ -40,18 +38,18 @@ class ApiFlowViewHeaderTest extends ApiTestCase {
'ehprev_revision' => '',
'ehcontent' => 'swimmingly',
'ehformat' => 'wikitext',
- ) );
+ ] );
$debug = json_encode( $data );
$this->assertEquals( 'ok', $data[0]['flow']['edit-header']['status'], $debug );
$this->assertCount( 1, $data[0]['flow']['edit-header']['committed'], $debug );
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => "Talk:Flow_QA",
'action' => 'flow',
'submodule' => 'view-header',
'vhformat' => 'html',
- ) );
+ ] );
$result = $data[0]['flow']['view-header']['result']['header'];
$debug = json_encode( $result );
$this->assertArrayHasKey( 'errors', $result, $debug );
@@ -64,7 +62,7 @@ class ApiFlowViewHeaderTest extends ApiTestCase {
$this->assertArrayHasKey( 'content', $revision['content'], $debug );
$this->assertEquals(
'swimmingly',
- trim( strip_tags( $revision['content']['content'] ) ),
+ trim( Sanitizer::stripAllTags( $revision['content']['content'] ) ),
$debug
);
$this->assertArrayHasKey( 'format', $revision['content'], $debug );
diff --git a/Flow/tests/phpunit/api/ApiFlowViewTopicListTest.php b/Flow/tests/phpunit/api/ApiFlowViewTopicListTest.php
index d9d6f754..e4fdab5e 100644
--- a/Flow/tests/phpunit/api/ApiFlowViewTopicListTest.php
+++ b/Flow/tests/phpunit/api/ApiFlowViewTopicListTest.php
@@ -13,40 +13,41 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
const TITLE_PREFIX = 'VTL Test ';
public function testTocOnly() {
- $topicData = array();
+ $topicData = [];
for ( $i = 0; $i < 3; $i++ ) {
$title = self::TITLE_PREFIX . $i;
$topic = $this->createTopic( $title );
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => $topic['topic-page'],
'action' => 'flow',
'submodule' => 'view-topic',
- ) );
+ ] );
$topicData[$i]['response'] = $data[0]['flow']['view-topic']['result']['topic'];
$topicData[$i]['page'] = $topic['topic-page'];
$topicData[$i]['id'] = $topic['topic-id'];
$topicData[$i]['revisionId'] = $topic['topic-revision-id'];
$actualRevision = $topicData[$i]['response']['revisions'][$topicData[$i]['revisionId']];
- $topicData[$i]['expectedRevision'] = array(
- 'content' => array(
+ $topicData[$i]['expectedRevision'] = [
+ 'content' => [
'content' => $title,
- 'format' => 'plaintext'
- ),
+ 'format' => 'topic-title-wikitext',
+ 'plaintext' => $title,
+ ],
// This last_updated is used for the 'newest' test, then later changed for 'updated' test.
'last_updated' => $actualRevision['last_updated'],
'isModerated' => false,
- );
+ ];
}
$flowQaTitle = Title::newFromText( 'Talk:Flow_QA' );
- $expectedCommonResponse = array(
- 'flow' => array(
- 'view-topiclist' => array(
- 'result' => array(
- 'topiclist' => array(
- 'submitted' => array(
+ $expectedCommonResponse = [
+ 'flow' => [
+ 'view-topiclist' => [
+ 'result' => [
+ 'topiclist' => [
+ 'submitted' => [
'savesortby' => false,
'offset-dir' => 'fwd',
'offset-id' => null,
@@ -55,39 +56,39 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
'toconly' => true,
'include-offset' => false,
'format' => 'fixed-html',
- ),
- 'errors' => array(),
+ ],
+ 'errors' => [],
'type' => 'topiclist',
- ),
- ),
+ ],
+ ],
'status' => 'ok',
- ),
- ),
- );
+ ],
+ ],
+ ];
- $expectedEmptyPageResponse = array_merge_recursive( array(
- 'flow' => array(
- 'view-topiclist' => array(
- 'result' => array(
- 'topiclist' => array(
- 'submitted' => array(
+ $expectedEmptyPageResponse = array_merge_recursive( [
+ 'flow' => [
+ 'view-topiclist' => [
+ 'result' => [
+ 'topiclist' => [
+ 'submitted' => [
'sortby' => 'newest',
- ),
+ ],
'sortby' => 'newest',
- 'roots' => array(),
- 'posts' => array(),
- 'revisions' => array(),
- 'links' => array(
- 'pagination' => array(),
- ),
- ),
- ),
- ),
- ),
- ), $expectedCommonResponse );
+ 'roots' => [],
+ 'posts' => [],
+ 'revisions' => [],
+ 'links' => [
+ 'pagination' => [],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ], $expectedCommonResponse );
$actualEmptyPageResponse = $this->doApiRequest(
- array(
+ [
'action' => 'flow',
'page' => 'Talk:Intentionally blank',
'submodule' => 'view-topiclist',
@@ -95,7 +96,7 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
'vtlsortby' => 'newest',
'vtltoconly' => true,
'vtlformat' => 'fixed-html',
- )
+ ]
);
$actualEmptyPageResponse = $actualEmptyPageResponse[0];
@@ -105,49 +106,49 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
'TOC-only output for an empty, but occupied, Flow board'
);
- $expectedNewestResponse = array_merge_recursive( array(
- 'flow' => array(
- 'view-topiclist' => array(
- 'result' => array(
- 'topiclist' => array(
- 'submitted' => array(
+ $expectedNewestResponse = array_merge_recursive( [
+ 'flow' => [
+ 'view-topiclist' => [
+ 'result' => [
+ 'topiclist' => [
+ 'submitted' => [
'sortby' => 'newest',
- ),
+ ],
'sortby' => 'newest',
- 'roots' => array(
+ 'roots' => [
$topicData[2]['id'],
$topicData[1]['id'],
- ),
- 'posts' => array(
+ ],
+ 'posts' => [
$topicData[2]['id'] => $topicData[2]['response']['posts'][$topicData[2]['id']],
$topicData[1]['id'] => $topicData[1]['response']['posts'][$topicData[1]['id']],
- ),
- 'revisions' => array(
+ ],
+ 'revisions' => [
$topicData[2]['revisionId'] => $topicData[2]['expectedRevision'],
$topicData[1]['revisionId'] => $topicData[1]['expectedRevision'],
- ),
- 'links' => array(
- 'pagination' => array(
- 'fwd' => array(
- 'url' => $flowQaTitle->getLinkURL( array(
+ ],
+ 'links' => [
+ 'pagination' => [
+ 'fwd' => [
+ 'url' => $flowQaTitle->getLinkURL( [
'topiclist_offset-dir' => 'fwd',
'topiclist_limit' => '2',
'topiclist_offset-id' => $topicData[1]['id'],
'topiclist_sortby' => 'newest',
- ) ),
+ ] ),
'title' => 'fwd',
'text' => 'fwd',
- ),
- ),
- ),
- ),
- )
- )
- )
- ), $expectedCommonResponse );
+ ],
+ ],
+ ],
+ ],
+ ]
+ ]
+ ]
+ ], $expectedCommonResponse );
$actualNewestResponse = $this->doApiRequest(
- array(
+ [
'action' => 'flow',
'page' => 'Talk:Flow QA',
'submodule' => 'view-topiclist',
@@ -155,7 +156,7 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
'vtlsortby' => 'newest',
'vtltoconly' => true,
'vtlformat' => 'fixed-html',
- )
+ ]
);
$actualNewestResponse = $actualNewestResponse[0];
@@ -168,25 +169,24 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
// Make it so update order is chronologically (1, 0, 2)
// We then expect it to be returned reverse chronologically (2, 0)
- $updateList = array( 1, 0, 2 );
+ $updateList = [ 1, 0, 2 ];
foreach ( $updateList as $updateListInd => $topicDataInd ) {
$replyResponse = $this->doApiRequest(
- array(
+ [
'action' => 'flow',
'page' => $topicData[$topicDataInd]['page'],
'submodule' => 'reply',
'token' => $this->getEditToken(),
'repreplyTo' => $topicData[$topicDataInd]['id'],
'repcontent' => "Reply to topic $topicDataInd",
- )
+ ]
);
// This is because we use timestamps with second granularity.
// Without this, the timestamp can be exactly the same
// for two topics, which means the ordering is undefined (and thus
// untestable). This was causing failures on Jenkins.
- //
// Possible improvement: Make a simple class for getting the current
// time that normally calls wfTimestampNow. Have an alternative
// implementation for tests that can be controlled by an API like
@@ -201,49 +201,49 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
$topicData[$topicDataInd]['expectedRevision']['last_updated'] = wfTimestamp( TS_UNIX, $topicData[$topicDataInd]['updateTimestamp'] ) * 1000;
}
- $expectedUpdatedResponse = array_merge_recursive( array(
- 'flow' => array(
- 'view-topiclist' => array(
- 'result' => array(
- 'topiclist' => array(
- 'submitted' => array(
+ $expectedUpdatedResponse = array_merge_recursive( [
+ 'flow' => [
+ 'view-topiclist' => [
+ 'result' => [
+ 'topiclist' => [
+ 'submitted' => [
'sortby' => 'updated',
- ),
+ ],
'sortby' => 'updated',
- 'roots' => array(
+ 'roots' => [
$topicData[2]['id'],
$topicData[0]['id'],
- ),
- 'posts' => array(
+ ],
+ 'posts' => [
$topicData[2]['id'] => $topicData[2]['response']['posts'][$topicData[2]['id']],
$topicData[0]['id'] => $topicData[0]['response']['posts'][$topicData[0]['id']],
- ),
- 'revisions' => array(
+ ],
+ 'revisions' => [
$topicData[2]['revisionId'] => $topicData[2]['expectedRevision'],
$topicData[0]['revisionId'] => $topicData[0]['expectedRevision'],
- ),
- 'links' => array(
- 'pagination' => array(
- 'fwd' => array(
- 'url' => $flowQaTitle->getLinkURL( array(
+ ],
+ 'links' => [
+ 'pagination' => [
+ 'fwd' => [
+ 'url' => $flowQaTitle->getLinkURL( [
'topiclist_offset-dir' => 'fwd',
'topiclist_limit' => '2',
'topiclist_offset' => $topicData[0]['updateTimestamp'],
'topiclist_sortby' => 'updated',
- ) ),
+ ] ),
'title' => 'fwd',
'text' => 'fwd',
- ),
- ),
- ),
- ),
- )
- )
- )
- ), $expectedCommonResponse );
+ ],
+ ],
+ ],
+ ],
+ ]
+ ]
+ ]
+ ], $expectedCommonResponse );
$actualUpdatedResponse = $this->doApiRequest(
- array(
+ [
'action' => 'flow',
'page' => 'Talk:Flow QA',
'submodule' => 'view-topiclist',
@@ -251,7 +251,7 @@ class ApiFlowViewTopicListTest extends ApiTestCase {
'vtlsortby' => 'updated',
'vtltoconly' => true,
'vtlformat' => 'fixed-html',
- )
+ ]
);
$actualUpdatedResponse = $actualUpdatedResponse[0];
diff --git a/Flow/tests/phpunit/api/ApiTestCase.php b/Flow/tests/phpunit/api/ApiTestCase.php
index f88cb1aa..adc9f33d 100644
--- a/Flow/tests/phpunit/api/ApiTestCase.php
+++ b/Flow/tests/phpunit/api/ApiTestCase.php
@@ -5,7 +5,7 @@ namespace Flow\Tests\Api;
use ApiTestCase as BaseApiTestCase;
use Flow\Container;
use FlowHooks;
-use TestUser;
+use MediaWiki\MediaWikiServices;
use User;
/**
@@ -13,10 +13,9 @@ use User;
* @group medium
*/
abstract class ApiTestCase extends BaseApiTestCase {
- protected $tablesUsed = array(
+ protected $tablesUsed = [
'flow_ext_ref',
'flow_revision',
- 'flow_subscription',
'flow_topic_list',
'flow_tree_node',
'flow_tree_revision',
@@ -24,17 +23,18 @@ abstract class ApiTestCase extends BaseApiTestCase {
'flow_workflow',
'page',
'revision',
+ 'ip_changes',
'text',
- );
+ ];
protected function setUp() {
- $this->setMwGlobals( 'wgNamespaceContentModels', array(
+ $this->setMwGlobals( 'wgNamespaceContentModels', [
NS_TALK => CONTENT_MODEL_FLOW_BOARD,
NS_TOPIC => CONTENT_MODEL_FLOW_BOARD,
- ) );
+ ] );
- Container::reset();
parent::setUp();
+ $this->setCurrentUser( self::$users['sysop']->getUser() );
}
protected function getEditToken( $user = null, $token = 'edittoken' ) {
@@ -43,25 +43,25 @@ abstract class ApiTestCase extends BaseApiTestCase {
}
/**
- * Ensures Flow is reset before passing control on
- * to parent::doApiRequest. Defaults all requests to
- * the sysop user if not specified.
+ * Set $user in the Flow container
+ * WARNING: This resets your container and
+ * gets rid of anything you may have mocked.
+ * @param User $user
*/
+ protected function setCurrentUser( User $user ) {
+ Container::reset();
+ $container = Container::getContainer();
+ $container['user'] = $user;
+ }
+
protected function doApiRequest(
array $params,
array $session = null,
$appendModule = false,
User $user = null
) {
- if ( $user === null ) {
- $user = self::$users['sysop']->getUser();
- }
-
// reset flow state before each request
FlowHooks::resetFlowExtension();
- Container::reset();
- $container = Container::getContainer();
- $container['user'] = $user;
return parent::doApiRequest( $params, $session, $appendModule, $user );
}
@@ -69,14 +69,14 @@ abstract class ApiTestCase extends BaseApiTestCase {
* Create a topic on a board using the default user
*/
protected function createTopic( $topicTitle = 'Hi there!' ) {
- $data = $this->doApiRequest( array(
+ $data = $this->doApiRequest( [
'page' => 'Talk:Flow QA',
'token' => $this->getEditToken(),
'action' => 'flow',
'submodule' => 'new-topic',
'nttopic' => $topicTitle,
'ntcontent' => '...',
- ) );
+ ] );
$this->assertTrue(
isset( $data[0]['flow']['new-topic']['committed']['topiclist']['topic-id'] ),
@@ -85,4 +85,29 @@ abstract class ApiTestCase extends BaseApiTestCase {
return $data[0]['flow']['new-topic']['committed']['topiclist'];
}
+
+ protected function expectCacheInvalidate() {
+ $mock = $this->mockCache();
+ $mock->expects( $this->never() )->method( 'set' );
+ $mock->expects( $this->atLeastOnce() )->method( 'delete' );
+ return $mock;
+ }
+
+ protected function mockCache() {
+ global $wgFlowCacheTime;
+ Container::reset();
+ $container = Container::getContainer();
+ $wanCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
+ $mock = $this->getMockBuilder( 'Flow\Data\FlowObjectCache' )
+ ->setConstructorArgs( [ $wanCache, $container['db.factory'], $wgFlowCacheTime ] )
+ ->enableProxyingToOriginalMethods()
+ ->getMock();
+
+ $container->extend( 'flowcache', function () use ( $mock ) {
+ return $mock;
+ } );
+
+ return $mock;
+ }
}
diff --git a/Flow/tests/phpunit/api/ApiWatchTopicTest.php b/Flow/tests/phpunit/api/ApiWatchTopicTest.php
index b18e4d39..0093dda7 100644
--- a/Flow/tests/phpunit/api/ApiWatchTopicTest.php
+++ b/Flow/tests/phpunit/api/ApiWatchTopicTest.php
@@ -3,7 +3,7 @@
namespace Flow\Tests\Api;
use Title;
-use WatchedItem;
+use User;
/**
* @group Flow
@@ -12,26 +12,30 @@ use WatchedItem;
class ApiWatchTopicTest extends ApiTestCase {
public function watchTopicProvider() {
- return array(
- array(
+ return [
+ [
'Watch a topic',
// expected key in api result
'watched',
// initialization
- function( WatchedItem $item ) { $item->removeWatch(); },
+ function ( User $user, Title $title ) {
+ $user->removeWatch( $title, false );
+ },
// extra request parameters
- array(),
- ),
- array(
+ [],
+ ],
+ [
'Unwatch a topic',
// expected key in api result
'unwatched',
// initialization
- function( WatchedItem $item ) { $item->addWatch(); },
+ function ( User $user, Title $title ) {
+ $user->addWatch( $title, false );
+ },
// extra request parameters
- array( 'unwatch' => 1 ),
- ),
- );
+ [ 'unwatch' => 1 ],
+ ],
+ ];
}
/**
@@ -41,15 +45,15 @@ class ApiWatchTopicTest extends ApiTestCase {
$topic = $this->createTopic();
$title = Title::newFromText( $topic['topic-page'] );
- $init( WatchedItem::fromUserTitle( self::$users['sysop']->getUser(), $title, false ) );
+ $init( self::$users['sysop']->getUser(), $title );
// issue a watch api request
- $data = $this->doApiRequest( $request + array(
+ $data = $this->doApiRequest( $request + [
'action' => 'watch',
'format' => 'json',
'titles' => $topic['topic-page'],
'token' => $this->getEditToken( null, 'watchtoken' ),
- ) );
+ ] );
$this->assertArrayHasKey( $expect, $data[0]['watch'][0], $message );
}
}
diff --git a/Flow/tests/phpunit/bootstrap.php b/Flow/tests/phpunit/bootstrap.php
index cddd5d5a..d4852266 100644
--- a/Flow/tests/phpunit/bootstrap.php
+++ b/Flow/tests/phpunit/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/Flow/tests/qunit/engine/misc/test_flow-handlebars.js b/Flow/tests/qunit/engine/misc/test_flow-handlebars.js
index 6c88391c..84c893ef 100644
--- a/Flow/tests/qunit/engine/misc/test_flow-handlebars.js
+++ b/Flow/tests/qunit/engine/misc/test_flow-handlebars.js
@@ -1,153 +1,155 @@
( function ( $ ) {
-QUnit.module( 'ext.flow: Handlebars helpers', {
- setup: function () {
- var stub = this.sandbox.stub( mw.template, 'get' ),
- stubUser;
-
- stub.withArgs( 'ext.flow.templating', 'foo.handlebars' ).returns( {
- render: function ( data ) {
- return data && data.val ? '<div>Magic.</div>' : 'Stubbed.';
- }
- } );
- this.handlebarsProto = mw.flow.FlowHandlebars.prototype;
- this.handlebarsProto._qunit_helper_test = function ( a, b ) {
- return a + b;
- };
-
- // Stub user
- stubUser = this.sandbox.stub( mw.user, 'isAnon' );
- stubUser.onCall( 0 ).returns( true );
- stubUser.onCall( 1 ).returns( false );
- this.opts = {
- fn: function () {
- return 'ok';
+ QUnit.module( 'ext.flow: Handlebars helpers', {
+ setup: function () {
+ var stub = this.sandbox.stub( mw.template, 'get' ),
+ stubUser;
+
+ stub.withArgs( 'ext.flow.templating', 'foo.handlebars' ).returns( {
+ render: function ( data ) {
+ return data && data.val ? '<div>Magic.</div>' : 'Stubbed.';
+ }
+ } );
+ this.handlebarsProto = mw.flow.FlowHandlebars.prototype;
+ this.handlebarsProto._qunit_helper_test = function ( a, b ) {
+ return a + b;
+ };
+
+ // Stub user
+ stubUser = this.sandbox.stub( mw.user, 'isAnon' );
+ stubUser.onCall( 0 ).returns( true );
+ stubUser.onCall( 1 ).returns( false );
+ this.opts = {
+ fn: function () {
+ return 'ok';
+ },
+ inverse: function () {
+ return 'nope';
+ }
+ };
+ }
+ } );
+
+ QUnit.test( 'Handlebars.prototype.processTemplate', 1, function ( assert ) {
+ assert.strictEqual( this.handlebarsProto.processTemplate( 'foo', { val: 'Hello' } ),
+ '<div>Magic.</div>', 'Getting a template works.' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.processTemplateGetFragment', 1, function ( assert ) {
+ assert.strictEqual( this.handlebarsProto.processTemplateGetFragment( 'foo', { val: 'Hello' } ).childNodes.length,
+ 1, 'Return a fragment with the div child node' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.getTemplate', 2, function ( assert ) {
+ assert.strictEqual( this.handlebarsProto.getTemplate( 'foo' )(), 'Stubbed.', 'Getting a template works.' );
+ assert.strictEqual( this.handlebarsProto.getTemplate( 'foo' )(), 'Stubbed.', 'Getting a template from cache works.' );
+ } );
+
+ // Helpers
+ QUnit.test( 'Handlebars.prototype.callHelper', 1, function ( assert ) {
+ assert.strictEqual( this.handlebarsProto.callHelper( '_qunit_helper_test', 1, 2 ),
+ 3, 'Check the helper was called.' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.eachPost', 3, function ( assert ) {
+ var ctx = {
+ posts: {
+ 1: [ 300 ],
+ // Purposely points to a missing revision to deal with edge case
+ 2: [ 500 ]
},
- inverse: function () {
- return 'nope';
+ revisions: {
+ 300: { content: 'a' }
}
};
- }
-} );
-
-QUnit.test( 'Handlebars.prototype.processTemplate', 1, function ( assert ) {
- assert.strictEqual( this.handlebarsProto.processTemplate( 'foo', { val: 'Hello' } ),
- '<div>Magic.</div>', 'Getting a template works.' );
-} );
-
-QUnit.test( 'Handlebars.prototype.processTemplateGetFragment', 1, function ( assert ) {
- assert.strictEqual( this.handlebarsProto.processTemplateGetFragment( 'foo', { val: 'Hello' } ).childNodes.length,
- 1, 'Return a fragment with the div child node' );
-} );
-
-QUnit.test( 'Handlebars.prototype.getTemplate', 2, function ( assert ) {
- assert.strictEqual( this.handlebarsProto.getTemplate( 'foo' )(), 'Stubbed.', 'Getting a template works.' );
- assert.strictEqual( this.handlebarsProto.getTemplate( 'foo' )(), 'Stubbed.', 'Getting a template from cache works.' );
-} );
-
-// Helpers
-QUnit.test( 'Handlebars.prototype.callHelper', 1, function ( assert ) {
- assert.strictEqual( this.handlebarsProto.callHelper( '_qunit_helper_test', 1, 2 ),
- 3, 'Check the helper was called.' );
-} );
-
-QUnit.test( 'Handlebars.prototype.eachPost', 3, function ( assert ) {
- var ctx = {
- posts: {
- 1: [ 300 ],
- // Purposely points to a missing revision to deal with edge case
- 2: [ 500 ]
- },
- revisions: {
- 300: { content: 'a' }
- }
- };
-
- assert.deepEqual( this.handlebarsProto.eachPost( ctx, 1, {} ), { content: 'a' }, 'Matches given id.' );
- assert.deepEqual( this.handlebarsProto.eachPost( ctx, 1, this.opts ), 'ok', 'Runs fn when given.' );
- assert.deepEqual( this.handlebarsProto.eachPost( ctx, 2, {} ), { content: null }, 'Missing revision id.' );
-} );
-
-QUnit.test( 'Handlebars.prototype.ifCond', 8, function ( assert ) {
- assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '===', 'bar', this.opts ), 'nope', 'not equal' );
- assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '===', 'foo', this.opts ), 'ok', 'equal' );
- assert.strictEqual( this.handlebarsProto.ifCond( true, 'or', false, this.opts ), 'ok', 'true || false' );
- assert.strictEqual( this.handlebarsProto.ifCond( true, 'or', true, this.opts ), 'ok', 'true || true' );
- assert.strictEqual( this.handlebarsProto.ifCond( false, 'or', false, this.opts ), 'nope', 'false || false' );
- assert.strictEqual( this.handlebarsProto.ifCond( false, 'monkeypunch', this.opts ), '', 'Unknown operator' );
- assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '!==', 'foo', this.opts ), 'nope' );
- assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '!==', 'bar', this.opts ), 'ok' );
-} );
-
-QUnit.test( 'Handlebars.prototype.ifAnonymous', 2, function () {
- strictEqual( this.handlebarsProto.ifAnonymous( this.opts ), 'ok', 'User should be anonymous first time.' );
- strictEqual( this.handlebarsProto.ifAnonymous( this.opts ), 'nope', 'User should be logged in on second call.' );
-} );
-
-QUnit.test( 'Handlebars.prototype.concat', 2, function () {
- strictEqual( this.handlebarsProto.concat( 'a', 'b', 'c', this.opts ), 'abc', 'Check concat working fine.' );
- strictEqual( this.handlebarsProto.concat( this.opts ), '', 'Without arguments.' );
-} );
-
-QUnit.test( 'Handlebars.prototype.progressiveEnhancement', 5, function () {
- var opts = $.extend( { hash: { type: 'insert', target: 'abc', id: 'def' } }, this.opts ),
- $div = $( document.createElement( 'div' ) );
-
- // Render script tag
- strictEqual(
- this.handlebarsProto.progressiveEnhancement( opts ).string,
- '<scr' + 'ipt' +
- ' type="text/x-handlebars-template-progressive-enhancement"' +
- ' data-type="' + opts.hash.type + '"' +
- ' data-target="' + opts.hash.target + '"' +
- ' id="' + opts.hash.id + '">' +
- 'ok' +
+
+ assert.deepEqual( this.handlebarsProto.eachPost( ctx, 1, {} ), { content: 'a' }, 'Matches given id.' );
+ assert.deepEqual( this.handlebarsProto.eachPost( ctx, 1, this.opts ), 'ok', 'Runs fn when given.' );
+ assert.deepEqual( this.handlebarsProto.eachPost( ctx, 2, {} ), { content: null }, 'Missing revision id.' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.ifCond', 8, function ( assert ) {
+ assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '===', 'bar', this.opts ), 'nope', 'not equal' );
+ assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '===', 'foo', this.opts ), 'ok', 'equal' );
+ assert.strictEqual( this.handlebarsProto.ifCond( true, 'or', false, this.opts ), 'ok', 'true || false' );
+ assert.strictEqual( this.handlebarsProto.ifCond( true, 'or', true, this.opts ), 'ok', 'true || true' );
+ assert.strictEqual( this.handlebarsProto.ifCond( false, 'or', false, this.opts ), 'nope', 'false || false' );
+ assert.strictEqual( this.handlebarsProto.ifCond( false, 'monkeypunch', this.opts ), '', 'Unknown operator' );
+ assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '!==', 'foo', this.opts ), 'nope' );
+ assert.strictEqual( this.handlebarsProto.ifCond( 'foo', '!==', 'bar', this.opts ), 'ok' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.ifAnonymous', 2, function () {
+ strictEqual( this.handlebarsProto.ifAnonymous( this.opts ), 'ok', 'User should be anonymous first time.' );
+ strictEqual( this.handlebarsProto.ifAnonymous( this.opts ), 'nope', 'User should be logged in on second call.' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.concat', 2, function () {
+ strictEqual( this.handlebarsProto.concat( 'a', 'b', 'c', this.opts ), 'abc', 'Check concat working fine.' );
+ strictEqual( this.handlebarsProto.concat( this.opts ), '', 'Without arguments.' );
+ } );
+
+ QUnit.test( 'Handlebars.prototype.progressiveEnhancement', 5, function () {
+ var opts = $.extend( { hash: { type: 'insert', target: 'abc', id: 'def' } }, this.opts ),
+ $div = $( document.createElement( 'div' ) );
+
+ // Render script tag
+ strictEqual(
+ this.handlebarsProto.progressiveEnhancement( opts ).string,
+ // eslint-disable-next-line no-useless-concat
+ '<scr' + 'ipt' +
+ ' type="text/x-handlebars-template-progressive-enhancement"' +
+ ' data-type="' + opts.hash.type + '"' +
+ ' data-target="' + opts.hash.target + '"' +
+ ' id="' + opts.hash.id + '">' +
+ 'ok' +
+ // eslint-disable-next-line no-useless-concat
'</scr' + 'ipt>',
- 'Should output exact replica of script tag.'
- );
-
- // Replace itself: no target (default to self), no type (default to insert)
- $div.empty().append( this.handlebarsProto.processTemplateGetFragment(
- Handlebars.compile( '{{#progressiveEnhancement}}hello{{/progressiveEnhancement}}' )
- ) );
- strictEqual(
- $div.html(),
- 'hello',
- 'progressiveEnhancement should be processed in template string.'
- );
-
- // Replace a target entirely: target + type=replace
- $div.empty().append( this.handlebarsProto.processTemplateGetFragment(
- Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="replace"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
- ) );
- strictEqual(
- $div.html(),
- 'hello',
- 'progressiveEnhancement should replace target node.'
- );
-
- // Insert before a target: target + type=insert
- $div.empty().append(
- this.handlebarsProto.processTemplateGetFragment(
- Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="insert"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
- )
- );
- strictEqual(
- $div.html(),
- 'hello<div class="pgetest">foo</div>',
- 'progressiveEnhancement should insert before target.'
- );
-
- // Replace target's content: target + type=content
- $div.empty().append(
- this.handlebarsProto.processTemplateGetFragment(
- Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="content"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
- )
- );
- strictEqual(
- $div.html(),
- '<div class="pgetest">hello</div>',
- 'progressiveEnhancement should replace target content.'
- );
-} );
+ 'Should output exact replica of script tag.'
+ );
+
+ // Replace itself: no target (default to self), no type (default to insert)
+ $div.empty().append( this.handlebarsProto.processTemplateGetFragment(
+ Handlebars.compile( '{{#progressiveEnhancement}}hello{{/progressiveEnhancement}}' )
+ ) );
+ strictEqual(
+ $div.html(),
+ 'hello',
+ 'progressiveEnhancement should be processed in template string.'
+ );
+
+ // Replace a target entirely: target + type=replace
+ $div.empty().append( this.handlebarsProto.processTemplateGetFragment(
+ Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="replace"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
+ ) );
+ strictEqual(
+ $div.html(),
+ 'hello',
+ 'progressiveEnhancement should replace target node.'
+ );
+
+ // Insert before a target: target + type=insert
+ $div.empty().append(
+ this.handlebarsProto.processTemplateGetFragment(
+ Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="insert"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
+ )
+ );
+ strictEqual(
+ $div.html(),
+ 'hello<div class="pgetest">foo</div>',
+ 'progressiveEnhancement should insert before target.'
+ );
+
+ // Replace target's content: target + type=content
+ $div.empty().append(
+ this.handlebarsProto.processTemplateGetFragment(
+ Handlebars.compile( '{{#progressiveEnhancement target="~ .pgetest" type="content"}}hello{{/progressiveEnhancement}}<div class="pgetest">foo</div>' )
+ )
+ );
+ strictEqual(
+ $div.html(),
+ '<div class="pgetest">hello</div>',
+ 'progressiveEnhancement should replace target content.'
+ );
+ } );
}( jQuery ) );
diff --git a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Board.js b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Board.js
index 255b51f9..cb1aa61e 100644
--- a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Board.js
+++ b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Board.js
@@ -21,7 +21,6 @@ QUnit.test( 'Create board', function ( assert ) {
author: null,
changeType: null,
content: null,
- contentFormat: null,
creator: null,
id: null,
lastUpdate: null,
@@ -30,6 +29,7 @@ QUnit.test( 'Create board', function ( assert ) {
revisionId: null,
timestamp: null,
watchable: true,
+ editable: true,
watched: false,
workflowId: null
}
@@ -46,21 +46,21 @@ QUnit.test( 'Create board', function ( assert ) {
new mw.flow.dm.Topic( 'topic1', {
content: {
content: 'Topic 1',
- format: 'plaintext'
+ format: 'topic-title-wikitext'
},
last_updated: '123123123'
} ),
new mw.flow.dm.Topic( 'topic2', {
content: {
content: 'Topic 2',
- format: 'plaintext'
+ format: 'topic-title-wikitext'
},
last_updated: '123123321'
} ),
new mw.flow.dm.Topic( 'topic3', {
content: {
content: 'Topic 3',
- format: 'plaintext'
+ format: 'topic-title-wikitext'
},
last_updated: '123123543'
} )
@@ -94,7 +94,6 @@ QUnit.test( 'Create board', function ( assert ) {
author: null,
changeType: null,
content: '<h1>This is a test board description.</h1>',
- contentFormat: 'html',
creator: null,
id: null,
lastUpdate: null,
@@ -103,6 +102,7 @@ QUnit.test( 'Create board', function ( assert ) {
revisionId: null,
timestamp: null,
watchable: true,
+ editable: false,
watched: false,
workflowId: null
}
@@ -113,6 +113,46 @@ QUnit.test( 'Create board', function ( assert ) {
method: 'hasBeenChanged',
expected: true,
msg: 'Check if board has changed since breakpoint'
+ },
+ {
+ method: 'setDescription',
+ params: [
+ new mw.flow.dm.BoardDescription( {
+ content: {
+ content: '<h1>This is a test board description.</h1>',
+ format: 'html'
+ },
+ actions: {
+ edit: 'http://some.url.for.edit/'
+ }
+ } )
+ ]
+ },
+ {
+ method: 'getHashObject',
+ expected: {
+ id: 'xxx123xxx',
+ isDeleted: false,
+ pagePrefixedDb: 'Special:FlowTestBoardPage',
+ topicCount: 3,
+ description: {
+ author: null,
+ changeType: null,
+ content: '<h1>This is a test board description.</h1>',
+ creator: null,
+ id: null,
+ lastUpdate: null,
+ originalContent: true,
+ previousRevisionId: null,
+ revisionId: null,
+ timestamp: null,
+ watchable: true,
+ editable: true,
+ watched: false,
+ workflowId: null
+ }
+ },
+ msg: 'Get current board state with editable description'
}
];
diff --git a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Content.js b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Content.js
new file mode 100644
index 00000000..9c0bf342
--- /dev/null
+++ b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Content.js
@@ -0,0 +1,29 @@
+QUnit.module( 'ext.flow.dm mw.flow.dm.Content' );
+
+/* Tests */
+
+QUnit.test( 'Stores different content representations (formats)', function ( assert ) {
+ var content = new mw.flow.dm.Content( {
+ content: 'content in default format (wikitext, for instance)',
+ format: 'wikitext',
+ html: 'content in html format',
+ plaintext: 'content in plaintext format',
+ someNewFormat: 'content in some new format'
+ } );
+
+ assert.equal( content.get( 'html' ), 'content in html format' );
+ assert.equal( content.get( 'wikitext' ), 'content in default format (wikitext, for instance)' );
+ assert.equal( content.get(), 'content in default format (wikitext, for instance)' );
+ assert.equal( content.get( 'unknown format' ), null );
+
+ QUnit.expect( 4 );
+} );
+
+QUnit.test( 'Behaves when empty', function ( assert ) {
+ var content = new mw.flow.dm.Content();
+
+ assert.equal( content.get(), null );
+ assert.equal( content.get( 'whatever format' ), null );
+
+ QUnit.expect( 2 );
+} );
diff --git a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Post.js b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Post.js
index c4e5e6ed..e46f9113 100644
--- a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Post.js
+++ b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Post.js
@@ -53,7 +53,7 @@ QUnit.test( 'Hierarchical post structure', function ( assert ) {
isModeratedNotLocked: false,
content: {
content: 'Topic with hierarchical posts',
- format: 'plaintext'
+ format: 'topic-title-wikitext'
},
isWatched: true,
watchable: true,
diff --git a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.System.js b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.System.js
index a6a35249..73878714 100644
--- a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.System.js
+++ b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.System.js
@@ -43,7 +43,7 @@ QUnit.test( 'Initialize flow system', function ( assert ) {
dateFormats: [],
properties: {
'topic-of-post': {
- plaintext: 'This is a test content in plaintext.'
+ plaintext: 'This is a test content in topic-title-wikitext.'
}
},
isOriginalContent: true,
@@ -81,8 +81,8 @@ QUnit.test( 'Initialize flow system', function ( assert ) {
lastEditId: null,
previousRevisionId: null,
content: {
- content: 'This is a test content in plaintext.',
- format: 'plaintext'
+ content: 'This is a test content in topic-title-wikitext.',
+ format: 'topic-title-wikitext'
},
watchable: false,
replyToId: null,
diff --git a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Topic.js b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Topic.js
index 75c9eb49..6066a3bc 100644
--- a/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Topic.js
+++ b/Flow/tests/qunit/flow/dm/test_mw.flow.dm.Topic.js
@@ -3,12 +3,13 @@ QUnit.module( 'ext.flow.dm mw.flow.dm.Topic' );
/* Tests */
QUnit.test( 'Load topics', function ( assert ) {
- var i, j, ilen, jlen, topic, result, operation,
+ var i, j, ilen, jlen, topic, result, operation, cases,
executeOperation = function ( obj, operation, params ) {
return obj[ operation ].apply( obj, params );
},
- expectCount = 0,
- cases = [
+ expectCount = 0;
+
+ cases = [
{
args: {
id: 'sgl9yjs9nwgmc7l7',
@@ -138,7 +139,7 @@ QUnit.test( 'Load topics', function ( assert ) {
previousRevisionId: null,
content: {
content: 'This is the title of the topic.',
- format: 'plaintext'
+ format: 'topic-title-wikitext'
},
isWatched: true,
watchable: true,
@@ -190,12 +191,7 @@ QUnit.test( 'Load topics', function ( assert ) {
{
method: 'getContent',
expected: 'This is the title of the topic.',
- msg: 'Get topic raw content'
- },
- {
- method: 'getContentFormat',
- expected: 'plaintext',
- msg: 'Get topic content format'
+ msg: 'Get topic content in default format'
},
{
method: 'isModerated',
diff --git a/Flow/vendor/autoload.php b/Flow/vendor/autoload.php
index fc8756e4..54fc1307 100644
--- a/Flow/vendor/autoload.php
+++ b/Flow/vendor/autoload.php
@@ -2,6 +2,6 @@
// autoload.php @generated by Composer
-require_once __DIR__ . '/composer' . '/autoload_real.php';
+require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e::getLoader();
+return ComposerAutoloaderInit805335e19cbed64472f1539b7dc2ba21::getLoader();
diff --git a/Flow/vendor/composer/ClassLoader.php b/Flow/vendor/composer/ClassLoader.php
index 5e1469e8..dc02dfb1 100644
--- a/Flow/vendor/composer/ClassLoader.php
+++ b/Flow/vendor/composer/ClassLoader.php
@@ -13,9 +13,7 @@
namespace Composer\Autoload;
/**
- * ClassLoader implements a PSR-0 class loader
- *
- * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
@@ -39,6 +37,8 @@ namespace Composer\Autoload;
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see http://www.php-fig.org/psr/psr-0/
+ * @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
@@ -53,8 +53,9 @@ class ClassLoader
private $useIncludePath = false;
private $classMap = array();
-
private $classMapAuthoritative = false;
+ private $missingClasses = array();
+ private $apcuPrefix;
public function getPrefixes()
{
@@ -147,7 +148,7 @@ class ClassLoader
* 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 array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
@@ -272,6 +273,26 @@ class ClassLoader
}
/**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
@@ -313,29 +334,34 @@ class ClassLoader
*/
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) {
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
- if ($file === null && defined('HHVM_VERSION')) {
+ if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
- if ($file === null) {
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
// Remember that this class does not exist.
- return $this->classMap[$class] = false;
+ $this->missingClasses[$class] = true;
}
return $file;
@@ -348,10 +374,14 @@ class ClassLoader
$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))) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath.'\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
@@ -399,6 +429,8 @@ class ClassLoader
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
+
+ return false;
}
}
diff --git a/Flow/vendor/composer/autoload_namespaces.php b/Flow/vendor/composer/autoload_namespaces.php
index d04bf529..c3cd0229 100644
--- a/Flow/vendor/composer/autoload_namespaces.php
+++ b/Flow/vendor/composer/autoload_namespaces.php
@@ -6,6 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
- 'Symfony\\Component\\DomCrawler\\' => array($vendorDir . '/symfony/dom-crawler'),
- 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
+ 'Pimple' => array($vendorDir . '/pimple/pimple/src'),
);
diff --git a/Flow/vendor/composer/autoload_real.php b/Flow/vendor/composer/autoload_real.php
index 7a5d889a..37c22f51 100644
--- a/Flow/vendor/composer/autoload_real.php
+++ b/Flow/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e
+class ComposerAutoloaderInit805335e19cbed64472f1539b7dc2ba21
{
private static $loader;
@@ -19,23 +19,30 @@ class ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e
return self::$loader;
}
- spl_autoload_register(array('ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit805335e19cbed64472f1539b7dc2ba21', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- spl_autoload_unregister(array('ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e', '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);
+ spl_autoload_unregister(array('ComposerAutoloaderInit805335e19cbed64472f1539b7dc2ba21', 'loadClassLoader'));
+
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+ if ($useStaticLoader) {
+ require_once __DIR__ . '/autoload_static.php';
+
+ call_user_func(\Composer\Autoload\ComposerStaticInit805335e19cbed64472f1539b7dc2ba21::getInitializer($loader));
+ } else {
+ $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);
@@ -43,8 +50,3 @@ class ComposerAutoloaderInite0507a57d4ccaaf625d56239803b952e
return $loader;
}
}
-
-function composerRequiree0507a57d4ccaaf625d56239803b952e($file)
-{
- require $file;
-}
diff --git a/Flow/vendor/composer/installed.json b/Flow/vendor/composer/installed.json
index ec78d590..e4b64082 100644
--- a/Flow/vendor/composer/installed.json
+++ b/Flow/vendor/composer/installed.json
@@ -1,34 +1,33 @@
[
{
- "name": "symfony/css-selector",
- "version": "v2.5.6",
- "version_normalized": "2.5.6.0",
- "target-dir": "Symfony/Component/CssSelector",
+ "name": "pimple/pimple",
+ "version": "v3.0.2",
+ "version_normalized": "3.0.2.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/CssSelector.git",
- "reference": "7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc"
+ "url": "https://github.com/silexphp/Pimple.git",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/CssSelector/zipball/7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc",
- "reference": "7cdf543a3f31935aae58de4e6e607d4bdeb3f5dc",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
+ "reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.0"
},
- "time": "2014-10-09 16:00:03",
+ "time": "2015-09-11T15:10:35+00:00",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.5-dev"
+ "dev-master": "3.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
- "Symfony\\Component\\CssSelector\\": ""
+ "Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -37,74 +36,15 @@
],
"authors": [
{
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
- "name": "Jean-François Simon",
- "email": "jeanfrancois.simon@sensiolabs.com"
- },
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Symfony CssSelector Component",
- "homepage": "http://symfony.com"
- },
- {
- "name": "symfony/dom-crawler",
- "version": "v2.5.6",
- "version_normalized": "2.5.6.0",
- "target-dir": "Symfony/Component/DomCrawler",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/DomCrawler.git",
- "reference": "5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/DomCrawler/zipball/5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e",
- "reference": "5b45ef9b8a8e6dda47eb9b9b982f61e8b2caa21e",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "symfony/css-selector": "~2.0"
- },
- "suggest": {
- "symfony/css-selector": ""
- },
- "time": "2014-10-01 05:50:18",
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.5-dev"
- }
- },
- "installation-source": "dist",
- "autoload": {
- "psr-0": {
- "Symfony\\Component\\DomCrawler\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
- "description": "Symfony DomCrawler Component",
- "homepage": "http://symfony.com"
+ "description": "Pimple, a simple Dependency Injection Container",
+ "homepage": "http://pimple.sensiolabs.org",
+ "keywords": [
+ "container",
+ "dependency injection"
+ ]
}
]
diff --git a/Flow/version b/Flow/version
index ba23c2cc..3908b610 100644
--- a/Flow/version
+++ b/Flow/version
@@ -1,4 +1,4 @@
-Flow: REL1_26
-2016-01-04T17:05:37
+Flow: REL1_30
+2018-10-30T21:07:39
-c89d781
+f75fa78