r99364 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99363‎ | r99364 | r99365 >
Date:18:35, 9 October 2011
Author:ashley
Status:deferred (Comments)
Tags:
Comment:
adding AJAX Poll extension. JavaScript should be cleaned up (and maybe rewritten to use jQuery?) so that we can support ResourceLoader and functions in AJAXPoll.php should be moved into a new class instead of them being in the global scope.
Modified paths:
  • /trunk/extensions/AJAXPoll (added) (history)
  • /trunk/extensions/AJAXPoll/AJAXPoll.css (added) (history)
  • /trunk/extensions/AJAXPoll/AJAXPoll.i18n.php (added) (history)
  • /trunk/extensions/AJAXPoll/AJAXPoll.php (added) (history)
  • /trunk/extensions/AJAXPoll/poll.sql (added) (history)

Diff [purge]

Index: trunk/extensions/AJAXPoll/AJAXPoll.php
@@ -0,0 +1,374 @@
 2+<?php
 3+/**
 4+ * AJAX Poll extension for MediaWiki
 5+ * Created by Dariusz Siedlecki, based on the work by Eric David.
 6+ * Licensed under the GFDL.
 7+ *
 8+ * <poll>
 9+ * [Option]
 10+ * Question
 11+ * Answer 1
 12+ * Answer 2
 13+ * ...
 14+ * Answer n
 15+ * </poll>
 16+ *
 17+ * @file
 18+ * @ingroup Extensions
 19+ * @author Dariusz Siedlecki <datrio@gmail.com>
 20+ * @author Jack Phoenix <jack@countervandalism.net>
 21+ * @version 1.4.1
 22+ * @link http://www.mediawiki.org/wiki/Extension:AJAX_Poll Documentation
 23+ */
 24+
 25+if( !defined( 'MEDIAWIKI' ) ) {
 26+ die( "This is not a valid entry point.\n" );
 27+}
 28+
 29+// Extension credits that will show up on Special:Version
 30+$wgExtensionCredits['parserhook'][] = array(
 31+ 'name' => 'AJAX Poll',
 32+ 'version' => '1.4.1',
 33+ 'author' => array( 'Dariusz Siedlecki', 'Jack Phoenix' ),
 34+ 'description' => 'Allows AJAX-based polls with <tt>&lt;poll&gt;</tt> tag',
 35+ 'url' => 'http://www.mediawiki.org/wiki/Extension:AJAX_Poll'
 36+);
 37+
 38+// Internationalization + AJAX function
 39+$dir = dirname( __FILE__ ) . '/';
 40+$wgExtensionMessagesFiles['AJAXPoll'] = $dir . 'AJAXPoll.i18n.php';
 41+$wgAjaxExportList[] = 'submitVote';
 42+
 43+$wgHooks['ParserFirstCallInit'][] = 'wfPoll';
 44+
 45+/**
 46+ * Register <poll> tag with the parser
 47+ *
 48+ * @param $parser Object: instance of Parser (not necessarily $wgParser)
 49+ * @return Boolean: true
 50+ */
 51+function wfPoll( &$parser ) {
 52+ $parser->setHook( 'poll', 'renderPoll' );
 53+ return true;
 54+}
 55+
 56+# The callback function for converting the input text to HTML output
 57+function renderPoll( $input ) {
 58+ global $wgParser, $wgUser, $wgOut, $wgTitle, $wgScriptPath;
 59+
 60+ $wgParser->disableCache();
 61+
 62+ if ( $wgUser->getName() == '' ) {
 63+ $user = wfGetIP();
 64+ } else {
 65+ $user = $wgUser->getName();
 66+ }
 67+
 68+ // ID of the poll
 69+ $ID = strtoupper( md5( $input ) );
 70+
 71+ $par = new Parser();
 72+ $input = $par->parse( $input, $wgTitle, $wgOut->parserOptions() );
 73+ $input = trim( strip_tags( $input->getText() ) );
 74+ $lines = explode( "\n", trim( $input ) );
 75+
 76+ // Deprecating AJAX
 77+ /*if ( isset( $_POST['p_id'] ) && isset( $_POST['p_answer'] ) && $_POST['p_id'] == $ID ) {
 78+ submitVote( $_POST['p_id'], intval( $_POST['p_answer'] ) );
 79+ }*/
 80+
 81+ $dbw = wfGetDB( DB_MASTER );
 82+ $dbw->begin();
 83+ /**
 84+ * Register poll in the database
 85+ */
 86+ $row = $dbw->selectRow(
 87+ array( 'poll_info' ),
 88+ array( 'COUNT(poll_id) AS count' ),
 89+ array( 'poll_id' => $ID ),
 90+ __METHOD__
 91+ );
 92+
 93+ if( empty( $row->count ) ) {
 94+ $dbw->insert(
 95+ 'poll_info',
 96+ array(
 97+ 'poll_id' => $ID,
 98+ 'poll_txt' => $input,
 99+ 'poll_date' => wfTimestampNow(),
 100+ 'poll_title' => $wgParser->mTitle->getText()
 101+ ),
 102+ __METHOD__
 103+ );
 104+ }
 105+ $dbw->commit();
 106+
 107+ // Add CSS
 108+ $wgOut->addExtensionStyle( $wgScriptPath . '/extensions/AJAXPoll/AJAXPoll.css' );
 109+ switch( $lines[0] ) {
 110+ case 'STATS':
 111+ $retVal = buildStats( $ID, $user );
 112+ break;
 113+ default:
 114+ $retVal = '<div id="pollContainer' . $ID . '">' .
 115+ buildHTML( $ID, $user, $lines ) .
 116+ '</div>';
 117+ break;
 118+ }
 119+ return $retVal;
 120+}
 121+
 122+function buildStats( $ID, $user ) {
 123+ $dbw = wfGetDB( DB_MASTER );
 124+
 125+ $res = $dbw->select(
 126+ 'poll_vote',
 127+ array(
 128+ 'COUNT(*)',
 129+ 'COUNT(DISTINCT poll_id)',
 130+ 'COUNT(DISTINCT poll_user)',
 131+ 'TIMEDIFF(NOW(), MAX(poll_date))'
 132+ ),
 133+ array(),
 134+ __METHOD__
 135+ );
 136+ $tab = $dbw->fetchRow( $res );
 137+
 138+ $clock = explode( ':', $tab[3] );
 139+
 140+ if ( $clock[0] == '00' && $clock[1] == '00' ) {
 141+ $x = $clock[2];
 142+ $y = 'second';
 143+ } elseif( $clock[0] == '00' ) {
 144+ $x = $clock[1];
 145+ $y = 'minute';
 146+ } else {
 147+ if ( $clock[0] < 24 ) {
 148+ $x = $clock[0];
 149+ $y = 'hour';
 150+ } else {
 151+ $x = floor( $hr / 24 );
 152+ $y = 'day';
 153+ }
 154+ }
 155+
 156+ $clockago = $x . ' ' . $y . ( $x > 1 ? 's' : '' );
 157+
 158+ $res = $dbw->select(
 159+ 'poll_vote',
 160+ 'COUNT(*)',
 161+ array( 'DATE_SUB(CURDATE(), INTERVAL 2 DAY) <= poll_date' ),
 162+ __METHOD__
 163+ );
 164+ $tab2 = $dbw->fetchRow( $res );
 165+
 166+ return "There are $tab[1] polls and $tab[0] votes given by $tab[2] different people.<br />The last vote has been given $clockago ago.<br/>During the last 48 hours, $tab2[0] votes have been given.";
 167+}
 168+
 169+function submitVote( $ID, $answer ) {
 170+ global $wgUser;
 171+
 172+ $dbw = wfGetDB( DB_MASTER );
 173+
 174+ if ( $wgUser->getName() == '' ) {
 175+ $user = wfGetIP();
 176+ } else {
 177+ $user = $wgUser->getName();
 178+ }
 179+
 180+ if ( $wgUser->isAllowed( 'bot' ) ) {
 181+ return buildHTML( $ID, $user );
 182+ }
 183+
 184+ $answer = $dbw->strencode( ++$answer );
 185+
 186+ $q = $dbw->select(
 187+ 'poll_vote',
 188+ 'COUNT(*) AS c',
 189+ array(
 190+ 'poll_id' => $ID,
 191+ 'poll_user' => $dbw->addQuotes( $user )
 192+ ),
 193+ __METHOD__
 194+ );
 195+ $r = $dbw->fetchRow( $q );
 196+
 197+ if ( $r['c'] > 0 ) {
 198+ $updateQuery = $dbw->update(
 199+ 'poll_vote',
 200+ array(
 201+ "poll_answer='{$answer}'",
 202+ 'poll_date' => wfTimestampNow()
 203+ ),
 204+ array(
 205+ 'poll_id' => $ID,
 206+ 'poll_user' => $dbw->addQuotes( $user )
 207+ ),
 208+ __METHOD__
 209+ );
 210+ $dbw->commit();
 211+ if ( $updateQuery ) {
 212+ return buildHTML( $ID, $user, '', 'poll-vote-update' );
 213+ } else {
 214+ return buildHTML( $ID, $user, '', 'poll-vote-error' );
 215+ }
 216+ } else {
 217+ $insertQuery = $dbw->insert(
 218+ 'poll_vote',
 219+ array(
 220+ 'poll_id' => $ID,
 221+ 'poll_user' => $dbw->addQuotes( $user ),
 222+ 'poll_ip' => wfGetIP(),
 223+ 'poll_answer' => $answer,
 224+ 'poll_date' => wfTimestampNow()
 225+ ),
 226+ __METHOD__
 227+ );
 228+ $dbw->commit();
 229+ if ( $insertQuery ) {
 230+ return buildHTML( $ID, $user, '', 'poll-vote-add' );
 231+ } else {
 232+ return buildHTML( $ID, $user, '', 'poll-vote-error' );
 233+ }
 234+ }
 235+}
 236+
 237+function buildHTML( $ID, $user, $lines = '', $extra_from_ajax = '' ) {
 238+ global $wgTitle, $wgLang, $wgUseAjax;
 239+
 240+ $dbw = wfGetDB( DB_SLAVE );
 241+
 242+ $q = $dbw->select(
 243+ 'poll_info',
 244+ array( 'poll_txt', 'poll_date' ),
 245+ array( 'poll_id' => $ID ),
 246+ __METHOD__
 247+ );
 248+ $r = $dbw->fetchRow( $q );
 249+
 250+ if ( empty( $lines ) ) {
 251+ $lines = explode( "\n", trim( $r['poll_txt'] ) );
 252+ }
 253+
 254+ $start_date = $r['poll_date'];
 255+
 256+ $q = $dbw->select(
 257+ 'poll_vote',
 258+ array( 'poll_answer', 'COUNT(*)' ),
 259+ array( 'poll_id' => $ID ),
 260+ __METHOD__,
 261+ array( 'GROUP BY' => 'poll_answer' )
 262+ );
 263+
 264+ $poll_result = array();
 265+
 266+ while ( $r = $q->fetchRow() ) {
 267+ $poll_result[$r[0]] = $r[1];
 268+ }
 269+
 270+ $amountOfVotes = array_sum( $poll_result );
 271+
 272+ // Did we vote?
 273+ $q = $dbw->select(
 274+ 'poll_vote',
 275+ array( 'poll_answer', 'poll_date' ),
 276+ array(
 277+ 'poll_id' => $ID,
 278+ 'poll_user' => $dbw->addQuotes( $user )
 279+ ),
 280+ __METHOD__
 281+ );
 282+
 283+ if ( $r = $dbw->fetchRow( $q ) ) {
 284+ $tmp_date = wfMsg(
 285+ 'poll-your-vote',
 286+ $lines[$r[0] - 1],
 287+ $wgLang->timeanddate( wfTimestamp( TS_MW, $r[1] ), true /* adjust? */ )
 288+ );
 289+ }
 290+
 291+ if ( is_object( $wgTitle ) ) {
 292+ if( !empty( $extra_from_ajax ) ) {
 293+ $additionalAttributes = ' style="display: block;"';
 294+ $message = wfMsg( $extra_from_ajax );
 295+ } else {
 296+ $additionalAttributes = '';
 297+ $message = '';
 298+ }
 299+ // HTML output has to be on one line thanks to a MediaWiki bug
 300+ // @see https://bugzilla.wikimedia.org/show_bug.cgi?id=1319
 301+ $ret = '<div id="pollId' . $ID . '" class="poll"><div class="pollAjax" id="pollAjax' . $ID . '"' .
 302+ $additionalAttributes . '>' . $message .
 303+ '</div><div class="pollQuestion">' . strip_tags( $lines[0] ) . '</div>';
 304+
 305+ // Different message depending on if the user has already voted or not.
 306+ if ( isset( $r[0] ) ) {
 307+ $ret .= '<div class="pollMisc">' . $tmp_date . '</div>';
 308+ } else {
 309+ $ret .= '<div class="pollMisc">' . wfMsg( 'poll-no-vote' ) . '</div>';
 310+ }
 311+
 312+ $ret .= '<form method="post" action="' . $wgTitle->getLocalURL() .
 313+ '" id="pollIdAnswer' . $ID . '"><input type="hidden" name="p_id" value="' . $ID . '" />';
 314+
 315+ for ( $i = 1; $i < count( $lines ); $i++ ) {
 316+ $ans_no = $i - 1;
 317+
 318+ if ( $amountOfVotes == 0 ) {
 319+ $percent = 0;
 320+ } else {
 321+ $percent = $wgLang->formatNum( round( ( isset( $poll_result[$i + 1] ) ? $poll_result[$i + 1] : 0 ) * 100 / $amountOfVotes, 2 ) );
 322+ }
 323+
 324+ if ( isset( $r[0] ) && $r[0] == $i ) {
 325+ $our = true;
 326+ } else {
 327+ $our = false;
 328+ }
 329+
 330+ // If AJAX is enabled, as it is by default in modern MWs, we can
 331+ // just use sajax library function here for that AJAX-y feel.
 332+ // If not, we'll have to submit the form old-school way...
 333+ if ( $wgUseAjax ) {
 334+ $submitJS = "sajax_do_call(\"submitVote\", [\"" . $ID . "\", \"" . $i . "\"], document.getElementById(\"pollContainer" . $ID . "\"));";
 335+ } else {
 336+ $submitJS = "document.getElementById(\"pollIdAnswer" . $ID . "\").submit();";
 337+ }
 338+
 339+ // HTML output has to be on one line thanks to a MediaWiki bug
 340+ // @see https://bugzilla.wikimedia.org/show_bug.cgi?id=1319
 341+ $ret .= "<div class='pollAnswer' id='pollAnswer" . $ans_no .
 342+ "'><div class='pollAnswerName'><label for='pollAnswerRadio" .
 343+ $ans_no . "' onclick='document.getElementById(\"pollAjax" .
 344+ $ID . "\").innerHTML=\"" . wfMsg( 'poll-submitting' ) .
 345+ "\"; document.getElementById(\"pollAjax" . $ID .
 346+ "\").style.display=\"block\"; this.getElementsByTagName(\"input\")[0].checked = true; " .
 347+ $submitJS . "'><input type='radio' id='p_answer" . $ans_no .
 348+ "' name='p_answer' value='" . $i . "' />" .
 349+ strip_tags( $lines[$i] ) .
 350+ "</label></div> <div class='pollAnswerVotes" . ( $our ? ' ourVote' : '' ) .
 351+ "' onmouseover='span=this.getElementsByTagName(\"span\")[0];tmpPollVar=span.innerHTML;span.innerHTML=span.title;span.title=\"\";' onmouseout='span=this.getElementsByTagName(\"span\")[0];span.title=span.innerHTML;span.innerHTML=tmpPollVar;'><span title='" .
 352+ wfMsg( 'poll-percent-votes', sprintf( $percent ) ) . "'>" .
 353+ ( ( isset( $poll_result ) && !empty( $poll_result[$i + 1] ) ) ? $poll_result[$i + 1] : 0 ) .
 354+ "</span><div style='width: " . $percent . "%;" . ( $percent == 0 ? ' border:0;' : '' ) . "'></div></div></div>";
 355+ }
 356+
 357+ $ret .= '</form>';
 358+
 359+ // Display information about the poll (creation date, amount of votes)
 360+ $tmp_date = wfMsgExt(
 361+ 'poll-info',
 362+ 'parsemag', // parse PLURAL
 363+ $amountOfVotes, // amount of votes
 364+ $wgLang->timeanddate( wfTimestamp( TS_MW, $start_date ), true /* adjust? */ )
 365+ );
 366+
 367+ $ret .= '<div id="pollInfo">' . $tmp_date . '</div>';
 368+
 369+ $ret .= '</div>';
 370+ } else {
 371+ $ret = '';
 372+ }
 373+
 374+ return $ret;
 375+}
