r91118 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r91117‎ | r91118 | r91119 >
Date:21:57, 29 June 2011
Author:awjrichards
Status:ok
Tags:
Comment:
MFT r83564-91107
Modified paths:
  • /branches/wmf/1.17wmf1/extensions/CentralNotice (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.alias.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.db.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.i18n.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.sql (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/README (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerAllocation.php (deleted) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerController.php (deleted) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerListLoader.php (deleted) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialCentralNotice.php (deleted) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialNoticeTemplate.php (deleted) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/TemplatePager.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/centralnotice.css (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/centralnotice.js (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-notice_logs.sql (added) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-template_fundraising.sql (added) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/special (added) (history)
  • /branches/wmf/1.17wmf1/extensions/CentralNotice/tests (added) (history)

Diff [purge]

Index: branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerListLoader.php
@@ -1,79 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * Generates JSON files listing all the banners for a particular site
6 - */
7 -class SpecialBannerListLoader extends UnlistedSpecialPage {
8 - public $project; // Project name
9 - public $language; // Project language
10 - public $location; // User country
11 - protected $sharedMaxAge = 300; // Cache for 5 minutes on the server side
12 - protected $maxAge = 300; // Cache for 5 minutes on the client side
13 -
14 - function __construct() {
15 - // Register special page
16 - parent::__construct( "BannerListLoader" );
17 - }
18 -
19 - function execute( $par ) {
20 - global $wgOut, $wgRequest;
21 -
22 - $wgOut->disable();
23 - $this->sendHeaders();
24 -
25 - // Get project language from the query string
26 - $this->language = $wgRequest->getText( 'language', 'en' );
27 -
28 - // Get project name from the query string
29 - $this->project = $wgRequest->getText( 'project', 'wikipedia' );
30 -
31 - // Get location from the query string
32 - $this->location = $wgRequest->getText( 'country' );
33 -
34 - if ( $this->project && $this->language ) {
35 - $content = $this->getJsonList();
36 - if ( strlen( $content ) == 0 ) {
37 - // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
38 - echo "/* Empty */";
39 - } else {
40 - echo $content;
41 - }
42 - } else {
43 - echo "/* No site specified */";
44 - }
45 - }
46 -
47 - /**
48 - * Generate the HTTP response headers for the banner file
49 - */
50 - function sendHeaders() {
51 - global $wgJsMimeType;
52 - header( "Content-type: $wgJsMimeType; charset=utf-8" );
53 - header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
54 - }
55 -
56 - /**
57 - * Generate JSON for the specified site
58 - */
59 - function getJsonList() {
60 - $templates = array();
61 -
62 - // See if we have any preferred campaigns for this language and project
63 - $notices = CentralNoticeDB::getNotices( $this->project, $this->language, null, 1, 1, $this->location );
64 -
65 - // Quick short circuit to show preferred campaigns
66 - if ( $notices ) {
67 - // Pull banners
68 - $templates = CentralNoticeDB::selectTemplatesAssigned( $notices );
69 - }
70 -
71 - // Didn't find any preferred banners so do an old style lookup
72 - if ( !$templates ) {
73 - $templates = CentralNotice::selectNoticeTemplates(
74 - $this->project, $this->language, $this->location );
75 - }
76 -
77 - return FormatJson::encode( $templates );
78 - }
79 -
80 -}
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialCentralNotice.php
@@ -1,1856 +0,0 @@
2 -<?php
3 -
4 -if ( !defined( 'MEDIAWIKI' ) ) {
5 - echo "CentralNotice extension\n";
6 - exit( 1 );
7 -}
8 -
9 -class CentralNotice extends SpecialPage {
10 - var $editable, $centralNoticeError;
11 -
12 - function __construct() {
13 - // Register special page
14 - parent::__construct( 'CentralNotice' );
15 - }
16 -
17 - /**
18 - * Handle different types of page requests
19 - */
20 - function execute( $sub ) {
21 - global $wgOut, $wgUser, $wgRequest, $wgExtensionAssetsPath;
22 -
23 - // Begin output
24 - $this->setHeaders();
25 -
26 - // Add style file to the output headers
27 - $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
28 -
29 - // Add script file to the output headers
30 - $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
31 -
32 - // Check permissions
33 - $this->editable = $wgUser->isAllowed( 'centralnotice-admin' );
34 -
35 - // Initialize error variable
36 - $this->centralNoticeError = false;
37 -
38 - // Show summary
39 - $wgOut->addWikiText( wfMsg( 'centralnotice-summary' ) );
40 -
41 - // Show header
42 - $this->printHeader( $sub );
43 -
44 - // Begin Campaigns tab content
45 - $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
46 -
47 - $method = $wgRequest->getVal( 'method' );
48 -
49 - // Switch to campaign detail interface if requested
50 - if ( $method == 'listNoticeDetail' ) {
51 - $notice = $wgRequest->getVal ( 'notice' );
52 - $this->listNoticeDetail( $notice );
53 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
54 - return;
55 - }
56 -
57 - // Handle form submissions from "Manage campaigns" or "Add a campaign" interface
58 - if ( $this->editable && $wgRequest->wasPosted() ) {
59 -
60 - // Check authentication token
61 - if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
62 -
63 - // Handle removing campaigns
64 - $toRemove = $wgRequest->getArray( 'removeNotices' );
65 - if ( $toRemove ) {
66 - // Remove campaigns in list
67 - foreach ( $toRemove as $notice ) {
68 - $this->removeNotice( $notice );
69 - }
70 -
71 - // Skip subsequent form handling and show list of campaigns
72 - $this->listNotices();
73 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
74 - return;
75 - }
76 -
77 - // Handle locking/unlocking campaigns
78 - $lockedNotices = $wgRequest->getArray( 'locked' );
79 - if ( $lockedNotices ) {
80 - // Build list of campaigns to lock
81 - $unlockedNotices = array_diff( $this->getNoticesName(), $lockedNotices );
82 -
83 - // Set locked/unlocked flag accordingly
84 - foreach ( $lockedNotices as $notice ) {
85 - $this->updateLock( $notice, '1' );
86 - }
87 - foreach ( $unlockedNotices as $notice ) {
88 - $this->updateLock( $notice, '0' );
89 - }
90 - // Handle updates if no post content came through (all checkboxes unchecked)
91 - } elseif ( $method !== 'addNotice' ) {
92 - $allNotices = $this->getNoticesName();
93 - foreach ( $allNotices as $notice ) {
94 - $this->updateLock( $notice, '0' );
95 - }
96 - }
97 -
98 - // Handle enabling/disabling campaigns
99 - $enabledNotices = $wgRequest->getArray( 'enabled' );
100 - if ( $enabledNotices ) {
101 - // Build list of campaigns to disable
102 - $disabledNotices = array_diff( $this->getNoticesName(), $enabledNotices );
103 -
104 - // Set enabled/disabled flag accordingly
105 - foreach ( $enabledNotices as $notice ) {
106 - $this->updateEnabled( $notice, '1' );
107 - }
108 - foreach ( $disabledNotices as $notice ) {
109 - $this->updateEnabled( $notice, '0' );
110 - }
111 - // Handle updates if no post content came through (all checkboxes unchecked)
112 - } elseif ( $method !== 'addNotice' ) {
113 - $allNotices = $this->getNoticesName();
114 - foreach ( $allNotices as $notice ) {
115 - $this->updateEnabled( $notice, '0' );
116 - }
117 - }
118 -
119 - // Handle setting preferred campaigns
120 - $preferredNotices = $wgRequest->getArray( 'preferred' );
121 - if ( $preferredNotices ) {
122 - // Build list of campaigns to unset
123 - $unsetNotices = array_diff( $this->getNoticesName(), $preferredNotices );
124 -
125 - // Set flag accordingly
126 - foreach ( $preferredNotices as $notice ) {
127 - $this->updatePreferred( $notice, '1' );
128 - }
129 - foreach ( $unsetNotices as $notice ) {
130 - $this->updatePreferred( $notice, '0' );
131 - }
132 - // Handle updates if no post content came through (all checkboxes unchecked)
133 - } elseif ( $method !== 'addNotice' ) {
134 - $allNotices = $this->getNoticesName();
135 - foreach ( $allNotices as $notice ) {
136 - $this->updatePreferred( $notice, '0' );
137 - }
138 - }
139 -
140 - // Handle adding of campaign
141 - if ( $method == 'addNotice' ) {
142 - $noticeName = $wgRequest->getVal( 'noticeName' );
143 - $start = $wgRequest->getArray( 'start' );
144 - $projects = $wgRequest->getArray( 'projects' );
145 - $project_languages = $wgRequest->getArray( 'project_languages' );
146 - $geotargeted = $wgRequest->getCheck( 'geotargeted' );
147 - $geo_countries = $wgRequest->getArray( 'geo_countries' );
148 - if ( $noticeName == '' ) {
149 - $this->showError( 'centralnotice-null-string' );
150 - } else {
151 - $this->addNotice( $noticeName, '0', $start, $projects,
152 - $project_languages, $geotargeted, $geo_countries );
153 - }
154 - }
155 -
156 - // If there were no errors, reload the page to prevent duplicate form submission
157 - if ( !$this->centralNoticeError ) {
158 - $wgOut->redirect( $this->getTitle()->getLocalUrl() );
159 - return;
160 - }
161 -
162 - } else {
163 - $this->showError( 'sessionfailure' );
164 - }
165 -
166 - }
167 -
168 - // Show list of campaigns
169 - $this->listNotices();
170 -
171 - // End Campaigns tab content
172 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
173 - }
174 -
175 - public static function printHeader() {
176 - global $wgOut, $wgTitle, $wgUser;
177 - $sk = $wgUser->getSkin();
178 -
179 - $pages = array(
180 - 'CentralNotice' => wfMsg( 'centralnotice-notices' ),
181 - 'NoticeTemplate' => wfMsg ( 'centralnotice-templates' ),
182 - 'BannerAllocation' => wfMsg ( 'centralnotice-allocation' )
183 - );
184 - $htmlOut = Xml::openElement( 'ul', array( 'id' => 'preftoc' ) );
185 - foreach ( $pages as $page => $msg ) {
186 - $title = SpecialPage::getTitleFor( $page );
187 - $attribs = array();
188 - if ( $wgTitle->equals( $title ) ) {
189 - $attribs['class'] = 'selected';
190 - }
191 - $htmlOut .= Xml::tags( 'li', $attribs,
192 - $sk->makeLinkObj( $title, htmlspecialchars( $msg ) )
193 - );
194 - }
195 - $htmlOut .= Xml::closeElement( 'ul' );
196 -
197 - $wgOut->addHTML( $htmlOut );
198 - }
199 -
200 - /**
201 - * Get all the campaigns in the database
202 - * @return an array of campaign names
203 - */
204 - function getNoticesName() {
205 - $dbr = wfGetDB( DB_SLAVE );
206 - $res = $dbr->select( 'cn_notices', 'not_name', null, __METHOD__ );
207 - $notices = array();
208 - foreach ( $res as $row ) {
209 - $notices[] = $row->not_name;
210 - }
211 - return $notices;
212 - }
213 -
214 - /**
215 - * Build a table row. Needed since Xml::buildTableRow escapes all HTML.
216 - */
217 - function tableRow( $fields, $element = 'td', $attribs = array() ) {
218 - $cells = array();
219 - foreach ( $fields as $field ) {
220 - $cells[] = Xml::tags( $element, array(), $field );
221 - }
222 - return Xml::tags( 'tr', $attribs, implode( "\n", $cells ) ) . "\n";
223 - }
224 -
225 - function dateSelector( $prefix, $timestamp = null ) {
226 - if ( $this->editable ) {
227 - // Default ranges...
228 - $years = range( 2008, 2014 );
229 - $months = range( 1, 12 );
230 - $months = array_map( array( $this, 'addZero' ), $months );
231 - $days = range( 1 , 31 );
232 - $days = array_map( array( $this, 'addZero' ), $days );
233 -
234 - // Normalize timestamp format. If no timestamp passed, defaults to now.
235 - $ts = wfTimestamp( TS_MW, $timestamp );
236 -
237 - $fields = array(
238 - array( "month", "centralnotice-month", $months, substr( $ts, 4, 2 ) ),
239 - array( "day", "centralnotice-day", $days, substr( $ts, 6, 2 ) ),
240 - array( "year", "centralnotice-year", $years, substr( $ts, 0, 4 ) ),
241 - );
242 -
243 - return $this->genSelector( $prefix, $fields );
244 - } else {
245 - global $wgLang;
246 - return $wgLang->date( $timestamp );
247 - }
248 - }
249 -
250 - function timeSelector( $prefix, $timestamp = null ) {
251 - if ( $this->editable ) {
252 - // Default ranges...
253 - $minutes = range( 0, 59 ); // formerly in 15-minute increments
254 - $minutes = array_map( array( $this, 'addZero' ), $minutes );
255 - $hours = range( 0 , 23 );
256 - $hours = array_map( array( $this, 'addZero' ), $hours );
257 -
258 - // Normalize timestamp format...
259 - $ts = wfTimestamp( TS_MW, $timestamp );
260 -
261 - $fields = array(
262 - array( "hour", "centralnotice-hours", $hours, substr( $ts, 8, 2 ) ),
263 - array( "min", "centralnotice-min", $minutes, substr( $ts, 10, 2 ) ),
264 - );
265 -
266 - return $this->genSelector( $prefix, $fields );
267 - } else {
268 - global $wgLang;
269 - return $wgLang->time( $timestamp );
270 - }
271 - }
272 -
273 - private function genSelector( $prefix, $fields ) {
274 - $out = '';
275 - foreach ( $fields as $data ) {
276 - list( $field, $label, $set, $current ) = $data;
277 - $out .= Xml::listDropDown( "{$prefix}[{$field}]",
278 - $this->dropDownList( wfMsg( $label ), $set ),
279 - '',
280 - $current );
281 - }
282 - return $out;
283 - }
284 -
285 - /**
286 - * Show all campaigns found in the database, show "Add a campaign" form
287 - */
288 - function listNotices() {
289 - global $wgOut, $wgUser, $wgLang, $wgRequest, $wgNoticeProjects;
290 -
291 - // Get connection
292 - $dbr = wfGetDB( DB_SLAVE );
293 - $sk = $wgUser->getSkin();
294 - if ( $this->editable ) {
295 - $readonly = array();
296 - } else {
297 - $readonly = array( 'disabled' => 'disabled' );
298 - }
299 -
300 - // Get all campaigns from the database
301 - $res = $dbr->select( 'cn_notices',
302 - array(
303 - 'not_name',
304 - 'not_start',
305 - 'not_end',
306 - 'not_enabled',
307 - 'not_preferred',
308 - 'not_locked'
309 - ),
310 - null,
311 - __METHOD__,
312 - array( 'ORDER BY' => 'not_id DESC' )
313 - );
314 -
315 - // Begin building HTML
316 - $htmlOut = '';
317 -
318 - // Begin Manage campaigns fieldset
319 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
320 -
321 - // If there are campaigns to show...
322 - if ( $dbr->numRows( $res ) >= 1 ) {
323 - if ( $this->editable ) {
324 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
325 - }
326 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-manage' ) );
327 -
328 - // Begin table of campaigns
329 - $htmlOut .= Xml::openElement( 'table',
330 - array(
331 - 'cellpadding' => 9,
332 - 'width' => '100%',
333 - 'class' => 'wikitable sortable'
334 - )
335 - );
336 -
337 - // Table headers
338 - $headers = array(
339 - wfMsgHtml( 'centralnotice-notice-name' ),
340 - wfMsgHtml( 'centralnotice-projects' ),
341 - wfMsgHtml( 'centralnotice-languages' ),
342 - wfMsgHtml( 'centralnotice-start-date' ),
343 - wfMsgHtml( 'centralnotice-end-date' ),
344 - wfMsgHtml( 'centralnotice-enabled' ),
345 - wfMsgHtml( 'centralnotice-preferred' ),
346 - wfMsgHtml( 'centralnotice-locked' ),
347 - );
348 - if ( $this->editable ) {
349 - $headers[] = wfMsgHtml( 'centralnotice-remove' );
350 - }
351 - $htmlOut .= $this->tableRow( $headers, 'th' );
352 -
353 - // Table rows
354 - foreach ( $res as $row ) {
355 - $fields = array();
356 -
357 - // Name
358 - $fields[] = $sk->makeLinkObj( $this->getTitle(),
359 - htmlspecialchars( $row->not_name ),
360 - 'method=listNoticeDetail&notice=' . urlencode( $row->not_name ) );
361 -
362 - // Projects
363 - $projects = $this->getNoticeProjects( $row->not_name );
364 - $project_count = count( $projects );
365 - $projectList = '';
366 - if ( $project_count > 1 ) {
367 - $allProjects = true;
368 - foreach ( $wgNoticeProjects as $project ) {
369 - if ( !in_array( $project, $projects ) ) {
370 - $allProjects = false;
371 - break;
372 - }
373 - }
374 - if ( $allProjects ) {
375 - $projectList = wfMsg ( 'centralnotice-all-projects' );
376 - } else {
377 - $projectList = wfMsg ( 'centralnotice-multiple', $project_count );
378 - }
379 - } elseif ( $project_count == 1 ) {
380 - $projectList = htmlspecialchars( $projects[0] );
381 - }
382 - $fields[] = $projectList;
383 -
384 - // Languages
385 - $project_langs = $this->getNoticeLanguages( $row->not_name );
386 - $language_count = count( $project_langs );
387 - $languageList = '';
388 - if ( $language_count > 3 ) {
389 - $languageList = wfMsg ( 'centralnotice-multiple', $language_count );
390 - } elseif ( $language_count > 0 ) {
391 - $languageList = $wgLang->commaList( $project_langs );
392 - }
393 - $fields[] = $languageList;
394 -
395 - // Date and time calculations
396 - $start_timestamp = wfTimestamp( TS_MW, $row->not_start );
397 - $start_year = substr( $start_timestamp, 0 , 4 );
398 - $start_month = substr( $start_timestamp, 4, 2 );
399 - $start_day = substr( $start_timestamp, 6, 2 );
400 - $start_hour = substr( $start_timestamp, 8, 2 );
401 - $start_min = substr( $start_timestamp, 10, 2 );
402 - $end_timestamp = wfTimestamp( TS_MW, $row->not_end );
403 - $end_year = substr( $end_timestamp, 0 , 4 );
404 - $end_month = substr( $end_timestamp, 4, 2 );
405 - $end_day = substr( $end_timestamp, 6, 2 );
406 - $end_hour = substr( $end_timestamp, 8, 2 );
407 - $end_min = substr( $end_timestamp, 10, 2 );
408 -
409 - // Start
410 - $fields[] = "{$start_year}/{$start_month}/{$start_day} {$start_hour}:{$start_min}";
411 -
412 - // End
413 - $fields[] = "{$end_year}/{$end_month}/{$end_day} {$end_hour}:{$end_min}";
414 -
415 - // Enabled
416 - $fields[] =
417 - Xml::check( 'enabled[]', ( $row->not_enabled == '1' ),
418 - wfArrayMerge( $readonly,
419 - array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
420 -
421 - // Preferred
422 - $fields[] =
423 - Xml::check( 'preferred[]', ( $row->not_preferred == '1' ),
424 - wfArrayMerge( $readonly,
425 - array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
426 -
427 - // Locked
428 - $fields[] =
429 - Xml::check( 'locked[]', ( $row->not_locked == '1' ),
430 - wfArrayMerge( $readonly,
431 - array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
432 -
433 - if ( $this->editable ) {
434 - // Remove
435 - $fields[] = Xml::check( 'removeNotices[]', false,
436 - array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) );
437 - }
438 -
439 - // If campaign is currently active, set special class on table row.
440 - $attribs = array();
441 - if ( wfTimestamp() > wfTimestamp( TS_UNIX , $row->not_start )
442 - && wfTimestamp() < wfTimestamp( TS_UNIX , $row->not_end )
443 - && $row->not_enabled == '1' )
444 - {
445 - $attribs = array( 'class' => 'cn-active-campaign' );
446 - }
447 -
448 - $htmlOut .= $this->tableRow( $fields, 'td', $attribs );
449 - }
450 - // End table of campaigns
451 - $htmlOut .= Xml::closeElement( 'table' );
452 -
453 - if ( $this->editable ) {
454 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
455 - $htmlOut .= Xml::openElement( 'div', array( 'class' => 'cn-buttons' ) );
456 - $htmlOut .= Xml::submitButton( wfMsg( 'centralnotice-modify' ),
457 - array(
458 - 'id' => 'centralnoticesubmit',
459 - 'name' => 'centralnoticesubmit'
460 - )
461 - );
462 - $htmlOut .= Xml::closeElement( 'div' );
463 - $htmlOut .= Xml::closeElement( 'form' );
464 - }
465 -
466 - // No campaigns to show
467 - } else {
468 - $htmlOut .= wfMsg( 'centralnotice-no-notices-exist' );
469 - }
470 -
471 - // End Manage Campaigns fieldset
472 - $htmlOut .= Xml::closeElement( 'fieldset' );
473 -
474 - if ( $this->editable ) {
475 -
476 - // If there was an error, we'll need to restore the state of the form
477 - if ( $wgRequest->wasPosted() && ( $wgRequest->getVal( 'method' ) == 'addNotice' ) ) {
478 - $startArray = $wgRequest->getArray( 'start' );
479 - $startTimestamp = $startArray['year'] .
480 - $startArray['month'] .
481 - $startArray['day'] .
482 - $startArray['hour'] .
483 - $startArray['min'] . '00'
484 - ;
485 - $noticeProjects = $wgRequest->getArray( 'projects', array() );
486 - $noticeLanguages = $wgRequest->getArray( 'project_languages', array() );
487 - } else { // Defaults
488 - $startTimestamp = null;
489 - $noticeProjects = array();
490 - $noticeLanguages = array();
491 - }
492 -
493 - // Begin Add a campaign fieldset
494 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
495 -
496 - // Form for adding a campaign
497 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
498 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-add-notice' ) );
499 - $htmlOut .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
500 - $htmlOut .= Html::hidden( 'method', 'addNotice' );
501 -
502 - $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
503 -
504 - // Name
505 - $htmlOut .= Xml::openElement( 'tr' );
506 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-notice-name' ) );
507 - $htmlOut .= Xml::tags( 'td', array(),
508 - Xml::input( 'noticeName', 25, $wgRequest->getVal( 'noticeName' ) ) );
509 - $htmlOut .= Xml::closeElement( 'tr' );
510 - // Start Date
511 - $htmlOut .= Xml::openElement( 'tr' );
512 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-date' ) );
513 - $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'start', $startTimestamp ) );
514 - $htmlOut .= Xml::closeElement( 'tr' );
515 - // Start Time
516 - $htmlOut .= Xml::openElement( 'tr' );
517 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-time' ) );
518 - $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'start', $startTimestamp ) );
519 - $htmlOut .= Xml::closeElement( 'tr' );
520 - // Project
521 - $htmlOut .= Xml::openElement( 'tr' );
522 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
523 - wfMsgHtml( 'centralnotice-projects' ) );
524 - $htmlOut .= Xml::tags( 'td', array(), $this->projectMultiSelector( $noticeProjects ) );
525 - $htmlOut .= Xml::closeElement( 'tr' );
526 - // Languages
527 - $htmlOut .= Xml::openElement( 'tr' );
528 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
529 - wfMsgHtml( 'centralnotice-languages' ) );
530 - $htmlOut .= Xml::tags( 'td', array(),
531 - $this->languageMultiSelector( $noticeLanguages ) );
532 - $htmlOut .= Xml::closeElement( 'tr' );
533 - // Countries
534 - $htmlOut .= Xml::openElement( 'tr' );
535 - $htmlOut .= Xml::tags( 'td', array(),
536 - Xml::label( wfMsg( 'centralnotice-geotargeted' ), 'geotargeted' ) );
537 - $htmlOut .= Xml::tags( 'td', array(),
538 - Xml::check( 'geotargeted', false,
539 - wfArrayMerge( $readonly, array( 'value' => 1, 'id' => 'geotargeted' ) ) ) );
540 - $htmlOut .= Xml::closeElement( 'tr' );
541 - $htmlOut .= Xml::openElement( 'tr',
542 - array( 'id'=>'geoMultiSelector', 'style'=>'display:none;' ) );
543 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
544 - wfMsgHtml( 'centralnotice-countries' ) );
545 - $htmlOut .= Xml::tags( 'td', array(), $this->geoMultiSelector() );
546 - $htmlOut .= Xml::closeElement( 'tr' );
547 -
548 - $htmlOut .= Xml::closeElement( 'table' );
549 - $htmlOut .= Html::hidden( 'change', 'weight' );
550 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
551 -
552 - // Submit button
553 - $htmlOut .= Xml::tags( 'div',
554 - array( 'class' => 'cn-buttons' ),
555 - Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
556 - );
557 -
558 - $htmlOut .= Xml::closeElement( 'form' );
559 -
560 - // End Add a campaign fieldset
561 - $htmlOut .= Xml::closeElement( 'fieldset' );
562 - }
563 -
564 - // Output HTML
565 - $wgOut->addHTML( $htmlOut );
566 - }
567 -
568 - /**
569 - * Show the interface for viewing/editing an individual campaign
570 - * @param $notice The name of the campaign to view
571 - */
572 - function listNoticeDetail( $notice ) {
573 - global $wgOut, $wgRequest, $wgUser;
574 -
575 - // Make sure notice exists
576 - if ( !$this->noticeExists( $notice ) ) {
577 - $this->showError( 'centralnotice-notice-doesnt-exist' );
578 - } else {
579 -
580 - // Handle form submissions from campaign detail interface
581 - if ( $this->editable && $wgRequest->wasPosted() ) {
582 -
583 - // Check authentication token
584 - if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
585 -
586 - // Handle removing campaign
587 - if ( $wgRequest->getVal( 'remove' ) ) {
588 - $this->removeNotice( $notice );
589 - if ( !$this->centralNoticeError ) {
590 - // Leave campaign detail interface
591 - $wgOut->redirect( $this->getTitle()->getLocalUrl() );
592 - return;
593 - }
594 - }
595 -
596 - // Handle locking/unlocking campaign
597 - if ( $wgRequest->getCheck( 'locked' ) ) {
598 - $this->updateLock( $notice, '1' );
599 - } else {
600 - $this->updateLock( $notice, 0 );
601 - }
602 -
603 - // Handle enabling/disabling campaign
604 - if ( $wgRequest->getCheck( 'enabled' ) ) {
605 - $this->updateEnabled( $notice, '1' );
606 - } else {
607 - $this->updateEnabled( $notice, 0 );
608 - }
609 -
610 - // Handle setting campaign to preferred/not preferred
611 - if ( $wgRequest->getCheck( 'preferred' ) ) {
612 - $this->updatePreferred( $notice, '1' );
613 - } else {
614 - $this->updatePreferred( $notice, 0 );
615 - }
616 -
617 - // Handle updating geotargeting
618 - if ( $wgRequest->getCheck( 'geotargeted' ) ) {
619 - $this->updateGeotargeted( $notice, 1 );
620 - $countries = $wgRequest->getArray( 'geo_countries' );
621 - if ( $countries ) {
622 - $this->updateCountries( $notice, $countries );
623 - }
624 - } else {
625 - $this->updateGeotargeted( $notice, 0 );
626 - }
627 -
628 - // Handle updating the start and end settings
629 - $start = $wgRequest->getArray( 'start' );
630 - $end = $wgRequest->getArray( 'end' );
631 - if ( $start && $end ) {
632 - $updatedStart = sprintf( "%04d%02d%02d%02d%02d00",
633 - $start['year'],
634 - $start['month'],
635 - $start['day'],
636 - $start['hour'],
637 - $start['min']
638 - );
639 - $updatedEnd = sprintf( "%04d%02d%02d%02d%02d00",
640 - $end['year'],
641 - $end['month'],
642 - $end['day'],
643 - $end['hour'],
644 - $end['min']
645 - );
646 -
647 - $this->updateNoticeDate( $notice, $updatedStart, $updatedEnd );
648 - }
649 -
650 - // Handle adding of banners to the campaign
651 - $templatesToAdd = $wgRequest->getArray( 'addTemplates' );
652 - if ( $templatesToAdd ) {
653 - $weight = $wgRequest->getArray( 'weight' );
654 - foreach ( $templatesToAdd as $templateName ) {
655 - $templateId = $this->getTemplateId( $templateName );
656 - $this->addTemplateTo( $notice, $templateName, $weight[$templateId] );
657 - }
658 - }
659 -
660 - // Handle removing of banners from the campaign
661 - $templateToRemove = $wgRequest->getArray( 'removeTemplates' );
662 - if ( $templateToRemove ) {
663 - foreach ( $templateToRemove as $template ) {
664 - $this->removeTemplateFor( $notice, $template );
665 - }
666 - }
667 -
668 - // Handle weight changes
669 - $updatedWeights = $wgRequest->getArray( 'weight' );
670 - if ( $updatedWeights ) {
671 - foreach ( $updatedWeights as $templateId => $weight ) {
672 - $this->updateWeight( $notice, $templateId, $weight );
673 - }
674 - }
675 -
676 - // Handle new projects
677 - $projects = $wgRequest->getArray( 'projects' );
678 - if ( $projects ) {
679 - $this->updateProjects( $notice, $projects );
680 - }
681 -
682 - // Handle new project languages
683 - $projectLangs = $wgRequest->getArray( 'project_languages' );
684 - if ( $projectLangs ) {
685 - $this->updateProjectLanguages( $notice, $projectLangs );
686 - }
687 -
688 - // If there were no errors, reload the page to prevent duplicate form submission
689 - if ( !$this->centralNoticeError ) {
690 - $wgOut->redirect( $this->getTitle()->getLocalUrl(
691 - "method=listNoticeDetail&notice=$notice" ) );
692 - return;
693 - }
694 - } else {
695 - $this->showError( 'sessionfailure' );
696 - }
697 -
698 - }
699 -
700 - $htmlOut = '';
701 -
702 - // Begin Campaign detail fieldset
703 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
704 -
705 - if ( $this->editable ) {
706 - $htmlOut .= Xml::openElement( 'form',
707 - array(
708 - 'method' => 'post',
709 - 'action' => $this->getTitle()->getLocalUrl(
710 - "method=listNoticeDetail&notice=$notice" )
711 - )
712 - );
713 - }
714 -
715 - $output_detail = $this->noticeDetailForm( $notice );
716 - $output_assigned = $this->assignedTemplatesForm( $notice );
717 - $output_templates = $this->addTemplatesForm( $notice );
718 -
719 - $htmlOut .= $output_detail;
720 -
721 - // Catch for no banners so that we don't double message
722 - if ( $output_assigned == '' && $output_templates == '' ) {
723 - $htmlOut .= wfMsg( 'centralnotice-no-templates' );
724 - $htmlOut .= Xml::element( 'p' );
725 - $newPage = $this->getTitleFor( 'NoticeTemplate', 'add' );
726 - $sk = $wgUser->getSkin();
727 - $htmlOut .= $sk->makeLinkObj( $newPage, wfMsgHtml( 'centralnotice-add-template' ) );
728 - $htmlOut .= Xml::element( 'p' );
729 - } elseif ( $output_assigned == '' ) {
730 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-assigned-templates' ) );
731 - $htmlOut .= wfMsg( 'centralnotice-no-templates-assigned' );
732 - $htmlOut .= Xml::closeElement( 'fieldset' );
733 - if ( $this->editable ) {
734 - $htmlOut .= $output_templates;
735 - }
736 - } else {
737 - $htmlOut .= $output_assigned;
738 - if ( $this->editable ) {
739 - $htmlOut .= $output_templates;
740 - }
741 - }
742 - if ( $this->editable ) {
743 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
744 -
745 - // Submit button
746 - $htmlOut .= Xml::tags( 'div',
747 - array( 'class' => 'cn-buttons' ),
748 - Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
749 - );
750 - }
751 -
752 - if ( $this->editable ) {
753 - $htmlOut .= Xml::closeElement( 'form' );
754 - }
755 - $htmlOut .= Xml::closeElement( 'fieldset' );
756 - $wgOut->addHTML( $htmlOut );
757 - }
758 - }
759 -
760 - /**
761 - * Create form for managing campaign settings (start date, end date, languages, etc.)
762 - */
763 - function noticeDetailForm( $notice ) {
764 - global $wgRequest;
765 -
766 - if ( $this->editable ) {
767 - $readonly = array();
768 - } else {
769 - $readonly = array( 'disabled' => 'disabled' );
770 - }
771 - $dbr = wfGetDB( DB_SLAVE );
772 -
773 - // Get campaign info from database
774 - $row = $dbr->selectRow( 'cn_notices',
775 - array(
776 - 'not_id',
777 - 'not_name',
778 - 'not_start',
779 - 'not_end',
780 - 'not_enabled',
781 - 'not_preferred',
782 - 'not_locked',
783 - 'not_geo'
784 - ),
785 - array( 'not_name' => $notice ),
786 - __METHOD__
787 - );
788 -
789 - if ( $row ) {
790 -
791 - // If there was an error, we'll need to restore the state of the form
792 - if ( $wgRequest->wasPosted() ) {
793 - $startArray = $wgRequest->getArray( 'start' );
794 - $startTimestamp = $startArray['year'] .
795 - $startArray['month'] .
796 - $startArray['day'] .
797 - $startArray['hour'] .
798 - $startArray['min'] . '00'
799 - ;
800 - $endArray = $wgRequest->getArray( 'end' );
801 - $endTimestamp = $endArray['year'] .
802 - $endArray['month'] .
803 - $endArray['day'] .
804 - $endArray['hour'] .
805 - $endArray['min'] .'00'
806 - ;
807 - $isEnabled = $wgRequest->getCheck( 'enabled' );
808 - $isPreferred = $wgRequest->getCheck( 'preferred' );
809 - $isLocked = $wgRequest->getCheck( 'locked' );
810 - $noticeProjects = $wgRequest->getArray( 'projects', array() );
811 - $noticeLanguages = $wgRequest->getArray( 'project_languages', array() );
812 - $isGeotargeted = $wgRequest->getCheck( 'geotargeted' );
813 - $countries = $wgRequest->getArray( 'geo_countries', array() );
814 - } else { // Defaults
815 - $startTimestamp = $row->not_start;
816 - $endTimestamp = $row->not_end;
817 - $isEnabled = ( $row->not_enabled == '1' );
818 - $isPreferred = ( $row->not_preferred == '1' );
819 - $isLocked = ( $row->not_locked == '1' );
820 - $noticeProjects = $this->getNoticeProjects( $notice );
821 - $noticeLanguages = $this->getNoticeLanguages( $notice );
822 - $isGeotargeted = ( $row->not_geo == '1' );
823 - $countries = $this->getNoticeCountries( $notice );
824 - }
825 -
826 - // Build Html
827 - $htmlOut = '';
828 - $htmlOut .= Xml::tags( 'h2', null, wfMsg( 'centralnotice-notice-heading', $notice ) );
829 - $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
830 -
831 - // Rows
832 - // Start Date
833 - $htmlOut .= Xml::openElement( 'tr' );
834 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-date' ) );
835 - $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'start', $startTimestamp ) );
836 - $htmlOut .= Xml::closeElement( 'tr' );
837 - // Start Time
838 - $htmlOut .= Xml::openElement( 'tr' );
839 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-time' ) );
840 - $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'start', $startTimestamp ) );
841 - $htmlOut .= Xml::closeElement( 'tr' );
842 - // End Date
843 - $htmlOut .= Xml::openElement( 'tr' );
844 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-end-date' ) );
845 - $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'end', $endTimestamp ) );
846 - $htmlOut .= Xml::closeElement( 'tr' );
847 - // End Time
848 - $htmlOut .= Xml::openElement( 'tr' );
849 - $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-end-time' ) );
850 - $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'end', $endTimestamp ) );
851 - $htmlOut .= Xml::closeElement( 'tr' );
852 - // Project
853 - $htmlOut .= Xml::openElement( 'tr' );
854 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
855 - wfMsgHtml( 'centralnotice-projects' ) );
856 - $htmlOut .= Xml::tags( 'td', array(),
857 - $this->projectMultiSelector( $noticeProjects ) );
858 - $htmlOut .= Xml::closeElement( 'tr' );
859 - // Languages
860 - $htmlOut .= Xml::openElement( 'tr' );
861 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
862 - wfMsgHtml( 'centralnotice-languages' ) );
863 - $htmlOut .= Xml::tags( 'td', array(),
864 - $this->languageMultiSelector( $noticeLanguages ) );
865 - $htmlOut .= Xml::closeElement( 'tr' );
866 - // Countries
867 - $htmlOut .= Xml::openElement( 'tr' );
868 - $htmlOut .= Xml::tags( 'td', array(),
869 - Xml::label( wfMsg( 'centralnotice-geotargeted' ), 'geotargeted' ) );
870 - $htmlOut .= Xml::tags( 'td', array(),
871 - Xml::check( 'geotargeted', $isGeotargeted,
872 - wfArrayMerge(
873 - $readonly,
874 - array( 'value' => $row->not_name, 'id' => 'geotargeted' ) ) ) );
875 - $htmlOut .= Xml::closeElement( 'tr' );
876 - if ( $isGeotargeted ) {
877 - $htmlOut .= Xml::openElement( 'tr', array( 'id'=>'geoMultiSelector' ) );
878 - } else {
879 - $htmlOut .= Xml::openElement( 'tr',
880 - array( 'id'=>'geoMultiSelector', 'style'=>'display:none;' ) );
881 - }
882 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
883 - wfMsgHtml( 'centralnotice-countries' ) );
884 - $htmlOut .= Xml::tags( 'td', array(), $this->geoMultiSelector( $countries ) );
885 - $htmlOut .= Xml::closeElement( 'tr' );
886 - // Enabled
887 - $htmlOut .= Xml::openElement( 'tr' );
888 - $htmlOut .= Xml::tags( 'td', array(),
889 - Xml::label( wfMsg( 'centralnotice-enabled' ), 'enabled' ) );
890 - $htmlOut .= Xml::tags( 'td', array(),
891 - Xml::check( 'enabled', $isEnabled,
892 - wfArrayMerge( $readonly,
893 - array( 'value' => $row->not_name, 'id' => 'enabled' ) ) ) );
894 - $htmlOut .= Xml::closeElement( 'tr' );
895 - // Preferred
896 - $htmlOut .= Xml::openElement( 'tr' );
897 - $htmlOut .= Xml::tags( 'td', array(),
898 - Xml::label( wfMsg( 'centralnotice-preferred' ), 'preferred' ) );
899 - $htmlOut .= Xml::tags( 'td', array(),
900 - Xml::check( 'preferred', $isPreferred,
901 - wfArrayMerge( $readonly,
902 - array( 'value' => $row->not_name, 'id' => 'preferred' ) ) ) );
903 - $htmlOut .= Xml::closeElement( 'tr' );
904 - // Locked
905 - $htmlOut .= Xml::openElement( 'tr' );
906 - $htmlOut .= Xml::tags( 'td', array(),
907 - Xml::label( wfMsg( 'centralnotice-locked' ), 'locked' ) );
908 - $htmlOut .= Xml::tags( 'td', array(),
909 - Xml::check( 'locked', $isLocked,
910 - wfArrayMerge( $readonly,
911 - array( 'value' => $row->not_name, 'id' => 'locked' ) ) ) );
912 - $htmlOut .= Xml::closeElement( 'tr' );
913 - if ( $this->editable ) {
914 - // Locked
915 - $htmlOut .= Xml::openElement( 'tr' );
916 - $htmlOut .= Xml::tags( 'td', array(),
917 - Xml::label( wfMsg( 'centralnotice-remove' ), 'remove' ) );
918 - $htmlOut .= Xml::tags( 'td', array(),
919 - Xml::check( 'remove', false,
920 - array( 'value' => $row->not_name, 'id' => 'remove' ) ) );
921 - $htmlOut .= Xml::closeElement( 'tr' );
922 - }
923 - $htmlOut .= Xml::closeElement( 'table' );
924 - return $htmlOut;
925 - } else {
926 - return '';
927 - }
928 - }
929 -
930 - /**
931 - * Create form for managing banners assigned to a campaign
932 - */
933 - function assignedTemplatesForm( $notice ) {
934 - global $wgUser;
935 - $sk = $wgUser->getSkin();
936 -
937 - $dbr = wfGetDB( DB_SLAVE );
938 - $res = $dbr->select(
939 - array(
940 - 'cn_notices',
941 - 'cn_assignments',
942 - 'cn_templates'
943 - ),
944 - array(
945 - 'cn_templates.tmp_id',
946 - 'cn_templates.tmp_name',
947 - 'cn_assignments.tmp_weight'
948 - ),
949 - array(
950 - 'cn_notices.not_name' => $notice,
951 - 'cn_notices.not_id = cn_assignments.not_id',
952 - 'cn_assignments.tmp_id = cn_templates.tmp_id'
953 - ),
954 - __METHOD__,
955 - array( 'ORDER BY' => 'cn_notices.not_id' )
956 - );
957 -
958 - // No banners found
959 - if ( $dbr->numRows( $res ) < 1 ) {
960 - return;
961 - }
962 -
963 - // Build Assigned banners HTML
964 - $htmlOut = Html::hidden( 'change', 'weight' );
965 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-assigned-templates' ) );
966 - $htmlOut .= Xml::openElement( 'table',
967 - array(
968 - 'cellpadding' => 9,
969 - 'width' => '100%'
970 - )
971 - );
972 - if ( $this->editable ) {
973 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
974 - wfMsg ( "centralnotice-remove" ) );
975 - }
976 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
977 - wfMsg ( "centralnotice-weight" ) );
978 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '70%' ),
979 - wfMsg ( "centralnotice-templates" ) );
980 -
981 - // Table rows
982 - foreach( $res as $row ) {
983 -
984 - $htmlOut .= Xml::openElement( 'tr' );
985 -
986 - if ( $this->editable ) {
987 - // Remove
988 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
989 - Xml::check( 'removeTemplates[]', false, array( 'value' => $row->tmp_name ) )
990 - );
991 - }
992 -
993 - // Weight
994 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
995 - $this->weightDropDown( "weight[$row->tmp_id]", $row->tmp_weight )
996 - );
997 -
998 - $viewPage = $this->getTitleFor( 'NoticeTemplate', 'view' );
999 - $render = new SpecialBannerLoader();
1000 - $render->siteName = 'Wikipedia';
1001 - global $wgRequest;
1002 - $render->language = $wgRequest->getVal( 'wpUserLanguage' );
1003 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
1004 - $sk->makeLinkObj( $viewPage,
1005 - htmlspecialchars( $row->tmp_name ),
1006 - 'template=' . urlencode( $row->tmp_name ) ) .
1007 - Xml::fieldset( wfMsg( 'centralnotice-preview' ),
1008 - $render->getHtmlNotice( $row->tmp_name ),
1009 - array( 'class' => 'cn-bannerpreview')
1010 - )
1011 - );
1012 -
1013 - $htmlOut .= Xml::closeElement( 'tr' );
1014 - }
1015 - $htmlOut .= XMl::closeElement( 'table' );
1016 - $htmlOut .= Xml::closeElement( 'fieldset' );
1017 - return $htmlOut;
1018 -
1019 - }
1020 -
1021 - function weightDropDown( $name, $selected ) {
1022 - if ( $this->editable ) {
1023 - return Xml::listDropDown( $name,
1024 - $this->dropDownList( wfMsg( 'centralnotice-weight' ),
1025 - range ( 0, 100, 5 ) ),
1026 - '',
1027 - $selected,
1028 - '',
1029 - 1 );
1030 - } else {
1031 - return htmlspecialchars( $selected );
1032 - }
1033 - }
1034 -
1035 - /**
1036 - * Create form for adding banners to a campaign
1037 - */
1038 - function addTemplatesForm( $notice ) {
1039 - $pager = new CentralNoticePager( $this );
1040 - $dbr = wfGetDB( DB_SLAVE );
1041 - $res = $dbr->select( 'cn_templates', 'tmp_name', '', '', array( 'ORDER BY' => 'tmp_id' ) );
1042 -
1043 - if ( $dbr->numRows( $res ) > 0 ) {
1044 - // Build HTML
1045 - $htmlOut = Xml::fieldset( wfMsg( "centralnotice-available-templates" ) );
1046 -
1047 - // Show paginated list of banners
1048 - $htmlOut .= Xml::tags( 'div',
1049 - array( 'class' => 'cn-pager' ),
1050 - $pager->getNavigationBar() );
1051 - $htmlOut .= $pager->getBody();
1052 - $htmlOut .= Xml::tags( 'div',
1053 - array( 'class' => 'cn-pager' ),
1054 - $pager->getNavigationBar() );
1055 -
1056 - $htmlOut .= Xml::closeElement( 'fieldset' );
1057 - } else {
1058 - // Nothing found
1059 - return;
1060 - }
1061 - return $htmlOut;
1062 - }
1063 -
1064 - /**
1065 - * Lookup function for active banners under a given language/project/location. This function is
1066 - * called by SpecialBannerListLoader::getJsonList() in order to build the banner list JSON for
1067 - * each project.
1068 - * @return A 2D array of running banners with associated weights and settings
1069 - */
1070 - static function selectNoticeTemplates( $project, $language, $location = null ) {
1071 - global $wgCentralDBname;
1072 -
1073 - $campaigns = array();
1074 - $dbr = wfGetDB( DB_SLAVE, array(), $wgCentralDBname );
1075 - $encTimestamp = $dbr->addQuotes( $dbr->timestamp() );
1076 -
1077 - // Pull non-geotargeted campaigns
1078 - $campaignResults1 = $dbr->select(
1079 - array(
1080 - 'cn_notices',
1081 - 'cn_notice_projects',
1082 - 'cn_notice_languages'
1083 - ),
1084 - array(
1085 - 'not_id'
1086 - ),
1087 - array(
1088 - "not_start <= $encTimestamp",
1089 - "not_end >= $encTimestamp",
1090 - 'not_enabled = 1', // enabled
1091 - 'not_geo = 0', // not geotargeted
1092 - 'np_notice_id = cn_notices.not_id',
1093 - 'np_project' => $project,
1094 - 'nl_notice_id = cn_notices.not_id',
1095 - 'nl_language' => $language
1096 - ),
1097 - __METHOD__
1098 - );
1099 - foreach ( $campaignResults1 as $row ) {
1100 - $campaigns[] = $row->not_id;
1101 - }
1102 - if ( $location ) {
1103 -
1104 - // Normalize location parameter (should be an uppercase 2-letter country code)
1105 - preg_match( '/[a-zA-Z][a-zA-Z]/', $location, $matches );
1106 - if ( $matches ) {
1107 - $location = strtoupper( $matches[0] );
1108 -
1109 - // Pull geotargeted campaigns
1110 - $campaignResults2 = $dbr->select(
1111 - array(
1112 - 'cn_notices',
1113 - 'cn_notice_projects',
1114 - 'cn_notice_languages',
1115 - 'cn_notice_countries'
1116 - ),
1117 - array(
1118 - 'not_id'
1119 - ),
1120 - array(
1121 - "not_start <= $encTimestamp",
1122 - "not_end >= $encTimestamp",
1123 - 'not_enabled = 1', // enabled
1124 - 'not_geo = 1', // geotargeted
1125 - 'nc_notice_id = cn_notices.not_id',
1126 - 'nc_country' => $location,
1127 - 'np_notice_id = cn_notices.not_id',
1128 - 'np_project' => $project,
1129 - 'nl_notice_id = cn_notices.not_id',
1130 - 'nl_language' => $language
1131 - ),
1132 - __METHOD__
1133 - );
1134 - foreach ( $campaignResults2 as $row ) {
1135 - $campaigns[] = $row->not_id;
1136 - }
1137 - }
1138 - }
1139 -
1140 - $templates = array();
1141 - if ( $campaigns ) {
1142 - // Pull all banners assigned to the campaigns
1143 - $templates = CentralNoticeDB::selectTemplatesAssigned( $campaigns );
1144 - }
1145 - return $templates;
1146 - }
1147 -
1148 - function addNotice( $noticeName, $enabled, $start, $projects,
1149 - $project_languages, $geotargeted, $geo_countries )
1150 - {
1151 - if ( $this->noticeExists( $noticeName ) ) {
1152 - $this->showError( 'centralnotice-notice-exists' );
1153 - return;
1154 - } elseif ( empty( $projects ) ) {
1155 - $this->showError( 'centralnotice-no-project' );
1156 - return;
1157 - } elseif ( empty( $project_languages ) ) {
1158 - $this->showError( 'centralnotice-no-language' );
1159 - return;
1160 - } else {
1161 - $dbw = wfGetDB( DB_MASTER );
1162 - $dbw->begin();
1163 - $start['hour'] = substr( $start['hour'], 0 , 2 );
1164 - $start['min'] = substr( $start['min'], 0 , 2 );
1165 - if ( $start['month'] == 12 ) {
1166 - $end['month'] = '01';
1167 - $end['year'] = ( $start['year'] + 1 );
1168 - } elseif ( $start['month'] == '09' ) {
1169 - $end['month'] = '10';
1170 - $end['year'] = $start['year'];
1171 - } else {
1172 - $end['month'] =
1173 - ( substr( $start['month'], 0, 1 ) ) == 0
1174 - ? 0 . ( intval( $start['month'] ) + 1 )
1175 - : ( $start['month'] + 1 );
1176 - $end['year'] = $start['year'];
1177 - }
1178 -
1179 - $startTs = wfTimeStamp( TS_MW, "{$start['year']}:{$start['month']}:{$start['day']} " .
1180 - "{$start['hour']}:{$start['min']}:00" );
1181 - $endTs = wfTimeStamp( TS_MW, "{$end['year']}:{$end['month']}:{$start['day']} " .
1182 - "{$start['hour']}:{$start['min']}:00" );
1183 -
1184 - $res = $dbw->insert( 'cn_notices',
1185 - array( 'not_name' => $noticeName,
1186 - 'not_enabled' => $enabled,
1187 - 'not_start' => $dbw->timestamp( $startTs ),
1188 - 'not_end' => $dbw->timestamp( $endTs ),
1189 - 'not_geo' => $geotargeted
1190 - )
1191 - );
1192 - $not_id = $dbw->insertId();
1193 -
1194 - // Do multi-row insert for campaign projects
1195 - $insertArray = array();
1196 - foreach( $projects as $project ) {
1197 - $insertArray[] = array( 'np_notice_id' => $not_id, 'np_project' => $project );
1198 - }
1199 - $res = $dbw->insert( 'cn_notice_projects', $insertArray,
1200 - __METHOD__, array( 'IGNORE' ) );
1201 -
1202 - // Do multi-row insert for campaign languages
1203 - $insertArray = array();
1204 - foreach( $project_languages as $code ) {
1205 - $insertArray[] = array( 'nl_notice_id' => $not_id, 'nl_language' => $code );
1206 - }
1207 - $res = $dbw->insert( 'cn_notice_languages', $insertArray,
1208 - __METHOD__, array( 'IGNORE' ) );
1209 -
1210 - if ( $geotargeted ) {
1211 - // Do multi-row insert for campaign countries
1212 - $insertArray = array();
1213 - foreach( $geo_countries as $code ) {
1214 - $insertArray[] = array( 'nc_notice_id' => $not_id, 'nc_country' => $code );
1215 - }
1216 - $res = $dbw->insert( 'cn_notice_countries', $insertArray,
1217 - __METHOD__, array( 'IGNORE' ) );
1218 - }
1219 -
1220 - $dbw->commit();
1221 - return;
1222 - }
1223 - }
1224 -
1225 - function removeNotice( $noticeName ) {
1226 - $dbr = wfGetDB( DB_SLAVE );
1227 -
1228 - $res = $dbr->select( 'cn_notices', 'not_name, not_locked',
1229 - array( 'not_name' => $noticeName )
1230 - );
1231 - if ( $dbr->numRows( $res ) < 1 ) {
1232 - $this->showError( 'centralnotice-remove-notice-doesnt-exist' );
1233 - return;
1234 - }
1235 - $row = $dbr->fetchObject( $res );
1236 - if ( $row->not_locked == '1' ) {
1237 - $this->showError( 'centralnotice-notice-is-locked' );
1238 - return;
1239 - } else {
1240 - $dbw = wfGetDB( DB_MASTER );
1241 - $dbw->begin();
1242 - $noticeId = htmlspecialchars( $this->getNoticeId( $noticeName ) );
1243 - $res = $dbw->delete( 'cn_assignments', array ( 'not_id' => $noticeId ) );
1244 - $res = $dbw->delete( 'cn_notices', array ( 'not_name' => $noticeName ) );
1245 - $res = $dbw->delete( 'cn_notice_languages', array ( 'nl_notice_id' => $noticeId ) );
1246 - $dbw->commit();
1247 - return;
1248 - }
1249 - }
1250 -
1251 - function addTemplateTo( $noticeName, $templateName, $weight ) {
1252 - $dbr = wfGetDB( DB_SLAVE );
1253 -
1254 - $eNoticeName = htmlspecialchars ( $noticeName );
1255 - $noticeId = $this->getNoticeId( $eNoticeName );
1256 - $templateId = $this->getTemplateId( $templateName );
1257 - $res = $dbr->select( 'cn_assignments', 'asn_id',
1258 - array(
1259 - 'tmp_id' => $templateId,
1260 - 'not_id' => $noticeId
1261 - )
1262 - );
1263 - if ( $dbr->numRows( $res ) > 0 ) {
1264 - $this->showError( 'centralnotice-template-already-exists' );
1265 - } else {
1266 - $dbw = wfGetDB( DB_MASTER );
1267 - $dbw->begin();
1268 - $noticeId = $this->getNoticeId( $eNoticeName );
1269 - $res = $dbw->insert( 'cn_assignments',
1270 - array(
1271 - 'tmp_id' => $templateId,
1272 - 'tmp_weight' => $weight,
1273 - 'not_id' => $noticeId
1274 - )
1275 - );
1276 - $dbw->commit();
1277 - }
1278 - }
1279 -
1280 - /**
1281 - * Lookup the ID for a campaign based on the campaign name
1282 - */
1283 - public static function getNoticeId( $noticeName ) {
1284 - $dbr = wfGetDB( DB_SLAVE );
1285 - $eNoticeName = htmlspecialchars( $noticeName );
1286 - $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
1287 - if ( $row ) {
1288 - return $row->not_id;
1289 - } else {
1290 - return null;
1291 - }
1292 - }
1293 -
1294 - function getNoticeProjects( $noticeName ) {
1295 - $dbr = wfGetDB( DB_SLAVE );
1296 - $eNoticeName = htmlspecialchars( $noticeName );
1297 - $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
1298 - $projects = array();
1299 - if ( $row ) {
1300 - $res = $dbr->select( 'cn_notice_projects', 'np_project',
1301 - array( 'np_notice_id' => $row->not_id ) );
1302 - foreach ( $res as $projectRow ) {
1303 - $projects[] = $projectRow->np_project;
1304 - }
1305 - }
1306 - return $projects;
1307 - }
1308 -
1309 - function getNoticeLanguages( $noticeName ) {
1310 - $dbr = wfGetDB( DB_SLAVE );
1311 - $eNoticeName = htmlspecialchars( $noticeName );
1312 - $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
1313 - $languages = array();
1314 - if ( $row ) {
1315 - $res = $dbr->select( 'cn_notice_languages', 'nl_language',
1316 - array( 'nl_notice_id' => $row->not_id ) );
1317 - foreach ( $res as $langRow ) {
1318 - $languages[] = $langRow->nl_language;
1319 - }
1320 - }
1321 - return $languages;
1322 - }
1323 -
1324 - function getNoticeCountries( $noticeName ) {
1325 - $dbr = wfGetDB( DB_SLAVE );
1326 - $eNoticeName = htmlspecialchars( $noticeName );
1327 - $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
1328 - $countries = array();
1329 - if ( $row ) {
1330 - $res = $dbr->select( 'cn_notice_countries', 'nc_country',
1331 - array( 'nc_notice_id' => $row->not_id ) );
1332 - foreach ( $res as $countryRow ) {
1333 - $countries[] = $countryRow->nc_country;
1334 - }
1335 - }
1336 - return $countries;
1337 - }
1338 -
1339 - function getNoticeProjectName( $noticeName ) {
1340 - $dbr = wfGetDB( DB_SLAVE );
1341 - $eNoticeName = htmlspecialchars( $noticeName );
1342 - $res = $dbr->select( 'cn_notices', 'not_project', array( 'not_name' => $eNoticeName ) );
1343 - $row = $dbr->fetchObject( $res );
1344 - return $row->not_project;
1345 - }
1346 -
1347 - function getTemplateId( $templateName ) {
1348 - $dbr = wfGetDB( DB_SLAVE );
1349 - $templateName = htmlspecialchars ( $templateName );
1350 - $res = $dbr->select( 'cn_templates', 'tmp_id', array( 'tmp_name' => $templateName ) );
1351 - $row = $dbr->fetchObject( $res );
1352 - return $row->tmp_id;
1353 - }
1354 -
1355 - function removeTemplateFor( $noticeName, $templateName ) {
1356 - $dbw = wfGetDB( DB_MASTER );
1357 - $dbw->begin();
1358 - $noticeId = $this->getNoticeId( $noticeName );
1359 - $templateId = $this->getTemplateId( $templateName );
1360 - $dbw->delete( 'cn_assignments', array ( 'tmp_id' => $templateId, 'not_id' => $noticeId ) );
1361 - $dbw->commit();
1362 - }
1363 -
1364 - function updateNoticeDate( $noticeName, $start, $end ) {
1365 - $dbr = wfGetDB( DB_SLAVE );
1366 -
1367 - // Start/end don't line up
1368 - if ( $start > $end || $end < $start ) {
1369 - $this->showError( 'centralnotice-invalid-date-range' );
1370 - return;
1371 - }
1372 -
1373 - // Invalid campaign name
1374 - if ( !$this->noticeExists( $noticeName ) ) {
1375 - $this->showError( 'centralnotice-notice-doesnt-exist' );
1376 - return;
1377 - }
1378 -
1379 - // Overlap over a date within the same project and language
1380 - $startDate = $dbr->timestamp( $start );
1381 - $endDate = $dbr->timestamp( $end );
1382 -
1383 - $dbw = wfGetDB( DB_MASTER );
1384 - $res = $dbw->update( 'cn_notices',
1385 - array(
1386 - 'not_start' => $startDate,
1387 - 'not_end' => $endDate
1388 - ),
1389 - array( 'not_name' => $noticeName )
1390 - );
1391 - }
1392 -
1393 - /**
1394 - * Update the enabled/disabled state of a campaign
1395 - */
1396 - private function updateEnabled( $noticeName, $isEnabled ) {
1397 - if ( !$this->noticeExists( $noticeName ) ) {
1398 - $this->showError( 'centralnotice-doesnt-exist' );
1399 - } else {
1400 - $dbw = wfGetDB( DB_MASTER );
1401 - $res = $dbw->update( 'cn_notices',
1402 - array( 'not_enabled' => $isEnabled ),
1403 - array( 'not_name' => $noticeName )
1404 - );
1405 - }
1406 - }
1407 -
1408 - /**
1409 - * Update the preferred/not preferred state of a campaign
1410 - */
1411 - function updatePreferred( $noticeName, $isPreferred ) {
1412 - if ( !$this->noticeExists( $noticeName ) ) {
1413 - $this->showError( 'centralnotice-doesnt-exist' );
1414 - } else {
1415 - $dbw = wfGetDB( DB_MASTER );
1416 - $res = $dbw->update( 'cn_notices',
1417 - array( 'not_preferred' => $isPreferred ),
1418 - array( 'not_name' => $noticeName )
1419 - );
1420 - }
1421 - }
1422 -
1423 - /**
1424 - * Update the geotargeted/not geotargeted state of a campaign
1425 - */
1426 - function updateGeotargeted( $noticeName, $isGeotargeted ) {
1427 - if ( !$this->noticeExists( $noticeName ) ) {
1428 - $this->showError( 'centralnotice-doesnt-exist' );
1429 - } else {
1430 - $dbw = wfGetDB( DB_MASTER );
1431 - $res = $dbw->update( 'cn_notices',
1432 - array( 'not_geo' => $isGeotargeted ),
1433 - array( 'not_name' => $noticeName )
1434 - );
1435 - }
1436 - }
1437 -
1438 - /**
1439 - * Update the locked/unlocked state of a campaign
1440 - */
1441 - function updateLock( $noticeName, $isLocked ) {
1442 - if ( !$this->noticeExists( $noticeName ) ) {
1443 - $this->showError( 'centralnotice-doesnt-exist' );
1444 - } else {
1445 - $dbw = wfGetDB( DB_MASTER );
1446 - $res = $dbw->update( 'cn_notices',
1447 - array( 'not_locked' => $isLocked ),
1448 - array( 'not_name' => $noticeName )
1449 - );
1450 - }
1451 - }
1452 -
1453 - function updateWeight( $noticeName, $templateId, $weight ) {
1454 - $dbw = wfGetDB( DB_MASTER );
1455 - $noticeId = $this->getNoticeId( $noticeName );
1456 - $dbw->update( 'cn_assignments',
1457 - array ( 'tmp_weight' => $weight ),
1458 - array(
1459 - 'tmp_id' => $templateId,
1460 - 'not_id' => $noticeId
1461 - )
1462 - );
1463 - }
1464 -
1465 - /**
1466 - * Generates a multiple select list of all languages.
1467 - * @param $selected The language codes of the selected languages
1468 - * @param $customisedOnly If true only languages which have some content are listed
1469 - * @return multiple select list
1470 - */
1471 - function languageMultiSelector( $selected = array(), $customisedOnly = true ) {
1472 - global $wgContLanguageCode, $wgExtensionAssetsPath, $wgLang;
1473 - $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
1474 - // Make sure the site language is in the list; a custom language code
1475 - // might not have a defined name...
1476 - $languages = Language::getLanguageNames( $customisedOnly );
1477 - if( !array_key_exists( $wgContLanguageCode, $languages ) ) {
1478 - $languages[$wgContLanguageCode] = $wgContLanguageCode;
1479 - }
1480 - ksort( $languages );
1481 -
1482 - $options = "\n";
1483 - foreach( $languages as $code => $name ) {
1484 - $options .= Xml::option(
1485 - wfMsg( 'centralnotice-language-listing', $code, $name ),
1486 - $code,
1487 - in_array( $code, $selected )
1488 - ) . "\n";
1489 - }
1490 - $htmlOut = '';
1491 - if ( $this->editable ) {
1492 - $htmlOut .= Xml::tags( 'select',
1493 - array( 'multiple' => 'multiple', 'size' => 4, 'id' => 'project_languages[]', 'name' => 'project_languages[]' ),
1494 - $options
1495 - );
1496 - $buttons = array();
1497 - $buttons[] = '<a href="#" onclick="selectLanguages(true);return false;">' .
1498 - wfMsg( 'powersearch-toggleall' ) . '</a>';
1499 - $buttons[] = '<a href="#" onclick="selectLanguages(false);return false;">' .
1500 - wfMsg( 'powersearch-togglenone' ) . '</a>';
1501 - $buttons[] = '<a href="#" onclick="top10Languages();return false;">' .
1502 - wfMsg( 'centralnotice-top-ten-languages' ) . '</a>';
1503 - $htmlOut .= Xml::tags( 'div',
1504 - array( 'style' => 'margin-top: 0.2em;' ),
1505 - '<img src="'.$scriptPath.'/up-arrow.png" style="vertical-align:baseline;"/>' .
1506 - wfMsg( 'centralnotice-select', $wgLang->commaList( $buttons ) )
1507 - );
1508 - } else {
1509 - $htmlOut .= Xml::tags( 'select',
1510 - array(
1511 - 'multiple' => 'multiple',
1512 - 'size' => 4,
1513 - 'id' => 'project_languages[]',
1514 - 'name' => 'project_languages[]',
1515 - 'disabled' => 'disabled'
1516 - ),
1517 - $options
1518 - );
1519 - }
1520 - return $htmlOut;
1521 - }
1522 -
1523 - /**
1524 - * Generates a multiple select list of all project types.
1525 - * @param $selected The name of the selected project type
1526 - * @return multiple select list
1527 - */
1528 - function projectMultiSelector( $selected = array() ) {
1529 - global $wgNoticeProjects, $wgExtensionAssetsPath, $wgLang;
1530 - $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
1531 -
1532 - $options = "\n";
1533 - foreach( $wgNoticeProjects as $project ) {
1534 - $options .= Xml::option(
1535 - $project,
1536 - $project,
1537 - in_array( $project, $selected )
1538 - ) . "\n";
1539 - }
1540 - $htmlOut = '';
1541 - if ( $this->editable ) {
1542 - $htmlOut .= Xml::tags( 'select',
1543 - array( 'multiple' => 'multiple', 'size' => 4, 'id' => 'projects[]', 'name' => 'projects[]' ),
1544 - $options
1545 - );
1546 - $buttons = array();
1547 - $buttons[] = '<a href="#" onclick="selectProjects(true);return false;">' .
1548 - wfMsg( 'powersearch-toggleall' ) . '</a>';
1549 - $buttons[] = '<a href="#" onclick="selectProjects(false);return false;">' .
1550 - wfMsg( 'powersearch-togglenone' ) . '</a>';
1551 - $htmlOut .= Xml::tags( 'div',
1552 - array( 'style' => 'margin-top: 0.2em;' ),
1553 - '<img src="'.$scriptPath.'/up-arrow.png" style="vertical-align:baseline;"/>' .
1554 - wfMsg( 'centralnotice-select', $wgLang->commaList( $buttons ) )
1555 - );
1556 - } else {
1557 - $htmlOut .= Xml::tags( 'select',
1558 - array(
1559 - 'multiple' => 'multiple',
1560 - 'size' => 4,
1561 - 'id' => 'projects[]',
1562 - 'name' => 'projects[]',
1563 - 'disabled' => 'disabled'
1564 - ),
1565 - $options
1566 - );
1567 - }
1568 - return $htmlOut;
1569 - }
1570 -
1571 - function getProjectName( $value ) {
1572 - return $value; // @fixme -- use wfMsg()
1573 - }
1574 -
1575 - function updateProjectName( $notice, $projectName ) {
1576 - $dbw = wfGetDB( DB_MASTER );
1577 - $res = $dbw->update( 'cn_notices',
1578 - array ( 'not_project' => $projectName ),
1579 - array(
1580 - 'not_name' => $notice
1581 - )
1582 - );
1583 - }
1584 -
1585 - function updateProjects( $notice, $newProjects ) {
1586 - $dbw = wfGetDB( DB_MASTER );
1587 - $dbw->begin();
1588 -
1589 - // Get the previously assigned projects
1590 - $oldProjects = $this->getNoticeProjects( $notice );
1591 -
1592 - // Get the notice id
1593 - $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
1594 -
1595 - // Add newly assigned projects
1596 - $addProjects = array_diff( $newProjects, $oldProjects );
1597 - $insertArray = array();
1598 - foreach( $addProjects as $project ) {
1599 - $insertArray[] = array( 'np_notice_id' => $row->not_id, 'np_project' => $project );
1600 - }
1601 - $res = $dbw->insert( 'cn_notice_projects', $insertArray, __METHOD__, array( 'IGNORE' ) );
1602 -
1603 - // Remove disassociated projects
1604 - $removeProjects = array_diff( $oldProjects, $newProjects );
1605 - if ( $removeProjects ) {
1606 - $res = $dbw->delete( 'cn_notice_projects',
1607 - array( 'np_notice_id' => $row->not_id, 'np_project' => $removeProjects )
1608 - );
1609 - }
1610 -
1611 - $dbw->commit();
1612 - }
1613 -
1614 - function updateProjectLanguages( $notice, $newLanguages ) {
1615 - $dbw = wfGetDB( DB_MASTER );
1616 - $dbw->begin();
1617 -
1618 - // Get the previously assigned languages
1619 - $oldLanguages = $this->getNoticeLanguages( $notice );
1620 -
1621 - // Get the notice id
1622 - $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
1623 -
1624 - // Add newly assigned languages
1625 - $addLanguages = array_diff( $newLanguages, $oldLanguages );
1626 - $insertArray = array();
1627 - foreach( $addLanguages as $code ) {
1628 - $insertArray[] = array( 'nl_notice_id' => $row->not_id, 'nl_language' => $code );
1629 - }
1630 - $res = $dbw->insert( 'cn_notice_languages', $insertArray, __METHOD__, array( 'IGNORE' ) );
1631 -
1632 - // Remove disassociated languages
1633 - $removeLanguages = array_diff( $oldLanguages, $newLanguages );
1634 - if ( $removeLanguages ) {
1635 - $res = $dbw->delete( 'cn_notice_languages',
1636 - array( 'nl_notice_id' => $row->not_id, 'nl_language' => $removeLanguages )
1637 - );
1638 - }
1639 -
1640 - $dbw->commit();
1641 - }
1642 -
1643 - function updateCountries( $notice, $newCountries ) {
1644 - $dbw = wfGetDB( DB_MASTER );
1645 -
1646 - // Get the previously assigned languages
1647 - $oldCountries = $this->getNoticeCountries( $notice );
1648 -
1649 - // Get the notice id
1650 - $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
1651 -
1652 - // Add newly assigned countries
1653 - $addCountries = array_diff( $newCountries, $oldCountries );
1654 - $insertArray = array();
1655 - foreach( $addCountries as $code ) {
1656 - $insertArray[] = array( 'nc_notice_id' => $row->not_id, 'nc_country' => $code );
1657 - }
1658 - $res = $dbw->insert( 'cn_notice_countries', $insertArray, __METHOD__, array( 'IGNORE' ) );
1659 -
1660 - // Remove disassociated countries
1661 - $removeCountries = array_diff( $oldCountries, $newCountries );
1662 - if ( $removeCountries ) {
1663 - $dbw->delete( 'cn_notice_countries',
1664 - array( 'nc_notice_id' => $row->not_id, 'nc_country' => $removeCountries )
1665 - );
1666 - }
1667 - }
1668 -
1669 - public static function noticeExists( $noticeName ) {
1670 - $dbr = wfGetDB( DB_SLAVE );
1671 - $eNoticeName = htmlspecialchars( $noticeName );
1672 - $row = $dbr->selectRow( 'cn_notices', 'not_name', array( 'not_name' => $eNoticeName ) );
1673 - if ( $row ) {
1674 - return true;
1675 - } else {
1676 - return false;
1677 - }
1678 - }
1679 -
1680 - public static function dropDownList( $text, $values ) {
1681 - $dropDown = "* {$text}\n";
1682 - foreach ( $values as $value ) {
1683 - $dropDown .= "**{$value}\n";
1684 - }
1685 - return $dropDown;
1686 - }
1687 -
1688 - function addZero( $text ) {
1689 - // Prepend a 0 for text needing it
1690 - if ( strlen( $text ) == 1 ) {
1691 - $text = "0{$text}";
1692 - }
1693 - return $text;
1694 - }
1695 -
1696 - function showError( $message ) {
1697 - global $wgOut;
1698 - $wgOut->wrapWikiMsg( "<div class='cn-error'>\n$1\n</div>", $message );
1699 - $this->centralNoticeError = true;
1700 - }
1701 -
1702 - /**
1703 - * Generates a multiple select list of all countries.
1704 - * @param $selected The country codes of the selected countries
1705 - * @return multiple select list
1706 - */
1707 - function geoMultiSelector( $selected = array() ) {
1708 - $countries = CentralNoticeDB::getCountriesList();
1709 - $options = "\n";
1710 - foreach( $countries as $code => $name ) {
1711 - $options .= Xml::option(
1712 - $name,
1713 - $code,
1714 - in_array( $code, $selected )
1715 - ) . "\n";
1716 - }
1717 - $htmlOut = '';
1718 - if ( $this->editable ) {
1719 - $htmlOut .= Xml::tags( 'select',
1720 - array(
1721 - 'multiple' => 'multiple',
1722 - 'size' => 5,
1723 - 'id' => 'geo_countries[]',
1724 - 'name' => 'geo_countries[]'
1725 - ),
1726 - $options
1727 - );
1728 - } else {
1729 - $htmlOut .= Xml::tags( 'select',
1730 - array(
1731 - 'multiple' => 'multiple',
1732 - 'size' => 5,
1733 - 'id' => 'geo_countries[]',
1734 - 'name' => 'geo_countries[]',
1735 - 'disabled' => 'disabled'
1736 - ),
1737 - $options
1738 - );
1739 - }
1740 - return $htmlOut;
1741 - }
1742 -}
1743 -
1744 -class CentralNoticePager extends TemplatePager {
1745 - var $viewPage, $special;
1746 - var $editable;
1747 -
1748 - function __construct( $special ) {
1749 - parent::__construct( $special );
1750 - }
1751 -
1752 - /**
1753 - * Pull banners from the database
1754 - */
1755 - function getQueryInfo() {
1756 - $notice = $this->mRequest->getVal( 'notice' );
1757 - $noticeId = CentralNotice::getNoticeId( $notice );
1758 - if ( $noticeId ) {
1759 - // Return all the banners not already assigned to the current campaign
1760 - return array(
1761 - 'tables' => array( 'cn_assignments', 'cn_templates' ),
1762 - 'fields' => array( 'cn_templates.tmp_name', 'cn_templates.tmp_id' ),
1763 - 'conds' => array( 'cn_assignments.tmp_id IS NULL' ),
1764 - 'join_conds' => array(
1765 - 'cn_assignments' => array(
1766 - 'LEFT JOIN',
1767 - "cn_assignments.tmp_id = cn_templates.tmp_id " .
1768 - "AND cn_assignments.not_id = $noticeId"
1769 - )
1770 - )
1771 - );
1772 - } else {
1773 - // Return all the banners in the database
1774 - return array(
1775 - 'tables' => 'cn_templates',
1776 - 'fields' => array( 'tmp_name', 'tmp_id' ),
1777 - );
1778 - }
1779 - }
1780 -
1781 - /**
1782 - * Generate the content of each table row (1 row = 1 banner)
1783 - */
1784 - function formatRow( $row ) {
1785 -
1786 - // Begin banner row
1787 - $htmlOut = Xml::openElement( 'tr' );
1788 -
1789 - if ( $this->editable ) {
1790 - // Add box
1791 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
1792 - Xml::check( 'addTemplates[]', '', array ( 'value' => $row->tmp_name ) )
1793 - );
1794 - // Weight select
1795 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
1796 - Xml::listDropDown( "weight[$row->tmp_id]",
1797 - CentralNotice::dropDownList(
1798 - wfMsg( 'centralnotice-weight' ), range ( 0, 100, 5 )
1799 - ) ,
1800 - '',
1801 - '25',
1802 - '',
1803 - '' )
1804 - );
1805 - }
1806 -
1807 - // Link and Preview
1808 - $render = new SpecialBannerLoader();
1809 - $render->siteName = 'Wikipedia';
1810 - $render->language = $this->mRequest->getVal( 'wpUserLanguage' );
1811 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
1812 - $this->getSkin()->makeLinkObj( $this->viewPage,
1813 - htmlspecialchars( $row->tmp_name ),
1814 - 'template=' . urlencode( $row->tmp_name ) ) .
1815 - Xml::fieldset( wfMsg( 'centralnotice-preview' ),
1816 - $render->getHtmlNotice( $row->tmp_name ),
1817 - array( 'class' => 'cn-bannerpreview')
1818 - )
1819 - );
1820 -
1821 - // End banner row
1822 - $htmlOut .= Xml::closeElement( 'tr' );
1823 -
1824 - return $htmlOut;
1825 - }
1826 -
1827 - /**
1828 - * Specify table headers
1829 - */
1830 - function getStartBody() {
1831 - $htmlOut = '';
1832 - $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
1833 - $htmlOut .= Xml::openElement( 'tr' );
1834 - if ( $this->editable ) {
1835 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
1836 - wfMsg ( "centralnotice-add" )
1837 - );
1838 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
1839 - wfMsg ( "centralnotice-weight" )
1840 - );
1841 - }
1842 - $htmlOut .= Xml::element( 'th', array( 'align' => 'left' ),
1843 - wfMsg ( 'centralnotice-templates' )
1844 - );
1845 - $htmlOut .= Xml::closeElement( 'tr' );
1846 - return $htmlOut;
1847 - }
1848 -
1849 - /**
1850 - * Close table
1851 - */
1852 - function getEndBody() {
1853 - $htmlOut = '';
1854 - $htmlOut .= Xml::closeElement( 'table' );
1855 - return $htmlOut;
1856 - }
1857 -}
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerController.php
@@ -1,185 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * Generates Javascript file which controls banner selection on the client side
6 - */
7 -class SpecialBannerController extends UnlistedSpecialPage {
8 - protected $sharedMaxAge = 3600; // Cache for 1 hour on the server side
9 - protected $maxAge = 3600; // Cache for 1 hour on the client side
10 -
11 - function __construct() {
12 - // Register special page
13 - parent::__construct( "BannerController" );
14 - }
15 -
16 - function execute( $par ) {
17 - global $wgOut;
18 -
19 - $wgOut->disable();
20 - $this->sendHeaders();
21 -
22 - $content = $this->getOutput();
23 - if ( strlen( $content ) == 0 ) {
24 - // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
25 - echo "/* Empty */";
26 - } else {
27 - echo $content;
28 - }
29 - }
30 -
31 - /**
32 - * Generate the HTTP response headers for the banner controller
33 - */
34 - function sendHeaders() {
35 - global $wgJsMimeType;
36 - header( "Content-type: $wgJsMimeType; charset=utf-8" );
37 - header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
38 - }
39 -
40 - /**
41 - * Generate the body for the Javascript file
42 - *
43 - * We use a jsonp scheme for actual delivery of the banner so that they can be served from meta.
44 - * In order to circumvent the normal squid cache override we add '/cn.js' to the bannerlist URL.
45 - */
46 - function getOutput() {
47 - global $wgCentralPagePath, $wgContLang;
48 -
49 - $js = $this->getScriptFunctions() . $this->getToggleScripts();
50 - $js .= <<<JAVASCRIPT
51 -( function( $ ) {
52 - $.ajaxSetup({ cache: true });
53 - $.centralNotice = {
54 - 'data': {
55 - 'getVars': {}
56 - },
57 - 'fn': {
58 - 'loadBanner': function( bannerName ) {
59 - // Get the requested banner
60 - var bannerPageQuery = $.param( {
61 - 'banner': bannerName, 'userlang': wgUserLanguage,
62 - 'db': wgDBname, 'sitename': wgSiteName, 'country': Geo.country } );
63 - var bannerPage = '?title=Special:BannerLoader&' + bannerPageQuery;
64 -JAVASCRIPT;
65 - $js .= "\n\t\t\t\tvar bannerScript = '<script type=\"text/javascript\" src=\"" .
66 - Xml::escapeJsString( $wgCentralPagePath ) .
67 - "' + bannerPage + '\"></script>';\n";
68 - $js .= <<<JAVASCRIPT
69 - $( '#siteNotice' ).prepend( '<div id="centralNotice" class="' +
70 - ( wgNoticeToggleState ? 'expanded' : 'collapsed' ) +
71 - '">'+bannerScript+'</div>' );
72 - },
73 - 'loadBannerList': function( geoOverride ) {
74 - if ( geoOverride ) {
75 - var geoLocation = geoOverride; // override the geo info
76 - } else {
77 - var geoLocation = Geo.country; // pull the geo info
78 - }
79 - var bannerListQuery = $.param( { 'language': wgContentLanguage, 'project': wgNoticeProject, 'country': geoLocation } );
80 -JAVASCRIPT;
81 - $js .= "\n\t\t\t\tvar bannerListURL = wgScript + '?title=' + encodeURIComponent('" .
82 - $wgContLang->specialPage( 'BannerListLoader' ) .
83 - "') + '&cache=/cn.js&' + bannerListQuery;\n";
84 - $js .= <<<JAVASCRIPT
85 - var request = $.ajax( {
86 - url: bannerListURL,
87 - dataType: 'json',
88 - success: $.centralNotice.fn.chooseBanner
89 - } );
90 - },
91 - 'chooseBanner': function( bannerList ) {
92 - // Convert the json object to a true array
93 - bannerList = Array.prototype.slice.call( bannerList );
94 -
95 - // Make sure there are some banners to choose from
96 - if ( bannerList.length == 0 ) return false;
97 -
98 - var groomedBannerList = [];
99 -
100 - for( var i = 0; i < bannerList.length; i++ ) {
101 - // Only include this banner if it's intended for the current user
102 - if( ( wgUserName && bannerList[i].display_account ) ||
103 - ( !wgUserName && bannerList[i].display_anon == 1 ) )
104 - {
105 - // add the banner to our list once per weight
106 - for( var j=0; j < bannerList[i].weight; j++ ) {
107 - groomedBannerList.push( bannerList[i] );
108 - }
109 - }
110 - }
111 -
112 - // Return if there's nothing left after the grooming
113 - if( groomedBannerList.length == 0 ) return false;
114 -
115 - // Load a random banner from our groomed list
116 - $.centralNotice.fn.loadBanner(
117 - groomedBannerList[
118 - Math.floor( Math.random() * groomedBannerList.length )
119 - ].name
120 - );
121 - },
122 - 'getQueryStringVariables': function() {
123 - document.location.search.replace( /\??(?:([^=]+)=([^&]*)&?)/g, function () {
124 - function decode( s ) {
125 - return decodeURIComponent( s.split( "+" ).join( " " ) );
126 - }
127 - $.centralNotice.data.getVars[decode( arguments[1] )] = decode( arguments[2] );
128 - } );
129 - }
130 - }
131 - }
132 - $( document ).ready( function () {
133 - // Initialize the query string vars
134 - $.centralNotice.fn.getQueryStringVariables();
135 - if( $.centralNotice.data.getVars['banner'] ) {
136 - // if we're forcing one banner
137 - $.centralNotice.fn.loadBanner( $.centralNotice.data.getVars['banner'] );
138 - } else {
139 - // Look for banners ready to go NOW
140 - $.centralNotice.fn.loadBannerList( $.centralNotice.data.getVars['country'] );
141 - }
142 - } ); //document ready
143 -} )( jQuery );
144 -JAVASCRIPT;
145 - return $js;
146 -
147 - }
148 -
149 - function getToggleScripts() {
150 - $script = "var wgNoticeToggleState = (document.cookie.indexOf('hidesnmessage=1')==-1);\n\n";
151 - return $script;
152 - }
153 -
154 - function getScriptFunctions() {
155 - $script = <<<JAVASCRIPT
156 -function insertBanner(bannerJson) {
157 - jQuery('div#centralNotice').prepend( bannerJson.banner );
158 -}
159 -function toggleNotice() {
160 - var notice = document.getElementById('centralNotice');
161 - if (!wgNoticeToggleState) {
162 - notice.className = notice.className.replace('collapsed', 'expanded');
163 - toggleNoticeCookie('0');
164 - } else {
165 - notice.className = notice.className.replace('expanded', 'collapsed');
166 - toggleNoticeCookie('1');
167 - }
168 - wgNoticeToggleState = !wgNoticeToggleState;
169 -}
170 -function toggleNoticeStyle(elems, display) {
171 - if(elems)
172 - for(var i=0;i<elems.length;i++)
173 - elems[i].style.display = display;
174 -}
175 -function toggleNoticeCookie(state) {
176 - var e = new Date();
177 - e.setTime( e.getTime() + (7*24*60*60*1000) ); // one week
178 - var work='hidesnmessage='+state+'; expires=' + e.toGMTString() + '; path=/';
179 - document.cookie = work;
180 -}
181 -
182 -JAVASCRIPT;
183 - return $script;
184 - }
185 -
186 -}
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialBannerAllocation.php
@@ -1,194 +0,0 @@
2 -<?php
3 -
4 -if ( !defined( 'MEDIAWIKI' ) ) {
5 - echo "CentralNotice extension\n";
6 - exit( 1 );
7 -}
8 -
9 -class SpecialBannerAllocation extends UnlistedSpecialPage {
10 - public $project = 'wikipedia';
11 - public $language = 'en';
12 - public $location = 'US';
13 -
14 - function __construct() {
15 - // Register special page
16 - parent::__construct( "BannerAllocation" );
17 - }
18 -
19 - /**
20 - * Handle different types of page requests
21 - */
22 - function execute( $sub ) {
23 - global $wgOut, $wgRequest, $wgExtensionAssetsPath, $wgNoticeProjects, $wgLanguageCode;
24 -
25 - if ( $wgRequest->wasPosted() ) {
26 - $this->project = $wgRequest->getText( 'project', 'wikipedia' );
27 - $this->language = $wgRequest->getText( 'language', 'en' );
28 - $this->location = $wgRequest->getText( 'country', 'US' );
29 - }
30 -
31 - // Begin output
32 - $this->setHeaders();
33 -
34 - // Add style file to the output headers
35 - $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
36 -
37 - // Add script file to the output headers
38 - $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
39 -
40 - // Initialize error variable
41 - $this->centralNoticeError = false;
42 -
43 - // Show summary
44 - $wgOut->addWikiMsg( 'centralnotice-summary' );
45 -
46 - // Show header
47 - CentralNotice::printHeader();
48 -
49 - // Begin Banners tab content
50 - $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
51 -
52 - $htmlOut = '';
53 -
54 - // Begin Allocation selection fieldset
55 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
56 -
57 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
58 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-view-allocation' ) );
59 - $htmlOut .= Xml::tags( 'p', null, wfMsg( 'centralnotice-allocation-instructions' ) );
60 -
61 - $htmlOut .= Xml::openElement( 'table', array ( 'id' => 'envpicker', 'cellpadding' => 7 ) );
62 - $htmlOut .= Xml::openElement( 'tr' );
63 - $htmlOut .= Xml::tags( 'td',
64 - array( 'style' => 'width: 20%;' ),
65 - wfMsg( 'centralnotice-project-name' ) );
66 - $htmlOut .= Xml::openElement( 'td' );
67 - $htmlOut .= Xml::openElement( 'select', array( 'name' => 'project' ) );
68 - foreach ( $wgNoticeProjects as $value ) {
69 - $htmlOut .= Xml::option( $value, $value, $value === $this->project );
70 - }
71 - $htmlOut .= Xml::closeElement( 'select' );
72 - $htmlOut .= Xml::closeElement( 'td' );
73 - $htmlOut .= Xml::closeElement( 'tr' );
74 - $htmlOut .= Xml::openElement( 'tr' );
75 - $htmlOut .= Xml::tags( 'td',
76 - array( 'valign' => 'top' ),
77 - wfMsg( 'centralnotice-project-lang' ) );
78 - $htmlOut .= Xml::openElement( 'td' );
79 - // Make sure the site language is in the list; a custom language code
80 - // might not have a defined name...
81 - $languages = Language::getLanguageNames( true );
82 - if( !array_key_exists( $wgLanguageCode, $languages ) ) {
83 - $languages[$wgLanguageCode] = $wgLanguageCode;
84 - }
85 - ksort( $languages );
86 - $htmlOut .= Xml::openElement( 'select', array( 'name' => 'language' ) );
87 - foreach( $languages as $code => $name ) {
88 - $htmlOut .= Xml::option(
89 - wfMsg( 'centralnotice-language-listing', $code, $name ),
90 - $code, $code === $this->language );
91 - }
92 - $htmlOut .= Xml::closeElement( 'select' );
93 - $htmlOut .= Xml::closeElement( 'td' );
94 - $htmlOut .= Xml::closeElement( 'tr' );
95 - $htmlOut .= Xml::openElement( 'tr' );
96 - $htmlOut .= Xml::tags( 'td', array(), wfMsg( 'centralnotice-country' ) );
97 - $htmlOut .= Xml::openElement( 'td' );
98 - $countries = CentralNoticeDB::getCountriesList();
99 - $htmlOut .= Xml::openElement( 'select', array( 'name' => 'country' ) );
100 - foreach( $countries as $code => $name ) {
101 - $htmlOut .= Xml::option( $name, $code, $code === $this->location );
102 - }
103 - $htmlOut .= Xml::closeElement( 'select' );
104 - $htmlOut .= Xml::closeElement( 'td' );
105 - $htmlOut .= Xml::closeElement( 'tr' );
106 - $htmlOut .= Xml::closeElement( 'table' );
107 -
108 - $htmlOut .= Xml::tags( 'div',
109 - array( 'class' => 'cn-buttons' ),
110 - Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
111 - );
112 - $htmlOut .= Xml::closeElement( 'form' );
113 -
114 - // End Allocation selection fieldset
115 - $htmlOut .= Xml::closeElement( 'fieldset' );
116 -
117 - $wgOut->addHTML( $htmlOut );
118 -
119 - // Handle form submissions
120 - if ( $wgRequest->wasPosted() ) {
121 - $this->showList();
122 - }
123 -
124 - // End Banners tab content
125 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
126 - }
127 -
128 - /**
129 - * Show a list of banners with allocation. Newer banners are shown first.
130 - */
131 - function showList() {
132 - global $wgOut, $wgUser, $wgRequest, $wgLang;
133 -
134 - $sk = $wgUser->getSkin();
135 - $viewPage = $this->getTitleFor( 'NoticeTemplate', 'view' );
136 -
137 - // Begin building HTML
138 - $htmlOut = '';
139 -
140 - // Begin Allocation list fieldset
141 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
142 -
143 - $bannerLister = new SpecialBannerListLoader();
144 - $bannerLister->project = $wgRequest->getVal( 'project' );
145 - $bannerLister->language = $wgRequest->getVal( 'language' );
146 - $bannerLister->location = $wgRequest->getVal( 'country' );
147 -
148 - $htmlOut .= Xml::tags( 'p', null,
149 - wfMsg (
150 - 'centralnotice-allocation-description',
151 - htmlspecialchars( $bannerLister->language ),
152 - htmlspecialchars( $bannerLister->project ),
153 - htmlspecialchars( $bannerLister->location )
154 - )
155 - );
156 -
157 - $bannerList = $bannerLister->getJsonList();
158 - $banners = FormatJson::decode( $bannerList, true );
159 - $totalWeight = 0;
160 - foreach ( $banners as $banner ) {
161 - $totalWeight += $banner['weight'];
162 - }
163 - if ( $banners ) {
164 - $htmlOut .= Xml::openElement( 'table',
165 - array ( 'cellpadding' => 9, 'class' => 'wikitable sortable' ) );
166 - $htmlOut .= Xml::openElement( 'tr' );
167 - $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ),
168 - wfMsg ( 'centralnotice-percentage' ) );
169 - $htmlOut .= Xml::element( 'th', array( 'width' => '60%' ),
170 - wfMsg ( 'centralnotice-banner' ) );
171 - $htmlOut .= Xml::closeElement( 'tr' );
172 - foreach ( $banners as $banner ) {
173 - $htmlOut .= Xml::openElement( 'tr' );
174 - $htmlOut .= Xml::openElement( 'td' );
175 - $percentage = ( $banner['weight'] / $totalWeight ) * 100;
176 - $htmlOut .= wfMsg ( 'percent', $wgLang->formatNum( $percentage ) );
177 - $htmlOut .= Xml::closeElement( 'td' );
178 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
179 - $sk->makeLinkObj( $viewPage, htmlspecialchars( $banner['name'] ),
180 - 'template=' . urlencode( $banner['name'] ) )
181 - );
182 - $htmlOut .= Xml::closeElement( 'tr' );
183 - }
184 - $htmlOut .= Xml::closeElement( 'table' );
185 - } else {
186 - $htmlOut .= Xml::tags( 'p', null, wfMsg ( 'centralnotice-no-allocation' ) );
187 - }
188 -
189 - // End Allocation list fieldset
190 - $htmlOut .= Xml::closeElement( 'fieldset' );
191 -
192 - $wgOut->addHTML( $htmlOut );
193 - }
194 -
195 -}
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/SpecialNoticeTemplate.php
@@ -1,889 +0,0 @@
2 -<?php
3 -
4 -if ( !defined( 'MEDIAWIKI' ) ) {
5 - echo "CentralNotice extension\n";
6 - exit( 1 );
7 -}
8 -
9 -class SpecialNoticeTemplate extends UnlistedSpecialPage {
10 - var $editable, $centralNoticeError;
11 -
12 - function __construct() {
13 - // Register special page
14 - parent::__construct( 'NoticeTemplate' );
15 - }
16 -
17 - /**
18 - * Handle different types of page requests
19 - */
20 - function execute( $sub ) {
21 - global $wgOut, $wgUser, $wgRequest, $wgScriptPath;
22 -
23 - // Begin output
24 - $this->setHeaders();
25 -
26 - // Add style file to the output headers
27 - $wgOut->addExtensionStyle( "$wgScriptPath/extensions/CentralNotice/centralnotice.css" );
28 -
29 - // Add localized script error messages
30 - $scriptVars = array(
31 - 'documentWriteError' => wfMsg( 'centralnotice-documentwrite-error' )
32 - );
33 - $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
34 -
35 - // Add script file to the output headers
36 - $wgOut->addScriptFile( "$wgScriptPath/extensions/CentralNotice/centralnotice.js" );
37 -
38 - // Check permissions
39 - $this->editable = $wgUser->isAllowed( 'centralnotice-admin' );
40 -
41 - // Initialize error variable
42 - $this->centralNoticeError = false;
43 -
44 - // Show summary
45 - $wgOut->addWikiMsg( 'centralnotice-summary' );
46 -
47 - // Show header
48 - CentralNotice::printHeader();
49 -
50 - // Begin Banners tab content
51 - $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
52 -
53 - $method = $wgRequest->getVal( 'wpMethod' );
54 -
55 - // Handle form submissions
56 - if ( $this->editable && $wgRequest->wasPosted() ) {
57 -
58 - // Check authentication token
59 - if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
60 -
61 - // Handle removing banners
62 - $toRemove = $wgRequest->getArray( 'removeTemplates' );
63 - if ( isset( $toRemove ) ) {
64 - // Remove banners in list
65 - foreach ( $toRemove as $template ) {
66 - $this->removeTemplate( $template );
67 - }
68 - }
69 -
70 - // Handle translation message update
71 - $update = $wgRequest->getArray( 'updateText' );
72 - if ( isset ( $update ) ) {
73 - foreach ( $update as $lang => $messages ) {
74 - foreach ( $messages as $text => $translation ) {
75 - // If we actually have text
76 - if ( $translation ) {
77 - $this->updateMessage( $text, $translation, $lang );
78 - }
79 - }
80 - }
81 - }
82 -
83 - // Handle adding banner
84 - if ( $method == 'addTemplate' ) {
85 - $newTemplateName = $wgRequest->getText( 'templateName' );
86 - $newTemplateBody = $wgRequest->getText( 'templateBody' );
87 - if ( $newTemplateName != '' && $newTemplateBody != '' ) {
88 - $this->addTemplate(
89 - $newTemplateName,
90 - $newTemplateBody,
91 - $wgRequest->getBool( 'displayAnon' ),
92 - $wgRequest->getBool( 'displayAccount' )
93 - );
94 - $sub = 'view';
95 - } else {
96 - $this->showError( 'centralnotice-null-string' );
97 - }
98 - }
99 -
100 - // Handle editing banner
101 - if ( $method == 'editTemplate' ) {
102 - $this->editTemplate(
103 - $wgRequest->getText( 'template' ),
104 - $wgRequest->getText( 'templateBody' ),
105 - $wgRequest->getBool( 'displayAnon' ),
106 - $wgRequest->getBool( 'displayAccount' )
107 - );
108 - $sub = 'view';
109 - }
110 -
111 - } else {
112 - $this->showError( 'sessionfailure' );
113 - }
114 -
115 - }
116 -
117 - // Handle viewing of a banner in all languages
118 - if ( $sub == 'view' && $wgRequest->getVal( 'wpUserLanguage' ) == 'all' ) {
119 - $template = $wgRequest->getVal( 'template' );
120 - $this->showViewAvailable( $template );
121 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
122 - return;
123 - }
124 -
125 - // Handle viewing a specific banner
126 - if ( $sub == 'view' && $wgRequest->getText( 'template' ) != '' ) {
127 - $this->showView();
128 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
129 - return;
130 - }
131 -
132 - if ( $this->editable ) {
133 - // Handle showing "Add a banner" interface
134 - if ( $sub == 'add' ) {
135 - $this->showAdd();
136 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
137 - return;
138 - }
139 -
140 - // Handle cloning a specific banner
141 - if ( $sub == 'clone' ) {
142 -
143 - // Check authentication token
144 - if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
145 -
146 - $oldTemplate = $wgRequest->getVal( 'oldTemplate' );
147 - $newTemplate = $wgRequest->getVal( 'newTemplate' );
148 - // We use the returned name in case any special characters had to be removed
149 - $template = $this->cloneTemplate( $oldTemplate, $newTemplate );
150 - $wgOut->redirect(
151 - $this->getTitle( 'view' )->getLocalUrl( "template=$template" ) );
152 - return;
153 -
154 - } else {
155 - $this->showError( 'sessionfailure' );
156 - }
157 -
158 - }
159 -
160 - }
161 -
162 - // Show list of banners by default
163 - $this->showList();
164 -
165 - // End Banners tab content
166 - $wgOut->addHTML( Xml::closeElement( 'div' ) );
167 - }
168 -
169 - /**
170 - * Show a list of available banners. Newer banners are shown first.
171 - */
172 - function showList() {
173 - global $wgOut, $wgUser;
174 -
175 - $sk = $wgUser->getSkin();
176 - $pager = new TemplatePager( $this );
177 -
178 - // Begin building HTML
179 - $htmlOut = '';
180 -
181 - // Begin Manage Banners fieldset
182 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
183 -
184 - if ( !$pager->getNumRows() ) {
185 - $htmlOut .= Xml::element( 'p', null, wfMsg( 'centralnotice-no-templates' ) );
186 - } else {
187 - if ( $this->editable ) {
188 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
189 - }
190 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-manage-templates' ) );
191 -
192 - // Show paginated list of banners
193 - $htmlOut .= Xml::tags( 'div', array( 'class' => 'cn-pager' ),
194 - $pager->getNavigationBar() );
195 - $htmlOut .= $pager->getBody();
196 - $htmlOut .= Xml::tags( 'div', array( 'class' => 'cn-pager' ),
197 - $pager->getNavigationBar() );
198 -
199 - if ( $this->editable ) {
200 - $htmlOut .= Xml::closeElement( 'form' );
201 - }
202 - }
203 -
204 - if ( $this->editable ) {
205 - $htmlOut .= Xml::element( 'p' );
206 - $newPage = $this->getTitle( 'add' );
207 - $htmlOut .= $sk->makeLinkObj( $newPage, wfMsgHtml( 'centralnotice-add-template' ) );
208 - }
209 -
210 - // End Manage Banners fieldset
211 - $htmlOut .= Xml::closeElement( 'fieldset' );
212 -
213 - $wgOut->addHTML( $htmlOut );
214 - }
215 -
216 - /**
217 - * Show "Add a banner" interface
218 - */
219 - function showAdd() {
220 - global $wgOut, $wgUser, $wgScriptPath, $wgLang, $wgRequest;
221 - $scriptPath = "$wgScriptPath/extensions/CentralNotice";
222 -
223 - // Build HTML
224 - $htmlOut = '';
225 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
226 - $htmlOut .= Xml::openElement( 'form',
227 - array( 'method' => 'post', 'onsubmit' => 'return validateBannerForm(this)' ) );
228 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-add-template' ) );
229 - $htmlOut .= Html::hidden( 'wpMethod', 'addTemplate' );
230 - $htmlOut .= Xml::tags( 'p', null,
231 - Xml::inputLabel(
232 - wfMsg( 'centralnotice-banner-name' ),
233 - 'templateName', 'templateName', 25, $wgRequest->getVal( 'templateName' )
234 - )
235 - );
236 -
237 - $htmlOut .= Xml::openElement( 'p', null );
238 - $htmlOut .= wfMsg( 'centralnotice-banner-display' );
239 - if ( $wgRequest->wasPosted() ) {
240 - // Restore checkbox state in event of error
241 - $displayAnon = $wgRequest->getCheck( 'displayAnon' );
242 - } else {
243 - // Default is checked
244 - $displayAnon = true;
245 - }
246 - $htmlOut .= Xml::check( 'displayAnon', $displayAnon, array( 'id' => 'displayAnon' ) );
247 - $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-anonymous' ), 'displayAnon' );
248 - if ( $wgRequest->wasPosted() ) {
249 - // Restore checkbox state in event of error
250 - $displayAccount = $wgRequest->getCheck( 'displayAccount' );
251 - } else {
252 - // Default is checked
253 - $displayAccount = true;
254 - }
255 - $htmlOut .= Xml::check( 'displayAccount', $displayAccount,
256 - array( 'id' => 'displayAccount' ) );
257 - $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-logged-in' ), 'displayAccount' );
258 - $htmlOut .= Xml::closeElement( 'p' );
259 -
260 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-banner' ) );
261 - $htmlOut .= wfMsg( 'centralnotice-edit-template-summary' );
262 - $buttons = array();
263 - $buttons[] = '<a href="#" onclick="insertButton(\'close\');return false;">' .
264 - wfMsg( 'centralnotice-close-button' ) . '</a>';
265 - $htmlOut .= Xml::tags( 'div',
266 - array( 'style' => 'margin-bottom: 0.2em;' ),
267 - '<img src="'.$scriptPath.'/down-arrow.png" style="vertical-align:baseline;"/>' .
268 - wfMsg( 'centralnotice-insert', $wgLang->commaList( $buttons ) )
269 - );
270 -
271 - // Restore banner body state in the event of an error on form submit
272 - $body = $wgRequest->getVal( 'templateBody', '' );
273 -
274 - $htmlOut .= Xml::textarea( 'templateBody', $body, 60, 20 );
275 - $htmlOut .= Xml::closeElement( 'fieldset' );
276 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
277 -
278 - // Submit button
279 - $htmlOut .= Xml::tags( 'div',
280 - array( 'class' => 'cn-buttons' ),
281 - Xml::submitButton( wfMsg( 'centralnotice-save-banner' ) )
282 - );
283 -
284 - $htmlOut .= Xml::closeElement( 'form' );
285 - $htmlOut .= Xml::closeElement( 'fieldset' );
286 -
287 - // Output HTML
288 - $wgOut->addHTML( $htmlOut );
289 - }
290 -
291 - /**
292 - * View or edit an individual banner
293 - */
294 - private function showView() {
295 - global $wgOut, $wgUser, $wgRequest, $wgLanguageCode, $wgScriptPath, $wgLang;
296 -
297 - $scriptPath = "$wgScriptPath/extensions/CentralNotice";
298 - $sk = $wgUser->getSkin();
299 -
300 - if ( $this->editable ) {
301 - $readonly = array();
302 - $disabled = array();
303 - } else {
304 - $readonly = array( 'readonly' => 'readonly' );
305 - $disabled = array( 'disabled' => 'disabled' );
306 - }
307 -
308 - // Get user's language
309 - $wpUserLang = $wgRequest->getVal( 'wpUserLanguage', $wgLanguageCode );
310 -
311 - // Get current banner
312 - $currentTemplate = $wgRequest->getText( 'template' );
313 -
314 - // Pull banner settings from database
315 - $dbr = wfGetDB( DB_SLAVE );
316 - $row = $dbr->selectRow( 'cn_templates',
317 - array(
318 - 'tmp_display_anon',
319 - 'tmp_display_account'
320 - ),
321 - array( 'tmp_name' => $currentTemplate ),
322 - __METHOD__
323 - );
324 -
325 - if ( !$row ) {
326 - $this->showError( 'centralnotice-banner-doesnt-exist' );
327 - return;
328 - } else {
329 - // Begin building HTML
330 - $htmlOut = '';
331 -
332 - // Begin View Banner fieldset
333 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
334 -
335 - $htmlOut .= Xml::element( 'h2', null,
336 - wfMsg( 'centralnotice-banner-heading', $currentTemplate ) );
337 -
338 - // Show preview of banner
339 - $render = new SpecialBannerLoader();
340 - $render->siteName = 'Wikipedia';
341 - $render->language = $wpUserLang;
342 - if ( $render->language != '' ) {
343 - $htmlOut .= Xml::fieldset(
344 - wfMsg( 'centralnotice-preview' ) . " ($render->language)",
345 - $render->getHtmlNotice( $wgRequest->getText( 'template' ) )
346 - );
347 - } else {
348 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-preview' ),
349 - $render->getHtmlNotice( $wgRequest->getText( 'template' ) )
350 - );
351 - }
352 -
353 - // Pull banner text and respect any inc: markup
354 - $bodyPage = Title::newFromText(
355 - "Centralnotice-template-{$currentTemplate}", NS_MEDIAWIKI );
356 - $curRev = Revision::newFromTitle( $bodyPage );
357 - $body = $curRev ? $curRev->getText() : '';
358 -
359 - // Extract message fields from the banner body
360 - $fields = array();
361 - $allowedChars = Title::legalChars();
362 - preg_match_all( "/\{\{\{([$allowedChars]+)\}\}\}/u", $body, $fields );
363 -
364 - // If there are any message fields in the banner, display translation tools.
365 - if ( count( $fields[0] ) > 0 ) {
366 - if ( $this->editable ) {
367 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
368 - }
369 - $htmlOut .= Xml::fieldset(
370 - wfMsg( 'centralnotice-translate-heading', $currentTemplate ),
371 - false,
372 - array( 'id' => 'mw-centralnotice-translations-for' )
373 - );
374 - $htmlOut .= Xml::openElement( 'table',
375 - array (
376 - 'cellpadding' => 9,
377 - 'width' => '100%'
378 - )
379 - );
380 -
381 - // Table headers
382 - $htmlOut .= Xml::element( 'th', array( 'width' => '15%' ),
383 - wfMsg( 'centralnotice-message' ) );
384 - $htmlOut .= Xml::element( 'th', array( 'width' => '5%' ),
385 - wfMsg ( 'centralnotice-number-uses' ) );
386 - $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ),
387 - wfMsg ( 'centralnotice-english' ) );
388 - $languages = Language::getLanguageNames();
389 - $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ),
390 - $languages[$wpUserLang] );
391 -
392 - // Remove duplicate message fields
393 - $filteredFields = array();
394 - foreach ( $fields[1] as $field ) {
395 - $filteredFields[$field] = array_key_exists( $field, $filteredFields )
396 - ? $filteredFields[$field] + 1 : 1;
397 - }
398 -
399 - // Table rows
400 - foreach ( $filteredFields as $field => $count ) {
401 - // Message
402 - $message = ( $wpUserLang == 'en' )
403 - ? "Centralnotice-{$currentTemplate}-{$field}"
404 - : "Centralnotice-{$currentTemplate}-{$field}/{$wpUserLang}";
405 -
406 - // English value
407 - $htmlOut .= Xml::openElement( 'tr' );
408 -
409 - $title = Title::newFromText( "MediaWiki:{$message}" );
410 - $htmlOut .= Xml::tags( 'td', null,
411 - $sk->makeLinkObj( $title, htmlspecialchars( $field ) )
412 - );
413 -
414 - $htmlOut .= Xml::element( 'td', null, $count );
415 -
416 - // English text
417 - $englishText = wfMsg( 'centralnotice-message-not-set' );
418 - $englishTextExists = false;
419 - if (
420 - Title::newFromText(
421 - "Centralnotice-{$currentTemplate}-{$field}", NS_MEDIAWIKI
422 - )->exists() )
423 - {
424 - $englishText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
425 - array( 'language' => 'en' )
426 - );
427 - $englishTextExists = true;
428 - }
429 - $htmlOut .= Xml::tags( 'td', null,
430 - Xml::element( 'span',
431 - array(
432 - 'style' => 'font-style:italic;' .
433 - ( !$englishTextExists ? 'color:silver' : '' )
434 - ),
435 - $englishText
436 - )
437 - );
438 -
439 - // Foreign text input
440 - $foreignText = '';
441 - $foreignTextExists = false;
442 - if ( Title::newFromText( $message, NS_MEDIAWIKI )->exists() ) {
443 - $foreignText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
444 - array( 'language' => $wpUserLang )
445 - );
446 - $foreignTextExists = true;
447 - }
448 - $htmlOut .= Xml::tags( 'td', null,
449 - Xml::input(
450 - "updateText[{$wpUserLang}][{$currentTemplate}-{$field}]",
451 - '',
452 - $foreignText,
453 - wfArrayMerge( $readonly,
454 - array( 'style' => 'width:100%;' .
455 - ( !$foreignTextExists ? 'color:red' : '' ) ) )
456 - )
457 - );
458 - $htmlOut .= Xml::closeElement( 'tr' );
459 - }
460 - $htmlOut .= Xml::closeElement( 'table' );
461 -
462 - if ( $this->editable ) {
463 - $htmlOut .= Html::hidden( 'wpUserLanguage', $wpUserLang );
464 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
465 - $htmlOut .= Xml::tags( 'div',
466 - array( 'class' => 'cn-buttons' ),
467 - Xml::submitButton(
468 - wfMsg( 'centralnotice-modify' ),
469 - array( 'name' => 'update' )
470 - )
471 - );
472 - }
473 -
474 - $htmlOut .= Xml::closeElement( 'fieldset' );
475 -
476 - if ( $this->editable ) {
477 - $htmlOut .= Xml::closeElement( 'form' );
478 - }
479 -
480 - // Show language selection form
481 - $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
482 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-change-lang' ) );
483 - $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
484 - list( $lsLabel, $lsSelect ) = Xml::languageSelector( $wpUserLang );
485 -
486 - $newPage = $this->getTitle( 'view' );
487 -
488 - $htmlOut .= Xml::tags( 'tr', null,
489 - Xml::tags( 'td', null, $lsLabel ) .
490 - Xml::tags( 'td', null, $lsSelect ) .
491 - Xml::tags( 'td', array( 'colspan' => 2 ),
492 - Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
493 - )
494 - );
495 - $htmlOut .= Xml::tags( 'tr', null,
496 - Xml::tags( 'td', null, '' ) .
497 - Xml::tags( 'td', null,
498 - $sk->makeLinkObj(
499 - $newPage,
500 - wfMsgHtml( 'centralnotice-preview-all-template-translations' ),
501 - "template=$currentTemplate&wpUserLanguage=all" )
502 - )
503 - );
504 - $htmlOut .= Xml::closeElement( 'table' );
505 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
506 - $htmlOut .= Xml::closeElement( 'fieldset' );
507 - $htmlOut .= Xml::closeElement( 'form' );
508 - }
509 -
510 - // Show edit form
511 - if ( $this->editable ) {
512 - $htmlOut .= Xml::openElement( 'form',
513 - array(
514 - 'method' => 'post',
515 - 'onsubmit' => 'return validateBannerForm(this)'
516 - )
517 - );
518 - $htmlOut .= Html::hidden( 'wpMethod', 'editTemplate' );
519 - }
520 -
521 - // If there was an error, we'll need to restore the state of the form
522 - if ( $wgRequest->wasPosted() && $wgRequest->getVal( 'mainform' ) ) {
523 - $displayAnon = $wgRequest->getCheck( 'displayAnon' );
524 - $displayAccount = $wgRequest->getCheck( 'displayAccount' );
525 - $body = $wgRequest->getVal( 'templateBody', $body );
526 - } else { // Defaults
527 - $displayAnon = ( $row->tmp_display_anon == 1 );
528 - $displayAccount = ( $row->tmp_display_account == 1 );
529 - }
530 -
531 - // Show banner settings
532 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-settings' ) );
533 - $htmlOut .= Xml::openElement( 'p', null );
534 - $htmlOut .= wfMsg( 'centralnotice-banner-display' );
535 - $htmlOut .= Xml::check( 'displayAnon', $displayAnon,
536 - wfArrayMerge( $disabled, array( 'id' => 'displayAnon' ) ) );
537 - $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-anonymous' ), 'displayAnon' );
538 - $htmlOut .= Xml::check( 'displayAccount', $displayAccount,
539 - wfArrayMerge( $disabled, array( 'id' => 'displayAccount' ) ) );
540 - $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-logged-in' ), 'displayAccount' );
541 - $htmlOut .= Xml::closeElement( 'p' );
542 - $htmlOut .= Xml::closeElement( 'fieldset' );
543 - if ( $this->editable ) {
544 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-edit-template' ) );
545 - $htmlOut .= wfMsg( 'centralnotice-edit-template-summary' );
546 - $buttons = array();
547 - $buttons[] = '<a href="#" onclick="insertButton(\'close\');return false;">' .
548 - wfMsg( 'centralnotice-close-button' ) . '</a>';
549 - $htmlOut .= Xml::tags( 'div',
550 - array( 'style' => 'margin-bottom: 0.2em;' ),
551 - '<img src="' . $scriptPath . '/down-arrow.png" ' .
552 - 'style="vertical-align:baseline;"/>' .
553 - wfMsg( 'centralnotice-insert', $wgLang->commaList( $buttons ) )
554 - );
555 - } else {
556 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-banner' ) );
557 - }
558 - $htmlOut .= Xml::textarea( 'templateBody', $body, 60, 20, $readonly );
559 - $htmlOut .= Xml::closeElement( 'fieldset' );
560 - if ( $this->editable ) {
561 - // Indicate which form was submitted
562 - $htmlOut .= Html::hidden( 'mainform', 'true' );
563 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
564 - $htmlOut .= Xml::tags( 'div',
565 - array( 'class' => 'cn-buttons' ),
566 - Xml::submitButton( wfMsg( 'centralnotice-save-banner' ) )
567 - );
568 - $htmlOut .= Xml::closeElement( 'form' );
569 - }
570 -
571 - // Show clone form
572 - if ( $this->editable ) {
573 - $htmlOut .= Xml::openElement ( 'form',
574 - array(
575 - 'method' => 'post',
576 - 'action' => $this->getTitle( 'clone' )->getLocalUrl()
577 - )
578 - );
579 -
580 - $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-clone-notice' ) );
581 - $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
582 - $htmlOut .= Xml::openElement( 'tr' );
583 - $htmlOut .= Xml::inputLabel(
584 - wfMsg( 'centralnotice-clone-name' ),
585 - 'newTemplate', 'newTemplate', '25' );
586 - $htmlOut .= Xml::submitButton(
587 - wfMsg( 'centralnotice-clone' ),
588 - array ( 'id' => 'clone' ) );
589 - $htmlOut .= Html::hidden( 'oldTemplate', $currentTemplate );
590 -
591 - $htmlOut .= Xml::closeElement( 'tr' );
592 - $htmlOut .= Xml::closeElement( 'table' );
593 - $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
594 - $htmlOut .= Xml::closeElement( 'fieldset' );
595 - $htmlOut .= Xml::closeElement( 'form' );
596 - }
597 -
598 - // End View Banner fieldset
599 - $htmlOut .= Xml::closeElement( 'fieldset' );
600 -
601 - // Output HTML
602 - $wgOut->addHTML( $htmlOut );
603 - }
604 - }
605 -
606 - /**
607 - * Preview all available translations of a banner
608 - */
609 - public function showViewAvailable( $template ) {
610 - global $wgOut, $wgUser;
611 -
612 - // Testing to see if bumping up the memory limit lets meta preview
613 - ini_set( 'memory_limit', '120M' );
614 -
615 - $sk = $wgUser->getSkin();
616 -
617 - // Pull all available text for a banner
618 - $langs = array_keys( $this->getTranslations( $template ) );
619 - $htmlOut = '';
620 -
621 - // Begin View Banner fieldset
622 - $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
623 -
624 - $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-banner-heading', $template ) );
625 -
626 - foreach ( $langs as $lang ) {
627 - // Link and Preview all available translations
628 - $viewPage = $this->getTitle( 'view' );
629 - $render = new SpecialBannerLoader();
630 - $render->siteName = 'Wikipedia';
631 - $render->language = $lang;
632 - $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
633 - $sk->makeLinkObj( $viewPage,
634 - $lang,
635 - 'template=' . urlencode( $template ) . "&wpUserLanguage=$lang" ) .
636 - Xml::fieldset( wfMsg( 'centralnotice-preview' ),
637 - $render->getHtmlNotice( $template ),
638 - array( 'class' => 'cn-bannerpreview')
639 - )
640 - );
641 - }
642 -
643 - // End View Banner fieldset
644 - $htmlOut .= Xml::closeElement( 'fieldset' );
645 -
646 - return $wgOut->addHtml( $htmlOut );
647 - }
648 -
649 - /**
650 - * Add or update a message
651 - */
652 - private function updateMessage( $text, $translation, $lang ) {
653 - $title = Title::newFromText(
654 - ( $lang == 'en' ) ? "Centralnotice-{$text}" : "Centralnotice-{$text}/{$lang}",
655 - NS_MEDIAWIKI
656 - );
657 - $article = new Article( $title );
658 - $article->doEdit( $translation, '', EDIT_FORCE_BOT );
659 - }
660 -
661 - private function getTemplateId ( $templateName ) {
662 - $dbr = wfGetDB( DB_SLAVE );
663 - $res = $dbr->select( 'cn_templates', 'tmp_id',
664 - array( 'tmp_name' => $templateName ),
665 - __METHOD__
666 - );
667 -
668 - $row = $dbr->fetchObject( $res );
669 - if ( $row ) {
670 - return $row->tmp_id;
671 - }
672 - return null;
673 - }
674 -
675 - private function removeTemplate ( $name ) {
676 - $id = $this->getTemplateId( $name );
677 - $dbr = wfGetDB( DB_SLAVE );
678 - $res = $dbr->select( 'cn_assignments', 'asn_id', array( 'tmp_id' => $id ), __METHOD__ );
679 -
680 - if ( $dbr->numRows( $res ) > 0 ) {
681 - $this->showError( 'centralnotice-template-still-bound' );
682 - return;
683 - } else {
684 - $dbw = wfGetDB( DB_MASTER );
685 - $dbw->begin();
686 - $dbw->delete( 'cn_templates',
687 - array( 'tmp_id' => $id ),
688 - __METHOD__
689 - );
690 - $dbw->commit();
691 -
692 - $article = new Article(
693 - Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
694 - );
695 - $article->doDeleteArticle( 'CentralNotice Automated Removal' );
696 - }
697 - }
698 -
699 - /**
700 - * Create a new banner
701 - */
702 - private function addTemplate( $name, $body, $displayAnon, $displayAccount ) {
703 - if ( $body == '' || $name == '' ) {
704 - $this->showError( 'centralnotice-null-string' );
705 - return;
706 - }
707 -
708 - // Format name so there are only letters, numbers, and underscores
709 - $name = preg_replace( '/[^A-Za-z0-9_]/', '', $name );
710 -
711 - $dbr = wfGetDB( DB_SLAVE );
712 - $res = $dbr->select(
713 - 'cn_templates',
714 - 'tmp_name',
715 - array( 'tmp_name' => $name ),
716 - __METHOD__
717 - );
718 -
719 - if ( $dbr->numRows( $res ) > 0 ) {
720 - $this->showError( 'centralnotice-template-exists' );
721 - return false;
722 - } else {
723 - $dbw = wfGetDB( DB_MASTER );
724 - $res = $dbw->insert( 'cn_templates',
725 - array(
726 - 'tmp_name' => $name,
727 - 'tmp_display_anon' => $displayAnon,
728 - 'tmp_display_account' => $displayAccount
729 - ),
730 - __METHOD__
731 - );
732 -
733 - // Perhaps these should move into the db as blob
734 - $article = new Article(
735 - Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
736 - );
737 - $article->doEdit( $body, '', EDIT_FORCE_BOT );
738 - return true;
739 - }
740 - }
741 -
742 - /**
743 - * Update a banner
744 - */
745 - private function editTemplate( $name, $body, $displayAnon, $displayAccount ) {
746 - if ( $body == '' || $name == '' ) {
747 - $this->showError( 'centralnotice-null-string' );
748 - return;
749 - }
750 -
751 - $dbr = wfGetDB( DB_SLAVE );
752 - $res = $dbr->select( 'cn_templates', 'tmp_name',
753 - array( 'tmp_name' => $name ),
754 - __METHOD__
755 - );
756 -
757 - if ( $dbr->numRows( $res ) == 1 ) {
758 - $dbw = wfGetDB( DB_MASTER );
759 - $res = $dbw->update( 'cn_templates',
760 - array(
761 - 'tmp_display_anon' => $displayAnon,
762 - 'tmp_display_account' => $displayAccount
763 - ),
764 - array( 'tmp_name' => $name )
765 - );
766 -
767 - // Perhaps these should move into the db as blob
768 - $article = new Article(
769 - Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
770 - );
771 - $article->doEdit( $body, '', EDIT_FORCE_BOT );
772 - return;
773 - }
774 - }
775 -
776 - /**
777 - * Copy all the data from one banner to another
778 - */
779 - public function cloneTemplate( $source, $dest ) {
780 -
781 - // Reset the timer as updates on meta take a long time
782 - set_time_limit( 300 );
783 -
784 - // Pull all possible langs
785 - $langs = $this->getTranslations( $source );
786 -
787 - // Normalize name
788 - $dest = preg_replace( '/[^A-Za-z0-9_]/', '', $dest );
789 -
790 - // Pull banner settings from database
791 - $dbr = wfGetDB( DB_SLAVE );
792 - $row = $dbr->selectRow( 'cn_templates',
793 - array(
794 - 'tmp_display_anon',
795 - 'tmp_display_account'
796 - ),
797 - array( 'tmp_name' => $source ),
798 - __METHOD__
799 - );
800 - $displayAnon = $row->tmp_display_anon;
801 - $displayAccount = $row->tmp_display_account;
802 -
803 - // Pull banner text and respect any inc: markup
804 - $bodyPage = Title::newFromText( "Centralnotice-template-{$source}", NS_MEDIAWIKI );
805 - $template_body = Revision::newFromTitle( $bodyPage )->getText();
806 -
807 - // Create new banner
808 - if ( $this->addTemplate( $dest, $template_body, $displayAnon, $displayAccount ) ) {
809 -
810 - // Populate the fields
811 - foreach ( $langs as $lang => $fields ) {
812 - foreach ( $fields as $field => $text ) {
813 - $this->updateMessage( "$dest-$field", $text, $lang );
814 - }
815 - }
816 - return $dest;
817 - }
818 - }
819 -
820 - /**
821 - * Find all message fields set for a banner
822 - */
823 - private function findFields( $template ) {
824 - $body = wfMsg( "Centralnotice-template-{$template}" );
825 -
826 - // Generate list of message fields from parsing the body
827 - $fields = array();
828 - $allowedChars = Title::legalChars();
829 - preg_match_all( "/\{\{\{([$allowedChars]+)\}\}\}/u", $body, $fields );
830 -
831 - // Remove duplicates
832 - $filteredFields = array();
833 - foreach ( $fields[1] as $field ) {
834 - $filteredFields[$field] = array_key_exists( $field, $filteredFields )
835 - ? $filteredFields[$field] + 1
836 - : 1;
837 - }
838 - return $filteredFields;
839 - }
840 -
841 - /**
842 - * Get all the translations of all the messages for a banner
843 - * @return a 2D array of every set message in every language for one banner
844 - */
845 - public function getTranslations( $template ) {
846 - $translations = array();
847 -
848 - // Pull all language codes to enumerate
849 - $allLangs = array_keys( Language::getLanguageNames() );
850 -
851 - // Lookup all the message fields for a banner
852 - $fields = $this->findFields( $template );
853 -
854 - // Iterate through all possible languages to find matches
855 - foreach ( $allLangs as $lang ) {
856 - // Iterate through all possible message fields
857 - foreach ( $fields as $field => $count ) {
858 - // Put all message fields together for a lookup
859 - $message = ( $lang == 'en' )
860 - ? "Centralnotice-{$template}-{$field}"
861 - : "Centralnotice-{$template}-{$field}/{$lang}";
862 - if ( Title::newFromText( $message, NS_MEDIAWIKI )->exists() ) {
863 - $translations[$lang][$field] = wfMsgExt(
864 - "Centralnotice-{$template}-{$field}",
865 - array( 'language' => $lang )
866 - );
867 - }
868 - }
869 - }
870 - return $translations;
871 - }
872 -
873 - function showError( $message ) {
874 - global $wgOut;
875 - $wgOut->wrapWikiMsg( "<div class='cn-error'>\n$1\n</div>", $message );
876 - $this->centralNoticeError = true;
877 - }
878 -
879 - public static function templateExists( $templateName ) {
880 - $dbr = wfGetDB( DB_SLAVE );
881 - $eTemplateName = htmlspecialchars( $templateName );
882 - $row = $dbr->selectRow( 'cn_templates', 'tmp_name',
883 - array( 'tmp_name' => $eTemplateName ) );
884 - if ( $row ) {
885 - return true;
886 - } else {
887 - return false;
888 - }
889 - }
890 -}
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerListLoader.php
@@ -0,0 +1,79 @@
 2+<?php
 3+
 4+/**
 5+ * Generates JSON files listing all the banners for a particular site
 6+ */
 7+class SpecialBannerListLoader extends UnlistedSpecialPage {
 8+ public $project; // Project name
 9+ public $language; // Project language
 10+ public $location; // User country
 11+ protected $sharedMaxAge = 300; // Cache for 5 minutes on the server side
 12+ protected $maxAge = 300; // Cache for 5 minutes on the client side
 13+
 14+ function __construct() {
 15+ // Register special page
 16+ parent::__construct( "BannerListLoader" );
 17+ }
 18+
 19+ function execute( $par ) {
 20+ global $wgOut, $wgRequest;
 21+
 22+ $wgOut->disable();
 23+ $this->sendHeaders();
 24+
 25+ // Get project language from the query string
 26+ $this->language = $wgRequest->getText( 'language', 'en' );
 27+
 28+ // Get project name from the query string
 29+ $this->project = $wgRequest->getText( 'project', 'wikipedia' );
 30+
 31+ // Get location from the query string
 32+ $this->location = $wgRequest->getText( 'country' );
 33+
 34+ if ( $this->project && $this->language ) {
 35+ $content = $this->getJsonList();
 36+ if ( strlen( $content ) == 0 ) {
 37+ // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
 38+ echo "/* Empty */";
 39+ } else {
 40+ echo $content;
 41+ }
 42+ } else {
 43+ echo "/* No site specified */";
 44+ }
 45+ }
 46+
 47+ /**
 48+ * Generate the HTTP response headers for the banner file
 49+ */
 50+ function sendHeaders() {
 51+ global $wgJsMimeType;
 52+ header( "Content-type: $wgJsMimeType; charset=utf-8" );
 53+ header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
 54+ }
 55+
 56+ /**
 57+ * Generate JSON for the specified site
 58+ */
 59+ function getJsonList() {
 60+ $banners = array();
 61+
 62+ // See if we have any preferred campaigns for this language and project
 63+ $campaigns = CentralNoticeDB::getCampaigns( $this->project, $this->language, null, 1, 1, $this->location );
 64+
 65+ // Quick short circuit to show preferred campaigns
 66+ if ( $campaigns ) {
 67+ // Pull banners
 68+ $banners = CentralNoticeDB::selectBannersAssigned( $campaigns );
 69+ }
 70+
 71+ // Didn't find any preferred banners so do an old style lookup
 72+ if ( !$banners ) {
 73+ $banners = CentralNotice::selectNoticeTemplates(
 74+ $this->project, $this->language, $this->location );
 75+ }
 76+
 77+ return FormatJson::encode( $banners );
 78+ }
 79+
 80+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerListLoader.php
___________________________________________________________________
Added: svn:eol-style
181 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerController.php
@@ -0,0 +1,210 @@
 2+<?php
 3+
 4+/**
 5+ * Generates Javascript file which controls banner selection on the client side
 6+ */
 7+class SpecialBannerController extends UnlistedSpecialPage {
 8+ protected $sharedMaxAge = 3600; // Cache for 1 hour on the server side
 9+ protected $maxAge = 3600; // Cache for 1 hour on the client side
 10+
 11+ function __construct() {
 12+ // Register special page
 13+ parent::__construct( "BannerController" );
 14+ }
 15+
 16+ function execute( $par ) {
 17+ global $wgOut;
 18+
 19+ $wgOut->disable();
 20+ $this->sendHeaders();
 21+
 22+ $content = $this->getOutput();
 23+ if ( strlen( $content ) == 0 ) {
 24+ // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
 25+ echo "/* Empty */";
 26+ } else {
 27+ echo $content;
 28+ }
 29+ }
 30+
 31+ /**
 32+ * Generate the HTTP response headers for the banner controller
 33+ */
 34+ function sendHeaders() {
 35+ global $wgJsMimeType;
 36+ header( "Content-type: $wgJsMimeType; charset=utf-8" );
 37+ header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
 38+ }
 39+
 40+ /**
 41+ * Generate the body for the Javascript file
 42+ *
 43+ * We use a jsonp scheme for actual delivery of the banner so that they can be served from meta.
 44+ * In order to circumvent the normal squid cache override we add '/cn.js' to the bannerlist URL.
 45+ */
 46+ function getOutput() {
 47+ global $wgCentralPagePath, $wgNoticeFundraisingUrl, $wgContLang;
 48+
 49+ $js = $this->getScriptFunctions() . $this->getToggleScripts();
 50+ $js .= <<<JAVASCRIPT
 51+( function( $ ) {
 52+ $.ajaxSetup({ cache: true });
 53+ $.centralNotice = {
 54+ 'data': {
 55+ 'getVars': {}
 56+ },
 57+ 'fn': {
 58+ 'loadBanner': function( bannerName, fundraising, landingPages, campaign ) {
 59+ // Get the requested banner
 60+ var bannerPageQuery = $.param( {
 61+ 'banner': bannerName, 'campaign': campaign, 'userlang': wgUserLanguage,
 62+ 'db': wgDBname, 'sitename': wgSiteName, 'country': Geo.country,
 63+ 'fundraising': fundraising, 'landingpages': landingPages
 64+ } );
 65+ var bannerPage = '?title=Special:BannerLoader&' + bannerPageQuery;
 66+JAVASCRIPT;
 67+ $js .= "\n\t\t\t\tvar bannerScript = '<script type=\"text/javascript\" src=\"" .
 68+ Xml::escapeJsString( $wgCentralPagePath ) .
 69+ "' + bannerPage + '\"></script>';\n";
 70+ $js .= <<<JAVASCRIPT
 71+ $( '#siteNotice' ).prepend( '<div id="centralNotice" class="' +
 72+ ( wgNoticeToggleState ? 'expanded' : 'collapsed' ) +
 73+ '">'+bannerScript+'</div>' );
 74+ },
 75+ 'loadBannerList': function( geoOverride ) {
 76+ if ( geoOverride ) {
 77+ var geoLocation = geoOverride; // override the geo info
 78+ } else {
 79+ var geoLocation = Geo.country; // pull the geo info
 80+ }
 81+ var bannerListQuery = $.param( { 'language': wgContentLanguage, 'project': wgNoticeProject, 'country': geoLocation } );
 82+JAVASCRIPT;
 83+ $js .= "\n\t\t\t\tvar bannerListURL = wgScript + '?title=' + encodeURIComponent('" .
 84+ $wgContLang->specialPage( 'BannerListLoader' ) .
 85+ "') + '&cache=/cn.js&' + bannerListQuery;\n";
 86+ $js .= <<<JAVASCRIPT
 87+ var request = $.ajax( {
 88+ url: bannerListURL,
 89+ dataType: 'json',
 90+ success: $.centralNotice.fn.chooseBanner
 91+ } );
 92+ },
 93+ 'chooseBanner': function( bannerList ) {
 94+ // Convert the json object to a true array
 95+ bannerList = Array.prototype.slice.call( bannerList );
 96+
 97+ // Make sure there are some banners to choose from
 98+ if ( bannerList.length == 0 ) return false;
 99+
 100+ var groomedBannerList = [];
 101+
 102+ for( var i = 0; i < bannerList.length; i++ ) {
 103+ // Only include this banner if it's intended for the current user
 104+ if( ( wgUserName && bannerList[i].display_account ) ||
 105+ ( !wgUserName && bannerList[i].display_anon == 1 ) )
 106+ {
 107+ // add the banner to our list once per weight
 108+ for( var j=0; j < bannerList[i].weight; j++ ) {
 109+ groomedBannerList.push( bannerList[i] );
 110+ }
 111+ }
 112+ }
 113+
 114+ // Return if there's nothing left after the grooming
 115+ if( groomedBannerList.length == 0 ) return false;
 116+
 117+ // Choose a random key
 118+ var pointer = Math.floor( Math.random() * groomedBannerList.length );
 119+
 120+ // Load a random banner from our groomed list
 121+ $.centralNotice.fn.loadBanner(
 122+ groomedBannerList[pointer].name,
 123+ groomedBannerList[pointer].fundraising,
 124+ groomedBannerList[pointer].landing_pages,
 125+ groomedBannerList[pointer].campaign
 126+ );
 127+ },
 128+ 'getQueryStringVariables': function() {
 129+ document.location.search.replace( /\??(?:([^=]+)=([^&]*)&?)/g, function () {
 130+ function decode( s ) {
 131+ return decodeURIComponent( s.split( "+" ).join( " " ) );
 132+ }
 133+ $.centralNotice.data.getVars[decode( arguments[1] )] = decode( arguments[2] );
 134+ } );
 135+ }
 136+ }
 137+ }
 138+ $( document ).ready( function () {
 139+ // Initialize the query string vars
 140+ $.centralNotice.fn.getQueryStringVariables();
 141+ if( $.centralNotice.data.getVars['banner'] ) {
 142+ // if we're forcing one banner
 143+ $.centralNotice.fn.loadBanner( $.centralNotice.data.getVars['banner'] );
 144+ } else {
 145+ // Look for banners ready to go NOW
 146+ $.centralNotice.fn.loadBannerList( $.centralNotice.data.getVars['country'] );
 147+ }
 148+ } ); //document ready
 149+} )( jQuery );
 150+JAVASCRIPT;
 151+ return $js;
 152+
 153+ }
 154+
 155+ function getToggleScripts() {
 156+ $script = "var wgNoticeToggleState = (document.cookie.indexOf('hidesnmessage=1')==-1);\n\n";
 157+ return $script;
 158+ }
 159+
 160+ function getScriptFunctions() {
 161+ global $wgNoticeFundraisingUrl;
 162+ $script = <<<JAVASCRIPT
 163+function insertBanner(bannerJson) {
 164+ jQuery( 'div#centralNotice' ).prepend( bannerJson.bannerHtml );
 165+ if ( bannerJson.fundraising ) {
 166+JAVASCRIPT;
 167+ $script .= "\n\t\tvar url = '" .
 168+ Xml::escapeJsString( $wgNoticeFundraisingUrl ) . "';";
 169+ $script .= <<<JAVASCRIPT
 170+ if ( bannerJson.landingPages.length ) {
 171+ targets = String( bannerJson.landingPages ).split(',');
 172+ url += "?" + jQuery.param( {
 173+ 'landing_page': targets[Math.floor( Math.random() * targets.length )].replace( /^\s+|\s+$/, '' )
 174+ } );
 175+ url += "&" + jQuery.param( {
 176+ 'utm_medium': 'sitenotice', 'utm_campaign': bannerJson.campaign,
 177+ 'utm_source': bannerJson.bannerName, 'language': wgUserLanguage,
 178+ 'country': Geo.country
 179+ } );
 180+ jQuery( '#cn_fundraising_link' ).attr( 'href', url );
 181+ }
 182+ }
 183+}
 184+function toggleNotice() {
 185+ var notice = document.getElementById('centralNotice');
 186+ if (!wgNoticeToggleState) {
 187+ notice.className = notice.className.replace('collapsed', 'expanded');
 188+ toggleNoticeCookie('0');
 189+ } else {
 190+ notice.className = notice.className.replace('expanded', 'collapsed');
 191+ toggleNoticeCookie('1');
 192+ }
 193+ wgNoticeToggleState = !wgNoticeToggleState;
 194+}
 195+function toggleNoticeStyle(elems, display) {
 196+ if(elems)
 197+ for(var i=0;i<elems.length;i++)
 198+ elems[i].style.display = display;
 199+}
 200+function toggleNoticeCookie(state) {
 201+ var e = new Date();
 202+ e.setTime( e.getTime() + (7*24*60*60*1000) ); // one week
 203+ var work='hidesnmessage='+state+'; expires=' + e.toGMTString() + '; path=/';
 204+ document.cookie = work;
 205+}
 206+
 207+JAVASCRIPT;
 208+ return $script;
 209+ }
 210+
 211+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerController.php
___________________________________________________________________
Added: svn:eol-style
1212 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialCentralNotice.php
@@ -0,0 +1,1898 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class CentralNotice extends SpecialPage {
 10+ var $editable, $centralNoticeError;
 11+
 12+ function __construct() {
 13+ // Register special page
 14+ parent::__construct( 'CentralNotice' );
 15+ }
 16+
 17+ /**
 18+ * Handle different types of page requests
 19+ */
 20+ function execute( $sub ) {
 21+ global $wgOut, $wgUser, $wgRequest, $wgExtensionAssetsPath;
 22+
 23+ // Begin output
 24+ $this->setHeaders();
 25+ $this->outputHeader();
 26+
 27+ // Add style file to the output headers
 28+ $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
 29+
 30+ // Add script file to the output headers
 31+ $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
 32+
 33+ // Check permissions
 34+ $this->editable = $wgUser->isAllowed( 'centralnotice-admin' );
 35+
 36+ // Initialize error variable
 37+ $this->centralNoticeError = false;
 38+
 39+ // Show header
 40+ $this->printHeader( $sub );
 41+
 42+ // Begin Campaigns tab content
 43+ $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
 44+
 45+ $method = $wgRequest->getVal( 'method' );
 46+
 47+ // Switch to campaign detail interface if requested
 48+ if ( $method == 'listNoticeDetail' ) {
 49+ $notice = $wgRequest->getVal ( 'notice' );
 50+ $this->listNoticeDetail( $notice );
 51+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 52+ return;
 53+ }
 54+
 55+ // Handle form submissions from "Manage campaigns" or "Add a campaign" interface
 56+ if ( $this->editable && $wgRequest->wasPosted() ) {
 57+
 58+ // Check authentication token
 59+ if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
 60+
 61+ // Handle removing campaigns
 62+ $toRemove = $wgRequest->getArray( 'removeNotices' );
 63+ if ( $toRemove ) {
 64+ // Remove campaigns in list
 65+ foreach ( $toRemove as $notice ) {
 66+ $this->removeNotice( $notice );
 67+ }
 68+
 69+ // Skip subsequent form handling and show list of campaigns
 70+ $this->listNotices();
 71+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 72+ return;
 73+ }
 74+
 75+ // Handle locking/unlocking campaigns
 76+ $lockedNotices = $wgRequest->getArray( 'locked' );
 77+ if ( $lockedNotices ) {
 78+ // Build list of campaigns to lock
 79+ $unlockedNotices = array_diff( $this->getAllCampaignNames(), $lockedNotices );
 80+
 81+ // Set locked/unlocked flag accordingly
 82+ foreach ( $lockedNotices as $notice ) {
 83+ $this->updateLock( $notice, '1' );
 84+ }
 85+ foreach ( $unlockedNotices as $notice ) {
 86+ $this->updateLock( $notice, '0' );
 87+ }
 88+ // Handle updates if no post content came through (all checkboxes unchecked)
 89+ } elseif ( $method !== 'addNotice' ) {
 90+ $allNotices = $this->getAllCampaignNames();
 91+ foreach ( $allNotices as $notice ) {
 92+ $this->updateLock( $notice, '0' );
 93+ }
 94+ }
 95+
 96+ // Handle enabling/disabling campaigns
 97+ $enabledNotices = $wgRequest->getArray( 'enabled' );
 98+ if ( $enabledNotices ) {
 99+ // Build list of campaigns to disable
 100+ $disabledNotices = array_diff( $this->getAllCampaignNames(), $enabledNotices );
 101+
 102+ // Set enabled/disabled flag accordingly
 103+ foreach ( $enabledNotices as $notice ) {
 104+ $this->updateEnabled( $notice, '1' );
 105+ }
 106+ foreach ( $disabledNotices as $notice ) {
 107+ $this->updateEnabled( $notice, '0' );
 108+ }
 109+ // Handle updates if no post content came through (all checkboxes unchecked)
 110+ } elseif ( $method !== 'addNotice' ) {
 111+ $allNotices = $this->getAllCampaignNames();
 112+ foreach ( $allNotices as $notice ) {
 113+ $this->updateEnabled( $notice, '0' );
 114+ }
 115+ }
 116+
 117+ // Handle setting preferred campaigns
 118+ $preferredNotices = $wgRequest->getArray( 'preferred' );
 119+ if ( $preferredNotices ) {
 120+ // Build list of campaigns to unset
 121+ $unsetNotices = array_diff( $this->getAllCampaignNames(), $preferredNotices );
 122+
 123+ // Set flag accordingly
 124+ foreach ( $preferredNotices as $notice ) {
 125+ $this->updatePreferred( $notice, '1' );
 126+ }
 127+ foreach ( $unsetNotices as $notice ) {
 128+ $this->updatePreferred( $notice, '0' );
 129+ }
 130+ // Handle updates if no post content came through (all checkboxes unchecked)
 131+ } elseif ( $method !== 'addNotice' ) {
 132+ $allNotices = $this->getAllCampaignNames();
 133+ foreach ( $allNotices as $notice ) {
 134+ $this->updatePreferred( $notice, '0' );
 135+ }
 136+ }
 137+
 138+ // Handle adding of campaign
 139+ if ( $method == 'addNotice' ) {
 140+ $noticeName = $wgRequest->getVal( 'noticeName' );
 141+ $start = $wgRequest->getArray( 'start' );
 142+ $projects = $wgRequest->getArray( 'projects' );
 143+ $project_languages = $wgRequest->getArray( 'project_languages' );
 144+ $geotargeted = $wgRequest->getCheck( 'geotargeted' );
 145+ $geo_countries = $wgRequest->getArray( 'geo_countries' );
 146+ if ( $noticeName == '' ) {
 147+ $this->showError( 'centralnotice-null-string' );
 148+ } else {
 149+ $this->addNotice( $noticeName, '0', $start, $projects,
 150+ $project_languages, $geotargeted, $geo_countries );
 151+ }
 152+ }
 153+
 154+ // If there were no errors, reload the page to prevent duplicate form submission
 155+ if ( !$this->centralNoticeError ) {
 156+ $wgOut->redirect( $this->getTitle()->getLocalUrl() );
 157+ return;
 158+ }
 159+
 160+ } else {
 161+ $this->showError( 'sessionfailure' );
 162+ }
 163+
 164+ }
 165+
 166+ // Show list of campaigns
 167+ $this->listNotices();
 168+
 169+ // End Campaigns tab content
 170+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 171+ }
 172+
 173+ /**
 174+ * Output the tabs for the different CentralNotice interfaces (Allocation, Logs, etc.)
 175+ */
 176+ public static function printHeader() {
 177+ global $wgOut, $wgTitle, $wgUser;
 178+ $sk = $wgUser->getSkin();
 179+
 180+ $pages = array(
 181+ 'CentralNotice' => wfMsg( 'centralnotice-notices' ),
 182+ 'NoticeTemplate' => wfMsg ( 'centralnotice-templates' ),
 183+ 'BannerAllocation' => wfMsg ( 'centralnotice-allocation' )
 184+ );
 185+ $htmlOut = Xml::openElement( 'ul', array( 'id' => 'preftoc' ) );
 186+ foreach ( $pages as $page => $msg ) {
 187+ $title = SpecialPage::getTitleFor( $page );
 188+ $attribs = array();
 189+ if ( $wgTitle->equals( $title ) ) {
 190+ $attribs['class'] = 'selected';
 191+ }
 192+ $htmlOut .= Xml::tags( 'li', $attribs,
 193+ $sk->makeLinkObj( $title, htmlspecialchars( $msg ) )
 194+ );
 195+ }
 196+ $htmlOut .= Xml::closeElement( 'ul' );
 197+
 198+ $wgOut->addHTML( $htmlOut );
 199+ }
 200+
 201+ /**
 202+ * Get all the campaigns in the database
 203+ * @return an array of campaign names
 204+ */
 205+ function getAllCampaignNames() {
 206+ $dbr = wfGetDB( DB_SLAVE );
 207+ $res = $dbr->select( 'cn_notices', 'not_name', null, __METHOD__ );
 208+ $notices = array();
 209+ foreach ( $res as $row ) {
 210+ $notices[] = $row->not_name;
 211+ }
 212+ return $notices;
 213+ }
 214+
 215+ /**
 216+ * Build a table row. Needed since Xml::buildTableRow escapes all HTML.
 217+ */
 218+ function tableRow( $fields, $element = 'td', $attribs = array() ) {
 219+ $cells = array();
 220+ foreach ( $fields as $field ) {
 221+ $cells[] = Xml::tags( $element, array(), $field );
 222+ }
 223+ return Xml::tags( 'tr', $attribs, implode( "\n", $cells ) ) . "\n";
 224+ }
 225+
 226+ function dateSelector( $prefix, $timestamp = null ) {
 227+ if ( $this->editable ) {
 228+ // Default ranges...
 229+ $years = range( 2008, 2014 );
 230+ $months = range( 1, 12 );
 231+ $months = array_map( array( $this, 'addZero' ), $months );
 232+ $days = range( 1 , 31 );
 233+ $days = array_map( array( $this, 'addZero' ), $days );
 234+
 235+ // Normalize timestamp format. If no timestamp passed, defaults to now.
 236+ $ts = wfTimestamp( TS_MW, $timestamp );
 237+
 238+ $fields = array(
 239+ array( "month", "centralnotice-month", $months, substr( $ts, 4, 2 ) ),
 240+ array( "day", "centralnotice-day", $days, substr( $ts, 6, 2 ) ),
 241+ array( "year", "centralnotice-year", $years, substr( $ts, 0, 4 ) ),
 242+ );
 243+
 244+ return $this->createSelector( $prefix, $fields );
 245+ } else {
 246+ global $wgLang;
 247+ return $wgLang->date( $timestamp );
 248+ }
 249+ }
 250+
 251+ function timeSelector( $prefix, $timestamp = null ) {
 252+ if ( $this->editable ) {
 253+ // Default ranges...
 254+ $minutes = range( 0, 59 ); // formerly in 15-minute increments
 255+ $minutes = array_map( array( $this, 'addZero' ), $minutes );
 256+ $hours = range( 0 , 23 );
 257+ $hours = array_map( array( $this, 'addZero' ), $hours );
 258+
 259+ // Normalize timestamp format...
 260+ $ts = wfTimestamp( TS_MW, $timestamp );
 261+
 262+ $fields = array(
 263+ array( "hour", "centralnotice-hours", $hours, substr( $ts, 8, 2 ) ),
 264+ array( "min", "centralnotice-min", $minutes, substr( $ts, 10, 2 ) ),
 265+ );
 266+
 267+ return $this->createSelector( $prefix, $fields );
 268+ } else {
 269+ global $wgLang;
 270+ return $wgLang->time( $timestamp );
 271+ }
 272+ }
 273+
 274+ /**
 275+ * Build a set of select lists. Used by dateSelector and timeSelector.
 276+ * @param $prefix string
 277+ * @param $fields array
 278+ */
 279+ private function createSelector( $prefix, $fields ) {
 280+ $out = '';
 281+ foreach ( $fields as $data ) {
 282+ list( $field, $label, $set, $current ) = $data;
 283+ $out .= Xml::listDropDown( "{$prefix}[{$field}]",
 284+ $this->dropDownList( wfMsg( $label ), $set ),
 285+ '',
 286+ $current );
 287+ }
 288+ return $out;
 289+ }
 290+
 291+ /**
 292+ * Show all campaigns found in the database, show "Add a campaign" form
 293+ */
 294+ function listNotices() {
 295+ global $wgOut, $wgUser, $wgLang, $wgRequest, $wgNoticeProjects;
 296+
 297+ // Get connection
 298+ $dbr = wfGetDB( DB_SLAVE );
 299+ $sk = $wgUser->getSkin();
 300+ if ( $this->editable ) {
 301+ $readonly = array();
 302+ } else {
 303+ $readonly = array( 'disabled' => 'disabled' );
 304+ }
 305+
 306+ // Get all campaigns from the database
 307+ $res = $dbr->select( 'cn_notices',
 308+ array(
 309+ 'not_name',
 310+ 'not_start',
 311+ 'not_end',
 312+ 'not_enabled',
 313+ 'not_preferred',
 314+ 'not_locked'
 315+ ),
 316+ null,
 317+ __METHOD__,
 318+ array( 'ORDER BY' => 'not_id DESC' )
 319+ );
 320+
 321+ // Begin building HTML
 322+ $htmlOut = '';
 323+
 324+ // Begin Manage campaigns fieldset
 325+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 326+
 327+ // If there are campaigns to show...
 328+ if ( $dbr->numRows( $res ) >= 1 ) {
 329+ if ( $this->editable ) {
 330+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 331+ }
 332+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-manage' ) );
 333+
 334+ // Begin table of campaigns
 335+ $htmlOut .= Xml::openElement( 'table',
 336+ array(
 337+ 'cellpadding' => 9,
 338+ 'width' => '100%',
 339+ 'class' => 'wikitable sortable'
 340+ )
 341+ );
 342+
 343+ // Table headers
 344+ $headers = array(
 345+ wfMsgHtml( 'centralnotice-notice-name' ),
 346+ wfMsgHtml( 'centralnotice-projects' ),
 347+ wfMsgHtml( 'centralnotice-languages' ),
 348+ wfMsgHtml( 'centralnotice-start-date' ),
 349+ wfMsgHtml( 'centralnotice-end-date' ),
 350+ wfMsgHtml( 'centralnotice-enabled' ),
 351+ wfMsgHtml( 'centralnotice-preferred' ),
 352+ wfMsgHtml( 'centralnotice-locked' ),
 353+ );
 354+ if ( $this->editable ) {
 355+ $headers[] = wfMsgHtml( 'centralnotice-remove' );
 356+ }
 357+ $htmlOut .= $this->tableRow( $headers, 'th' );
 358+
 359+ // Table rows
 360+ foreach ( $res as $row ) {
 361+ $fields = array();
 362+
 363+ // Name
 364+ $fields[] = $sk->makeLinkObj( $this->getTitle(),
 365+ htmlspecialchars( $row->not_name ),
 366+ 'method=listNoticeDetail&notice=' . urlencode( $row->not_name ) );
 367+
 368+ // Projects
 369+ $projects = $this->getNoticeProjects( $row->not_name );
 370+ $project_count = count( $projects );
 371+ $projectList = '';
 372+ if ( $project_count > 1 ) {
 373+ $allProjects = true;
 374+ foreach ( $wgNoticeProjects as $project ) {
 375+ if ( !in_array( $project, $projects ) ) {
 376+ $allProjects = false;
 377+ break;
 378+ }
 379+ }
 380+ if ( $allProjects ) {
 381+ $projectList = wfMsg ( 'centralnotice-all-projects' );
 382+ } else {
 383+ $projectList = wfMsg ( 'centralnotice-multiple-projects', $project_count );
 384+ }
 385+ } elseif ( $project_count == 1 ) {
 386+ $projectList = htmlspecialchars( $projects[0] );
 387+ }
 388+ $fields[] = $projectList;
 389+
 390+ // Languages
 391+ $project_langs = $this->getNoticeLanguages( $row->not_name );
 392+ $language_count = count( $project_langs );
 393+ $languageList = '';
 394+ if ( $language_count > 3 ) {
 395+ $languageList = wfMsg ( 'centralnotice-multiple-languages', $language_count );
 396+ } elseif ( $language_count > 0 ) {
 397+ $languageList = $wgLang->commaList( $project_langs );
 398+ }
 399+ $fields[] = $languageList;
 400+
 401+ // Date and time calculations
 402+ $start_timestamp = wfTimestamp( TS_MW, $row->not_start );
 403+ $start_year = substr( $start_timestamp, 0 , 4 );
 404+ $start_month = substr( $start_timestamp, 4, 2 );
 405+ $start_day = substr( $start_timestamp, 6, 2 );
 406+ $start_hour = substr( $start_timestamp, 8, 2 );
 407+ $start_min = substr( $start_timestamp, 10, 2 );
 408+ $end_timestamp = wfTimestamp( TS_MW, $row->not_end );
 409+ $end_year = substr( $end_timestamp, 0 , 4 );
 410+ $end_month = substr( $end_timestamp, 4, 2 );
 411+ $end_day = substr( $end_timestamp, 6, 2 );
 412+ $end_hour = substr( $end_timestamp, 8, 2 );
 413+ $end_min = substr( $end_timestamp, 10, 2 );
 414+
 415+ // Start
 416+ $fields[] = "{$start_year}/{$start_month}/{$start_day} {$start_hour}:{$start_min}";
 417+
 418+ // End
 419+ $fields[] = "{$end_year}/{$end_month}/{$end_day} {$end_hour}:{$end_min}";
 420+
 421+ // Enabled
 422+ $fields[] =
 423+ Xml::check( 'enabled[]', ( $row->not_enabled == '1' ),
 424+ wfArrayMerge( $readonly,
 425+ array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
 426+
 427+ // Preferred
 428+ $fields[] =
 429+ Xml::check( 'preferred[]', ( $row->not_preferred == '1' ),
 430+ wfArrayMerge( $readonly,
 431+ array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
 432+
 433+ // Locked
 434+ $fields[] =
 435+ Xml::check( 'locked[]', ( $row->not_locked == '1' ),
 436+ wfArrayMerge( $readonly,
 437+ array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) ) );
 438+
 439+ if ( $this->editable ) {
 440+ // Remove
 441+ $fields[] = Xml::check( 'removeNotices[]', false,
 442+ array( 'value' => $row->not_name, 'class' => 'noshiftselect' ) );
 443+ }
 444+
 445+ // If campaign is currently active, set special class on table row.
 446+ $attribs = array();
 447+ if ( wfTimestamp() > wfTimestamp( TS_UNIX , $row->not_start )
 448+ && wfTimestamp() < wfTimestamp( TS_UNIX , $row->not_end )
 449+ && $row->not_enabled == '1' )
 450+ {
 451+ $attribs = array( 'class' => 'cn-active-campaign' );
 452+ }
 453+
 454+ $htmlOut .= $this->tableRow( $fields, 'td', $attribs );
 455+ }
 456+ // End table of campaigns
 457+ $htmlOut .= Xml::closeElement( 'table' );
 458+
 459+ if ( $this->editable ) {
 460+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 461+ $htmlOut .= Xml::openElement( 'div', array( 'class' => 'cn-buttons' ) );
 462+ $htmlOut .= Xml::submitButton( wfMsg( 'centralnotice-modify' ),
 463+ array(
 464+ 'id' => 'centralnoticesubmit',
 465+ 'name' => 'centralnoticesubmit'
 466+ )
 467+ );
 468+ $htmlOut .= Xml::closeElement( 'div' );
 469+ $htmlOut .= Xml::closeElement( 'form' );
 470+ }
 471+
 472+ // No campaigns to show
 473+ } else {
 474+ $htmlOut .= wfMsg( 'centralnotice-no-notices-exist' );
 475+ }
 476+
 477+ // End Manage Campaigns fieldset
 478+ $htmlOut .= Xml::closeElement( 'fieldset' );
 479+
 480+ if ( $this->editable ) {
 481+
 482+ // If there was an error, we'll need to restore the state of the form
 483+ if ( $wgRequest->wasPosted() && ( $wgRequest->getVal( 'method' ) == 'addNotice' ) ) {
 484+ $startArray = $wgRequest->getArray( 'start' );
 485+ $startTimestamp = $startArray['year'] .
 486+ $startArray['month'] .
 487+ $startArray['day'] .
 488+ $startArray['hour'] .
 489+ $startArray['min'] . '00'
 490+ ;
 491+ $noticeProjects = $wgRequest->getArray( 'projects', array() );
 492+ $noticeLanguages = $wgRequest->getArray( 'project_languages', array() );
 493+ } else { // Defaults
 494+ $startTimestamp = null;
 495+ $noticeProjects = array();
 496+ $noticeLanguages = array();
 497+ }
 498+
 499+ // Begin Add a campaign fieldset
 500+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 501+
 502+ // Form for adding a campaign
 503+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 504+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-add-notice' ) );
 505+ $htmlOut .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
 506+ $htmlOut .= Html::hidden( 'method', 'addNotice' );
 507+
 508+ $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
 509+
 510+ // Name
 511+ $htmlOut .= Xml::openElement( 'tr' );
 512+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-notice-name' ) );
 513+ $htmlOut .= Xml::tags( 'td', array(),
 514+ Xml::input( 'noticeName', 25, $wgRequest->getVal( 'noticeName' ) ) );
 515+ $htmlOut .= Xml::closeElement( 'tr' );
 516+ // Start Date
 517+ $htmlOut .= Xml::openElement( 'tr' );
 518+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-date' ) );
 519+ $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'start', $startTimestamp ) );
 520+ $htmlOut .= Xml::closeElement( 'tr' );
 521+ // Start Time
 522+ $htmlOut .= Xml::openElement( 'tr' );
 523+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-time' ) );
 524+ $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'start', $startTimestamp ) );
 525+ $htmlOut .= Xml::closeElement( 'tr' );
 526+ // Project
 527+ $htmlOut .= Xml::openElement( 'tr' );
 528+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 529+ wfMsgHtml( 'centralnotice-projects' ) );
 530+ $htmlOut .= Xml::tags( 'td', array(), $this->projectMultiSelector( $noticeProjects ) );
 531+ $htmlOut .= Xml::closeElement( 'tr' );
 532+ // Languages
 533+ $htmlOut .= Xml::openElement( 'tr' );
 534+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 535+ wfMsgHtml( 'centralnotice-languages' ) );
 536+ $htmlOut .= Xml::tags( 'td', array(),
 537+ $this->languageMultiSelector( $noticeLanguages ) );
 538+ $htmlOut .= Xml::closeElement( 'tr' );
 539+ // Countries
 540+ $htmlOut .= Xml::openElement( 'tr' );
 541+ $htmlOut .= Xml::tags( 'td', array(),
 542+ Xml::label( wfMsg( 'centralnotice-geotargeted' ), 'geotargeted' ) );
 543+ $htmlOut .= Xml::tags( 'td', array(),
 544+ Xml::check( 'geotargeted', false,
 545+ wfArrayMerge( $readonly, array( 'value' => 1, 'id' => 'geotargeted' ) ) ) );
 546+ $htmlOut .= Xml::closeElement( 'tr' );
 547+ $htmlOut .= Xml::openElement( 'tr',
 548+ array( 'id'=>'geoMultiSelector', 'style'=>'display:none;' ) );
 549+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 550+ wfMsgHtml( 'centralnotice-countries' ) );
 551+ $htmlOut .= Xml::tags( 'td', array(), $this->geoMultiSelector() );
 552+ $htmlOut .= Xml::closeElement( 'tr' );
 553+
 554+ $htmlOut .= Xml::closeElement( 'table' );
 555+ $htmlOut .= Html::hidden( 'change', 'weight' );
 556+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 557+
 558+ // Submit button
 559+ $htmlOut .= Xml::tags( 'div',
 560+ array( 'class' => 'cn-buttons' ),
 561+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 562+ );
 563+
 564+ $htmlOut .= Xml::closeElement( 'form' );
 565+
 566+ // End Add a campaign fieldset
 567+ $htmlOut .= Xml::closeElement( 'fieldset' );
 568+ }
 569+
 570+ // Output HTML
 571+ $wgOut->addHTML( $htmlOut );
 572+ }
 573+
 574+ /**
 575+ * Show the interface for viewing/editing an individual campaign
 576+ * @param $notice The name of the campaign to view
 577+ */
 578+ function listNoticeDetail( $notice ) {
 579+ global $wgOut, $wgRequest, $wgUser;
 580+
 581+ // Make sure notice exists
 582+ if ( !$this->noticeExists( $notice ) ) {
 583+ $this->showError( 'centralnotice-notice-doesnt-exist' );
 584+ } else {
 585+
 586+ // Handle form submissions from campaign detail interface
 587+ if ( $this->editable && $wgRequest->wasPosted() ) {
 588+
 589+ // Check authentication token
 590+ if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
 591+
 592+ // Handle removing campaign
 593+ if ( $wgRequest->getVal( 'remove' ) ) {
 594+ $this->removeNotice( $notice );
 595+ if ( !$this->centralNoticeError ) {
 596+ // Leave campaign detail interface
 597+ $wgOut->redirect( $this->getTitle()->getLocalUrl() );
 598+ return;
 599+ }
 600+ }
 601+
 602+ // Handle locking/unlocking campaign
 603+ if ( $wgRequest->getCheck( 'locked' ) ) {
 604+ $this->updateLock( $notice, '1' );
 605+ } else {
 606+ $this->updateLock( $notice, 0 );
 607+ }
 608+
 609+ // Handle enabling/disabling campaign
 610+ if ( $wgRequest->getCheck( 'enabled' ) ) {
 611+ $this->updateEnabled( $notice, '1' );
 612+ } else {
 613+ $this->updateEnabled( $notice, 0 );
 614+ }
 615+
 616+ // Handle setting campaign to preferred/not preferred
 617+ if ( $wgRequest->getCheck( 'preferred' ) ) {
 618+ $this->updatePreferred( $notice, '1' );
 619+ } else {
 620+ $this->updatePreferred( $notice, 0 );
 621+ }
 622+
 623+ // Handle updating geotargeting
 624+ if ( $wgRequest->getCheck( 'geotargeted' ) ) {
 625+ $this->updateGeotargeted( $notice, 1 );
 626+ $countries = $wgRequest->getArray( 'geo_countries' );
 627+ if ( $countries ) {
 628+ $this->updateCountries( $notice, $countries );
 629+ }
 630+ } else {
 631+ $this->updateGeotargeted( $notice, 0 );
 632+ }
 633+
 634+ // Handle updating the start and end settings
 635+ $start = $wgRequest->getArray( 'start' );
 636+ $end = $wgRequest->getArray( 'end' );
 637+ if ( $start && $end ) {
 638+ $updatedStart = sprintf( "%04d%02d%02d%02d%02d00",
 639+ $start['year'],
 640+ $start['month'],
 641+ $start['day'],
 642+ $start['hour'],
 643+ $start['min']
 644+ );
 645+ $updatedEnd = sprintf( "%04d%02d%02d%02d%02d00",
 646+ $end['year'],
 647+ $end['month'],
 648+ $end['day'],
 649+ $end['hour'],
 650+ $end['min']
 651+ );
 652+
 653+ $this->updateNoticeDate( $notice, $updatedStart, $updatedEnd );
 654+ }
 655+
 656+ // Handle adding of banners to the campaign
 657+ $templatesToAdd = $wgRequest->getArray( 'addTemplates' );
 658+ if ( $templatesToAdd ) {
 659+ $weight = $wgRequest->getArray( 'weight' );
 660+ foreach ( $templatesToAdd as $templateName ) {
 661+ $templateId = $this->getTemplateId( $templateName );
 662+ $this->addTemplateTo( $notice, $templateName, $weight[$templateId] );
 663+ }
 664+ }
 665+
 666+ // Handle removing of banners from the campaign
 667+ $templateToRemove = $wgRequest->getArray( 'removeTemplates' );
 668+ if ( $templateToRemove ) {
 669+ foreach ( $templateToRemove as $template ) {
 670+ $this->removeTemplateFor( $notice, $template );
 671+ }
 672+ }
 673+
 674+ // Handle weight changes
 675+ $updatedWeights = $wgRequest->getArray( 'weight' );
 676+ if ( $updatedWeights ) {
 677+ foreach ( $updatedWeights as $templateId => $weight ) {
 678+ $this->updateWeight( $notice, $templateId, $weight );
 679+ }
 680+ }
 681+
 682+ // Handle new projects
 683+ $projects = $wgRequest->getArray( 'projects' );
 684+ if ( $projects ) {
 685+ $this->updateProjects( $notice, $projects );
 686+ }
 687+
 688+ // Handle new project languages
 689+ $projectLangs = $wgRequest->getArray( 'project_languages' );
 690+ if ( $projectLangs ) {
 691+ $this->updateProjectLanguages( $notice, $projectLangs );
 692+ }
 693+
 694+ // If there were no errors, reload the page to prevent duplicate form submission
 695+ if ( !$this->centralNoticeError ) {
 696+ $wgOut->redirect( $this->getTitle()->getLocalUrl(
 697+ "method=listNoticeDetail&notice=$notice" ) );
 698+ return;
 699+ }
 700+ } else {
 701+ $this->showError( 'sessionfailure' );
 702+ }
 703+
 704+ }
 705+
 706+ $htmlOut = '';
 707+
 708+ // Begin Campaign detail fieldset
 709+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 710+
 711+ if ( $this->editable ) {
 712+ $htmlOut .= Xml::openElement( 'form',
 713+ array(
 714+ 'method' => 'post',
 715+ 'action' => $this->getTitle()->getLocalUrl(
 716+ "method=listNoticeDetail&notice=$notice" )
 717+ )
 718+ );
 719+ }
 720+
 721+ $output_detail = $this->noticeDetailForm( $notice );
 722+ $output_assigned = $this->assignedTemplatesForm( $notice );
 723+ $output_templates = $this->addTemplatesForm( $notice );
 724+
 725+ $htmlOut .= $output_detail;
 726+
 727+ // Catch for no banners so that we don't double message
 728+ if ( $output_assigned == '' && $output_templates == '' ) {
 729+ $htmlOut .= wfMsg( 'centralnotice-no-templates' );
 730+ $htmlOut .= Xml::element( 'p' );
 731+ $newPage = $this->getTitleFor( 'NoticeTemplate', 'add' );
 732+ $sk = $wgUser->getSkin();
 733+ $htmlOut .= $sk->makeLinkObj( $newPage, wfMsgHtml( 'centralnotice-add-template' ) );
 734+ $htmlOut .= Xml::element( 'p' );
 735+ } elseif ( $output_assigned == '' ) {
 736+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-assigned-templates' ) );
 737+ $htmlOut .= wfMsg( 'centralnotice-no-templates-assigned' );
 738+ $htmlOut .= Xml::closeElement( 'fieldset' );
 739+ if ( $this->editable ) {
 740+ $htmlOut .= $output_templates;
 741+ }
 742+ } else {
 743+ $htmlOut .= $output_assigned;
 744+ if ( $this->editable ) {
 745+ $htmlOut .= $output_templates;
 746+ }
 747+ }
 748+ if ( $this->editable ) {
 749+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 750+
 751+ // Submit button
 752+ $htmlOut .= Xml::tags( 'div',
 753+ array( 'class' => 'cn-buttons' ),
 754+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 755+ );
 756+ }
 757+
 758+ if ( $this->editable ) {
 759+ $htmlOut .= Xml::closeElement( 'form' );
 760+ }
 761+ $htmlOut .= Xml::closeElement( 'fieldset' );
 762+ $wgOut->addHTML( $htmlOut );
 763+ }
 764+ }
 765+
 766+ /**
 767+ * Create form for managing campaign settings (start date, end date, languages, etc.)
 768+ */
 769+ function noticeDetailForm( $notice ) {
 770+ global $wgRequest;
 771+
 772+ if ( $this->editable ) {
 773+ $readonly = array();
 774+ } else {
 775+ $readonly = array( 'disabled' => 'disabled' );
 776+ }
 777+ $dbr = wfGetDB( DB_SLAVE );
 778+
 779+ // Get campaign info from database
 780+ $row = $dbr->selectRow( 'cn_notices',
 781+ array(
 782+ 'not_id',
 783+ 'not_name',
 784+ 'not_start',
 785+ 'not_end',
 786+ 'not_enabled',
 787+ 'not_preferred',
 788+ 'not_locked',
 789+ 'not_geo'
 790+ ),
 791+ array( 'not_name' => $notice ),
 792+ __METHOD__
 793+ );
 794+
 795+ if ( $row ) {
 796+
 797+ // If there was an error, we'll need to restore the state of the form
 798+ if ( $wgRequest->wasPosted() ) {
 799+ $startArray = $wgRequest->getArray( 'start' );
 800+ $startTimestamp = $startArray['year'] .
 801+ $startArray['month'] .
 802+ $startArray['day'] .
 803+ $startArray['hour'] .
 804+ $startArray['min'] . '00'
 805+ ;
 806+ $endArray = $wgRequest->getArray( 'end' );
 807+ $endTimestamp = $endArray['year'] .
 808+ $endArray['month'] .
 809+ $endArray['day'] .
 810+ $endArray['hour'] .
 811+ $endArray['min'] .'00'
 812+ ;
 813+ $isEnabled = $wgRequest->getCheck( 'enabled' );
 814+ $isPreferred = $wgRequest->getCheck( 'preferred' );
 815+ $isLocked = $wgRequest->getCheck( 'locked' );
 816+ $noticeProjects = $wgRequest->getArray( 'projects', array() );
 817+ $noticeLanguages = $wgRequest->getArray( 'project_languages', array() );
 818+ $isGeotargeted = $wgRequest->getCheck( 'geotargeted' );
 819+ $countries = $wgRequest->getArray( 'geo_countries', array() );
 820+ } else { // Defaults
 821+ $startTimestamp = $row->not_start;
 822+ $endTimestamp = $row->not_end;
 823+ $isEnabled = ( $row->not_enabled == '1' );
 824+ $isPreferred = ( $row->not_preferred == '1' );
 825+ $isLocked = ( $row->not_locked == '1' );
 826+ $noticeProjects = $this->getNoticeProjects( $notice );
 827+ $noticeLanguages = $this->getNoticeLanguages( $notice );
 828+ $isGeotargeted = ( $row->not_geo == '1' );
 829+ $countries = $this->getNoticeCountries( $notice );
 830+ }
 831+
 832+ // Build Html
 833+ $htmlOut = '';
 834+ $htmlOut .= Xml::tags( 'h2', null, wfMsg( 'centralnotice-notice-heading', $notice ) );
 835+ $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 836+
 837+ // Rows
 838+ // Start Date
 839+ $htmlOut .= Xml::openElement( 'tr' );
 840+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-date' ) );
 841+ $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'start', $startTimestamp ) );
 842+ $htmlOut .= Xml::closeElement( 'tr' );
 843+ // Start Time
 844+ $htmlOut .= Xml::openElement( 'tr' );
 845+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-start-time' ) );
 846+ $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'start', $startTimestamp ) );
 847+ $htmlOut .= Xml::closeElement( 'tr' );
 848+ // End Date
 849+ $htmlOut .= Xml::openElement( 'tr' );
 850+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-end-date' ) );
 851+ $htmlOut .= Xml::tags( 'td', array(), $this->dateSelector( 'end', $endTimestamp ) );
 852+ $htmlOut .= Xml::closeElement( 'tr' );
 853+ // End Time
 854+ $htmlOut .= Xml::openElement( 'tr' );
 855+ $htmlOut .= Xml::tags( 'td', array(), wfMsgHtml( 'centralnotice-end-time' ) );
 856+ $htmlOut .= Xml::tags( 'td', array(), $this->timeSelector( 'end', $endTimestamp ) );
 857+ $htmlOut .= Xml::closeElement( 'tr' );
 858+ // Project
 859+ $htmlOut .= Xml::openElement( 'tr' );
 860+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 861+ wfMsgHtml( 'centralnotice-projects' ) );
 862+ $htmlOut .= Xml::tags( 'td', array(),
 863+ $this->projectMultiSelector( $noticeProjects ) );
 864+ $htmlOut .= Xml::closeElement( 'tr' );
 865+ // Languages
 866+ $htmlOut .= Xml::openElement( 'tr' );
 867+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 868+ wfMsgHtml( 'centralnotice-languages' ) );
 869+ $htmlOut .= Xml::tags( 'td', array(),
 870+ $this->languageMultiSelector( $noticeLanguages ) );
 871+ $htmlOut .= Xml::closeElement( 'tr' );
 872+ // Countries
 873+ $htmlOut .= Xml::openElement( 'tr' );
 874+ $htmlOut .= Xml::tags( 'td', array(),
 875+ Xml::label( wfMsg( 'centralnotice-geotargeted' ), 'geotargeted' ) );
 876+ $htmlOut .= Xml::tags( 'td', array(),
 877+ Xml::check( 'geotargeted', $isGeotargeted,
 878+ wfArrayMerge(
 879+ $readonly,
 880+ array( 'value' => $row->not_name, 'id' => 'geotargeted' ) ) ) );
 881+ $htmlOut .= Xml::closeElement( 'tr' );
 882+ if ( $isGeotargeted ) {
 883+ $htmlOut .= Xml::openElement( 'tr', array( 'id'=>'geoMultiSelector' ) );
 884+ } else {
 885+ $htmlOut .= Xml::openElement( 'tr',
 886+ array( 'id'=>'geoMultiSelector', 'style'=>'display:none;' ) );
 887+ }
 888+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 889+ wfMsgHtml( 'centralnotice-countries' ) );
 890+ $htmlOut .= Xml::tags( 'td', array(), $this->geoMultiSelector( $countries ) );
 891+ $htmlOut .= Xml::closeElement( 'tr' );
 892+ // Enabled
 893+ $htmlOut .= Xml::openElement( 'tr' );
 894+ $htmlOut .= Xml::tags( 'td', array(),
 895+ Xml::label( wfMsg( 'centralnotice-enabled' ), 'enabled' ) );
 896+ $htmlOut .= Xml::tags( 'td', array(),
 897+ Xml::check( 'enabled', $isEnabled,
 898+ wfArrayMerge( $readonly,
 899+ array( 'value' => $row->not_name, 'id' => 'enabled' ) ) ) );
 900+ $htmlOut .= Xml::closeElement( 'tr' );
 901+ // Preferred
 902+ $htmlOut .= Xml::openElement( 'tr' );
 903+ $htmlOut .= Xml::tags( 'td', array(),
 904+ Xml::label( wfMsg( 'centralnotice-preferred' ), 'preferred' ) );
 905+ $htmlOut .= Xml::tags( 'td', array(),
 906+ Xml::check( 'preferred', $isPreferred,
 907+ wfArrayMerge( $readonly,
 908+ array( 'value' => $row->not_name, 'id' => 'preferred' ) ) ) );
 909+ $htmlOut .= Xml::closeElement( 'tr' );
 910+ // Locked
 911+ $htmlOut .= Xml::openElement( 'tr' );
 912+ $htmlOut .= Xml::tags( 'td', array(),
 913+ Xml::label( wfMsg( 'centralnotice-locked' ), 'locked' ) );
 914+ $htmlOut .= Xml::tags( 'td', array(),
 915+ Xml::check( 'locked', $isLocked,
 916+ wfArrayMerge( $readonly,
 917+ array( 'value' => $row->not_name, 'id' => 'locked' ) ) ) );
 918+ $htmlOut .= Xml::closeElement( 'tr' );
 919+ if ( $this->editable ) {
 920+ // Locked
 921+ $htmlOut .= Xml::openElement( 'tr' );
 922+ $htmlOut .= Xml::tags( 'td', array(),
 923+ Xml::label( wfMsg( 'centralnotice-remove' ), 'remove' ) );
 924+ $htmlOut .= Xml::tags( 'td', array(),
 925+ Xml::check( 'remove', false,
 926+ array( 'value' => $row->not_name, 'id' => 'remove' ) ) );
 927+ $htmlOut .= Xml::closeElement( 'tr' );
 928+ }
 929+ $htmlOut .= Xml::closeElement( 'table' );
 930+ return $htmlOut;
 931+ } else {
 932+ return '';
 933+ }
 934+ }
 935+
 936+ /**
 937+ * Create form for managing banners assigned to a campaign
 938+ */
 939+ function assignedTemplatesForm( $notice ) {
 940+ global $wgUser;
 941+ $sk = $wgUser->getSkin();
 942+
 943+ $dbr = wfGetDB( DB_SLAVE );
 944+ $res = $dbr->select(
 945+ array(
 946+ 'cn_notices',
 947+ 'cn_assignments',
 948+ 'cn_templates'
 949+ ),
 950+ array(
 951+ 'cn_templates.tmp_id',
 952+ 'cn_templates.tmp_name',
 953+ 'cn_assignments.tmp_weight'
 954+ ),
 955+ array(
 956+ 'cn_notices.not_name' => $notice,
 957+ 'cn_notices.not_id = cn_assignments.not_id',
 958+ 'cn_assignments.tmp_id = cn_templates.tmp_id'
 959+ ),
 960+ __METHOD__,
 961+ array( 'ORDER BY' => 'cn_notices.not_id' )
 962+ );
 963+
 964+ // No banners found
 965+ if ( $dbr->numRows( $res ) < 1 ) {
 966+ return;
 967+ }
 968+
 969+ // Build Assigned banners HTML
 970+ $htmlOut = Html::hidden( 'change', 'weight' );
 971+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-assigned-templates' ) );
 972+ $htmlOut .= Xml::openElement( 'table',
 973+ array(
 974+ 'cellpadding' => 9,
 975+ 'width' => '100%'
 976+ )
 977+ );
 978+ if ( $this->editable ) {
 979+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 980+ wfMsg ( "centralnotice-remove" ) );
 981+ }
 982+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 983+ wfMsg ( "centralnotice-weight" ) );
 984+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '70%' ),
 985+ wfMsg ( "centralnotice-templates" ) );
 986+
 987+ // Table rows
 988+ foreach( $res as $row ) {
 989+
 990+ $htmlOut .= Xml::openElement( 'tr' );
 991+
 992+ if ( $this->editable ) {
 993+ // Remove
 994+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 995+ Xml::check( 'removeTemplates[]', false, array( 'value' => $row->tmp_name ) )
 996+ );
 997+ }
 998+
 999+ // Weight
 1000+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 1001+ $this->weightDropDown( "weight[$row->tmp_id]", $row->tmp_weight )
 1002+ );
 1003+
 1004+ $viewPage = $this->getTitleFor( 'NoticeTemplate', 'view' );
 1005+
 1006+ /* XXX this code is duplicated in the CentralNoticePager::formatRow */
 1007+ $render = new SpecialBannerLoader();
 1008+ $render->siteName = 'Wikipedia';
 1009+ global $wgRequest;
 1010+ $render->language = $wgRequest->getVal( 'wpUserLanguage' );
 1011+ try {
 1012+ $preview = $render->getHtmlNotice( $row->tmp_name );
 1013+ } catch ( SpecialBannerLoaderException $e ) {
 1014+ $preview = wfMsg( 'centralnotice-nopreview' );
 1015+ }
 1016+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 1017+ $sk->makeLinkObj( $viewPage,
 1018+ htmlspecialchars( $row->tmp_name ),
 1019+ 'template=' . urlencode( $row->tmp_name ) ) .
 1020+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 1021+ $preview,
 1022+ array( 'class' => 'cn-bannerpreview')
 1023+ )
 1024+ );
 1025+
 1026+ $htmlOut .= Xml::closeElement( 'tr' );
 1027+ }
 1028+ $htmlOut .= XMl::closeElement( 'table' );
 1029+ $htmlOut .= Xml::closeElement( 'fieldset' );
 1030+ return $htmlOut;
 1031+
 1032+ }
 1033+
 1034+ function weightDropDown( $name, $selected ) {
 1035+ if ( $this->editable ) {
 1036+ return Xml::listDropDown( $name,
 1037+ $this->dropDownList( wfMsg( 'centralnotice-weight' ),
 1038+ range ( 0, 100, 5 ) ),
 1039+ '',
 1040+ $selected,
 1041+ '',
 1042+ 1 );
 1043+ } else {
 1044+ return htmlspecialchars( $selected );
 1045+ }
 1046+ }
 1047+
 1048+ /**
 1049+ * Create form for adding banners to a campaign
 1050+ */
 1051+ function addTemplatesForm( $notice ) {
 1052+ $pager = new CentralNoticePager( $this );
 1053+ $dbr = wfGetDB( DB_SLAVE );
 1054+ $res = $dbr->select( 'cn_templates', 'tmp_name', '', '', array( 'ORDER BY' => 'tmp_id' ) );
 1055+
 1056+ if ( $dbr->numRows( $res ) > 0 ) {
 1057+ // Build HTML
 1058+ $htmlOut = Xml::fieldset( wfMsg( "centralnotice-available-templates" ) );
 1059+
 1060+ // Show paginated list of banners
 1061+ $htmlOut .= Xml::tags( 'div',
 1062+ array( 'class' => 'cn-pager' ),
 1063+ $pager->getNavigationBar() );
 1064+ $htmlOut .= $pager->getBody();
 1065+ $htmlOut .= Xml::tags( 'div',
 1066+ array( 'class' => 'cn-pager' ),
 1067+ $pager->getNavigationBar() );
 1068+
 1069+ $htmlOut .= Xml::closeElement( 'fieldset' );
 1070+ } else {
 1071+ // Nothing found
 1072+ return;
 1073+ }
 1074+ return $htmlOut;
 1075+ }
 1076+
 1077+ /**
 1078+ * Lookup function for active banners under a given language/project/location. This function is
 1079+ * called by SpecialBannerListLoader::getJsonList() in order to build the banner list JSON for
 1080+ * each project.
 1081+ * @return a 2D array of running banners with associated weights and settings
 1082+ */
 1083+ static function selectNoticeTemplates( $project, $language, $location = null ) {
 1084+ global $wgCentralDBname;
 1085+
 1086+ $campaigns = array();
 1087+ $dbr = wfGetDB( DB_SLAVE, array(), $wgCentralDBname );
 1088+ $encTimestamp = $dbr->addQuotes( $dbr->timestamp() );
 1089+
 1090+ // Pull non-geotargeted campaigns
 1091+ $campaignResults1 = $dbr->select(
 1092+ array(
 1093+ 'cn_notices',
 1094+ 'cn_notice_projects',
 1095+ 'cn_notice_languages'
 1096+ ),
 1097+ array(
 1098+ 'not_id'
 1099+ ),
 1100+ array(
 1101+ "not_start <= $encTimestamp",
 1102+ "not_end >= $encTimestamp",
 1103+ 'not_enabled = 1', // enabled
 1104+ 'not_geo = 0', // not geotargeted
 1105+ 'np_notice_id = cn_notices.not_id',
 1106+ 'np_project' => $project,
 1107+ 'nl_notice_id = cn_notices.not_id',
 1108+ 'nl_language' => $language
 1109+ ),
 1110+ __METHOD__
 1111+ );
 1112+ foreach ( $campaignResults1 as $row ) {
 1113+ $campaigns[] = $row->not_id;
 1114+ }
 1115+ if ( $location ) {
 1116+
 1117+ // Normalize location parameter (should be an uppercase 2-letter country code)
 1118+ preg_match( '/[a-zA-Z][a-zA-Z]/', $location, $matches );
 1119+ if ( $matches ) {
 1120+ $location = strtoupper( $matches[0] );
 1121+
 1122+ // Pull geotargeted campaigns
 1123+ $campaignResults2 = $dbr->select(
 1124+ array(
 1125+ 'cn_notices',
 1126+ 'cn_notice_projects',
 1127+ 'cn_notice_languages',
 1128+ 'cn_notice_countries'
 1129+ ),
 1130+ array(
 1131+ 'not_id'
 1132+ ),
 1133+ array(
 1134+ "not_start <= $encTimestamp",
 1135+ "not_end >= $encTimestamp",
 1136+ 'not_enabled = 1', // enabled
 1137+ 'not_geo = 1', // geotargeted
 1138+ 'nc_notice_id = cn_notices.not_id',
 1139+ 'nc_country' => $location,
 1140+ 'np_notice_id = cn_notices.not_id',
 1141+ 'np_project' => $project,
 1142+ 'nl_notice_id = cn_notices.not_id',
 1143+ 'nl_language' => $language
 1144+ ),
 1145+ __METHOD__
 1146+ );
 1147+ foreach ( $campaignResults2 as $row ) {
 1148+ $campaigns[] = $row->not_id;
 1149+ }
 1150+ }
 1151+ }
 1152+
 1153+ $templates = array();
 1154+ if ( $campaigns ) {
 1155+ // Pull all banners assigned to the campaigns
 1156+ $templates = CentralNoticeDB::selectBannersAssigned( $campaigns );
 1157+ }
 1158+ return $templates;
 1159+ }
 1160+
 1161+ function addNotice( $noticeName, $enabled, $start, $projects,
 1162+ $project_languages, $geotargeted, $geo_countries )
 1163+ {
 1164+ if ( $this->noticeExists( $noticeName ) ) {
 1165+ $this->showError( 'centralnotice-notice-exists' );
 1166+ return;
 1167+ } elseif ( empty( $projects ) ) {
 1168+ $this->showError( 'centralnotice-no-project' );
 1169+ return;
 1170+ } elseif ( empty( $project_languages ) ) {
 1171+ $this->showError( 'centralnotice-no-language' );
 1172+ return;
 1173+ } else {
 1174+ $dbw = wfGetDB( DB_MASTER );
 1175+ $dbw->begin();
 1176+ $start['hour'] = substr( $start['hour'], 0 , 2 );
 1177+ $start['min'] = substr( $start['min'], 0 , 2 );
 1178+ if ( $start['month'] == 12 ) {
 1179+ $end['month'] = '01';
 1180+ $end['year'] = ( $start['year'] + 1 );
 1181+ } elseif ( $start['month'] == '09' ) {
 1182+ $end['month'] = '10';
 1183+ $end['year'] = $start['year'];
 1184+ } else {
 1185+ $end['month'] =
 1186+ ( substr( $start['month'], 0, 1 ) ) == 0
 1187+ ? 0 . ( intval( $start['month'] ) + 1 )
 1188+ : ( $start['month'] + 1 );
 1189+ $end['year'] = $start['year'];
 1190+ }
 1191+
 1192+ $startTs = wfTimeStamp( TS_MW, "{$start['year']}:{$start['month']}:{$start['day']} " .
 1193+ "{$start['hour']}:{$start['min']}:00" );
 1194+ $endTs = wfTimeStamp( TS_MW, "{$end['year']}:{$end['month']}:{$start['day']} " .
 1195+ "{$start['hour']}:{$start['min']}:00" );
 1196+
 1197+ $res = $dbw->insert( 'cn_notices',
 1198+ array( 'not_name' => $noticeName,
 1199+ 'not_enabled' => $enabled,
 1200+ 'not_start' => $dbw->timestamp( $startTs ),
 1201+ 'not_end' => $dbw->timestamp( $endTs ),
 1202+ 'not_geo' => $geotargeted
 1203+ )
 1204+ );
 1205+ $not_id = $dbw->insertId();
 1206+
 1207+ // Do multi-row insert for campaign projects
 1208+ $insertArray = array();
 1209+ foreach( $projects as $project ) {
 1210+ $insertArray[] = array( 'np_notice_id' => $not_id, 'np_project' => $project );
 1211+ }
 1212+ $res = $dbw->insert( 'cn_notice_projects', $insertArray,
 1213+ __METHOD__, array( 'IGNORE' ) );
 1214+
 1215+ // Do multi-row insert for campaign languages
 1216+ $insertArray = array();
 1217+ foreach( $project_languages as $code ) {
 1218+ $insertArray[] = array( 'nl_notice_id' => $not_id, 'nl_language' => $code );
 1219+ }
 1220+ $res = $dbw->insert( 'cn_notice_languages', $insertArray,
 1221+ __METHOD__, array( 'IGNORE' ) );
 1222+
 1223+ if ( $geotargeted && $geo_countries ) {
 1224+ // Do multi-row insert for campaign countries
 1225+ $insertArray = array();
 1226+ foreach( $geo_countries as $code ) {
 1227+ $insertArray[] = array( 'nc_notice_id' => $not_id, 'nc_country' => $code );
 1228+ }
 1229+ $res = $dbw->insert( 'cn_notice_countries', $insertArray,
 1230+ __METHOD__, array( 'IGNORE' ) );
 1231+ }
 1232+
 1233+ $dbw->commit();
 1234+ return;
 1235+ }
 1236+ }
 1237+
 1238+ function removeNotice( $noticeName ) {
 1239+ $dbr = wfGetDB( DB_SLAVE );
 1240+
 1241+ $res = $dbr->select( 'cn_notices', 'not_name, not_locked',
 1242+ array( 'not_name' => $noticeName )
 1243+ );
 1244+ if ( $dbr->numRows( $res ) < 1 ) {
 1245+ $this->showError( 'centralnotice-remove-notice-doesnt-exist' );
 1246+ return;
 1247+ }
 1248+ $row = $dbr->fetchObject( $res );
 1249+ if ( $row->not_locked == '1' ) {
 1250+ $this->showError( 'centralnotice-notice-is-locked' );
 1251+ return;
 1252+ } else {
 1253+ $dbw = wfGetDB( DB_MASTER );
 1254+ $dbw->begin();
 1255+ $noticeId = htmlspecialchars( $this->getNoticeId( $noticeName ) );
 1256+ $res = $dbw->delete( 'cn_assignments', array ( 'not_id' => $noticeId ) );
 1257+ $res = $dbw->delete( 'cn_notices', array ( 'not_name' => $noticeName ) );
 1258+ $res = $dbw->delete( 'cn_notice_languages', array ( 'nl_notice_id' => $noticeId ) );
 1259+ $dbw->commit();
 1260+ return;
 1261+ }
 1262+ }
 1263+
 1264+ function addTemplateTo( $noticeName, $templateName, $weight ) {
 1265+ $dbr = wfGetDB( DB_SLAVE );
 1266+
 1267+ $eNoticeName = htmlspecialchars ( $noticeName );
 1268+ $noticeId = $this->getNoticeId( $eNoticeName );
 1269+ $templateId = $this->getTemplateId( $templateName );
 1270+ $res = $dbr->select( 'cn_assignments', 'asn_id',
 1271+ array(
 1272+ 'tmp_id' => $templateId,
 1273+ 'not_id' => $noticeId
 1274+ )
 1275+ );
 1276+ if ( $dbr->numRows( $res ) > 0 ) {
 1277+ $this->showError( 'centralnotice-template-already-exists' );
 1278+ } else {
 1279+ $dbw = wfGetDB( DB_MASTER );
 1280+ $dbw->begin();
 1281+ $noticeId = $this->getNoticeId( $eNoticeName );
 1282+ $res = $dbw->insert( 'cn_assignments',
 1283+ array(
 1284+ 'tmp_id' => $templateId,
 1285+ 'tmp_weight' => $weight,
 1286+ 'not_id' => $noticeId
 1287+ )
 1288+ );
 1289+ $dbw->commit();
 1290+ }
 1291+ }
 1292+
 1293+ /**
 1294+ * Lookup the ID for a campaign based on the campaign name
 1295+ */
 1296+ public static function getNoticeId( $noticeName ) {
 1297+ $dbr = wfGetDB( DB_SLAVE );
 1298+ $eNoticeName = htmlspecialchars( $noticeName );
 1299+ $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
 1300+ if ( $row ) {
 1301+ return $row->not_id;
 1302+ } else {
 1303+ return null;
 1304+ }
 1305+ }
 1306+
 1307+ /*
 1308+ * Lookup the name of a campaign based on the campaign ID
 1309+ */
 1310+ public static function getNoticeName( $noticeId ) {
 1311+ $dbr = wfGetDB( DB_SLAVE );
 1312+ if ( is_numeric( $noticeId ) ) {
 1313+ $row = $dbr->selectRow( 'cn_notices', 'not_name', array( 'not_id' => $noticeId ) );
 1314+ if ( $row ) {
 1315+ return $row->not_name;
 1316+ }
 1317+ }
 1318+ return null;
 1319+ }
 1320+
 1321+ function getNoticeProjects( $noticeName ) {
 1322+ $dbr = wfGetDB( DB_SLAVE );
 1323+ $eNoticeName = htmlspecialchars( $noticeName );
 1324+ $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
 1325+ $projects = array();
 1326+ if ( $row ) {
 1327+ $res = $dbr->select( 'cn_notice_projects', 'np_project',
 1328+ array( 'np_notice_id' => $row->not_id ) );
 1329+ foreach ( $res as $projectRow ) {
 1330+ $projects[] = $projectRow->np_project;
 1331+ }
 1332+ }
 1333+ return $projects;
 1334+ }
 1335+
 1336+ function getNoticeLanguages( $noticeName ) {
 1337+ $dbr = wfGetDB( DB_SLAVE );
 1338+ $eNoticeName = htmlspecialchars( $noticeName );
 1339+ $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
 1340+ $languages = array();
 1341+ if ( $row ) {
 1342+ $res = $dbr->select( 'cn_notice_languages', 'nl_language',
 1343+ array( 'nl_notice_id' => $row->not_id ) );
 1344+ foreach ( $res as $langRow ) {
 1345+ $languages[] = $langRow->nl_language;
 1346+ }
 1347+ }
 1348+ return $languages;
 1349+ }
 1350+
 1351+ function getNoticeCountries( $noticeName ) {
 1352+ $dbr = wfGetDB( DB_SLAVE );
 1353+ $eNoticeName = htmlspecialchars( $noticeName );
 1354+ $row = $dbr->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $eNoticeName ) );
 1355+ $countries = array();
 1356+ if ( $row ) {
 1357+ $res = $dbr->select( 'cn_notice_countries', 'nc_country',
 1358+ array( 'nc_notice_id' => $row->not_id ) );
 1359+ foreach ( $res as $countryRow ) {
 1360+ $countries[] = $countryRow->nc_country;
 1361+ }
 1362+ }
 1363+ return $countries;
 1364+ }
 1365+
 1366+ function getNoticeProjectName( $noticeName ) {
 1367+ $dbr = wfGetDB( DB_SLAVE );
 1368+ $eNoticeName = htmlspecialchars( $noticeName );
 1369+ $res = $dbr->select( 'cn_notices', 'not_project', array( 'not_name' => $eNoticeName ) );
 1370+ $row = $dbr->fetchObject( $res );
 1371+ return $row->not_project;
 1372+ }
 1373+
 1374+ function getTemplateId( $templateName ) {
 1375+ $dbr = wfGetDB( DB_SLAVE );
 1376+ $templateName = htmlspecialchars ( $templateName );
 1377+ $res = $dbr->select( 'cn_templates', 'tmp_id', array( 'tmp_name' => $templateName ) );
 1378+ $row = $dbr->fetchObject( $res );
 1379+ return $row->tmp_id;
 1380+ }
 1381+
 1382+ function removeTemplateFor( $noticeName, $templateName ) {
 1383+ $dbw = wfGetDB( DB_MASTER );
 1384+ $dbw->begin();
 1385+ $noticeId = $this->getNoticeId( $noticeName );
 1386+ $templateId = $this->getTemplateId( $templateName );
 1387+ $dbw->delete( 'cn_assignments', array ( 'tmp_id' => $templateId, 'not_id' => $noticeId ) );
 1388+ $dbw->commit();
 1389+ }
 1390+
 1391+ function updateNoticeDate( $noticeName, $start, $end ) {
 1392+ $dbr = wfGetDB( DB_SLAVE );
 1393+
 1394+ // Start/end don't line up
 1395+ if ( $start > $end || $end < $start ) {
 1396+ $this->showError( 'centralnotice-invalid-date-range' );
 1397+ return;
 1398+ }
 1399+
 1400+ // Invalid campaign name
 1401+ if ( !$this->noticeExists( $noticeName ) ) {
 1402+ $this->showError( 'centralnotice-notice-doesnt-exist' );
 1403+ return;
 1404+ }
 1405+
 1406+ // Overlap over a date within the same project and language
 1407+ $startDate = $dbr->timestamp( $start );
 1408+ $endDate = $dbr->timestamp( $end );
 1409+
 1410+ $dbw = wfGetDB( DB_MASTER );
 1411+ $res = $dbw->update( 'cn_notices',
 1412+ array(
 1413+ 'not_start' => $startDate,
 1414+ 'not_end' => $endDate
 1415+ ),
 1416+ array( 'not_name' => $noticeName )
 1417+ );
 1418+ }
 1419+
 1420+ /**
 1421+ * Update the enabled/disabled state of a campaign
 1422+ */
 1423+ private function updateEnabled( $noticeName, $isEnabled ) {
 1424+ if ( !$this->noticeExists( $noticeName ) ) {
 1425+ $this->showError( 'centralnotice-doesnt-exist' );
 1426+ } else {
 1427+ $dbw = wfGetDB( DB_MASTER );
 1428+ $res = $dbw->update( 'cn_notices',
 1429+ array( 'not_enabled' => $isEnabled ),
 1430+ array( 'not_name' => $noticeName )
 1431+ );
 1432+ }
 1433+ }
 1434+
 1435+ /**
 1436+ * Update the preferred/not preferred state of a campaign
 1437+ */
 1438+ function updatePreferred( $noticeName, $isPreferred ) {
 1439+ if ( !$this->noticeExists( $noticeName ) ) {
 1440+ $this->showError( 'centralnotice-doesnt-exist' );
 1441+ } else {
 1442+ $dbw = wfGetDB( DB_MASTER );
 1443+ $res = $dbw->update( 'cn_notices',
 1444+ array( 'not_preferred' => $isPreferred ),
 1445+ array( 'not_name' => $noticeName )
 1446+ );
 1447+ }
 1448+ }
 1449+
 1450+ /**
 1451+ * Update the geotargeted/not geotargeted state of a campaign
 1452+ */
 1453+ function updateGeotargeted( $noticeName, $isGeotargeted ) {
 1454+ if ( !$this->noticeExists( $noticeName ) ) {
 1455+ $this->showError( 'centralnotice-doesnt-exist' );
 1456+ } else {
 1457+ $dbw = wfGetDB( DB_MASTER );
 1458+ $res = $dbw->update( 'cn_notices',
 1459+ array( 'not_geo' => $isGeotargeted ),
 1460+ array( 'not_name' => $noticeName )
 1461+ );
 1462+ }
 1463+ }
 1464+
 1465+ /**
 1466+ * Update the locked/unlocked state of a campaign
 1467+ */
 1468+ function updateLock( $noticeName, $isLocked ) {
 1469+ if ( !$this->noticeExists( $noticeName ) ) {
 1470+ $this->showError( 'centralnotice-doesnt-exist' );
 1471+ } else {
 1472+ $dbw = wfGetDB( DB_MASTER );
 1473+ $res = $dbw->update( 'cn_notices',
 1474+ array( 'not_locked' => $isLocked ),
 1475+ array( 'not_name' => $noticeName )
 1476+ );
 1477+ }
 1478+ }
 1479+
 1480+ function updateWeight( $noticeName, $templateId, $weight ) {
 1481+ $dbw = wfGetDB( DB_MASTER );
 1482+ $noticeId = $this->getNoticeId( $noticeName );
 1483+ $dbw->update( 'cn_assignments',
 1484+ array ( 'tmp_weight' => $weight ),
 1485+ array(
 1486+ 'tmp_id' => $templateId,
 1487+ 'not_id' => $noticeId
 1488+ )
 1489+ );
 1490+ }
 1491+
 1492+ /**
 1493+ * Generates a multiple select list of all languages.
 1494+ * @param $selected The language codes of the selected languages
 1495+ * @param $customisedOnly If true only languages which have some content are listed
 1496+ * @return multiple select list
 1497+ */
 1498+ function languageMultiSelector( $selected = array(), $customisedOnly = true ) {
 1499+ global $wgLanguageCode, $wgExtensionAssetsPath, $wgLang;
 1500+ $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
 1501+ if ( is_callable( array( 'LanguageNames', 'getNames' ) ) ) {
 1502+ // Retrieve the list of languages in user's language (via CLDR)
 1503+ $languages = LanguageNames::getNames(
 1504+ $wgLang->getCode(), // User's language
 1505+ LanguageNames::FALLBACK_NORMAL, // Use fallback chain
 1506+ LanguageNames::LIST_MW // Pull all languages that are in Names.php
 1507+ );
 1508+ } else {
 1509+ // Use this as fallback if CLDR extension is not enabled
 1510+ $languages = Language::getLanguageNames();
 1511+ }
 1512+ // Make sure the site language is in the list; a custom language code
 1513+ // might not have a defined name...
 1514+ if( !array_key_exists( $wgLanguageCode, $languages ) ) {
 1515+ $languages[$wgLanguageCode] = $wgLanguageCode;
 1516+ }
 1517+ ksort( $languages );
 1518+
 1519+ $options = "\n";
 1520+ foreach( $languages as $code => $name ) {
 1521+ $options .= Xml::option(
 1522+ wfMsg( 'centralnotice-language-listing', $code, $name ),
 1523+ $code,
 1524+ in_array( $code, $selected )
 1525+ ) . "\n";
 1526+ }
 1527+ $htmlOut = '';
 1528+ if ( $this->editable ) {
 1529+ $htmlOut .= Xml::tags( 'select',
 1530+ array( 'multiple' => 'multiple', 'size' => 4, 'id' => 'project_languages[]', 'name' => 'project_languages[]' ),
 1531+ $options
 1532+ );
 1533+ $buttons = array();
 1534+ $buttons[] = '<a href="#" onclick="selectLanguages(true);return false;">' .
 1535+ wfMsg( 'powersearch-toggleall' ) . '</a>';
 1536+ $buttons[] = '<a href="#" onclick="selectLanguages(false);return false;">' .
 1537+ wfMsg( 'powersearch-togglenone' ) . '</a>';
 1538+ $buttons[] = '<a href="#" onclick="top10Languages();return false;">' .
 1539+ wfMsg( 'centralnotice-top-ten-languages' ) . '</a>';
 1540+ $htmlOut .= Xml::tags( 'div',
 1541+ array( 'style' => 'margin-top: 0.2em;' ),
 1542+ '<img src="'.$scriptPath.'/up-arrow.png" style="vertical-align:baseline;"/>' .
 1543+ wfMsg( 'centralnotice-select', $wgLang->commaList( $buttons ) )
 1544+ );
 1545+ } else {
 1546+ $htmlOut .= Xml::tags( 'select',
 1547+ array(
 1548+ 'multiple' => 'multiple',
 1549+ 'size' => 4,
 1550+ 'id' => 'project_languages[]',
 1551+ 'name' => 'project_languages[]',
 1552+ 'disabled' => 'disabled'
 1553+ ),
 1554+ $options
 1555+ );
 1556+ }
 1557+ return $htmlOut;
 1558+ }
 1559+
 1560+ /**
 1561+ * Generates a multiple select list of all project types.
 1562+ * @param $selected The name of the selected project type
 1563+ * @return multiple select list
 1564+ */
 1565+ function projectMultiSelector( $selected = array() ) {
 1566+ global $wgNoticeProjects, $wgExtensionAssetsPath, $wgLang;
 1567+ $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
 1568+
 1569+ $options = "\n";
 1570+ foreach( $wgNoticeProjects as $project ) {
 1571+ $options .= Xml::option(
 1572+ $project,
 1573+ $project,
 1574+ in_array( $project, $selected )
 1575+ ) . "\n";
 1576+ }
 1577+ $htmlOut = '';
 1578+ if ( $this->editable ) {
 1579+ $htmlOut .= Xml::tags( 'select',
 1580+ array( 'multiple' => 'multiple', 'size' => 4, 'id' => 'projects[]', 'name' => 'projects[]' ),
 1581+ $options
 1582+ );
 1583+ $buttons = array();
 1584+ $buttons[] = '<a href="#" onclick="selectProjects(true);return false;">' .
 1585+ wfMsg( 'powersearch-toggleall' ) . '</a>';
 1586+ $buttons[] = '<a href="#" onclick="selectProjects(false);return false;">' .
 1587+ wfMsg( 'powersearch-togglenone' ) . '</a>';
 1588+ $htmlOut .= Xml::tags( 'div',
 1589+ array( 'style' => 'margin-top: 0.2em;' ),
 1590+ '<img src="'.$scriptPath.'/up-arrow.png" style="vertical-align:baseline;"/>' .
 1591+ wfMsg( 'centralnotice-select', $wgLang->commaList( $buttons ) )
 1592+ );
 1593+ } else {
 1594+ $htmlOut .= Xml::tags( 'select',
 1595+ array(
 1596+ 'multiple' => 'multiple',
 1597+ 'size' => 4,
 1598+ 'id' => 'projects[]',
 1599+ 'name' => 'projects[]',
 1600+ 'disabled' => 'disabled'
 1601+ ),
 1602+ $options
 1603+ );
 1604+ }
 1605+ return $htmlOut;
 1606+ }
 1607+
 1608+ function getProjectName( $value ) {
 1609+ return $value; // @fixme -- use wfMsg()
 1610+ }
 1611+
 1612+ function updateProjectName( $notice, $projectName ) {
 1613+ $dbw = wfGetDB( DB_MASTER );
 1614+ $res = $dbw->update( 'cn_notices',
 1615+ array ( 'not_project' => $projectName ),
 1616+ array(
 1617+ 'not_name' => $notice
 1618+ )
 1619+ );
 1620+ }
 1621+
 1622+ function updateProjects( $notice, $newProjects ) {
 1623+ $dbw = wfGetDB( DB_MASTER );
 1624+ $dbw->begin();
 1625+
 1626+ // Get the previously assigned projects
 1627+ $oldProjects = $this->getNoticeProjects( $notice );
 1628+
 1629+ // Get the notice id
 1630+ $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
 1631+
 1632+ // Add newly assigned projects
 1633+ $addProjects = array_diff( $newProjects, $oldProjects );
 1634+ $insertArray = array();
 1635+ foreach( $addProjects as $project ) {
 1636+ $insertArray[] = array( 'np_notice_id' => $row->not_id, 'np_project' => $project );
 1637+ }
 1638+ $res = $dbw->insert( 'cn_notice_projects', $insertArray, __METHOD__, array( 'IGNORE' ) );
 1639+
 1640+ // Remove disassociated projects
 1641+ $removeProjects = array_diff( $oldProjects, $newProjects );
 1642+ if ( $removeProjects ) {
 1643+ $res = $dbw->delete( 'cn_notice_projects',
 1644+ array( 'np_notice_id' => $row->not_id, 'np_project' => $removeProjects )
 1645+ );
 1646+ }
 1647+
 1648+ $dbw->commit();
 1649+ }
 1650+
 1651+ function updateProjectLanguages( $notice, $newLanguages ) {
 1652+ $dbw = wfGetDB( DB_MASTER );
 1653+ $dbw->begin();
 1654+
 1655+ // Get the previously assigned languages
 1656+ $oldLanguages = $this->getNoticeLanguages( $notice );
 1657+
 1658+ // Get the notice id
 1659+ $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
 1660+
 1661+ // Add newly assigned languages
 1662+ $addLanguages = array_diff( $newLanguages, $oldLanguages );
 1663+ $insertArray = array();
 1664+ foreach( $addLanguages as $code ) {
 1665+ $insertArray[] = array( 'nl_notice_id' => $row->not_id, 'nl_language' => $code );
 1666+ }
 1667+ $res = $dbw->insert( 'cn_notice_languages', $insertArray, __METHOD__, array( 'IGNORE' ) );
 1668+
 1669+ // Remove disassociated languages
 1670+ $removeLanguages = array_diff( $oldLanguages, $newLanguages );
 1671+ if ( $removeLanguages ) {
 1672+ $res = $dbw->delete( 'cn_notice_languages',
 1673+ array( 'nl_notice_id' => $row->not_id, 'nl_language' => $removeLanguages )
 1674+ );
 1675+ }
 1676+
 1677+ $dbw->commit();
 1678+ }
 1679+
 1680+ function updateCountries( $notice, $newCountries ) {
 1681+ $dbw = wfGetDB( DB_MASTER );
 1682+
 1683+ // Get the previously assigned languages
 1684+ $oldCountries = $this->getNoticeCountries( $notice );
 1685+
 1686+ // Get the notice id
 1687+ $row = $dbw->selectRow( 'cn_notices', 'not_id', array( 'not_name' => $notice ) );
 1688+
 1689+ // Add newly assigned countries
 1690+ $addCountries = array_diff( $newCountries, $oldCountries );
 1691+ $insertArray = array();
 1692+ foreach( $addCountries as $code ) {
 1693+ $insertArray[] = array( 'nc_notice_id' => $row->not_id, 'nc_country' => $code );
 1694+ }
 1695+ $res = $dbw->insert( 'cn_notice_countries', $insertArray, __METHOD__, array( 'IGNORE' ) );
 1696+
 1697+ // Remove disassociated countries
 1698+ $removeCountries = array_diff( $oldCountries, $newCountries );
 1699+ if ( $removeCountries ) {
 1700+ $dbw->delete( 'cn_notice_countries',
 1701+ array( 'nc_notice_id' => $row->not_id, 'nc_country' => $removeCountries )
 1702+ );
 1703+ }
 1704+ }
 1705+
 1706+ public static function noticeExists( $noticeName ) {
 1707+ $dbr = wfGetDB( DB_SLAVE );
 1708+ $eNoticeName = htmlspecialchars( $noticeName );
 1709+ $row = $dbr->selectRow( 'cn_notices', 'not_name', array( 'not_name' => $eNoticeName ) );
 1710+ if ( $row ) {
 1711+ return true;
 1712+ } else {
 1713+ return false;
 1714+ }
 1715+ }
 1716+
 1717+ public static function dropDownList( $text, $values ) {
 1718+ $dropDown = "*{$text}\n";
 1719+ foreach ( $values as $value ) {
 1720+ $dropDown .= "**{$value}\n";
 1721+ }
 1722+ return $dropDown;
 1723+ }
 1724+
 1725+ function addZero( $text ) {
 1726+ // Prepend a 0 for text needing it
 1727+ if ( strlen( $text ) == 1 ) {
 1728+ $text = "0{$text}";
 1729+ }
 1730+ return $text;
 1731+ }
 1732+
 1733+ function showError( $message ) {
 1734+ global $wgOut;
 1735+ $wgOut->wrapWikiMsg( "<div class='cn-error'>\n$1\n</div>", $message );
 1736+ $this->centralNoticeError = true;
 1737+ }
 1738+
 1739+ /**
 1740+ * Generates a multiple select list of all countries.
 1741+ * @param $selected The country codes of the selected countries
 1742+ * @return multiple select list
 1743+ */
 1744+ function geoMultiSelector( $selected = array() ) {
 1745+ $countries = CentralNoticeDB::getCountriesList();
 1746+ $options = "\n";
 1747+ foreach( $countries as $code => $name ) {
 1748+ $options .= Xml::option(
 1749+ $name,
 1750+ $code,
 1751+ in_array( $code, $selected )
 1752+ ) . "\n";
 1753+ }
 1754+ $htmlOut = '';
 1755+ if ( $this->editable ) {
 1756+ $htmlOut .= Xml::tags( 'select',
 1757+ array(
 1758+ 'multiple' => 'multiple',
 1759+ 'size' => 5,
 1760+ 'id' => 'geo_countries[]',
 1761+ 'name' => 'geo_countries[]'
 1762+ ),
 1763+ $options
 1764+ );
 1765+ } else {
 1766+ $htmlOut .= Xml::tags( 'select',
 1767+ array(
 1768+ 'multiple' => 'multiple',
 1769+ 'size' => 5,
 1770+ 'id' => 'geo_countries[]',
 1771+ 'name' => 'geo_countries[]',
 1772+ 'disabled' => 'disabled'
 1773+ ),
 1774+ $options
 1775+ );
 1776+ }
 1777+ return $htmlOut;
 1778+ }
 1779+}
 1780+
 1781+class CentralNoticePager extends TemplatePager {
 1782+ var $viewPage, $special;
 1783+ var $editable;
 1784+
 1785+ function __construct( $special ) {
 1786+ parent::__construct( $special );
 1787+ }
 1788+
 1789+ /**
 1790+ * Pull banners from the database
 1791+ */
 1792+ function getQueryInfo() {
 1793+ $notice = $this->mRequest->getVal( 'notice' );
 1794+ $noticeId = CentralNotice::getNoticeId( $notice );
 1795+ if ( $noticeId ) {
 1796+ // Return all the banners not already assigned to the current campaign
 1797+ return array(
 1798+ 'tables' => array( 'cn_assignments', 'cn_templates' ),
 1799+ 'fields' => array( 'cn_templates.tmp_name', 'cn_templates.tmp_id' ),
 1800+ 'conds' => array( 'cn_assignments.tmp_id IS NULL' ),
 1801+ 'join_conds' => array(
 1802+ 'cn_assignments' => array(
 1803+ 'LEFT JOIN',
 1804+ "cn_assignments.tmp_id = cn_templates.tmp_id " .
 1805+ "AND cn_assignments.not_id = $noticeId"
 1806+ )
 1807+ )
 1808+ );
 1809+ } else {
 1810+ // Return all the banners in the database
 1811+ return array(
 1812+ 'tables' => 'cn_templates',
 1813+ 'fields' => array( 'tmp_name', 'tmp_id' ),
 1814+ );
 1815+ }
 1816+ }
 1817+
 1818+ /**
 1819+ * Generate the content of each table row (1 row = 1 banner)
 1820+ */
 1821+ function formatRow( $row ) {
 1822+
 1823+ // Begin banner row
 1824+ $htmlOut = Xml::openElement( 'tr' );
 1825+
 1826+ if ( $this->editable ) {
 1827+ // Add box
 1828+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 1829+ Xml::check( 'addTemplates[]', '', array ( 'value' => $row->tmp_name ) )
 1830+ );
 1831+ // Weight select
 1832+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 1833+ Xml::listDropDown( "weight[$row->tmp_id]",
 1834+ CentralNotice::dropDownList(
 1835+ wfMsg( 'centralnotice-weight' ), range ( 0, 100, 5 )
 1836+ ) ,
 1837+ '',
 1838+ '25',
 1839+ '',
 1840+ '' )
 1841+ );
 1842+ }
 1843+
 1844+ // Link and Preview
 1845+ $render = new SpecialBannerLoader();
 1846+ $render->siteName = 'Wikipedia';
 1847+ $render->language = $this->mRequest->getVal( 'wpUserLanguage' );
 1848+ try {
 1849+ $preview = $render->getHtmlNotice( $row->tmp_name );
 1850+ } catch ( SpecialBannerLoaderException $e ) {
 1851+ $preview = wfMsg( 'centralnotice-nopreview' );
 1852+ }
 1853+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 1854+ $this->getSkin()->makeLinkObj( $this->viewPage,
 1855+ htmlspecialchars( $row->tmp_name ),
 1856+ 'template=' . urlencode( $row->tmp_name ) ) .
 1857+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 1858+ $preview,
 1859+ array( 'class' => 'cn-bannerpreview')
 1860+ )
 1861+ );
 1862+
 1863+ // End banner row
 1864+ $htmlOut .= Xml::closeElement( 'tr' );
 1865+
 1866+ return $htmlOut;
 1867+ }
 1868+
 1869+ /**
 1870+ * Specify table headers
 1871+ */
 1872+ function getStartBody() {
 1873+ $htmlOut = '';
 1874+ $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 1875+ $htmlOut .= Xml::openElement( 'tr' );
 1876+ if ( $this->editable ) {
 1877+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 1878+ wfMsg ( "centralnotice-add" )
 1879+ );
 1880+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left', 'width' => '5%' ),
 1881+ wfMsg ( "centralnotice-weight" )
 1882+ );
 1883+ }
 1884+ $htmlOut .= Xml::element( 'th', array( 'align' => 'left' ),
 1885+ wfMsg ( 'centralnotice-templates' )
 1886+ );
 1887+ $htmlOut .= Xml::closeElement( 'tr' );
 1888+ return $htmlOut;
 1889+ }
 1890+
 1891+ /**
 1892+ * Close table
 1893+ */
 1894+ function getEndBody() {
 1895+ $htmlOut = '';
 1896+ $htmlOut .= Xml::closeElement( 'table' );
 1897+ return $htmlOut;
 1898+ }
 1899+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialCentralNotice.php
___________________________________________________________________
Added: svn:eol-style
11900 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerAllocation.php
@@ -0,0 +1,201 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class SpecialBannerAllocation extends UnlistedSpecialPage {
 10+ public $project = 'wikipedia';
 11+ public $language = 'en';
 12+ public $location = 'US';
 13+
 14+ function __construct() {
 15+ // Register special page
 16+ parent::__construct( "BannerAllocation" );
 17+ }
 18+
 19+ /**
 20+ * Handle different types of page requests
 21+ */
 22+ function execute( $sub ) {
 23+ global $wgOut, $wgRequest, $wgExtensionAssetsPath, $wgNoticeProjects, $wgLanguageCode;
 24+
 25+ if ( $wgRequest->wasPosted() ) {
 26+ $this->project = $wgRequest->getText( 'project', 'wikipedia' );
 27+ $this->language = $wgRequest->getText( 'language', 'en' );
 28+ $this->location = $wgRequest->getText( 'country', 'US' );
 29+ }
 30+
 31+ // Begin output
 32+ $this->setHeaders();
 33+
 34+ // Add style file to the output headers
 35+ $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
 36+
 37+ // Add script file to the output headers
 38+ $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
 39+
 40+ // Initialize error variable
 41+ $this->centralNoticeError = false;
 42+
 43+ // Show summary
 44+ $wgOut->addWikiMsg( 'centralnotice-summary' );
 45+
 46+ // Show header
 47+ CentralNotice::printHeader();
 48+
 49+ // Begin Banners tab content
 50+ $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
 51+
 52+ $htmlOut = '';
 53+
 54+ // Begin Allocation selection fieldset
 55+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 56+
 57+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 58+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-view-allocation' ) );
 59+ $htmlOut .= Xml::tags( 'p', null, wfMsg( 'centralnotice-allocation-instructions' ) );
 60+
 61+ $htmlOut .= Xml::openElement( 'table', array ( 'id' => 'envpicker', 'cellpadding' => 7 ) );
 62+ $htmlOut .= Xml::openElement( 'tr' );
 63+ $htmlOut .= Xml::tags( 'td',
 64+ array( 'style' => 'width: 20%;' ),
 65+ wfMsg( 'centralnotice-project-name' ) );
 66+ $htmlOut .= Xml::openElement( 'td' );
 67+ $htmlOut .= Xml::openElement( 'select', array( 'name' => 'project' ) );
 68+ foreach ( $wgNoticeProjects as $value ) {
 69+ $htmlOut .= Xml::option( $value, $value, $value === $this->project );
 70+ }
 71+ $htmlOut .= Xml::closeElement( 'select' );
 72+ $htmlOut .= Xml::closeElement( 'td' );
 73+ $htmlOut .= Xml::closeElement( 'tr' );
 74+ $htmlOut .= Xml::openElement( 'tr' );
 75+ $htmlOut .= Xml::tags( 'td',
 76+ array( 'valign' => 'top' ),
 77+ wfMsg( 'centralnotice-project-lang' ) );
 78+ $htmlOut .= Xml::openElement( 'td' );
 79+ // Make sure the site language is in the list; a custom language code
 80+ // might not have a defined name...
 81+ $languages = Language::getLanguageNames( true );
 82+ if( !array_key_exists( $wgLanguageCode, $languages ) ) {
 83+ $languages[$wgLanguageCode] = $wgLanguageCode;
 84+ }
 85+ ksort( $languages );
 86+ $htmlOut .= Xml::openElement( 'select', array( 'name' => 'language' ) );
 87+ foreach( $languages as $code => $name ) {
 88+ $htmlOut .= Xml::option(
 89+ wfMsg( 'centralnotice-language-listing', $code, $name ),
 90+ $code, $code === $this->language );
 91+ }
 92+ $htmlOut .= Xml::closeElement( 'select' );
 93+ $htmlOut .= Xml::closeElement( 'td' );
 94+ $htmlOut .= Xml::closeElement( 'tr' );
 95+ $htmlOut .= Xml::openElement( 'tr' );
 96+ $htmlOut .= Xml::tags( 'td', array(), wfMsg( 'centralnotice-country' ) );
 97+ $htmlOut .= Xml::openElement( 'td' );
 98+ $countries = CentralNoticeDB::getCountriesList();
 99+ $htmlOut .= Xml::openElement( 'select', array( 'name' => 'country' ) );
 100+ foreach( $countries as $code => $name ) {
 101+ $htmlOut .= Xml::option( $name, $code, $code === $this->location );
 102+ }
 103+ $htmlOut .= Xml::closeElement( 'select' );
 104+ $htmlOut .= Xml::closeElement( 'td' );
 105+ $htmlOut .= Xml::closeElement( 'tr' );
 106+ $htmlOut .= Xml::closeElement( 'table' );
 107+
 108+ $htmlOut .= Xml::tags( 'div',
 109+ array( 'class' => 'cn-buttons' ),
 110+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 111+ );
 112+ $htmlOut .= Xml::closeElement( 'form' );
 113+
 114+ // End Allocation selection fieldset
 115+ $htmlOut .= Xml::closeElement( 'fieldset' );
 116+
 117+ $wgOut->addHTML( $htmlOut );
 118+
 119+ // Handle form submissions
 120+ if ( $wgRequest->wasPosted() ) {
 121+ $this->showList();
 122+ }
 123+
 124+ // End Banners tab content
 125+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 126+ }
 127+
 128+ /**
 129+ * Show a list of banners with allocation. Newer banners are shown first.
 130+ */
 131+ function showList() {
 132+ global $wgOut, $wgUser, $wgRequest, $wgLang;
 133+
 134+ $sk = $wgUser->getSkin();
 135+ $viewBanner = $this->getTitleFor( 'NoticeTemplate', 'view' );
 136+ $viewCampaign = $this->getTitleFor( 'CentralNotice' );
 137+
 138+ // Begin building HTML
 139+ $htmlOut = '';
 140+
 141+ // Begin Allocation list fieldset
 142+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 143+
 144+ $bannerLister = new SpecialBannerListLoader();
 145+ $bannerLister->project = $wgRequest->getVal( 'project' );
 146+ $bannerLister->language = $wgRequest->getVal( 'language' );
 147+ $bannerLister->location = $wgRequest->getVal( 'country' );
 148+
 149+ $htmlOut .= Xml::tags( 'p', null,
 150+ wfMsg (
 151+ 'centralnotice-allocation-description',
 152+ htmlspecialchars( $bannerLister->language ),
 153+ htmlspecialchars( $bannerLister->project ),
 154+ htmlspecialchars( $bannerLister->location )
 155+ )
 156+ );
 157+
 158+ $bannerList = $bannerLister->getJsonList();
 159+ $banners = FormatJson::decode( $bannerList, true );
 160+ $totalWeight = 0;
 161+ foreach ( $banners as $banner ) {
 162+ $totalWeight += $banner['weight'];
 163+ }
 164+ if ( $banners ) {
 165+ $htmlOut .= Xml::openElement( 'table',
 166+ array ( 'cellpadding' => 9, 'class' => 'wikitable sortable' ) );
 167+ $htmlOut .= Xml::openElement( 'tr' );
 168+ $htmlOut .= Xml::element( 'th', array( 'width' => '20%' ),
 169+ wfMsg ( 'centralnotice-percentage' ) );
 170+ $htmlOut .= Xml::element( 'th', array( 'width' => '30%' ),
 171+ wfMsg ( 'centralnotice-banner' ) );
 172+ $htmlOut .= Xml::element( 'th', array( 'width' => '30%' ),
 173+ wfMsg ( 'centralnotice-notice' ) );
 174+ $htmlOut .= Xml::closeElement( 'tr' );
 175+ foreach ( $banners as $banner ) {
 176+ $htmlOut .= Xml::openElement( 'tr' );
 177+ $htmlOut .= Xml::openElement( 'td' );
 178+ $percentage = ( $banner['weight'] / $totalWeight ) * 100;
 179+ $htmlOut .= wfMsg ( 'percent', $wgLang->formatNum( $percentage ) );
 180+ $htmlOut .= Xml::closeElement( 'td' );
 181+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 182+ $sk->makeLinkObj( $viewBanner, htmlspecialchars( $banner['name'] ),
 183+ 'template=' . urlencode( $banner['name'] ) )
 184+ );
 185+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 186+ $sk->makeLinkObj( $viewCampaign, htmlspecialchars( $banner['campaign'] ),
 187+ 'method=listNoticeDetail&notice=' . urlencode( $banner['campaign'] ) )
 188+ );
 189+ $htmlOut .= Xml::closeElement( 'tr' );
 190+ }
 191+ $htmlOut .= Xml::closeElement( 'table' );
 192+ } else {
 193+ $htmlOut .= Xml::tags( 'p', null, wfMsg ( 'centralnotice-no-allocation' ) );
 194+ }
 195+
 196+ // End Allocation list fieldset
 197+ $htmlOut .= Xml::closeElement( 'fieldset' );
 198+
 199+ $wgOut->addHTML( $htmlOut );
 200+ }
 201+
 202+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerAllocation.php
___________________________________________________________________
Added: svn:eol-style
1203 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerLoader.php
@@ -0,0 +1,221 @@
 2+<?php
 3+
 4+/**
 5+ * Generates banner HTML files
 6+ */
 7+class SpecialBannerLoader extends UnlistedSpecialPage {
 8+ public $siteName = 'Wikipedia'; // Site name
 9+ public $language = 'en'; // User language
 10+ protected $sharedMaxAge = 600; // Cache for 10 minutes on the server side
 11+ protected $maxAge = 0; // No client-side banner caching so we get all impressions
 12+
 13+ function __construct() {
 14+ // Register special page
 15+ parent::__construct( "BannerLoader" );
 16+ }
 17+
 18+ function execute( $par ) {
 19+ global $wgOut, $wgRequest;
 20+
 21+ $wgOut->disable();
 22+ $this->sendHeaders();
 23+
 24+ // Get values from the query string
 25+ $this->language = $wgRequest->getText( 'userlang', 'en' );
 26+ $this->siteName = $wgRequest->getText( 'sitename', 'Wikipedia' );
 27+ $this->campaign = $wgRequest->getText( 'campaign', 'unknown' );
 28+ $this->fundraising = $wgRequest->getBool( 'fundraising', false );
 29+ $this->landingPages = $wgRequest->getText( 'landingpages' );
 30+
 31+ if ( $wgRequest->getText( 'banner' ) ) {
 32+ $bannerName = $wgRequest->getText( 'banner' );
 33+ try {
 34+ $content = $this->getJsNotice( $bannerName );
 35+ if ( preg_match( "/&lt;centralnotice-template-\w+&gt;\z/", $content ) ) {
 36+ echo "/* Failed cache lookup */";
 37+ } elseif ( strlen( $content ) == 0 ) {
 38+ // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
 39+ echo "/* Empty */";
 40+ } else {
 41+ echo $content;
 42+ }
 43+ } catch (SpecialBannerLoaderException $e) {
 44+ echo "/* Banner could not be generated */";
 45+ }
 46+ } else {
 47+ echo "/* No banner specified */";
 48+ }
 49+ }
 50+
 51+ /**
 52+ * Generate the HTTP response headers for the banner file
 53+ */
 54+ function sendHeaders() {
 55+ global $wgJsMimeType;
 56+ header( "Content-type: $wgJsMimeType; charset=utf-8" );
 57+ header( "Cache-Control: public, s-maxage=$this->sharedMaxAge, max-age=$this->maxAge" );
 58+ }
 59+
 60+ /**
 61+ * Generate the JS for the requested banner
 62+ * @return a string of Javascript containing a call to insertBanner()
 63+ * with JSON containing the banner content as the parameter
 64+ * @throws SpecialBannerLoaderException
 65+ */
 66+ function getJsNotice( $bannerName ) {
 67+ // Make sure the banner exists
 68+ if ( CentralNoticeDB::bannerExists( $bannerName ) ) {
 69+ $this->bannerName = $bannerName;
 70+ $bannerHtml = '';
 71+ $bannerHtml .= preg_replace_callback(
 72+ '/{{{(.*?)}}}/',
 73+ array( $this, 'getNoticeField' ),
 74+ $this->getNoticeTemplate()
 75+ );
 76+ $bannerArray = array(
 77+ 'bannerName' => $bannerName,
 78+ 'bannerHtml' => $bannerHtml,
 79+ 'campaign' => $this->campaign,
 80+ 'fundraising' => $this->fundraising,
 81+ 'landingPages' => $this->landingPages
 82+ );
 83+ $bannerJs = 'insertBanner('.FormatJson::encode( $bannerArray ).');';
 84+ return $bannerJs;
 85+ }
 86+ }
 87+
 88+ /**
 89+ * Generate the HTML for the requested banner
 90+ * @throws SpecialBannerLoaderException
 91+ */
 92+ function getHtmlNotice( $bannerName ) {
 93+ // Make sure the banner exists
 94+ if ( CentralNoticeDB::bannerExists( $bannerName ) ) {
 95+ $this->bannerName = $bannerName;
 96+ $bannerHtml = '';
 97+ $bannerHtml .= preg_replace_callback(
 98+ '/{{{(.*?)}}}/',
 99+ array( $this, 'getNoticeField' ),
 100+ $this->getNoticeTemplate()
 101+ );
 102+ return $bannerHtml;
 103+ }
 104+ }
 105+
 106+ /**
 107+ * Get the body of the banner with only {{int:...}} messages translated
 108+ */
 109+ function getNoticeTemplate() {
 110+ $out = $this->getMessage( "centralnotice-template-{$this->bannerName}" );
 111+ return $out;
 112+ }
 113+
 114+ /**
 115+ * Extract a message name and send to getMessage() for translation
 116+ * @param $match A message array with 2 members: raw match, short name of message
 117+ * @return translated messsage string
 118+ * @throws SpecialBannerLoaderException
 119+ */
 120+ function getNoticeField( $match ) {
 121+ $field = $match[1];
 122+ $params = array();
 123+ if ( $field == 'amount' ) {
 124+ $params = array( $this->toMillions( $this->getDonationAmount() ) );
 125+ }
 126+ $message = "centralnotice-{$this->bannerName}-$field";
 127+ $source = $this->getMessage( $message, $params );
 128+ return $source;
 129+ }
 130+
 131+ /**
 132+ * Convert number of dollars to millions of dollars
 133+ */
 134+ private function toMillions( $num ) {
 135+ $num = sprintf( "%.1f", $num / 1e6 );
 136+ if ( substr( $num, - 2 ) == '.0' ) {
 137+ $num = substr( $num, 0, - 2 );
 138+ }
 139+ $lang = Language::factory( $this->language );
 140+ return $lang->formatNum( $num );
 141+ }
 142+
 143+ /**
 144+ * Retrieve a translated message
 145+ * @param $msg The full name of the message
 146+ * @return translated messsage string
 147+ */
 148+ private function getMessage( $msg, $params = array() ) {
 149+ global $wgLang, $wgSitename;
 150+
 151+ // A god-damned dirty hack! :D
 152+ $oldLang = $wgLang;
 153+ $oldSitename = $wgSitename;
 154+
 155+ $wgSitename = $this->siteName; // hack for {{SITENAME}}
 156+ $wgLang = Language::factory( $this->language ); // hack for {{int:...}}
 157+
 158+ $options = array( 'language' => $this->language, 'parsemag' );
 159+ array_unshift( $params, $options );
 160+ array_unshift( $params, $msg );
 161+ $out = call_user_func_array( 'wfMsgExt', $params );
 162+
 163+ // Restore global variables
 164+ $wgLang = $oldLang;
 165+ $wgSitename = $oldSitename;
 166+
 167+ return $out;
 168+ }
 169+
 170+ /**
 171+ * Pull the current amount raised during a fundraiser
 172+ * @throws SpecialBannerLoaderException
 173+ */
 174+ private function getDonationAmount() {
 175+ global $wgNoticeCounterSource, $wgMemc;
 176+ // Pull short-cached amount
 177+ $count = intval( $wgMemc->get( wfMemcKey( 'centralnotice', 'counter' ) ) );
 178+ if ( !$count ) {
 179+ // Pull from dynamic counter
 180+ $counter_value = Http::get( $wgNoticeCounterSource );
 181+ if( !$counter_value ) {
 182+ throw new RemoteServerProblemException();
 183+ }
 184+ $count = intval( $counter_value );
 185+ if ( !$count ) {
 186+ // Pull long-cached amount
 187+ $count = intval( $wgMemc->get(
 188+ wfMemcKey( 'centralnotice', 'counter', 'fallback' ) ) );
 189+ if ( !$count ) {
 190+ throw new DonationAmountUnknownException();
 191+ }
 192+ }
 193+ // Expire in 60 seconds
 194+ $wgMemc->set( wfMemcKey( 'centralnotice', 'counter' ), $count, 60 );
 195+ // No expiration
 196+ $wgMemc->set( wfMemcKey( 'centralnotice', 'counter', 'fallback' ), $count );
 197+ }
 198+ return $count;
 199+ }
 200+}
 201+/**
 202+ * @defgroup Exception Exception
 203+ */
 204+
 205+/**
 206+ * SpecialBannerLoaderException exception
 207+ *
 208+ * This exception is being thrown whenever
 209+ * some fatal error occurs that may affect
 210+ * how the banner is presented.
 211+ *
 212+ * @ingroup Exception
 213+ */
 214+
 215+class SpecialBannerLoaderException extends Exception {
 216+}
 217+
 218+class RemoteServerProblemException extends SpecialBannerLoaderException {
 219+}
 220+
 221+class DonationAmountUnknownException extends SpecialBannerLoaderException {
 222+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialBannerLoader.php
___________________________________________________________________
Added: svn:eol-style
1223 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialNoticeTemplate.php
@@ -0,0 +1,964 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class SpecialNoticeTemplate extends UnlistedSpecialPage {
 10+ var $editable, $centralNoticeError;
 11+
 12+ function __construct() {
 13+ // Register special page
 14+ parent::__construct( 'NoticeTemplate' );
 15+ }
 16+
 17+ /**
 18+ * Handle different types of page requests
 19+ */
 20+ function execute( $sub ) {
 21+ global $wgOut, $wgUser, $wgRequest, $wgExtensionAssetsPath;
 22+
 23+ // Begin output
 24+ $this->setHeaders();
 25+
 26+ // Add style file to the output headers
 27+ $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
 28+
 29+ // Add localized script error messages
 30+ $scriptVars = array(
 31+ 'documentWriteError' => wfMsg( 'centralnotice-documentwrite-error' )
 32+ );
 33+ $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
 34+
 35+ // Add script file to the output headers
 36+ $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
 37+
 38+ // Check permissions
 39+ $this->editable = $wgUser->isAllowed( 'centralnotice-admin' );
 40+
 41+ // Initialize error variable
 42+ $this->centralNoticeError = false;
 43+
 44+ // Show summary
 45+ $wgOut->addWikiMsg( 'centralnotice-summary' );
 46+
 47+ // Show header
 48+ CentralNotice::printHeader();
 49+
 50+ // Begin Banners tab content
 51+ $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
 52+
 53+ $method = $wgRequest->getVal( 'wpMethod' );
 54+
 55+ // Handle form submissions
 56+ if ( $this->editable && $wgRequest->wasPosted() ) {
 57+
 58+ // Check authentication token
 59+ if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
 60+
 61+ // Handle removing banners
 62+ $toRemove = $wgRequest->getArray( 'removeTemplates' );
 63+ if ( isset( $toRemove ) ) {
 64+ // Remove banners in list
 65+ foreach ( $toRemove as $template ) {
 66+ $this->removeTemplate( $template );
 67+ }
 68+ }
 69+
 70+ // Handle translation message update
 71+ $update = $wgRequest->getArray( 'updateText' );
 72+ if ( isset ( $update ) ) {
 73+ foreach ( $update as $lang => $messages ) {
 74+ foreach ( $messages as $text => $translation ) {
 75+ // If we actually have text
 76+ if ( $translation ) {
 77+ $this->updateMessage( $text, $translation, $lang );
 78+ }
 79+ }
 80+ }
 81+ }
 82+
 83+ // Handle adding banner
 84+ if ( $method == 'addTemplate' ) {
 85+ $newTemplateName = $wgRequest->getText( 'templateName' );
 86+ $newTemplateBody = $wgRequest->getText( 'templateBody' );
 87+ if ( $newTemplateName != '' && $newTemplateBody != '' ) {
 88+ $this->addTemplate(
 89+ $newTemplateName,
 90+ $newTemplateBody,
 91+ $wgRequest->getBool( 'displayAnon' ),
 92+ $wgRequest->getBool( 'displayAccount' ),
 93+ $wgRequest->getBool( 'fundraising' ),
 94+ $wgRequest->getVal( 'landingPages' )
 95+ );
 96+ $sub = 'view';
 97+ } else {
 98+ $this->showError( 'centralnotice-null-string' );
 99+ }
 100+ }
 101+
 102+ // Handle editing banner
 103+ if ( $method == 'editTemplate' ) {
 104+ $this->editTemplate(
 105+ $wgRequest->getText( 'template' ),
 106+ $wgRequest->getText( 'templateBody' ),
 107+ $wgRequest->getBool( 'displayAnon' ),
 108+ $wgRequest->getBool( 'displayAccount' ),
 109+ $wgRequest->getBool( 'fundraising' ),
 110+ $wgRequest->getVal( 'landingPages' )
 111+ );
 112+ $sub = 'view';
 113+ }
 114+
 115+ } else {
 116+ $this->showError( 'sessionfailure' );
 117+ }
 118+
 119+ }
 120+
 121+ // Handle viewing of a banner in all languages
 122+ if ( $sub == 'view' && $wgRequest->getVal( 'wpUserLanguage' ) == 'all' ) {
 123+ $template = $wgRequest->getVal( 'template' );
 124+ $this->showViewAvailable( $template );
 125+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 126+ return;
 127+ }
 128+
 129+ // Handle viewing a specific banner
 130+ if ( $sub == 'view' && $wgRequest->getText( 'template' ) != '' ) {
 131+ $this->showView();
 132+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 133+ return;
 134+ }
 135+
 136+ if ( $this->editable ) {
 137+ // Handle showing "Add a banner" interface
 138+ if ( $sub == 'add' ) {
 139+ $this->showAdd();
 140+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 141+ return;
 142+ }
 143+
 144+ // Handle cloning a specific banner
 145+ if ( $sub == 'clone' ) {
 146+
 147+ // Check authentication token
 148+ if ( $wgUser->matchEditToken( $wgRequest->getVal( 'authtoken' ) ) ) {
 149+
 150+ $oldTemplate = $wgRequest->getVal( 'oldTemplate' );
 151+ $newTemplate = $wgRequest->getVal( 'newTemplate' );
 152+ // We use the returned name in case any special characters had to be removed
 153+ $template = $this->cloneTemplate( $oldTemplate, $newTemplate );
 154+ $wgOut->redirect(
 155+ $this->getTitle( 'view' )->getLocalUrl( "template=$template" ) );
 156+ return;
 157+
 158+ } else {
 159+ $this->showError( 'sessionfailure' );
 160+ }
 161+
 162+ }
 163+
 164+ }
 165+
 166+ // Show list of banners by default
 167+ $this->showList();
 168+
 169+ // End Banners tab content
 170+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 171+ }
 172+
 173+ /**
 174+ * Show a list of available banners. Newer banners are shown first.
 175+ */
 176+ function showList() {
 177+ global $wgOut, $wgUser;
 178+
 179+ $sk = $wgUser->getSkin();
 180+ $pager = new TemplatePager( $this );
 181+
 182+ // Begin building HTML
 183+ $htmlOut = '';
 184+
 185+ // Begin Manage Banners fieldset
 186+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 187+
 188+ if ( !$pager->getNumRows() ) {
 189+ $htmlOut .= Xml::element( 'p', null, wfMsg( 'centralnotice-no-templates' ) );
 190+ } else {
 191+ if ( $this->editable ) {
 192+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 193+ }
 194+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-manage-templates' ) );
 195+
 196+ // Show paginated list of banners
 197+ $htmlOut .= Xml::tags( 'div', array( 'class' => 'cn-pager' ),
 198+ $pager->getNavigationBar() );
 199+ $htmlOut .= $pager->getBody();
 200+ $htmlOut .= Xml::tags( 'div', array( 'class' => 'cn-pager' ),
 201+ $pager->getNavigationBar() );
 202+
 203+ if ( $this->editable ) {
 204+ $htmlOut .= Xml::closeElement( 'form' );
 205+ }
 206+ }
 207+
 208+ if ( $this->editable ) {
 209+ $htmlOut .= Xml::element( 'p' );
 210+ $newPage = $this->getTitle( 'add' );
 211+ $htmlOut .= $sk->makeLinkObj( $newPage, wfMsgHtml( 'centralnotice-add-template' ) );
 212+ }
 213+
 214+ // End Manage Banners fieldset
 215+ $htmlOut .= Xml::closeElement( 'fieldset' );
 216+
 217+ $wgOut->addHTML( $htmlOut );
 218+ }
 219+
 220+ /**
 221+ * Show "Add a banner" interface
 222+ */
 223+ function showAdd() {
 224+ global $wgOut, $wgUser, $wgExtensionAssetsPath, $wgLang, $wgRequest,
 225+ $wgNoticeEnableFundraising;
 226+ $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
 227+
 228+ // Build HTML
 229+ $htmlOut = '';
 230+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 231+ $htmlOut .= Xml::openElement( 'form',
 232+ array( 'method' => 'post', 'onsubmit' => 'return validateBannerForm(this)' ) );
 233+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-add-template' ) );
 234+ $htmlOut .= Html::hidden( 'wpMethod', 'addTemplate' );
 235+
 236+ // If there was an error, we'll need to restore the state of the form
 237+ if ( $wgRequest->wasPosted() ) {
 238+ $templateName = $wgRequest->getVal( 'templateName' );
 239+ $displayAnon = $wgRequest->getCheck( 'displayAnon' );
 240+ $displayAccount = $wgRequest->getCheck( 'displayAccount' );
 241+ $fundraising = $wgRequest->getCheck( 'fundraising' );
 242+ $landingPages = $wgRequest->getVal( 'landingPages' );
 243+ $body = $wgRequest->getVal( 'templateBody' );
 244+ } else { // Use default values
 245+ $templateName = '';
 246+ $displayAnon = true;
 247+ $displayAccount = true;
 248+ $fundraising = false;
 249+ $landingPages = '';
 250+ $body = '';
 251+ }
 252+
 253+ $htmlOut .= Xml::tags( 'p', null,
 254+ Xml::inputLabel(
 255+ wfMsg( 'centralnotice-banner-name' ),
 256+ 'templateName', 'templateName', 25, $templateName
 257+ )
 258+ );
 259+
 260+ // Display settings
 261+ $htmlOut .= Xml::openElement( 'p', null );
 262+ $htmlOut .= wfMsg( 'centralnotice-banner-display' );
 263+ $htmlOut .= Xml::check( 'displayAnon', $displayAnon, array( 'id' => 'displayAnon' ) );
 264+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-anonymous' ), 'displayAnon' );
 265+ $htmlOut .= Xml::check( 'displayAccount', $displayAccount,
 266+ array( 'id' => 'displayAccount' ) );
 267+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-logged-in' ), 'displayAccount' );
 268+ $htmlOut .= Xml::closeElement( 'p' );
 269+
 270+ // Fundraising settings
 271+ if ( $wgNoticeEnableFundraising ) {
 272+ $htmlOut .= Xml::openElement( 'p', null );
 273+ $htmlOut .= Xml::check( 'fundraising', $fundraising, array( 'id' => 'fundraising' ) );
 274+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-fundraising' ), 'fundraising' );
 275+ $htmlOut .= Xml::closeElement( 'p' );
 276+ $htmlOut .= Xml::openElement( 'div',
 277+ array( 'id' => 'fundraisingInterface', 'style' => 'display: none;' ) );
 278+ $htmlOut .= Xml::tags( 'p', array(), wfMsg( 'centralnotice-banner-fundraising-help' ) );
 279+ $htmlOut .= Xml::tags( 'p', array(),
 280+ Xml::inputLabel(
 281+ wfMsg( 'centralnotice-banner-landing-pages' ),
 282+ 'landingPages', 'landingPages', 40, $landingPages,
 283+ array( 'maxlength' => 255 )
 284+ )
 285+ );
 286+ $htmlOut .= Xml::closeElement( 'div' );
 287+ }
 288+
 289+ // Begin banner body section
 290+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-banner' ) );
 291+ $htmlOut .= wfMsg( 'centralnotice-edit-template-summary' );
 292+ $buttons = array();
 293+ $buttons[] = '<a href="#" onclick="insertButton(\'close\');return false;">' .
 294+ wfMsg( 'centralnotice-close-button' ) . '</a>';
 295+ $htmlOut .= Xml::tags( 'div',
 296+ array( 'style' => 'margin-bottom: 0.2em;' ),
 297+ '<img src="'.$scriptPath.'/down-arrow.png" style="vertical-align:baseline;"/>' .
 298+ wfMsg( 'centralnotice-insert', $wgLang->commaList( $buttons ) )
 299+ );
 300+
 301+ $htmlOut .= Xml::textarea( 'templateBody', $body, 60, 20 );
 302+ $htmlOut .= Xml::closeElement( 'fieldset' );
 303+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 304+
 305+ // Submit button
 306+ $htmlOut .= Xml::tags( 'div',
 307+ array( 'class' => 'cn-buttons' ),
 308+ Xml::submitButton( wfMsg( 'centralnotice-save-banner' ) )
 309+ );
 310+
 311+ $htmlOut .= Xml::closeElement( 'form' );
 312+ $htmlOut .= Xml::closeElement( 'fieldset' );
 313+
 314+ // Output HTML
 315+ $wgOut->addHTML( $htmlOut );
 316+ }
 317+
 318+ /**
 319+ * View or edit an individual banner
 320+ */
 321+ private function showView() {
 322+ global $wgOut, $wgUser, $wgRequest, $wgLanguageCode, $wgExtensionAssetsPath, $wgLang,
 323+ $wgNoticeEnableFundraising;
 324+
 325+ $scriptPath = "$wgExtensionAssetsPath/CentralNotice";
 326+ $sk = $wgUser->getSkin();
 327+
 328+ if ( $this->editable ) {
 329+ $readonly = array();
 330+ $disabled = array();
 331+ } else {
 332+ $readonly = array( 'readonly' => 'readonly' );
 333+ $disabled = array( 'disabled' => 'disabled' );
 334+ }
 335+
 336+ // Get user's language
 337+ $wpUserLang = $wgRequest->getVal( 'wpUserLanguage', $wgLanguageCode );
 338+
 339+ // Get current banner
 340+ $currentTemplate = $wgRequest->getText( 'template' );
 341+
 342+ // Pull banner settings from database
 343+ $dbr = wfGetDB( DB_SLAVE );
 344+ $row = $dbr->selectRow( 'cn_templates',
 345+ array(
 346+ 'tmp_display_anon',
 347+ 'tmp_display_account',
 348+ 'tmp_fundraising',
 349+ 'tmp_landing_pages'
 350+ ),
 351+ array( 'tmp_name' => $currentTemplate ),
 352+ __METHOD__
 353+ );
 354+
 355+ if ( !$row ) {
 356+ $this->showError( 'centralnotice-banner-doesnt-exist' );
 357+ return;
 358+ } else {
 359+ // Begin building HTML
 360+ $htmlOut = '';
 361+
 362+ // Begin View Banner fieldset
 363+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 364+
 365+ $htmlOut .= Xml::element( 'h2', null,
 366+ wfMsg( 'centralnotice-banner-heading', $currentTemplate ) );
 367+
 368+ // Show preview of banner
 369+ $render = new SpecialBannerLoader();
 370+ $render->siteName = 'Wikipedia';
 371+ $render->language = $wpUserLang;
 372+ try {
 373+ $preview = $render->getHtmlNotice( $wgRequest->getText( 'template' ) );
 374+ } catch ( SpecialBannerLoaderException $e ) {
 375+ $preview = wfMsg( 'centralnotice-nopreview' );
 376+ }
 377+ if ( $render->language != '' ) {
 378+ $htmlOut .= Xml::fieldset(
 379+ wfMsg( 'centralnotice-preview' ) . " ($render->language)",
 380+ $preview
 381+ );
 382+ } else {
 383+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 384+ $preview
 385+ );
 386+ }
 387+
 388+ // Pull banner text and respect any inc: markup
 389+ $bodyPage = Title::newFromText(
 390+ "Centralnotice-template-{$currentTemplate}", NS_MEDIAWIKI );
 391+ $curRev = Revision::newFromTitle( $bodyPage );
 392+ $body = $curRev ? $curRev->getText() : '';
 393+
 394+ // Extract message fields from the banner body
 395+ $fields = array();
 396+ $allowedChars = Title::legalChars();
 397+ preg_match_all( "/\{\{\{([$allowedChars]+)\}\}\}/u", $body, $fields );
 398+
 399+ // If there are any message fields in the banner, display translation tools.
 400+ if ( count( $fields[0] ) > 0 ) {
 401+ if ( $this->editable ) {
 402+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 403+ }
 404+ $htmlOut .= Xml::fieldset(
 405+ wfMsg( 'centralnotice-translate-heading', $currentTemplate ),
 406+ false,
 407+ array( 'id' => 'mw-centralnotice-translations-for' )
 408+ );
 409+ $htmlOut .= Xml::openElement( 'table',
 410+ array (
 411+ 'cellpadding' => 9,
 412+ 'width' => '100%'
 413+ )
 414+ );
 415+
 416+ // Table headers
 417+ $htmlOut .= Xml::element( 'th', array( 'width' => '15%' ),
 418+ wfMsg( 'centralnotice-message' ) );
 419+ $htmlOut .= Xml::element( 'th', array( 'width' => '5%' ),
 420+ wfMsg ( 'centralnotice-number-uses' ) );
 421+ $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ),
 422+ wfMsg ( 'centralnotice-english' ) );
 423+ $languages = Language::getLanguageNames();
 424+ $htmlOut .= Xml::element( 'th', array( 'width' => '40%' ),
 425+ $languages[$wpUserLang] );
 426+
 427+ // Remove duplicate message fields
 428+ $filteredFields = array();
 429+ foreach ( $fields[1] as $field ) {
 430+ $filteredFields[$field] = array_key_exists( $field, $filteredFields )
 431+ ? $filteredFields[$field] + 1 : 1;
 432+ }
 433+
 434+ // Table rows
 435+ foreach ( $filteredFields as $field => $count ) {
 436+ // Message
 437+ $message = ( $wpUserLang == 'en' )
 438+ ? "Centralnotice-{$currentTemplate}-{$field}"
 439+ : "Centralnotice-{$currentTemplate}-{$field}/{$wpUserLang}";
 440+
 441+ // English value
 442+ $htmlOut .= Xml::openElement( 'tr' );
 443+
 444+ $title = Title::newFromText( "MediaWiki:{$message}" );
 445+ $htmlOut .= Xml::tags( 'td', null,
 446+ $sk->makeLinkObj( $title, htmlspecialchars( $field ) )
 447+ );
 448+
 449+ $htmlOut .= Xml::element( 'td', null, $count );
 450+
 451+ // English text
 452+ $englishText = wfMsg( 'centralnotice-message-not-set' );
 453+ $englishTextExists = false;
 454+ if (
 455+ Title::newFromText(
 456+ "Centralnotice-{$currentTemplate}-{$field}", NS_MEDIAWIKI
 457+ )->exists() )
 458+ {
 459+ $englishText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
 460+ array( 'language' => 'en' )
 461+ );
 462+ $englishTextExists = true;
 463+ }
 464+ $htmlOut .= Xml::tags( 'td', null,
 465+ Xml::element( 'span',
 466+ array(
 467+ 'style' => 'font-style:italic;' .
 468+ ( !$englishTextExists ? 'color:silver' : '' )
 469+ ),
 470+ $englishText
 471+ )
 472+ );
 473+
 474+ // Foreign text input
 475+ $foreignText = '';
 476+ $foreignTextExists = false;
 477+ if ( Title::newFromText( $message, NS_MEDIAWIKI )->exists() ) {
 478+ $foreignText = wfMsgExt( "Centralnotice-{$currentTemplate}-{$field}",
 479+ array( 'language' => $wpUserLang )
 480+ );
 481+ $foreignTextExists = true;
 482+ }
 483+ $htmlOut .= Xml::tags( 'td', null,
 484+ Xml::input(
 485+ "updateText[{$wpUserLang}][{$currentTemplate}-{$field}]",
 486+ '',
 487+ $foreignText,
 488+ wfArrayMerge( $readonly,
 489+ array( 'style' => 'width:100%;' .
 490+ ( !$foreignTextExists ? 'color:red' : '' ) ) )
 491+ )
 492+ );
 493+ $htmlOut .= Xml::closeElement( 'tr' );
 494+ }
 495+ $htmlOut .= Xml::closeElement( 'table' );
 496+
 497+ if ( $this->editable ) {
 498+ $htmlOut .= Html::hidden( 'wpUserLanguage', $wpUserLang );
 499+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 500+ $htmlOut .= Xml::tags( 'div',
 501+ array( 'class' => 'cn-buttons' ),
 502+ Xml::submitButton(
 503+ wfMsg( 'centralnotice-modify' ),
 504+ array( 'name' => 'update' )
 505+ )
 506+ );
 507+ }
 508+
 509+ $htmlOut .= Xml::closeElement( 'fieldset' );
 510+
 511+ if ( $this->editable ) {
 512+ $htmlOut .= Xml::closeElement( 'form' );
 513+ }
 514+
 515+ // Show language selection form
 516+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 517+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-change-lang' ) );
 518+ $htmlOut .= Xml::openElement( 'table', array ( 'cellpadding' => 9 ) );
 519+ list( $lsLabel, $lsSelect ) = Xml::languageSelector( $wpUserLang );
 520+
 521+ $newPage = $this->getTitle( 'view' );
 522+
 523+ $htmlOut .= Xml::tags( 'tr', null,
 524+ Xml::tags( 'td', null, $lsLabel ) .
 525+ Xml::tags( 'td', null, $lsSelect ) .
 526+ Xml::tags( 'td', array( 'colspan' => 2 ),
 527+ Xml::submitButton( wfMsg( 'centralnotice-modify' ) )
 528+ )
 529+ );
 530+ $htmlOut .= Xml::tags( 'tr', null,
 531+ Xml::tags( 'td', null, '' ) .
 532+ Xml::tags( 'td', null,
 533+ $sk->makeLinkObj(
 534+ $newPage,
 535+ wfMsgHtml( 'centralnotice-preview-all-template-translations' ),
 536+ "template=$currentTemplate&wpUserLanguage=all" )
 537+ )
 538+ );
 539+ $htmlOut .= Xml::closeElement( 'table' );
 540+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 541+ $htmlOut .= Xml::closeElement( 'fieldset' );
 542+ $htmlOut .= Xml::closeElement( 'form' );
 543+ }
 544+
 545+ // Show edit form
 546+ if ( $this->editable ) {
 547+ $htmlOut .= Xml::openElement( 'form',
 548+ array(
 549+ 'method' => 'post',
 550+ 'onsubmit' => 'return validateBannerForm(this)'
 551+ )
 552+ );
 553+ $htmlOut .= Html::hidden( 'wpMethod', 'editTemplate' );
 554+ }
 555+
 556+ // If there was an error, we'll need to restore the state of the form
 557+ if ( $wgRequest->wasPosted() && $wgRequest->getVal( 'mainform' ) ) {
 558+ $displayAnon = $wgRequest->getCheck( 'displayAnon' );
 559+ $displayAccount = $wgRequest->getCheck( 'displayAccount' );
 560+ $fundraising = $wgRequest->getCheck( 'fundraising' );
 561+ $landingPages = $wgRequest->getVal( 'landingPages' );
 562+ $body = $wgRequest->getVal( 'templateBody', $body );
 563+ } else { // Use previously stored values
 564+ $displayAnon = ( $row->tmp_display_anon == 1 );
 565+ $displayAccount = ( $row->tmp_display_account == 1 );
 566+ $fundraising = ( $row->tmp_fundraising == 1 );
 567+ $landingPages = $row->tmp_landing_pages;
 568+ // $body default is defined prior to message interface code
 569+ }
 570+
 571+ // Show banner settings
 572+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-settings' ) );
 573+ $htmlOut .= Xml::openElement( 'p', null );
 574+ $htmlOut .= wfMsg( 'centralnotice-banner-display' );
 575+ $htmlOut .= Xml::check( 'displayAnon', $displayAnon,
 576+ wfArrayMerge( $disabled, array( 'id' => 'displayAnon' ) ) );
 577+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-anonymous' ), 'displayAnon' );
 578+ $htmlOut .= Xml::check( 'displayAccount', $displayAccount,
 579+ wfArrayMerge( $disabled, array( 'id' => 'displayAccount' ) ) );
 580+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-logged-in' ), 'displayAccount' );
 581+ $htmlOut .= Xml::closeElement( 'p' );
 582+
 583+ // Fundraising settings
 584+ if ( $wgNoticeEnableFundraising ) {
 585+ $htmlOut .= Xml::openElement( 'p', null );
 586+ $htmlOut .= Xml::check( 'fundraising', $fundraising,
 587+ wfArrayMerge( $disabled, array( 'id' => 'fundraising' ) ) );
 588+ $htmlOut .= Xml::label( wfMsg( 'centralnotice-banner-fundraising' ),
 589+ 'fundraising' );
 590+ $htmlOut .= Xml::closeElement( 'p' );
 591+ if ( $fundraising ) {
 592+ $htmlOut .= Xml::openElement( 'div', array( 'id'=>'fundraisingInterface' ) );
 593+ } else {
 594+ $htmlOut .= Xml::openElement( 'div',
 595+ array( 'id'=>'fundraisingInterface', 'style'=>'display:none;' ) );
 596+ }
 597+ $htmlOut .= Xml::tags( 'p', array(),
 598+ wfMsg( 'centralnotice-banner-fundraising-help' ) );
 599+ $htmlOut .= Xml::tags( 'p', array(),
 600+ Xml::inputLabel(
 601+ wfMsg( 'centralnotice-banner-landing-pages' ),
 602+ 'landingPages', 'landingPages', 40, $landingPages,
 603+ array( 'maxlength' => 255 )
 604+ )
 605+ );
 606+ $htmlOut .= Xml::closeElement( 'div' );
 607+ }
 608+
 609+ // Begin banner body section
 610+ $htmlOut .= Xml::closeElement( 'fieldset' );
 611+ if ( $this->editable ) {
 612+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-edit-template' ) );
 613+ $htmlOut .= wfMsg( 'centralnotice-edit-template-summary' );
 614+ $buttons = array();
 615+ $buttons[] = '<a href="#" onclick="insertButton(\'close\');return false;">' .
 616+ wfMsg( 'centralnotice-close-button' ) . '</a>';
 617+ $htmlOut .= Xml::tags( 'div',
 618+ array( 'style' => 'margin-bottom: 0.2em;' ),
 619+ '<img src="' . $scriptPath . '/down-arrow.png" ' .
 620+ 'style="vertical-align:baseline;"/>' .
 621+ wfMsg( 'centralnotice-insert', $wgLang->commaList( $buttons ) )
 622+ );
 623+ } else {
 624+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-banner' ) );
 625+ }
 626+ $htmlOut .= Xml::textarea( 'templateBody', $body, 60, 20, $readonly );
 627+ $htmlOut .= Xml::closeElement( 'fieldset' );
 628+ if ( $this->editable ) {
 629+ // Indicate which form was submitted
 630+ $htmlOut .= Html::hidden( 'mainform', 'true' );
 631+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 632+ $htmlOut .= Xml::tags( 'div',
 633+ array( 'class' => 'cn-buttons' ),
 634+ Xml::submitButton( wfMsg( 'centralnotice-save-banner' ) )
 635+ );
 636+ $htmlOut .= Xml::closeElement( 'form' );
 637+ }
 638+
 639+ // Show clone form
 640+ if ( $this->editable ) {
 641+ $htmlOut .= Xml::openElement ( 'form',
 642+ array(
 643+ 'method' => 'post',
 644+ 'action' => $this->getTitle( 'clone' )->getLocalUrl()
 645+ )
 646+ );
 647+
 648+ $htmlOut .= Xml::fieldset( wfMsg( 'centralnotice-clone-notice' ) );
 649+ $htmlOut .= Xml::openElement( 'table', array( 'cellpadding' => 9 ) );
 650+ $htmlOut .= Xml::openElement( 'tr' );
 651+ $htmlOut .= Xml::inputLabel(
 652+ wfMsg( 'centralnotice-clone-name' ),
 653+ 'newTemplate', 'newTemplate', '25' );
 654+ $htmlOut .= Xml::submitButton(
 655+ wfMsg( 'centralnotice-clone' ),
 656+ array ( 'id' => 'clone' ) );
 657+ $htmlOut .= Html::hidden( 'oldTemplate', $currentTemplate );
 658+
 659+ $htmlOut .= Xml::closeElement( 'tr' );
 660+ $htmlOut .= Xml::closeElement( 'table' );
 661+ $htmlOut .= Html::hidden( 'authtoken', $wgUser->editToken() );
 662+ $htmlOut .= Xml::closeElement( 'fieldset' );
 663+ $htmlOut .= Xml::closeElement( 'form' );
 664+ }
 665+
 666+ // End View Banner fieldset
 667+ $htmlOut .= Xml::closeElement( 'fieldset' );
 668+
 669+ // Output HTML
 670+ $wgOut->addHTML( $htmlOut );
 671+ }
 672+ }
 673+
 674+ /**
 675+ * Preview all available translations of a banner
 676+ */
 677+ public function showViewAvailable( $template ) {
 678+ global $wgOut, $wgUser;
 679+
 680+ // Testing to see if bumping up the memory limit lets meta preview
 681+ ini_set( 'memory_limit', '120M' );
 682+
 683+ $sk = $wgUser->getSkin();
 684+
 685+ // Pull all available text for a banner
 686+ $langs = array_keys( $this->getTranslations( $template ) );
 687+ $htmlOut = '';
 688+
 689+ // Begin View Banner fieldset
 690+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 691+
 692+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-banner-heading', $template ) );
 693+
 694+ foreach ( $langs as $lang ) {
 695+ // Link and Preview all available translations
 696+ $viewPage = $this->getTitle( 'view' );
 697+ $render = new SpecialBannerLoader();
 698+ $render->siteName = 'Wikipedia';
 699+ $render->language = $lang;
 700+ try {
 701+ $preview = $render->getHtmlNotice( $template );
 702+ } catch ( SpecialBannerLoaderException $e ) {
 703+ $preview = wfMsg( 'centralnotice-nopreview' );
 704+ }
 705+ $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
 706+ $sk->makeLinkObj( $viewPage,
 707+ $lang,
 708+ 'template=' . urlencode( $template ) . "&wpUserLanguage=$lang" ) .
 709+ Xml::fieldset( wfMsg( 'centralnotice-preview' ),
 710+ $preview,
 711+ array( 'class' => 'cn-bannerpreview')
 712+ )
 713+ );
 714+ }
 715+
 716+ // End View Banner fieldset
 717+ $htmlOut .= Xml::closeElement( 'fieldset' );
 718+
 719+ return $wgOut->addHtml( $htmlOut );
 720+ }
 721+
 722+ /**
 723+ * Add or update a message
 724+ */
 725+ private function updateMessage( $text, $translation, $lang ) {
 726+ $title = Title::newFromText(
 727+ ( $lang == 'en' ) ? "Centralnotice-{$text}" : "Centralnotice-{$text}/{$lang}",
 728+ NS_MEDIAWIKI
 729+ );
 730+ $article = new Article( $title );
 731+ $article->doEdit( $translation, '', EDIT_FORCE_BOT );
 732+ }
 733+
 734+ private function getTemplateId ( $templateName ) {
 735+ $dbr = wfGetDB( DB_SLAVE );
 736+ $res = $dbr->select( 'cn_templates', 'tmp_id',
 737+ array( 'tmp_name' => $templateName ),
 738+ __METHOD__
 739+ );
 740+
 741+ $row = $dbr->fetchObject( $res );
 742+ if ( $row ) {
 743+ return $row->tmp_id;
 744+ }
 745+ return null;
 746+ }
 747+
 748+ private function removeTemplate ( $name ) {
 749+ $id = $this->getTemplateId( $name );
 750+ $dbr = wfGetDB( DB_SLAVE );
 751+ $res = $dbr->select( 'cn_assignments', 'asn_id', array( 'tmp_id' => $id ), __METHOD__ );
 752+
 753+ if ( $dbr->numRows( $res ) > 0 ) {
 754+ $this->showError( 'centralnotice-template-still-bound' );
 755+ return;
 756+ } else {
 757+ $dbw = wfGetDB( DB_MASTER );
 758+ $dbw->begin();
 759+ $dbw->delete( 'cn_templates',
 760+ array( 'tmp_id' => $id ),
 761+ __METHOD__
 762+ );
 763+ $dbw->commit();
 764+
 765+ $article = new Article(
 766+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 767+ );
 768+ $article->doDeleteArticle( 'CentralNotice Automated Removal' );
 769+ }
 770+ }
 771+
 772+ /**
 773+ * Create a new banner
 774+ */
 775+ private function addTemplate( $name, $body, $displayAnon, $displayAccount, $fundraising,
 776+ $landingPages ) {
 777+
 778+ if ( $body == '' || $name == '' ) {
 779+ $this->showError( 'centralnotice-null-string' );
 780+ return;
 781+ }
 782+
 783+ // Format name so there are only letters, numbers, and underscores
 784+ $name = preg_replace( '/[^A-Za-z0-9_]/', '', $name );
 785+
 786+ $dbr = wfGetDB( DB_SLAVE );
 787+ $res = $dbr->select(
 788+ 'cn_templates',
 789+ 'tmp_name',
 790+ array( 'tmp_name' => $name ),
 791+ __METHOD__
 792+ );
 793+
 794+ if ( $dbr->numRows( $res ) > 0 ) {
 795+ $this->showError( 'centralnotice-template-exists' );
 796+ return false;
 797+ } else {
 798+ $dbw = wfGetDB( DB_MASTER );
 799+ $res = $dbw->insert( 'cn_templates',
 800+ array(
 801+ 'tmp_name' => $name,
 802+ 'tmp_display_anon' => $displayAnon,
 803+ 'tmp_display_account' => $displayAccount,
 804+ 'tmp_fundraising' => $fundraising,
 805+ 'tmp_landing_pages' => $landingPages
 806+ ),
 807+ __METHOD__
 808+ );
 809+
 810+ // Perhaps these should move into the db as blobs instead of being stored as articles
 811+ $article = new Article(
 812+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 813+ );
 814+ $article->doEdit( $body, '', EDIT_FORCE_BOT );
 815+ return true;
 816+ }
 817+ }
 818+
 819+ /**
 820+ * Update a banner
 821+ */
 822+ private function editTemplate( $name, $body, $displayAnon, $displayAccount, $fundraising,
 823+ $landingPages ) {
 824+
 825+ if ( $body == '' || $name == '' ) {
 826+ $this->showError( 'centralnotice-null-string' );
 827+ return;
 828+ }
 829+
 830+ $dbr = wfGetDB( DB_SLAVE );
 831+ $res = $dbr->select( 'cn_templates', 'tmp_name',
 832+ array( 'tmp_name' => $name ),
 833+ __METHOD__
 834+ );
 835+
 836+ if ( $dbr->numRows( $res ) == 1 ) {
 837+ $dbw = wfGetDB( DB_MASTER );
 838+ $res = $dbw->update( 'cn_templates',
 839+ array(
 840+ 'tmp_display_anon' => $displayAnon,
 841+ 'tmp_display_account' => $displayAccount,
 842+ 'tmp_fundraising' => $fundraising,
 843+ 'tmp_landing_pages' => $landingPages
 844+ ),
 845+ array( 'tmp_name' => $name )
 846+ );
 847+
 848+ // Perhaps these should move into the db as blob
 849+ $article = new Article(
 850+ Title::newFromText( "centralnotice-template-{$name}", NS_MEDIAWIKI )
 851+ );
 852+ $article->doEdit( $body, '', EDIT_FORCE_BOT );
 853+ return;
 854+ }
 855+ }
 856+
 857+ /**
 858+ * Copy all the data from one banner to another
 859+ */
 860+ public function cloneTemplate( $source, $dest ) {
 861+
 862+ // Reset the timer as updates on meta take a long time
 863+ set_time_limit( 300 );
 864+
 865+ // Pull all possible langs
 866+ $langs = $this->getTranslations( $source );
 867+
 868+ // Normalize name
 869+ $dest = preg_replace( '/[^A-Za-z0-9_]/', '', $dest );
 870+
 871+ // Pull banner settings from database
 872+ $dbr = wfGetDB( DB_SLAVE );
 873+ $row = $dbr->selectRow( 'cn_templates',
 874+ array(
 875+ 'tmp_display_anon',
 876+ 'tmp_display_account',
 877+ 'tmp_fundraising',
 878+ 'tmp_landing_pages'
 879+ ),
 880+ array( 'tmp_name' => $source ),
 881+ __METHOD__
 882+ );
 883+ $displayAnon = $row->tmp_display_anon;
 884+ $displayAccount = $row->tmp_display_account;
 885+ $fundraising = $row->tmp_fundraising;
 886+ $landingPages = $row->tmp_landing_pages;
 887+
 888+ // Pull banner text and respect any inc: markup
 889+ $bodyPage = Title::newFromText( "Centralnotice-template-{$source}", NS_MEDIAWIKI );
 890+ $template_body = Revision::newFromTitle( $bodyPage )->getText();
 891+
 892+ // Create new banner
 893+ if ( $this->addTemplate( $dest, $template_body, $displayAnon, $displayAccount, $fundraising,
 894+ $landingPages ) ) {
 895+
 896+ // Populate the fields
 897+ foreach ( $langs as $lang => $fields ) {
 898+ foreach ( $fields as $field => $text ) {
 899+ $this->updateMessage( "$dest-$field", $text, $lang );
 900+ }
 901+ }
 902+ return $dest;
 903+ }
 904+ }
 905+
 906+ /**
 907+ * Find all message fields set for a banner
 908+ */
 909+ private function findFields( $template ) {
 910+ $body = wfMsg( "Centralnotice-template-{$template}" );
 911+
 912+ // Generate list of message fields from parsing the body
 913+ $fields = array();
 914+ $allowedChars = Title::legalChars();
 915+ preg_match_all( "/\{\{\{([$allowedChars]+)\}\}\}/u", $body, $fields );
 916+
 917+ // Remove duplicates
 918+ $filteredFields = array();
 919+ foreach ( $fields[1] as $field ) {
 920+ $filteredFields[$field] = array_key_exists( $field, $filteredFields )
 921+ ? $filteredFields[$field] + 1
 922+ : 1;
 923+ }
 924+ return $filteredFields;
 925+ }
 926+
 927+ /**
 928+ * Get all the translations of all the messages for a banner
 929+ * @return a 2D array of every set message in every language for one banner
 930+ */
 931+ public function getTranslations( $template ) {
 932+ $translations = array();
 933+
 934+ // Pull all language codes to enumerate
 935+ $allLangs = array_keys( Language::getLanguageNames() );
 936+
 937+ // Lookup all the message fields for a banner
 938+ $fields = $this->findFields( $template );
 939+
 940+ // Iterate through all possible languages to find matches
 941+ foreach ( $allLangs as $lang ) {
 942+ // Iterate through all possible message fields
 943+ foreach ( $fields as $field => $count ) {
 944+ // Put all message fields together for a lookup
 945+ $message = ( $lang == 'en' )
 946+ ? "Centralnotice-{$template}-{$field}"
 947+ : "Centralnotice-{$template}-{$field}/{$lang}";
 948+ if ( Title::newFromText( $message, NS_MEDIAWIKI )->exists() ) {
 949+ $translations[$lang][$field] = wfMsgExt(
 950+ "Centralnotice-{$template}-{$field}",
 951+ array( 'language' => $lang )
 952+ );
 953+ }
 954+ }
 955+ }
 956+ return $translations;
 957+ }
 958+
 959+ function showError( $message ) {
 960+ global $wgOut;
 961+ $wgOut->wrapWikiMsg( "<div class='cn-error'>\n$1\n</div>", $message );
 962+ $this->centralNoticeError = true;
 963+ }
 964+
 965+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialNoticeTemplate.php
___________________________________________________________________
Added: svn:eol-style
1966 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialCentralNoticeLogs.php
@@ -0,0 +1,88 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ echo "CentralNotice extension\n";
 6+ exit( 1 );
 7+}
 8+
 9+class SpecialCentralNoticeLogs extends UnlistedSpecialPage {
 10+ public $logType = 'campaignsettings';
 11+
 12+ function __construct() {
 13+ // Register special page
 14+ parent::__construct( "CentralNoticeLogs" );
 15+ }
 16+
 17+ /**
 18+ * Handle different types of page requests
 19+ */
 20+ function execute( $sub ) {
 21+ global $wgOut, $wgRequest, $wgExtensionAssetsPath;
 22+
 23+ if ( $wgRequest->wasPosted() ) {
 24+ $this->logType = $wgRequest->getText( 'log', 'campaignsettings' );
 25+ }
 26+
 27+ // Begin output
 28+ $this->setHeaders();
 29+
 30+ // Add style file to the output headers
 31+ $wgOut->addExtensionStyle( "$wgExtensionAssetsPath/CentralNotice/centralnotice.css" );
 32+
 33+ // Add script file to the output headers
 34+ $wgOut->addScriptFile( "$wgExtensionAssetsPath/CentralNotice/centralnotice.js" );
 35+
 36+ // Initialize error variable
 37+ $this->centralNoticeError = false;
 38+
 39+ // Show summary
 40+ $wgOut->addWikiMsg( 'centralnotice-summary' );
 41+
 42+ // Show header
 43+ CentralNotice::printHeader();
 44+
 45+ // Begin Banners tab content
 46+ $wgOut->addHTML( Xml::openElement( 'div', array( 'id' => 'preferences' ) ) );
 47+
 48+ $htmlOut = '';
 49+
 50+ // Begin log selection fieldset
 51+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 52+
 53+ $htmlOut .= Xml::openElement( 'form', array( 'method' => 'post' ) );
 54+ $htmlOut .= Xml::element( 'h2', null, wfMsg( 'centralnotice-view-logs' ) );
 55+ $htmlOut .= Xml::closeElement( 'form' );
 56+
 57+ // End log selection fieldset
 58+ $htmlOut .= Xml::closeElement( 'fieldset' );
 59+
 60+ $wgOut->addHTML( $htmlOut );
 61+
 62+ $this->showLog( $this->logType );
 63+
 64+ // End Banners tab content
 65+ $wgOut->addHTML( Xml::closeElement( 'div' ) );
 66+ }
 67+
 68+ /**
 69+ * Show a log.
 70+ */
 71+ function showLog( $logType ) {
 72+ global $wgOut;
 73+
 74+ $htmlOut = '';
 75+
 76+ // Begin log fieldset
 77+ $htmlOut .= Xml::openElement( 'fieldset', array( 'class' => 'prefsection' ) );
 78+
 79+ $htmlOut .= Xml::tags( 'p', null,
 80+ '<i>Coming soon...</i>'
 81+ );
 82+
 83+ // End log fieldset
 84+ $htmlOut .= Xml::closeElement( 'fieldset' );
 85+
 86+ $wgOut->addHTML( $htmlOut );
 87+ }
 88+
 89+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialCentralNoticeLogs.php
___________________________________________________________________
Added: svn:eol-style
190 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialHideBanners.php
@@ -0,0 +1,42 @@
 2+<?php
 3+if ( !defined( 'MEDIAWIKI' ) ) {
 4+ echo "CentralNotice extension\n";
 5+ exit( 1 );
 6+}
 7+
 8+/**
 9+ * Unlisted Special Page which sets a cookie for hiding banners across all languages of a project.
 10+ * This is typically used on donation thank-you pages so that users who have donated will no longer
 11+ * see fundrasing banners.
 12+ */
 13+class SpecialHideBanners extends UnlistedSpecialPage {
 14+ function __construct() {
 15+ parent::__construct( 'HideBanners' );
 16+ }
 17+
 18+ function execute( $par ) {
 19+ global $wgOut;
 20+
 21+ $this->setHideCookie();
 22+
 23+ $wgOut->disable();
 24+ wfResetOutputBuffers();
 25+
 26+ header( 'Content-Type: image/png' );
 27+ header( 'Cache-Control: no-cache' );
 28+
 29+ readfile( dirname( __FILE__ ) . '/1x1.png' );
 30+ }
 31+
 32+ function setHideCookie() {
 33+ global $wgNoticeCookieDomain, $wgCookieSecure;
 34+ $exp = time() + 86400 * 14; // Cookie expires after 2 weeks
 35+ if ( is_callable( array( 'CentralAuthUser', 'getCookieDomain' ) ) ) {
 36+ $cookieDomain = CentralAuthUser::getCookieDomain();
 37+ } else {
 38+ $cookieDomain = $wgNoticeCookieDomain;
 39+ }
 40+ // Hide banners for this domain
 41+ setcookie( 'hidesnmessage', '1', $exp, '/', $cookieDomain, $wgCookieSecure );
 42+ }
 43+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/special/SpecialHideBanners.php
___________________________________________________________________
Added: svn:eol-style
144 + native
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.php
___________________________________________________________________
Modified: svn:mergeinfo
245 Merged /trunk/extensions/CentralNotice/CentralNotice.php:r91112-91117
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/TemplatePager.php
@@ -30,7 +30,8 @@
3131 * Sort the banner list by tmp_id
3232 */
3333 function getIndexField() {
34 - return 'cn_templates.tmp_id';
 34+ $dbr = wfGetDB( DB_SLAVE );
 35+ return $dbr->tableName( 'cn_templates' ) . '.tmp_id';
3536 }
3637
3738 /**
@@ -57,12 +58,17 @@
5859 $render = new SpecialBannerLoader();
5960 $render->siteName = 'Wikipedia';
6061 $render->language = $this->mRequest->getVal( 'wpUserLanguage' );
 62+ try {
 63+ $preview = $render->getHtmlNotice( $row->tmp_name );
 64+ } catch ( SpecialBannerLoaderException $e ) {
 65+ $preview = wfMsg( 'centralnotice-nopreview' );
 66+ }
6167 $htmlOut .= Xml::tags( 'td', array( 'valign' => 'top' ),
6268 $this->getSkin()->makeLinkObj( $this->viewPage,
6369 htmlspecialchars( $row->tmp_name ),
6470 'template=' . urlencode( $row->tmp_name ) ) .
6571 Xml::fieldset( wfMsg( 'centralnotice-preview' ),
66 - $render->getHtmlNotice( $row->tmp_name ),
 72+ $preview,
6773 array( 'class' => 'cn-bannerpreview')
6874 )
6975 );
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/centralnotice.css
@@ -53,6 +53,10 @@
5454 border-style: solid;
5555 border-width: 1px;
5656 }
 57+#preferences div#fundraisingInterface {
 58+ margin-left:1.6em;
 59+ margin-right:1.6em;
 60+}
5761
5862 /* Vector-specific definitions */
5963 body.skin-vector #preferences fieldset.prefsection {
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-template_fundraising.sql
@@ -0,0 +1,6 @@
 2+-- Update to support fundraiser-specific functions for banners
 3+
 4+-- Store a flag indicating whether or not this is a fundraising banner
 5+ALTER TABLE /*$wgDBprefix*/cn_templates ADD `tmp_fundraising` bool NOT NULL DEFAULT 0;
 6+-- Store a list of one or more landing pages
 7+ALTER TABLE /*$wgDBprefix*/cn_templates ADD `tmp_landing_pages` VARCHAR( 255 ) NULL DEFAULT NULL;
\ No newline at end of file
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-template_fundraising.sql
___________________________________________________________________
Added: svn:eol-style
18 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-notice_logs.sql
@@ -0,0 +1,34 @@
 2+-- Update to allow for logging of changes to campaign settings.
 3+
 4+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/cn_notice_log (
 5+ `notlog_id` int unsigned NOT NULL PRIMARY KEY auto_increment,
 6+ `notlog_timestamp` binary(14) NOT NULL,
 7+ `notlog_user_id` int unsigned NOT NULL,
 8+ `notlog_action` enum('created','modified','removed') NOT NULL DEFAULT 'modified',
 9+ `notlog_not_id` int unsigned NOT NULL,
 10+ `notlog_begin_name` varchar(255),
 11+ `notlog_end_name` varchar(255),
 12+ `notlog_begin_projects` varchar(255),
 13+ `notlog_end_projects` varchar(255),
 14+ `notlog_begin_languages` text,
 15+ `notlog_end_languages` text,
 16+ `notlog_begin_countries` text,
 17+ `notlog_end_countries` text,
 18+ `notlog_begin_start` char(14),
 19+ `notlog_end_start` char(14),
 20+ `notlog_begin_end` char(14),
 21+ `notlog_end_end` char(14),
 22+ `notlog_begin_enabled` tinyint(1),
 23+ `notlog_end_enabled` tinyint(1),
 24+ `notlog_begin_preferred` tinyint(1),
 25+ `notlog_end_preferred` tinyint(1),
 26+ `notlog_begin_locked` tinyint(1),
 27+ `notlog_end_locked` tinyint(1),
 28+ `notlog_begin_geo` tinyint(1),
 29+ `notlog_end_geo` tinyint(1),
 30+ `notlog_begin_assignments` text,
 31+ `notlog_end_assignments` text
 32+) /*$wgDBTableOptions*/;
 33+CREATE INDEX /*i*/notlog_timestamp ON /*_*/cn_notice_log (notlog_timestamp);
 34+CREATE INDEX /*i*/notlog_user_id ON /*_*/cn_notice_log (notlog_user_id, notlog_timestamp);
 35+CREATE INDEX /*i*/notlog_not_id ON /*_*/cn_notice_log (notlog_not_id, notlog_timestamp);
\ No newline at end of file
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/patches/patch-notice_logs.sql
___________________________________________________________________
Added: svn:eol-style
136 + native
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.sql
___________________________________________________________________
Modified: svn:mergeinfo
237 Merged /trunk/extensions/CentralNotice/CentralNotice.sql:r91112-91117
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/README
@@ -1,52 +1,53 @@
2 -Proof of concept for the moment fiddling with an alternative sitenotice
3 -loading architecture. At the moment there's no backend logic or caching
4 -logic, I'm just testing the three-level loading.
 2+Wiki page HTML contains an unchanging bit that just sets JS variables
 3+about what site this is, then calls an external <script> to fetch site
 4+notice text. It also includes a facility to fetch a geolocation data.
55
6 -Wiki page HTML contains an unchanging bit that just sets JS variables about
7 -what site this is, then calls an external <script> to fetch site notice text.
 6+That second level is a stable URL which can be heavily cached within
 7+squids *and* cleanly purged on sitewide updates. This script is currently
 8+called Special:BannerController.
89
9 -That second level can be a stable URL which can be heavily cached within squids
10 -*and* cleanly purged on sitewide updates.
 10+BannerController fetches list of notices available by calling out to
 11+a third <script>, this time with the site info (project and language)
 12+and geolocation info in the query string. The third script, called
 13+Special:BannerListLoader provides list of currently available sitenotices
 14+for that match the given site and geolocation profile. It is possible
 15+that a number of notices will be available for the given site and user
 16+parameters.
1117
12 -It itself is small, just calling out to a third <script>, this time with the
13 -site info (project and language) and a cache validation epoch / version marker
14 -in the query string.
 18+The fourth level is the bit that would provide the actual site notice
 19+text, and could be cached arbitrarily long in both squids and final user
 20+agents, since changed versions will get a new URL with a version number
 21+one level up.
1522
16 -The third level is the bit that would provide the actual site notice text, and
17 -could be cached arbitrarily long in both squids and final user agents, since
18 -changed versions will get a new URL with a version number one level up.
19 -
2023 The theory here is that it should interact better with big-site caching.
2124 A user agent's first hit to the wiki will look something like:
2225
2326 * Load wiki page HTML
24 -* Load Special:NoticeLoader JS
25 -* Load Special:NoticeText JS
 27+* Load Special:BannerController JS
 28+* Load Special:BannerListLoader JS
 29+* Load Special:BannerLoader JS
2630
27 -A hit to another page on the same wiki can skip the third hit:
 31+A hit to another page on the same wiki can skip step two and three, but
 32+may need to load notice in step four (if there is more than one available)
2833
2934 * Load new wiki page HTML
30 -* Load unchanged Special:NoticeLoader JS
31 -* skip cached Special:NoticeText JS
 35+* skip cached Special:BannerController JS
 36+* skip cached Special:BannerListLoader JS
 37+* Load Special:BannerLoader JS
3238
33 -Then if the site notice changes, the system only has to purge that constant
34 -Special:NoticeLoader URL from squids, and right away at the next hit the user
35 -agent sees:
 39+Then if the site notice changes, the system only has to purge that
 40+constant Special:BannerListLoader URL from squids, and right away at
 41+the next hit the user agent sees:
3642
3743 * Load new wiki page HTML
38 -* Load new Special:NoticeLoader JS
39 -* Load new Special:NoticeText JS
 44+* skip cached Special:BannerController JS
 45+* Load new Special:BannerListLoader JS
 46+* Load new Special:BannerLoader JS
4047
41 -We could spare hits on the notice loader by letting clients cache it for a
42 -shorter term as well, so a typical second hit looks nicely like:
 48+Caching Special:BannerListLoader for a while could delay visibility of
 49+changed site notices until the allowed age runs out, but if we manage
 50+*scheduled* site notices, we could send cache headers which will run
 51+out at the expected changeover time.
4352
44 -* Load new wiki page HTML
45 -* skip cached Special:NoticeLoader JS
46 -* skip cached Special:NoticeText JS
47 -
48 -This could delay visibility of changed site notices until the allowed age
49 -runs out, but if we manage *scheduled* site notices, we could send cache
50 -headers which will run out at the expected changeover time.
51 -
52 -It might be nice to allow for quick corrections though, so caching for weeks
53 -at a time might not be wise. ;)
 53+It might be nice to allow for quick corrections though, so caching for
 54+weeks at a time might not be wise. ;)
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.i18n.php
@@ -13,6 +13,7 @@
1414 'centralnotice' => 'Central notice admin',
1515 'noticetemplate' => 'Central notice admin',
1616 'bannerallocation' => 'Central notice admin',
 17+ 'centralnoticelogs' => 'Central notice admin',
1718 'right-centralnotice-admin' => 'Manage central notices',
1819 'action-centralnotice-admin' => 'manage central notices',
1920 'centralnotice-desc' => 'Adds a central sitenotice',
@@ -25,6 +26,7 @@
2627 'centralnotice-modify' => 'Submit',
2728 'centralnotice-save-banner' => 'Save banner',
2829 'centralnotice-preview' => 'Preview',
 30+ 'centralnotice-nopreview' => '(Preview not available)',
2931 'centralnotice-add-new' => 'Add a new campaign',
3032 'centralnotice-remove' => 'Remove',
3133 'centralnotice-translate-heading' => 'Translation for $1',
@@ -36,8 +38,8 @@
3739 'centralnotice-add-template' => 'Add a banner',
3840 'centralnotice-show-notices' => 'Show campaigns',
3941 'centralnotice-list-templates' => 'List banners',
40 - 'centralnotice-multiple' => 'Multiple ($1)',
41 - 'centralnotice-all-projects' => 'All projects',
 42+ 'centralnotice-multiple-projects' => 'Multiple ($1)',
 43+ 'centralnotice-multiple-languages' => 'Multiple ($1)', 'centralnotice-all-projects' => 'All projects',
4244 'centralnotice-language-listing' => '$1 - $2',
4345 'centralnotice-translations' => 'Translations',
4446 'centralnotice-translate-to' => 'Translate to',
@@ -126,6 +128,9 @@
127129 'centralnotice-banner-type' => 'Banner type:',
128130 'centralnotice-banner-hidable' => 'Static/Hidable',
129131 'centralnotice-banner-collapsible' => 'Collapsible',
 132+ 'centralnotice-banner-fundraising' => 'This is a fundraising banner',
 133+ 'centralnotice-banner-fundraising-help' => 'Create an anchor tag in the banner body with id="cn_fundraising_link" and enter one or more landing pages below, for example, "JimmyAppeal01". The href of the link will be constructed automatically.',
 134+ 'centralnotice-banner-landing-pages' => 'Landing pages (comma-separated):',
130135 'centralnotice-geotargeted' => 'Geotargeted',
131136 'centralnotice-countries' => 'Countries',
132137 'centralnotice-allocation' => 'Allocation',
@@ -139,9 +144,12 @@
140145 'centralnotice-percentage' => 'Percentage',
141146 'centralnotice-documentwrite-error' => "document.write() cannot be used within a banner.\nSee http://meta.wikimedia.org/wiki/Help:CentralNotice for more information.",
142147 'centralnotice-preferred' => 'Preferred',
 148+ 'centralnotice-logs' => 'Logs',
 149+ 'centralnotice-view-logs' => 'View logs',
143150 );
144151
145152 /** Message documentation (Message documentation)
 153+ * @author Amire80
146154 * @author Bennylin
147155 * @author Darth Kule
148156 * @author EugeneZelenko
@@ -152,12 +160,16 @@
153161 * @author Nike
154162 * @author Purodha
155163 * @author Raymond
 164+ * @author Siebrand
156165 * @author The Evil IP address
157166 */
158167 $messages['qqq'] = array(
159168 'centralnotice' => 'Name of Special:CentralNotice in Special:SpecialPages and title of Special:CentralNotice page',
160169 'noticetemplate' => 'Title of Special:NoticeTemplate page, should be identical to centralnotice message. (Since the extension uses a secondary tab interface, the effective page title is actually centralnotice-manage-templates.)',
161170 'bannerallocation' => 'Title of Special:BannerAllocation page, should be identical to centralnotice message. (Since the extension uses a secondary tab interface, the effective page title is actually centralnotice-view-allocation.)',
 171+ 'centralnoticelogs' => 'Title of Special:CentralNoticeLogs page, should be identical to centralnotice message. (Since the extension uses a secondary tab interface, the effective page title is actually centralnotice-view-logs.)',
 172+ 'right-centralnotice-admin' => '{{doc-right}}',
 173+ 'action-centralnotice-admin' => '{{doc-action}}',
162174 'centralnotice-desc' => '{{desc}}',
163175 'centralnotice-summary' => 'Used in Special:CentralNotice',
164176 'centralnotice-end-date' => '{{Identical|End date}}',
@@ -165,11 +177,13 @@
166178 'centralnotice-modify' => '{{Identical|Submit}}',
167179 'centralnotice-save-banner' => 'Label for the submit button which saves a CentralNotice banner.',
168180 'centralnotice-preview' => '{{Identical|Preview}}',
 181+ 'centralnotice-nopreview' => '{{Identical|Nopreview}}',
169182 'centralnotice-remove' => '{{Identical|Remove}}',
170183 'centralnotice-translate-heading' => 'Fieldset label. $1 is a name of a template.',
171184 'centralnotice-add' => '{{Identical|Add}}',
172 - 'centralnotice-multiple' => '$1 is a number. More precisely, the number of languages a notice is available in. It is always greater than 3.',
 185+ 'centralnotice-multiple-languages' => '$1 is the number of languages in which the notice is available. It is always greater than 3. This message in the column "languages" in the table.',
173186 'centralnotice-language-listing' => 'A language listing for the language multi-select box. First parameter is the language code. Second parameter is the name of the language.',
 187+ 'centralnotice-translations' => '{{Identical|Translation}}',
174188 'centralnotice-translate' => '{{Identical|Translate}}',
175189 'centralnotice-notice-exists' => 'Error message displayed in Special:CentralNotice when trying to add a notice with the same name of another notice',
176190 'centralnotice-template-exists' => 'Error message displayed in Special:NoticeTemplate when trying to add a template with the same name of another template',
@@ -193,15 +207,17 @@
194208 'centralnotice-message' => '{{Identical|Message}}',
195209 'centralnotice-clone-name' => '{{Identical|Name}}',
196210 'centralnotice-insert' => '{{Identical|Insert}}',
 211+ 'centralnotice-hide-button' => 'See also {{msg|Centralnotice-expand-button}}.',
 212+ 'centralnotice-expand-button' => 'See also {{msg|Centralnotice-hide-button}}.',
197213 'centralnotice-geotargeted' => 'Used to label a checkbox which activates geotargeting',
198214 'centralnotice-languages' => '{{Identical|Language}}',
199215 'centralnotice-projects' => '{{Identical|Project}}',
200216 'centralnotice-country' => '{{Identical|Country}}',
201 - 'centralnotice-allocation-description' => 'A description of the environment whose allocation is being described. $1 is the language code for the site (en). $2 is the project name for the site (wikipedia). $3 is the country code (US).',
202 - 'right-centralnotice-admin' => '{{doc-right}}',
203 - 'right-centralnotice-translate' => '{{doc-right}}',
204 - 'action-centralnotice-admin' => '{{doc-action}}',
205 - 'action-centralnotice-translate' => '{{doc-action}}',
 217+ 'centralnotice-allocation-description' => 'A description of the environment the allocation of which is being described.
 218+* $1 is the language code for the site (e.g "en").
 219+* $2 is the project name for the site (e.g. "wikipedia").
 220+* $3 is the country code (e.g. "US").',
 221+ 'centralnotice-logs' => 'Label for tab which displays a log of changes',
206222 );
207223
208224 /** Afrikaans (Afrikaans)
@@ -210,6 +226,8 @@
211227 $messages['af'] = array(
212228 'centralnotice' => 'Bestuur sentrale kennisgewings',
213229 'noticetemplate' => 'Sjabloon vir sentrale kennisgewing',
 230+ 'right-centralnotice-admin' => 'Bestuur sentrale kennisgewings',
 231+ 'action-centralnotice-admin' => 'bestuur sentrale kennisgewings',
214232 'centralnotice-desc' => "Voeg 'n sentrale stelselkennisgewing by",
215233 'centralnotice-query' => 'Verander huidige kennisgewings',
216234 'centralnotice-notice-name' => 'Kennisgewing-naam',
@@ -229,7 +247,8 @@
230248 'centralnotice-add-template' => 'Voeg sjabloon by',
231249 'centralnotice-show-notices' => 'Wys kennisgewings',
232250 'centralnotice-list-templates' => 'Lys sjablone',
233 - 'centralnotice-multiple' => 'verskeie ($1)',
 251+ 'centralnotice-multiple-projects' => 'verskeie ($1)',
 252+ 'centralnotice-multiple-languages' => 'verskeie ($1)',
234253 'centralnotice-translations' => 'Vertalings',
235254 'centralnotice-translate-to' => 'Vertaal na',
236255 'centralnotice-translate' => 'Vertaal',
@@ -322,10 +341,6 @@
323342 'centralnotice-no-allocation' => 'Geen baniere toegeken nie.',
324343 'centralnotice-allocation-description' => 'Baniertoekenning vir $1.$2 in $3:',
325344 'centralnotice-percentage' => 'Persentasie',
326 - 'right-centralnotice-admin' => 'Bestuur sentrale kennisgewings',
327 - 'right-centralnotice-translate' => 'Vertaal sentrale kennisgewings',
328 - 'action-centralnotice-admin' => 'bestuur sentrale kennisgewings',
329 - 'action-centralnotice-translate' => 'vertaal sentrale kennisgewings',
330345 'centralnotice-preferred' => 'Voorkeur',
331346 );
332347
@@ -391,13 +406,17 @@
392407 );
393408
394409 /** Arabic (العربية)
 410+ * @author Aiman titi
395411 * @author Meno25
396412 * @author OsamaK
397413 * @author Ouda
398414 */
399415 $messages['ar'] = array(
400416 'centralnotice' => 'مدير الإخطار المركزي',
401 - 'noticetemplate' => 'قالب الإخطار المركزي',
 417+ 'noticetemplate' => 'إداري الإخطار المركزي',
 418+ 'bannerallocation' => 'أخطار الإداري المركزي',
 419+ 'right-centralnotice-admin' => 'أدر الإخطارات المركزية',
 420+ 'action-centralnotice-admin' => 'التحكم بالإعلانات المركزية',
402421 'centralnotice-desc' => 'يضيف إعلانا مركزيا للموقع',
403422 'centralnotice-summary' => 'هذه الوحدة تسمح لك بتعديل إعدادات الإخطار المركزي الحالية.
404423 يمكن أن تستخدم أيضا لإضافة أو إزالة إخطارات قديمة.',
@@ -405,32 +424,47 @@
406425 'centralnotice-notice-name' => 'اسم الإخطار',
407426 'centralnotice-end-date' => 'تاريخ الانتهاء',
408427 'centralnotice-enabled' => 'مُفعّل',
409 - 'centralnotice-modify' => 'سلّم',
 428+ 'centralnotice-modify' => 'أرسل',
 429+ 'centralnotice-save-banner' => 'حفظ الشعار',
410430 'centralnotice-preview' => 'عاين',
 431+ 'centralnotice-nopreview' => '(المعاينة غير متوفرة)',
411432 'centralnotice-add-new' => 'أضف إخطار جديد مركزي',
412433 'centralnotice-remove' => 'أزل',
413434 'centralnotice-translate-heading' => 'ترجمة $1',
414435 'centralnotice-manage' => 'أدر الإخطار المركزي',
 436+ 'centralnotice-manage-templates' => 'إدارة اللافتات',
415437 'centralnotice-add' => 'أضف',
416438 'centralnotice-add-notice' => 'إضافة إخطار',
 439+ 'centralnotice-edit-notice' => 'تحرير الحملة',
417440 'centralnotice-add-template' => 'إضافة قالب',
418441 'centralnotice-show-notices' => 'إظهار الإخطارات',
419442 'centralnotice-list-templates' => 'اعرض القوالب',
 443+ 'centralnotice-multiple-projects' => 'متعددة ( $1 )',
 444+ 'centralnotice-multiple-languages' => 'متعددة ( $1 )',
 445+ 'centralnotice-all-projects' => 'كل المشاريع',
420446 'centralnotice-translations' => 'الترجمات',
421447 'centralnotice-translate-to' => 'ترجم إلى',
422448 'centralnotice-translate' => 'ترجم',
423449 'centralnotice-english' => 'الإنجليزية',
424 - 'centralnotice-banner-name' => 'اسم القالب',
 450+ 'centralnotice-banner-name' => 'اسم الشعار:',
 451+ 'centralnotice-banner' => 'الشعار',
 452+ 'centralnotice-banner-heading' => 'الشعار:$1',
425453 'centralnotice-templates' => 'القوالب',
426454 'centralnotice-weight' => 'الوزن',
427455 'centralnotice-locked' => 'مغلق',
 456+ 'centralnotice-notice' => 'حملة',
 457+ 'centralnotice-notice-heading' => 'الحملة : $1',
428458 'centralnotice-notices' => 'الإخطارات',
429459 'centralnotice-notice-exists' => 'الإخطار موجود بالفعل.
430460 لا إضافة',
 461+ 'centralnotice-no-language' => 'لم يتم أختيار أي لغة. لايمكن الإضافة.',
 462+ 'centralnotice-no-project' => 'لم يتم أختيار أي لغة. لايمكن الإضافة.',
431463 'centralnotice-template-exists' => 'القالب موجود فعلا
432464 لا تضيفه',
433 - 'centralnotice-notice-doesnt-exist' => 'الملاحظة غير موجودة.
434 -لا شيء للإزالة',
 465+ 'centralnotice-notice-doesnt-exist' => 'الحملة غير موجودة.',
 466+ 'centralnotice-remove-notice-doesnt-exist' => 'حملة غير موجود.
 467+لا شيء يمكن إزالته',
 468+ 'centralnotice-banner-doesnt-exist' => 'الشعار غير موجود',
435469 'centralnotice-template-still-bound' => 'القالب مازال مرتبطا بملاحظة.
436470 لن تتم الإزالة.',
437471 'centralnotice-template-body' => 'جسم القالب:',
@@ -440,9 +474,12 @@
441475 'centralnotice-hours' => 'الساعة',
442476 'centralnotice-min' => 'الدقيقة',
443477 'centralnotice-project-lang' => 'لغة المشروع',
 478+ 'centralnotice-select' => 'حدد : $1',
 479+ 'centralnotice-top-ten-languages' => 'أفضل 10 لغات',
444480 'centralnotice-project-name' => 'اسم المشروع',
445481 'centralnotice-start-date' => 'تاريخ البدء',
446482 'centralnotice-start-time' => 'وقت البداية (UTC)',
 483+ 'centralnotice-end-time' => 'نهاية الوقت (بالتوقيت العالمي)',
447484 'centralnotice-assigned-templates' => 'القوالب المرتبطة',
448485 'centralnotice-no-templates' => 'لا قوالب موجود.
449486 أضف بعضا منها!',
@@ -468,16 +505,46 @@
469506 أضف واحدا أسفله',
470507 'centralnotice-no-templates-translate' => 'لا يوجد أي قالب لتحرير ترجمته',
471508 'centralnotice-number-uses' => 'الاستخدامات',
 509+ 'centralnotice-settings' => 'الإعدادات',
472510 'centralnotice-edit-template' => 'حرّر قالبا',
 511+ 'centralnotice-edit-template-summary' => 'لإنشاء الرسالة القابلة للترجمة، قم بإحاطة سلسلة النص بثلاث من الأقواس المعقوفة، مثل {{{jimbo-الإقتباس}}}.',
473512 'centralnotice-message' => 'الرسالة',
474513 'centralnotice-message-not-set' => 'الرسالة غير مضبوطة',
475514 'centralnotice-clone' => 'استنساخ',
476515 'centralnotice-clone-notice' => 'أنشئ نسخة من القالب',
 516+ 'centralnotice-clone-name' => 'الاسم:',
477517 'centralnotice-preview-all-template-translations' => 'عرض كل الترجمات المتوفرة للقالب',
478 - 'right-centralnotice-admin' => 'أدر الإخطارات المركزية',
479 - 'right-centralnotice-translate' => 'ترجم الإخطارات المركزية',
480 - 'action-centralnotice-admin' => 'التحكم بالإعلانات المركزية',
481 - 'action-centralnotice-translate' => 'ترجمة الإعلانات المركزية',
 518+ 'centralnotice-insert' => 'إدراج : $1',
 519+ 'centralnotice-hide-button' => 'أخفِ الوصلة',
 520+ 'centralnotice-collapse-button' => 'اطوِ الوصلة',
 521+ 'centralnotice-expand-button' => 'وسّع الوصلة',
 522+ 'centralnotice-close-button' => 'زر الإغلاق',
 523+ 'centralnotice-translate-button' => 'المساعدة في ترجمة الارتباط',
 524+ 'centralnotice-donate-button' => 'زر التبرع',
 525+ 'centralnotice-expanded-banner' => 'الشعار الموسع',
 526+ 'centralnotice-collapsed-banner' => 'الشعار مطلوب',
 527+ 'centralnotice-banner-display' => 'عرض:',
 528+ 'centralnotice-banner-anonymous' => 'مستخدمون مجهولون',
 529+ 'centralnotice-banner-logged-in' => 'قائمة المستخدمين الوالجين',
 530+ 'centralnotice-banner-type' => 'نوع الشعار:',
 531+ 'centralnotice-banner-hidable' => 'ثابت/ مخفي',
 532+ 'centralnotice-banner-collapsible' => 'قابلة للطي',
 533+ 'centralnotice-banner-fundraising' => 'هذا هو شعار جمع التبرعات.',
 534+ 'centralnotice-banner-fundraising-help' => 'إنشاء علامة ارتساء في نص الشعار مع معرف = "cn_fundraising_link"، وقم بإدخال واحد أو أكثر الصفحات المقصودة أدناه، على سبيل المثال، "JimmyAppeal01". سيتم تعبيد href الارتباط تلقائياً.',
 535+ 'centralnotice-banner-landing-pages' => 'الصفحات المقصودة (مفصولة بفواصل) :',
 536+ 'centralnotice-geotargeted' => 'الاستهداف الجغرافي',
 537+ 'centralnotice-countries' => 'الدول',
 538+ 'centralnotice-allocation' => 'تخصيص',
 539+ 'centralnotice-view-allocation' => 'موقع عرض الشعار',
 540+ 'centralnotice-allocation-instructions' => 'اختر البيئة قد ترغب في عرض الشعار بها:',
 541+ 'centralnotice-languages' => 'اللغات',
 542+ 'centralnotice-projects' => 'مشاريع',
 543+ 'centralnotice-country' => 'الدولة',
 544+ 'centralnotice-no-allocation' => 'لا يوجد شعارات مخصصة.',
 545+ 'centralnotice-allocation-description' => 'الشعار المخصص ل $1.$2 في $3:',
 546+ 'centralnotice-percentage' => 'نسبة مئوية',
 547+ 'centralnotice-documentwrite-error' => 'لا يمكن إستخدام التعبير document.write() في داخل الشعار.
 548+للحصول على مزيد من المعلومات راجع http://meta.wikimedia.org/wiki/Help:CentralNotice .',
482549 'centralnotice-preferred' => 'مفضل',
483550 );
484551
@@ -518,6 +585,8 @@
519586 $messages['arz'] = array(
520587 'centralnotice' => 'مدير الاعلانات المركزية',
521588 'noticetemplate' => 'قالب الاعلانات المركزية',
 589+ 'right-centralnotice-admin' => 'ادارة الاعلانات المركزيه',
 590+ 'action-centralnotice-admin' => 'ادارة الاعلانات المركزية',
522591 'centralnotice-desc' => 'بيحط اعلان مركزى للموقع',
523592 'centralnotice-summary' => 'الوحدة دى بتسمحلك بتعديل إعدادات الإخطار المركزى الحالية.
524593 ممكن تستخدم كمان لإضافة أو إزالة إخطارات قديمة.',
@@ -594,21 +663,126 @@
595664 'centralnotice-clone' => 'انسخ',
596665 'centralnotice-clone-notice' => 'اعمل نسخة من القالب',
597666 'centralnotice-preview-all-template-translations' => 'اعرض كل الترجمات الموجودة للقالب',
598 - 'right-centralnotice-admin' => 'ادارة الاعلانات المركزيه',
599 - 'right-centralnotice-translate' => 'ترجم الاعلانات المركزية',
600 - 'action-centralnotice-admin' => 'ادارة الاعلانات المركزية',
601 - 'action-centralnotice-translate' => 'ترجمة الاعلانات المركزية',
602667 'centralnotice-preferred' => ' مفضله',
603668 );
604669
605670 /** Asturian (Asturianu)
606671 * @author Esbardu
 672+ * @author Xuacu
607673 */
608674 $messages['ast'] = array(
 675+ 'centralnotice' => "Alministrador d'avisos centralizaos",
 676+ 'noticetemplate' => "Alministrador d'avisos centralizaos",
 677+ 'bannerallocation' => "Alministrador d'avisos centralizaos",
 678+ 'right-centralnotice-admin' => 'Xestionar los avisos centralizaos',
 679+ 'action-centralnotice-admin' => 'xestionar los avisos centralizaos',
609680 'centralnotice-desc' => 'Añade una anuncia centralizada del sitiu (sitenotice)',
 681+ 'centralnotice-summary' => "Esti módulu permite editar la configuración actual d'avisos centralizaos.
 682+Tamién se pue usar p'amestar o desaniciar avisos antiguos.",
 683+ 'centralnotice-query' => 'Camudar les campañes actuales',
 684+ 'centralnotice-notice-name' => 'Nome de la campaña',
 685+ 'centralnotice-end-date' => 'Data final',
 686+ 'centralnotice-enabled' => 'Activada',
 687+ 'centralnotice-modify' => 'Unviar',
 688+ 'centralnotice-save-banner' => 'Guardar cartel',
 689+ 'centralnotice-preview' => 'Entever',
 690+ 'centralnotice-nopreview' => '(Entever nun ta disponible)',
 691+ 'centralnotice-add-new' => 'Amestar una campaña nueva',
 692+ 'centralnotice-remove' => 'Desaniciar',
 693+ 'centralnotice-translate-heading' => 'Traducción pa $1',
 694+ 'centralnotice-manage' => 'Xestionar campañes',
 695+ 'centralnotice-manage-templates' => 'Xestionar los carteles',
 696+ 'centralnotice-add' => 'Amestar',
 697+ 'centralnotice-add-notice' => 'Amestar una campaña',
 698+ 'centralnotice-edit-notice' => 'Editar campaña',
 699+ 'centralnotice-add-template' => 'Amestar un cartel',
 700+ 'centralnotice-show-notices' => 'Amosar les campañes',
 701+ 'centralnotice-list-templates' => 'Llistar cartelos',
 702+ 'centralnotice-multiple-projects' => 'Múltiples ($1)',
 703+ 'centralnotice-multiple-languages' => 'Múltiples ($1)',
 704+ 'centralnotice-all-projects' => 'Tolos proyeutos',
 705+ 'centralnotice-translations' => 'Traducciones',
 706+ 'centralnotice-translate-to' => 'Traducir al',
 707+ 'centralnotice-translate' => 'Traducir',
 708+ 'centralnotice-english' => 'Inglés',
 709+ 'centralnotice-banner-name' => 'Nome del cartel:',
 710+ 'centralnotice-banner' => 'Cartel',
 711+ 'centralnotice-banner-heading' => 'Cartel: $1',
 712+ 'centralnotice-templates' => 'Cartelos',
 713+ 'centralnotice-weight' => 'Pesu',
 714+ 'centralnotice-locked' => 'Candáu',
 715+ 'centralnotice-notice' => 'Campaña',
 716+ 'centralnotice-notice-heading' => 'Campaña: $1',
 717+ 'centralnotice-notices' => 'Campañes',
 718+ 'centralnotice-notice-exists' => "La campaña yá esiste.
 719+Nun s'amiesta.",
 720+ 'centralnotice-day' => 'Día',
 721+ 'centralnotice-year' => 'Añu',
 722+ 'centralnotice-month' => 'Mes',
 723+ 'centralnotice-hours' => 'Hora',
 724+ 'centralnotice-min' => 'Minutu',
 725+ 'centralnotice-project-lang' => 'Llingua del proyeutu',
 726+ 'centralnotice-select' => 'Seleicionar: $1',
 727+ 'centralnotice-top-ten-languages' => 'Les 10 primeres llingües',
 728+ 'centralnotice-project-name' => 'Nome del proyeutu',
 729+ 'centralnotice-start-date' => "Data d'aniciu",
 730+ 'centralnotice-start-time' => "Hora d'aniciu (UTC)",
 731+ 'centralnotice-end-time' => 'Hora final (UTC)',
 732+ 'centralnotice-languages' => 'Llingües',
 733+ 'centralnotice-projects' => 'Proyeutos',
 734+ 'centralnotice-country' => 'País',
610735 );
611736
612 -/** Bashkir (Башҡорт)
 737+/** Azerbaijani (Azərbaycanca)
 738+ * @author Cekli829
 739+ * @author PPerviz
 740+ * @author Vago
 741+ * @author Vugar 1981
 742+ */
 743+$messages['az'] = array(
 744+ 'centralnotice' => 'Mərkəzi xəbərdarlıq idarəçisi',
 745+ 'noticetemplate' => 'Mərkəzi xəbərdarlıq idarəçisi',
 746+ 'bannerallocation' => 'Mərkəzi xəbərdarlıq idarəçisi',
 747+ 'centralnotice-end-date' => 'Son tarix',
 748+ 'centralnotice-enabled' => 'Effektiv',
 749+ 'centralnotice-modify' => 'Yolla',
 750+ 'centralnotice-preview' => 'Sınaq göstərişi',
 751+ 'centralnotice-remove' => 'Çıxar',
 752+ 'centralnotice-add' => 'Əlavə et',
 753+ 'centralnotice-all-projects' => 'Bütün layihələr',
 754+ 'centralnotice-language-listing' => '$1 - $2',
 755+ 'centralnotice-translate' => 'Tərcümə et',
 756+ 'centralnotice-english' => 'İngiliscə',
 757+ 'centralnotice-banner-name' => 'Banner adı:',
 758+ 'centralnotice-banner' => 'Banner',
 759+ 'centralnotice-banner-heading' => 'Banner: $1',
 760+ 'centralnotice-templates' => 'Bannerlər',
 761+ 'centralnotice-weight' => 'Hündürlük',
 762+ 'centralnotice-day' => 'Gün',
 763+ 'centralnotice-year' => 'İl',
 764+ 'centralnotice-month' => 'Ay',
 765+ 'centralnotice-hours' => 'Saat',
 766+ 'centralnotice-min' => 'Dəqiqə',
 767+ 'centralnotice-project-lang' => 'Layihə dili',
 768+ 'centralnotice-select' => 'Seçin: $1',
 769+ 'centralnotice-top-ten-languages' => 'Dillərin Top-10-u',
 770+ 'centralnotice-project-name' => 'Layihə səhifəsi',
 771+ 'centralnotice-start-date' => 'Başlanğıc tarixi',
 772+ 'centralnotice-start-time' => 'Başlanğıc tarixi (UTC)',
 773+ 'centralnotice-end-time' => 'Son tarix (UTC)',
 774+ 'centralnotice-weights' => 'Hündürlük',
 775+ 'centralnotice-number-uses' => 'İstifadəçilər',
 776+ 'centralnotice-message' => 'Məlumat',
 777+ 'centralnotice-clone' => 'Bağla',
 778+ 'centralnotice-clone-name' => 'Ad:',
 779+ 'centralnotice-hide-button' => 'Gizli keçid',
 780+ 'centralnotice-countries' => 'Ölkələr',
 781+ 'centralnotice-languages' => 'Dillər',
 782+ 'centralnotice-projects' => 'Layihələr',
 783+ 'centralnotice-country' => 'Ölkə',
 784+);
 785+
 786+/** Bashkir (Башҡортса)
613787 * @author Assele
614788 * @author Haqmar
615789 */
@@ -628,6 +802,7 @@
629803 'centralnotice-modify' => 'Һаҡларға',
630804 'centralnotice-save-banner' => 'Баннерҙы һаҡларға',
631805 'centralnotice-preview' => 'Алдан байҡау',
 806+ 'centralnotice-nopreview' => '(Ҡарап сығыу мөмкин түгел)',
632807 'centralnotice-add-new' => 'Яңы үҙәктән белдереүҙе өҫтәргә',
633808 'centralnotice-remove' => 'Юйырға',
634809 'centralnotice-translate-heading' => '$1 өсөн тәржемә',
@@ -639,7 +814,8 @@
640815 'centralnotice-add-template' => 'Ҡалып өҫтәргә',
641816 'centralnotice-show-notices' => 'Белдереүҙәрҙе күрһәтергә',
642817 'centralnotice-list-templates' => 'Ҡалыптар исемлеге',
643 - 'centralnotice-multiple' => 'бер нисә ($1)',
 818+ 'centralnotice-multiple-projects' => 'бер нисә ($1)',
 819+ 'centralnotice-multiple-languages' => 'бер нисә ($1)',
644820 'centralnotice-all-projects' => 'Бөтә проекттар',
645821 'centralnotice-translations' => 'Тәржемәләр',
646822 'centralnotice-translate-to' => 'Тәржемә:',
@@ -714,9 +890,9 @@
715891 'centralnotice-clone-name' => 'Исем:',
716892 'centralnotice-preview-all-template-translations' => 'Баннерҙың мөмкин булған бар тәржемәләрен ҡарарға',
717893 'centralnotice-insert' => 'Өҫтәү: $1',
718 - 'centralnotice-hide-button' => 'һылтанманы {{int:centralnotice-shared-hide}}',
719 - 'centralnotice-collapse-button' => 'һылтанманы {{int:centralnotice-shared-collapse}}',
720 - 'centralnotice-expand-button' => 'һылтанманы {{int:centralnotice-shared-expand}}',
 894+ 'centralnotice-hide-button' => 'Һылтанманы йәшерергә',
 895+ 'centralnotice-collapse-button' => 'Һылтанманы төрөргә',
 896+ 'centralnotice-expand-button' => 'Һылтанманы йәйергә',
721897 'centralnotice-close-button' => '«Ябыу» төймәһе',
722898 'centralnotice-translate-button' => 'Тәржемә ярҙамы өсөн һылтанма',
723899 'centralnotice-donate-button' => 'Ярҙам төймәһе',
@@ -786,12 +962,14 @@
787963 * @author Jim-by
788964 * @author Red Winged Duck
789965 * @author Wizardist
 966+ * @author Zedlik
790967 * @author Александр Сигачёв
791968 */
792969 $messages['be-tarask'] = array(
793970 'centralnotice' => 'Кіраваньне цэнтралізаванымі паведамленьнямі',
794971 'noticetemplate' => 'Кіраваньне цэнтралізаванымі паведамленьнямі',
795972 'bannerallocation' => 'Кіраваньне цэнтралізаванымі паведамленьнямі',
 973+ 'centralnoticelogs' => 'Кіраваньне цэнтралізаванымі паведамленьнямі',
796974 'right-centralnotice-admin' => 'Кіраваньне цэнтральнымі паведамленьнямі',
797975 'action-centralnotice-admin' => 'кіраваньне цэнтралізаванымі паведамленьнямі',
798976 'centralnotice-desc' => 'Дадае цэнтралізаванае паведамленьне сайту',
@@ -804,6 +982,7 @@
805983 'centralnotice-modify' => 'Захаваць',
806984 'centralnotice-save-banner' => 'Захаваць банэр',
807985 'centralnotice-preview' => 'Папярэдні прагляд',
 986+ 'centralnotice-nopreview' => '(Прагляд недаступны)',
808987 'centralnotice-add-new' => 'Дадаць новую кампанію',
809988 'centralnotice-remove' => 'Выдаліць',
810989 'centralnotice-translate-heading' => 'Пераклад для $1',
@@ -815,7 +994,8 @@
816995 'centralnotice-add-template' => 'Дадаць паведамленьне',
817996 'centralnotice-show-notices' => 'Паказаць кампаніі',
818997 'centralnotice-list-templates' => 'Сьпіс паведамленьняў',
819 - 'centralnotice-multiple' => 'некалькі ($1)',
 998+ 'centralnotice-multiple-projects' => 'некалькі ($1)',
 999+ 'centralnotice-multiple-languages' => 'некалькі ($1)',
8201000 'centralnotice-all-projects' => 'Усе праекты',
8211001 'centralnotice-translations' => 'Пераклады',
8221002 'centralnotice-translate-to' => 'Пераклад на',
@@ -880,7 +1060,7 @@
8811061 Дадайце адну ніжэй.',
8821062 'centralnotice-no-templates-translate' => 'Няма паведамленьняў для рэдагаваньня перакладаў',
8831063 'centralnotice-number-uses' => 'Выкарыстоўвае',
884 - 'centralnotice-settings' => 'Устаноўкі',
 1064+ 'centralnotice-settings' => 'Налады',
8851065 'centralnotice-edit-template' => 'Рэдагаваць паведамленьне',
8861066 'centralnotice-edit-template-summary' => 'Каб стварыць лякалізуемае паведамленьне, атачыце дэфісны радок у тры фігурныя дужкі, напрыклад, {{{цытата-джымба}}}.',
8871067 'centralnotice-message' => 'Паведамленьне',
@@ -904,6 +1084,9 @@
9051085 'centralnotice-banner-type' => 'Тып банэра:',
9061086 'centralnotice-banner-hidable' => 'Фіксаваны / Хаваемы',
9071087 'centralnotice-banner-collapsible' => 'Згортваемы',
 1088+ 'centralnotice-banner-fundraising' => 'Гэта банэр для збору ахвяраваньняў',
 1089+ 'centralnotice-banner-fundraising-help' => 'Стварыце тэг спасылкі ў зьмесьце банэра з id="cn_fundraising_link" і пазначце адну ці некалькі мэтавых старонак, напрыклад, «JimmyAppeal01». Атрыбут href будзе створаны аўтаматычна.',
 1090+ 'centralnotice-banner-landing-pages' => 'Мэтавыя старонкі (праз коску):',
9081091 'centralnotice-geotargeted' => 'Геаграфічная прывязка',
9091092 'centralnotice-countries' => 'Краіны',
9101093 'centralnotice-allocation' => 'Прызначэньне',
@@ -918,17 +1101,21 @@
9191102 'centralnotice-documentwrite-error' => 'document.write() не магчыма выкарыстоўваць у банэре.
9201103 Падрабязнасьці глядзіце на http://meta.wikimedia.org/wiki/Help:CentralNotice.',
9211104 'centralnotice-preferred' => 'Пажадана',
 1105+ 'centralnotice-logs' => 'Журналы падзеяў',
 1106+ 'centralnotice-view-logs' => 'Паказаць журнал падзеяў',
9221107 );
9231108
9241109 /** Bulgarian (Български)
9251110 * @author Borislav
9261111 * @author DCLXVI
9271112 * @author Spiritia
 1113+ * @author Stanqo
9281114 * @author Turin
9291115 */
9301116 $messages['bg'] = array(
9311117 'centralnotice' => 'Администратор на централизираните съобщения',
9321118 'noticetemplate' => 'Шаблон за централизирани съобщения',
 1119+ 'right-centralnotice-admin' => 'Управление на централизираните съобщения',
9331120 'centralnotice-desc' => 'Добавя главнa сайтова бележка',
9341121 'centralnotice-summary' => 'Този интерфейс позволява да редактирате текущо съществуващите централизирани съобщения.
9351122 Той може да се използва и за прибавяне на нови и премахване на стари съобщения.',
@@ -942,6 +1129,7 @@
9431130 'centralnotice-remove' => 'Премахване',
9441131 'centralnotice-translate-heading' => 'Превод за $1',
9451132 'centralnotice-manage' => 'Управление на централизираното съобщение',
 1133+ 'centralnotice-manage-templates' => 'Управление на банерите',
9461134 'centralnotice-add' => 'Добавяне',
9471135 'centralnotice-add-notice' => 'Добавяне на съобщение',
9481136 'centralnotice-add-template' => 'Добавяне на шаблон',
@@ -952,7 +1140,7 @@
9531141 'centralnotice-translate-to' => 'Превеждане на',
9541142 'centralnotice-translate' => 'Превеждане',
9551143 'centralnotice-english' => 'Английски',
956 - 'centralnotice-banner-name' => 'Име на шаблона',
 1144+ 'centralnotice-banner-name' => 'Име на банера:',
9571145 'centralnotice-banner' => 'Банер',
9581146 'centralnotice-banner-heading' => 'Банер: $1',
9591147 'centralnotice-templates' => 'Шаблони',
@@ -967,6 +1155,7 @@
9681156 'centralnotice-hours' => 'Час',
9691157 'centralnotice-min' => 'Минута',
9701158 'centralnotice-project-lang' => 'Език на проекта',
 1159+ 'centralnotice-select' => 'Избиране: $1',
9711160 'centralnotice-top-ten-languages' => 'Топ 10 езика',
9721161 'centralnotice-project-name' => 'Име на проекта',
9731162 'centralnotice-start-date' => 'Начална дата',
@@ -982,11 +1171,15 @@
9831172 'centralnotice-clone-notice' => 'Създаване на копие на шаблона',
9841173 'centralnotice-clone-name' => 'Име:',
9851174 'centralnotice-preview-all-template-translations' => 'Преглед на всички налични преводи на шаблона',
 1175+ 'centralnotice-banner-display' => 'Показване на:',
 1176+ 'centralnotice-banner-anonymous' => 'Анонимни потребители',
 1177+ 'centralnotice-banner-logged-in' => 'Регистрирани потребители',
 1178+ 'centralnotice-countries' => 'Страни',
 1179+ 'centralnotice-allocation' => 'Разпределение',
9861180 'centralnotice-languages' => 'Езици',
9871181 'centralnotice-projects' => 'Проекти',
 1182+ 'centralnotice-country' => 'Страна',
9881183 'centralnotice-percentage' => 'Процент',
989 - 'right-centralnotice-admin' => 'Управление на централизираните съобщения',
990 - 'right-centralnotice-translate' => 'Превод на централизираните съобщения',
9911184 'centralnotice-preferred' => 'Предпочитано',
9921185 );
9931186
@@ -999,10 +1192,13 @@
10001193
10011194 /** Bengali (বাংলা)
10021195 * @author Bellayet
 1196+ * @author Wikitanvir
10031197 */
10041198 $messages['bn'] = array(
10051199 'centralnotice' => 'কেন্দ্রীয় নোটিশ প্রশাসক',
10061200 'noticetemplate' => 'কেন্দ্রীয় নোটিশ প্রশাসক',
 1201+ 'right-centralnotice-admin' => 'কেন্দ্রীয় নোটিশ ব্যবস্থাপনা',
 1202+ 'action-centralnotice-admin' => 'কেন্দ্রীয় নোটিশ ব্যবস্থাপনা করুন',
10071203 'centralnotice-desc' => 'একটি কেন্দ্রীয় সাইটনোটিশ যোগ করো',
10081204 'centralnotice-summary' => 'এই মডিউলটি বর্তমান সেটআপ করা সাইট নোটিশ সম্পাদনা করার সুযোগ দিবে।
10091205 পুরাতন নোটিশ যোগ বা অপসারণের কাজেও এটি ব্যবহার করা যাবে।',
@@ -1088,21 +1284,26 @@
10891285 'centralnotice-clone-name' => 'নাম:',
10901286 'centralnotice-preview-all-template-translations' => 'টেম্পলেটের বিদ্যমান সকল অনুবাদের প্রাকদর্শন দেখাও',
10911287 'centralnotice-insert' => 'যোগ: $1',
 1288+ 'centralnotice-hide-button' => 'সংযোগ লুকাও',
 1289+ 'centralnotice-collapse-button' => 'ভাঁজকৃত সংযোগ',
 1290+ 'centralnotice-expand-button' => 'সংযোগ বর্ধিতকরণ',
10921291 'centralnotice-close-button' => 'বন্ধ বোতাম',
 1292+ 'centralnotice-translate-button' => 'সংযোগ অনুবাদে সাহায্য করুন',
10931293 'centralnotice-donate-button' => 'দান বোতাম',
10941294 'centralnotice-expanded-banner' => 'সম্প্রসারিত ব্যানার',
10951295 'centralnotice-collapsed-banner' => 'ভাঁজ করা ব্যানার',
 1296+ 'centralnotice-banner-display' => 'যেখানে প্রদর্শিত হবে:',
10961297 'centralnotice-banner-anonymous' => 'বেনামী ব্যবহারকারী',
 1298+ 'centralnotice-banner-logged-in' => 'প্রবেশকৃত ব্যবহারকারীসমূহ',
 1299+ 'centralnotice-banner-type' => 'ব্যানারের ধরন:',
 1300+ 'centralnotice-banner-hidable' => 'স্ট্যাটিক/লুকানোযোগ্য',
10971301 'centralnotice-banner-collapsible' => 'ভাঁজযোগ্য',
 1302+ 'centralnotice-geotargeted' => 'স্থানাংকলক্ষ্য',
10981303 'centralnotice-countries' => 'দেশ',
10991304 'centralnotice-languages' => 'ভাষা',
11001305 'centralnotice-projects' => 'প্রকল্প',
11011306 'centralnotice-country' => 'দেশ',
11021307 'centralnotice-percentage' => 'শতাংশ',
1103 - 'right-centralnotice-admin' => 'কেন্দ্রীয় নোটিশ ব্যবস্থাপনা',
1104 - 'right-centralnotice-translate' => 'কেন্দ্রীয় নোটিশ অনুবাদ করুন',
1105 - 'action-centralnotice-admin' => 'কেন্দ্রীয় নোটিশ ব্যবস্থাপনা করুন',
1106 - 'action-centralnotice-translate' => 'কেন্দ্রীয় নোটিশ অনুবাদ করুন',
11071308 'centralnotice-preferred' => 'পছন্দনীয়',
11081309 );
11091310
@@ -1133,6 +1334,7 @@
11341335 'centralnotice' => 'Melestradurezh an alioù kreiz',
11351336 'noticetemplate' => 'Melestradurezh an alioù kreiz',
11361337 'bannerallocation' => 'Melestradurezh an alioù kreiz',
 1338+ 'centralnoticelogs' => 'Merour an alioù kreiz',
11371339 'right-centralnotice-admin' => 'Merañ an alioù kreiz',
11381340 'action-centralnotice-admin' => 'merañ an alioù kreiz',
11391341 'centralnotice-desc' => "Ouzhpennañ a ra ur c'hemenn kreiz e laez ar pajennoù (sitenotice).",
@@ -1145,6 +1347,7 @@
11461348 'centralnotice-modify' => 'Kas',
11471349 'centralnotice-save-banner' => 'Enrollañ ar giton',
11481350 'centralnotice-preview' => 'Rakwelet',
 1351+ 'centralnotice-nopreview' => '(Dibosupl rakwelet)',
11491352 'centralnotice-add-new' => 'Ouzhpennañ un ali kreiz nevez',
11501353 'centralnotice-remove' => 'Dilemel',
11511354 'centralnotice-translate-heading' => 'Troidigezh eus $1',
@@ -1156,7 +1359,8 @@
11571360 'centralnotice-add-template' => 'Ouzhpennañ ur patrom',
11581361 'centralnotice-show-notices' => 'Diskouez ar menegoù',
11591362 'centralnotice-list-templates' => 'Rollañ ar patromoù',
1160 - 'centralnotice-multiple' => 'lies ($1)',
 1363+ 'centralnotice-multiple-projects' => 'lies ($1)',
 1364+ 'centralnotice-multiple-languages' => 'lies ($1)',
11611365 'centralnotice-all-projects' => 'An holl raktresoù',
11621366 'centralnotice-translations' => 'Troidigezhioù',
11631367 'centralnotice-translate-to' => 'Treiñ e',
@@ -1207,16 +1411,16 @@
12081412 'centralnotice-preview-template' => 'Rakwelet ar patrom',
12091413 'centralnotice-change-lang' => 'Cheñch yezh an droidigezh',
12101414 'centralnotice-weights' => 'Pouezioù',
1211 - 'centralnotice-notice-is-locked' => "Prenet eo an ali.
1212 -N'eo ket bet dilammet.",
 1415+ 'centralnotice-notice-is-locked' => "Prennet eo an ali.
 1416+N'eo ket bet diverket.",
12131417 'centralnotice-overlap' => "Goleiñ a ra ar c'hemenn ur c'hemenn all, evit darn pe da vat.
1214 -N'eo ket bet ouhzpennet",
 1418+N'eo ket bet ouzhpennet",
12151419 'centralnotice-invalid-date-range' => "Frapad deiziadoù direizh.
12161420 N'eo ket bet hizivaet",
12171421 'centralnotice-null-string' => "Ne c'haller ket ouzhpennañ un neudennad c'houllo.
12181422 N'eo ket bet ouzhpennet",
1219 - 'centralnotice-confirm-delete' => "Ha sur oc'h ho peus c'hoant dilemmel an elfenn-mañ ?
1220 -Ne vo ket tu adtapout anezhi.",
 1423+ 'centralnotice-confirm-delete' => "Ha sur oc'h da gaout c'hoant da ziverkañ an elfenn-mañ ?
 1424+Ne vo ket tu da zizober an traoù.",
12211425 'centralnotice-no-notices-exist' => "N'eus ali ebet.
12221426 Ouzhpennit unan da heul.",
12231427 'centralnotice-no-templates-translate' => "N'eus patrom ebet da dreiñ",
@@ -1245,6 +1449,9 @@
12461450 'centralnotice-banner-type' => 'Doare banniel :',
12471451 'centralnotice-banner-hidable' => 'Statek/Masklus',
12481452 'centralnotice-banner-collapsible' => 'Digreskus',
 1453+ 'centralnotice-banner-fundraising' => "Ur giton dastum arc'hant eo hemañ",
 1454+ 'centralnotice-banner-fundraising-help' => 'Krouiñ ur valizenn eoriañ e-korf ar giton gant id = "cn_fundraising_link" ha merkit ur bajenn dal pe meur a hini a-is, da skouer, "JimmyAppeal01". Savet e vo href al liamm ent emgefre.',
 1455+ 'centralnotice-banner-landing-pages' => 'Pajennoù pal (dispartiet dre skejoù) :',
12491456 'centralnotice-geotargeted' => "Geolec'hiet",
12501457 'centralnotice-countries' => 'Broioù',
12511458 'centralnotice-allocation' => 'Skorenn',
@@ -1259,6 +1466,8 @@
12601467 'centralnotice-documentwrite-error' => "N'hall ket document.write() bezañ implijet hep giton.
12611468 Sellet ouzh http://meta.wikimedia.org/wiki/Help:CentralNotice evit gouzout hiroc'h.",
12621469 'centralnotice-preferred' => "Kavet gwelloc'h",
 1470+ 'centralnotice-logs' => 'Marilhoù',
 1471+ 'centralnotice-view-logs' => 'Gwelet ar marilhoù',
12631472 );
12641473
12651474 /** Bosnian (Bosanski)
@@ -1268,6 +1477,7 @@
12691478 'centralnotice' => 'Uređivanje središnjeg obavještenja',
12701479 'noticetemplate' => 'Uređivanje središnjeg obavještenja',
12711480 'bannerallocation' => 'Uređivanje središnjeg obavještenja',
 1481+ 'centralnoticelogs' => 'Administrator središnjeg obavještenja',
12721482 'right-centralnotice-admin' => 'Uređivanje središnjeg obavještenja',
12731483 'action-centralnotice-admin' => 'uređujete središnje obavještenje',
12741484 'centralnotice-desc' => 'Dodaje središnju obavijest na stranici',
@@ -1280,6 +1490,7 @@
12811491 'centralnotice-modify' => 'Pošalji',
12821492 'centralnotice-save-banner' => 'Spremi obavještenje',
12831493 'centralnotice-preview' => 'Izgled',
 1494+ 'centralnotice-nopreview' => '(Pregled nije dostupan)',
12841495 'centralnotice-add-new' => 'Dodavanje novog središnjeg obavještenja',
12851496 'centralnotice-remove' => 'Ukloni',
12861497 'centralnotice-translate-heading' => 'Prijevod za $1',
@@ -1291,7 +1502,8 @@
12921503 'centralnotice-add-template' => 'Dodaj šablon',
12931504 'centralnotice-show-notices' => 'Prikaži obavještenja',
12941505 'centralnotice-list-templates' => 'Spisak šablona',
1295 - 'centralnotice-multiple' => 'više ($1)',
 1506+ 'centralnotice-multiple-projects' => 'više ($1)',
 1507+ 'centralnotice-multiple-languages' => 'više ($1)',
12961508 'centralnotice-all-projects' => 'Svi projekti',
12971509 'centralnotice-translations' => 'Prijevodi',
12981510 'centralnotice-translate-to' => 'Prevedi na',
@@ -1380,6 +1592,9 @@
13811593 'centralnotice-banner-type' => 'Tip banera:',
13821594 'centralnotice-banner-hidable' => 'Statično/Dinamično',
13831595 'centralnotice-banner-collapsible' => 'Moguće sakriti',
 1596+ 'centralnotice-banner-fundraising' => 'Ovo je plakat za donacije',
 1597+ 'centralnotice-banner-fundraising-help' => 'Pravi oznaku za uklapanje u tijelo banera sa id="cn_fundraising_link" i unosi jedan ili više ciljnih članaka ispod, naprimjer, "JimmyAppeal01". Oznaka href za link će biti automatski napravljen.',
 1598+ 'centralnotice-banner-landing-pages' => 'Ciljne stranice (razdvojene zarezima):',
13841599 'centralnotice-geotargeted' => 'Geociljano',
13851600 'centralnotice-countries' => 'Države',
13861601 'centralnotice-allocation' => 'Raspoređivanje',
@@ -1394,6 +1609,8 @@
13951610 'centralnotice-documentwrite-error' => 'document.write() se ne može koristiti unutar obavještenja.
13961611 Pogledajte http://meta.wikimedia.org/wiki/Help:CentralNotice za više informacija.',
13971612 'centralnotice-preferred' => 'Preferirano',
 1613+ 'centralnotice-logs' => 'Zapisnici',
 1614+ 'centralnotice-view-logs' => 'Pogledaj zapisnike',
13981615 );
13991616
14001617 /** Catalan (Català)
@@ -1410,7 +1627,7 @@
14111628 'centralnotice' => "Administrador d'avisos centrals",
14121629 'noticetemplate' => "Administració d'avisos centrals",
14131630 'bannerallocation' => "Administració d'avisos centrals",
1414 - 'right-centralnotice-admin' => 'Gestionau els avisos centrals',
 1631+ 'right-centralnotice-admin' => 'Gestionar els avisos centrals',
14151632 'action-centralnotice-admin' => 'Gestionau els avisos centrals',
14161633 'centralnotice-desc' => "Afegeix un lloc central d'avisos",
14171634 'centralnotice-summary' => "Aquesta extensió us permet editar el vostre lloc central d'avisos.
@@ -1422,6 +1639,7 @@
14231640 'centralnotice-modify' => 'Tramet',
14241641 'centralnotice-save-banner' => 'Salva pancarta',
14251642 'centralnotice-preview' => 'Previsualitza',
 1643+ 'centralnotice-nopreview' => '(Vista prèvia no disponible)',
14261644 'centralnotice-add-new' => "Afegeix una nova central d'avisos",
14271645 'centralnotice-remove' => 'Elimina',
14281646 'centralnotice-translate-heading' => 'Traducció de $1',
@@ -1433,7 +1651,8 @@
14341652 'centralnotice-add-template' => 'Afegeix una plantilla',
14351653 'centralnotice-show-notices' => 'Mostra avisos',
14361654 'centralnotice-list-templates' => 'Llista les plantilles',
1437 - 'centralnotice-multiple' => 'Múltiple ($1)',
 1655+ 'centralnotice-multiple-projects' => 'Múltiple ($1)',
 1656+ 'centralnotice-multiple-languages' => 'Múltiple ($1)',
14381657 'centralnotice-all-projects' => 'Tots els projectes',
14391658 'centralnotice-translations' => 'Traduccions',
14401659 'centralnotice-translate-to' => 'Tradueix a',
@@ -1499,6 +1718,7 @@
15001719 'centralnotice-number-uses' => 'Usos',
15011720 'centralnotice-settings' => 'Configuració',
15021721 'centralnotice-edit-template' => 'Modifica la plantilla',
 1722+ 'centralnotice-edit-template-summary' => 'Per a crear missatges traduïbles, envolteu en tres claus una cadena de text amb un guionet, per exemple: {{{citacions-jimbo}}}.',
15031723 'centralnotice-message' => 'Missatge',
15041724 'centralnotice-message-not-set' => 'Missatge no fixat',
15051725 'centralnotice-clone' => 'Duplica',
@@ -1506,9 +1726,9 @@
15071727 'centralnotice-clone-name' => 'Nom:',
15081728 'centralnotice-preview-all-template-translations' => 'Previsualitza totes les traduccions disponibles de plantilles',
15091729 'centralnotice-insert' => 'Inserir: $1',
1510 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} enllaç',
1511 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}} enllaç',
1512 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} enllaç',
 1730+ 'centralnotice-hide-button' => 'Amaga enllaç',
 1731+ 'centralnotice-collapse-button' => 'plega enllaç',
 1732+ 'centralnotice-expand-button' => 'Amplia enllaç',
15131733 'centralnotice-close-button' => 'Botó tancar',
15141734 'centralnotice-translate-button' => "Ajudar a traduir l'enllaç",
15151735 'centralnotice-donate-button' => 'Botó donar',
@@ -1551,9 +1771,24 @@
15521772 'centralnotice-year' => 'Шо',
15531773 );
15541774
1555 -/** Sorani (کوردی) */
 1775+/** Sorani (کوردی)
 1776+ * @author Asoxor
 1777+ */
15561778 $messages['ckb'] = array(
15571779 'centralnotice-modify' => 'ناردن',
 1780+ 'centralnotice-english' => 'ئینگلیزی',
 1781+ 'centralnotice-day' => 'ڕۆژ',
 1782+ 'centralnotice-year' => 'ساڵ',
 1783+ 'centralnotice-month' => 'مانگ',
 1784+ 'centralnotice-hours' => 'کاتژمێر',
 1785+ 'centralnotice-min' => 'خولەک',
 1786+ 'centralnotice-project-lang' => 'زمانی پرۆژە',
 1787+ 'centralnotice-start-date' => 'ڕێکەوتی دەستپێکردن',
 1788+ 'centralnotice-start-time' => 'کاتی دەستپێکردن (UTC)',
 1789+ 'centralnotice-end-time' => 'کاتی کۆتایی (UTC)',
 1790+ 'centralnotice-languages' => 'زمانەکان',
 1791+ 'centralnotice-projects' => 'پرۆژەکان',
 1792+ 'centralnotice-country' => 'وڵات',
15581793 );
15591794
15601795 /** Czech (Česky)
@@ -1566,6 +1801,7 @@
15671802 'centralnotice' => 'Správa centralizovaných oznámení',
15681803 'noticetemplate' => 'Správa centralizovaných oznámení',
15691804 'bannerallocation' => 'Správa centralizovaných oznámení',
 1805+ 'centralnoticelogs' => 'Správa centralizovaných oznámení',
15701806 'right-centralnotice-admin' => 'Správa centralizovaných oznámení',
15711807 'action-centralnotice-admin' => 'spravovat centralizovaná oznámení',
15721808 'centralnotice-desc' => 'Přidává centrální zprávu do záhlaví',
@@ -1578,6 +1814,7 @@
15791815 'centralnotice-modify' => 'Odeslat',
15801816 'centralnotice-save-banner' => 'Uložit banner',
15811817 'centralnotice-preview' => 'Náhled',
 1818+ 'centralnotice-nopreview' => '(Náhled není dostupný)',
15821819 'centralnotice-add-new' => 'Přidat nové centrální oznámení',
15831820 'centralnotice-remove' => 'Odstranit',
15841821 'centralnotice-translate-heading' => 'Překlad šablony „$1“',
@@ -1589,7 +1826,8 @@
15901827 'centralnotice-add-template' => 'Přidat šablonu',
15911828 'centralnotice-show-notices' => 'Zobrazit oznámení',
15921829 'centralnotice-list-templates' => 'Seznam šablon',
1593 - 'centralnotice-multiple' => 'více ($1)',
 1830+ 'centralnotice-multiple-projects' => 'více ($1)',
 1831+ 'centralnotice-multiple-languages' => 'více ($1)',
15941832 'centralnotice-all-projects' => 'Všechny projekty',
15951833 'centralnotice-translations' => 'Překlady',
15961834 'centralnotice-translate-to' => 'Přeložit do jazyka',
@@ -1655,9 +1893,9 @@
16561894 'centralnotice-clone-name' => 'Název:',
16571895 'centralnotice-preview-all-template-translations' => 'Náhled všech dostupných překladů šablony',
16581896 'centralnotice-insert' => 'Vložit: $1',
1659 - 'centralnotice-hide-button' => 'Skrýt odkaz',
1660 - 'centralnotice-collapse-button' => 'Sbalit odkaz',
1661 - 'centralnotice-expand-button' => 'Rozbalit odkaz',
 1897+ 'centralnotice-hide-button' => 'Odkaz pro skrytí',
 1898+ 'centralnotice-collapse-button' => 'Odkaz pro sbalení',
 1899+ 'centralnotice-expand-button' => 'Odkaz pro rozbalení',
16621900 'centralnotice-close-button' => 'Zavírací tlačítko',
16631901 'centralnotice-translate-button' => 'Odkaz „Pomozte s překladem“',
16641902 'centralnotice-donate-button' => 'Tlačítko „Přispějte“',
@@ -1669,6 +1907,9 @@
16701908 'centralnotice-banner-type' => 'Typ banneru:',
16711909 'centralnotice-banner-hidable' => 'Statický/skrývatelný',
16721910 'centralnotice-banner-collapsible' => 'Sbalitelný',
 1911+ 'centralnotice-banner-fundraising' => 'Tohle je banner pro fundraising',
 1912+ 'centralnotice-banner-fundraising-help' => 'V těle banneru vytvořte odkaz s id="cn_fundraising_link" a níže zadejte jednu nebo více cílových stránek, například „JimmyAppeal01“. U odkazu se href vyplní automaticky.',
 1913+ 'centralnotice-banner-landing-pages' => 'Cílové stránky (oddělené čárkou):',
16731914 'centralnotice-geotargeted' => 'Zeměpisně cílené',
16741915 'centralnotice-countries' => 'Země',
16751916 'centralnotice-allocation' => 'Přidělení',
@@ -1683,6 +1924,8 @@
16841925 'centralnotice-documentwrite-error' => 'V banneru nelze používat document.write().
16851926 Další informace naleznete na stránce http://meta.wikimedia.org/wiki/Help:CentralNotice.',
16861927 'centralnotice-preferred' => 'Preferováno',
 1928+ 'centralnotice-logs' => 'Protokolovací záznamy',
 1929+ 'centralnotice-view-logs' => 'Zobrazit protokolovací záznamy',
16871930 );
16881931
16891932 /** Welsh (Cymraeg)
@@ -1692,6 +1935,9 @@
16931936 $messages['cy'] = array(
16941937 'centralnotice' => "Gweinyddu'r hysbysiad canolog",
16951938 'noticetemplate' => "Gweinyddu'r hysbysiad canolog",
 1939+ 'bannerallocation' => "Gweinyddu'r hysbysiad canolog",
 1940+ 'right-centralnotice-admin' => 'Gweinyddu hysbysiadau canolog',
 1941+ 'action-centralnotice-admin' => 'gweinyddu hysbysiadau canolog',
16961942 'centralnotice-desc' => 'Yn ychwanegu hysbysiad canolog',
16971943 'centralnotice-summary' => "Mae'r teclyn hwn yn eich galluogi i olygu'r hysbysiadau canolog sydd wedi eu gosod ar hyn o bryd.
16981944 Gall hefyd gael ei ddefnyddio i ychwanegu hen hysbysiadau neu eu tynnu i ffwrdd.",
@@ -1772,18 +2018,20 @@
17732019 'centralnotice-view-allocation' => 'Gweld dosbarthiad y faner',
17742020 'centralnotice-languages' => 'Ieithoedd',
17752021 'centralnotice-country' => 'Gwlad',
1776 - 'right-centralnotice-admin' => 'Gweinyddu hysbysiadau canolog',
1777 - 'right-centralnotice-translate' => 'Cyfieithu hysbysiadau canolog',
1778 - 'action-centralnotice-admin' => 'gweinyddu hysbysiadau canolog',
1779 - 'action-centralnotice-translate' => 'cyfieithu hysbysiadau canolog',
 2022+ 'centralnotice-percentage' => 'Canran',
 2023+ 'centralnotice-preferred' => 'Gorau gennych',
17802024 );
17812025
17822026 /** Danish (Dansk)
17832027 * @author Byrial
17842028 * @author Masz
 2029+ * @author Peter Alberti
17852030 * @author Sarrus
17862031 */
17872032 $messages['da'] = array(
 2033+ 'right-centralnotice-admin' => 'Administrere centrale meddelelser',
 2034+ 'action-centralnotice-admin' => 'administrere centrale beskeder',
 2035+ 'centralnotice-desc' => 'Tilføjer en central sitenotice',
17882036 'centralnotice-query' => 'Ændr nuværende kampagner',
17892037 'centralnotice-notice-name' => 'Kampagnenavn',
17902038 'centralnotice-end-date' => 'Slutdato',
@@ -1791,6 +2039,7 @@
17922040 'centralnotice-modify' => 'Send',
17932041 'centralnotice-save-banner' => 'Gem banner',
17942042 'centralnotice-preview' => 'Forhåndsvisning',
 2043+ 'centralnotice-nopreview' => '(Forhåndsvisning ikke mulig)',
17952044 'centralnotice-add-new' => 'Tilføj en ny kampagne',
17962045 'centralnotice-remove' => 'Fjern',
17972046 'centralnotice-translate-heading' => 'Oversættelse for $1',
@@ -1802,7 +2051,8 @@
18032052 'centralnotice-add-template' => 'Tilføj et banner',
18042053 'centralnotice-show-notices' => 'Vis kampagner',
18052054 'centralnotice-list-templates' => 'Vis bannere',
1806 - 'centralnotice-multiple' => 'Flere ($1)',
 2055+ 'centralnotice-multiple-projects' => 'Flere ($1)',
 2056+ 'centralnotice-multiple-languages' => 'Flere ($1)',
18072057 'centralnotice-all-projects' => 'Alle projekter',
18082058 'centralnotice-translations' => 'Oversættelser',
18092059 'centralnotice-translate-to' => 'Oversæt til',
@@ -1847,9 +2097,18 @@
18482098 'centralnotice-no-templates-assigned' => 'Ingen bannere tildelt kampagne.
18492099 Tilføj nogle!',
18502100 'centralnotice-available-templates' => 'Tilgængelige bannere',
1851 - 'right-centralnotice-admin' => 'Administrere centrale meddelelser',
1852 - 'action-centralnotice-admin' => 'administrere centrale beskeder',
1853 - 'action-centralnotice-translate' => 'oversætte centrale beskeder',
 2101+ 'centralnotice-preview-template' => 'Forhåndsvis banner',
 2102+ 'centralnotice-weights' => 'Vægte',
 2103+ 'centralnotice-number-uses' => 'Bruger',
 2104+ 'centralnotice-clone-name' => 'Navn:',
 2105+ 'centralnotice-insert' => 'Indsæt: $1',
 2106+ 'centralnotice-banner-anonymous' => 'Anonyme brugere',
 2107+ 'centralnotice-banner-type' => 'Bannertype:',
 2108+ 'centralnotice-countries' => 'Lande',
 2109+ 'centralnotice-languages' => 'Sprog',
 2110+ 'centralnotice-country' => 'Land',
 2111+ 'centralnotice-percentage' => 'Procentdel',
 2112+ 'centralnotice-preferred' => 'Foretrukket',
18542113 );
18552114
18562115 /** German (Deutsch)
@@ -1865,6 +2124,7 @@
18662125 'centralnotice' => 'Verwaltung zentraler Meldungen',
18672126 'noticetemplate' => 'Verwaltung zentraler Meldungen',
18682127 'bannerallocation' => 'Verwaltung zentraler Meldungen',
 2128+ 'centralnoticelogs' => 'Verwaltung zentraler Meldungen',
18692129 'right-centralnotice-admin' => 'Zentrale Meldungen verwalten',
18702130 'action-centralnotice-admin' => 'zentrale Meldungen verwalten',
18712131 'centralnotice-desc' => 'Ermöglicht es, zentrale Meldungen für das Wiki zu erstellen',
@@ -1877,6 +2137,7 @@
18782138 'centralnotice-modify' => 'Speichern',
18792139 'centralnotice-save-banner' => 'Vorlage speichern',
18802140 'centralnotice-preview' => 'Vorschau',
 2141+ 'centralnotice-nopreview' => '(Vorschau nicht verfügbar)',
18812142 'centralnotice-add-new' => 'Füge eine neue zentrale Meldung hinzu',
18822143 'centralnotice-remove' => 'Entfernen',
18832144 'centralnotice-translate-heading' => 'Übersetzung von „$1“',
@@ -1888,7 +2149,8 @@
18892150 'centralnotice-add-template' => 'Hinzufügen einer Vorlage',
18902151 'centralnotice-show-notices' => 'Zeige Meldungen',
18912152 'centralnotice-list-templates' => 'Vorlagen auflisten',
1892 - 'centralnotice-multiple' => 'mehrere ($1)',
 2153+ 'centralnotice-multiple-projects' => 'mehrere ($1)',
 2154+ 'centralnotice-multiple-languages' => 'mehrere ($1)',
18932155 'centralnotice-all-projects' => 'Alle Projekte',
18942156 'centralnotice-translations' => 'Übersetzungen',
18952157 'centralnotice-translate-to' => 'Übersetzen in',
@@ -1977,23 +2239,28 @@
19782240 'centralnotice-banner-type' => 'Bannertyp:',
19792241 'centralnotice-banner-hidable' => 'Statisch/Ausblendbar',
19802242 'centralnotice-banner-collapsible' => 'Einklappbar',
 2243+ 'centralnotice-banner-fundraising' => 'Dies ist ein Fundraisingbanner',
 2244+ 'centralnotice-banner-fundraising-help' => 'Ein Ankerelement im Korpus des Banners mit id="cn_fundraising_link" erstellen sowie eine oder mehrere Zielseiten, wie bspw. "JimmysAufruf01". Das href-Attribut des Links wird automatisch erstellt.',
 2245+ 'centralnotice-banner-landing-pages' => 'Zielseiten (durch Kommata getrennt):',
19812246 'centralnotice-geotargeted' => 'Geo-anvisiert',
1982 - 'centralnotice-countries' => 'Länder',
 2247+ 'centralnotice-countries' => 'Staaten',
19832248 'centralnotice-allocation' => 'Anordnung',
19842249 'centralnotice-view-allocation' => 'Anordnung der Vorlagen ansehen',
19852250 'centralnotice-allocation-instructions' => 'Die Ausgabeumgebung für die Ansicht der Vorlagenanordnung auswählen:',
19862251 'centralnotice-languages' => 'Sprachen',
19872252 'centralnotice-projects' => 'Projekte',
1988 - 'centralnotice-country' => 'Land',
 2253+ 'centralnotice-country' => 'Staat',
19892254 'centralnotice-no-allocation' => 'Es wurden keine Vorlagen angeordnet.',
19902255 'centralnotice-allocation-description' => 'Vorlagenanordnung für $1.$2 in $3:',
19912256 'centralnotice-percentage' => 'Prozentsatz',
19922257 'centralnotice-documentwrite-error' => 'document.write() kann nicht innerhalb eines Banners verwendet werden.
19932258 Siehe http://meta.wikimedia.org/wiki/Help:CentralNotice für mehr Informationen.',
19942259 'centralnotice-preferred' => 'Bevorzugt',
 2260+ 'centralnotice-logs' => 'Logbücher',
 2261+ 'centralnotice-view-logs' => 'Logbücher ansehen',
19952262 );
19962263
1997 -/** German (formal address) (Deutsch (Sie-Form))
 2264+/** German (formal address) (‪Deutsch (Sie-Form)‬)
19982265 * @author Imre
19992266 * @author Kghbln
20002267 */
@@ -2009,6 +2276,8 @@
20102277 $messages['diq'] = array(
20112278 'centralnotice' => 'Noticeyê adminê merkezî',
20122279 'noticetemplate' => 'Templatê adminê merkezî',
 2280+ 'right-centralnotice-admin' => 'Îkazanê merkezî îdare bike',
 2281+ 'action-centralnotice-admin' => 'îkazanê merkezî îdare bike',
20132282 'centralnotice-desc' => 'Yew sitenoticeyê merkezî de keno',
20142283 'centralnotice-summary' => 'Ena panel ti ra yardim keno ke ti eşkeno îkazanê merkezî bivurne.
20152284 Ena panel eyni zeman de eşkeno îkazanê kihanî de biko ya zi wedaro.',
@@ -2086,10 +2355,6 @@
20872356 'centralnotice-clone' => 'Kopye bike',
20882357 'centralnotice-clone-notice' => 'Ye kopyayê templateyî viraze',
20892358 'centralnotice-preview-all-template-translations' => 'Çarnayîşê template yê hemî bivîne',
2090 - 'right-centralnotice-admin' => 'Îkazanê merkezî îdare bike',
2091 - 'right-centralnotice-translate' => 'Çarnayîşê merkezî îdare bike',
2092 - 'action-centralnotice-admin' => 'îkazanê merkezî îdare bike',
2093 - 'action-centralnotice-translate' => 'çarnayîşê merkezî îdare bike',
20942359 'centralnotice-preferred' => 'Tercih biyo',
20952360 );
20962361
@@ -2123,7 +2388,8 @@
21242389 'centralnotice-add-template' => 'Pśedłogu pśidaś',
21252390 'centralnotice-show-notices' => 'Powěźeńki pokazaś',
21262391 'centralnotice-list-templates' => 'Pśedłogi nalistowaś',
2127 - 'centralnotice-multiple' => 'někotare ($1)',
 2392+ 'centralnotice-multiple-projects' => 'někotare ($1)',
 2393+ 'centralnotice-multiple-languages' => 'někotare ($1)',
21282394 'centralnotice-all-projects' => 'Wše projekty',
21292395 'centralnotice-translations' => 'Pśełožki',
21302396 'centralnotice-translate-to' => 'Pśełoźiś do',
@@ -2261,6 +2527,7 @@
22622528 'centralnotice-modify' => 'Καταχώρηση',
22632529 'centralnotice-save-banner' => 'Αποθήκευση banner',
22642530 'centralnotice-preview' => 'Προεπισκόπηση',
 2531+ 'centralnotice-nopreview' => '(Μη διαθέσιμη προεπισκόπηση)',
22652532 'centralnotice-add-new' => 'Προσθήκη νέας κεντρικής ανακοίνωσης',
22662533 'centralnotice-remove' => 'Αφαίρεση',
22672534 'centralnotice-translate-heading' => 'Μετάφραση για το $1',
@@ -2272,7 +2539,8 @@
22732540 'centralnotice-add-template' => 'Προσθήκη προτύπου',
22742541 'centralnotice-show-notices' => 'Εμφάνιση ανακοινώσεων',
22752542 'centralnotice-list-templates' => 'Κατάλογος προτύπων',
2276 - 'centralnotice-multiple' => 'Πολλαπλές ($1)',
 2543+ 'centralnotice-multiple-projects' => 'Πολλαπλές ($1)',
 2544+ 'centralnotice-multiple-languages' => 'Πολλαπλές ($1)',
22772545 'centralnotice-all-projects' => 'Όλα τα εγχειρήματα',
22782546 'centralnotice-translations' => 'Μεταφράσεις',
22792547 'centralnotice-translate-to' => 'Μετάφραση σε',
@@ -2347,9 +2615,9 @@
23482616 'centralnotice-clone-name' => 'Όνομα:',
23492617 'centralnotice-preview-all-template-translations' => 'Προεπισκόπηση όλων των διαθέσιμων μεταφράσεων του προτύπου',
23502618 'centralnotice-insert' => 'Εισαγωγή: $1',
2351 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} σύνδεσμος',
2352 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}} σύνδεσμος',
2353 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} σύνδεσμος',
 2619+ 'centralnotice-hide-button' => 'Απόκρυψη συνδέσμου',
 2620+ 'centralnotice-collapse-button' => 'Σύμπτυξη συνδέσμου',
 2621+ 'centralnotice-expand-button' => 'Επεκτείνετε τον σύνδεσμο',
23542622 'centralnotice-close-button' => 'Κουμπί κλεισίματος',
23552623 'centralnotice-translate-button' => 'Σύνδεσμος για βοήθεια στην μετάφραση',
23562624 'centralnotice-donate-button' => 'Κουμπί δωρεάς',
@@ -2398,6 +2666,7 @@
23992667 'centralnotice-modify' => 'Enigi',
24002668 'centralnotice-save-banner' => 'Konservi rubandon',
24012669 'centralnotice-preview' => 'Antaŭrigardo',
 2670+ 'centralnotice-nopreview' => '(Antaŭvido ne montrebla)',
24022671 'centralnotice-add-new' => 'Aldoni novan centralan noticon',
24032672 'centralnotice-remove' => 'Forigi',
24042673 'centralnotice-translate-heading' => 'Traduko por $1',
@@ -2409,7 +2678,8 @@
24102679 'centralnotice-add-template' => 'Aldoni ŝablonon',
24112680 'centralnotice-show-notices' => 'Montri noticojn',
24122681 'centralnotice-list-templates' => 'Rigardi ŝablonojn',
2413 - 'centralnotice-multiple' => 'multlingve ($1)',
 2682+ 'centralnotice-multiple-projects' => 'multlingve ($1)',
 2683+ 'centralnotice-multiple-languages' => 'multlingve ($1)',
24142684 'centralnotice-all-projects' => 'Ĉiuj projektoj',
24152685 'centralnotice-translations' => 'Tradukoj',
24162686 'centralnotice-translate-to' => 'Traduki al',
@@ -2518,6 +2788,7 @@
25192789 * @author Crazymadlover
25202790 * @author Danke7
25212791 * @author Dferg
 2792+ * @author Fitoschido
25222793 * @author Imre
25232794 * @author Locos epraix
25242795 * @author McDutchie
@@ -2543,6 +2814,7 @@
25442815 'centralnotice-modify' => 'Enviar',
25452816 'centralnotice-save-banner' => 'Grabar banner',
25462817 'centralnotice-preview' => 'Previsualizar',
 2818+ 'centralnotice-nopreview' => '(Previsualización no disponible)',
25472819 'centralnotice-add-new' => 'Añadir un nuevo aviso central',
25482820 'centralnotice-remove' => 'Quitar',
25492821 'centralnotice-translate-heading' => 'Traducción para $1',
@@ -2554,7 +2826,8 @@
25552827 'centralnotice-add-template' => 'Añadir una plantilla',
25562828 'centralnotice-show-notices' => 'Mostrar avisos',
25572829 'centralnotice-list-templates' => 'Listar plantillas',
2558 - 'centralnotice-multiple' => 'múltiples ($1)',
 2830+ 'centralnotice-multiple-projects' => 'múltiples ($1)',
 2831+ 'centralnotice-multiple-languages' => 'múltiples ($1)',
25592832 'centralnotice-all-projects' => 'Todos los proyectos',
25602833 'centralnotice-translations' => 'Traducciones',
25612834 'centralnotice-translate-to' => 'Traducir al',
@@ -2643,6 +2916,7 @@
26442917 'centralnotice-banner-type' => 'Tipo de banner:',
26452918 'centralnotice-banner-hidable' => 'Estático/Ocultable',
26462919 'centralnotice-banner-collapsible' => 'Colapsable',
 2920+ 'centralnotice-banner-fundraising' => 'Esto es un anuncio de la campaña de recaudación de fondos',
26472921 'centralnotice-geotargeted' => 'Geosegmentado',
26482922 'centralnotice-countries' => 'Países',
26492923 'centralnotice-allocation' => 'Asignación',
@@ -2667,6 +2941,8 @@
26682942 'centralnotice' => 'Keskuse teadete haldamine',
26692943 'noticetemplate' => 'Keskuse teadete haldamine',
26702944 'bannerallocation' => 'Keskuse teadete haldamine',
 2945+ 'right-centralnotice-admin' => 'Keskuse teateid hallata',
 2946+ 'action-centralnotice-admin' => 'keskuse teateid hallata',
26712947 'centralnotice-desc' => 'Lisab keskse võrgukohateatesüsteemi.',
26722948 'centralnotice-summary' => 'See komponent võimaldab muuta praegu üles seatud keskuse teateid.
26732949 Samuti saab sellega teateid lisada või vanu teateid eemaldada.',
@@ -2685,7 +2961,8 @@
26862962 'centralnotice-add-template' => 'Lisa mall',
26872963 'centralnotice-show-notices' => 'Näita teateid',
26882964 'centralnotice-list-templates' => 'Mallide list',
2689 - 'centralnotice-multiple' => 'Mitmed ($1)',
 2965+ 'centralnotice-multiple-projects' => 'Mitmed ($1)',
 2966+ 'centralnotice-multiple-languages' => 'Mitmed ($1)',
26902967 'centralnotice-all-projects' => 'Kõik projektid',
26912968 'centralnotice-translations' => 'Tõlked',
26922969 'centralnotice-translate-to' => 'Tõlgi',
@@ -2773,10 +3050,6 @@
27743051 'centralnotice-no-allocation' => 'Ühtegi malli pole üles seatud.',
27753052 'centralnotice-allocation-description' => 'Üles seatud mallid maal koodiga $3 ja saidil $1.$2.',
27763053 'centralnotice-percentage' => 'Protsent',
2777 - 'right-centralnotice-admin' => 'Keskuse teateid hallata',
2778 - 'right-centralnotice-translate' => 'Tõlkida keskuse teateid',
2779 - 'action-centralnotice-admin' => 'keskuse teateid hallata',
2780 - 'action-centralnotice-translate' => 'keskuse teateid tõlkida',
27813054 'centralnotice-preferred' => 'Eelistatud',
27823055 );
27833056
@@ -2867,6 +3140,7 @@
28683141 'centralnotice-modify' => 'ارسال',
28693142 'centralnotice-save-banner' => 'پرچم ذخیره',
28703143 'centralnotice-preview' => 'پیش‌نمایش',
 3144+ 'centralnotice-nopreview' => '(پیش‌نمایش در دسترس نیست)',
28713145 'centralnotice-add-new' => 'افزودن یک اعلان متمرکز جدید',
28723146 'centralnotice-remove' => 'حذف',
28733147 'centralnotice-translate-heading' => 'ترجمه از $1',
@@ -2878,7 +3152,8 @@
28793153 'centralnotice-add-template' => 'اضافه کردن الگو',
28803154 'centralnotice-show-notices' => 'نمایش اعلان‌ها',
28813155 'centralnotice-list-templates' => 'فهرست الگوها',
2882 - 'centralnotice-multiple' => 'چندگانه ($1)',
 3156+ 'centralnotice-multiple-projects' => 'چندگانه ($1)',
 3157+ 'centralnotice-multiple-languages' => 'چندگانه ($1)',
28833158 'centralnotice-all-projects' => 'همهٔ پروژه‌ها',
28843159 'centralnotice-translations' => 'ترجمه‌ها',
28853160 'centralnotice-translate-to' => 'ترجمه به',
@@ -2978,8 +3253,8 @@
29793254 'centralnotice-no-allocation' => 'هیچ آگهی‌ای اختصاص نیافته است.',
29803255 'centralnotice-allocation-description' => 'اختصاص آگهی برای $1.$2 در $3:',
29813256 'centralnotice-percentage' => 'درصد',
2982 - 'centralnotice-documentwrite-error' => 'دستور document.write() نمی‌تواند درون یک آگهی استفاده شود.
2983 -برای اطلاعات بیشتر ttp://meta.wikimedia.org/wiki/Help:CentralNotice را ببینید.',
 3257+ 'centralnotice-documentwrite-error' => 'دستور document.write()&lrm; نمی‌تواند درون یک آگهی استفاده شود.
 3258+برای اطلاعات بیشتر http://meta.wikimedia.org/wiki/Help:CentralNotice را ببینید.',
29843259 'centralnotice-preferred' => 'ترجیح داده شده',
29853260 );
29863261
@@ -3019,7 +3294,8 @@
30203295 'centralnotice-add-template' => 'Lisää malline',
30213296 'centralnotice-show-notices' => 'Näytä tiedotteet',
30223297 'centralnotice-list-templates' => 'Luettele mallineet',
3023 - 'centralnotice-multiple' => 'useita ($1)',
 3298+ 'centralnotice-multiple-projects' => 'useita ($1)',
 3299+ 'centralnotice-multiple-languages' => 'useita ($1)',
30243300 'centralnotice-all-projects' => 'Kaikki projektit',
30253301 'centralnotice-translations' => 'Käännökset',
30263302 'centralnotice-translate-to' => 'Käännös:',
@@ -3094,9 +3370,9 @@
30953371 'centralnotice-clone-name' => 'Nimi:',
30963372 'centralnotice-preview-all-template-translations' => 'Esikatsele kaikkia saatavilla olevia mallineen käännöksiä',
30973373 'centralnotice-insert' => 'Lisää: $1',
3098 - 'centralnotice-hide-button' => 'Linkki {{int:centralnotice-shared-hide}}',
 3374+ 'centralnotice-hide-button' => 'Piilota linkki',
30993375 'centralnotice-collapse-button' => 'Linkki {{int:centralnotice-shared-collapse}}',
3100 - 'centralnotice-expand-button' => 'Linkki {{int:centralnotice-shared-expand}}',
 3376+ 'centralnotice-expand-button' => 'Laajenna linkki',
31013377 'centralnotice-close-button' => 'Sulje-painike',
31023378 'centralnotice-translate-button' => 'Auta kääntämisessä -linkki',
31033379 'centralnotice-donate-button' => 'Lahjoituspainike',
@@ -3141,6 +3417,7 @@
31423418 'centralnotice' => 'Administration des avis centraux',
31433419 'noticetemplate' => 'Administration des avis centraux',
31443420 'bannerallocation' => 'Administration des avis centraux',
 3421+ 'centralnoticelogs' => 'Administrateur des avis centraux',
31453422 'right-centralnotice-admin' => 'Gérer les avis centraux',
31463423 'action-centralnotice-admin' => 'gérer les avis centraux',
31473424 'centralnotice-desc' => 'Ajoute un avis central du site',
@@ -3153,6 +3430,7 @@
31543431 'centralnotice-modify' => 'Soumettre',
31553432 'centralnotice-save-banner' => 'Enregistrer la bannière',
31563433 'centralnotice-preview' => 'Prévisualiser',
 3434+ 'centralnotice-nopreview' => '(Prévisualisation non disponible)',
31573435 'centralnotice-add-new' => 'Ajouter un nouvel avis central',
31583436 'centralnotice-remove' => 'Enlever',
31593437 'centralnotice-translate-heading' => 'Traduction de l’avis « $1 »',
@@ -3164,7 +3442,8 @@
31653443 'centralnotice-add-template' => 'Ajouter un modèle',
31663444 'centralnotice-show-notices' => 'Afficher les avis',
31673445 'centralnotice-list-templates' => 'Lister les modèles',
3168 - 'centralnotice-multiple' => 'multiple ($1)',
 3446+ 'centralnotice-multiple-projects' => 'multiple ($1)',
 3447+ 'centralnotice-multiple-languages' => 'multiple ($1)',
31693448 'centralnotice-all-projects' => 'Tous les projets',
31703449 'centralnotice-translations' => 'Traductions',
31713450 'centralnotice-translate-to' => 'Traduire en',
@@ -3253,6 +3532,9 @@
32543533 'centralnotice-banner-type' => 'Type de bannière :',
32553534 'centralnotice-banner-hidable' => 'Statique/masquable',
32563535 'centralnotice-banner-collapsible' => 'Réductible',
 3536+ 'centralnotice-banner-fundraising' => "Il s'agit d'une bannière de levée de fonds",
 3537+ 'centralnotice-banner-fundraising-help' => 'Créer une balise d\'ancrage dans le corps de la bannière avec id = "cn_fundraising_link" et entrez un ou plusieurs pages de destination ci-dessous, par exemple, "JimmyAppeal01". Le href du lien sera construit automatiquement.',
 3538+ 'centralnotice-banner-landing-pages' => 'Pages de destination (séparées par des virgules):',
32573539 'centralnotice-geotargeted' => 'Géolocalisé',
32583540 'centralnotice-countries' => 'Pays',
32593541 'centralnotice-allocation' => 'Allocation',
@@ -3267,6 +3549,8 @@
32683550 'centralnotice-documentwrite-error' => 'document.write() ne peut pas être utilisé dans une bannière.
32693551 Veuillez consulter http://meta.wikimedia.org/wiki/Help:CentralNotice pour plus d’informations.',
32703552 'centralnotice-preferred' => 'Préféré',
 3553+ 'centralnotice-logs' => 'Journaux',
 3554+ 'centralnotice-view-logs' => 'Voir les journaux',
32713555 );
32723556
32733557 /** Franco-Provençal (Arpetan)
@@ -3288,6 +3572,7 @@
32893573 'centralnotice-modify' => 'Sometre',
32903574 'centralnotice-save-banner' => 'Encartar la baniére',
32913575 'centralnotice-preview' => 'Prèvisualisacion',
 3576+ 'centralnotice-nopreview' => '(Prèvisualisacion pas disponibla)',
32923577 'centralnotice-add-new' => 'Apondre una propaganda novèla',
32933578 'centralnotice-remove' => 'Enlevar',
32943579 'centralnotice-translate-heading' => 'Traduccion de « $1 »',
@@ -3299,7 +3584,9 @@
33003585 'centralnotice-add-template' => 'Apondre una baniére',
33013586 'centralnotice-show-notices' => 'Fâre vêre les propagandes',
33023587 'centralnotice-list-templates' => 'Listar les baniéres',
3303 - 'centralnotice-multiple' => 'un mouél ($1)',
 3588+ 'centralnotice-multiple-projects' => 'un mouél ($1)',
 3589+ 'centralnotice-multiple-languages' => 'un mouél ($1)',
 3590+ 'centralnotice-all-projects' => 'Tôs los projèts',
33043591 'centralnotice-translations' => 'Traduccions',
33053592 'centralnotice-translate-to' => 'Traduire en',
33063593 'centralnotice-translate' => 'Traduire',
@@ -3316,6 +3603,7 @@
33173604 'centralnotice-notice-exists' => 'La propaganda ègziste ja.
33183605 El at pas étâ apondua.',
33193606 'centralnotice-no-language' => 'Niona lengoua at étâ chouèsia por la propaganda. El at pas étâ apondua.',
 3607+ 'centralnotice-no-project' => 'Nion projèt at étâ chouèsi por la propaganda. Il at pas étâ apondu.',
33203608 'centralnotice-template-exists' => 'La baniére ègziste ja.
33213609 El at pas étâ apondua.',
33223610 'centralnotice-notice-doesnt-exist' => 'La propaganda ègziste pas.',
@@ -3372,9 +3660,9 @@
33733661 'centralnotice-clone-name' => 'Nom :',
33743662 'centralnotice-preview-all-template-translations' => 'Prèvisualisar totes les traduccions disponibles de la baniére',
33753663 'centralnotice-insert' => 'Entrebetar : $1',
3376 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} lo lim',
3377 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}} lo lim',
3378 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} lo lim',
 3664+ 'centralnotice-hide-button' => 'Cachiér lo lim',
 3665+ 'centralnotice-collapse-button' => 'Recllôre lo lim',
 3666+ 'centralnotice-expand-button' => 'Dèvelopar lo lim',
33793667 'centralnotice-close-button' => 'Boton cllôre',
33803668 'centralnotice-translate-button' => 'Lim d’éde a la traduccion',
33813669 'centralnotice-donate-button' => 'Boton de donacion',
@@ -3391,6 +3679,8 @@
33923680 'centralnotice-allocation' => 'Alocacion',
33933681 'centralnotice-view-allocation' => 'Vêre l’alocacion de baniére',
33943682 'centralnotice-allocation-instructions' => 'Chouèsésséd l’enveronance por laquinta vos souhètâd fâre vêre l’alocacion de baniére :',
 3683+ 'centralnotice-languages' => 'Lengoues',
 3684+ 'centralnotice-projects' => 'Projèts',
33953685 'centralnotice-country' => 'Payis',
33963686 'centralnotice-no-allocation' => 'Gins de baniére balyê.',
33973687 'centralnotice-allocation-description' => 'Alocacion de baniére por $1.$2 en $3 :',
@@ -3412,6 +3702,7 @@
34133703 'centralnotice' => 'Administración do aviso central',
34143704 'noticetemplate' => 'Administración do aviso central',
34153705 'bannerallocation' => 'Administración do aviso central',
 3706+ 'centralnoticelogs' => 'Administración do aviso central',
34163707 'right-centralnotice-admin' => 'Xestionar os avisos centrais',
34173708 'action-centralnotice-admin' => 'xestionar os avisos centrais',
34183709 'centralnotice-desc' => 'Engade un aviso central',
@@ -3419,11 +3710,12 @@
34203711 Tamén pode ser usado para engadir ou eliminar avisos vellos.',
34213712 'centralnotice-query' => 'Modificar os avisos actuais',
34223713 'centralnotice-notice-name' => 'Nome do aviso',
3423 - 'centralnotice-end-date' => 'Data da fin',
 3714+ 'centralnotice-end-date' => 'Data de fin',
34243715 'centralnotice-enabled' => 'Permitido',
34253716 'centralnotice-modify' => 'Enviar',
34263717 'centralnotice-save-banner' => 'Gardar o cartel',
34273718 'centralnotice-preview' => 'Vista previa',
 3719+ 'centralnotice-nopreview' => '(A vista previa non está dispoñíbel)',
34283720 'centralnotice-add-new' => 'Engadir un novo aviso central',
34293721 'centralnotice-remove' => 'Eliminar',
34303722 'centralnotice-translate-heading' => 'Traducións de "$1"',
@@ -3435,7 +3727,8 @@
34363728 'centralnotice-add-template' => 'Engadir un modelo',
34373729 'centralnotice-show-notices' => 'Amosar os avisos',
34383730 'centralnotice-list-templates' => 'Listar os modelos',
3439 - 'centralnotice-multiple' => 'Múltiples ($1)',
 3731+ 'centralnotice-multiple-projects' => 'Múltiples ($1)',
 3732+ 'centralnotice-multiple-languages' => 'Múltiples ($1)',
34403733 'centralnotice-all-projects' => 'Todos os proxectos',
34413734 'centralnotice-translations' => 'Traducións',
34423735 'centralnotice-translate-to' => 'Traducir ao',
@@ -3524,6 +3817,9 @@
35253818 'centralnotice-banner-type' => 'Tipo de cartel:',
35263819 'centralnotice-banner-hidable' => 'Estático/Agochable',
35273820 'centralnotice-banner-collapsible' => 'Contraíble',
 3821+ 'centralnotice-banner-fundraising' => 'Este é un cartel da recadación de fondos',
 3822+ 'centralnotice-banner-fundraising-help' => 'Cree unha etiqueta de largo no corpo do cartel con id="cn_fundraising_link" e insira a continuación unha ou máis páxina de destino; por exemplo, "JimmyAppeal01". O parámetro href da ligazón construirase automaticamente.',
 3823+ 'centralnotice-banner-landing-pages' => 'Páxinas de destino (separadas por comas):',
35283824 'centralnotice-geotargeted' => 'Localizado xeograficamente',
35293825 'centralnotice-countries' => 'Países',
35303826 'centralnotice-allocation' => 'Asignación',
@@ -3538,6 +3834,8 @@
35393835 'centralnotice-documentwrite-error' => 'document.write() non se pode empregar nos carteis.
35403836 Olle http://meta.wikimedia.org/wiki/Help:CentralNotice para obter máis información.',
35413837 'centralnotice-preferred' => 'Preferido',
 3838+ 'centralnotice-logs' => 'Rexistros',
 3839+ 'centralnotice-view-logs' => 'Ver os rexistros',
35423840 );
35433841
35443842 /** Ancient Greek (Ἀρχαία ἑλληνικὴ)
@@ -3584,6 +3882,7 @@
35853883 'centralnotice-modify' => 'In Ornig',
35863884 'centralnotice-save-banner' => 'Banner spychere',
35873885 'centralnotice-preview' => 'Vorschau',
 3886+ 'centralnotice-nopreview' => '(s isch kei Vorschau verfiegbar)',
35883887 'centralnotice-add-new' => 'Fieg e neiji zentrali Mäldig zue',
35893888 'centralnotice-remove' => 'Useneh',
35903889 'centralnotice-translate-heading' => 'Ibersetzig vu „$1“',
@@ -3595,7 +3894,8 @@
35963895 'centralnotice-add-template' => 'Zuefiege vun ere Vorlag',
35973896 'centralnotice-show-notices' => 'Zeig Mäldige',
35983897 'centralnotice-list-templates' => 'Vorlage uflischte',
3599 - 'centralnotice-multiple' => 'mehreri ($1)',
 3898+ 'centralnotice-multiple-projects' => 'mehreri ($1)',
 3899+ 'centralnotice-multiple-languages' => 'mehreri ($1)',
36003900 'centralnotice-all-projects' => 'Alli Projäkt',
36013901 'centralnotice-translations' => 'Ibersetzige',
36023902 'centralnotice-translate-to' => 'Ibersetze in',
@@ -3709,11 +4009,12 @@
37104010 'centralnotice' => 'ניהול ההודעה המרכזית',
37114011 'noticetemplate' => 'ניהול ההודעה המרכזית',
37124012 'bannerallocation' => 'ניהול ההודעה המרכזית',
 4013+ 'centralnoticelogs' => 'ניהול הודעה מרכזית',
37134014 'right-centralnotice-admin' => 'ניהול הודעת מרכזיות',
37144015 'action-centralnotice-admin' => 'לנהל הודעות מרכזיות',
37154016 'centralnotice-desc' => 'הוספת הודעה בראש הדף משרת מרכזי',
3716 - 'centralnotice-summary' => 'מודול זה מאפשר את עריכת ההודעות המרכזיות המותקנות כעת.
3717 -ניתן גם להשתמש בו כדי להוסיף או להסיר הודעות ישנות.',
 4017+ 'centralnotice-summary' => 'מודול זה מאפשר את עריכת ההודעות המרכזיות המוגדרות כעת.
 4018+ניתן להשתמש בו גם כדי להוסיף ולהסיר הודעות.',
37184019 'centralnotice-query' => 'שינוי ההודעות הקיימות',
37194020 'centralnotice-notice-name' => 'שם ההודעה',
37204021 'centralnotice-end-date' => 'תאריך סיום',
@@ -3721,6 +4022,7 @@
37224023 'centralnotice-modify' => 'שליחה',
37234024 'centralnotice-save-banner' => 'שמירת הבאנר',
37244025 'centralnotice-preview' => 'תצוגה מקדימה',
 4026+ 'centralnotice-nopreview' => '(תצוגה מקדימה אינה זמינה)',
37254027 'centralnotice-add-new' => 'הוספת הודעה מרכזית חדשה',
37264028 'centralnotice-remove' => 'הסרה',
37274029 'centralnotice-translate-heading' => 'תרגום של $1',
@@ -3732,7 +4034,8 @@
37334035 'centralnotice-add-template' => 'הוספת תבנית',
37344036 'centralnotice-show-notices' => 'הצגת הודעות',
37354037 'centralnotice-list-templates' => 'רשימת תבניות',
3736 - 'centralnotice-multiple' => 'מרובים ($1)',
 4038+ 'centralnotice-multiple-projects' => 'מרובים ($1)',
 4039+ 'centralnotice-multiple-languages' => 'מרובות ($1)',
37374040 'centralnotice-all-projects' => 'כל המיזמים',
37384041 'centralnotice-translations' => 'תרגומים',
37394042 'centralnotice-translate-to' => 'תרגום ל',
@@ -3743,7 +4046,7 @@
37444047 'centralnotice-banner-heading' => 'באנר: $1',
37454048 'centralnotice-templates' => 'תבניות',
37464049 'centralnotice-weight' => 'משקל',
3747 - 'centralnotice-locked' => 'נעול',
 4050+ 'centralnotice-locked' => 'נעולה',
37484051 'centralnotice-notice' => 'מסע פרסום',
37494052 'centralnotice-notice-heading' => 'מסע פרסום: $1',
37504053 'centralnotice-notices' => 'הודעות',
@@ -3821,20 +4124,25 @@
38224125 'centralnotice-banner-type' => 'סוג הבאנר:',
38234126 'centralnotice-banner-hidable' => 'סטטי/ניתן להסתרה',
38244127 'centralnotice-banner-collapsible' => 'מתקפל',
 4128+ 'centralnotice-banner-fundraising' => 'זוהי כרזת התרמה',
 4129+ 'centralnotice-banner-fundraising-help' => 'נא ליצור תג עוגן בגוף הכּרזה עם id="cn_fundraising_link"‎ ולהזין דף נחיתה אחד או יותר בהמשך, למשל "JimmyAppeal01". ערך ה־href של הקישור ייבנה באופן אוטומטי.',
 4130+ 'centralnotice-banner-landing-pages' => 'דפי נחיתה (מופרדים בפסיקים):',
38254131 'centralnotice-geotargeted' => 'ממוקד גאוגרפית',
38264132 'centralnotice-countries' => 'מדינות',
38274133 'centralnotice-allocation' => 'הקצאה',
38284134 'centralnotice-view-allocation' => 'צפייה בהקצאת הבאנר',
3829 - 'centralnotice-allocation-instructions' => 'נא לבחור את הסביבה עבורה ברצונך לצפות בהקצאת הבאנר:',
 4135+ 'centralnotice-allocation-instructions' => 'נא לבחור את הסביבה שברצונך לצפות בהקצאת הבאנר עבורה:',
38304136 'centralnotice-languages' => 'שפות',
38314137 'centralnotice-projects' => 'מיזמים',
38324138 'centralnotice-country' => 'ארץ',
38334139 'centralnotice-no-allocation' => 'לא הוקצו באנרים',
38344140 'centralnotice-allocation-description' => 'הקצאת באנר עבור $1.$2 תחת $3:',
38354141 'centralnotice-percentage' => 'אחוזים',
3836 - 'centralnotice-documentwrite-error' => 'לא ניתן להשתמש ב־document.write() בתוך באנר.
 4142+ 'centralnotice-documentwrite-error' => 'לא ניתן להשתמש ב־document.write()‎ בתוך באנר.
38374143 ניתן לעיין ב־http://meta.wikimedia.org/wiki/Help:CentralNotice למידע נוסף.',
38384144 'centralnotice-preferred' => 'מועדפת',
 4145+ 'centralnotice-logs' => 'יומנים',
 4146+ 'centralnotice-view-logs' => 'הצגת יומנים',
38394147 );
38404148
38414149 /** Hindi (हिन्दी)
@@ -3852,6 +4160,7 @@
38534161 );
38544162
38554163 /** Croatian (Hrvatski)
 4164+ * @author Anton008
38564165 * @author Dalibor Bosits
38574166 * @author Ex13
38584167 * @author Herr Mlinka
@@ -3873,6 +4182,7 @@
38744183 'centralnotice-modify' => 'Postavi',
38754184 'centralnotice-save-banner' => 'Spremi poruku',
38764185 'centralnotice-preview' => 'Pregledaj',
 4186+ 'centralnotice-nopreview' => '(Prikaz nije moguć)',
38774187 'centralnotice-add-new' => 'Dodaj novu središnju obavijest',
38784188 'centralnotice-remove' => 'Ukloni',
38794189 'centralnotice-translate-heading' => 'Prijevod za $1',
@@ -3884,7 +4194,8 @@
38854195 'centralnotice-add-template' => 'Dodaj predložak',
38864196 'centralnotice-show-notices' => 'Pokaži obavijesti',
38874197 'centralnotice-list-templates' => 'Popis predložaka',
3888 - 'centralnotice-multiple' => 'više ($1)',
 4198+ 'centralnotice-multiple-projects' => 'više ($1)',
 4199+ 'centralnotice-multiple-languages' => 'više ($1)',
38894200 'centralnotice-all-projects' => 'Svi projekti',
38904201 'centralnotice-translations' => 'Prijevodi',
38914202 'centralnotice-translate-to' => 'Prevedi na',
@@ -3959,9 +4270,9 @@
39604271 'centralnotice-clone-name' => 'Ime:',
39614272 'centralnotice-preview-all-template-translations' => 'Vidi sve dostupne prijevode predloška',
39624273 'centralnotice-insert' => 'Umetni: $1',
3963 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} poveznica',
3964 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}} poveznica',
3965 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} poveznica',
 4274+ 'centralnotice-hide-button' => 'Sakrij poveznicu',
 4275+ 'centralnotice-collapse-button' => 'Sažmi poveznicu',
 4276+ 'centralnotice-expand-button' => 'Proširi poveznicu',
39664277 'centralnotice-close-button' => 'Zatvori gumb',
39674278 'centralnotice-translate-button' => 'Poveznica za pomoć pri prevođenju',
39684279 'centralnotice-donate-button' => 'Gumb za donacije',
@@ -4008,6 +4319,7 @@
40094320 'centralnotice-modify' => 'Wotpósłać',
40104321 'centralnotice-save-banner' => 'Chorhoj składować',
40114322 'centralnotice-preview' => 'Přehlad',
 4323+ 'centralnotice-nopreview' => '(žadyn přehlad k dispoziciji)',
40124324 'centralnotice-add-new' => 'Nowu centralnu zdźělenku přidać',
40134325 'centralnotice-remove' => 'Wotstronić',
40144326 'centralnotice-translate-heading' => 'Přełožk za $1',
@@ -4019,7 +4331,8 @@
40204332 'centralnotice-add-template' => 'Předłohu přidać',
40214333 'centralnotice-show-notices' => 'Zdźělenki pokazać',
40224334 'centralnotice-list-templates' => 'Předłohi nalistować',
4023 - 'centralnotice-multiple' => 'wjacore ($1)',
 4335+ 'centralnotice-multiple-projects' => 'wjacore ($1)',
 4336+ 'centralnotice-multiple-languages' => 'wjacore ($1)',
40244337 'centralnotice-all-projects' => 'Wšě projekty',
40254338 'centralnotice-translations' => 'Přełožki',
40264339 'centralnotice-translate-to' => 'Přełožić do',
@@ -4086,7 +4399,7 @@
40874400 'centralnotice-number-uses' => 'Wužića',
40884401 'centralnotice-settings' => 'Nastajenja',
40894402 'centralnotice-edit-template' => 'Předłohu wobdźěłać',
4090 - 'centralnotice-edit-template-summary' => '↓ Zo by lokalizujomnu stronu wutowrił, wobdaj znamješkowy rjećazk z wjazawku z třomi zhibowanymi spinkami. na př. {{{citat-jimbo}}}.',
 4403+ 'centralnotice-edit-template-summary' => 'Zo by lokalizujomnu stronu wutowrił, wobdaj znamješkowy rjećazk z wjazawku z třomi zhibowanymi spinkami. na př. {{{citat-jimbo}}}.',
40914404 'centralnotice-message' => 'Powěsć',
40924405 'centralnotice-message-not-set' => 'Powěsć njepostajena',
40934406 'centralnotice-clone' => 'Klonować',
@@ -4145,6 +4458,7 @@
41464459 'centralnotice-modify' => 'Elküldés',
41474460 'centralnotice-save-banner' => 'Hirdetés mentése',
41484461 'centralnotice-preview' => 'Előnézet',
 4462+ 'centralnotice-nopreview' => '(Előnézet nem áll rendelkezésre)',
41494463 'centralnotice-add-new' => 'Új központi üzenet hozzáadása',
41504464 'centralnotice-remove' => 'Eltávolítás',
41514465 'centralnotice-translate-heading' => '$1 fordítása',
@@ -4156,7 +4470,8 @@
41574471 'centralnotice-add-template' => 'Sablon hozzáadása',
41584472 'centralnotice-show-notices' => 'Üzenetek megjelenítése',
41594473 'centralnotice-list-templates' => 'Sablonok listázása',
4160 - 'centralnotice-multiple' => 'több ($1)',
 4474+ 'centralnotice-multiple-projects' => 'több ($1)',
 4475+ 'centralnotice-multiple-languages' => 'több ($1)',
41614476 'centralnotice-all-projects' => 'Minden projekt',
41624477 'centralnotice-translations' => 'Fordítások',
41634478 'centralnotice-translate-to' => 'Lefordítás',
@@ -4231,9 +4546,9 @@
42324547 'centralnotice-clone-name' => 'Név:',
42334548 'centralnotice-preview-all-template-translations' => 'A sablon összes fordításának megtekintése',
42344549 'centralnotice-insert' => 'Beszúrás: $1',
4235 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}}-hivatkozás',
4236 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}}-hivatkozás',
4237 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}}-hivatkozás',
 4550+ 'centralnotice-hide-button' => 'Hivatkozás elrejtése',
 4551+ 'centralnotice-collapse-button' => 'Hivatkozás összecsukása',
 4552+ 'centralnotice-expand-button' => 'Hivatkozás kibontása',
42384553 'centralnotice-close-button' => 'Bezárás gomb',
42394554 'centralnotice-translate-button' => '„Segíts a fordításban”-hivatkozás',
42404555 'centralnotice-donate-button' => 'Adakozás-gomb',
@@ -4268,6 +4583,7 @@
42694584 'centralnotice' => 'Administration de avisos central',
42704585 'noticetemplate' => 'Administration de avisos central',
42714586 'bannerallocation' => 'Administration de avisos central',
 4587+ 'centralnoticelogs' => 'Administration de avisos central',
42724588 'right-centralnotice-admin' => 'Gerer avisos central',
42734589 'action-centralnotice-admin' => 'gerer avisos central',
42744590 'centralnotice-desc' => 'Adde un aviso de sito central',
@@ -4280,6 +4596,7 @@
42814597 'centralnotice-modify' => 'Submitter',
42824598 'centralnotice-save-banner' => 'Salveguardar bandiera',
42834599 'centralnotice-preview' => 'Previsualisar',
 4600+ 'centralnotice-nopreview' => '(Previsualisation non disponibile)',
42844601 'centralnotice-add-new' => 'Adder un nove campania',
42854602 'centralnotice-remove' => 'Remover',
42864603 'centralnotice-translate-heading' => 'Traduction de $1',
@@ -4291,7 +4608,8 @@
42924609 'centralnotice-add-template' => 'Adder un bandiera',
42934610 'centralnotice-show-notices' => 'Monstrar campanias',
42944611 'centralnotice-list-templates' => 'Listar bandieras',
4295 - 'centralnotice-multiple' => 'multiple ($1)',
 4612+ 'centralnotice-multiple-projects' => 'multiple ($1)',
 4613+ 'centralnotice-multiple-languages' => 'multiple ($1)',
42964614 'centralnotice-all-projects' => 'Tote le projectos',
42974615 'centralnotice-translations' => 'Traductiones',
42984616 'centralnotice-translate-to' => 'Traducer in',
@@ -4380,6 +4698,9 @@
43814699 'centralnotice-banner-type' => 'Typo de bandiera:',
43824700 'centralnotice-banner-hidable' => 'Static/Celabile',
43834701 'centralnotice-banner-collapsible' => 'Plicabile',
 4702+ 'centralnotice-banner-fundraising' => 'Isto es un bandiera de collecta de fundos',
 4703+ 'centralnotice-banner-fundraising-help' => 'Crea un etiquetta de ancora in le corpore del bandiera con id="cn_fundraising_link" e entra un o plus paginas de arrivata hic infra, per exemplo "AppelloJimmy01". Le "href" del ligamine essera construite automaticamente.',
 4704+ 'centralnotice-banner-landing-pages' => 'Paginas de arrivata (separate per commas):',
43844705 'centralnotice-geotargeted' => 'Localisation geographic',
43854706 'centralnotice-countries' => 'Paises',
43864707 'centralnotice-allocation' => 'Allocation',
@@ -4394,6 +4715,8 @@
43954716 'centralnotice-documentwrite-error' => 'document.write() non pote esser usate intra un bandiera.
43964717 Vide http://meta.wikimedia.org/wiki/Help:CentralNotice pro plus informationes.',
43974718 'centralnotice-preferred' => 'Preferite',
 4719+ 'centralnotice-logs' => 'Registros',
 4720+ 'centralnotice-view-logs' => 'Vider registros',
43984721 );
43994722
44004723 /** Indonesian (Bahasa Indonesia)
@@ -4420,6 +4743,7 @@
44214744 'centralnotice-modify' => 'Kirim',
44224745 'centralnotice-save-banner' => 'Panji simpan',
44234746 'centralnotice-preview' => 'Pratayang',
 4747+ 'centralnotice-nopreview' => '(Pratayang tak tersedia)',
44244748 'centralnotice-add-new' => 'Buat pengumuman sentral baru',
44254749 'centralnotice-remove' => 'Hapus',
44264750 'centralnotice-translate-heading' => 'Terjemahan untuk $1',
@@ -4431,7 +4755,8 @@
44324756 'centralnotice-add-template' => 'Tambah templat',
44334757 'centralnotice-show-notices' => 'Tampilkan pengumuman',
44344758 'centralnotice-list-templates' => 'Daftar templat',
4435 - 'centralnotice-multiple' => 'ganda ($1)',
 4759+ 'centralnotice-multiple-projects' => 'ganda ($1)',
 4760+ 'centralnotice-multiple-languages' => 'ganda ($1)',
44364761 'centralnotice-all-projects' => 'Semua proyek',
44374762 'centralnotice-translations' => 'Terjemahan',
44384763 'centralnotice-translate-to' => 'Terjemahkan ke',
@@ -4561,6 +4886,17 @@
45624887 'centralnotice-clone-name' => 'Áhà',
45634888 );
45644889
 4890+/** Ingush (ГІалгІай Ğalğaj)
 4891+ * @author Sapral Mikail
 4892+ */
 4893+$messages['inh'] = array(
 4894+ 'centralnotice-day' => 'Ди',
 4895+ 'centralnotice-year' => 'Шу',
 4896+ 'centralnotice-month' => 'Бутт',
 4897+ 'centralnotice-hours' => 'Сахьат',
 4898+ 'centralnotice-min' => 'Минот',
 4899+);
 4900+
45654901 /** Ido (Ido)
45664902 * @author Malafaya
45674903 */
@@ -4602,6 +4938,8 @@
46034939 'centralnotice' => 'Gestione avviso centralizzato',
46044940 'noticetemplate' => 'Gestione avviso centralizzato',
46054941 'bannerallocation' => 'Gestione avviso centralizzato',
 4942+ 'right-centralnotice-admin' => 'Gestisce gli avvisi centralizzati',
 4943+ 'action-centralnotice-admin' => 'gestire gli avvisi centralizzati',
46064944 'centralnotice-desc' => 'Aggiunge un avviso centralizzato a inizio pagina (sitenotice)',
46074945 'centralnotice-summary' => 'Questo modulo permette di modificare gli avvisi centralizzati. Puoi essere inoltre usato per aggiungere o rimuovere vecchi avvisi.',
46084946 'centralnotice-query' => 'Modifica avvisi attuali',
@@ -4611,6 +4949,7 @@
46124950 'centralnotice-modify' => 'Invia',
46134951 'centralnotice-save-banner' => 'Salva banner',
46144952 'centralnotice-preview' => 'Anteprima',
 4953+ 'centralnotice-nopreview' => '(Anteprima non disponibile)',
46154954 'centralnotice-add-new' => 'Aggiungi un nuovo avviso centralizzato',
46164955 'centralnotice-remove' => 'Rimuovi',
46174956 'centralnotice-translate-heading' => 'Traduzione di $1',
@@ -4622,7 +4961,8 @@
46234962 'centralnotice-add-template' => 'Aggiungi un template',
46244963 'centralnotice-show-notices' => 'Mostra avvisi',
46254964 'centralnotice-list-templates' => 'Elenca template',
4626 - 'centralnotice-multiple' => 'Multiple ($1)',
 4965+ 'centralnotice-multiple-projects' => 'Multiple ($1)',
 4966+ 'centralnotice-multiple-languages' => 'Multiple ($1)',
46274967 'centralnotice-all-projects' => 'Tutti i progetti',
46284968 'centralnotice-translations' => 'Traduzioni',
46294969 'centralnotice-translate-to' => 'Traduci in',
@@ -4705,10 +5045,6 @@
47065046 'centralnotice-percentage' => 'Percentuale',
47075047 'centralnotice-documentwrite-error' => 'Non è possibile usare document.write() dentro un banner.
47085048 Vedi http://meta.wikimedia.org/wiki/Help:CentralNotice per maggiori informazioni.',
4709 - 'right-centralnotice-admin' => 'Gestisce gli avvisi centralizzati',
4710 - 'right-centralnotice-translate' => 'Traduce avvisi centralizzati',
4711 - 'action-centralnotice-admin' => 'gestire gli avvisi centralizzati',
4712 - 'action-centralnotice-translate' => 'tradurre avvisi centralizzati',
47135049 'centralnotice-preferred' => 'Preferito',
47145050 );
47155051
@@ -4737,6 +5073,7 @@
47385074 'centralnotice-modify' => '投稿',
47395075 'centralnotice-save-banner' => 'テンプレートを保存',
47405076 'centralnotice-preview' => 'プレビュー',
 5077+ 'centralnotice-nopreview' => '(プレビューはありません)',
47415078 'centralnotice-add-new' => '新しい告知を追加する',
47425079 'centralnotice-remove' => '除去',
47435080 'centralnotice-translate-heading' => '$1の翻訳',
@@ -4748,7 +5085,8 @@
47495086 'centralnotice-add-template' => 'テンプレートを追加',
47505087 'centralnotice-show-notices' => '告知を表示',
47515088 'centralnotice-list-templates' => 'テンプレートを一覧表示',
4752 - 'centralnotice-multiple' => '複数($1)',
 5089+ 'centralnotice-multiple-projects' => '複数($1)',
 5090+ 'centralnotice-multiple-languages' => '複数($1)',
47535091 'centralnotice-all-projects' => '全プロジェクト',
47545092 'centralnotice-translations' => '翻訳',
47555093 'centralnotice-translate-to' => '翻訳先',
@@ -4864,6 +5202,8 @@
48655203 $messages['jv'] = array(
48665204 'centralnotice' => "Admin cathetan pusat (''central notice'')",
48675205 'noticetemplate' => "Cithakan cathetan pusat (''central notice'')",
 5206+ 'right-centralnotice-admin' => 'Tata cathetan pusat',
 5207+ 'action-centralnotice-admin' => "tata cathetan pusat (''central notices'')",
48685208 'centralnotice-desc' => 'Nambahaké wara-wara situs punjer',
48695209 'centralnotice-summary' => "Modul iki kanggo nyunting tatanan cathetan pusat (''central notice'') sing ana.
48705210 Iki uga bisa kanggo nambah utawa mbuwang cathetan/pangumuman lawas.",
@@ -4939,10 +5279,6 @@
49405280 'centralnotice-clone' => 'Kloning',
49415281 'centralnotice-clone-notice' => "Gawé salinan (''copy'') saka cithakan",
49425282 'centralnotice-preview-all-template-translations' => 'Tampilaké kabèh terjemahan cithakan sing ana',
4943 - 'right-centralnotice-admin' => 'Tata cathetan pusat',
4944 - 'right-centralnotice-translate' => "Terjemahaké cathetan pusat (''central notices'')",
4945 - 'action-centralnotice-admin' => "tata cathetan pusat (''central notices'')",
4946 - 'action-centralnotice-translate' => "terjemahaké cathetan pusat (''central notices'')",
49475283 );
49485284
49495285 /** Georgian (ქართული)
@@ -4977,7 +5313,8 @@
49785314 'centralnotice-add-template' => 'დაამატეთ თარგი',
49795315 'centralnotice-show-notices' => 'შეტყობინებების ჩვენება',
49805316 'centralnotice-list-templates' => 'თარგების სია',
4981 - 'centralnotice-multiple' => 'მრავალი ($1)',
 5317+ 'centralnotice-multiple-projects' => 'მრავალი ($1)',
 5318+ 'centralnotice-multiple-languages' => 'მრავალი ($1)',
49825319 'centralnotice-all-projects' => 'ყველა პროექტი',
49835320 'centralnotice-translations' => 'თარგმანები',
49845321 'centralnotice-translate-to' => 'გადათარგმნა',
@@ -5024,6 +5361,8 @@
50255362 'centralnotice-invalid-date-range' => 'დროის არასწორი მონაკვეთი.
50265363 არ განახლდება.',
50275364 'centralnotice-confirm-delete' => 'დარწმუნებული ხართ, რომ გინდათ ამ ელემენტის წაშლა? ეს მოქმედება ვეღარ გაუქმნდება.',
 5365+ 'centralnotice-no-notices-exist' => 'შეტყობინება არ არსებობს.
 5366+დაამატე.',
50285367 'centralnotice-number-uses' => 'გამოიყენება',
50295368 'centralnotice-settings' => 'კონფიგურაცია',
50305369 'centralnotice-edit-template' => 'თარგის რედაქტირება',
@@ -5032,12 +5371,17 @@
50335372 'centralnotice-clone' => 'კლონირება',
50345373 'centralnotice-clone-notice' => 'თარგის ასლის შექმნა',
50355374 'centralnotice-clone-name' => 'სახელი:',
 5375+ 'centralnotice-preview-all-template-translations' => 'ბანერის ყველა არსებული თარგმანის ხილვა',
50365376 'centralnotice-insert' => 'ჩასვით: $1',
50375377 'centralnotice-hide-button' => 'ბმულის დამალვა',
50385378 'centralnotice-close-button' => 'დახურვის ღილაკი',
 5379+ 'centralnotice-translate-button' => 'დამხმარე ბმული თარგმანებისთვის',
50395380 'centralnotice-donate-button' => 'შემოწირულობების ღილაკი',
 5381+ 'centralnotice-banner-display' => 'აჩვენე:',
50405382 'centralnotice-banner-anonymous' => 'ანონიმური მომხმარებლები',
 5383+ 'centralnotice-banner-logged-in' => 'შემოსული მომხმარებლები',
50415384 'centralnotice-banner-type' => 'ბანერის ტიპი:',
 5385+ 'centralnotice-banner-hidable' => 'სტატიკური/დაფარული',
50425386 'centralnotice-banner-collapsible' => 'დასაკეცი',
50435387 'centralnotice-geotargeted' => 'გეო-მიზნობრივი',
50445388 'centralnotice-countries' => 'ქვეყნები',
@@ -5046,7 +5390,11 @@
50475391 'centralnotice-languages' => 'ენები',
50485392 'centralnotice-projects' => 'პროექტები',
50495393 'centralnotice-country' => 'ქვეყანა',
 5394+ 'centralnotice-no-allocation' => 'ბანერები არ განაწილდა.',
 5395+ 'centralnotice-allocation-description' => 'ბანერთა განაწილება $1.$2-თვის $3–ში:',
50505396 'centralnotice-percentage' => 'პროცენტი',
 5397+ 'centralnotice-documentwrite-error' => 'document.write() არ შეიძლება გამოყენებული იქნას ბანერის შიგნით.
 5398+იხილეთ http://meta.wikimedia.org/wiki/Help:CentralNotice მეტი ინფორმაციისათვის.',
50515399 'centralnotice-preferred' => 'პრივილეგირებული',
50525400 );
50535401
@@ -5063,6 +5411,7 @@
50645412 'centralnotice-modify' => 'ដាក់ស្នើ',
50655413 'centralnotice-save-banner' => 'រក្សាទុកបដា',
50665414 'centralnotice-preview' => 'មើលជាមុន',
 5415+ 'centralnotice-nopreview' => '(គ្មានការមើលជាមុន)',
50675416 'centralnotice-add-new' => 'បន្ថែមយុទ្ធនាការថ្មីមួយ',
50685417 'centralnotice-remove' => 'ដកចេញ',
50695418 'centralnotice-translate-heading' => 'ការប្រែសម្រួល​សម្រាប់​$1',
@@ -5074,7 +5423,8 @@
50755424 'centralnotice-add-template' => 'បន្ថែមទំព័រគំរូ',
50765425 'centralnotice-show-notices' => 'បង្ហាញយុទ្ធនាការ',
50775426 'centralnotice-list-templates' => 'បញ្ជីបដា',
5078 - 'centralnotice-multiple' => 'ច្រើនភាសា($1)',
 5427+ 'centralnotice-multiple-projects' => 'ច្រើនភាសា($1)',
 5428+ 'centralnotice-multiple-languages' => 'ច្រើនភាសា($1)',
50795429 'centralnotice-all-projects' => 'គំរោងទាំងអស់',
50805430 'centralnotice-translations' => 'ការបកប្រែ',
50815431 'centralnotice-translate-to' => 'បកប្រែ​ទៅ',
@@ -5134,6 +5484,7 @@
51355485 'centralnotice-banner-type' => 'ប្រភេទបដា៖',
51365486 'centralnotice-banner-hidable' => 'នឹងថ្កល់/អាចលាក់បាន',
51375487 'centralnotice-banner-collapsible' => 'អាចបង្រួញបាន',
 5488+ 'centralnotice-banner-fundraising' => 'នេះជាបដាសំរាប់ឃោសនារៃអង្គាសប្រាក់',
51385489 'centralnotice-geotargeted' => 'អាចកំនត់តំបន់សំរាប់បង្ហាញ',
51395490 'centralnotice-countries' => 'ប្រទេស',
51405491 'centralnotice-languages' => 'ភាសា',
@@ -5171,6 +5522,9 @@
51725523 'centralnotice' => '중앙 공지 관리',
51735524 'noticetemplate' => '중앙 공지 관리',
51745525 'bannerallocation' => '중앙 공지 관리',
 5526+ 'centralnoticelogs' => '중앙 공지 관리자',
 5527+ 'right-centralnotice-admin' => '중앙 공지 관리',
 5528+ 'action-centralnotice-admin' => '중앙 공지를 관리하기',
51755529 'centralnotice-desc' => '중앙에서 공지하는 사이트노티스를 추가',
51765530 'centralnotice-summary' => '전체 공지 기능을 추가합니다. 현재의 공지 편집 기능과 공지의 추가/삭제 기능을 제공합니다.',
51775531 'centralnotice-query' => '현재 공지 수정하기',
@@ -5191,7 +5545,9 @@
51925546 'centralnotice-add-template' => '틀을 추가하기',
51935547 'centralnotice-show-notices' => '공지 표시하기',
51945548 'centralnotice-list-templates' => '템플릿 목록 표시하기',
5195 - 'centralnotice-multiple' => '다수 ($1)',
 5549+ 'centralnotice-multiple-projects' => '다수 ($1)',
 5550+ 'centralnotice-multiple-languages' => '다수 ($1)',
 5551+ 'centralnotice-all-projects' => '모든 프로젝트',
51965552 'centralnotice-translations' => '번역',
51975553 'centralnotice-translate-to' => '번역할 언어',
51985554 'centralnotice-translate' => '번역하기',
@@ -5254,14 +5610,29 @@
52555611 'centralnotice-clone-notice' => '이 틀의 사본을 만들기',
52565612 'centralnotice-clone-name' => '이름:',
52575613 'centralnotice-preview-all-template-translations' => '템플렛의 모든 번역 미리 보기',
 5614+ 'centralnotice-insert' => '삽입: $1',
 5615+ 'centralnotice-hide-button' => '숨기기 링크',
 5616+ 'centralnotice-collapse-button' => '접기 링크',
 5617+ 'centralnotice-expand-button' => '펼치기 링크',
 5618+ 'centralnotice-close-button' => '닫기 버튼',
 5619+ 'centralnotice-translate-button' => '번역 도움 요청 링크',
 5620+ 'centralnotice-donate-button' => '기부 버튼',
 5621+ 'centralnotice-expanded-banner' => '펼친 배너',
 5622+ 'centralnotice-collapsed-banner' => '접힌 배너',
 5623+ 'centralnotice-banner-display' => '공지를 보여 줄 대상:',
 5624+ 'centralnotice-banner-anonymous' => '익명 사용자',
 5625+ 'centralnotice-banner-logged-in' => '계정 등록 사용자',
 5626+ 'centralnotice-banner-type' => '배너 유형:',
 5627+ 'centralnotice-banner-hidable' => '정적/숨길 수 있음',
 5628+ 'centralnotice-banner-collapsible' => '접을 수 있음',
 5629+ 'centralnotice-geotargeted' => '특정 지역을 대상으로 공지',
 5630+ 'centralnotice-countries' => '국가',
 5631+ 'centralnotice-allocation' => '배당',
 5632+ 'centralnotice-languages' => '언어',
52585633 'centralnotice-projects' => '프로젝트',
52595634 'centralnotice-country' => '국가',
52605635 'centralnotice-documentwrite-error' => '배너에 document.write() 메서드는 사용할 수 없습니다.
52615636 자세한 내용에 대해서는 [http://meta.wikimedia.org/wiki/Help:CentralNotice http://meta.wikimedia.org/wiki/Help:CentralNotice]를 참조하십시오.',
5262 - 'right-centralnotice-admin' => '중앙 공지 관리',
5263 - 'right-centralnotice-translate' => '중앙 공지 번역',
5264 - 'action-centralnotice-admin' => '중앙 공지를 관리하기',
5265 - 'action-centralnotice-translate' => '중앙 공지를 번역할',
52665637 'centralnotice-preferred' => '우선 사용',
52675638 );
52685639
@@ -5270,51 +5641,64 @@
52715642 */
52725643 $messages['ksh'] = array(
52735644 'centralnotice' => 'Zentraal Nohreschte verwallde',
5274 - 'noticetemplate' => 'Schabloon för zentraal Nohreschte',
 5645+ 'noticetemplate' => 'Zentraal Nohreschte verwallde',
 5646+ 'bannerallocation' => 'Zentraal Nohreschte verwallde',
 5647+ 'right-centralnotice-admin' => 'Zentraal Nohreschte verwallde',
 5648+ 'action-centralnotice-admin' => 'zentraal Nohreschte ze verwallde',
52755649 'centralnotice-desc' => "Brengk en zentraale ''sitenotice'' en et wiki",
52765650 'centralnotice-summary' => 'Hee met kanns De de zentraal Nohreschte ändere, die jraad em Wiki opjesaz sen,
52775651 ävver och neue dobei donn, un allde fott schmieße.',
5278 - 'centralnotice-query' => 'Aktowälle zentraale Nohreesch ändere.',
5279 - 'centralnotice-notice-name' => 'Dä Nohreesch ier Name',
 5652+ 'centralnotice-query' => 'De Aktowälle Kampannje ändere',
 5653+ 'centralnotice-notice-name' => 'Dä Kampannje ier Name',
52805654 'centralnotice-end-date' => 'Et Dattum fum Engk',
52815655 'centralnotice-enabled' => 'Aanjeschalldt',
52825656 'centralnotice-modify' => 'Loß Jonn!',
 5657+ 'centralnotice-save-banner' => 'De Banner_Schablohn faßhallde',
52835658 'centralnotice-preview' => 'Vör-Aansich zeije',
5284 - 'centralnotice-add-new' => 'Donn en zentrale Nohreesch dobei',
 5659+ 'centralnotice-nopreview' => '(Kein Vör-Aansich ze hann)',
 5660+ 'centralnotice-add-new' => 'Donn en Kampannje dobei',
52855661 'centralnotice-remove' => 'Fottnämme',
52865662 'centralnotice-translate-heading' => 'Övversäzong för $1',
5287 - 'centralnotice-manage' => 'Zentrale Nohreschte fowallde',
 5663+ 'centralnotice-manage' => 'Kampannje fowallde',
 5664+ 'centralnotice-manage-templates' => 'Banner_Schablohne verwallde',
52885665 'centralnotice-add' => 'Dobeidonn',
5289 - 'centralnotice-add-notice' => 'En zentral Nohreesch dobei donn',
5290 - 'centralnotice-edit-notice' => 'En zentrale Nohreesch ändere',
5291 - 'centralnotice-add-template' => 'En Schabloon dobei donn',
5292 - 'centralnotice-show-notices' => 'Zentrale Nohreschte zeije',
5293 - 'centralnotice-list-templates' => 'Schablone opleßte',
5294 - 'centralnotice-multiple' => 'etlijje ($1)',
 5666+ 'centralnotice-add-notice' => 'En Kampannje dobei donn',
 5667+ 'centralnotice-edit-notice' => 'En Kampannje ändere',
 5668+ 'centralnotice-add-template' => 'En Banner_Schablohn dobei donn',
 5669+ 'centralnotice-show-notices' => 'En Kampannje zeije',
 5670+ 'centralnotice-list-templates' => 'Banner_Schablohne opleßte',
 5671+ 'centralnotice-multiple-projects' => 'etlijje ($1)',
 5672+ 'centralnotice-multiple-languages' => 'etlijje ($1)',
52955673 'centralnotice-all-projects' => 'All Projäkte',
 5674+ 'centralnotice-language-listing' => '$1 — $2',
52965675 'centralnotice-translations' => 'Övversäzonge',
52975676 'centralnotice-translate-to' => 'Övversäze noh',
52985677 'centralnotice-translate' => 'Övversäze',
52995678 'centralnotice-english' => 'Englesch',
5300 - 'centralnotice-banner-name' => 'Dä Schablon iere Name',
5301 - 'centralnotice-templates' => 'Schablone',
 5679+ 'centralnotice-banner-name' => 'Dä Banner_Schablohne ier Name',
 5680+ 'centralnotice-banner' => 'Banner_Schablohne',
 5681+ 'centralnotice-banner-heading' => 'Banner_Schablohn: $1',
 5682+ 'centralnotice-templates' => 'Banner_Schablohne',
53025683 'centralnotice-weight' => 'Jeweesch',
53035684 'centralnotice-locked' => 'jespert',
5304 - 'centralnotice-notices' => 'zentrale Nohreschte',
5305 - 'centralnotice-notice-exists' => 'Di zentrale Nohreesch es ald doh.
 5685+ 'centralnotice-notice' => 'Kampannje',
 5686+ 'centralnotice-notice-heading' => 'Kampannje: $1',
 5687+ 'centralnotice-notices' => 'Kampannje',
 5688+ 'centralnotice-notice-exists' => 'Di Kampannje es ald doh.
53065689 Nix dobei jedonn.',
5307 - 'centralnotice-no-language' => 'Et es kein Shprooch för di zentrale Nohreesch ußjesöhk.
 5690+ 'centralnotice-no-language' => 'Et es kein Shprooch för di Kampannje ußjesöhk.
53085691 Nix dobei jedonn.',
5309 - 'centralnotice-no-project' => 'Et es kein Projäk för di zentrale Nohreesch ußjesöhk.
 5692+ 'centralnotice-no-project' => 'Et es kein Projäk för di Kampannje ußjesöhk.
53105693 Nix dobei jedonn.',
5311 - 'centralnotice-template-exists' => 'Di Schablon es ald doh.
5312 -Nit dobei jedonn.',
5313 - 'centralnotice-notice-doesnt-exist' => 'Di zentrale Nohreesch jidd et nit.',
5314 - 'centralnotice-remove-notice-doesnt-exist' => 'Di zentrale Nohreesch es nit doh.
 5694+ 'centralnotice-template-exists' => 'Di Banner_Schablohn es ald doh.
 5695+Nit norr_ens dobei jedonn.',
 5696+ 'centralnotice-notice-doesnt-exist' => 'Di Kampannje jidd et nit.',
 5697+ 'centralnotice-remove-notice-doesnt-exist' => 'Di Kampannje es nit doh.
53155698 Nix wood fott jelohße.',
5316 - 'centralnotice-template-still-bound' => 'Di Schablon deit aan ene zentrale Nohreesch hange.
 5699+ 'centralnotice-banner-doesnt-exist' => 'Di Banner_Schablohn jidd_et nit.',
 5700+ 'centralnotice-template-still-bound' => 'Di Banner_Schablohn deit aan en Kampannje hange.
53175701 Di kam_mer nit fott nämme.',
5318 - 'centralnotice-template-body' => 'Dä Tex fun dä Schablon:',
 5702+ 'centralnotice-template-body' => 'Dat es en dä Banner_Schablohn dren:',
53195703 'centralnotice-day' => 'Daach',
53205704 'centralnotice-year' => 'Johr',
53215705 'centralnotice-month' => 'Moohnd',
@@ -5327,20 +5711,20 @@
53285712 'centralnotice-start-date' => 'Et Annfangsdattum',
53295713 'centralnotice-start-time' => 'De Aanfangszick (UTC)',
53305714 'centralnotice-end-time' => 'De UTC Zick för et Engk',
5331 - 'centralnotice-assigned-templates' => 'Zojedeilte Schablone',
5332 - 'centralnotice-no-templates' => 'Mer han kein Schablone.
 5715+ 'centralnotice-assigned-templates' => 'Zojedeilte Banner_Schablohne',
 5716+ 'centralnotice-no-templates' => 'Mer hann_er kein Banner_Schablohne jefonge.
53335717 Kanns ävver welshe dobei don.',
5334 - 'centralnotice-no-templates-assigned' => 'Et sin kein Schablone för di zentraal Nohreesch zojedeilt.
 5718+ 'centralnotice-no-templates-assigned' => 'Et sinn_er kein Banner_Schablohne för di Kampannje zohjedeilt.
53355719 Donn dat ens!',
5336 - 'centralnotice-available-templates' => 'Müjjelesche Schabloone',
5337 - 'centralnotice-template-already-exists' => 'Di Schablon weed ald förr_en Kampannje jebruch.
 5720+ 'centralnotice-available-templates' => 'Müjjelesche Banner_Schablohne',
 5721+ 'centralnotice-template-already-exists' => 'Di Banner_Schablohn weed ald förr_en Kampannje jebruch.
53385722 Nit dobeijedonn.',
5339 - 'centralnotice-preview-template' => 'Vör-Ansich för di Schablon',
 5723+ 'centralnotice-preview-template' => 'Vör-Ansich för di Banner_Schablohn',
53405724 'centralnotice-change-lang' => 'Shprooch fö et Övversäze ändere',
53415725 'centralnotice-weights' => 'Jeweeschte',
5342 - 'centralnotice-notice-is-locked' => 'Di zentraal Nohreesch es jesperrt.
 5726+ 'centralnotice-notice-is-locked' => 'Di Kampannje es jesperrt.
53435727 Se blief.',
5344 - 'centralnotice-overlap' => 'De Zick vun hee dä, un en ander vun dä zentraale Nohreschte, donn sesch övverlappe. Dat jeiht nit.
 5728+ 'centralnotice-overlap' => 'De Zick vun hee dä Kampannje, un en ander donn sesch övverlappe. Dat jeiht nit.
53455729 Nit dobei jedonn.',
53465730 'centralnotice-invalid-date-range' => 'Die Zigge jidd_et nit.
53475731 Nix jedonn.',
@@ -5348,19 +5732,19 @@
53495733 Dat maache mer nit.',
53505734 'centralnotice-confirm-delete' => "Bes De sescher, dat De dä Enndraach fottschmiiße well?
53515735 Fott eß fott, dä kam_mer '''nit''' widder zeröck holle!",
5352 - 'centralnotice-no-notices-exist' => 'Mer han kein Nohreschte.
5353 -De kanns ävver welshe dobei don.',
5354 - 'centralnotice-no-templates-translate' => 'Mer hann kein Schablone, woh mer Översäzunge för beärbeide künnt.',
 5736+ 'centralnotice-no-notices-exist' => 'Mer han kein Kampannje.
 5737+De kanns ävver heh dronger ein dobei donn.',
 5738+ 'centralnotice-no-templates-translate' => 'Mer hann kein Banner_Schablohne, woh mer Översäzunge för beärbeide künnt.',
53555739 'centralnotice-number-uses' => 'mol jebruch',
53565740 'centralnotice-settings' => 'Enshtällonge',
5357 - 'centralnotice-edit-template' => 'Schablon beärbeide',
 5741+ 'centralnotice-edit-template' => 'Banner_Schablohn beärbeide',
53585742 'centralnotice-edit-template-summary' => 'Öm en Nohreesch för zem Övversäze ze krijje, donn ene Name doför (uß Boochshtabe un Bendeshtresch) zwesche drei jeschwänzde Klammre erin schrieve, wi för e Beishpell; <code lang="en">{{{jimbo-zitat}}}</code>.',
53595743 'centralnotice-message' => 'Nohreesch',
53605744 'centralnotice-message-not-set' => 'De Nohreesch es nit jesaz',
53615745 'centralnotice-clone' => 'Kopi maache',
5362 - 'centralnotice-clone-notice' => 'Maach en Kopi fun dä Schabloon',
5363 - 'centralnotice-clone-name' => 'Name:',
5364 - 'centralnotice-preview-all-template-translations' => 'Vör-Aansich fun all dä Övversäzunge fun dä Schablon',
 5746+ 'centralnotice-clone-notice' => 'Maach en Kopi fun dä Banner_Schablohn',
 5747+ 'centralnotice-clone-name' => 'Der Name:',
 5748+ 'centralnotice-preview-all-template-translations' => 'Vör-Aansich fun all dä Övversäzunge fun dä Banner_Schablohn',
53655749 'centralnotice-insert' => 'Enfööje: $1',
53665750 'centralnotice-hide-button' => 'Lengk vershteiche',
53675751 'centralnotice-collapse-button' => 'Lengk zosammefallde',
@@ -5368,25 +5752,56 @@
53695753 'centralnotice-close-button' => 'Knopp zom Zohmaache',
53705754 'centralnotice-translate-button' => 'Hellef met bem Övversäze!',
53715755 'centralnotice-donate-button' => 'Dä Knopp för et Spände',
 5756+ 'centralnotice-expanded-banner' => 'Opjeklapp Banner_Schablohn',
 5757+ 'centralnotice-collapsed-banner' => 'Zohjeklapp Banner_Schablohn',
53725758 'centralnotice-banner-display' => 'Aanzeije för de:',
53735759 'centralnotice-banner-anonymous' => 'Nameloose Metmaacher',
53745760 'centralnotice-banner-logged-in' => 'Enjeelog Metmaacher',
5375 - 'centralnotice-banner-type' => 'Banner Zoot:',
 5761+ 'centralnotice-banner-type' => 'De Zoot Banner_Schablohn:',
53765762 'centralnotice-banner-hidable' => 'Faß udder ußschaltbaa',
53775763 'centralnotice-banner-collapsible' => 'Enklappbaa',
53785764 'centralnotice-geotargeted' => 'Met Koodinaate op de Ääd',
53795765 'centralnotice-countries' => 'Länder',
 5766+ 'centralnotice-allocation' => 'Verdeilong',
 5767+ 'centralnotice-view-allocation' => 'De Banner_Schablohne iehr Zohdeilong beloore',
 5768+ 'centralnotice-allocation-instructions' => 'Donn de Ömjävong udder der Zohsammehang ußwähle, woh De de zohjedeilte Banner_Schablohne för belooere wells:',
53805769 'centralnotice-languages' => 'Shprooche',
53815770 'centralnotice-projects' => 'Projäkte',
53825771 'centralnotice-country' => 'Land',
5383 - 'right-centralnotice-admin' => 'Zentraal Nohreschte verwallde',
5384 - 'right-centralnotice-translate' => 'Zentraal Nohreschte övversäze',
5385 - 'action-centralnotice-admin' => 'zentraal Nohreschte ze verwallde',
5386 - 'action-centralnotice-translate' => 'zentraal Nohreschte ze övversäze',
 5772+ 'centralnotice-no-allocation' => 'Kein Banner_Schablohne zohjedeilt',
 5773+ 'centralnotice-allocation-description' => 'De zohjedeilte Banner_Schablohne för $1.$2 en $3 sin:',
 5774+ 'centralnotice-percentage' => 'Prozäntsaz',
 5775+ 'centralnotice-documentwrite-error' => 'Mer künne <code lang="en">document.write()</code> nit ennerhallef vun ene Banner_Schablohn bruche.
 5776+Loor op http://meta.wikimedia.org/wiki/Help:CentralNotice wann De mieh weße wells.',
53875777 'centralnotice-preferred' => 'Förjetrocke!',
53885778 );
53895779
5390 -/** Cornish (Kernewek)
 5780+/** Kurdish (Latin) (Kurdî (Latin))
 5781+ * @author George Animal
 5782+ */
 5783+$messages['ku-latn'] = array(
 5784+ 'centralnotice-preview' => 'Pêşdîtin',
 5785+ 'centralnotice-add' => 'Zêde bike',
 5786+ 'centralnotice-translations' => 'Wergerran',
 5787+ 'centralnotice-translate' => 'Wergerrîne',
 5788+ 'centralnotice-english' => 'Inglîzî',
 5789+ 'centralnotice-locked' => 'Hate astengkirin',
 5790+ 'centralnotice-day' => 'Roj',
 5791+ 'centralnotice-year' => 'Sal',
 5792+ 'centralnotice-month' => 'Meh',
 5793+ 'centralnotice-hours' => 'Saet',
 5794+ 'centralnotice-min' => 'Deqîqe',
 5795+ 'centralnotice-project-lang' => 'Zimanê projeyê',
 5796+ 'centralnotice-top-ten-languages' => 'Zimanên Top 10',
 5797+ 'centralnotice-project-name' => 'Navê projeyê',
 5798+ 'centralnotice-message' => 'Mesaj',
 5799+ 'centralnotice-clone-name' => 'Nav:',
 5800+ 'centralnotice-hide-button' => 'Lînkê veşêre',
 5801+ 'centralnotice-languages' => 'Ziman',
 5802+ 'centralnotice-country' => 'Welat',
 5803+);
 5804+
 5805+/** Cornish (Kernowek)
53915806 * @author Kernoweger
53925807 * @author Kw-Moon
53935808 */
@@ -5417,6 +5832,7 @@
54185833 'centralnotice-modify' => 'Späicheren',
54195834 'centralnotice-save-banner' => 'Banner späicheren',
54205835 'centralnotice-preview' => 'Weisen ouni ze späicheren',
 5836+ 'centralnotice-nopreview' => '(Kucken ouni ofzespäichere geet net)',
54215837 'centralnotice-add-new' => 'Eng nei zentral Matdeelung derbäisetzen',
54225838 'centralnotice-remove' => 'Ewechhuelen',
54235839 'centralnotice-translate-heading' => 'Iwwersetzung vu(n) $1',
@@ -5428,7 +5844,8 @@
54295845 'centralnotice-add-template' => 'E Banner derbäisetzen',
54305846 'centralnotice-show-notices' => 'Matdeelunge weisen',
54315847 'centralnotice-list-templates' => 'Lëscht vun de Banneren',
5432 - 'centralnotice-multiple' => 'méi ($1)',
 5848+ 'centralnotice-multiple-projects' => 'méi ($1)',
 5849+ 'centralnotice-multiple-languages' => 'méi ($1)',
54335850 'centralnotice-all-projects' => 'All Projeten',
54345851 'centralnotice-translations' => 'Iwwersetzungen',
54355852 'centralnotice-translate-to' => 'Iwwersetzen op',
@@ -5517,6 +5934,7 @@
55185935 'centralnotice-banner-type' => 'Bannertyp:',
55195936 'centralnotice-banner-hidable' => 'Statesch/Ka verstoppt ginn',
55205937 'centralnotice-banner-collapsible' => 'Aklappbar',
 5938+ 'centralnotice-banner-fundraising' => "Dëst ass e Banner vun enger Campagne fir Don'en ze sammelen",
55215939 'centralnotice-geotargeted' => 'Geografesch geziilt',
55225940 'centralnotice-countries' => 'Länner',
55235941 'centralnotice-allocation' => 'Dispositioun',
@@ -5531,6 +5949,7 @@
55325950 'centralnotice-documentwrite-error' => 'document.write() kann net bannen an engem Banner benotzt ginn.
55335951 Kuckt http://meta.wikimedia.org/wiki/Help:CentralNotice fir méi Informatiounen.',
55345952 'centralnotice-preferred' => 'Am léiwsten',
 5953+ 'centralnotice-logs' => 'Logbicher',
55355954 );
55365955
55375956 /** Lingua Franca Nova (Lingua Franca Nova)
@@ -5574,7 +5993,8 @@
55755994 'centralnotice-add-template' => 'Sjabloon biedoon',
55765995 'centralnotice-show-notices' => 'Sitemitdeilinge waergaeve',
55775996 'centralnotice-list-templates' => 'Sjablone waergaeve',
5578 - 'centralnotice-multiple' => 'meerdere ($1)',
 5997+ 'centralnotice-multiple-projects' => 'meerdere ($1)',
 5998+ 'centralnotice-multiple-languages' => 'meerdere ($1)',
55795999 'centralnotice-translations' => 'Euverzèttinge',
55806000 'centralnotice-translate-to' => 'Euverzètte nao',
55816001 'centralnotice-translate' => 'Euverzètte',
@@ -5677,6 +6097,7 @@
56786098 );
56796099
56806100 /** Lithuanian (Lietuvių)
 6101+ * @author Eitvys200
56816102 * @author Garas
56826103 * @author Matasg
56836104 */
@@ -5690,6 +6111,7 @@
56916112 'centralnotice-modify' => 'Pateikti',
56926113 'centralnotice-save-banner' => 'Įrašyti reklaminę juostą',
56936114 'centralnotice-preview' => 'Peržiūra',
 6115+ 'centralnotice-nopreview' => '(Peržiūra negalima)',
56946116 'centralnotice-add-new' => 'Pridėti naują kampaniją',
56956117 'centralnotice-remove' => 'Pašalinti',
56966118 'centralnotice-translate-heading' => '$1 vertimas',
@@ -5706,12 +6128,19 @@
57076129 'centralnotice-translate-to' => 'Išversti į',
57086130 'centralnotice-translate' => 'Išversti',
57096131 'centralnotice-english' => 'Anglų',
 6132+ 'centralnotice-banner-name' => 'Banerio pavadinimas:',
 6133+ 'centralnotice-banner' => 'Baneris',
 6134+ 'centralnotice-banner-heading' => 'Baneris: $1',
 6135+ 'centralnotice-templates' => 'Baneriai',
 6136+ 'centralnotice-locked' => 'Užrakintas',
 6137+ 'centralnotice-banner-doesnt-exist' => 'Baneris neegzistuoja.',
57106138 'centralnotice-day' => 'Diena',
57116139 'centralnotice-year' => 'Metai',
57126140 'centralnotice-month' => 'Mėnuo',
57136141 'centralnotice-hours' => 'Valanda',
57146142 'centralnotice-min' => 'Minutė',
57156143 'centralnotice-project-lang' => 'Projekto kalba',
 6144+ 'centralnotice-select' => 'Pasirinkite: $1',
57166145 'centralnotice-project-name' => 'Projekto pavadinimas',
57176146 'centralnotice-start-date' => 'Pradžios data',
57186147 'centralnotice-start-time' => 'Pradžios laikas (UTC)',
@@ -5748,6 +6177,13 @@
57496178 'centralnotice-preferred' => 'Pageidaujamas',
57506179 );
57516180
 6181+/** Latgalian (Latgaļu)
 6182+ * @author Dark Eagle
 6183+ */
 6184+$messages['ltg'] = array(
 6185+ 'centralnotice-message' => 'Viestejums',
 6186+);
 6187+
57526188 /** Latvian (Latviešu)
57536189 * @author Papuass
57546190 */
@@ -5761,6 +6197,7 @@
57626198 'centralnotice-add-notice' => 'Pievienot kampaņu',
57636199 'centralnotice-edit-notice' => 'Labot kampaņu',
57646200 'centralnotice-show-notices' => 'Rādīt kampaņas',
 6201+ 'centralnotice-all-projects' => 'Visi projekti',
57656202 'centralnotice-translations' => 'Tulkojumi',
57666203 'centralnotice-translate-to' => 'Tulkot uz',
57676204 'centralnotice-translate' => 'Tulkot',
@@ -5788,6 +6225,8 @@
57896226 'centralnotice-banner-anonymous' => 'Anonīmiem lietotājiem',
57906227 'centralnotice-banner-logged-in' => 'Lietotājiem, kas pieslēgušies',
57916228 'centralnotice-countries' => 'Valstis',
 6229+ 'centralnotice-languages' => 'Valodas',
 6230+ 'centralnotice-projects' => 'Projekti',
57926231 'centralnotice-country' => 'Valsts',
57936232 );
57946233
@@ -5797,6 +6236,7 @@
57986237 $messages['mg'] = array(
57996238 'centralnotice' => "Fandrindàn'ny toerana fampandrenesana",
58006239 'noticetemplate' => "Endrin'ny toerana fampandrenesana",
 6240+ 'action-centralnotice-admin' => "mikojakoja n'io hafatra io",
58016241 'centralnotice-desc' => "Manampy toerana fampandrenesana amin'ilay tranonkala",
58026242 'centralnotice-query' => 'Ovay ny fampandrenesana misy ankehitriny',
58036243 'centralnotice-notice-name' => "Anaran'ilay fampandrenesana",
@@ -5848,9 +6288,6 @@
58496289 'centralnotice-message' => 'Hafatra',
58506290 'centralnotice-clone' => 'Avereno dikao',
58516291 'centralnotice-clone-notice' => "Angala-tahaka n'ilay endrika",
5852 - 'right-centralnotice-translate' => 'dikao teny ny hafatra',
5853 - 'action-centralnotice-admin' => "mikojakoja n'io hafatra io",
5854 - 'action-centralnotice-translate' => 'dikao teny ny fampandrenesana',
58556292 'centralnotice-preferred' => 'Ny tiako/ny tianao/Ny tiny',
58566293 );
58576294
@@ -5862,6 +6299,7 @@
58636300 'centralnotice' => 'Администратор на централни известувања',
58646301 'noticetemplate' => 'Администратор на централни известувања',
58656302 'bannerallocation' => 'Администратор на централни известувања',
 6303+ 'centralnoticelogs' => 'Администратор на централни известувања',
58666304 'right-centralnotice-admin' => 'Раководење со централни известувања',
58676305 'action-centralnotice-admin' => 'раководење со централни известувања',
58686306 'centralnotice-desc' => 'Централизирано известување',
@@ -5874,6 +6312,7 @@
58756313 'centralnotice-modify' => 'Испрати',
58766314 'centralnotice-save-banner' => 'Зачувај плакат',
58776315 'centralnotice-preview' => 'Преглед',
 6316+ 'centralnotice-nopreview' => '(Прегледот не е достапен)',
58786317 'centralnotice-add-new' => 'Додај ново централно известување',
58796318 'centralnotice-remove' => 'Тргни',
58806319 'centralnotice-translate-heading' => 'Превод на $1',
@@ -5885,7 +6324,8 @@
58866325 'centralnotice-add-template' => 'Додај шаблон',
58876326 'centralnotice-show-notices' => 'Прикажи известувања',
58886327 'centralnotice-list-templates' => 'Наведи шаблони',
5889 - 'centralnotice-multiple' => 'повеќе ($1)',
 6328+ 'centralnotice-multiple-projects' => 'повеќе ($1)',
 6329+ 'centralnotice-multiple-languages' => 'повеќе ($1)',
58906330 'centralnotice-all-projects' => 'Сите проекти',
58916331 'centralnotice-translations' => 'Преводи',
58926332 'centralnotice-translate-to' => 'Преведи на',
@@ -5974,6 +6414,9 @@
59756415 'centralnotice-banner-type' => 'Тип на плакат:',
59766416 'centralnotice-banner-hidable' => 'Статичен/Склоплив',
59776417 'centralnotice-banner-collapsible' => 'Расклоплив',
 6418+ 'centralnotice-banner-fundraising' => 'Ова е плакат за прибирање на средства',
 6419+ 'centralnotice-banner-fundraising-help' => 'Создајте ознака за вкотвување во содржината на плакатот со id="cn_fundraising_link" и внесете една или повеќе целни страници, како на пр. „JimmyAppeal01“. href на врската ќе се исконструира автоматски.',
 6420+ 'centralnotice-banner-landing-pages' => 'Целни страници (одделени со запирки):',
59786421 'centralnotice-geotargeted' => 'Геобележано',
59796422 'centralnotice-countries' => 'Земји',
59806423 'centralnotice-allocation' => 'Распределба',
@@ -5987,6 +6430,8 @@
59886431 'centralnotice-percentage' => 'Постоток',
59896432 'centralnotice-documentwrite-error' => 'document.write() не може да се користи во рамките на плаЗа повеќе информации, погледајте ја страницата http://meta.wikimedia.org/wiki/Help:CentralNotice',
59906433 'centralnotice-preferred' => 'Претпочитано',
 6434+ 'centralnotice-logs' => 'Дневници',
 6435+ 'centralnotice-view-logs' => 'Погл. дневници',
59916436 );
59926437
59936438 /** Malayalam (മലയാളം)
@@ -5997,6 +6442,7 @@
59986443 'centralnotice' => 'കേന്ദ്രീകൃത അറിയിപ്പ് കാര്യനിർവാഹകൻ',
59996444 'noticetemplate' => 'കേന്ദ്രീകൃത അറിയിപ്പ് കാര്യനിർവാഹകൻ',
60006445 'bannerallocation' => 'കേന്ദ്രീകൃത അറിയിപ്പ് കാര്യനിർവാഹകൻ',
 6446+ 'centralnoticelogs' => 'കേന്ദ്രീകൃത അറിയിപ്പ് കാര്യനിർവാഹകൻ',
60016447 'right-centralnotice-admin' => 'കേന്ദ്രീകൃത അറിയിപ്പുകൾ കൈകാര്യം ചെയ്യുക',
60026448 'action-centralnotice-admin' => 'കേന്ദ്രീകൃത അറിയിപ്പുകൾ കൈകാര്യം ചെയ്യുക',
60036449 'centralnotice-desc' => 'കേന്ദീകൃത സൈറ്റ്നോട്ടീസ് ചേർക്കുന്നു',
@@ -6009,6 +6455,7 @@
60106456 'centralnotice-modify' => 'സമർപ്പിക്കുക',
60116457 'centralnotice-save-banner' => 'എഴുത്തുപട്ട സേവ് ചെയ്യുക',
60126458 'centralnotice-preview' => 'എങ്ങനെയുണ്ടെന്നു കാണുക',
 6459+ 'centralnotice-nopreview' => '(പ്രിവ്യൂ ലഭ്യമല്ല)',
60136460 'centralnotice-add-new' => 'പുതിയൊരു കേന്ദ്രീകൃത അറിയിപ്പ് ചേർക്കുക',
60146461 'centralnotice-remove' => 'നീക്കം ചെയ്യുക',
60156462 'centralnotice-translate-heading' => '$1 എന്നതിനുള്ള തർജ്ജമ',
@@ -6020,7 +6467,8 @@
60216468 'centralnotice-add-template' => 'ഫലകം കൂട്ടിച്ചേർക്കുക',
60226469 'centralnotice-show-notices' => 'അറിയിപ്പുകൾ പ്രദർശിപ്പിക്കുക',
60236470 'centralnotice-list-templates' => 'ഫലകങ്ങൾ പട്ടികവത്കരിക്കുക',
6024 - 'centralnotice-multiple' => 'നിരവധി ($1)',
 6471+ 'centralnotice-multiple-projects' => 'നിരവധി ($1)',
 6472+ 'centralnotice-multiple-languages' => 'നിരവധി ($1)',
60256473 'centralnotice-all-projects' => 'എല്ലാ പദ്ധതികളും',
60266474 'centralnotice-translations' => 'തർജ്ജമകൾ',
60276475 'centralnotice-translate-to' => 'ഇതിലേയ്ക്ക് തർജ്ജമ ചെയ്യുക',
@@ -6109,6 +6557,8 @@
61106558 'centralnotice-banner-type' => 'എഴുത്തുപട്ടയുടെ തരം:',
61116559 'centralnotice-banner-hidable' => 'സ്ഥിരസ്ഥിതി/മറയ്ക്കാവുന്നത്',
61126560 'centralnotice-banner-collapsible' => 'ചുരുക്കാവുന്നത്',
 6561+ 'centralnotice-banner-fundraising' => 'ഇത് ഫണ്ട്‌റൈസിങ് എഴുത്തുപട്ടയാണ്',
 6562+ 'centralnotice-banner-landing-pages' => 'എത്തിച്ചേരേണ്ട താളുകൾ (അങ്കുശത്താൽ വേർതിരിച്ച്):',
61136563 'centralnotice-geotargeted' => 'ഭൂപ്രദേശങ്ങൾ ലക്ഷ്യമാക്കിയവ',
61146564 'centralnotice-countries' => 'രാജ്യങ്ങൾ',
61156565 'centralnotice-allocation' => 'വിന്യാസം',
@@ -6123,6 +6573,8 @@
61246574 'centralnotice-documentwrite-error' => 'എഴുത്തുപട്ടയിൽ document.write() ഉപയോഗിക്കാനാവില്ല.
61256575 കൂടുതൽ വിവരങ്ങൾക്ക് http://meta.wikimedia.org/wiki/Help:CentralNotice കാണുക',
61266576 'centralnotice-preferred' => 'അഭിലഷണീയമായുള്ളത്',
 6577+ 'centralnotice-logs' => 'പ്രവർത്തനരേഖകൾ',
 6578+ 'centralnotice-view-logs' => 'പ്രവർത്തനരേഖകൾ കാണുക',
61276579 );
61286580
61296581 /** Mongolian (Монгол)
@@ -6134,25 +6586,28 @@
61356587 );
61366588
61376589 /** Marathi (मराठी)
 6590+ * @author Htt
61386591 * @author Mahitgar
61396592 * @author V.narsikar
61406593 */
61416594 $messages['mr'] = array(
 6595+ 'right-centralnotice-admin' => 'मध्यवर्ती सूचनांचे प्रबंधन करा',
 6596+ 'action-centralnotice-admin' => 'मध्यवर्ती सूचनांचे प्रबंधन करा',
61426597 'centralnotice-desc' => 'संकेतस्थळाचा मध्यवर्ती सूचना फलक',
6143 - 'centralnotice-end-date' => 'अंतिम तारीख',
 6598+ 'centralnotice-end-date' => 'अंतिम दिनांक',
61446599 'centralnotice-add-new' => 'नव्या मोहीमेची सुरूवात करा',
61456600 'centralnotice-translate-heading' => '$1 चे भाषांतर',
61466601 'centralnotice-manage' => 'मोहीम हाताळा',
61476602 'centralnotice-add-notice' => 'नव्या मोहीमेची भर घाला',
61486603 'centralnotice-add-template' => 'नविन मथळा लावा',
61496604 'centralnotice-translations' => 'भाषांतरे',
6150 - 'centralnotice-translate-to' => '(Language name) या भाषेत भाषांतर करा',
 6605+ 'centralnotice-translate-to' => 'या भाषेत भाषांतर करा',
61516606 'centralnotice-banner-name' => 'मथळ्याचे नाव',
61526607 'centralnotice-day' => 'दिनांक',
61536608 'centralnotice-hours' => 'तास',
61546609 'centralnotice-project-lang' => 'प्रकल्प भाषा',
61556610 'centralnotice-project-name' => 'प्रकल्पाचे नाव',
6156 - 'centralnotice-start-date' => 'सुरू केल्याचा दिनांक',
 6611+ 'centralnotice-start-date' => 'सुरूवात दिनांक',
61576612 'centralnotice-start-time' => 'सुरू केल्याची वेळ (युटीसी)',
61586613 'centralnotice-no-templates' => 'मथळे सापडले नाहीत.काहींची भर घाला',
61596614 'centralnotice-available-templates' => 'उपलब्ध मथळे',
@@ -6164,23 +6619,20 @@
61656620 ही कृती परतविता येणार नाही.',
61666621 'centralnotice-no-notices-exist' => 'मथळा अस्तित्वात नाही.
61676622 एक मथळा खाली जोडा.',
6168 - 'centralnotice-no-templates-translate' => '↓ भाषांतरे संपादीत करण्याकरिता कोणतेही मुखशीर्षक (बॅनर) उपलब्ध नाही',
6169 - 'centralnotice-number-uses' => '↓ उपयोग',
6170 - 'centralnotice-edit-template' => '↓ मुखशीर्षक (बॅनर) संपादीत करा',
6171 - 'centralnotice-edit-template-summary' => '↓ स्थानिकीकरण संदेश तयार करण्याकरिता, तीहेरी महिरपीकंस संयोगचिन्ह(-) असलेले सूत्राने (स्ट्रींग)भरा, उदाहरणार्थ. {{{jimbo-quote}}}.',
 6623+ 'centralnotice-no-templates-translate' => 'भाषांतरे संपादीत करण्याकरिता कोणतेही मुखशीर्षक (बॅनर) उपलब्ध नाही',
 6624+ 'centralnotice-number-uses' => 'उपयोग',
 6625+ 'centralnotice-edit-template' => 'मुखशीर्षक (बॅनर) संपादीत करा',
 6626+ 'centralnotice-edit-template-summary' => 'स्थानिकीकरण संदेश तयार करण्याकरिता, तीहेरी महिरपीकंस संयोगचिन्ह(-) असलेले सूत्राने (स्ट्रींग)भरा, उदाहरणार्थ. {{{jimbo-quote}}}.',
61726627 'centralnotice-message' => 'संदेश',
6173 - 'centralnotice-message-not-set' => '↓ संदेश स्थापित केलेला नाही',
6174 - 'centralnotice-clone' => '↓ कृत्तक (क्लोन)',
6175 - 'centralnotice-clone-notice' => '↓ मुखशीर्षकाची(बॅनरची प्रत बनवा)',
6176 - 'centralnotice-preview-all-template-translations' => '↓ मुखशीर्षकांच्या सर्व उपलब्ध भाषांतराची झलक पहा',
6177 - 'right-centralnotice-admin' => '↓ मध्यवर्ती सूचनांचे प्रबंधन करा',
6178 - 'right-centralnotice-translate' => '↓ मध्यवर्ती सूचनांचे भाषांतरकरा',
6179 - 'action-centralnotice-admin' => 'मध्यवर्ती सूचनांचे प्रबंधन करा',
6180 - 'action-centralnotice-translate' => 'मध्यवर्ती सूचनांचे भाषांतरकरा',
 6628+ 'centralnotice-message-not-set' => 'संदेश स्थापित केलेला नाही',
 6629+ 'centralnotice-clone' => 'कृत्तक (क्लोन)',
 6630+ 'centralnotice-clone-notice' => 'मुखशीर्षकाची(बॅनरची प्रत बनवा)',
 6631+ 'centralnotice-preview-all-template-translations' => 'मुखशीर्षकांच्या सर्व उपलब्ध भाषांतराची झलक पहा',
61816632 'centralnotice-preferred' => 'प्राधान्य',
61826633 );
61836634
61846635 /** Malay (Bahasa Melayu)
 6636+ * @author Anakmalaysia
61856637 * @author Aurora
61866638 * @author Aviator
61876639 * @author Izzudin
@@ -6188,35 +6640,46 @@
61896641 $messages['ms'] = array(
61906642 'centralnotice' => 'Pentadbiran pemberitahuan pusat',
61916643 'noticetemplate' => 'Pentadbiran pemberitahuan pusat',
 6644+ 'right-centralnotice-admin' => 'Mengurus pemberitahuan pusat',
 6645+ 'action-centralnotice-admin' => 'mengurus pemberitahuan pusat',
61926646 'centralnotice-desc' => 'Menambah pemberitahuan pusat',
61936647 'centralnotice-summary' => 'Anda boleh menggunakan modul ini untuk menyunting pemberitahuan pusat yang disediakan. Anda juga boleh menambah atau membuang pemberitahuan yang lama.',
61946648 'centralnotice-query' => 'Ubah suai pemberitahuan semasa',
61956649 'centralnotice-notice-name' => 'Nama pemberitahuan',
61966650 'centralnotice-end-date' => 'Tarikh tamat',
6197 - 'centralnotice-enabled' => 'Boleh',
6198 - 'centralnotice-modify' => 'Serah',
 6651+ 'centralnotice-enabled' => 'Dihidupkan',
 6652+ 'centralnotice-modify' => 'Serahkan',
61996653 'centralnotice-preview' => 'Pralihat',
 6654+ 'centralnotice-nopreview' => '(Tiada pralihat)',
62006655 'centralnotice-add-new' => 'Tambah pemberitahuan pusat baru',
62016656 'centralnotice-remove' => 'Buang',
62026657 'centralnotice-translate-heading' => 'Penterjemahan $1',
62036658 'centralnotice-manage' => 'Urus pemberitahuan pusat',
6204 - 'centralnotice-add' => 'Tambah',
 6659+ 'centralnotice-add' => 'Tambahkan',
62056660 'centralnotice-add-notice' => 'Tambah pemberitahuan',
62066661 'centralnotice-add-template' => 'Tambah templat',
62076662 'centralnotice-show-notices' => 'Papar pemberitahuan',
62086663 'centralnotice-list-templates' => 'Senarai templat',
 6664+ 'centralnotice-multiple-projects' => 'Berbilang ($1)',
 6665+ 'centralnotice-multiple-languages' => 'Berbilang ($1)',
 6666+ 'centralnotice-all-projects' => 'Semua projek',
62096667 'centralnotice-translations' => 'Terjemahan',
62106668 'centralnotice-translate-to' => 'Terjemah',
62116669 'centralnotice-translate' => 'Terjemah',
62126670 'centralnotice-english' => 'Bahasa Inggeris',
6213 - 'centralnotice-banner-name' => 'Nama templat',
 6671+ 'centralnotice-banner-name' => 'Nama sepanduk:',
 6672+ 'centralnotice-banner' => 'Sepanduk',
 6673+ 'centralnotice-banner-heading' => 'Sepanduk: $1',
62146674 'centralnotice-templates' => 'Templat',
62156675 'centralnotice-weight' => 'Berat',
62166676 'centralnotice-locked' => 'Dikunci',
 6677+ 'centralnotice-notice' => 'Kempen',
 6678+ 'centralnotice-notice-heading' => 'Kempen: $1',
62176679 'centralnotice-notices' => 'Pemberitahuan',
62186680 'centralnotice-notice-exists' => 'Pemberitahuan telah pun wujud dan tidak ditambah.',
62196681 'centralnotice-template-exists' => 'Templat telah pun wujud dan tidak ditambah.',
6220 - 'centralnotice-notice-doesnt-exist' => 'Pemberitahuan tidak wujud untuk dibuang.',
 6682+ 'centralnotice-notice-doesnt-exist' => 'Kempen tidak wujud.',
 6683+ 'centralnotice-banner-doesnt-exist' => 'Sepanduk tak wujud.',
62216684 'centralnotice-template-still-bound' => 'Templat masih digunakan untuk pemberitahuan dan tidak dibuang.',
62226685 'centralnotice-template-body' => 'Kandungan templat:',
62236686 'centralnotice-day' => 'Hari',
@@ -6225,9 +6688,12 @@
62266689 'centralnotice-hours' => 'Jam',
62276690 'centralnotice-min' => 'Minit',
62286691 'centralnotice-project-lang' => 'Bahasa projek',
 6692+ 'centralnotice-select' => 'Pilih: $1',
 6693+ 'centralnotice-top-ten-languages' => '10 bahasa teratas',
62296694 'centralnotice-project-name' => 'Nama projek',
62306695 'centralnotice-start-date' => 'Tarikh mula',
62316696 'centralnotice-start-time' => 'Waktu mula (UTC)',
 6697+ 'centralnotice-end-time' => 'Waktu tamat (UTC)',
62326698 'centralnotice-assigned-templates' => 'Templat ditugasi',
62336699 'centralnotice-no-templates' => 'Tiada templat. Sila cipta templat baru.',
62346700 'centralnotice-no-templates-assigned' => 'Tiada templat untuk pemberitahuan. Tambah templat baru!',
@@ -6244,16 +6710,22 @@
62456711 'centralnotice-no-notices-exist' => 'Tiada pemberitahuan. Anda boleh menambahnya di bawah.',
62466712 'centralnotice-no-templates-translate' => 'Tiada templat untuk diterjemah',
62476713 'centralnotice-number-uses' => 'Penggunaan',
 6714+ 'centralnotice-settings' => 'Tetapan',
62486715 'centralnotice-edit-template' => 'Sunting templat',
62496716 'centralnotice-message' => 'Pesanan',
62506717 'centralnotice-message-not-set' => 'Pesanan tidak ditetapkan',
62516718 'centralnotice-clone' => 'Salin',
62526719 'centralnotice-clone-notice' => 'Buat salinan templat ini',
 6720+ 'centralnotice-clone-name' => 'Nama:',
62536721 'centralnotice-preview-all-template-translations' => 'Pratonton semua terjemahan yang ada bagi templat ini',
6254 - 'right-centralnotice-admin' => 'Mengurus pemberitahuan pusat',
6255 - 'right-centralnotice-translate' => 'Menterjemah pemberitahuan pusat',
6256 - 'action-centralnotice-admin' => 'mengurus pemberitahuan pusat',
6257 - 'action-centralnotice-translate' => 'menterjemah pemberitahuan pusat',
 6722+ 'centralnotice-insert' => 'Masukkan: $1',
 6723+ 'centralnotice-hide-button' => 'Sorokkan pautan',
 6724+ 'centralnotice-collapse-button' => 'Lipat pautan',
 6725+ 'centralnotice-expand-button' => 'Bentangkan pautan',
 6726+ 'centralnotice-close-button' => 'Butang tutup',
 6727+ 'centralnotice-translate-button' => 'Pautan bantu menterjemah',
 6728+ 'centralnotice-languages' => 'Bahasa',
 6729+ 'centralnotice-country' => 'Negara',
62586730 'centralnotice-preferred' => 'Dipilih',
62596731 );
62606732
@@ -6262,7 +6734,7 @@
62636735 */
62646736 $messages['mt'] = array(
62656737 'centralnotice-add-template' => 'Żid mudell',
6266 - 'centralnotice-banner-name' => 'Isem tal-mudell',
 6738+ 'centralnotice-banner-name' => "Isem tal-''banner'':",
62676739 'centralnotice-number-uses' => 'Użi',
62686740 'centralnotice-message' => 'Messaġġ',
62696741 );
@@ -6274,6 +6746,8 @@
62756747 'centralnotice-add' => 'Поладомс',
62766748 'centralnotice-add-template' => 'Поладомс лопа парцун',
62776749 'centralnotice-translations' => 'Ютавтомат',
 6750+ 'centralnotice-translate-to' => 'Ютавтомс $1 келентень',
 6751+ 'centralnotice-translate' => 'Ютавтомс',
62786752 'centralnotice-banner-name' => 'Баннеранть лемезэ:',
62796753 'centralnotice-templates' => 'Лопа парцунт',
62806754 'centralnotice-weight' => 'Сталмо',
@@ -6299,12 +6773,28 @@
63006774 'centralnotice-country' => 'Мастор',
63016775 );
63026776
 6777+/** Nahuatl (Nāhuatl)
 6778+ * @author Teòtlalili
 6779+ */
 6780+$messages['nah'] = array(
 6781+ 'centralnotice-translate-to' => 'Motlâtòlkuepas ìka',
 6782+ 'centralnotice-translate' => 'Motlâtòlkuepas',
 6783+ 'centralnotice-day' => 'Tònalli',
 6784+ 'centralnotice-year' => 'Xiwitl',
 6785+ 'centralnotice-month' => 'Mètztli',
 6786+ 'centralnotice-hours' => 'Ìmantli',
 6787+ 'centralnotice-project-lang' => 'Ìtlâtòl tlayekàntekitl',
 6788+ 'centralnotice-select' => 'Motlapêpenìs: $1',
 6789+);
 6790+
63036791 /** Low German (Plattdüütsch)
63046792 * @author Slomox
63056793 */
63066794 $messages['nds'] = array(
63076795 'centralnotice' => 'Sitenotice verwalten',
63086796 'noticetemplate' => 'Vörlaag för Sitenotice',
 6797+ 'right-centralnotice-admin' => 'Zentrale Siedennotiz verwalten',
 6798+ 'action-centralnotice-admin' => 'zentrale Siedennotiz verwalten',
63096799 'centralnotice-desc' => 'Föögt en zentrale Naricht för de Websteed to',
63106800 'centralnotice-summary' => 'Dit Modul verlöövt di dat Ännern vun de Instellungen för Sitenotice.
63116801 Dat kann ok bruukt warrn, üm Sitenotices totofögen oder ruttonehmen.',
@@ -6381,10 +6871,6 @@
63826872 'centralnotice-clone' => 'Koperen',
63836873 'centralnotice-clone-notice' => 'En Kopie vun de Vörlaag maken',
63846874 'centralnotice-preview-all-template-translations' => 'All vörhannen Översetten vun en Vörlaag ankieken',
6385 - 'right-centralnotice-admin' => 'Zentrale Siedennotiz verwalten',
6386 - 'right-centralnotice-translate' => 'Zentrale Siedennotiz översetten',
6387 - 'action-centralnotice-admin' => 'zentrale Siedennotiz verwalten',
6388 - 'action-centralnotice-translate' => 'zentrale Siedennotiz översetten',
63896875 'centralnotice-preferred' => 'Vörtagen',
63906876 );
63916877
@@ -6400,14 +6886,43 @@
64016887 'centralnotice-change-lang' => 'Taal dee-j vertalen willen wiezigen',
64026888 );
64036889
 6890+/** Nepali (नेपाली)
 6891+ * @author Bhawani Gautam Rhk
 6892+ */
 6893+$messages['ne'] = array(
 6894+ 'centralnotice-end-date' => 'समाप्ति तिथि',
 6895+ 'centralnotice-preview' => 'पूर्वालोकन',
 6896+ 'centralnotice-add' => 'थप्ने',
 6897+ 'centralnotice-translations' => 'अनुवाद',
 6898+ 'centralnotice-translate-to' => 'अनुवाद गर्ने यसमा',
 6899+ 'centralnotice-weight' => 'ओजन',
 6900+ 'centralnotice-day' => 'दिन',
 6901+ 'centralnotice-year' => 'वर्ष',
 6902+ 'centralnotice-month' => 'महिना',
 6903+ 'centralnotice-hours' => 'घण्टा',
 6904+ 'centralnotice-min' => 'मिनट',
 6905+ 'centralnotice-project-lang' => 'परियोजना भाषा',
 6906+ 'centralnotice-select' => '$1 चुन्ने',
 6907+ 'centralnotice-start-date' => 'सुरुको तिथि',
 6908+ 'centralnotice-start-time' => 'सुरुको तिथि (UTC)',
 6909+ 'centralnotice-message' => 'सन्देश',
 6910+ 'centralnotice-message-not-set' => 'सन्देश व्यवस्थित व्यवस्थित गरिएकोछैन',
 6911+ 'centralnotice-clone-name' => 'नाम:',
 6912+ 'centralnotice-close-button' => 'बटन बन्द गर्ने',
 6913+ 'centralnotice-languages' => 'भाषाहरु',
 6914+);
 6915+
64046916 /** Dutch (Nederlands)
 6917+ * @author Romaine
 6918+ * @author SPQRobin
64056919 * @author Siebrand
64066920 * @author Tvdm
64076921 */
64086922 $messages['nl'] = array(
6409 - 'centralnotice' => 'Beheer centrale sitenotice',
 6923+ 'centralnotice' => 'Centrale sitenotice beheren',
64106924 'noticetemplate' => 'Centrale sitenotice beheren',
64116925 'bannerallocation' => 'Centrale sitenotice beheren',
 6926+ 'centralnoticelogs' => 'Centrale sitenotice beheren',
64126927 'right-centralnotice-admin' => 'Centrale sitenotices beheren',
64136928 'action-centralnotice-admin' => 'centrale sitenotices beheren',
64146929 'centralnotice-desc' => 'Voegt een centrale sitemededeling toe',
@@ -6420,6 +6935,7 @@
64216936 'centralnotice-modify' => 'Opslaan',
64226937 'centralnotice-save-banner' => 'Banner opslaan',
64236938 'centralnotice-preview' => 'Voorvertoning',
 6939+ 'centralnotice-nopreview' => '(Voorvertoning niet beschikbaar)',
64246940 'centralnotice-add-new' => 'Nieuwe centrale sitenotice toevoegen',
64256941 'centralnotice-remove' => 'Verwijderen',
64266942 'centralnotice-translate-heading' => 'Vertaling voor $1',
@@ -6431,7 +6947,8 @@
64326948 'centralnotice-add-template' => 'Sjabloon toevoegen',
64336949 'centralnotice-show-notices' => 'Sitenotices weergeven',
64346950 'centralnotice-list-templates' => 'Sjablonen weergeven',
6435 - 'centralnotice-multiple' => 'meerdere ($1)',
 6951+ 'centralnotice-multiple-projects' => 'meerdere ($1)',
 6952+ 'centralnotice-multiple-languages' => 'meerdere ($1)',
64366953 'centralnotice-all-projects' => 'Alle projecten',
64376954 'centralnotice-translations' => 'Vertalingen',
64386955 'centralnotice-translate-to' => 'Vertalen naar',
@@ -6457,7 +6974,7 @@
64586975 'centralnotice-notice-doesnt-exist' => 'De campagne bestaat niet.',
64596976 'centralnotice-remove-notice-doesnt-exist' => 'De campagne bestaat niet.
64606977 Er is niets te verwijderen',
6461 - 'centralnotice-banner-doesnt-exist' => 'DE banner bestaat niet.',
 6978+ 'centralnotice-banner-doesnt-exist' => 'De banner bestaat niet.',
64626979 'centralnotice-template-still-bound' => 'Het sjabloon is nog gekoppeld aan een sitenotice.
64636980 Het wordt niet verwijderd.',
64646981 'centralnotice-template-body' => 'Sjablooninhoud:',
@@ -6521,6 +7038,9 @@
65227039 'centralnotice-banner-type' => 'Bannertype:',
65237040 'centralnotice-banner-hidable' => 'Statisch/te verbergen',
65247041 'centralnotice-banner-collapsible' => 'In te klappen',
 7042+ 'centralnotice-banner-fundraising' => 'Dit is een fondsenwervingsbanner',
 7043+ 'centralnotice-banner-fundraising-help' => 'Maak een ankertag in de body van de banner met id="cn_fundraising_link" en voer hieronder een of meer bestemmingspagina\'s in, bijvoorbeeld "JimmyAppeal01". De href voor de verwijzing wordt automatisch geconstrueerd.',
 7044+ 'centralnotice-banner-landing-pages' => "Landingspagina's (kommagescheiden):",
65257045 'centralnotice-geotargeted' => 'Geografische doelen',
65267046 'centralnotice-countries' => 'Landen',
65277047 'centralnotice-allocation' => 'Toewijzing',
@@ -6535,6 +7055,8 @@
65367056 'centralnotice-documentwrite-error' => 'document.write() kan niet worden gebruikt binnen een banner.
65377057 Zie http://meta.wikimedia.org/wiki/Help:CentralNotice voor meer informatie.',
65387058 'centralnotice-preferred' => 'Voorkeur',
 7059+ 'centralnotice-logs' => 'Logboeken',
 7060+ 'centralnotice-view-logs' => 'Logboeken bekijken',
65397061 );
65407062
65417063 /** Norwegian Nynorsk (‪Norsk (nynorsk)‬)
@@ -6544,6 +7066,8 @@
65457067 $messages['nn'] = array(
65467068 'centralnotice' => 'Administrasjon av sentrale merknader',
65477069 'noticetemplate' => 'Mal for sentrale merknader',
 7070+ 'right-centralnotice-admin' => 'Handtera sentrale merknader',
 7071+ 'action-centralnotice-admin' => 'handtera sentrale merknader',
65487072 'centralnotice-desc' => 'Legg til ein sentral sidemerknad',
65497073 'centralnotice-summary' => 'Denne modulen lèt deg endra dine noverande sentralmerknader.
65507074 Han kan òg bli nytta til å leggja til eller fjerna gamle merknader.',
@@ -6615,10 +7139,6 @@
66167140 'centralnotice-preview-all-template-translations' => 'Førehandsvis alle tilgjengelege omsetjingar av malen',
66177141 'centralnotice-insert' => 'Sett inn: $1',
66187142 'centralnotice-country' => 'Land',
6619 - 'right-centralnotice-admin' => 'Handtera sentrale merknader',
6620 - 'right-centralnotice-translate' => 'Omsetja sentrale merknader',
6621 - 'action-centralnotice-admin' => 'handtera sentrale merknader',
6622 - 'action-centralnotice-translate' => 'omsetja sentrale merknader',
66237143 'centralnotice-preferred' => 'Føretrukke',
66247144 );
66257145
@@ -6644,6 +7164,7 @@
66457165 'centralnotice-modify' => 'Lagre',
66467166 'centralnotice-save-banner' => 'Lagre banner',
66477167 'centralnotice-preview' => 'Forhåndsvisning',
 7168+ 'centralnotice-nopreview' => '(Forhåndsvisning ikke tilgjengelig)',
66487169 'centralnotice-add-new' => 'Legg til en ny sentralmelding',
66497170 'centralnotice-remove' => 'Fjern',
66507171 'centralnotice-translate-heading' => 'Oversettelse for $1',
@@ -6655,7 +7176,8 @@
66567177 'centralnotice-add-template' => 'Legg til en mal',
66577178 'centralnotice-show-notices' => 'Vis meldinger',
66587179 'centralnotice-list-templates' => 'Vis maler',
6659 - 'centralnotice-multiple' => 'flere ($1)',
 7180+ 'centralnotice-multiple-projects' => 'flere ($1)',
 7181+ 'centralnotice-multiple-languages' => 'flere ($1)',
66607182 'centralnotice-all-projects' => 'Alle prosjekter',
66617183 'centralnotice-translations' => 'Oversettelser',
66627184 'centralnotice-translate-to' => 'Oversett til',
@@ -6766,6 +7288,8 @@
67677289 $messages['oc'] = array(
67687290 'centralnotice' => 'Administracion de las notificacions centralas',
67697291 'noticetemplate' => 'Modèls de las notificacions centralas',
 7292+ 'right-centralnotice-admin' => 'Gerís las notificacions centralas',
 7293+ 'action-centralnotice-admin' => 'gerir las notificacions centralas',
67707294 'centralnotice-desc' => 'Apond un sitenotice central',
67717295 'centralnotice-summary' => 'Aqueste modul vos permet de modificar vòstres paramètres de las notificacions centralas.',
67727296 'centralnotice-query' => 'Modificar las notificacions actualas',
@@ -6841,13 +7365,41 @@
68427366 'centralnotice-clone' => 'Clonar',
68437367 'centralnotice-clone-notice' => "Crear una còpia d'aqueste modèl",
68447368 'centralnotice-preview-all-template-translations' => "Previsualizar totas las traduccions d'aqueste modèl",
6845 - 'right-centralnotice-admin' => 'Gerís las notificacions centralas',
6846 - 'right-centralnotice-translate' => 'Traduire las notificacions centralas',
6847 - 'action-centralnotice-admin' => 'gerir las notificacions centralas',
6848 - 'action-centralnotice-translate' => 'traduire las notificacions centralas',
68497369 'centralnotice-preferred' => 'Preferit',
68507370 );
68517371
 7372+/** Oriya (ଓଡ଼ିଆ)
 7373+ * @author Odisha1
 7374+ * @author Psubhashish
 7375+ */
 7376+$messages['or'] = array(
 7377+ 'centralnotice-enabled' => 'ସଚଳ କରାଗଲା',
 7378+ 'centralnotice-modify' => 'ଦାଖଲ କରିବା',
 7379+ 'centralnotice-save-banner' => 'ବ୍ୟାନରଟିକୁ ସାଇତିବା',
 7380+ 'centralnotice-preview' => 'ସାଇତିବା ଆଗରୁ ଦେଖଣା',
 7381+ 'centralnotice-nopreview' => '(ଆଗଦେଖଣା ମିଳୁନାହିଁ)',
 7382+ 'centralnotice-add-new' => 'ନୂଆ କାମଟିଏ ଯୋଡିବା',
 7383+ 'centralnotice-remove' => 'ବାହାର କରିବା',
 7384+ 'centralnotice-translate-heading' => '$1 ପାଇଁ ଅନୁବାଦ',
 7385+ 'centralnotice-template-body' => 'ବ୍ୟାନର ଭିତର:',
 7386+ 'centralnotice-day' => 'ଦିନ',
 7387+ 'centralnotice-year' => 'ବର୍ଷ',
 7388+ 'centralnotice-month' => 'ମାସ',
 7389+ 'centralnotice-hours' => 'ଘଣ୍ଟା',
 7390+ 'centralnotice-min' => 'ମିନିଟ',
 7391+ 'centralnotice-project-lang' => 'ପ୍ରକଳ୍ପ ଭାଷା',
 7392+ 'centralnotice-select' => 'ବାଛିବା: $1',
 7393+ 'centralnotice-top-ten-languages' => '୧୦ ଟି ନାଆଁକରା ଭାଷା',
 7394+ 'centralnotice-project-name' => 'ପ୍ରକଳ୍ପ ନାଆଁ',
 7395+ 'centralnotice-start-date' => 'ଆରମ୍ଭ ତାରିଖ',
 7396+ 'centralnotice-number-uses' => 'ବ୍ୟବହାର',
 7397+ 'centralnotice-clone-name' => 'ନାମ:',
 7398+ 'centralnotice-banner-logged-in' => 'ଲଗଇନ କରିଥିବା ଇଉଜରମାନେ',
 7399+ 'centralnotice-banner-type' => 'ବ୍ୟାନର ପ୍ରକାର',
 7400+ 'centralnotice-languages' => 'ଭାଷା',
 7401+ 'centralnotice-projects' => 'ପ୍ରକଳ୍ପ',
 7402+);
 7403+
68527404 /** Ossetic (Иронау)
68537405 * @author Amikeco
68547406 */
@@ -6884,6 +7436,7 @@
68857437 * @author Derbeth
68867438 * @author Leinad
68877439 * @author Maikking
 7440+ * @author Odder
68887441 * @author Qblik
68897442 * @author Sp5uhe
68907443 */
@@ -6891,6 +7444,7 @@
68927445 'centralnotice' => 'Administrowanie wspólnymi komunikatami',
68937446 'noticetemplate' => 'Zarządzanie wspólnymi komunikatami',
68947447 'bannerallocation' => 'Zarządzanie wspólnymi komunikatami',
 7448+ 'centralnoticelogs' => 'Zarządzanie wspólnymi komunikatami',
68957449 'right-centralnotice-admin' => 'Zarządzanie wspólnymi komunikatami',
68967450 'action-centralnotice-admin' => 'zarządzaj centralnymi komunikatami',
68977451 'centralnotice-desc' => 'Dodaje wspólny komunikat dla serwisów',
@@ -6903,6 +7457,7 @@
69047458 'centralnotice-modify' => 'Zapisz',
69057459 'centralnotice-save-banner' => 'Zapisz baner',
69067460 'centralnotice-preview' => 'Podgląd',
 7461+ 'centralnotice-nopreview' => '(Podgląd niedostępny)',
69077462 'centralnotice-add-new' => 'Dodaj nowy wspólny komunikat',
69087463 'centralnotice-remove' => 'Usuń',
69097464 'centralnotice-translate-heading' => 'Tłumaczenie dla $1',
@@ -6914,7 +7469,8 @@
69157470 'centralnotice-add-template' => 'Dodaj szablon',
69167471 'centralnotice-show-notices' => 'Pokaż komunikaty',
69177472 'centralnotice-list-templates' => 'Lista szablonów',
6918 - 'centralnotice-multiple' => 'wiele ($1)',
 7473+ 'centralnotice-multiple-projects' => 'wiele ($1)',
 7474+ 'centralnotice-multiple-languages' => 'wiele ($1)',
69197475 'centralnotice-all-projects' => 'Wszystkie projekty',
69207476 'centralnotice-translations' => 'Tłumaczenia',
69217477 'centralnotice-translate-to' => 'Przetłumacz na',
@@ -6996,6 +7552,9 @@
69977553 'centralnotice-banner-type' => 'Typ banera:',
69987554 'centralnotice-banner-hidable' => 'Statyczny czy ukrywalny',
69997555 'centralnotice-banner-collapsible' => 'Zwijalny',
 7556+ 'centralnotice-banner-fundraising' => 'Baner zbiórki pieniędzy',
 7557+ 'centralnotice-banner-fundraising-help' => 'Utwórz znacznik kotwicy w ciele banera z id="cn_fundraising_link" i wprowadź jedną lub więcej stron docelowych, na przykład "ApelJimmiego01". Dla linku href zostanie wygenerowane automatycznie.',
 7558+ 'centralnotice-banner-landing-pages' => 'Strony docelowe (rozdzielone przecinkami):',
70007559 'centralnotice-geotargeted' => 'Geograficznie nakierowane',
70017560 'centralnotice-countries' => 'Kraje',
70027561 'centralnotice-allocation' => 'Przydział',
@@ -7010,6 +7569,8 @@
70117570 'centralnotice-documentwrite-error' => 'Nie można korzystać z document.write() w banerze.
70127571 Więcej informacji odnajdziesz na stronie http://meta.wikimedia.org/wiki/Help:CentralNotice',
70137572 'centralnotice-preferred' => 'Preferowany',
 7573+ 'centralnotice-logs' => 'Rejestr operacji',
 7574+ 'centralnotice-view-logs' => 'Rejestr odsłon',
70147575 );
70157576
70167577 /** Piedmontese (Piemontèis)
@@ -7032,6 +7593,7 @@
70337594 'centralnotice-modify' => 'Spediss',
70347595 'centralnotice-save-banner' => 'Salvé ël tilèt',
70357596 'centralnotice-preview' => 'Previsualisassion',
 7597+ 'centralnotice-nopreview' => "(Gnun-a preuva ch'as peula smon-se)",
70367598 'centralnotice-add-new' => 'Gionta na Neuva Sentral neuva',
70377599 'centralnotice-remove' => 'Gava',
70387600 'centralnotice-translate-heading' => 'Tradussion për $1',
@@ -7043,7 +7605,8 @@
70447606 'centralnotice-add-template' => 'Gionta në stamp',
70457607 'centralnotice-show-notices' => 'Mostra neuva',
70467608 'centralnotice-list-templates' => 'Lista stamp',
7047 - 'centralnotice-multiple' => 'mùltipl ($1)',
 7609+ 'centralnotice-multiple-projects' => 'mùltipl ($1)',
 7610+ 'centralnotice-multiple-languages' => 'mùltipl ($1)',
70487611 'centralnotice-all-projects' => 'Tùit ij proget',
70497612 'centralnotice-translations' => 'Tradussion',
70507613 'centralnotice-translate-to' => 'Volté an',
@@ -7118,9 +7681,9 @@
71197682 'centralnotice-clone-name' => 'Nòm:',
71207683 'centralnotice-preview-all-template-translations' => 'Previsualisa tute le tradussion disponìbij ëd lë stamp',
71217684 'centralnotice-insert' => 'Anserì: $1',
7122 - 'centralnotice-hide-button' => 'Stërma colegament',
7123 - 'centralnotice-collapse-button' => 'Strenz colegament',
7124 - 'centralnotice-expand-button' => 'Espand colegament',
 7685+ 'centralnotice-hide-button' => "Stërmé l'anliura",
 7686+ 'centralnotice-collapse-button' => "Strenze l'anliura",
 7687+ 'centralnotice-expand-button' => "Espande l'anliura",
71257688 'centralnotice-close-button' => 'Boton për boton',
71267689 'centralnotice-translate-button' => 'Colegament për giuté a volté',
71277690 'centralnotice-donate-button' => "Boton për fé dj'oferte",
@@ -7169,8 +7732,11 @@
71707733 'centralnotice-translations' => 'ژباړې',
71717734 'centralnotice-translate' => 'ژباړل',
71727735 'centralnotice-english' => 'انګرېزي',
7173 - 'centralnotice-banner-name' => 'د کينډۍ نوم',
7174 - 'centralnotice-templates' => 'کينډۍ',
 7736+ 'centralnotice-banner-name' => 'د ليكتوغ نوم:',
 7737+ 'centralnotice-banner' => 'ليكتوغ',
 7738+ 'centralnotice-banner-heading' => 'ليكتوغ: $1',
 7739+ 'centralnotice-templates' => 'ليكتوغونه',
 7740+ 'centralnotice-weight' => 'تول',
71757741 'centralnotice-day' => 'ورځ',
71767742 'centralnotice-year' => 'کال',
71777743 'centralnotice-month' => 'مياشت',
@@ -7178,6 +7744,7 @@
71797745 'centralnotice-min' => 'دقيقه',
71807746 'centralnotice-project-lang' => 'د ژبې پروژه',
71817747 'centralnotice-select' => 'ټاکل: $1',
 7748+ 'centralnotice-top-ten-languages' => 'د سر 10 ژبې',
71827749 'centralnotice-project-name' => 'د پروژې نوم',
71837750 'centralnotice-start-date' => 'د پيل نېټه',
71847751 'centralnotice-start-time' => 'د پيل وخت (UTC)',
@@ -7191,6 +7758,8 @@
71927759 'centralnotice-banner-anonymous' => 'ورکنومي کارنان',
71937760 'centralnotice-banner-logged-in' => 'ننوتي کارنان',
71947761 'centralnotice-countries' => 'هيوادونه',
 7762+ 'centralnotice-languages' => 'ژبې',
 7763+ 'centralnotice-projects' => 'پروژې',
71957764 'centralnotice-country' => 'هېواد',
71967765 'centralnotice-percentage' => 'سلنه',
71977766 );
@@ -7206,18 +7775,20 @@
72077776 'centralnotice' => 'Administração de avisos centralizados',
72087777 'noticetemplate' => 'Administração de avisos centralizados',
72097778 'bannerallocation' => 'Administração de avisos centralizados',
 7779+ 'centralnoticelogs' => 'Administração de avisos centralizados',
72107780 'right-centralnotice-admin' => 'Gerir avisos centralizados',
72117781 'action-centralnotice-admin' => 'gerir avisos centralizados',
72127782 'centralnotice-desc' => 'Adiciona um aviso centralizado',
7213 - 'centralnotice-summary' => 'Este módulo permite-lhe editar os avisos centralizados configurados.
7214 -Pode também ser usado para adicionar novos ou remover antigos.',
 7783+ 'centralnotice-summary' => 'Este módulo permite-lhe editar os avisos centralizados que estejam configurados.
 7784+Também pode ser usado para adicionar avisos novos ou remover antigos.',
72157785 'centralnotice-query' => 'Modificar avisos actuais',
72167786 'centralnotice-notice-name' => 'Nome do aviso',
72177787 'centralnotice-end-date' => 'Data de fim',
72187788 'centralnotice-enabled' => 'Activo',
7219 - 'centralnotice-modify' => 'Submeter',
 7789+ 'centralnotice-modify' => 'Enviar',
72207790 'centralnotice-save-banner' => 'Gravar modelo',
72217791 'centralnotice-preview' => 'Antevisão',
 7792+ 'centralnotice-nopreview' => '(Antevisão indisponível)',
72227793 'centralnotice-add-new' => 'Adicionar um aviso centralizado',
72237794 'centralnotice-remove' => 'Remover',
72247795 'centralnotice-translate-heading' => 'Tradução para $1',
@@ -7229,7 +7800,8 @@
72307801 'centralnotice-add-template' => 'Adicionar um modelo',
72317802 'centralnotice-show-notices' => 'Mostrar avisos',
72327803 'centralnotice-list-templates' => 'Listar modelos',
7233 - 'centralnotice-multiple' => 'múltiplas ($1)',
 7804+ 'centralnotice-multiple-projects' => 'múltiplas ($1)',
 7805+ 'centralnotice-multiple-languages' => 'múltiplas ($1)',
72347806 'centralnotice-all-projects' => 'Todos os projetos',
72357807 'centralnotice-translations' => 'Traduções',
72367808 'centralnotice-translate-to' => 'Traduzir para',
@@ -7304,9 +7876,9 @@
73057877 'centralnotice-clone-name' => 'Nome:',
73067878 'centralnotice-preview-all-template-translations' => 'Antever todas as traduções disponíveis do modelo',
73077879 'centralnotice-insert' => 'Inserir: $1',
7308 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} ocultar',
7309 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-collapse}} recolher',
7310 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} expandir',
 7880+ 'centralnotice-hide-button' => 'Ocultar link',
 7881+ 'centralnotice-collapse-button' => 'Recolher link',
 7882+ 'centralnotice-expand-button' => 'Expandir link',
73117883 'centralnotice-close-button' => 'Botão Fechar',
73127884 'centralnotice-translate-button' => 'Ajudar a traduzir link',
73137885 'centralnotice-donate-button' => 'Botão Donativo',
@@ -7318,6 +7890,9 @@
73197891 'centralnotice-banner-type' => 'Tipo de modelo:',
73207892 'centralnotice-banner-hidable' => 'Estático/Ocultável',
73217893 'centralnotice-banner-collapsible' => 'Ocultável',
 7894+ 'centralnotice-banner-fundraising' => 'Este é um modelo de angariação de fundos',
 7895+ 'centralnotice-banner-fundraising-help' => 'Crie uma âncora no corpo do modelo com id="cn_fundraising_link" e introduza abaixo uma ou mais páginas de destino. Por exemplo, "ApeloJimmy01". O parâmetro href do link será construído automaticamente.',
 7896+ 'centralnotice-banner-landing-pages' => 'Páginas de destino (separadas por vírgulas):',
73227897 'centralnotice-geotargeted' => 'Com segmentação geográfica',
73237898 'centralnotice-countries' => 'Países',
73247899 'centralnotice-allocation' => 'Atribuição',
@@ -7332,6 +7907,8 @@
73337908 'centralnotice-documentwrite-error' => 'document.write() não pode ser usado num modelo.
73347909 Para mais informações, consulte http://meta.wikimedia.org/wiki/Help:CentralNotice.',
73357910 'centralnotice-preferred' => 'Preferido',
 7911+ 'centralnotice-logs' => 'Registos',
 7912+ 'centralnotice-view-logs' => 'Ver registos',
73367913 );
73377914
73387915 /** Brazilian Portuguese (Português do Brasil)
@@ -7344,6 +7921,7 @@
73457922 'centralnotice' => 'Administração de aviso centralizado',
73467923 'noticetemplate' => 'Administração de avisos centralizados',
73477924 'bannerallocation' => 'Administração de avisos centralizados',
 7925+ 'centralnoticelogs' => 'Administração de avisos centralizados',
73487926 'right-centralnotice-admin' => 'Gerenciar avisos centralizados',
73497927 'action-centralnotice-admin' => 'gerenciar avisos centralizados',
73507928 'centralnotice-desc' => 'Adiciona um aviso do sítio centralizado',
@@ -7356,6 +7934,7 @@
73577935 'centralnotice-modify' => 'Enviar',
73587936 'centralnotice-save-banner' => 'Salvar modelo',
73597937 'centralnotice-preview' => 'Pré-visualização',
 7938+ 'centralnotice-nopreview' => '(Previsualização não disponível)',
73607939 'centralnotice-add-new' => 'Adicionar um novo aviso centralizado',
73617940 'centralnotice-remove' => 'Remover',
73627941 'centralnotice-translate-heading' => 'Tradução de $1',
@@ -7367,7 +7946,8 @@
73687947 'centralnotice-add-template' => 'Adicionar um modelo',
73697948 'centralnotice-show-notices' => 'Mostrar avisos',
73707949 'centralnotice-list-templates' => 'Listar modelos',
7371 - 'centralnotice-multiple' => 'múltiplas ($1)',
 7950+ 'centralnotice-multiple-projects' => 'múltiplas ($1)',
 7951+ 'centralnotice-multiple-languages' => 'múltiplas ($1)',
73727952 'centralnotice-all-projects' => 'Todos os projetos',
73737953 'centralnotice-translations' => 'Traduções',
73747954 'centralnotice-translate-to' => 'Traduzir para',
@@ -7456,6 +8036,9 @@
74578037 'centralnotice-banner-type' => 'Tipo de banner:',
74588038 'centralnotice-banner-hidable' => 'Estático/Ocultável',
74598039 'centralnotice-banner-collapsible' => 'Colapsável',
 8040+ 'centralnotice-banner-fundraising' => 'Este é um banner de angariação de fundos',
 8041+ 'centralnotice-banner-fundraising-help' => 'Crie uma âncora no corpo do banner com id="cn_fundraising_link" e introduza abaixo uma ou mais páginas de destino. Por exemplo, "ApeloJimmy01". O parâmetro href do link será construído automaticamente.',
 8042+ 'centralnotice-banner-landing-pages' => 'Páginas de destino (separadas por vírgulas):',
74608043 'centralnotice-geotargeted' => 'Localizado geograficamente',
74618044 'centralnotice-countries' => 'Países',
74628045 'centralnotice-allocation' => 'Atribuição',
@@ -7470,6 +8053,8 @@
74718054 'centralnotice-documentwrite-error' => 'document.write() não pode ser usado num modelo.
74728055 Para mais informações, consulte http://meta.wikimedia.org/wiki/Help:CentralNotice.',
74738056 'centralnotice-preferred' => 'Preferido',
 8057+ 'centralnotice-logs' => 'Registros',
 8058+ 'centralnotice-view-logs' => 'Ver registros',
74748059 );
74758060
74768061 /** Quechua (Runa Simi)
@@ -7486,11 +8071,12 @@
74878072 Paywanmi mawk'a willaykunatapas yapayta icha qichuyta atinki.",
74888073 'centralnotice-query' => 'Kachkaq willaykunata hukchay',
74898074 'centralnotice-notice-name' => 'Willaypa sutin',
7490 - 'centralnotice-end-date' => "Tukuna p'unchaw",
 8075+ 'centralnotice-end-date' => "Puchukana p'unchaw",
74918076 'centralnotice-enabled' => 'Saqillasqa',
74928077 'centralnotice-modify' => 'Kachay',
74938078 'centralnotice-save-banner' => 'Unanchata waqaychay',
74948079 'centralnotice-preview' => 'Ñawpaqta qhawallay',
 8080+ 'centralnotice-nopreview' => '(Ama qhawarichunkuchu)',
74958081 'centralnotice-add-new' => 'Musuq chawpi willayta yapay',
74968082 'centralnotice-remove' => 'Qichuy',
74978083 'centralnotice-translate-heading' => "$1-paq t'ikrasqa",
@@ -7502,7 +8088,8 @@
75038089 'centralnotice-add-template' => 'Plantillata yapay',
75048090 'centralnotice-show-notices' => 'Willaykunata rikuchiy',
75058091 'centralnotice-list-templates' => 'Plantillakunata sutisuyupi rikuchiy',
7506 - 'centralnotice-multiple' => 'imaymana ($1)',
 8092+ 'centralnotice-multiple-projects' => 'imaymana ($1)',
 8093+ 'centralnotice-multiple-languages' => 'imaymana ($1)',
75078094 'centralnotice-all-projects' => 'Tukuy ruraykamaykuna',
75088095 'centralnotice-translations' => "T'ikrasqakuna",
75098096 'centralnotice-translate-to' => "Kayman t'ikray:",
@@ -7577,9 +8164,9 @@
75788165 'centralnotice-clone-name' => 'Suti:',
75798166 'centralnotice-preview-all-template-translations' => "Tukuy aypanalla plantillamanta t'ikrasqakunata ñawpaqta qhawallay",
75808167 'centralnotice-insert' => "Sat'iy: $1",
7581 - 'centralnotice-hide-button' => "{{int:centralnotice-shared-hide}} t'inki",
7582 - 'centralnotice-collapse-button' => "{{int:centralnotice-shared-collapse}} t'inki",
7583 - 'centralnotice-expand-button' => "{{int:centralnotice-shared-expand}} t'inki",
 8168+ 'centralnotice-hide-button' => "T'inkita pakay",
 8169+ 'centralnotice-collapse-button' => "T'inkita thuñichiy",
 8170+ 'centralnotice-expand-button' => "T'inkita mast'ariy",
75848171 'centralnotice-close-button' => "Wichq'ay butun",
75858172 'centralnotice-translate-button' => "T'ikraysiy t'inki",
75868173 'centralnotice-donate-button' => 'Qaray butun',
@@ -7626,11 +8213,12 @@
76278214 El poate fi folosit de asemenea pentru a adăuga sau șterge anunțuri vechi.',
76288215 'centralnotice-query' => 'Modifică anunțurile curente',
76298216 'centralnotice-notice-name' => 'Numele anunțului',
7630 - 'centralnotice-end-date' => 'Dată de încheiere',
 8217+ 'centralnotice-end-date' => 'Data de încheiere',
76318218 'centralnotice-enabled' => 'Activat',
76328219 'centralnotice-modify' => 'Trimite',
76338220 'centralnotice-save-banner' => 'Salvează banner',
76348221 'centralnotice-preview' => 'Previzualizare',
 8222+ 'centralnotice-nopreview' => '(Previzualizare indisponibilă)',
76358223 'centralnotice-add-new' => 'Adaugă un anunț central nou',
76368224 'centralnotice-remove' => 'Şterge',
76378225 'centralnotice-translate-heading' => 'Traducere pentru $1',
@@ -7642,7 +8230,8 @@
76438231 'centralnotice-add-template' => 'Adaugă un format',
76448232 'centralnotice-show-notices' => 'Arată anunțurile',
76458233 'centralnotice-list-templates' => 'Lista de formate',
7646 - 'centralnotice-multiple' => 'multiple ($1)',
 8234+ 'centralnotice-multiple-projects' => 'multiple ($1)',
 8235+ 'centralnotice-multiple-languages' => 'multiple ($1)',
76478236 'centralnotice-all-projects' => 'Toate proiectele',
76488237 'centralnotice-translations' => 'Traduceri',
76498238 'centralnotice-translate-to' => 'Tradu în',
@@ -7755,6 +8344,8 @@
77568345 'right-centralnotice-admin' => 'Gestiscere le notizie cendrale',
77578346 'action-centralnotice-admin' => 'gestiscere le notizie cendrale',
77588347 'centralnotice-desc' => "Aggiunge 'n'avvise cendrale a 'u site",
 8348+ 'centralnotice-summary' => "Stu module te permette de cangià le 'mbostaziune corrende sus a le notizie cendrale.
 8349+Quiste pò essere ausate pure pe aggiungere o luà le vecchie notizie.",
77598350 'centralnotice-query' => "Cange 'a cambagne corrende",
77608351 'centralnotice-notice-name' => "Nome d'a cambagne",
77618352 'centralnotice-end-date' => 'Date de fine',
@@ -7762,6 +8353,7 @@
77638354 'centralnotice-modify' => 'Conferme',
77648355 'centralnotice-save-banner' => "Salve 'u banner",
77658356 'centralnotice-preview' => 'Andeprime',
 8357+ 'centralnotice-nopreview' => "(L'andeprime non g'è disponibbile)",
77668358 'centralnotice-add-new' => "Aggiugne 'na cambagna nove",
77678359 'centralnotice-remove' => 'Live',
77688360 'centralnotice-translate-heading' => 'Traduzione pè $1',
@@ -7773,7 +8365,9 @@
77748366 'centralnotice-add-template' => "Aggiunge 'nu banner",
77758367 'centralnotice-show-notices' => 'Visualizze le cambagne',
77768368 'centralnotice-list-templates' => 'Liste de le banner',
7777 - 'centralnotice-multiple' => 'multiple ($1)',
 8369+ 'centralnotice-multiple-projects' => 'multiple ($1)',
 8370+ 'centralnotice-multiple-languages' => 'multiple ($1)',
 8371+ 'centralnotice-all-projects' => 'Tutte le pruggette',
77788372 'centralnotice-translations' => 'Traduziune',
77798373 'centralnotice-translate-to' => 'Traduce a',
77808374 'centralnotice-translate' => 'Traduce',
@@ -7790,6 +8384,7 @@
77918385 'centralnotice-notice-exists' => "'A cambagne esiste ggià.
77928386 No a scè aggiungere.",
77938387 'centralnotice-no-language' => 'Nisciuna lènghe ha state scacchiate pe sta cambagne. No scè aggiungenne.',
 8388+ 'centralnotice-no-project' => 'Nisciune proggette ha state scacchiate pe sta cambagne. No scè aggiungenne.',
77948389 'centralnotice-template-exists' => "'U banner esiste ggià.
77958390 No a scè aggiungere.",
77968391 'centralnotice-notice-doesnt-exist' => "'A cambagne non g'esiste.",
@@ -7859,15 +8454,20 @@
78608455 'centralnotice-banner-logged-in' => 'Utinde trasute',
78618456 'centralnotice-banner-type' => 'Tipe de banner:',
78628457 'centralnotice-banner-hidable' => 'Stateche/Scunnibbele',
 8458+ 'centralnotice-banner-collapsible' => 'Collassabbele',
78638459 'centralnotice-geotargeted' => 'Geo referenziate',
78648460 'centralnotice-countries' => 'Paìse',
78658461 'centralnotice-allocation' => 'Allocazione',
78668462 'centralnotice-view-allocation' => "Visualizze l'assignazione d'u banner",
 8463+ 'centralnotice-allocation-instructions' => "Scacchie l'ambiende addo tu vuè vedè 'u banner allocate pe:",
 8464+ 'centralnotice-languages' => 'Lènghe',
78678465 'centralnotice-projects' => 'Pruggette',
78688466 'centralnotice-country' => 'Nazione',
78698467 'centralnotice-no-allocation' => 'Nisciune banner assignate.',
78708468 'centralnotice-allocation-description' => 'Assignazione de banner pè $1.$2 jndre $3:',
78718469 'centralnotice-percentage' => 'Percenduale',
 8470+ 'centralnotice-documentwrite-error' => "document.write() non ge pò essere ausate jndr'à 'nu banner.
 8471+Vide http://meta.wikimedia.org/wiki/Help:CentralNotice pe cchiù 'mbormaziune.",
78728472 'centralnotice-preferred' => 'Preferite',
78738473 );
78748474
@@ -7884,6 +8484,7 @@
78858485 'centralnotice' => 'Управление централизованными уведомлениями',
78868486 'noticetemplate' => 'Управление централизованными уведомлениями',
78878487 'bannerallocation' => 'Управление централизованными уведомлениями',
 8488+ 'centralnoticelogs' => 'Управление централизованными уведомлениями',
78888489 'right-centralnotice-admin' => 'управление централизованными уведомлениями',
78898490 'action-centralnotice-admin' => 'управление централизованными уведомлениями',
78908491 'centralnotice-desc' => 'Добавляет общее сообщение сайта',
@@ -7896,6 +8497,7 @@
78978498 'centralnotice-modify' => 'Отправить',
78988499 'centralnotice-save-banner' => 'Сохранить баннер',
78998500 'centralnotice-preview' => 'Предпросмотр',
 8501+ 'centralnotice-nopreview' => '(Предпросмотр недоступен)',
79008502 'centralnotice-add-new' => 'Добавить новое централизованное уведомление',
79018503 'centralnotice-remove' => 'Удалить',
79028504 'centralnotice-translate-heading' => 'Перевод для $1',
@@ -7907,7 +8509,8 @@
79088510 'centralnotice-add-template' => 'Добавить шаблон',
79098511 'centralnotice-show-notices' => 'Показать уведомления',
79108512 'centralnotice-list-templates' => 'Вывести список шаблонов',
7911 - 'centralnotice-multiple' => 'несколько ($1)',
 8513+ 'centralnotice-multiple-projects' => 'несколько ($1)',
 8514+ 'centralnotice-multiple-languages' => 'несколько ($1)',
79128515 'centralnotice-all-projects' => 'Все проекты',
79138516 'centralnotice-translations' => 'Переводы',
79148517 'centralnotice-translate-to' => 'Перевод на',
@@ -7996,6 +8599,9 @@
79978600 'centralnotice-banner-type' => 'Тип баннера:',
79988601 'centralnotice-banner-hidable' => 'Статический / Скрываемый',
79998602 'centralnotice-banner-collapsible' => 'Сворачиваемый',
 8603+ 'centralnotice-banner-fundraising' => 'Это баннер сбора средств',
 8604+ 'centralnotice-banner-fundraising-help' => 'Создайте тег ссылки в тела баннера с id="cn_fundraising_link" и укажите ниже одну или несколько целевых страниц, например, «JimmyAppeal01». Поле HREF ссылки будет создано автоматически.',
 8605+ 'centralnotice-banner-landing-pages' => 'Целевые страницы (через запятую):',
80008606 'centralnotice-geotargeted' => 'Геопривязка',
80018607 'centralnotice-countries' => 'Страны',
80028608 'centralnotice-allocation' => 'Распределение',
@@ -8010,6 +8616,8 @@
80118617 'centralnotice-documentwrite-error' => 'document.write() нельзя использовать в баннере.
80128618 Подробности: [http://meta.wikimedia.org/wiki/Help:CentralNotice http://meta.wikimedia.org/wiki/Help:CentralNotice].',
80138619 'centralnotice-preferred' => 'Желательно',
 8620+ 'centralnotice-logs' => 'Журналы',
 8621+ 'centralnotice-view-logs' => 'Просмотр журналов',
80148622 );
80158623
80168624 /** Rusyn (Русиньскый)
@@ -8042,7 +8650,8 @@
80438651 'centralnotice-add-template' => 'Додати шаблону',
80448652 'centralnotice-show-notices' => 'Указати повідомлїня',
80458653 'centralnotice-list-templates' => 'Cписок шаблон',
8046 - 'centralnotice-multiple' => 'веце ($1)',
 8654+ 'centralnotice-multiple-projects' => 'веце ($1)',
 8655+ 'centralnotice-multiple-languages' => 'веце ($1)',
80478656 'centralnotice-all-projects' => 'Вшыткы проєкты',
80488657 'centralnotice-translations' => 'Переклады',
80498658 'centralnotice-translate-to' => 'Переклад до',
@@ -8149,6 +8758,7 @@
81508759 'centralnotice' => 'Кииннэммит биллэриилэри салайыы',
81518760 'noticetemplate' => 'Кииннэммит биллэриилэри салайыы',
81528761 'bannerallocation' => 'Кииннэммит биллэриилэри салайыы',
 8762+ 'centralnoticelogs' => 'Кииннэммит биллэриилэри салайыы',
81538763 'right-centralnotice-admin' => 'Кииннэмит биллэриилэри салайыы',
81548764 'action-centralnotice-admin' => 'кииннэммит биллэриилэри салайыы',
81558765 'centralnotice-desc' => 'Саайт биллэриитин эбэр',
@@ -8161,6 +8771,7 @@
81628772 'centralnotice-modify' => 'Ыытарга',
81638773 'centralnotice-save-banner' => 'Бааннеры бигэргэтии',
81648774 'centralnotice-preview' => 'Ыытыах иннинэ көрүү',
 8775+ 'centralnotice-nopreview' => '(Бигэргэтиэх иннинэ көрүү сатаммат)',
81658776 'centralnotice-add-new' => 'Саҥа кииннэммит биллэриини эбэргэ',
81668777 'centralnotice-remove' => 'Сот',
81678778 'centralnotice-translate-heading' => '$1 тылбааһа',
@@ -8172,7 +8783,8 @@
81738784 'centralnotice-add-template' => 'Халыып эбэргэ',
81748785 'centralnotice-show-notices' => 'Биллэриилэри көрдөр',
81758786 'centralnotice-list-templates' => 'Халыыптар тиһиктэрэ',
8176 - 'centralnotice-multiple' => 'хас да ($1)',
 8787+ 'centralnotice-multiple-projects' => 'хас да ($1)',
 8788+ 'centralnotice-multiple-languages' => 'хас да ($1)',
81778789 'centralnotice-all-projects' => 'Бары бырайыактар',
81788790 'centralnotice-translations' => 'Тылбаастар',
81798791 'centralnotice-translate-to' => 'Манна тылбаас',
@@ -8261,6 +8873,7 @@
82628874 'centralnotice-banner-type' => 'Бааннер көрүҥэ:',
82638875 'centralnotice-banner-hidable' => 'Статическэй / Кистэниллэр',
82648876 'centralnotice-banner-collapsible' => 'Кыччатыллар',
 8877+ 'centralnotice-banner-fundraising' => 'Харчы хомуйуу бааннера',
82658878 'centralnotice-geotargeted' => 'Сиргэ баайыы',
82668879 'centralnotice-countries' => 'Дойдулар',
82678880 'centralnotice-allocation' => 'Тарҕаныыта',
@@ -8275,6 +8888,8 @@
82768889 'centralnotice-documentwrite-error' => 'document.write() диэни бааннерга туттар сатаммат.
82778890 Сиһилии: [http://meta.wikimedia.org/wiki/Help:CentralNotice http://meta.wikimedia.org/wiki/Help:CentralNotice].',
82788891 'centralnotice-preferred' => 'Бэрт буолуо этэ',
 8892+ 'centralnotice-logs' => 'Сурунааллар',
 8893+ 'centralnotice-view-logs' => 'Сурунааллары көрүү',
82798894 );
82808895
82818896 /** Sicilian (Sicilianu)
@@ -8285,6 +8900,8 @@
82868901 $messages['scn'] = array(
82878902 'centralnotice' => 'Gistioni di avvisu cintralizzatu',
82888903 'noticetemplate' => "Template di l'avvisi cintralizzati",
 8904+ 'right-centralnotice-admin' => "Gistisci l'avvisi cintralizzati",
 8905+ 'action-centralnotice-admin' => "Guverna l'avvisi cintralizzati",
82898906 'centralnotice-desc' => "Jiunci n'avvisu cintralizzatu a inìzziu pàggina",
82908907 'centralnotice-summary' => "Stu mòdulu pirmetti di canciari l'avvisa cintralizzati. Pò èssiri usatu pi junciri o livari avvisa vecchi.",
82918908 'centralnotice-query' => "Cancia l'avvisa attuali",
@@ -8356,10 +8973,6 @@
83578974 'centralnotice-clone-name' => 'Nomu:',
83588975 'centralnotice-preview-all-template-translations' => "Tutti li traduzzioni dî template dispunìbbili 'n anteprima",
83598976 'centralnotice-banner-anonymous' => 'Utenti anònimi',
8360 - 'right-centralnotice-admin' => "Gistisci l'avvisi cintralizzati",
8361 - 'right-centralnotice-translate' => 'Traduci avvisi cintralizzati',
8362 - 'action-centralnotice-admin' => "Guverna l'avvisi cintralizzati",
8363 - 'action-centralnotice-translate' => 'tradùciri avvisi cintralizzati',
83648977 'centralnotice-preferred' => 'Prifiriti',
83658978 );
83668979
@@ -8371,8 +8984,10 @@
83728985 );
83738986
83748987 /** Sinhala (සිංහල)
 8988+ * @author Singhalawap
83758989 * @author Thameera123
83768990 * @author තඹරු විජේසේකර
 8991+ * @author පසිඳු කාවින්ද
83778992 */
83788993 $messages['si'] = array(
83798994 'centralnotice' => 'ප්‍රධාන දැන්වීම් පාලක',
@@ -8390,6 +9005,7 @@
83919006 'centralnotice-modify' => 'යොමන්න',
83929007 'centralnotice-save-banner' => 'බැනරය සුරකින්න',
83939008 'centralnotice-preview' => 'පෙරදසුන',
 9009+ 'centralnotice-nopreview' => '(පෙර-දසුන ලබාගත නොහැක)',
83949010 'centralnotice-add-new' => 'නව ව්‍යාපාරයක් එකතු කරන්න',
83959011 'centralnotice-remove' => 'ඉවත් කරන්න',
83969012 'centralnotice-translate-heading' => '$1 සඳහා පරිවර්තනය',
@@ -8401,7 +9017,8 @@
84029018 'centralnotice-add-template' => 'බැනරයක් එකතු කරන්න',
84039019 'centralnotice-show-notices' => 'ව්‍යාපාර පෙන්වන්න',
84049020 'centralnotice-list-templates' => 'බැනර ලයිස්තුගත කරන්න',
8405 - 'centralnotice-multiple' => 'බහු ($1)',
 9021+ 'centralnotice-multiple-projects' => 'බහු ($1)',
 9022+ 'centralnotice-multiple-languages' => 'බහු ($1)',
84069023 'centralnotice-all-projects' => 'සියලු ව්‍යාපෘති',
84079024 'centralnotice-translations' => 'පරිවර්තන',
84089025 'centralnotice-translate-to' => 'ට පරිවර්තනය කරන්න',
@@ -8466,7 +9083,7 @@
84679084 පහතින් එකක් එකතු කරන්න.',
84689085 'centralnotice-no-templates-translate' => 'පරිවර්තන සංස්කරණය කිරීමට බැනර නොපවතී.',
84699086 'centralnotice-number-uses' => 'භාවිත',
8470 - 'centralnotice-settings' => 'පරිස්ථිතීන්',
 9087+ 'centralnotice-settings' => 'සැකසුම්',
84719088 'centralnotice-edit-template' => 'බැනරය සංස්කරණය කරන්න',
84729089 'centralnotice-edit-template-summary' => 'Localize කළ හැකි පණිවුඩයක් සෑදීමට, එම වචන සඟල වරහන් තුළ අසුරන්න',
84739090 'centralnotice-message' => 'පණිවුඩය',
@@ -8476,9 +9093,9 @@
84779094 'centralnotice-clone-name' => 'නම:',
84789095 'centralnotice-preview-all-template-translations' => 'බැනරය සඳහා පවතින සියලු පරිවර්තනවල පෙරදසුන් පෙන්වන්න',
84799096 'centralnotice-insert' => 'ඇතුළු කරන්න: $1',
8480 - 'centralnotice-hide-button' => '{{int:centralnotice-shared-hide}} යොමුව',
8481 - 'centralnotice-collapse-button' => '{{int:centralnotice-shared-hide}} යොමුව',
8482 - 'centralnotice-expand-button' => '{{int:centralnotice-shared-expand}} යොමුව',
 9097+ 'centralnotice-hide-button' => 'සබැඳිය සගවන්න',
 9098+ 'centralnotice-collapse-button' => 'සබැඳිය හකුලන්න',
 9099+ 'centralnotice-expand-button' => 'විකසිත සබැඳිය',
84839100 'centralnotice-close-button' => 'වැසීමේ බොත්තම',
84849101 'centralnotice-translate-button' => 'යොමුව පරිවර්තනය කිරීමට උදව් වන්න',
84859102 'centralnotice-donate-button' => 'පරිත්‍යාග කිරීමේ බොත්තම',
@@ -8525,6 +9142,7 @@
85269143 'centralnotice-modify' => 'Odoslať',
85279144 'centralnotice-save-banner' => 'Uložiť oznam',
85289145 'centralnotice-preview' => 'Náhľad',
 9146+ 'centralnotice-nopreview' => '(Náhľad nie je k dispozícii)',
85299147 'centralnotice-add-new' => 'Pridať nový centrálny oznam',
85309148 'centralnotice-remove' => 'Odstrániť',
85319149 'centralnotice-translate-heading' => 'Preklad $1',
@@ -8536,7 +9154,8 @@
85379155 'centralnotice-add-template' => 'Pridať šablónu',
85389156 'centralnotice-show-notices' => 'Zobraziť oznamy',
85399157 'centralnotice-list-templates' => 'Zoznam šablón',
8540 - 'centralnotice-multiple' => 'viaceré ($1)',
 9158+ 'centralnotice-multiple-projects' => 'viaceré ($1)',
 9159+ 'centralnotice-multiple-languages' => 'viaceré ($1)',
85419160 'centralnotice-all-projects' => 'Všetky projekty',
85429161 'centralnotice-translations' => 'Preklady',
85439162 'centralnotice-translate-to' => 'Preložiť do jazyka',
@@ -8637,6 +9256,7 @@
86389257 'centralnotice' => 'Upravljanje osrednjega obvestila',
86399258 'noticetemplate' => 'Upravljanje osrednjega obvestila',
86409259 'bannerallocation' => 'Upravljanje osrednjega obvestila',
 9260+ 'centralnoticelogs' => 'Upravljanje osrednjega obvestila',
86419261 'right-centralnotice-admin' => 'Upravljanje osrednjih sporočil',
86429262 'action-centralnotice-admin' => 'upravljanje osrednjih sporočil',
86439263 'centralnotice-desc' => 'Doda osrednje obvestilo strani',
@@ -8649,6 +9269,7 @@
86509270 'centralnotice-modify' => 'Pošlji',
86519271 'centralnotice-save-banner' => 'Shrani pasico',
86529272 'centralnotice-preview' => 'Predogled',
 9273+ 'centralnotice-nopreview' => '(Predogled ni na voljo)',
86539274 'centralnotice-add-new' => 'Dodaj novo akcijo',
86549275 'centralnotice-remove' => 'Odstrani',
86559276 'centralnotice-translate-heading' => 'Prevod za $1',
@@ -8660,7 +9281,8 @@
86619282 'centralnotice-add-template' => 'Dodaj pasico',
86629283 'centralnotice-show-notices' => 'Prikaži akcije',
86639284 'centralnotice-list-templates' => 'Seznam pasic',
8664 - 'centralnotice-multiple' => 'več ($1)',
 9285+ 'centralnotice-multiple-projects' => 'več ($1)',
 9286+ 'centralnotice-multiple-languages' => 'več ($1)',
86659287 'centralnotice-all-projects' => 'Vsi projekti',
86669288 'centralnotice-translations' => 'Prevodi',
86679289 'centralnotice-translate-to' => 'Prevedi v',
@@ -8749,6 +9371,9 @@
87509372 'centralnotice-banner-type' => 'Vrsta pasice:',
87519373 'centralnotice-banner-hidable' => 'Statična/Skrita',
87529374 'centralnotice-banner-collapsible' => 'Zložljiva',
 9375+ 'centralnotice-banner-fundraising' => 'To je donatorska pasica',
 9376+ 'centralnotice-banner-fundraising-help' => 'Ustvarite sidrno oznako v telesu pasice z id="cn_fundraising_link" in spodaj vnesite eno ali več ciljnih strani, na primer "JimmyAppeal01". Celotna povezava bo ustvarjena samodejno.',
 9377+ 'centralnotice-banner-landing-pages' => 'Ciljne strani (ločene z vejicami):',
87539378 'centralnotice-geotargeted' => 'Geociljano',
87549379 'centralnotice-countries' => 'Države',
87559380 'centralnotice-allocation' => 'Dodelitev',
@@ -8763,30 +9388,98 @@
87649389 'centralnotice-documentwrite-error' => 'document.write() ni mogoče uporabiti v pasici.
87659390 Oglejte si http://meta.wikimedia.org/wiki/Help:CentralNotice za več informacij.',
87669391 'centralnotice-preferred' => 'Prednostno',
 9392+ 'centralnotice-logs' => 'Dnevniki',
 9393+ 'centralnotice-view-logs' => 'Ogled dnevnikov',
87679394 );
87689395
87699396 /** Albanian (Shqip)
87709397 * @author Mikullovci11
87719398 * @author Olsi
87729399 * @author Techlik
 9400+ * @author Vinie007
87739401 */
87749402 $messages['sq'] = array(
 9403+ 'centralnotice' => 'Menaxhimi e mesazheve qendrore',
 9404+ 'noticetemplate' => 'Menaxhimi e mesazheve qendrore',
 9405+ 'bannerallocation' => 'Menaxhimi e mesazheve qendrore',
 9406+ 'right-centralnotice-admin' => 'Menaxhoni mesazhet qendrore',
 9407+ 'action-centralnotice-admin' => 'menaxhoni mesazhet qendrore',
 9408+ 'centralnotice-desc' => 'Ju lejon, të krijoni mesazhe qendrore për Wiki.',
 9409+ 'centralnotice-summary' => 'Ky modul ju lejon që të editoni shënimet tuaja të tanishme qendrore.
 9410+Ai gjithashtu mund të përdoret për të shtuar ose hequr njoftime të vjetra.',
 9411+ 'centralnotice-query' => 'Ndryshoni mesazhin aktuale',
 9412+ 'centralnotice-notice-name' => 'Emri i shënimit',
87759413 'centralnotice-end-date' => 'Data e përfundimit',
 9414+ 'centralnotice-enabled' => 'Aktivizuar',
87769415 'centralnotice-modify' => 'Dërgo',
 9416+ 'centralnotice-save-banner' => 'Dërgo Stampën',
87779417 'centralnotice-preview' => 'Parapamje',
 9418+ 'centralnotice-nopreview' => '(Pamjeje jo në dispozicion)',
 9419+ 'centralnotice-add-new' => 'Shto një mesazh të re',
87789420 'centralnotice-remove' => 'Largo',
 9421+ 'centralnotice-translate-heading' => 'Përkthimi për $1',
 9422+ 'centralnotice-manage' => 'Menaxhimi e mesazheve qendrore',
 9423+ 'centralnotice-manage-templates' => 'Menaxhoni Stampat',
87799424 'centralnotice-add' => 'Shto',
 9425+ 'centralnotice-add-notice' => 'Shto një mesazh të re',
 9426+ 'centralnotice-edit-notice' => 'Redaktoni mesazhet',
 9427+ 'centralnotice-add-template' => 'Shtoni një stampë',
 9428+ 'centralnotice-show-notices' => 'Shiko mesazhet',
 9429+ 'centralnotice-list-templates' => 'Lista e stampëve',
 9430+ 'centralnotice-multiple-projects' => 'Më shumë ($1)',
 9431+ 'centralnotice-multiple-languages' => 'Më shumë ($1)',
87809432 'centralnotice-all-projects' => 'Të gjitha projekte',
87819433 'centralnotice-translations' => 'Përkthyes',
87829434 'centralnotice-translate-to' => 'Përkthime',
87839435 'centralnotice-translate' => 'Përkthime',
87849436 'centralnotice-english' => 'Anglisht',
 9437+ 'centralnotice-banner-name' => 'Emri i stampës:',
 9438+ 'centralnotice-banner' => 'Stampë',
 9439+ 'centralnotice-banner-heading' => 'Stampë: $1',
 9440+ 'centralnotice-templates' => 'Stampat',
 9441+ 'centralnotice-weight' => 'Peshësia',
 9442+ 'centralnotice-locked' => 'I bllokuar',
 9443+ 'centralnotice-notice' => 'Mesazh',
 9444+ 'centralnotice-notice-heading' => 'Mesazh: $1',
 9445+ 'centralnotice-notices' => 'Mesazhet',
 9446+ 'centralnotice-notice-exists' => 'Ky mesazhi ekziston.
 9447+Prandaj mesazhi nuk është shtuar.',
 9448+ 'centralnotice-no-language' => 'Për këtë mesaxh nuk është zgjedhur gjuha. Prandaj nuk u shtuar.',
 9449+ 'centralnotice-no-project' => 'Për këtë projekt nuk është zgjedhur fushata. Prandaj nuk u shtuar.',
 9450+ 'centralnotice-template-exists' => 'Stampa ekziston.
 9451+Prandaj stampa nuk është shtuar.',
 9452+ 'centralnotice-notice-doesnt-exist' => 'Mesazhi nuk ekziston.',
 9453+ 'centralnotice-remove-notice-doesnt-exist' => 'Mesazhi nuk ekziston.
 9454+Largimi nuk është e mundur.',
 9455+ 'centralnotice-banner-doesnt-exist' => 'Stampa nuk ekziston.',
 9456+ 'centralnotice-template-still-bound' => 'Stampa është ende i lidhur me një mesazh.
 9457+Largimi nuk është e mundur.',
 9458+ 'centralnotice-template-body' => 'Teksti i stampës',
87859459 'centralnotice-day' => 'Ditë',
87869460 'centralnotice-year' => 'Viti',
87879461 'centralnotice-month' => 'Muaj',
87889462 'centralnotice-hours' => 'Orë',
87899463 'centralnotice-min' => 'Minutë',
87909464 'centralnotice-project-lang' => 'Gjuha e Projektit',
 9465+ 'centralnotice-select' => 'Zgjidheni: $1',
 9466+ 'centralnotice-top-ten-languages' => 'Top-10-Gjuhat',
 9467+ 'centralnotice-project-name' => 'Emri i projektit',
 9468+ 'centralnotice-start-date' => 'Data e fillimit',
 9469+ 'centralnotice-start-time' => 'Koha e fillimit (UTC)',
 9470+ 'centralnotice-end-time' => 'Koha e përfundimit',
 9471+ 'centralnotice-assigned-templates' => 'Stampat e caktuara',
 9472+ 'centralnotice-no-templates' => 'Nuk ka rezultate që përputhen me kërkesën.
 9473+Shtoje prandaj!',
 9474+ 'centralnotice-no-templates-assigned' => 'Nuk ka baner të lidhur me fushatën.
 9475+Shtoni disa!',
 9476+ 'centralnotice-available-templates' => 'Stampat në dispozicion',
 9477+ 'centralnotice-template-already-exists' => 'Baneri është tashmë i lidhur për fushatën.
 9478+Nuk ka shtim.',
 9479+ 'centralnotice-preview-template' => 'Parapamje e stampës',
 9480+ 'centralnotice-change-lang' => 'Ndryshoni gjuhën përkthimi',
 9481+ 'centralnotice-weights' => 'Peshësia',
 9482+ 'centralnotice-notice-is-locked' => 'Mesazhi është e bllokuar.
 9483+Kjo nuk mund të hiqet.',
87919484 'centralnotice-overlap' => 'Fushata përputhet me kohën e një fushate tjetër.
87929485 Nuk ka shtim.',
87939486 'centralnotice-invalid-date-range' => 'Bashkësi e gabuar për datën.
@@ -8800,14 +9493,46 @@
88019494 'centralnotice-no-templates-translate' => 'Nuk ka asnjë parullë për tu redaktuar për përkthime.',
88029495 'centralnotice-number-uses' => 'Përdorues',
88039496 'centralnotice-settings' => 'Alternativa',
 9497+ 'centralnotice-edit-template' => 'Redaktoni Stampën',
88049498 'centralnotice-edit-template-summary' => 'Për të krijuar një mesazh të lokalizuar, bashkangjitni një varg i shkruar me vizë në kllapa tre valë-valë, si p.sh. {{{jimbo-quote}}}.',
88059499 'centralnotice-message' => 'Mesazh',
 9500+ 'centralnotice-message-not-set' => 'Mesauhi nuk është caktuar',
88069501 'centralnotice-clone' => 'Mbylle',
 9502+ 'centralnotice-clone-notice' => 'Krijo një kopje të Stampës',
88079503 'centralnotice-clone-name' => 'Emri:',
 9504+ 'centralnotice-preview-all-template-translations' => 'Shikoni të gjitha përkthimet e mundshme të "banner"',
 9505+ 'centralnotice-insert' => 'Shtoni: $1',
 9506+ 'centralnotice-hide-button' => 'Hsheh Lidhjen',
 9507+ 'centralnotice-collapse-button' => 'Rënë Lidhjen',
 9508+ 'centralnotice-expand-button' => ' Zmadhoje Lidhjen',
 9509+ 'centralnotice-close-button' => 'Mbylle buton',
 9510+ 'centralnotice-translate-button' => 'Lidhja ndihmues',
 9511+ 'centralnotice-donate-button' => 'Buton për dhurim',
 9512+ 'centralnotice-expanded-banner' => '"Banner" i zgjeruar',
 9513+ 'centralnotice-collapsed-banner' => '"Banner" i zvogëluar',
 9514+ 'centralnotice-banner-display' => 'Shfaqe për:',
 9515+ 'centralnotice-banner-anonymous' => 'Përdoruesit anonim',
 9516+ 'centralnotice-banner-logged-in' => 'Përdoruesit të regjistruar',
 9517+ 'centralnotice-banner-type' => 'Lloji i stampës:',
 9518+ 'centralnotice-banner-hidable' => 'Statik/I mundshëm për fshehje',
 9519+ 'centralnotice-banner-collapsible' => 'I mundshëm për zvogëlim',
 9520+ 'centralnotice-banner-fundraising' => 'Ky është një flamur për mbledhjen e fondeve',
 9521+ 'centralnotice-banner-fundraising-help' => 'Krijo një spirancë tag në trup flamurin me id = "cn_fundraising_link" dhe hyjnë në një apo më shumë faqe ulje më poshtë, për shembull, "JimmyAppeal01". Href e lidhjes do të ndërtohet automatikisht.',
 9522+ 'centralnotice-banner-landing-pages' => 'Faqet ulje (comma-ndarë):',
 9523+ 'centralnotice-geotargeted' => 'Geo-objektiv',
 9524+ 'centralnotice-countries' => 'Shtetet',
 9525+ 'centralnotice-allocation' => 'Rregullimi',
 9526+ 'centralnotice-view-allocation' => 'Shikoni rregullimin e Stampës',
88089527 'centralnotice-allocation-instructions' => 'Zgjidhni mjedisin që dëshironi të shihni shpërndarjen e "bannerit" për:',
88099528 'centralnotice-languages' => 'Gjuha',
88109529 'centralnotice-projects' => 'Projekte',
88119530 'centralnotice-country' => 'Veni',
 9531+ 'centralnotice-no-allocation' => 'As një stampë e caktuar.',
 9532+ 'centralnotice-allocation-description' => 'Caktimi e stampës për $1.$2 në $3:',
 9533+ 'centralnotice-percentage' => 'Përqindje',
 9534+ 'centralnotice-documentwrite-error' => 'document.write() nuk mund të përdoret brenda një "banneri".
 9535+Shikoni http://meta.wikimedia.org/wiki/Help:CentralNotice për më shumë informacion.',
 9536+ 'centralnotice-preferred' => 'Preferuar',
88129537 );
88139538
88149539 /** Serbian Cyrillic ekavian (‪Српски (ћирилица)‬)
@@ -8884,7 +9609,7 @@
88859610 'centralnotice-clone-name' => 'Име:',
88869611 );
88879612
8888 -/** Serbian Latin ekavian (Srpski (latinica))
 9613+/** Serbian Latin ekavian (‪Srpski (latinica)‬)
88899614 * @author Michaello
88909615 */
88919616 $messages['sr-el'] = array(
@@ -8959,7 +9684,9 @@
89609685 */
89619686 $messages['stq'] = array(
89629687 'centralnotice' => 'Adminstrierenge fon do zentroale Mäldengen',
8963 - 'noticetemplate' => 'Zentroale Mäldengs-Foarloage',
 9688+ 'noticetemplate' => 'Ferwaltenge fon zentroale Mäldengen',
 9689+ 'right-centralnotice-admin' => 'Ferwaltjen fon zentroale Mäldengen',
 9690+ 'action-centralnotice-admin' => 'Zentroale Siedennotiz ferfaalen',
89649691 'centralnotice-desc' => "Föiget ne zentroale ''sitenotice'' bietou",
89659692 'centralnotice-summary' => 'Disse Ärwiederenge ferlööwet ju Konfiguration fon zentroale Mäldengen.
89669693 Ju kon uk tou dät Moakjen fon näie un Läskenge fon oolde Mäldengen ferwoand wäide.',
@@ -8982,7 +9709,7 @@
89839710 'centralnotice-translate-to' => 'Uursätte in',
89849711 'centralnotice-translate' => 'Uursätte',
89859712 'centralnotice-english' => 'Ängelsk',
8986 - 'centralnotice-banner-name' => 'Noome fon ju Foarloage',
 9713+ 'centralnotice-banner-name' => 'Noome fon ju Foarloage:',
89879714 'centralnotice-templates' => 'Foarloagen',
89889715 'centralnotice-weight' => 'Gewicht',
89899716 'centralnotice-locked' => 'Speerd',
@@ -8991,8 +9718,7 @@
89929719 Nit bietouföiged.',
89939720 'centralnotice-template-exists' => 'Foarloage is al deer.
89949721 Nit bietouföiged.',
8995 - 'centralnotice-notice-doesnt-exist' => 'Mäldenge is nit deer.
8996 -Wächhoaljen nit muugelk.',
 9722+ 'centralnotice-notice-doesnt-exist' => 'Mäldenge is nit deer.',
89979723 'centralnotice-template-still-bound' => 'Foarloage is noch an ne Mäldengen buunen.
89989724 Wächhoaljen nit muugelk.',
89999725 'centralnotice-template-body' => 'Foarloagentext:',
@@ -9012,7 +9738,7 @@
90139739 'centralnotice-available-templates' => 'Ferföichboare Foarloagen',
90149740 'centralnotice-template-already-exists' => 'Foarloage is al an ju Kampagne buunen.
90159741 Nit bietouföiged.',
9016 - 'centralnotice-preview-template' => 'Foarschau Foarloage',
 9742+ 'centralnotice-preview-template' => 'Foarbekiek Foarloage',
90179743 'centralnotice-change-lang' => 'Uursättengssproake annerje',
90189744 'centralnotice-weights' => 'Gewicht',
90199745 'centralnotice-notice-is-locked' => 'Mäldenge is speerd.
@@ -9034,11 +9760,7 @@
90359761 'centralnotice-message-not-set' => 'Ättergjucht nit sät.',
90369762 'centralnotice-clone' => 'Klon moakje',
90379763 'centralnotice-clone-notice' => 'Moak ne Kopie fon ju Foarloage',
9038 - 'centralnotice-preview-all-template-translations' => 'Foarschau fon aal do ferföichboare Uursättengen fon ne Foarloage',
9039 - 'right-centralnotice-admin' => 'Ferwaltjen fon zentroale Mäldengen',
9040 - 'right-centralnotice-translate' => 'Uursätten fon zentroale Mäldengen',
9041 - 'action-centralnotice-admin' => 'Zentroale Siedennotiz ferfaalen',
9042 - 'action-centralnotice-translate' => 'Zentroale Siedennotiz uursätte',
 9764+ 'centralnotice-preview-all-template-translations' => 'Foarbekiek fon aal do ferföichboare Uursättengen fon ne Foarloage',
90439765 'centralnotice-preferred' => 'Foarleeken',
90449766 );
90459767
@@ -9050,6 +9772,7 @@
90519773 );
90529774
90539775 /** Swedish (Svenska)
 9776+ * @author Ainali
90549777 * @author Boivie
90559778 * @author Cohan
90569779 * @author Fluff
@@ -9074,6 +9797,7 @@
90759798 'centralnotice-modify' => 'Verkställ',
90769799 'centralnotice-save-banner' => 'Spara banner',
90779800 'centralnotice-preview' => 'Förhandsgranska',
 9801+ 'centralnotice-nopreview' => '(Förhandsgranskning inte tillgänglig)',
90789802 'centralnotice-add-new' => 'Lägg till ett nytt centralmeddelande',
90799803 'centralnotice-remove' => 'Ta bort',
90809804 'centralnotice-translate-heading' => 'Översättning för $1',
@@ -9085,7 +9809,8 @@
90869810 'centralnotice-add-template' => 'Lägg till en mall',
90879811 'centralnotice-show-notices' => 'Visa meddelanden',
90889812 'centralnotice-list-templates' => 'Lista mallar',
9089 - 'centralnotice-multiple' => 'flera ($1)',
 9813+ 'centralnotice-multiple-projects' => 'flera ($1)',
 9814+ 'centralnotice-multiple-languages' => 'flera ($1)',
90909815 'centralnotice-all-projects' => 'Alla projekt',
90919816 'centralnotice-translations' => 'Översättningar',
90929817 'centralnotice-translate-to' => 'Översätt till',
@@ -9209,6 +9934,7 @@
92109935
92119936 /** Tamil (தமிழ்)
92129937 * @author TRYPPN
 9938+ * @author செல்வா
92139939 */
92149940 $messages['ta'] = array(
92159941 'centralnotice-end-date' => 'முடிவுத்தேதி',
@@ -9217,7 +9943,8 @@
92189944 'centralnotice-preview' => 'முன்தோற்றம்',
92199945 'centralnotice-remove' => 'நீக்கு',
92209946 'centralnotice-add' => 'சேர்க்கவும்',
9221 - 'centralnotice-multiple' => 'ஒன்றுக்கு மேற்பட்ட ($1)',
 9947+ 'centralnotice-multiple-projects' => 'ஒன்றுக்கு மேற்பட்ட ($1)',
 9948+ 'centralnotice-multiple-languages' => 'ஒன்றுக்கு மேற்பட்ட ($1)',
92229949 'centralnotice-translations' => 'மொழிபெயர்ப்புக்கள்',
92239950 'centralnotice-translate-to' => 'மொழிபெயர்ப்பு செய்யவும்',
92249951 'centralnotice-translate' => 'மொழிபெயர்ப்பு செய்யவும்',
@@ -9228,13 +9955,13 @@
92299956 'centralnotice-year' => 'ஆண்டு',
92309957 'centralnotice-month' => 'மாதம்',
92319958 'centralnotice-hours' => 'மணி',
9232 - 'centralnotice-min' => 'நிமிடம்',
 9959+ 'centralnotice-min' => 'நிமிடம் (மணித்துளி)',
92339960 'centralnotice-project-lang' => 'திட்டத்தின் மொழி',
92349961 'centralnotice-select' => 'தேர்ந்தெடுக்கவும்:$1',
9235 - 'centralnotice-top-ten-languages' => 'உயர்நிலையில் உள்ள 10 மொழிகள்',
 9962+ 'centralnotice-top-ten-languages' => 'முன்வரிசையில் உள்ள 10 மொழிகள்',
92369963 'centralnotice-project-name' => 'திட்டத்தின் பெயர்',
9237 - 'centralnotice-start-date' => 'ஆரம்பத்தேதி',
9238 - 'centralnotice-start-time' => 'ஆரம்ப நேரம் (UTC)',
 9964+ 'centralnotice-start-date' => 'தொடக்க நாள்',
 9965+ 'centralnotice-start-time' => 'தொடக்க நேரம் (UTC)',
92399966 'centralnotice-end-time' => 'முடிவு நேரம் (UTC)',
92409967 'centralnotice-change-lang' => 'மொழிபெயர்ப்புக்கான மொழியை மாற்றவும்',
92419968 'centralnotice-weights' => 'எடைகள்',
@@ -9260,27 +9987,35 @@
92619988 'noticetemplate' => 'కేంద్రీయ గమనిక నిర్వహణ',
92629989 'right-centralnotice-admin' => 'కేంద్రీయ గమనికలని నిర్వహించగలగడం',
92639990 'centralnotice-desc' => 'కేంద్రీయ సైటు గమనికని చేరుస్తుంది',
 9991+ 'centralnotice-summary' => 'మీ ప్రస్తుత కేంద్రీయ గమనికలను మార్చుకునేందుకు ఈ మాడ్యూలు వీలు కలిగిస్తుంది.
 9992+కొత్త గమనికలను చేర్చేందుకు, పాత గమనికలను తీసేసేందుకూ కూడా దీన్ని వాడవచ్చు',
92649993 'centralnotice-notice-name' => 'గమనిక పేరు',
92659994 'centralnotice-end-date' => 'ముగింపు తేదీ',
92669995 'centralnotice-enabled' => 'చేతనమైంది',
92679996 'centralnotice-modify' => 'దాఖలుచేయి',
92689997 'centralnotice-preview' => 'మునుజూపు',
 9998+ 'centralnotice-nopreview' => '(మునుజూపు అందుబాటులో లేదు)',
92699999 'centralnotice-add-new' => 'కొత్త కేంద్రీయ గమనికని చేర్చు',
927010000 'centralnotice-remove' => 'తొలగించు',
927110001 'centralnotice-translate-heading' => '$1కి అనువాదం',
927210002 'centralnotice-manage' => 'ప్రచారోద్యమాల నిర్వహణ',
 10003+ 'centralnotice-manage-templates' => 'బ్యానర్లను నిర్వహించు',
927310004 'centralnotice-add' => 'చేర్చు',
927410005 'centralnotice-add-notice' => 'ఒక ప్రచారోద్యమాన్ని చేర్చండి',
927510006 'centralnotice-edit-notice' => 'ప్రచారోద్యమాన్ని మార్చండి',
927610007 'centralnotice-add-template' => 'ఒక మూసని చేర్చు',
927710008 'centralnotice-show-notices' => 'ప్రచారోద్యమాలని చూపించు',
927810009 'centralnotice-list-templates' => 'మూసలను చూపించు',
9279 - 'centralnotice-multiple' => 'బహుళం ($1)',
 10010+ 'centralnotice-multiple-projects' => 'బహుళం ($1)',
 10011+ 'centralnotice-multiple-languages' => 'బహుళం ($1)',
928010012 'centralnotice-all-projects' => 'అన్ని ప్రాజెక్టులు',
928110013 'centralnotice-translations' => 'అనువాదాలు',
 10014+ 'centralnotice-translate-to' => 'ఈ భాషలోకి అనువదించు',
928210015 'centralnotice-translate' => 'అనువదించండి',
9283 - 'centralnotice-english' => 'ఇంగ్లీష్',
9284 - 'centralnotice-banner-name' => 'మూస పేరు',
 10016+ 'centralnotice-english' => 'ఆంగ్లం',
 10017+ 'centralnotice-banner-name' => 'బ్యానరు పేరు:',
 10018+ 'centralnotice-banner' => 'బ్యానరు',
 10019+ 'centralnotice-banner-heading' => 'బ్యానరు: $1',
928510020 'centralnotice-templates' => 'మూసలు',
928610021 'centralnotice-weight' => 'భారం',
928710022 'centralnotice-locked' => 'తాళం వేసారు',
@@ -9290,11 +10025,15 @@
929110026 'centralnotice-notice-exists' => 'గమనిక ఇప్పటికే ఉంది.
929210027 చేర్చట్లేదు',
929310028 'centralnotice-no-language' => 'ప్రచారోద్యమానికి ఏ భాషనీ ఎంచుకోలేదు. కనుక చేర్చట్లేదు.',
 10029+ 'centralnotice-no-project' => 'ప్రచారం కోసం ప్రాజెక్టు దేన్నీ ఎంచుకోలేదు. చేర్చడం లేదు.',
929410030 'centralnotice-template-exists' => 'మూస ఇప్పటికే ఉంది.
929510031 చేర్చట్లేదు',
929610032 'centralnotice-notice-doesnt-exist' => 'ప్రచారోద్యమం లేనే లేదు.',
929710033 'centralnotice-remove-notice-doesnt-exist' => 'ప్రచారోద్యమం లేనే లేదు.
929810034 తొలగించాల్సింది ఏమీలేదు.',
 10035+ 'centralnotice-banner-doesnt-exist' => 'బ్యానరు ఉనికిలో లేదు.',
 10036+ 'centralnotice-template-still-bound' => 'ఈ బ్యానరు ఇంకా ప్రచారంలో భాగంగా ఉంది.
 10037+తీసెయ్యడం లేదు.',
929910038 'centralnotice-template-body' => 'మూస వివరణ:',
930010039 'centralnotice-day' => 'రోజు',
930110040 'centralnotice-year' => 'సంవత్సరం',
@@ -9308,48 +10047,74 @@
930910048 'centralnotice-start-date' => 'ప్రారంభ తేదీ',
931010049 'centralnotice-start-time' => 'ప్రారంభ సమయం (UTC)',
931110050 'centralnotice-end-time' => 'ముగింపు సమయం (UTC)',
 10051+ 'centralnotice-assigned-templates' => 'నిర్దేశించబడిన బ్యానర్లు',
931210052 'centralnotice-no-templates' => 'మూసలు ఏమీ లేవు.
931310053 కొన్నింటిని చేర్చండి!',
 10054+ 'centralnotice-no-templates-assigned' => 'ప్రచారానికి బ్యానర్లేవీ నిర్దేశించబడి లేవు.
 10055+కొన్నిటిని చేర్చండి!',
931410056 'centralnotice-available-templates' => 'అందుబాటులో ఉన్న మూసలు',
 10057+ 'centralnotice-template-already-exists' => 'ఈ బ్యానరు ఈసరికే ఓ ప్రచారానికి అనుసంధించబడి ఉంది.
 10058+చేర్చడం లేదు.',
931510059 'centralnotice-preview-template' => 'మూస మునుజూపు',
931610060 'centralnotice-change-lang' => 'అనువాదపు భాషని మార్చండి',
931710061 'centralnotice-weights' => 'భారాలు',
931810062 'centralnotice-notice-is-locked' => 'ప్రచారోద్యమానికి తాళంవేసారు.
931910063 తొలగించడం లేదు.',
 10064+ 'centralnotice-overlap' => 'ఈ ప్రచారం వ్యవధి మరో ప్రచారపు సమయంతో ఓవరుల్యాపై ఉంది.
 10065+చేర్చడం లేదు.',
932010066 'centralnotice-invalid-date-range' => 'చెల్లని తేదీ అవధి.
932110067 తాజాకరించుటలేదు.',
 10068+ 'centralnotice-null-string' => 'నల్ స్స్ట్రింగును చేర్చలేం.
 10069+చేర్చడం లేదు.',
932210070 'centralnotice-confirm-delete' => 'ఈ అంశాన్ని మీరు నిజంగానే తొలగించాలనుకుంటున్నారా?
932310071 ఈ చర్యని వెనక్కితీసుకోలేరు.',
932410072 'centralnotice-no-notices-exist' => 'గమనికలు ఏమీ లేవు.
932510073 క్రింద చేర్చండి.',
 10074+ 'centralnotice-no-templates-translate' => 'అనువాదాలను సవరించాల్సిన బ్యానర్లేమీ లేవు.',
932610075 'centralnotice-number-uses' => 'వాడుకరులు',
932710076 'centralnotice-settings' => 'అమరికలు',
932810077 'centralnotice-edit-template' => 'మూసని మార్చు',
932910078 'centralnotice-edit-template-summary' => 'అనువదించదగ్గ సందేశాన్ని సృష్టించడానికి, హైఫన్లతో కూడిన పదబంధాన్ని మూడు మీసాల బ్రాకెట్ల మధ్యలో ఉంచండి, ఉ.దా. {{{jimbo-quote}}}.',
933010079 'centralnotice-message' => 'సందేశం',
 10080+ 'centralnotice-message-not-set' => 'సందేశం సెట్ చెయ్యలేదు',
 10081+ 'centralnotice-clone' => 'అనుసృజించు (క్లోన్)',
 10082+ 'centralnotice-clone-notice' => 'బ్యానరు యొక్క కాపీని సృష్టించు',
933110083 'centralnotice-clone-name' => 'పేరు:',
 10084+ 'centralnotice-preview-all-template-translations' => 'బ్యానరుకు ఉన్న అనువాదాలన్నిటినీ మునుజూడు',
 10085+ 'centralnotice-insert' => 'చేర్చు: $1',
933210086 'centralnotice-hide-button' => 'దాచు లంకె',
933310087 'centralnotice-collapse-button' => 'కుదించు లంకె',
933410088 'centralnotice-expand-button' => 'విస్తరించు లంకె',
933510089 'centralnotice-close-button' => 'మూసివేయి బొత్తం',
933610090 'centralnotice-translate-button' => 'అనువాదానికి తోడ్పడండి లంకె',
933710091 'centralnotice-donate-button' => 'విరాళమివ్వండి బొత్తం',
 10092+ 'centralnotice-expanded-banner' => 'విస్తరించబడిన బ్యానరు',
 10093+ 'centralnotice-collapsed-banner' => 'మూసేసిన బ్యానరు',
933810094 'centralnotice-banner-display' => 'ఎవరికి చూపించాలి:',
933910095 'centralnotice-banner-anonymous' => 'అజ్ఞాత వాడుకరులు',
934010096 'centralnotice-banner-logged-in' => 'ప్రవేశించిన వాడుకరులు',
 10097+ 'centralnotice-banner-type' => 'బ్యానరు రకం:',
934110098 'centralnotice-banner-hidable' => 'స్థిరం/దాచదగ్గది',
 10099+ 'centralnotice-banner-collapsible' => 'మూసివేయదగిన',
934210100 'centralnotice-countries' => 'దేశాలు',
934310101 'centralnotice-allocation' => 'కేటాయింపు',
 10102+ 'centralnotice-view-allocation' => 'బ్యానరు కేటాయింపును చూపించు',
 10103+ 'centralnotice-allocation-instructions' => 'ఏ ఎన్విరాన్ మెంటు కోసం బ్యానరు కేటాయింపులు చూడాలనుకుంటున్నారో ఎంచుకోండి:',
934410104 'centralnotice-languages' => 'భాషలు',
934510105 'centralnotice-projects' => 'ప్రాజెక్టులు',
934610106 'centralnotice-country' => 'దేశం',
 10107+ 'centralnotice-no-allocation' => 'బ్యానర్లేమీ కేటాయించలేదు.',
 10108+ 'centralnotice-allocation-description' => '$3 లో $1.$2 కోసం బ్యానరు కేటాయింపు:',
934710109 'centralnotice-percentage' => 'శాతం',
 10110+ 'centralnotice-documentwrite-error' => 'బ్యానరు లోపల document.write() వాడజాలరు.
 10111+మరింత సమాచారం కోసం http://meta.wikimedia.org/wiki/Help:CentralNotice చూడండి.',
934810112 );
934910113
935010114 /** Tetum (Tetun)
935110115 * @author MF-Warburg
935210116 */
935310117 $messages['tet'] = array(
 10118+ 'centralnotice-remove' => 'Hasai',
935410119 'centralnotice-add' => 'Tau tan',
935510120 'centralnotice-translations' => 'Tradusaun sira',
935610121 'centralnotice-translate' => 'Tradús',
@@ -9361,6 +10126,8 @@
936210127 'centralnotice-project-lang' => 'Lian projetu nian',
936310128 'centralnotice-project-name' => 'Naran projetu nian',
936410129 'centralnotice-number-uses' => 'Uza',
 10130+ 'centralnotice-clone-name' => 'Naran:',
 10131+ 'centralnotice-languages' => 'Lian sira',
936510132 );
936610133
936710134 /** Tajik (Cyrillic) (Тоҷикӣ (Cyrillic))
@@ -9369,6 +10136,8 @@
937010137 $messages['tg-cyrl'] = array(
937110138 'centralnotice' => 'Мудири эълони мутамарказ',
937210139 'noticetemplate' => 'Шаблони эълони мутамарказ',
 10140+ 'right-centralnotice-admin' => 'Идоракунии эълонҳои мутамарказ',
 10141+ 'action-centralnotice-admin' => 'идоракунии эълонҳои мутамарказ',
937310142 'centralnotice-desc' => 'Як иттилооти маркази илова мекунад',
937410143 'centralnotice-summary' => 'Ин модул ба шумо имкони вироиги насби эълони мутамаркази кунинро пешкаш мекунад.
937510144 Он боз метавонад барои изофа ё пок кардани эълонҳои кӯҳна истифода шавад.',
@@ -9445,10 +10214,6 @@
944610215 'centralnotice-clone' => 'Клон',
944710216 'centralnotice-clone-notice' => 'Эҷоди як нусхаи ин шаблон',
944810217 'centralnotice-preview-all-template-translations' => 'Пешнамоиши ҳамаи тарҷумаҳои дастраси шаблон',
9449 - 'right-centralnotice-admin' => 'Идоракунии эълонҳои мутамарказ',
9450 - 'right-centralnotice-translate' => 'Тарҷумаи эълонҳои мутамарказ',
9451 - 'action-centralnotice-admin' => 'идоракунии эълонҳои мутамарказ',
9452 - 'action-centralnotice-translate' => 'тарҷумаи эълонҳои мутамарказ',
945310218 'centralnotice-preferred' => 'Тарҷиҳи додашуда',
945410219 );
945510220
@@ -9458,6 +10223,8 @@
945910224 $messages['tg-latn'] = array(
946010225 'centralnotice' => "Mudiri e'loni mutamarkaz",
946110226 'noticetemplate' => "Şabloni e'loni mutamarkaz",
 10227+ 'right-centralnotice-admin' => "Idorakuniji e'lonhoi mutamarkaz",
 10228+ 'action-centralnotice-admin' => "idorakuniji e'lonhoi mutamarkaz",
946210229 'centralnotice-desc' => 'Jak ittilooti markazi ilova mekunad',
946310230 'centralnotice-summary' => "In modul ba şumo imkoni viroigi nasbi e'loni mutamarkazi kuninro peşkaş mekunad.
946410231 On boz metavonad baroi izofa jo pok kardani e'lonhoi kūhna istifoda şavad.",
@@ -9534,10 +10301,6 @@
953510302 'centralnotice-clone' => 'Klon',
953610303 'centralnotice-clone-notice' => 'Eçodi jak nusxai in şablon',
953710304 'centralnotice-preview-all-template-translations' => 'Peşnamoişi hamai tarçumahoi dastrasi şablon',
9538 - 'right-centralnotice-admin' => "Idorakuniji e'lonhoi mutamarkaz",
9539 - 'right-centralnotice-translate' => "Tarçumai e'lonhoi mutamarkaz",
9540 - 'action-centralnotice-admin' => "idorakuniji e'lonhoi mutamarkaz",
9541 - 'action-centralnotice-translate' => "tarçumai e'lonhoi mutamarkaz",
954210305 'centralnotice-preferred' => 'Tarçihi dodaşuda',
954310306 );
954410307
@@ -9550,6 +10313,8 @@
955110314 $messages['th'] = array(
955210315 'centralnotice' => 'การจัดการประกาศส่วนกลาง',
955310316 'noticetemplate' => 'แม่แบบประกาศของส่้วนกลาง',
 10317+ 'right-centralnotice-admin' => 'จัดการประกาศส่วนกลาง',
 10318+ 'action-centralnotice-admin' => 'จัดการประกาศส่วนกลาง',
955410319 'centralnotice-desc' => 'เพิ่มประกาศส่วนกลางของไซต์',
955510320 'centralnotice-summary' => 'คุณสามารถแก้ไขประกาศส่วนกลางปัจจุบันได้ โดยใช้เครื่องมือนี้
955610321 คุณสามารถเพิ่มหรือนำประกาศเก่าออกได้เช่นกัน',
@@ -9626,10 +10391,6 @@
962710392 'centralnotice-clone' => 'สำเนา',
962810393 'centralnotice-clone-notice' => 'สร้างสำเนาของแม่แบบ',
962910394 'centralnotice-preview-all-template-translations' => 'ดูการแปลในทุก ๆ ภาษาของแม่แบบ',
9630 - 'right-centralnotice-admin' => 'จัดการประกาศส่วนกลาง',
9631 - 'right-centralnotice-translate' => 'แปลประกาศส่วนกลาง',
9632 - 'action-centralnotice-admin' => 'จัดการประกาศส่วนกลาง',
9633 - 'action-centralnotice-translate' => 'แปลประกาศส่วนกลาง',
963410395 'centralnotice-preferred' => 'แบบที่เลือก',
963510396 );
963610397
@@ -9663,7 +10424,8 @@
966410425 'centralnotice-add-template' => 'Şablon goş',
966510426 'centralnotice-show-notices' => 'Uwedomleniýeleri görkez',
966610427 'centralnotice-list-templates' => 'Şablonlaryň sanawyny görkez',
9667 - 'centralnotice-multiple' => 'köpsanly ($1)',
 10428+ 'centralnotice-multiple-projects' => 'köpsanly ($1)',
 10429+ 'centralnotice-multiple-languages' => 'köpsanly ($1)',
966810430 'centralnotice-translations' => 'Terjimeler',
966910431 'centralnotice-translate-to' => 'Şu dile terjime et:',
967010432 'centralnotice-translate' => 'Terjime et',
@@ -9778,6 +10540,7 @@
977910541 'centralnotice-modify' => 'Ipasa',
978010542 'centralnotice-save-banner' => 'Sagipin ang bandera',
978110543 'centralnotice-preview' => 'Paunang tingin',
 10544+ 'centralnotice-nopreview' => '(Walang makuhang paunang-tingin)',
978210545 'centralnotice-add-new' => 'Magdagdag ng isang bagong pangunahing pabatid',
978310546 'centralnotice-remove' => 'Tanggalin',
978410547 'centralnotice-translate-heading' => 'Salinwika para sa $1',
@@ -9789,7 +10552,9 @@
979010553 'centralnotice-add-template' => 'Magdagdag ng isang suleras',
979110554 'centralnotice-show-notices' => 'Ipagkita ang mga pabatid',
979210555 'centralnotice-list-templates' => 'Itala ang mga suleras',
9793 - 'centralnotice-multiple' => 'maramihan ($1)',
 10556+ 'centralnotice-multiple-projects' => 'maramihan ($1)',
 10557+ 'centralnotice-multiple-languages' => 'maramihan ($1)',
 10558+ 'centralnotice-all-projects' => 'Lahat ng mga proyekto',
979410559 'centralnotice-translations' => 'Mga salinwika',
979510560 'centralnotice-translate-to' => 'Isalinwika patungong',
979610561 'centralnotice-translate' => 'Isalinwika',
@@ -9806,6 +10571,7 @@
980710572 'centralnotice-notice-exists' => 'Umiiral na ang pabatid/pahayag.
980810573 Hindi idaragdag',
980910574 'centralnotice-no-language' => 'Walang napiling wika para sa kampanya. Hindi idinaragdag.',
 10575+ 'centralnotice-no-project' => 'Walang napiling proyekto para sa kampanya. Hindi idaragdag.',
981010576 'centralnotice-template-exists' => 'Umiiral na ang suleras.
981110577 Hindi idinargdag',
981210578 'centralnotice-notice-doesnt-exist' => 'Hindi umiiral ang kampanya.',
@@ -9862,9 +10628,9 @@
986310629 'centralnotice-clone-name' => 'Pangalan:',
986410630 'centralnotice-preview-all-template-translations' => 'Paunang tanawin ang lahat ng mga makukuhang mga salinwika ng suleras',
986510631 'centralnotice-insert' => 'Isingit: $1',
9866 - 'centralnotice-hide-button' => 'Kawing na {{int:centralnotice-shared-hide}}',
9867 - 'centralnotice-collapse-button' => 'Kawing na {{int:centralnotice-shared-collapse}}',
9868 - 'centralnotice-expand-button' => 'Kawing na {{int:centralnotice-shared-expand}}',
 10632+ 'centralnotice-hide-button' => 'Itago ang kawing',
 10633+ 'centralnotice-collapse-button' => 'Ibagsak ang kawing',
 10634+ 'centralnotice-expand-button' => 'Ibuka ang kawing',
986910635 'centralnotice-close-button' => 'Pindutang pansara',
987010636 'centralnotice-translate-button' => 'Kawing na pantulong sa pagsasalinwika',
987110637 'centralnotice-donate-button' => 'Pindutang pang-abuloy',
@@ -9881,6 +10647,8 @@
988210648 'centralnotice-allocation' => 'Paglalaan',
988310649 'centralnotice-view-allocation' => 'Tingnan ang kabahagi ng bandera',
988410650 'centralnotice-allocation-instructions' => 'Piliin ang kapaligirang nais mong tingnan ang kabahagi ng bandera:',
 10651+ 'centralnotice-languages' => 'Mga wika',
 10652+ 'centralnotice-projects' => 'Mga proyekto',
988510653 'centralnotice-country' => 'Bansa',
988610654 'centralnotice-no-allocation' => 'Walang bandera ibinahagi.',
988710655 'centralnotice-allocation-description' => 'Ang banderang kabahagi para sa $1.$2 sa loob ng $3:',
@@ -9932,7 +10700,8 @@
993310701 'centralnotice-add-template' => 'Bir şablon ekle',
993410702 'centralnotice-show-notices' => 'Uyarıları göster',
993510703 'centralnotice-list-templates' => 'Şablonları listele',
9936 - 'centralnotice-multiple' => 'Çoklu ($1)',
 10704+ 'centralnotice-multiple-projects' => 'Çoklu ($1)',
 10705+ 'centralnotice-multiple-languages' => 'Çoklu ($1)',
993710706 'centralnotice-all-projects' => 'Tüm projeler',
993810707 'centralnotice-translations' => 'Çeviriler',
993910708 'centralnotice-translate-to' => 'Şu dile çevir',
@@ -10055,6 +10824,7 @@
1005610825 'centralnotice-modify' => 'Җибәрү',
1005710826 'centralnotice-save-banner' => 'Өлгене саклау',
1005810827 'centralnotice-preview' => 'Алдан карау',
 10828+ 'centralnotice-nopreview' => '(Алдан карау мөмкин түгел)',
1005910829 'centralnotice-add-new' => 'Яңа хәбәр өстәү',
1006010830 'centralnotice-remove' => 'Бетерү',
1006110831 'centralnotice-translate-heading' => '$1 өчен тәрҗемә',
@@ -10066,7 +10836,8 @@
1006710837 'centralnotice-add-template' => 'Үрнәк өстәү',
1006810838 'centralnotice-show-notices' => 'Хәбәрне ачарга',
1006910839 'centralnotice-list-templates' => 'Үрнәкләр исемлеге',
10070 - 'centralnotice-multiple' => 'берничә ($1)',
 10840+ 'centralnotice-multiple-projects' => 'берничә ($1)',
 10841+ 'centralnotice-multiple-languages' => 'берничә ($1)',
1007110842 'centralnotice-all-projects' => 'Барлык проектлар',
1007210843 'centralnotice-translations' => 'Тәрҗемәләр',
1007310844 'centralnotice-translate-to' => 'Тәрҗемә',
@@ -10207,6 +10978,7 @@
1020810979 'centralnotice-modify' => 'Відправити',
1020910980 'centralnotice-save-banner' => 'Зберегти банер',
1021010981 'centralnotice-preview' => 'Попередній перегляд',
 10982+ 'centralnotice-nopreview' => '(Попередній перегляд недоступний)',
1021110983 'centralnotice-add-new' => 'Додати нове централізоване повідомлення',
1021210984 'centralnotice-remove' => 'Вилучити',
1021310985 'centralnotice-translate-heading' => 'Переклад для $1',
@@ -10218,7 +10990,8 @@
1021910991 'centralnotice-add-template' => 'Додати шаблон',
1022010992 'centralnotice-show-notices' => 'Показати повідомлення',
1022110993 'centralnotice-list-templates' => 'Cписок шаблонів',
10222 - 'centralnotice-multiple' => 'декілька ($1)',
 10994+ 'centralnotice-multiple-projects' => 'декілька ($1)',
 10995+ 'centralnotice-multiple-languages' => 'декілька ($1)',
1022310996 'centralnotice-all-projects' => 'Всі проекти',
1022410997 'centralnotice-translations' => 'Переклади',
1022510998 'centralnotice-translate-to' => 'Переклад на',
@@ -10354,7 +11127,8 @@
1035511128 'centralnotice-add-template' => 'Zonta un modèl',
1035611129 'centralnotice-show-notices' => 'Mostra notifiche',
1035711130 'centralnotice-list-templates' => 'Elenca i modèi',
10358 - 'centralnotice-multiple' => 'multipli ($1)',
 11131+ 'centralnotice-multiple-projects' => 'multipli ($1)',
 11132+ 'centralnotice-multiple-languages' => 'multipli ($1)',
1035911133 'centralnotice-translations' => 'Tradussioni',
1036011134 'centralnotice-translate-to' => 'Tradusi con',
1036111135 'centralnotice-translate' => 'Tradusi',
@@ -10454,6 +11228,79 @@
1045511229 'centralnotice-preferred' => 'Preferìo',
1045611230 );
1045711231
 11232+/** Veps (Vepsan kel')
 11233+ * @author Игорь Бродский
 11234+ */
 11235+$messages['vep'] = array(
 11236+ 'centralnotice-end-date' => 'Lopdat',
 11237+ 'centralnotice-enabled' => 'Kävutamižes',
 11238+ 'centralnotice-modify' => 'Oigeta',
 11239+ 'centralnotice-save-banner' => 'Panda banner muštho',
 11240+ 'centralnotice-preview' => 'Ezikacund',
 11241+ 'centralnotice-nopreview' => '(Ei voi ezikacta)',
 11242+ 'centralnotice-remove' => 'Čuta poiš',
 11243+ 'centralnotice-translate-heading' => 'Känduz $1:n täht',
 11244+ 'centralnotice-manage-templates' => 'Ohjata bannerid',
 11245+ 'centralnotice-add' => 'Ližata',
 11246+ 'centralnotice-add-notice' => 'Ližata kampanii',
 11247+ 'centralnotice-edit-notice' => 'Redaktiruida kompanijad',
 11248+ 'centralnotice-add-template' => 'Ližata banner',
 11249+ 'centralnotice-show-notices' => 'Ozutada kampanijad',
 11250+ 'centralnotice-list-templates' => 'Ozutada banneriden nimikirjutez',
 11251+ 'centralnotice-multiple-projects' => 'Äjad ($1)',
 11252+ 'centralnotice-multiple-languages' => 'Äjad ($1)',
 11253+ 'centralnotice-all-projects' => 'Kaik projektad',
 11254+ 'centralnotice-translations' => 'Kändused',
 11255+ 'centralnotice-translate-to' => 'Känduz:',
 11256+ 'centralnotice-translate' => 'Käta',
 11257+ 'centralnotice-english' => 'Anglijaks',
 11258+ 'centralnotice-banner-name' => 'Banneran nimi:',
 11259+ 'centralnotice-banner' => 'Banner',
 11260+ 'centralnotice-banner-heading' => 'Banneri $1',
 11261+ 'centralnotice-templates' => 'Bannerad',
 11262+ 'centralnotice-weight' => 'Leveduz',
 11263+ 'centralnotice-locked' => 'Luklostadud',
 11264+ 'centralnotice-notice' => 'Kampanii',
 11265+ 'centralnotice-notice-heading' => 'Kampanii: $1',
 11266+ 'centralnotice-notices' => 'Kampanijad',
 11267+ 'centralnotice-notice-exists' => 'Mugoi kampanii om ko olmas.
 11268+Ei ližakoi.',
 11269+ 'centralnotice-no-language' => "Kel' kampanijan täht ei ole valitud. Ei ližakoi.",
 11270+ 'centralnotice-no-project' => 'Projekt kampanijan täht ei ole valitud. Ei ližakoi.',
 11271+ 'centralnotice-template-exists' => 'Mugoi šablon om jo olmas.
 11272+Ei ližakoi.',
 11273+ 'centralnotice-notice-doesnt-exist' => 'Mugošt kampanijad ei ole.',
 11274+ 'centralnotice-remove-notice-doesnt-exist' => 'Mugošt kampanijad ei ole.
 11275+Ei ole midä čuta poiš.',
 11276+ 'centralnotice-banner-doesnt-exist' => 'Mugošt bannerad ei ole.',
 11277+ 'centralnotice-template-body' => 'Banneran hibj:',
 11278+ 'centralnotice-day' => 'Päiv',
 11279+ 'centralnotice-year' => "Voz'",
 11280+ 'centralnotice-month' => 'Ku',
 11281+ 'centralnotice-hours' => 'Čas',
 11282+ 'centralnotice-min' => 'Minut',
 11283+ 'centralnotice-project-lang' => "Projektan kel'",
 11284+ 'centralnotice-select' => 'Valiče: $1',
 11285+ 'centralnotice-top-ten-languages' => "10 päkel't",
 11286+ 'centralnotice-project-name' => 'Projektannimi',
 11287+ 'centralnotice-start-date' => 'Augotišen dat',
 11288+ 'centralnotice-start-time' => 'Augotišen dat (UTC)',
 11289+ 'centralnotice-end-time' => 'Lopindan aig (UTC)',
 11290+ 'centralnotice-assigned-templates' => 'Kävutadud šablonad',
 11291+ 'centralnotice-no-templates' => 'Ei voi löuta bannerid.
 11292+Ližakat banner!',
 11293+ 'centralnotice-available-templates' => 'Olijad olmas bannerad',
 11294+ 'centralnotice-template-already-exists' => 'Nece banner om jo sidodud.
 11295+Ei ližakoi.',
 11296+ 'centralnotice-preview-template' => 'Banneran ezikacund',
 11297+ 'centralnotice-change-lang' => "Vajehtada kändmižen kel'",
 11298+ 'centralnotice-weights' => 'Vedadused',
 11299+ 'centralnotice-notice-is-locked' => 'Kampanii om luklostadud.
 11300+Ei čukoi poiš.',
 11301+ 'centralnotice-null-string' => "Ei voi ližata pall'ast rived.
 11302+Ei ližakoi.",
 11303+);
 11304+
1045811305 /** Vietnamese (Tiếng Việt)
1045911306 * @author Minh Nguyen
1046011307 * @author Vinhtantran
@@ -10462,6 +11309,7 @@
1046311310 'centralnotice' => 'Quản lý các thông báo chung',
1046411311 'noticetemplate' => 'Quản lý các thông báo chung',
1046511312 'bannerallocation' => 'Quản lý các thông báo chung',
 11313+ 'centralnoticelogs' => 'Quản lý các thông báo chung',
1046611314 'right-centralnotice-admin' => 'Quản lý thông báo chung',
1046711315 'action-centralnotice-admin' => 'quản lý thông báo chung',
1046811316 'centralnotice-desc' => 'Thêm thông báo ở đầu các trang tại hơn một wiki',
@@ -10471,8 +11319,9 @@
1047211320 'centralnotice-end-date' => 'Ngày kết thúc',
1047311321 'centralnotice-enabled' => 'Đang hiện',
1047411322 'centralnotice-modify' => 'Lưu các thông báo',
10475 - 'centralnotice-save-banner' => 'Lưu bảng',
 11323+ 'centralnotice-save-banner' => 'Lưu biểu ngữ',
1047611324 'centralnotice-preview' => 'Xem trước',
 11325+ 'centralnotice-nopreview' => '(Không có thể xem trước)',
1047711326 'centralnotice-add-new' => 'Thêm thông báo chung mới',
1047811327 'centralnotice-remove' => 'Dời',
1047911328 'centralnotice-translate-heading' => 'Dịch $1',
@@ -10484,17 +11333,18 @@
1048511334 'centralnotice-add-template' => 'Thêm bảng',
1048611335 'centralnotice-show-notices' => 'Xem các thông báo',
1048711336 'centralnotice-list-templates' => 'Liệt kê các bảng',
10488 - 'centralnotice-multiple' => 'đa ngữ ($1)',
 11337+ 'centralnotice-multiple-projects' => 'đa ngữ ($1)',
 11338+ 'centralnotice-multiple-languages' => 'đa ngữ ($1)',
1048911339 'centralnotice-all-projects' => 'Tất cả các dự án',
1049011340 'centralnotice-language-listing' => '$1 – $2',
1049111341 'centralnotice-translations' => 'Bản dịch',
1049211342 'centralnotice-translate-to' => 'Dịch ra',
1049311343 'centralnotice-translate' => 'Biên dịch',
1049411344 'centralnotice-english' => 'tiếng Anh',
10495 - 'centralnotice-banner-name' => 'Tên bảng:',
10496 - 'centralnotice-banner' => 'Bảng',
10497 - 'centralnotice-banner-heading' => 'Bảng: $1',
10498 - 'centralnotice-templates' => 'Bảng',
 11345+ 'centralnotice-banner-name' => 'Tên biểu ngữ:',
 11346+ 'centralnotice-banner' => 'Biểu ngữ',
 11347+ 'centralnotice-banner-heading' => 'Biểu ngữ: $1',
 11348+ 'centralnotice-templates' => 'Biểu ngữ',
1049911349 'centralnotice-weight' => 'Mức ưu tiên',
1050011350 'centralnotice-locked' => 'Bị khóa',
1050111351 'centralnotice-notice' => 'Cuộc vận động',
@@ -10507,7 +11357,7 @@
1050811358 'centralnotice-notice-doesnt-exist' => 'Cuộc vận động không tồn tại.',
1050911359 'centralnotice-remove-notice-doesnt-exist' => 'Cuộc vận động không tồn tại.
1051011360 Không có gì để dời.',
10511 - 'centralnotice-banner-doesnt-exist' => 'Bảng không tồn tại.',
 11361+ 'centralnotice-banner-doesnt-exist' => 'Biểu ngữ không tồn tại.',
1051211362 'centralnotice-template-still-bound' => 'Không dời được: có thông báo dựa theo cuộc vận động.',
1051311363 'centralnotice-template-body' => 'Nội dung bảng:',
1051411364 'centralnotice-day' => 'Ngày',
@@ -10555,14 +11405,17 @@
1055611406 'centralnotice-close-button' => 'Nút Đóng',
1055711407 'centralnotice-translate-button' => 'Liên kết Giúp dịch',
1055811408 'centralnotice-donate-button' => 'Nút quyên góp',
10559 - 'centralnotice-expanded-banner' => 'Bảng mở rộng',
10560 - 'centralnotice-collapsed-banner' => 'Bảng thu nhỏ',
 11409+ 'centralnotice-expanded-banner' => 'Biểu ngữ mở rộng',
 11410+ 'centralnotice-collapsed-banner' => 'Biểu ngữ thu nhỏ',
1056111411 'centralnotice-banner-display' => 'Hiển thị cho:',
1056211412 'centralnotice-banner-anonymous' => 'Người dùng vô danh',
1056311413 'centralnotice-banner-logged-in' => 'Thành viên đã đăng nhập',
10564 - 'centralnotice-banner-type' => 'Kiểu bảng:',
10565 - 'centralnotice-banner-hidable' => 'Cố định / Ẩn được',
 11414+ 'centralnotice-banner-type' => 'Kiểu biểu ngữ:',
 11415+ 'centralnotice-banner-hidable' => 'Cố định / ẩn được',
1056611416 'centralnotice-banner-collapsible' => 'Thu nhỏ được',
 11417+ 'centralnotice-banner-fundraising' => 'Đây là một biểu ngữ gây quỹ',
 11418+ 'centralnotice-banner-fundraising-help' => 'Tạo một thẻ neo trong phần chính của biểu ngữ có thuộc tính id="cn_fundraising_link" và nhập tên của ít nhất một trang đích ở dưới, thí dụ “JimmyAppeal01”. Thuộc tính href của liên kết sẽ được biên soạn tự động.',
 11419+ 'centralnotice-banner-landing-pages' => 'Các trang đích (định giới bằng dấu phẩy):',
1056711420 'centralnotice-geotargeted' => 'Mục tiêu địa lý',
1056811421 'centralnotice-countries' => 'Quốc gia',
1056911422 'centralnotice-allocation' => 'Phân bổ',
@@ -10577,6 +11430,8 @@
1057811431 'centralnotice-documentwrite-error' => 'Không có thể sử dụng document.write() trong bảng.
1057911432 Xem thêm chi tiết tại http://meta.wikimedia.org/wiki/Help:CentralNotice .',
1058011433 'centralnotice-preferred' => 'Nổi bật hơn',
 11434+ 'centralnotice-logs' => 'Nhật trình',
 11435+ 'centralnotice-view-logs' => 'Xem nhật trình',
1058111436 );
1058211437
1058311438 /** Volapük (Volapük)
@@ -10636,19 +11491,45 @@
1063711492 'centralnotice' => 'צענטראַלע מעלדונג פֿאַרוואַטונג',
1063811493 'noticetemplate' => 'צענטראַלע מעלדונג פֿאַרוואַטונג',
1063911494 'bannerallocation' => 'צענטראַלע מעלדונג פֿאַרוואַטונג',
 11495+ 'right-centralnotice-admin' => 'פֿאַרוואַלטן צענטראַלע מעלדונגען',
 11496+ 'action-centralnotice-admin' => 'פֿאַרוואַלטן צענטראַלע מעלדונגען',
1064011497 'centralnotice-desc' => 'לייגט צו א צענטראַלע מעלדונג',
 11498+ 'centralnotice-summary' => 'די מאָדולע דערלויבט אײַך צו רעדאַגירן אייער צענטראַלע מעלדונגען.
 11499+מען קען זי אויך ניצן צושטעלן אָדער אַראָפּנעמען אַלטע מעלדונגען.',
 11500+ 'centralnotice-query' => 'ענדערן אַקטועלע מעלדונגען',
 11501+ 'centralnotice-notice-name' => 'נאטיץ נאָמען',
 11502+ 'centralnotice-end-date' => 'סוף דאַטע',
 11503+ 'centralnotice-enabled' => 'אַקטיוויזירט',
1064111504 'centralnotice-modify' => 'אײַנגעבן',
 11505+ 'centralnotice-save-banner' => 'אויפֿהיטן פאָן',
1064211506 'centralnotice-preview' => 'פֿאראויסשטעלונג',
 11507+ 'centralnotice-nopreview' => '(פֿאראויסקוק נישט פֿאַראַן)',
 11508+ 'centralnotice-add-new' => 'צולייגן אַ נייַע צענטראַלע מעלדונג',
 11509+ 'centralnotice-remove' => 'אַראָפּנעמען',
1064311510 'centralnotice-translate-heading' => 'פֿאַרטייטשונג פֿאַר $1',
 11511+ 'centralnotice-manage' => 'פֿאַרוואַלטן צענטראַלע מעלדונגען',
 11512+ 'centralnotice-manage-templates' => 'פֿאַרוואַלטן פֿאָנעס',
1064411513 'centralnotice-add' => 'צולייגן',
 11514+ 'centralnotice-add-notice' => 'צולייגן אַ צענטראַלע מעלדונג',
 11515+ 'centralnotice-edit-notice' => 'באַאַרבעטן מעלדונג',
 11516+ 'centralnotice-add-template' => 'צולייגן אַ פֿאָנע',
 11517+ 'centralnotice-show-notices' => 'ווייַזן מעלדונגען',
 11518+ 'centralnotice-list-templates' => 'אויסרעכענען פֿאָנעס',
 11519+ 'centralnotice-multiple-projects' => 'מערערע ($1)',
 11520+ 'centralnotice-multiple-languages' => 'מערערע ($1)',
 11521+ 'centralnotice-all-projects' => 'אַלע פראיעקטן',
1064511522 'centralnotice-translations' => 'פֿאַרטייטשונגען',
1064611523 'centralnotice-translate-to' => 'פֿאַרטייטשן אויף',
1064711524 'centralnotice-translate' => 'פֿאַרטייטשן',
1064811525 'centralnotice-english' => 'ענגליש',
1064911526 'centralnotice-banner-name' => 'פֿאנע נאָמען',
1065011527 'centralnotice-banner' => 'פֿאנע',
 11528+ 'centralnotice-banner-heading' => 'פֿאָנע: $1',
1065111529 'centralnotice-templates' => 'מוסטערן',
 11530+ 'centralnotice-weight' => 'געוויכט',
1065211531 'centralnotice-locked' => 'פֿאַרשלאסן',
 11532+ 'centralnotice-notice' => 'מעלדונג',
 11533+ 'centralnotice-notice-heading' => 'מעלדונג: $1',
1065311534 'centralnotice-notices' => 'נאטיצן',
1065411535 'centralnotice-day' => 'טאג',
1065511536 'centralnotice-year' => 'יאר',
@@ -10708,6 +11589,7 @@
1070911590 /** Cantonese (粵語)
1071011591 * @author Horacewai2
1071111592 * @author Shinjiman
 11593+ * @author Waihorace
1071211594 */
1071311595 $messages['yue'] = array(
1071411596 'centralnotice' => '統一通告管理',
@@ -10725,6 +11607,7 @@
1072611608 * @author PhiLiP
1072711609 * @author Wmr89502270
1072811610 * @author Xiaomingyan
 11611+ * @author 阿pp
1072911612 */
1073011613 $messages['zh-hans'] = array(
1073111614 'centralnotice' => '中央通告管理',
@@ -10742,6 +11625,7 @@
1074311626 'centralnotice-modify' => '提交',
1074411627 'centralnotice-save-banner' => '保存横幅',
1074511628 'centralnotice-preview' => '预览',
 11629+ 'centralnotice-nopreview' => '(无预览可用)',
1074611630 'centralnotice-add-new' => '添加一个新的中央通告',
1074711631 'centralnotice-remove' => '移除',
1074811632 'centralnotice-translate-heading' => '$1的翻译',
@@ -10753,7 +11637,8 @@
1075411638 'centralnotice-add-template' => '添加一个模板',
1075511639 'centralnotice-show-notices' => '显示通告',
1075611640 'centralnotice-list-templates' => '列出模板',
10757 - 'centralnotice-multiple' => '较多($1)',
 11641+ 'centralnotice-multiple-projects' => '较多($1)',
 11642+ 'centralnotice-multiple-languages' => '较多($1)',
1075811643 'centralnotice-all-projects' => '所有项目',
1075911644 'centralnotice-translations' => '翻译',
1076011645 'centralnotice-translate-to' => '翻译到',
@@ -10842,6 +11727,8 @@
1084311728 'centralnotice-banner-type' => '横幅类型:',
1084411729 'centralnotice-banner-hidable' => '静态/可隐藏',
1084511730 'centralnotice-banner-collapsible' => '可收缩',
 11731+ 'centralnotice-banner-fundraising' => '这是一个筹款横幅',
 11732+ 'centralnotice-banner-landing-pages' => '登录页(逗号分隔):',
1084611733 'centralnotice-geotargeted' => '已地理定位的',
1084711734 'centralnotice-countries' => '国家',
1084811735 'centralnotice-allocation' => '配额',
@@ -10883,6 +11770,7 @@
1088411771 'centralnotice-modify' => '提交',
1088511772 'centralnotice-save-banner' => '儲存橫幅',
1088611773 'centralnotice-preview' => '預覽',
 11774+ 'centralnotice-nopreview' => '(無預覽可用)',
1088711775 'centralnotice-add-new' => '新增一個新的中央通告',
1088811776 'centralnotice-remove' => '移除',
1088911777 'centralnotice-translate-heading' => '$1的翻譯',
@@ -10894,7 +11782,8 @@
1089511783 'centralnotice-add-template' => '新增一個模板',
1089611784 'centralnotice-show-notices' => '顯示通告',
1089711785 'centralnotice-list-templates' => '列出模板',
10898 - 'centralnotice-multiple' => '較多($1)',
 11786+ 'centralnotice-multiple-projects' => '較多($1)',
 11787+ 'centralnotice-multiple-languages' => '較多($1)',
1089911788 'centralnotice-all-projects' => '所有計畫',
1090011789 'centralnotice-translations' => '翻譯',
1090111790 'centralnotice-translate-to' => '翻譯到',
@@ -10929,7 +11818,7 @@
1093011819 'centralnotice-min' => '分',
1093111820 'centralnotice-project-lang' => '計劃語言',
1093211821 'centralnotice-select' => '選擇:$1',
10933 - 'centralnotice-top-ten-languages' => '前10種語言',
 11822+ 'centralnotice-top-ten-languages' => '前 10 種語言',
1093411823 'centralnotice-project-name' => '計劃名稱',
1093511824 'centralnotice-start-date' => '開始日期',
1093611825 'centralnotice-start-time' => '開始時間(UTC)',
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/tests/CentralNoticeTest.php
@@ -0,0 +1,18 @@
 2+<?php
 3+
 4+require dirname( __FILE__ ) . '/../SpecialCentralNotice.php';
 5+
 6+/**
 7+ * @group Fundraising
 8+ */
 9+class CentralNoticeTest extends PHPUnit_Framework_TestCase {
 10+
 11+ public function testDropDownList() {
 12+ $text = 'Weight';
 13+ $values = range ( 0, 50, 10 );
 14+ $this->assertEquals(
 15+ "*Weight\n**0\n**10\n**20\n**30\n**40\n**50\n",
 16+ CentralNotice::dropDownList( $text, $values ) );
 17+ }
 18+
 19+}
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice/tests/CentralNoticeTest.php
___________________________________________________________________
Added: svn:eol-style
120 + native
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.db.php
@@ -11,8 +11,9 @@
1212 /*
1313 * Return campaigns in the system within given constraints
1414 * By default returns enabled campaigns, if $enabled set to false, returns both enabled and disabled campaigns
 15+ * @return an array of ids
1516 */
16 - static function getNotices( $project = false, $language = false, $date = false, $enabled = true, $preferred = false, $location = false ) {
 17+ static function getCampaigns( $project = false, $language = false, $date = false, $enabled = true, $preferred = false, $location = false ) {
1718 global $wgCentralDBname;
1819
1920 $notices = array();
@@ -120,14 +121,17 @@
121122
122123 /*
123124 * Given one or more campaign ids, return all banners bound to them
 125+ * @param $campaigns An array of id numbers
 126+ * @return a 2D array of banners with associated weights and settings
124127 */
125 - static function selectTemplatesAssigned( $campaigns ) {
 128+ static function selectBannersAssigned( $campaigns ) {
126129 global $wgCentralDBname;
127130
128131 $dbr = wfGetDB( DB_SLAVE, array(), $wgCentralDBname );
129132
 133+ $templates = array();
 134+
130135 if ( $campaigns ) {
131 - // Pull templates based on join with assignments
132136 $res = $dbr->select(
133137 array(
134138 'cn_notices',
@@ -136,34 +140,53 @@
137141 ),
138142 array(
139143 'tmp_name',
140 - 'SUM(tmp_weight) AS total_weight',
 144+ 'tmp_weight',
141145 'tmp_display_anon',
142 - 'tmp_display_account'
 146+ 'tmp_display_account',
 147+ 'tmp_fundraising',
 148+ 'tmp_landing_pages',
 149+ 'not_name'
143150 ),
144151 array(
145152 'cn_notices.not_id' => $campaigns,
146153 'cn_notices.not_id = cn_assignments.not_id',
147154 'cn_assignments.tmp_id = cn_templates.tmp_id'
148155 ),
149 - __METHOD__,
150 - array(
151 - 'GROUP BY' => 'tmp_name'
152 - )
 156+ __METHOD__
153157 );
 158+
 159+ foreach ( $res as $row ) {
 160+ $templates[] = array(
 161+ 'name' => $row->tmp_name,
 162+ 'weight' => intval( $row->tmp_weight ),
 163+ 'display_anon' => intval( $row->tmp_display_anon ),
 164+ 'display_account' => intval( $row->tmp_display_account ),
 165+ 'fundraising' => intval( $row->tmp_fundraising ),
 166+ 'landing_pages' => $row->tmp_landing_pages,
 167+ 'campaign' => $row->not_name
 168+ );
 169+ }
154170 }
155 - $templates = array();
156 - foreach ( $res as $row ) {
157 - $templates[] = array(
158 - 'name' => $row->tmp_name,
159 - 'weight' => intval( $row->total_weight ),
160 - 'display_anon' => intval( $row->tmp_display_anon ),
161 - 'display_account' => intval( $row->tmp_display_account ),
162 - );
163 - }
164171 return $templates;
165172 }
166173
167174 /*
 175+ * See if a given banner exists in the database
 176+ */
 177+ public static function bannerExists( $bannerName ) {
 178+ global $wgCentralDBname;
 179+ $dbr = wfGetDB( DB_SLAVE, array(), $wgCentralDBname );
 180+
 181+ $eBannerName = htmlspecialchars( $bannerName );
 182+ $row = $dbr->selectRow( 'cn_templates', 'tmp_name', array( 'tmp_name' => $eBannerName ) );
 183+ if ( $row ) {
 184+ return true;
 185+ } else {
 186+ return false;
 187+ }
 188+ }
 189+
 190+ /*
168191 * Return all of the available countries for geotargeting
169192 * (This should probably be moved to a core database table at some point.)
170193 */
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/centralnotice.js
@@ -69,5 +69,12 @@
7070 $("#geoMultiSelector").fadeOut('fast');
7171 }
7272 });
 73+ $("#fundraising").click(function () {
 74+ if ($('#fundraising:checked').val() !== undefined) {
 75+ $("#fundraisingInterface").fadeIn('fast');
 76+ } else {
 77+ $("#fundraisingInterface").fadeOut('fast');
 78+ }
 79+ });
7380 });
7481 })(jQuery);
Index: branches/wmf/1.17wmf1/extensions/CentralNotice/CentralNotice.alias.php
@@ -8,43 +8,79 @@
99 /** English (English) */
1010 $specialPageAliases['en'] = array(
1111 'CentralNotice' => array( 'CentralNotice' ),
12 - 'NoticeText' => array( 'NoticeText' ),
 12+ 'CentralNoticeLogs' => array( 'CentralNoticeLogs' ),
1313 'NoticeTemplate' => array( 'NoticeTemplate' ),
14 - 'NoticeLocal' => array( 'NoticeLocal' ),
1514 'BannerAllocation' => array( 'BannerAllocation' ),
1615 'BannerController' => array( 'BannerController' ),
1716 'BannerListLoader' => array( 'BannerListLoader' ),
1817 'BannerLoader' => array( 'BannerLoader' ),
 18+ 'HideBanners' => array( 'HideBanners' ),
1919 );
2020
2121 /** Arabic (العربية) */
2222 $specialPageAliases['ar'] = array(
2323 'CentralNotice' => array( 'ملاحظة_مركزية' ),
24 - 'NoticeText' => array( 'نص_الملاحظة' ),
2524 'NoticeTemplate' => array( 'قالب_الملاحظة' ),
 25+ 'BannerAllocation' => array( 'وضع_الإعلان' ),
 26+ 'BannerController' => array( 'متحكم_الإعلان' ),
 27+ 'BannerListLoader' => array( 'محمل_قائمة_الإعلان' ),
 28+ 'BannerLoader' => array( 'محمل_الإعلان' ),
 29+ 'HideBanners' => array( 'إخفاء_الإعلان' ),
2630 );
2731
2832 /** Egyptian Spoken Arabic (مصرى) */
2933 $specialPageAliases['arz'] = array(
3034 'CentralNotice' => array( 'ملاحظة_مركزية' ),
31 - 'NoticeText' => array( 'نص_الملاحظة' ),
3235 'NoticeTemplate' => array( 'قالب_الملاحظة' ),
3336 );
3437
 38+/** Breton (Brezhoneg) */
 39+$specialPageAliases['br'] = array(
 40+ 'HideBanners' => array( 'KuzhatBanniel' ),
 41+);
 42+
 43+/** Esperanto (Esperanto) */
 44+$specialPageAliases['eo'] = array(
 45+ 'CentralNotice' => array( 'Centra_informilo' ),
 46+ 'NoticeTemplate' => array( 'Informŝablono' ),
 47+ 'BannerAllocation' => array( 'Strirezervado' ),
 48+ 'BannerController' => array( 'Informstrikontrolisto' ),
 49+ 'BannerListLoader' => array( 'Informstrilistoŝargilo' ),
 50+ 'BannerLoader' => array( 'Informstriŝargilo' ),
 51+ 'HideBanners' => array( 'Kaŝu_striojn' ),
 52+);
 53+
3554 /** Persian (فارسی) */
3655 $specialPageAliases['fa'] = array(
3756 'CentralNotice' => array( 'اعلامیه_مرکزی' ),
38 - 'NoticeText' => array( 'متن_اعلامیه' ),
3957 'NoticeTemplate' => array( 'الگوی_اعلامیه' ),
40 - 'NoticeLocal' => array( 'اعلامیه_محلی' ),
4158 );
4259
 60+/** 湘语 (湘语) */
 61+$specialPageAliases['hsn'] = array(
 62+ 'CentralNotice' => array( '中心公告' ),
 63+ 'NoticeTemplate' => array( '公告样范' ),
 64+ 'BannerAllocation' => array( '横幅配置' ),
 65+ 'BannerController' => array( '横幅控制器' ),
 66+ 'BannerListLoader' => array( '横幅清单载入器' ),
 67+ 'BannerLoader' => array( '横幅载入器' ),
 68+ 'HideBanners' => array( '隐藏横幅' ),
 69+);
 70+
 71+/** Haitian (Kreyòl ayisyen) */
 72+$specialPageAliases['ht'] = array(
 73+ 'CentralNotice' => array( 'NòtSantral' ),
 74+ 'NoticeTemplate' => array( 'ModèlNòt' ),
 75+ 'BannerAllocation' => array( 'BayAnsey' ),
 76+ 'BannerController' => array( 'KontroleAnsey' ),
 77+ 'BannerListLoader' => array( 'ChajeLisAnsey' ),
 78+ 'BannerLoader' => array( 'ChajeAnsey' ),
 79+);
 80+
4381 /** Interlingua (Interlingua) */
4482 $specialPageAliases['ia'] = array(
4583 'CentralNotice' => array( 'Aviso_central' ),
46 - 'NoticeText' => array( 'Texto_de_aviso' ),
4784 'NoticeTemplate' => array( 'Patrono_de_aviso' ),
48 - 'NoticeLocal' => array( 'Aviso_local' ),
4985 'BannerAllocation' => array( 'Alloca_bandieras' ),
5086 'BannerController' => array( 'Controla_bandieras' ),
5187 'BannerListLoader' => array( 'Carga_lista_de_bandieras' ),
@@ -54,70 +90,107 @@
5591 /** Japanese (日本語) */
5692 $specialPageAliases['ja'] = array(
5793 'CentralNotice' => array( '中央管理通知' ),
58 - 'NoticeText' => array( '通知文' ),
5994 'NoticeTemplate' => array( '通知テンプレート' ),
60 - 'NoticeLocal' => array( 'ローカル通知' ),
6195 'BannerAllocation' => array( 'テンプレート割り当て' ),
6296 'BannerController' => array( 'テンプレート制御' ),
6397 'BannerListLoader' => array( 'テンプレート一覧読み込み' ),
6498 'BannerLoader' => array( 'テンプレート読み込み' ),
 99+ 'HideBanners' => array( 'バナーを隠す' ),
65100 );
66101
67102 /** Ladino (Ladino) */
68103 $specialPageAliases['lad'] = array(
69104 'CentralNotice' => array( 'AvisoCentral' ),
70 - 'NoticeText' => array( 'Teksto_de_aviso' ),
71105 'NoticeTemplate' => array( 'Xabblón_de_aviso' ),
72 - 'NoticeLocal' => array( 'AvisoLocal' ),
73106 );
74107
 108+/** Macedonian (Македонски) */
 109+$specialPageAliases['mk'] = array(
 110+ 'CentralNotice' => array( 'ЦентралноИзвестување' ),
 111+ 'NoticeTemplate' => array( 'ШаблонЗаИзвестување' ),
 112+ 'BannerAllocation' => array( 'РаспределбаНаПлакати' ),
 113+ 'BannerController' => array( 'КонтролорНаПлакати' ),
 114+ 'BannerListLoader' => array( 'ВчитувачНаСписоциНаПлакати' ),
 115+ 'BannerLoader' => array( 'ВчитувачНаПлакати' ),
 116+ 'HideBanners' => array( 'СкријПлакати' ),
 117+);
 118+
75119 /** Malayalam (മലയാളം) */
76120 $specialPageAliases['ml'] = array(
77121 'CentralNotice' => array( 'കേന്ദ്രീകൃതഅറിയിപ്പ്' ),
78 - 'NoticeText' => array( 'അറിയിപ്പ്‌‌എഴുത്ത്' ),
79122 'NoticeTemplate' => array( 'അറിയിപ്പ്ഫലകം' ),
80 - 'NoticeLocal' => array( 'പ്രാദേശിക‌‌അറിയിപ്പ്' ),
81123 );
82124
83125 /** Dutch (Nederlands) */
84126 $specialPageAliases['nl'] = array(
85127 'CentralNotice' => array( 'CentraleMededeling' ),
86 - 'NoticeText' => array( 'Mededeling' ),
87128 'NoticeTemplate' => array( 'Mededelingsjabloon' ),
88 - 'NoticeLocal' => array( 'LokaleMededeling' ),
89129 'BannerAllocation' => array( 'Bannertoewijzing' ),
90130 'BannerController' => array( 'Bannerbeheerder' ),
91131 'BannerListLoader' => array( 'Bannerlijstlader' ),
92132 'BannerLoader' => array( 'Bannerlader' ),
 133+ 'HideBanners' => array( 'BannersVerbergen' ),
93134 );
94135
95136 /** Norwegian Nynorsk (‪Norsk (nynorsk)‬) */
96137 $specialPageAliases['nn'] = array(
97138 'CentralNotice' => array( 'Sentralmerknad' ),
98 - 'NoticeText' => array( 'Merknadstekst' ),
99139 'NoticeTemplate' => array( 'Merknadsmal' ),
100140 );
101141
102142 /** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬) */
103143 $specialPageAliases['no'] = array(
104144 'CentralNotice' => array( 'Sentralnotis' ),
105 - 'NoticeText' => array( 'Notistekst' ),
106145 'NoticeTemplate' => array( 'Notismal' ),
 146+ 'BannerAllocation' => array( 'Bannerplassering' ),
 147+ 'BannerController' => array( 'Bannerkontroll' ),
 148+ 'BannerListLoader' => array( 'Bannerlistelaster' ),
 149+ 'BannerLoader' => array( 'Bannerlaster' ),
107150 );
108151
109152 /** Polish (Polski) */
110153 $specialPageAliases['pl'] = array(
111154 'CentralNotice' => array( 'Globalny_komunikat' ),
112 - 'NoticeText' => array( 'Treść_komunikatu' ),
113155 'NoticeTemplate' => array( 'Szablon_komunikatu' ),
114156 );
115157
 158+/** Turkish (Türkçe) */
 159+$specialPageAliases['tr'] = array(
 160+ 'CentralNotice' => array( 'MerkeziBildirim' ),
 161+ 'NoticeTemplate' => array( 'BildirimŞablonu' ),
 162+ 'BannerAllocation' => array( 'AfişTahsisi' ),
 163+ 'BannerController' => array( 'AfişKontrolü', 'AfişKontrolAracı' ),
 164+ 'BannerListLoader' => array( 'AfişListeYükleyici' ),
 165+ 'BannerLoader' => array( 'AfişYükleyici' ),
 166+ 'HideBanners' => array( 'AfişleriGizle', 'AfişGizle' ),
 167+);
 168+
 169+/** Vietnamese (Tiếng Việt) */
 170+$specialPageAliases['vi'] = array(
 171+ 'CentralNotice' => array( 'Thông_báo_chung' ),
 172+ 'NoticeTemplate' => array( 'Bản_mẫu_thông_báo' ),
 173+ 'BannerAllocation' => array( 'Phân_bố_bảng' ),
 174+ 'BannerController' => array( 'Điều_khiển_bảng' ),
 175+ 'BannerListLoader' => array( 'Tải_danh_sách_bảng' ),
 176+ 'BannerLoader' => array( 'Tải_bảng' ),
 177+ 'HideBanners' => array( 'Ẩn_bảng' ),
 178+);
 179+
 180+/** Simplified Chinese (‪中文(简体)‬) */
 181+$specialPageAliases['zh-hans'] = array(
 182+ 'CentralNotice' => array( '中央通知' ),
 183+ 'NoticeTemplate' => array( '公告模板' ),
 184+ 'BannerAllocation' => array( '横幅分配' ),
 185+ 'BannerController' => array( '横幅控制器' ),
 186+ 'BannerListLoader' => array( '布条装载机' ),
 187+ 'BannerLoader' => array( '横幅装载机' ),
 188+ 'HideBanners' => array( '隐藏横幅' ),
 189+);
 190+
116191 /** Traditional Chinese (‪中文(繁體)‬) */
117192 $specialPageAliases['zh-hant'] = array(
118193 'CentralNotice' => array( '中央通告' ),
119 - 'NoticeText' => array( '通告內文' ),
120194 'NoticeTemplate' => array( '通告模板' ),
121 - 'NoticeLocal' => array( '本地化通告' ),
122195 );
123196
124197 /**
Property changes on: branches/wmf/1.17wmf1/extensions/CentralNotice
___________________________________________________________________
Modified: svn:mergeinfo
125198 Merged /trunk/extensions/CentralNotice:r83565-91117

Follow-up revisions

RevisionCommit summaryAuthorDate
r91218MFT r91118-r91217 for special/SpecialBannerLoader.php and special/SpecialBann...awjrichards20:31, 30 June 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r83564Syncing up to head of trunk from r81460tomasz02:32, 9 March 2011

Status & tagging log