\ No newline at end of file
Property changes on: trunk/extensions/AJAXPoll/AJAXPoll.php
___________________________________________________________________
Added: svn:eol-style
1376 + native
Index: trunk/extensions/AJAXPoll/AJAXPoll.css
@@ -0,0 +1,69 @@
 2+/**
 3+ * CSS for AJAX Poll extension
 4+ * @file
 5+ * @ingroup Extensions
 6+ * @author Dariusz Siedlecki
 7+ */
 8+
 9+.poll {
 10+ width: 400px;
 11+ border: 1px dashed #999;
 12+ background: #FAFAFA;
 13+ padding: 10px 20px 10px 10px
 14+}
 15+
 16+.poll .pollQuestion {
 17+ font-weight: bold;
 18+}
 19+
 20+.poll .pollAjax {
 21+ background: #FFFFCF;
 22+ padding: 1px 4px;
 23+ width: 200px;
 24+ border-radius: 0.5em;
 25+ -moz-border-radius: 0.5em;
 26+ display: none;
 27+}
 28+
 29+.poll .pollAnswerName {
 30+ padding-left: 10px;
 31+ font-size: 0.9em;
 32+}
 33+
 34+.poll .pollAnswerVotes {
 35+ border: 1px solid #CCC;
 36+ width: 100%;
 37+ margin-left: 10px;
 38+ height: 12px;
 39+ font-size: 10px;
 40+ position: relative;
 41+}
 42+
 43+.poll .pollAnswerVotes div {
 44+ border-right: 1px solid #CCC;
 45+ background: #E5E5E5;
 46+ position: absolute;
 47+ top: 0;
 48+ left: 0;
 49+ height: 12px;
 50+ font-size: 1px;
 51+ line-height: 12px;
 52+ z-index: 2;
 53+}
 54+
 55+.poll .ourVote div {
 56+ border: 1px solid #777;
 57+ top: -1px;
 58+ left: -1px;
 59+}
 60+
 61+.poll .pollAnswerVotes span {
 62+ position: absolute;
 63+ top: -3px;
 64+ left: 3px;
 65+ z-index: 4;
 66+}
 67+
 68+.poll label {
 69+ cursor: pointer;
 70+}
\ No newline at end of file
Property changes on: trunk/extensions/AJAXPoll/AJAXPoll.css
___________________________________________________________________
Added: svn:eol-style
171 + native
Index: trunk/extensions/AJAXPoll/poll.sql
@@ -0,0 +1,15 @@
 2+CREATE TABLE IF NOT EXISTS /*_*/poll_info (
 3+ `poll_id` varchar(32) NOT NULL PRIMARY KEY default '',
 4+ `poll_txt` text,
 5+ `poll_date` datetime default NULL,
 6+ `poll_title` varchar(255) default NULL
 7+) /*$wgDBTableOptions*/;
 8+
 9+CREATE TABLE IF NOT EXISTS /*_*/poll_vote (
 10+ `poll_id` varchar(32) NOT NULL default '',
 11+ `poll_user` varchar(255) NOT NULL default '',
 12+ `poll_ip` varchar(255) default NULL,
 13+ `poll_answer` int(3) default NULL,
 14+ `poll_date` datetime default NULL,
 15+ PRIMARY KEY (`poll_id`,`poll_user`)
 16+) /*$wgDBTableOptions*/;
\ No newline at end of file
Property changes on: trunk/extensions/AJAXPoll/poll.sql
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/AJAXPoll/AJAXPoll.i18n.php
@@ -0,0 +1,302 @@
 2+<?php
 3+/**
 4+ * Internationalization file for the AJAX Poll extension.
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Dariusz Siedlecki
 14+ */
 15+$messages['en'] = array(
 16+ 'poll-vote-update' => 'Your vote has been updated.',
 17+ 'poll-vote-add' => 'Your vote has been added.',
 18+ 'poll-vote-error' => 'There was a problem with processing your vote, please try again.',
 19+ 'poll-percent-votes' => '$1% of all votes', // $1 is the percentage number of the votes
 20+ 'poll-your-vote' => 'You already voted for "$1" on $2, you can change your vote by clicking an answer below.', // $1 is the answer name, $2 is the date when the answer was casted
 21+ 'poll-no-vote' => 'Please vote below.', // http://trac.wikia-code.com/changeset/867
 22+ 'poll-info' => 'There {{PLURAL:$1|was one vote|were $1 votes}} since the poll was created on $2.', // $1 is the number of votes, $2 is when the poll was started
 23+ 'poll-submitting' => 'Please wait, submitting your vote.',
 24+);
 25+
 26+/** Afrikaans (Afrikaans)
 27+ * @author Naudefj
 28+ */
 29+$messages['af'] = array(
 30+ 'poll-vote-update' => 'U stem is opgedateer.',
 31+ 'poll-vote-add' => 'U stem is bygevoeg.',
 32+ 'poll-percent-votes' => '$1% van alle stemme',
 33+ 'poll-no-vote' => 'Stem asseblief hier onder.',
 34+);
 35+
 36+/** Arabic (العربية)
 37+ * @author OsamaK
 38+ */
 39+$messages['ar'] = array(
 40+ 'poll-vote-update' => 'تم تحديث صوتك.',
 41+ 'poll-vote-add' => 'تم إضافة تصويتك',
 42+ 'poll-info' => 'هذه كانت $1 تصويتا منذ بداية التصويت في $2.', // @todo FIXME: out of date, needs PLURAL
 43+ 'poll-submitting' => 'من فضلك انتظر، يرسل صوتك.',
 44+);
 45+
 46+/** Breton (Brezhoneg)
 47+ * @author Y-M D
 48+ */
 49+$messages['br'] = array(
 50+ 'poll-vote-update' => 'Hizivaet eo bet ho vot.',
 51+ 'poll-vote-add' => 'Ouzhpennet eo bet ho vot.',
 52+ 'poll-vote-error' => "Ur gudenn a zo bet pa vezer oc'h ober war-dro ho vot. Mar plij klaskit adarre.",
 53+ 'poll-percent-votes' => '$1% eus hollad ar mouezhioù',
 54+ 'poll-your-vote' => "Votet ho peus dija evit \"$1\" d'an $2, tu 'zo deoc'h kemmañ ho vot en ur klikañ war unan eus ar respontoù da heul.",
 55+ 'poll-no-vote' => 'Mar plij votit amañ dindan.',
 56+ 'poll-info' => "$1 vot a zo bet abaoe ma 'z eo bet krouet ar sontadeg war $2.", // @todo FIXME: out of date, needs PLURAL
 57+ 'poll-submitting' => "Mar plij gortozit, emeur oc'h ober war-dro ho vot.",
 58+);
 59+
 60+/** German (Deutsch)
 61+ * @author Tim 'Avatar' Bartel
 62+ */
 63+$messages['de'] = array(
 64+ 'poll-vote-update' => 'Deine Stimme wurde aktualisiert.',
 65+ 'poll-vote-add' => 'Deine Stimme wurde gezählt.',
 66+ 'poll-vote-error' => 'Es gab ein Problem bei der Verarbeitung deiner Stimme. Probiere es bitte noch einmal.',
 67+ 'poll-percent-votes' => '$1% aller Stimmen',
 68+ 'poll-your-vote' => 'Du hast bereits für "$1" abgestimmt (am $2). Du kannst deine Stimme ändern, indem du eine der untenstehenden Antworten anklickst.',
 69+ 'poll-no-vote' => 'Bitte stimme unten ab.',
 70+ 'poll-info' => 'Es gab $1 Stimmen, seit der Erstellung der Umfrage am $2.', // @todo FIXME: out of date, needs PLURAL
 71+ 'poll-submitting' => 'Bitte warte kurz, deine Stimme wird verarbeitet.',
 72+);
 73+
 74+/** Greek (Ελληνικά)
 75+ * @author Περίεργος
 76+ */
 77+$messages['el'] = array(
 78+ 'poll-vote-update' => 'Η ψήφος σας έχει ενημερωθεί.',
 79+ 'poll-vote-add' => 'Η ψήφος σας προστέθηκε.',
 80+ 'poll-vote-error' => 'Παρουσιάστηκε πρόβλημα κατά την επεξεργασία της ψήφους σας, παρακαλώ ξαναπροσπαθήστε.',
 81+ 'poll-percent-votes' => '$1% επί των συνολικών ψήφων',
 82+ 'poll-your-vote' => 'Έχετε ήδη ψηφίσει το $1 στο $2, μπορείτε να αλλάξετε τη ψήφο σας πατώντας μια απάντηση παρακάτω.',
 83+ 'poll-no-vote' => 'Παρακαλώ ψηφίστε παρακάτω.',
 84+ 'poll-info' => 'Υπάρχουν $1 ψήφοι από τότε που δημιουργήθηκε η ψηφοφορία στις $2.', // @todo FIXME: out of date, needs PLURAL
 85+ 'poll-submitting' => 'Παρακαλώ περιμένετε,η ψήφο σας υποβάλλεται.',
 86+);
 87+
 88+/** Spanish (Español)
 89+ * @author Bola
 90+ */
 91+$messages['es'] = array(
 92+ 'poll-vote-update' => 'Tu voto ha sido actualizado.',
 93+ 'poll-vote-add' => 'Tu voto ha sido añadido.',
 94+ 'poll-vote-error' => 'Ha habido un problema cuando comprobábamos tu voto, por favor, inténtalo de nuevo.',
 95+ 'poll-percent-votes' => '$1% de todos los votos',
 96+ 'poll-your-vote' => 'Ya votaste por "$1" el $2, puedes cambiar tu voto haciendo clic en una respuesta debajo.',
 97+ 'poll-no-vote' => 'Por favor, vota debajo.',
 98+ 'poll-info' => 'Ha habido {{PLURAL:$1|un voto|$1 votos}} desde que la encuesta fue creada el $2.',
 99+ 'poll-submitting' => 'Por favor espera, estamos comprobando tu voto, ten paciencia.',
 100+);
 101+
 102+/** Finnish (Suomi)
 103+ * @author Jack Phoenix
 104+ */
 105+$messages['fi'] = array(
 106+ 'poll-vote-update' => 'Äänesi on päivitetty',
 107+ 'poll-vote-add' => 'Äänesi on lisätty.',
 108+ 'poll-vote-error' => 'Äänesi prosessoimisessa oli ongelma, yritä uudelleen.',
 109+ 'poll-percent-votes' => '$1% kaikista äänistä',
 110+ 'poll-your-vote' => 'Äänestit jo vaihtoehtoa "$1" $2, voit muuttaa ääntäsi napsauttamalla vastausta alempana',
 111+ 'poll-no-vote' => 'Äänestä alempana.',
 112+ 'poll-info' => '{{PLURAL:$1|Yksi ääni|$1 ääntä}} on annettu siitä lähtien kun tämä äänestys tehtiin, $2.',
 113+ 'poll-submitting' => 'Odota hetki, lähetetään ääntäsi.',
 114+);
 115+
 116+/** French (Français)
 117+ * @author Tim 'Avatar' Bartel
 118+ */
 119+$messages['fr'] = array(
 120+ 'poll-vote-update' => 'Ta voix est actualisé.',
 121+ 'poll-vote-add' => 'Ta voix était compté.',
 122+ 'poll-vote-error' => "Il y avait une problème avec le traitement de ta voix. Essaie-cela s'il te plaît encore une fois.",
 123+ 'poll-percent-votes' => '$1% de tous voix.',
 124+ 'poll-your-vote' => "Tu a déjà voté pour $1 (à $2). Tu peux changer ta voix, si tu cliques à l'une des réponses en bas.",
 125+ 'poll-no-vote' => 'Vote en bas.',
 126+ 'poll-info' => "Il y avait {{PLURAL:$1|une voix|$1 voix}}, depuis l'élaboration du sondage au $2.",
 127+ 'poll-submitting' => 'Attends une moment, ta voix est traité...',
 128+);
 129+
 130+/** Galician (Galego)
 131+ * @author Toliño
 132+ */
 133+$messages['gl'] = array(
 134+ 'poll-vote-update' => 'Actualizouse o seu voto.',
 135+ 'poll-vote-add' => 'Engadiuse o seu voto.',
 136+ 'poll-vote-error' => 'Houbo algún problema co procesamento do seu voto, por favor, inténteo de novo.',
 137+ 'poll-percent-votes' => '$1% do total dos votos',
 138+ 'poll-your-vote' => 'Xa votou por "$1" o $2, pode cambiar o seu voto premendo nunha resposta das que aparecen a continuación.',
 139+ 'poll-no-vote' => 'Por favor, vote a continuación.',
 140+ 'poll-info' => 'Recibíronse {{PLURAL:$1|un voto|$1 votos}} des que a enquisa foi creada o $2.',
 141+ 'poll-submitting' => 'Por favor, agarde durante o envío do seu voto.',
 142+);
 143+
 144+/** Hungarian (Magyar)
 145+ * @author Glanthor Reviol
 146+ */
 147+$messages['hu'] = array(
 148+ 'poll-vote-update' => 'A szavazatod frissítve.',
 149+ 'poll-vote-add' => 'A szavazatod rögzítve.',
 150+ 'poll-no-vote' => 'Kérlek szavazz alant.',
 151+ 'poll-submitting' => 'Kérlek várj a szavazatod elküldésére.',
 152+);
 153+
 154+/** Interlingua (Interlingua)
 155+ * @author McDutchie
 156+ */
 157+$messages['ia'] = array(
 158+ 'poll-vote-update' => 'Tu voto ha essite actualisate.',
 159+ 'poll-vote-add' => 'Tu voto ha essite addite.',
 160+ 'poll-vote-error' => 'Un problema occurreva durante le tractamento de tu voto. Per favor reproba.',
 161+ 'poll-percent-votes' => '$1% de tote le votos',
 162+ 'poll-your-vote' => 'Tu ha ja votate pro "$1" in $2. Tu pote cambiar tu voto per cliccar super un responsa hic infra.',
 163+ 'poll-no-vote' => 'Per favor vota hic infra.',
 164+ 'poll-info' => 'Il habeva $1 votos post le creation del sondage le $2.', // @todo FIXME: out of date, needs PLURAL
 165+ 'poll-submitting' => 'Un momento, tu voto es submittite.',
 166+);
 167+
 168+/** Japanese (日本語)
 169+ * @author Shun Fukuzawa
 170+ */
 171+$messages['ja'] = array(
 172+ 'poll-vote-update' => '投票を更新しました。',
 173+ 'poll-vote-add' => '投票が追加されました。',
 174+ 'poll-vote-error' => '問題が発生しました。少ししてから再度投票してください。',
 175+ 'poll-percent-votes' => '全体の$1%',
 176+ 'poll-your-vote' => '$2について、$1に投票しています。以下の回答をクリックすると、投票を変更できます。',
 177+ 'poll-no-vote' => 'さあ、投票しよう!',
 178+ 'poll-submitting' => '投票を処理しています。少しお待ちください。',
 179+);
 180+
 181+/** Macedonian (Македонски)
 182+ * @author Bjankuloski06
 183+ */
 184+$messages['mk'] = array(
 185+ 'poll-vote-update' => 'Вашиот глас е подновен.',
 186+ 'poll-vote-add' => 'Вашиот глас е додаден.',
 187+ 'poll-vote-error' => 'Се појави проблем при обработката на вашиот глас. Обидете се повторно.',
 188+ 'poll-percent-votes' => '$1% од вкупниот број на гласови',
 189+ 'poll-your-vote' => 'Веќе имате гласано за „$1“ на $2; можете да го промените гласот со кликнување на еден од одговорите подолу.',
 190+ 'poll-no-vote' => 'Гласајте подолу.',
 191+ 'poll-info' => 'Откако е создадена анкетата ($2) гласано е $1 пати.', // @todo FIXME: out of date, needs PLURAL
 192+ 'poll-submitting' => 'Почекајте, го заведувам вашиот глас.',
 193+);
 194+
 195+/** Dutch (Nederlands)
 196+ * @author Siebrand
 197+ */
 198+$messages['nl'] = array(
 199+ 'poll-vote-update' => 'Uw stem is bijgewerkt.',
 200+ 'poll-vote-add' => 'Uw stem is toegevoegd.',
 201+ 'poll-vote-error' => 'Er is een probleem opgetreden tijdens het verwerken van uw stem. Probeer het opnieuw.',
 202+ 'poll-percent-votes' => '$1% van alle stemmen',
 203+ 'poll-your-vote' => 'U hebt al voor "$1" gestemd op $2. U kunt uw stem wijzigen door hieronder op een antwoord te klikken.',
 204+ 'poll-no-vote' => 'Stem hieronder.',
 205+ 'poll-info' => 'Er zijn {{PLURAL:$1|een stem|$1 stemmen}} uitgebracht sinds de peiling op $2 is aangemaakt.',
 206+ 'poll-submitting' => 'Even geduld alstublieft. Uw stem wordt opgeslagen...',
 207+);
 208+
 209+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 210+ * @author Nghtwlkr
 211+ */
 212+$messages['no'] = array(
 213+ 'poll-vote-update' => 'Din stemme har blitt oppdatert.',
 214+ 'poll-vote-add' => 'Din stemme har blitt lagt til.',
 215+ 'poll-vote-error' => 'Det oppstod et problem med behandlingen av din stemme, vennligst prøv igjen.',
 216+ 'poll-percent-votes' => '$1% av alle stemmer',
 217+ 'poll-your-vote' => 'Du har allerede stemt på «$1» den $2, du kan endre din stemme ved å klikke på et svar nedenfor.',
 218+ 'poll-no-vote' => 'Vennligst stem nedenfor.',
 219+ 'poll-info' => 'Det var $1 stemmer siden spørreundersøkelsen ble opprettet den $2.', // @todo FIXME: out of date, needs PLURAL
 220+ 'poll-submitting' => 'Vennligst vent, sender inn stemmen din.',
 221+);
 222+
 223+/** Polish (Polskie)
 224+ * @author Dariusz Siedlecki
 225+ */
 226+$messages['pl'] = array(
 227+ 'poll-vote-update' => 'Twój głos został zmieniony.',
 228+ 'poll-vote-add' => 'Twój głos został dodany.',
 229+ 'poll-vote-error' => 'Wystąpił błąd w czasie dodawania głosu, proszę spróbować później.',
 230+ 'poll-percent-votes' => '$1% wszystkich głosów',
 231+ 'poll-your-vote' => 'Zagłosowałeś juz na "$1" $2, możesz zaktualizować swój głos klikając na odpowiedź poniżej.',
 232+ 'poll-no-vote' => 'Podaj swój głos poniżej.',
 233+ 'poll-info' => 'Oddano już $1 głosy/ów od założenia ankiety dnia $2.', // @todo FIXME: out of date, needs PLURAL
 234+ 'poll-submitting' => 'Proszę czekać, trwa dodawanie głosu.',
 235+);
 236+
 237+/** Piedmontese (Piemontèis)
 238+ * @author Borichèt
 239+ * @author Dragonòt
 240+ */
 241+$messages['pms'] = array(
 242+ 'poll-vote-update' => "Tò vot a l'é stàit modificà.",
 243+ 'poll-vote-add' => "Tò vot a l'é stàit giontà.",
 244+ 'poll-vote-error' => "A l'é staje un problema an tratand sò vot, për piasì ch'a preuva torna.",
 245+ 'poll-percent-votes' => '$1% ëd tùit ij vot',
 246+ 'poll-your-vote' => 'A l\'ha già votà për "$1" su $2; a peul cangé sò vot an sgnacand su na rispòsta sì-sota.',
 247+ 'poll-no-vote' => 'Për piasì, voté sì-sota.',
 248+ 'poll-info' => "A son staje $1 vot da quand ël sondagi a l'é stàit creà su $2.", // @todo FIXME: out of date, needs PLURAL
 249+ 'poll-submitting' => "Për piasì ch'a speta, sò vot a l'é an camin ch'a riva.",
 250+);
 251+
 252+/** Brazilian Portuguese (Português do Brasil)
 253+ * @author Daemorris
 254+ */
 255+$messages['pt-br'] = array(
 256+ 'poll-vote-update' => 'Seu voto foi atualizado.',
 257+ 'poll-vote-add' => 'Seu voto foi adicionado.',
 258+ 'poll-vote-error' => 'Houve um problema com o processamento de seu voto, por favor tente novamente.',
 259+ 'poll-percent-votes' => '$1% de todos votos',
 260+ 'poll-your-vote' => 'Vocâ já votou para "$1" em $2, você pode alterar seu voto clicando em uma opção abaixo.',
 261+ 'poll-no-vote' => 'Por favor vote abaixo.',
 262+ 'poll-info' => '{{PLURAL:$1|Um voto|$1 votos}} desde a criação da votação em $2.',
 263+ 'poll-submitting' => 'Por favor aguarde, enviando sua opção.',
 264+);
 265+
 266+/** Russian (Русский)
 267+ * @author Lockal
 268+ * @author Александр Сигачёв
 269+ */
 270+$messages['ru'] = array(
 271+ 'poll-vote-add' => 'Ваш голос добавлен.',
 272+ 'poll-vote-update' => 'Ваш голос обновлён.',
 273+ 'poll-vote-error' => 'Возникла проблема с обработкой вашего голоса, пожалуйста, попробуйте ещё раз.',
 274+ 'poll-percent-votes' => '$1% от всех голосов',
 275+ 'poll-your-vote' => 'Вы уже проголосовали «$1» $2. Вы можете изменить свой выбор, нажав на один из представленных ниже ответов.',
 276+ 'poll-no-vote' => 'Пожалуйста, проголосуйте ниже.',
 277+ 'poll-info' => 'С момента создания голосования $2 поступило $1 голосов.', // @todo FIXME: out of date, needs PLURAL
 278+ 'poll-submitting' => 'Пожалуйста, подождите, ваш голос обрабатывается.',
 279+);
 280+
 281+/** Serbian Cyrillic ekavian (Српски (ћирилица))
 282+ * @author Sasa Stefanovic
 283+ * @author Verlor
 284+ */
 285+$messages['sr-ec'] = array(
 286+ 'poll-vote-update' => 'аш глас је био урачунат.',
 287+ 'poll-vote-add' => 'Ваш галс је додан',
 288+ 'poll-percent-votes' => '$1% од свих гласова',
 289+ 'poll-no-vote' => 'Молимо гласајте испод.',
 290+ 'poll-submitting' => 'Чекајте, шаљемо ваш глас.',
 291+);
 292+
 293+/** Chinese (中文)
 294+ * @author 許瑜真 (Yuchen Hsu/KaurJmeb)
 295+ */
 296+$messages['zh'] = array(
 297+ 'poll-no-vote' => '請於下方投票',
 298+ 'poll-percent-votes' => '$1%',
 299+ 'poll-submitting' => '正在處理您的投票,請稍候。',
 300+ 'poll-vote-add' => '您的投票已計入',
 301+ 'poll-vote-error' => '投票過程發生問題,請再試一次',
 302+ 'poll-vote-update' => '你的投票已更新',
 303+);
\ No newline at end of file
Property changes on: trunk/extensions/AJAXPoll/AJAXPoll.i18n.php
___________________________________________________________________
Added: svn:eol-style
1304 + native

Comments

#Comment by Siebrand (talk | contribs)   18:46, 9 October 2011

Please add message documentation for the newly added messages. Thanks.

Hooks functions should be in a separate file/class.

#Comment by Jack Phoenix (talk | contribs)   19:08, 9 October 2011

Interface message documentation is now available on-wiki.

As for the issue with functions polluting the global scope, it's a known issue (see the commit message); this code is rather old. I figured I'd commit it since someone might want to use it and it works.

#Comment by Johnduhart (talk | contribs)   19:30, 9 October 2011

But it being on-wiki doesn't help translators who use the translation interface over at translatewiki

#Comment by Jack Phoenix (talk | contribs)   20:51, 9 October 2011

I'm aware of that, but I believe that the whole message documentation system in its current state is as functional as Special:UserRights before Werdna rewrote it.

  1. qqq is not a translation and adds additional, unwanted clutter into the .i18n.php files
  2. Translators are not the only audience of message documentation; wiki administrators (end users) might also be interested in how to customize an extension (or a skin, etc.)
  3. You can't really embed images in a PHP file, but you can do that on a wiki page

For me, it's all about quality, not about quantity — a picture is worth a thousand words, as they say, and I think that images are a lot more useful than English text snippets; with images, you can actually see where and how the message you're about to translate is used.

#Comment by Nikerabbit (talk | contribs)   21:10, 9 October 2011

Not providing message documentation is sure way to reduce the quality of translations. You can use images in message documentation, as long as the image is uploaded to translatewiki.net or commons. Imho (1) is just bikeshedding and not a real argument.

#Comment by Reach Out to the Truth (talk | contribs)   01:21, 10 October 2011

The secondary audience mentioned in point 2 can also benefit from the qqq messages you criticized in point 1.

And if there's more detailed information/images elsewhere, why not link to them in the qqq messages?

#Comment by Jack Phoenix (talk | contribs)   21:16, 10 October 2011

My biggest issue with qqq "messages" is their very presence in the .i18n.php files. We don't commit any other site-specific messages into core or extension .i18n.php files, so I don't think we should commit TWN-specific stuff.

As a stopgap solution, I'd propose adding a new configuration variable to Extension:Translate and thus to TWN's config, which would allow extensions to opt out of certain "translations", in this case, qqq. When someone from TWN staff exports messages, certain "languages" for certain extensions (groups) would be excluded, i.e. social tools could opt out of qqq "translations". It's not the solution for the issue, but it's a solution that could work.

While things have changed quite a lot in 5 years, what Rob Church wrote back in December 2006 still holds true: "I don't *care* if no one translates it. I would *like* people to do so, but the software works fine without 30 odd language versions." (emphasis mine) I would also like to point out that the on-wiki documentation written by me, stored on a wiki, has worked well for various different translators at ShoutWiki.

#Comment by Raymond (talk | contribs)   21:30, 10 October 2011

Message documentation as pseudo language 'qqq' is maybe not the best solution but the qqq section does not hurt, neither in a technical way nor for coders. Feel free to provide a better solution. But is has to shown the message doc in translatewiki.net for proper translations.

I can remove all "your" extensions from translatewiki if that is what you want.

Btw: Rob is definitly *not* right. Software w/o translation works fine for a English speaking people only. Not everybody in the world understand English.

#Comment by Nikerabbit (talk | contribs)   06:59, 11 October 2011

There is not inherently any site specific in them, it just happens to be twn where translation happens. Opting out does not help if nobody writes them in the first place. Rob may not care, but we do, seriously.

#Comment by Jack Phoenix (talk | contribs)   20:36, 12 October 2011
But is has to shown the message doc in translatewiki.net for proper translations.

I'm just wondering why is it so unreasonable for a developer to assume that translators will take the time to read a page or two on MediaWiki.org to find out what kind of a thing they're translating.

I can remove all "your" extensions from translatewiki if that is what you want.

I think that wouldn't be the best solution, considering things from the end-user's point of view, but you'll do what you must.

There is not inherently any site specific in them

We don't bundle templates (i.e. {{desc}} and friends) with core, so I'd say that is site-specific enough.

Opting out does not help if nobody writes them in the first place.

I'm willing to document the extensions which I've helped to write, as I've done in the past; I'm OK with copying whatever I've written over to TWN (or any other wiki, for that matter), I just don't want to see that stuff in the .i18n.php file. :)

If I may suggest, I'd like to propose that we continue this discussion on wikitech-l, because that way it might reach a wider audience and this conversation is no longer directly related to this revision — the complaint about the lack of message documentation has been adressed.

Status & tagging log