r91585 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r91584‎ | r91585 | r91586 >
Date:19:18, 6 July 2011
Author:questpc
Status:deferred
Tags:
Comment:
Merging old revision of QPoll to use svn move at next commit
Modified paths:
  • /trunk/extensions/QPoll/INSTALL (modified) (history)
  • /trunk/extensions/QPoll/README (modified) (history)
  • /trunk/extensions/QPoll/archives (deleted) (history)
  • /trunk/extensions/QPoll/ctrl (deleted) (history)
  • /trunk/extensions/QPoll/i18n (deleted) (history)
  • /trunk/extensions/QPoll/qp_eval.php (deleted) (history)
  • /trunk/extensions/QPoll/qp_i18n.php (added) (history)
  • /trunk/extensions/QPoll/qp_interpret.php (deleted) (history)
  • /trunk/extensions/QPoll/qp_pollstore.php (modified) (history)
  • /trunk/extensions/QPoll/qp_question.php (added) (history)
  • /trunk/extensions/QPoll/qp_results.css (modified) (history)
  • /trunk/extensions/QPoll/qp_results.php (modified) (history)
  • /trunk/extensions/QPoll/qp_user.css (modified) (history)
  • /trunk/extensions/QPoll/qp_user.js (modified) (history)
  • /trunk/extensions/QPoll/qp_user.php (modified) (history)
  • /trunk/extensions/QPoll/qp_user_rtl.css (modified) (history)
  • /trunk/extensions/QPoll/qpoll.sql (added) (history)
  • /trunk/extensions/QPoll/qpoll.src (added) (history)
  • /trunk/extensions/QPoll/tables (deleted) (history)
  • /trunk/extensions/QPoll/view (deleted) (history)

Diff [purge]

Index: trunk/extensions/QPoll/qp_interpret.php
@@ -1,119 +0,0 @@
2 -<?php
3 -/**
4 - * ***** BEGIN LICENSE BLOCK *****
5 - * This file is part of QPoll.
6 - * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved.
7 - *
8 - * QPoll is free software; you can redistribute it and/or modify
9 - * it under the terms of the GNU General Public License as published by
10 - * the Free Software Foundation; either version 2 of the License, or
11 - * (at your option) any later version.
12 - *
13 - * QPoll is distributed in the hope that it will be useful,
14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 - * GNU General Public License for more details.
17 - *
18 - * You should have received a copy of the GNU General Public License
19 - * along with QPoll; if not, write to the Free Software
20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 - *
22 - * ***** END LICENSE BLOCK *****
23 - *
24 - * QPoll is a poll tool for MediaWiki.
25 - *
26 - * To activate this extension :
27 - * * Create a new directory named QPoll into the directory "extensions" of MediaWiki.
28 - * * Place the files from the extension archive there.
29 - * * Add this line at the end of your LocalSettings.php file :
30 - * require_once "$IP/extensions/QPoll/qp_user.php";
31 - *
32 - * @version 0.8.0a
33 - * @link http://www.mediawiki.org/wiki/Extension:QPoll
34 - * @author QuestPC <questpc@rambler.ru>
35 - */
36 -
37 -if ( !defined( 'MEDIAWIKI' ) ) {
38 - die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
39 -}
40 -
41 -class qp_Interpret {
42 -
43 - /**
44 - * Glues the content of <qpinterpret> tags together, checks "lang" attribute
45 - * and calls appropriate interpretator to evaluate the user answer
46 - *
47 - * @param $interpArticle _existing_ article with interpretation script enclosed in <qpinterp> tags
48 - * @param $answers array of user selected categories for every proposal & question of the poll
49 - * @return instance of qp_InterpAnswer class
50 - */
51 - static function getAnswer( $interpArticle, $answers ) {
52 - global $wgParser;
53 - $matches = array();
54 - # extract <qpinterpret> tags from the article content
55 - $wgParser->extractTagsAndParams( array( qp_Setup::$interpTag ), $interpArticle->getRawText(), $matches );
56 - $interpAnswer = new qp_InterpAnswer();
57 - # glue content of all <qpinterpret> tags at the page together
58 - $interpretScript = '';
59 - $lang = '';
60 - foreach ( $matches as &$match ) {
61 - list( $tagName, $content, $attrs ) = $match;
62 - # basic checks for lang attribute (only lang="php" is implemented yet)
63 - # however we do not want to limit interpretation language,
64 - # so the attribute is enforced to use
65 - if ( !isset( $attrs['lang'] ) ) {
66 - return $interpAnswer->setError( wfMsg( 'qp_error_eval_missed_lang_attr' ) );
67 - }
68 - if ( $lang == '' ) {
69 - $lang = $attrs['lang'];
70 - } elseif ( $attrs['lang'] != $lang ) {
71 - return $interpAnswer->setError( wfMsg( 'qp_error_eval_mix_languages', $lang, $attrs['lang'] ) );
72 - }
73 - if ( $tagName == qp_Setup::$interpTag ) {
74 - $interpretScript .= $content;
75 - }
76 - }
77 - switch ( $lang ) {
78 - case 'php' :
79 - $result = qp_Eval::interpretAnswer( $interpretScript, $answers, $interpAnswer );
80 - if ( $result instanceof qp_InterpAnswer ) {
81 - # evaluation error (environment error) , return it;
82 - return $interpAnswer;
83 - }
84 - break;
85 - default :
86 - return $interpAnswer->setError( wfMsg( 'qp_error_eval_unsupported_language', $lang ) );
87 - }
88 - /*** process the result ***/
89 - if ( !is_array( $result ) ) {
90 - return $interpAnswer->setError( wfMsg( 'qp_error_interpretation_no_return' ) );
91 - }
92 - # initialize $interpAnswer->qpError[] member array
93 - foreach ( $result as $qidx => $question ) {
94 - if ( is_int( $qidx ) && is_array( $question ) ) {
95 - foreach ( $question as $pidx => $error ) {
96 - if ( is_int( $pidx ) ) {
97 - # everywhere but interpretation scripts:
98 - # question start from 1, proposals start from 0
99 - $interpAnswer->setQPerror( $qidx + 1, $pidx, $error );
100 - }
101 - }
102 - }
103 - }
104 - if ( isset( $result['error'] ) && trim( $result['error'] ) != '' ) {
105 - # script-generated error for the whole answer
106 - return $interpAnswer->setError( (string) $result['error'] );
107 - }
108 - # if there were question/proposal errors, return them;
109 - if ( $interpAnswer->isError() ) {
110 - return $interpAnswer;
111 - }
112 - if ( !isset( $result['short'] ) || !isset( $result['long'] ) ) {
113 - return $interpAnswer->setError( wfMsg( 'qp_error_interpretation_no_return' ) );
114 - }
115 - $interpAnswer->short = (string) $result['short'];
116 - $interpAnswer->long = (string) $result['long'];
117 - return $interpAnswer;
118 - }
119 -
120 -} /* end of qp_Interpret class */
Index: trunk/extensions/QPoll/qp_eval.php
@@ -1,358 +0,0 @@
2 -<?php
3 -/**
4 - * ***** BEGIN LICENSE BLOCK *****
5 - * This file is part of QPoll.
6 - * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved.
7 - *
8 - * QPoll is free software; you can redistribute it and/or modify
9 - * it under the terms of the GNU General Public License as published by
10 - * the Free Software Foundation; either version 2 of the License, or
11 - * (at your option) any later version.
12 - *
13 - * QPoll is distributed in the hope that it will be useful,
14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 - * GNU General Public License for more details.
17 - *
18 - * You should have received a copy of the GNU General Public License
19 - * along with QPoll; if not, write to the Free Software
20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 - *
22 - * ***** END LICENSE BLOCK *****
23 - *
24 - * QPoll is a poll tool for MediaWiki.
25 - *
26 - * To activate this extension :
27 - * * Create a new directory named QPoll into the directory "extensions" of MediaWiki.
28 - * * Place the files from the extension archive there.
29 - * * Add this line at the end of your LocalSettings.php file :
30 - * require_once "$IP/extensions/QPoll/qp_user.php";
31 - *
32 - * @version 0.8.0a
33 - * @link http://www.mediawiki.org/wiki/Extension:QPoll
34 - * @author QuestPC <questpc@rambler.ru>
35 - */
36 -
37 -if ( !defined( 'MEDIAWIKI' ) ) {
38 - die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
39 -}
40 -
41 -class qp_Eval {
42 -
43 - # the list of allowed PHP tokens
44 - # filtered using the complete list at http://www.php.net/manual/ru/tokens.php
45 - # is it bullet-proof enough?
46 - static $allowedTokens = array(
47 - T_AND_EQUAL,
48 - T_ARRAY,
49 - T_AS,
50 - T_BOOLEAN_AND,
51 - T_BOOLEAN_OR,
52 - T_BOOL_CAST,
53 - T_BREAK,
54 - T_CASE,
55 - T_COMMENT,
56 - T_CONCAT_EQUAL,
57 - T_CONSTANT_ENCAPSED_STRING,
58 - T_CONTINUE,
59 - T_DEC,
60 - T_DEFAULT,
61 - T_DIV_EQUAL,
62 - T_DNUMBER,
63 - T_DOC_COMMENT,
64 - T_DOUBLE_ARROW,
65 - T_DOUBLE_CAST,
66 - T_ELSE,
67 - T_ELSEIF,
68 - T_EMPTY,
69 - T_ENCAPSED_AND_WHITESPACE,
70 - T_ENDFOREACH,
71 - T_ENDIF,
72 - T_ENDSWITCH,
73 - T_END_HEREDOC,
74 - T_FOREACH,
75 - T_FUNCTION,
76 - T_IF,
77 - T_INC,
78 - T_INT_CAST,
79 - T_ISSET,
80 - T_IS_EQUAL,
81 - T_IS_GREATER_OR_EQUAL,
82 - T_IS_IDENTICAL,
83 - T_IS_NOT_EQUAL,
84 - T_IS_NOT_IDENTICAL,
85 - T_IS_SMALLER_OR_EQUAL,
86 - T_LIST,
87 - T_LNUMBER,
88 - T_LOGICAL_AND,
89 - T_LOGICAL_OR,
90 - T_LOGICAL_XOR,
91 - T_MINUS_EQUAL,
92 - T_MOD_EQUAL,
93 - T_MUL_EQUAL,
94 - T_NUM_STRING,
95 - T_OR_EQUAL,
96 - T_PLUS_EQUAL,
97 - T_RETURN,
98 - T_SL,
99 - T_SL_EQUAL,
100 - T_SR,
101 - T_SR_EQUAL,
102 - T_START_HEREDOC,
103 - T_STRING,
104 - T_STRING_CAST,
105 - T_SWITCH,
106 - T_UNSET,
107 - T_UNSET_CAST,
108 - T_VARIABLE,
109 - T_WHITESPACE,
110 - T_XOR_EQUAL
111 - );
112 -
113 - # allowed functions
114 - static $allowedCalls = array(
115 - # math
116 - 'round', 'trunc', 'ceil', 'floor',
117 - # arrays
118 - 'is_array', 'array_search',
119 - # strings
120 - 'preg_match', 'preg_split'
121 - );
122 -
123 - # disallowed superglobals
124 - static $superGlobals = array(
125 - '$GLOBALS',
126 - '$_SERVER',
127 - '$_GET',
128 - '$_POST',
129 - '$_FILES',
130 - '$_REQUEST',
131 - '$_SESSION',
132 - '$_ENV',
133 - '$_COOKIE',
134 - '$php_errormsg',
135 - '$HTTP_RAW_POST_DATA',
136 - '$http_response_header',
137 - '$argc',
138 - '$argv'
139 - );
140 -
141 - # prefix added to local variable names which prevents
142 - # from accessing local scope variables in eval'ed code
143 - static $pseudoNamespace = 'qpv_';
144 -
145 - # the list of disallowed code
146 - # please add new entries, if needed.
147 - # key 'badresult' means that formally the code is allowed,
148 - # however the returned result has to be checked
149 - # (eg. variable substitution is incorrect)
150 - static $disallowedCode = array(
151 - array(
152 - 'code' => '$test = $_SERVER["REQUEST_URI"];',
153 - 'desc' => 'Disallow reading from superglobals'
154 - ),
155 - array(
156 - 'code' => '$GLOBALS["wgVersion"] = "test";',
157 - 'desc' => 'Disallow writing to superglobals'
158 - ),
159 - array(
160 - 'code' => 'global $wgVersion;',
161 - 'desc' => 'Disallow visibility of globals in local scope'
162 - ),
163 - array(
164 - 'code' => 'return isset( $selfCheck );',
165 - 'badresult' => true,
166 - 'desc' => 'Disallow access to extension\'s locals in the eval scope'
167 - ),
168 - array(
169 - 'code' => '$writevar = 1; $var = "writevar"; $$var = "test";',
170 - 'desc' => 'Disallow writing to variable variables'
171 - ),
172 - array(
173 - 'code' => '$readvar = 1; $var = "readvar"; $test = $$var;',
174 - 'desc' => 'Disallow reading from variable variables'
175 - ),
176 - array(
177 - 'code' => '$readvar = 1; $var = "readvar"; $test = "my$$var 1";',
178 - 'desc' => 'Disallow reading from complex variable variables'
179 - ),
180 - array(
181 - 'code' => '$dh = opendir( "./" );',
182 - 'desc' => 'Disallow illegal function calls'
183 - ),
184 - array(
185 - 'code' => '$func = "opendir"; $dh=$func( "./" );',
186 - 'desc' => 'Disallow variable function calls'
187 - ),
188 - array(
189 - 'code' => 'return "test$selfCheck result";',
190 - 'badresult' => 'test1 result',
191 - 'desc' => 'Disallow extension\'s local scope variables in "simple" complex variables'
192 - ),
193 - array(
194 - 'code' => '$curlydollar = "1"; $var = "test{$curlydollar}a";',
195 - 'desc' => 'Disallow complex variables (curlydollar)'
196 - ),
197 - array(
198 - 'code' => '$dollarcurly = "1"; $var = "test${dollarcurly}a";',
199 - 'desc' => 'Disallow complex variables (dollarcurly)'
200 - ),
201 - array(
202 - 'code' => '$obj = new stdClass; $obj = new stdClass(); $obj -> a = 1;',
203 - 'desc' => 'Disallow creation of objects'
204 - ),
205 - array(
206 - 'code' => '$obj -> a = 1;',
207 - 'desc' => 'Disallow indirect creation of objects'
208 - ),
209 - array(
210 - 'code' => '$obj = (object) array("a"=>1);',
211 - 'desc' => 'Disallow cast to objects'
212 - ),
213 - array(
214 - 'code' => 'for ( $i = 0; $i < 1; $i++ ) {};',
215 - 'desc' => 'Disallow for loops, which easily can be made infinite'
216 - )
217 - );
218 -
219 - /**
220 - * Check against the list of known disallowed code (for eval)
221 - * should be executed before every eval, because PHP upgrade can introduce
222 - * incompatibility leading to secure hole at any time
223 - * @return
224 - */
225 - static function selfCheck() {
226 - # the following var is used to check access to extension's locals
227 - # in the eval scope
228 - $selfCheck = 1;
229 - foreach ( self::$disallowedCode as $key => &$sourceCode ) {
230 - # check source code sample
231 - $destinationCode = '';
232 - $result = self::checkAndTransformCode( $sourceCode['code'], $destinationCode );
233 - if ( isset( $sourceCode['badresult'] ) ) {
234 - # the code is meant to be vaild, however the result may be insecure
235 - if ( $result !== true ) {
236 - # there is an error in sample
237 - return 'Sample error:' . $sourceCode['desc'];
238 - }
239 - # compare eval() result with "insecure" bad result
240 - if ( eval( $destinationCode ) === $sourceCode['badresult'] ) {
241 - return $sourceCode['desc'];
242 - }
243 - } else {
244 - # the code meant to be invalid
245 - if ( $result === true ) {
246 - # illegal destination code which was passed as vaild
247 - return $sourceCode['desc'];
248 - }
249 - }
250 - }
251 - return true;
252 - }
253 -
254 - /**
255 - * Checks the submitted eval code for errors
256 - * In case of success returns transformed code, which is safer for eval
257 - * @param $sourceCode submitted code which has to be eval'ed (no php tags)
258 - * @param $destinationCode transformed code (in case of success) (no php tags)
259 - * @return boolean true in case of success, string with error message on failure
260 - */
261 - static function checkAndTransformCode( $sourceCode, &$destinationCode ) {
262 -
263 - # tokenizer requires php tags to parse propely,
264 - # eval(), however requires not to have php tags - weird..
265 - $tokens = token_get_all( "<?php $sourceCode ?>" );
266 - /* remove <?php ?> */
267 - array_shift( $tokens );
268 - array_pop( $tokens );
269 -
270 - $destinationCode = '';
271 - $prev_token = null;
272 - foreach ( $tokens as $token ) {
273 - if ( is_array( $token ) ) {
274 - list( $token_id, $content, $line ) = $token;
275 - # check against generic list of disallowed tokens
276 - if ( !in_array( $token_id, self::$allowedTokens, true ) ) {
277 - return wfMsg( 'qp_error_eval_illegal_token', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
278 - }
279 - if ( $token_id == T_VARIABLE ) {
280 - $prev_content = is_array( $prev_token ) ? $prev_token[1] : $prev_token;
281 - preg_match( '`(\$)$`', $prev_content, $matches );
282 - # disallow variable variables
283 - if ( count( $matches ) > 1 && $matches[1] == '$' ) {
284 - return wfMsg( 'qp_error_eval_variable_variable_access', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
285 - }
286 - # disallow superglobals
287 - if ( in_array( $content, self::$superGlobals ) ) {
288 - return wfMsg( 'qp_error_eval_illegal_superglobal', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
289 - }
290 - # restrict variable names
291 - preg_match( '`^(\$)([A-Za-z0-9_]*)$`', $content, $matches );
292 - if ( count( $matches ) != 3 ) {
293 - return wfMsg( 'qp_error_eval_illegal_variable_name', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
294 - }
295 - # correct variable names into pseudonamespace 'qpv_'
296 - $content = "\$" . self::$pseudoNamespace . $matches[2];
297 - }
298 - # do not count whitespace as previous token
299 - if ( $token_id != T_WHITESPACE ) {
300 - $prev_token = $token;
301 - }
302 - # concat corrected token to the destination
303 - $destinationCode .= $content;
304 - } else {
305 - if ( $token == '(' && is_array( $prev_token ) ) {
306 - list( $token_id, $content, $line ) = $prev_token;
307 - # disallow variable function calls
308 - if ( $token_id === T_VARIABLE ) {
309 - return wfMsg( 'qp_error_eval_variable_function_call', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
310 - }
311 - # disallow non-allowed function calls based on the list
312 - if ( $token_id === T_STRING && array_search( $content, self::$allowedCalls ) === false ) {
313 - return wfMsg( 'qp_error_eval_illegal_function_call', token_name( $token_id ), QP_Setup::specialchars( $content ), $line );
314 - }
315 - }
316 - $prev_token = $token;
317 - # concat current token to the destination
318 - $destinationCode .= $token;
319 - }
320 - }
321 -
322 - return true;
323 - }
324 -
325 - /**
326 - * Interpretates the answer with selected script
327 - * @param $interpretScript string source code of interpretation script
328 - * @param $answers array of user selected categories for every proposal & question of the poll
329 - * @param $interpAnswer instance of qp_InterpAnswer class
330 - * @modifies $interpAnswer
331 - * @return array script result to check, or
332 - * qpInterpAnswer $interpAnswer (in case of error)
333 - */
334 - function interpretAnswer( $interpretScript, $answers, qp_InterpAnswer $interpAnswer ) {
335 - # template page evaluation
336 - if ( !function_exists( 'json_decode' ) ) {
337 - # environment error
338 - return $interpAnswer->setError( wfMsg( 'qp_error_no_json_decode' ) );
339 - }
340 - if ( ( $check = self::selfCheck() ) !== true ) {
341 - # self-check error
342 - return $interpAnswer->setError( wfMsg( 'qp_error_eval_self_check', $check ) );
343 - }
344 - $evalScript = '';
345 - if ( ( $check = self::checkAndTransformCode( $interpretScript, $evalScript ) ) !== true ) {
346 - # possible malicious code
347 - return $interpAnswer->setError( $check );
348 - }
349 - # inject poll answer into the interpretation script
350 - $evalScript =
351 -"\$" . self::$pseudoNamespace . "a = json_decode( <<<HEREDOC
352 -" . FormatJson::encode( $answers ) . "
353 -HEREDOC
354 -, true );\n" . $evalScript;
355 - $result = eval( $evalScript );
356 - return $result;
357 - }
358 -
359 -}
Index: trunk/extensions/QPoll/qp_user.php
@@ -28,7 +28,7 @@
2929 * * Add this line at the end of your LocalSettings.php file :
3030 * require_once "$IP/extensions/QPoll/qp_user.php";
3131 *
32 - * @version 0.8.0a
 32+ * @version 0.7.0
3333 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3434 * @author QuestPC <questpc@rambler.ru>
3535 */
@@ -37,11 +37,13 @@
3838 die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
3939 }
4040
41 -# interpretation scripts namespace
42 -define( 'NS_QP_INTERPRETATION', 800 );
43 -# talk namespace is always + 1
44 -define( 'NS_QP_INTERPRETATION_TALK', 801 );
 41+define( 'QP_CSS_ERROR_COLOR2', "#D700D7" );
4542
 43+define( 'QP_ERROR_MISSED_TITLE', 1 );
 44+define( 'QP_ERROR_INVALID_ADDRESS', 2 );
 45+
 46+define( 'QP_MAX_TEXT_ANSWER_LENGTH', 1024 );
 47+
4648 qp_Setup::init();
4749
4850 /**
@@ -50,7 +52,7 @@
5153 $wgExtensionCredits['parserhook'][] = array(
5254 'path' => __FILE__,
5355 'name' => 'QPoll',
54 - 'version' => '0.8.0a',
 56+ 'version' => '0.7.0',
5557 'author' => 'QuestPC',
5658 'url' => 'http://www.mediawiki.org/wiki/Extension:QPoll',
5759 'descriptionmsg' => 'qp_desc',
@@ -58,7 +60,7 @@
5961 $wgExtensionCredits['specialpage'][] = array(
6062 'path' => __FILE__,
6163 'name' => 'QPoll results page',
62 - 'version' => '0.8.0a',
 64+ 'version' => '0.7.0',
6365 'author' => 'QuestPC',
6466 'url' => 'http://www.mediawiki.org/wiki/Extension:QPoll',
6567 'descriptionmsg' => 'qp_desc-sp',
@@ -78,82 +80,17 @@
7981 );
8082 }
8183
82 -if ( !isset( $wgAutoloadClasses['FormatJson'] ) ) {
83 - // for MediaWiki 1.15
84 - class FormatJson {
85 -
86 - /**
87 - * Returns the JSON representation of a value.
88 - *
89 - * @param $value Mixed: the value being encoded. Can be any type except a resource.
90 - * @param $isHtml Boolean
91 - *
92 - * @return string
93 - */
94 - public static function encode( $value, $isHtml = false ) {
95 - // Some versions of PHP have a broken json_encode, see PHP bug
96 - // 46944. Test encoding an affected character (U+20000) to
97 - // avoid this.
98 - if ( !function_exists( 'json_encode' ) || $isHtml || strtolower( json_encode( "\xf0\xa0\x80\x80" ) ) != '\ud840\udc00' ) {
99 - $json = new Services_JSON();
100 - return $json->encode( $value, $isHtml );
101 - } else {
102 - return json_encode( $value );
103 - }
104 - }
105 -
106 - /**
107 - * Decodes a JSON string.
108 - *
109 - * @param $value String: the json string being decoded.
110 - * @param $assoc Boolean: when true, returned objects will be converted into associative arrays.
111 - *
112 - * @return Mixed: the value encoded in json in appropriate PHP type.
113 - * Values true, false and null (case-insensitive) are returned as true, false
114 - * and &null; respectively. &null; is returned if the json cannot be
115 - * decoded or if the encoded data is deeper than the recursion limit.
116 - */
117 - public static function decode( $value, $assoc = false ) {
118 - if ( !function_exists( 'json_decode' ) ) {
119 - $json = new Services_JSON();
120 - $jsonDec = $json->decode( $value );
121 - if( $assoc ) {
122 - $jsonDec = wfObjectToArray( $jsonDec );
123 - }
124 - return $jsonDec;
125 - } else {
126 - return json_decode( $value, $assoc );
127 - }
128 - }
129 -
130 - } /* end of FormatJson class */
131 -}
132 -
13384 /**
13485 * Extension's global settings and initializiers
13586 * should be purely static and preferrably have no constructor
13687 */
13788 class qp_Setup {
13889
139 - const ERROR_MISSED_TITLE = 1;
140 - const ERROR_INVALID_ADDRESS = 2;
141 - const MAX_TEXT_ANSWER_LENGTH = 1024;
142 -
143 - static $pollTag = 'qpoll';
144 - static $interpTag = 'qpinterpret';
145 - # parser $interpTag hook output market list
146 - static $markerList = array();
147 -
14890 static $ExtDir; // filesys path with windows path fix
14991 static $ScriptPath; // apache virtual path
15092 static $messagesLoaded = false; // check whether the extension's localized messages are loaded
15193 static $article; // Article instance we got from hook parameter
15294 static $user; // User instance we got from hook parameter
153 - # extension's namespaces with their canonical names
154 - static $namespaces = array(
155 - NS_QP_INTERPRETATION => 'Interpretation',
156 - NS_QP_INTERPRETATION_TALK => 'Interpretation_talk'
157 - );
15895
15996 /**
16097 * default configuration settings
@@ -165,8 +102,6 @@
166103 public static $anon_forwarded_for = false;
167104 # enable parser and article caches control for better performance (somewhat experimental, may break compatibility; checked with MW v1.15, v1.16)
168105 public static $cache_control = false;
169 - # number of submit attempts allowed (0 or less for infinite number)
170 - public static $max_submit_attempts = 0;
171106 /* end of default configuration settings */
172107
173108 static function entities( $s ) {
@@ -206,137 +141,35 @@
207142 }
208143
209144 /**
210 - * Autoload classes from the map provided
211 - */
212 - static function autoLoad( $map ) {
213 - global $wgAutoloadClasses;
214 - foreach ( $map as $path => &$classes ) {
215 - if ( is_array( $classes ) ) {
216 - foreach ( $classes as &$className ) {
217 - $wgAutoloadClasses[$className] = self::$ExtDir . '/' . $path;
218 - }
219 - } else {
220 - $wgAutoloadClasses[$classes] = self::$ExtDir . '/' . $path;
221 - }
222 - }
223 - }
224 -
225 - /**
226145 * Add this extension to the mediawiki's extensions list.
227146 */
228147 static function init() {
229148 global $wgScriptPath;
230 - global $wgExtensionMessagesFiles, $wgExtensionAliasesFiles;
 149+ global $wgAutoloadClasses;
 150+ global $wgExtensionMessagesFiles;
231151 global $wgSpecialPages;
232152 global $wgHooks;
233 - global $wgExtraNamespaces, $wgNamespaceProtection;
234 - global $wgGroupPermissions;
235 -
236 - # core check and local / remote path
237153 self::coreRequirements();
238154 self::$ExtDir = str_replace( "\\", "/", dirname(__FILE__) );
239155 $dirs = explode( '/', self::$ExtDir );
240156 $top_dir = array_pop( $dirs );
241157 self::$ScriptPath = $wgScriptPath . '/extensions' . ( ( $top_dir == 'extensions' ) ? '' : '/' . $top_dir );
242 -
243 - # language files
244 - # extension messages
245 - $wgExtensionMessagesFiles['QPoll'] = self::$ExtDir . '/i18n/qp.i18n.php';
246 - # localized namespace names
247 - $wgExtensionMessagesFiles['QPollNamespaces'] = self::$ExtDir . '/i18n/qp.namespaces.php';
248 - # localized special page titles
249 - $wgExtensionAliasesFiles['QPoll'] = self::$ExtDir . '/i18n/qp.alias.php';
250 -
251 - # extension setup, hooks handling and content transformation
252 - self::autoLoad( array(
253 - 'qp_user.php' => array( 'FormatJson', 'qp_Setup', 'qp_Renderer', 'qp_FunctionsHook' ),
254 -
255 - ## controllers (polls and questions derived from separate abstract classes)
256 - # polls
257 - 'ctrl/qp_abstractpoll.php' => 'qp_AbstractPoll',
258 - 'ctrl/qp_poll.php' => 'qp_Poll',
259 - 'ctrl/qp_pollstats.php' => 'qp_PollStats',
260 - # questions
261 - 'ctrl/qp_abstractquestion.php' => 'qp_AbstractQuestion',
262 - 'ctrl/qp_question.php' => 'qp_Question',
263 - 'ctrl/qp_questionstats.php' => 'qp_QuestionStats',
264 -
265 - ## views are derived from single generic class
266 - ## isCompatibleController() method is used to check linked controllers (bugcheck)
267 - # generic
268 - 'view/qp_abstractview.php' => 'qp_AbstractView',
269 - # questions
270 - 'view/qp_questionview.php' => 'qp_QuestionView',
271 - 'view/qp_questionstatsview.php' => 'qp_QuestionStatsView',
272 - # polls
273 - 'view/qp_pollview.php' => 'qp_PollView',
274 - 'view/qp_pollstatsview.php' => 'qp_PollStatsView',
275 -
276 - # storage
277 - 'qp_pollstore.php' => array( 'qp_QuestionData', 'qp_InterpAnswer', 'qp_PollStore' ),
278 -
279 - # results page
280 - 'qp_results.php' => array( 'qp_QueryPage', 'PollResults' ),
281 -
282 - # interpretation of answers
283 - 'qp_interpret.php' => 'qp_Interpret',
284 - 'qp_eval.php' => 'qp_Eval'
285 - ) );
286 -
287 - # TODO: Use the new technique for i18n of special page aliases
 158+ $wgExtensionMessagesFiles['QPoll'] = self::$ExtDir . '/qp_i18n.php';
 159+ $wgAutoloadClasses['PollResults'] = self::$ExtDir . '/qp_results.php';
 160+ $wgAutoloadClasses['qp_Question'] =
 161+ $wgAutoloadClasses['qp_QuestionStats'] = self::$ExtDir . '/qp_question.php';
 162+ $wgAutoloadClasses['qp_PollStore'] =
 163+ $wgAutoloadClasses['qp_QuestionData'] = self::$ExtDir . '/qp_pollstore.php';
 164+ $wgAutoloadClasses['qp_QueryPage'] = self::$ExtDir . '/qp_results.php';
 165+ // TODO: Use the new technique for i18n of special page aliases
288166 $wgSpecialPages['PollResults'] = 'PollResults';
289 - # TODO: Use the new technique for i18n of magic words
290 - # instantiating fake instance for PHP < 5.2.3, which does not support 'Class::method' type of callbacks
 167+ // TODO: Use the new technique for i18n of magic words
 168+ // instantiating fake instance for PHP < 5.2.3, which does not support 'Class::method' type of callbacks
291169 $wgHooks['LanguageGetMagic'][] =
292170 $wgHooks['MediaWikiPerformAction'][] =
293 - $wgHooks['ParserFirstCallInit'][] =
294 - $wgHooks['LoadAllMessages'][] =
295 - $wgHooks['ParserAfterTidy'][] =
296 - $wgHooks['CanonicalNamespaces'][] =
297 - new qp_Setup;
298 -
299 - # define namespaces for the interpretation scripts and their talk pages
300 - foreach ( self::$namespaces as $ns_idx => $canonical_name ) {
301 - if ( isset( $wgExtraNamespaces[$ns_idx] ) ) {
302 - die( "QPoll requires namespace index {$ns_idx} which is already used by another extension. Either disable another extension or change the namespace index." );
303 - }
304 - $wgNamespaceProtection[$ns_idx] = array( 'editinterpretation' );
305 - }
306 - if ( self::mediaWikiVersionCompare( '1.17' ) ) {
307 - foreach ( self::$namespaces as $ns_idx => $canonical_name ) {
308 - $wgExtraNamespaces[$ns_idx] = $canonical_name;
309 - }
310 - }
311 -
312 - # groups which has permission to access poll results by default
313 - $wgGroupPermissions['sysop']['showresults'] = true;
314 - $wgGroupPermissions['bureaucrat']['showresults'] = true;
315 - $wgGroupPermissions['polladmin']['showresults'] = true;
316 - # groups which can edit interpretation scripts by default
317 - # please minimize the number of groups as low as you can
318 - # that is security measure against inserting of malicious code
319 - # into the source of interpretation scripts
320 - $wgGroupPermissions['sysop']['editinterpretation'] = true;
321 - $wgGroupPermissions['bureaucrat']['editinterpretation'] = true;
 171+ $wgHooks['ParserFirstCallInit'][] = new qp_Setup;
322172 }
323173
324 - static function mediaWikiVersionCompare( $version, $operator = '<' ) {
325 - global $wgVersion;
326 - return version_compare( $wgVersion, $version, $operator );
327 - }
328 -
329 - static function onLoadAllMessages() {
330 - if ( !self::$messagesLoaded ) {
331 - self::$messagesLoaded = true;
332 - # for MW 1.15 which is still being used by many customers
333 - # please do not remove until 2012
334 - if ( self::mediaWikiVersionCompare( '1.16' ) ) {
335 - wfLoadExtensionMessages( 'QPoll' );
336 - }
337 - }
338 - return true;
339 - }
340 -
341174 static function ParserFunctionsWords( $lang ) {
342175 $words = array();
343176 $words[ 'en' ] = array( 'qpuserchoice'=>array( 0, 'qpuserchoice' ) );
@@ -430,8 +263,7 @@
431264 }
432265 global $wgQPollFunctionsHook;
433266 # setup tag hook
434 - $parser->setHook( self::$pollTag, array( 'qp_Setup', 'showPoll' ) );
435 - $parser->setHook( self::$interpTag, array( 'qp_Setup', 'showScript' ) );
 267+ $parser->setHook( 'qpoll', array( 'qp_Setup', 'renderPoll' ) );
436268 $wgQPollFunctionsHook = new qp_FunctionsHook();
437269 # setup function hook
438270 $parser->setFunctionHook( 'qpuserchoice', array( &$wgQPollFunctionsHook, 'qpuserchoice' ), SFH_OBJECT_ARGS );
@@ -443,92 +275,789 @@
444276 *
445277 * @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax.
446278 * @param $argv An array containing any arguments passed to the extension
447 - * @param &$parser The wikitext parser.
 279+ * @param &$parser The wikitext parser.
448280 * @param &$frame PPFrame object passed in MW 1.16+
449281 * @return An HTML poll.
450282 */
451283
452284 /* @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax. */
453 - static function showPoll( $input, $argv, $parser, $frame = false ) {
 285+ static function renderPoll( $input, $argv, $parser, $frame = false ) {
454286 if ( !self::$cache_control ) {
455287 $parser->disableCache();
456288 }
457289 if ( array_key_exists( 'address', $argv ) ) {
458 - $qpoll = new qp_PollStats(
459 - $argv,
460 - new qp_PollStatsView( $parser, $frame )
461 - );
 290+ $qpoll = new qp_PollStats( $argv, $parser, $frame );
462291 } else {
463 - $qpoll = new qp_Poll(
464 - $argv,
465 - new qp_PollView( $parser, $frame )
466 - );
 292+ $qpoll = new qp_Poll( $argv, $parser, $frame );
467293 }
468294 return $qpoll->parsePoll( $input );
469295 }
470296
471 - /**
472 - * Show interpetation script source with line numbering (for debugging convenience)
 297+}
 298+
 299+/***
 300+ * a poll stub which cannot process and render itself
 301+ * to process and render itself, real Poll should extend this class to implement it's own:
 302+ $this->getPollStore()
 303+ $this->parseInput()
 304+ $this->generateOutput()
 305+ ***/
 306+class qp_AbstractPoll {
 307+
 308+ static $skin;
 309+ static $sOrderId = 0; // order of polls on the page (used for sorting of the output)
 310+ static $sPrevPollIDs = Array(); // used to check uniqueness of PollId on the page
 311+
 312+ var $parser; // parser for parsing tags content
 313+ var $ppframe; // parser context passed in MW 1.16+; unused in MW 1.15
 314+ var $username;
 315+
 316+ # an ID of the poll on current page (used in declaration/voting mode)
 317+ var $mPollId = null;
 318+ var $mOrderId = null; // order_id in DB that will used to sort out polls on the Special:PollResults statistics page
 319+ # poll address of the poll to display statistics (used in statistical mode)
 320+ var $pollAddr = null;
 321+ var $mQuestionId = null; // the unique index number of the question in the current poll (used to instantiate the questions)
 322+
 323+ var $mState = ''; // current state of poll parsing (no error)
 324+ var $dependsOn = ''; // optional address of the poll which must be answered first
 325+ var $mBeingCorrected = false; // true, when the poll is posted (answered)
 326+
 327+ # the following showresults types are currently available:
 328+ # 0 - none; 1 - percents; 2 - bars
 329+ # may contain extra options (color, width) for selected display type
 330+ var $showResults = Array( 'type'=>0 ); // hide showResults by default
 331+
 332+ // qp_pollStore instance that will be used to transfer poll data from/to DB
 333+ var $pollStore = null;
 334+
 335+ /**
 336+ * Constructor
473337 *
474 - * @param $input Text between <qpinterpret> and </qpinterper> tags, subset of PHP syntax.
475 - * @param $argv An array containing any arguments passed to the extension
476 - * @param &$parser The wikitext parser.
477 - * @param &$frame PPFrame object passed in MW 1.16+
478 - * @return script source with line numbering
 338+ * @public
479339 */
480 - static function showScript( $input, $argv, $parser, $frame = false ) {
481 - $lines_count = count( preg_split( '`(\r\n|\n|\r)`', $input, -1 ) );
482 - $line_numbers = '';
483 - for ( $i = 1; $i <= $lines_count; $i++ ) {
484 - $line_numbers .= "{$i}\n";
 340+ function __construct( $argv, &$parser, &$frame ) {
 341+ global $wgUser, $wgRequest, $wgLanguageCode;
 342+ $this->parser = &$parser;
 343+ $this->ppframe = $frame;
 344+ $this->mRequest = &$wgRequest;
 345+ $this->mResponse = $wgRequest->response();
 346+ # load current skin
 347+ if ( self::$skin === null ) {
 348+ self::$skin = $wgUser->getSkin();
485349 }
486 - $out =
487 - array( '__tag'=>'div', 'class'=>'qpoll',
488 - array( '__tag'=>'div', 'class'=>'line_numbers', $line_numbers ),
489 - array( '__tag'=>'div', 'class'=>'script_view', qp_Setup::specialchars( $input ) . "\n" )
490 - );
 350+ # reset the unique index number of the question in the current poll (used to instantiate the questions)
 351+ $this->mQuestionId = 0; // ( correspons to 'question_id' DB field )
 352+ $this->username = self::currentUserName();
491353
492 - $markercount = count( self::$markerList );
493 - $marker = "!qpoll-script-view{$markercount}-qpoll!";
494 - self::$markerList[$markercount] = qp_Renderer::renderHTMLobject( $out );
495 - return $marker;
 354+ # *** get visual style poll attributes ***
 355+ $this->perRow = intval( array_key_exists( 'perrow', $argv ) ? $argv['perrow'] : 1 );
 356+ if ( $this->perRow < 1 )
 357+ $this->perRow = 1;
 358+ $this->currCol = $this->perRow;
 359+ if ( array_key_exists( 'showresults', $argv ) && qp_Setup::$global_showresults != 0 ) {
 360+ if ( $argv['showresults'] == 'showresults' ) {
 361+ # default showresults for the empty value of xml attribute
 362+ $argv['showresults'] = '1';
 363+ }
 364+ $this->showResults = self::parse_showResults( $argv['showresults'] );
 365+ }
 366+ # every poll on the page should have unique poll id, to minimize the risk of collisions
 367+ # it is required to be set manually via id="value" parameter
 368+ # ( used only in "declaration" mode )
 369+ $this->mPollId = array_key_exists('id', $argv) ? trim( $argv['id'] ) : null;
 370+ if ( array_key_exists('dependance', $argv) ) {
 371+ $this->dependsOn = trim( $argv['dependance'] );
 372+ }
496373 }
497374
498375 /**
499 - * replace previousely set markers with actual rendered html of source text
500 - * which has line numbers for easier way to spot possible eval check errors
501 - * otherwise, this html code will be ruined when passed directly to parser
 376+ * Convert the input text to an HTML output.
 377+ *
 378+ * @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax.
502379 */
503 - static function onParserAfterTidy( $parser, &$text ) {
504 - # find markers in $text
505 - # replace markers with actual output
506 - $keys = array();
507 - $marker_count = count( self::$markerList );
 380+ function parsePoll( $input ) {
 381+ if ( ($result = $this->getPollStore() ) !== true ) {
 382+ # error message box (invalid poll attributes)
 383+ return $result;
 384+ }
 385+ if ( ($result = $this->parseInput( $input ) ) === true ) {
 386+ # no output generation - due to active redirect or access denied
 387+ return '';
 388+ } else {
 389+ # generateOutput() assumes that the poll is not being submitted and is correctly declared
 390+ return $this->generateOutput( $result );
 391+ }
 392+ }
508393
509 - for ( $i = 0; $i < $marker_count; $i++ ) {
510 - $keys[] = "!qpoll-script-view{$i}-qpoll!";
 394+ static function fatalError() {
 395+ $args = func_get_args();
 396+ $result = 'Extension bug: ' . __METHOD__ . ' called without arguments';
 397+ if ( count( $args > 0 ) ) {
 398+ $result = call_user_func_array( 'wfMsgHTML', $args );
511399 }
 400+ return '<div class="qpoll"><div class="fatalerror">' . $result . '</div></div>';
 401+ }
512402
513 - $text = str_replace( $keys, self::$markerList, $text );
 403+ # title fragment part (GET/POST)
 404+ static function getPollTitleFragment( $pollid, $dash = '#' ) {
 405+ return $dash . 'qp_' . Title::escapeFragmentForURL( $pollid );
 406+ }
 407+
 408+ static function addPollId ( $pollId ) {
 409+ self::$sPrevPollIDs[] = $pollId;
 410+ }
 411+
 412+ function isValidPollId( $pollId ) {
 413+ // more non-allowed chars ?
 414+ return !preg_match('`#`u', $pollId );
 415+ }
 416+
 417+ function isUniquePollId( $pollId ) {
 418+ return !in_array( $pollId, self::$sPrevPollIDs );
 419+ }
 420+
 421+ static function currentUserName() {
 422+ global $wgUser, $wgSquidServers;
 423+ global $wgUsePrivateIPs;
 424+ if ( qp_Setup::$anon_forwarded_for === true && $wgUser->isAnon() ) {
 425+ /* collect the originating IPs
 426+ borrowed from ProxyTools::wfGetIP
 427+ bypass trusted proxies list check */
 428+ # Client connecting to this webserver
 429+ if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
 430+ $ipchain = array( IP::canonicalize( $_SERVER['REMOTE_ADDR'] ) );
 431+ } else {
 432+ # Running on CLI?
 433+ $ipchain = array( '127.0.0.1' );
 434+ }
 435+ $ip = $ipchain[0];
 436+
 437+ # Append XFF on to $ipchain
 438+ $forwardedFor = wfGetForwardedFor();
 439+ if ( isset( $forwardedFor ) ) {
 440+ $xff = array_map( 'trim', explode( ',', $forwardedFor ) );
 441+ $xff = array_reverse( $xff );
 442+ $ipchain = array_merge( $ipchain, $xff );
 443+ }
 444+ $username = "";
 445+ foreach ( $ipchain as $i => $curIP ) {
 446+ if( $wgUsePrivateIPs || IP::isPublic( $curIP ) ) {
 447+ $username .= IP::canonicalize( $curIP ) . '/';
 448+ }
 449+ }
 450+ if ( $username != "" ) {
 451+ # remove trailing slash
 452+ $username = substr( $username, 0, strlen( $username ) - 1 );
 453+ } else {
 454+ $username .= IP::canonicalize( $ipchain[0] );
 455+ }
 456+ } else {
 457+ $username = $wgUser->getName();
 458+ }
 459+ return $username;
 460+ }
 461+
 462+ // @input $addr - source poll address (possibly the short one) in the string or array form
 463+ // @return array[0] - title where the poll is located
 464+ // array[1] - pollId string
 465+ // array[2] - prefixed (complete) poll address
 466+ // false - invalid source poll address was given
 467+ static function getPrefixedPollAddress( $addr ) {
 468+ global $wgTitle;
 469+ if ( is_array( $addr ) ) {
 470+ if ( count( $addr ) > 1 ) {
 471+ list( $titlePart, $pollIdPart ) = $addr;
 472+ } else {
 473+ return false;
 474+ }
 475+ } else {
 476+ preg_match( '`^(.*?)#(.*?)$`u', $addr, $matches );
 477+ if ( count( $matches ) == 3 ) {
 478+ $titlePart = trim( $matches[1] );
 479+ $pollIdPart = trim( $matches[2] );
 480+ } else {
 481+ return false;
 482+ }
 483+ }
 484+ if ( $pollIdPart == '' ) {
 485+ return false;
 486+ }
 487+ if ( $titlePart == '' ) {
 488+ # poll is located at the current page
 489+ $titlePart = $wgTitle->getPrefixedText();
 490+ }
 491+ return array( $titlePart, $pollIdPart, $titlePart . '#' . $pollIdPart );
 492+ }
 493+
 494+ // parses source showresults xml parameter value and returns the corresponding showResults array
 495+ // input: $str contains entries separated by ';'
 496+ // entry 1 is a number of showresults type (always presented)
 497+ // entries 2..n are optional css-style list of attributes and their values
 498+ // returns showResults parsed array
 499+ // 'type' indicates the type, optional keys contain values of css-style attributes
 500+ static function parse_showResults( $str ) {
 501+ $showResults['type'] = 0;
 502+ $attrs = array_map( 'trim', explode( ';', $str ) );
 503+ if ( count( $attrs ) > 0 ) {
 504+ $showResults['type'] = intval( array_shift( $attrs ) );
 505+ if ( $showResults['type'] < 0 ) {
 506+ $showResults['type'] = 0;
 507+ }
 508+ if ( $showResults['type'] != 0 && count( $attrs ) > 0 ) {
 509+ foreach( $attrs as &$attr ) {
 510+ preg_match( '`([A-Za-z]+):([#\w]+)`u', $attr, $matches );
 511+ if ( count( $matches ) == 3 ) {
 512+ $showResults[ $matches[1] ] = $matches[2];
 513+ }
 514+ }
 515+ }
 516+ }
 517+ return $showResults;
 518+ }
 519+
 520+}
 521+
 522+/**
 523+ * Processes poll markup in statistical mode (only to show the results)
 524+ */
 525+class qp_PollStats extends qp_AbstractPoll {
 526+
 527+ function __construct( $argv, &$parser, &$frame ) {
 528+ parent::__construct( $argv, $parser, $frame );
 529+ $this->pollAddr = trim( $argv['address'] );
 530+ # statistical mode is active, but qp_Setup::$global_showresults still can be false
 531+ if ( qp_Setup::$global_showresults == 0 ) {
 532+ $this->showResults = false;
 533+ }
 534+ }
 535+
 536+ # prepare qp_PollStore object
 537+ # @return true on success ($this->pollStore has been created successfully), error string on failure
 538+ function getPollStore() {
 539+ if ( $this->mPollId !== null ) {
 540+ $this->mState = "error";
 541+ return self::fatalError( 'qp_error_id_in_stats_mode' );
 542+ }
 543+ if ( $this->dependsOn !== '' ) {
 544+ $this->mState = "error";
 545+ return self::fatalError( 'qp_error_dependance_in_stats_mode' );
 546+ }
 547+ $this->pollStore = qp_PollStore::newFromAddr( $this->pollAddr );
 548+ if ( !($this->pollStore instanceof qp_PollStore) || $this->pollStore->pid === null ) {
 549+ return self::fatalError( 'qp_error_no_such_poll', $this->pollAddr );
 550+ }
 551+ if ( !$this->pollStore->loadQuestions() ) {
 552+ $this->mState = "error";
 553+ return self::fatalError( 'qp_error_no_stats', $this->pollAddr );
 554+ }
 555+ $this->pollStore->setLastUser( $this->username, false );
 556+ # do not check the result, because we may show results even if the user hasn't voted
 557+ $this->pollStore->loadUserAlreadyVoted();
514558 return true;
515559 }
516560
517 - public static function onCanonicalNamespaces( &$list ) {
518 - # do not use array_merge() as it will destroy negative indexes in $list
519 - # thus completely ruining the namespaces list
520 - foreach ( self::$namespaces as $ns_idx => $canonical_name ) {
521 - $list[$ns_idx] = $canonical_name;
 561+ # Replace questions from QPoll syntax to HTML
 562+ # @param $input - A question in QPoll statistical mode syntax
 563+ # @return string representing rendered set of the questions / boolean true - stop further processing
 564+ function parseInput( $input ) {
 565+ $write_row = Array();
 566+ $write_col = Array();
 567+ $questions = Array();
 568+ # question attributes split pattern
 569+ $splitPattern = '`\s*{|}\s*\n*`u';
 570+ # preg_split counts the matches starting from zero
 571+ $unparsedAttributes = preg_split( $splitPattern, $input, -1, PREG_SPLIT_NO_EMPTY );
 572+ # we count questions starting from 1
 573+ array_unshift( $unparsedAttributes, null );
 574+ unset( $unparsedAttributes[0] );
 575+ # first pass: parse the headers
 576+ foreach ( $this->pollStore->Questions as &$qdata ) {
 577+ $question = new qp_QuestionStats( $this->parser, $this->ppframe, $qdata->type, $qdata->question_id, $this->showResults );
 578+ if ( isset( $unparsedAttributes[$qdata->question_id] ) ) {
 579+ $attr_str = $unparsedAttributes[$qdata->question_id];
 580+ } else {
 581+ $attr_str = '';
 582+ }
 583+ if ( ($type = $question->parseAttributes( $attr_str )) != '' ) {
 584+ # there cannot be type attribute of question in statistical display mode
 585+ $question->setState( 'error', wfMsg( 'qp_error_type_in_stats_mode', $type ) );
 586+ }
 587+ $questions[] = $question;
522588 }
 589+ # analyze question headers
 590+ # check for showresults attribute
 591+ $questions_set = Array();
 592+ foreach ( $questions as &$question ) {
 593+ if ( $question->showResults['type'] != 0 &&
 594+ method_exists( 'qp_Question', 'addShowResults' . $question->showResults['type'] ) ) {
 595+ $questions_set[] = $question->mQuestionId;
 596+ }
 597+ }
 598+ # load the statistics for all/selective/none of questions
 599+ if ( count( $questions_set ) > 0 ) {
 600+ if ( count( $questions_set ) == count( $questions ) ) {
 601+ $this->pollStore->loadTotals();
 602+ } else {
 603+ $this->pollStore->loadTotals( $questions_set );
 604+ }
 605+ $this->pollStore->calculateStatistics();
 606+ }
 607+ # second pass: parse the statistics
 608+ foreach ( $questions as &$question ) {
 609+ # render the question statistics only when showResuls isn't 0 (suppress stats)
 610+ if ( $question->showResults['type'] != 0 ) {
 611+ if ( $this->perRow > 1 ) {
 612+ $write_col[] = array( '__tag'=>'td', 'valign'=>'top', 0=>$this->parseStats( $question ), '__end'=>"\n" );
 613+ if ( $this->currCol == 1 ) {
 614+ $write_row[] = array( '__tag'=>'tr', 0=>$write_col, '__end'=>"\n" );
 615+ $write_col = Array();
 616+ }
 617+ if ( --$this->currCol < 1 ) {
 618+ $this->currCol = $this->perRow;
 619+ }
 620+ } else {
 621+ $write_row[] = $this->parseStats( $question );
 622+ }
 623+ }
 624+ # question object is not needed anymore
 625+ unset( $question );
 626+ }
 627+ if ( $this->perRow > 1 && $this->currCol != $this->perRow ) {
 628+ # add last incomplete row
 629+ $write_row[] = array( '__tag'=>'tr', '__end'=>"\n", 0=>$write_col );
 630+ }
 631+ if ( $this->perRow > 1 ) {
 632+ $question_table = array( '__tag'=>'table', 0=>array( '__tag'=>'tbody', 0=>&$write_row, '__end'=>"\n" ), '__end'=>"\n" );
 633+ return qp_Renderer::renderHTMLobject( $question_table );
 634+ } else {
 635+ return qp_Renderer::renderHTMLobject( $write_row );
 636+ }
 637+ }
 638+
 639+ # encloses the output of $this->parseQuestions() into the output tag wrappers
 640+ # @param $input - the output of $this->parseQuestions()
 641+ # @return rendered "final" html
 642+ function generateOutput( $input ) {
 643+ global $wgOut;
 644+ # Generates the output.
 645+ $qpoll_div = array( '__tag'=>'div', 'class'=>'qpoll', 0=>$input );
 646+ return qp_Renderer::renderHTMLobject( $qpoll_div );
 647+ }
 648+
 649+ # populate the question with data and build it's HTML representation
 650+ # returns HTML representation of the question
 651+ function parseStats( qp_QuestionStats &$question ) {
 652+ # parse the question body
 653+ $buffer = '';
 654+ if ( $question->getQuestionAnswer( $this->pollStore ) ) {
 655+ # check whether the current global showresults level allows to display statistics
 656+ if ( qp_Setup::$global_showresults == 0 ||
 657+ (qp_Setup::$global_showresults <= 1 && !$question->alreadyVoted) ) {
 658+ # suppress the output
 659+ return '';
 660+ }
 661+ $buffer = $question->renderStats();
 662+ }
 663+ $output_table = array( '__tag'=>'table', '__end'=>"\n", 'class'=>'object' );
 664+ # Determine the side border color the question.
 665+ $output_table[] = array( '__tag'=>'tbody', '__end'=>"\n", 0=>$buffer );
 666+ $tags = array( '__tag'=>'div', '__end'=>"\n", 'class'=>'question',
 667+ 0=>array( '__tag'=>'div', '__end'=>"\n", 'class'=>'header',
 668+ 0=>array( '__tag'=>'span', 'class'=>'questionId', 0=>$question->mQuestionId )
 669+ ),
 670+ 1=>array( '__tag'=>'div', 0=>$this->parser->recursiveTagParse( $question->mCommonQuestion, $this->ppframe ) )
 671+ );
 672+ $tags[] = &$output_table;
 673+ return qp_Renderer::renderHTMLobject( $tags );
 674+ }
 675+
 676+}
 677+
 678+/**
 679+ * Processes poll markup in declaration/voting mode
 680+ */
 681+class qp_Poll extends qp_AbstractPoll {
 682+
 683+ function __construct( $argv, &$parser, &$frame ) {
 684+ parent::__construct( $argv, $parser, $frame );
 685+ # order_id is used to sort out polls on the Special:PollResults statistics page
 686+ $this->mOrderId = self::$sOrderId;
 687+ # Determine if this poll is being corrected or not, according to the pollId
 688+ $this->mBeingCorrected = ( $this->mRequest->getVal('pollId') == $this->mPollId );
 689+ }
 690+
 691+ # prepare qp_PollStore object
 692+ # @return true on success ($this->pollStore has been created successfully), error string on failure
 693+ function getPollStore() {
 694+ # check the headers for errors
 695+ if ( $this->mPollId == null ) {
 696+ $this->mState = "error";
 697+ return self::fatalError( 'qp_error_no_poll_id' );
 698+ }
 699+ if ( !self::isValidPollId( $this->mPollId ) ) {
 700+ $this->mState = "error";
 701+ return self::fatalError( 'qp_error_invalid_poll_id', $this->mPollId );
 702+ }
 703+ if ( !self::isUniquePollId( $this->mPollId ) ) {
 704+ $this->mState = "error";
 705+ return self::fatalError( 'qp_error_already_used_poll_id', $this->mPollId );
 706+ }
 707+ self::addPollId( $this->mPollId ); // add current poll id to the static list of poll ids on this page
 708+ if ( $this->pollAddr !== null ) {
 709+ $this->mState = "error";
 710+ return self::fatalError( 'qp_error_address_in_decl_mode' );
 711+ }
 712+ if ( $this->dependsOn != '' ) {
 713+ $depsOnAddr = self::getPrefixedPollAddress( $this->dependsOn );
 714+ if ( is_array( $depsOnAddr ) ) {
 715+ $this->dependsOn = $depsOnAddr[2];
 716+ } else {
 717+ return self::fatalError( 'qp_error_invalid_dependance_value', $this->mPollId, $this->dependsOn );
 718+ }
 719+ }
 720+ if ( ( $dependanceResult = $this->checkDependance( $this->dependsOn ) ) !== true ) {
 721+ # return an error string
 722+ # here we create a pollstore only to update poll attributes (order_id,dependance), in case these were changed
 723+ $this->pollStore = new qp_PollStore( array(
 724+ 'from'=>'poll_get',
 725+ 'poll_id'=>$this->mPollId,
 726+ 'order_id'=>$this->mOrderId,
 727+ 'dependance'=>$this->dependsOn ) );
 728+ return $dependanceResult;
 729+ }
 730+ if ( $this->mBeingCorrected ) {
 731+ $this->pollStore = new qp_PollStore( array(
 732+ 'from'=>'poll_post',
 733+ 'poll_id'=>$this->mPollId,
 734+ 'order_id'=>$this->mOrderId,
 735+ 'dependance'=>$this->dependsOn ) );
 736+ $this->pollStore->loadQuestions();
 737+ $this->pollStore->setLastUser( $this->username, false );
 738+ $this->pollStore->loadUserAlreadyVoted();
 739+ } else {
 740+ $this->pollStore = new qp_PollStore( array(
 741+ 'from'=>'poll_get',
 742+ 'poll_id'=>$this->mPollId,
 743+ 'order_id'=>$this->mOrderId,
 744+ 'dependance'=>$this->dependsOn ) );
 745+ $this->pollStore->loadQuestions();
 746+ $this->pollStore->setLastUser( $this->username, false );
 747+ # to show previous choice of current user, if that's available
 748+ # do not check the result, because user can vote even if haven't voted before
 749+ $this->pollStore->loadUserVote();
 750+ }
523751 return true;
524752 }
525753
526 -} /* end of qp_Setup class */
 754+ # parse the text enclosed in poll tag
 755+ # @param $input - text enclosed in poll tag
 756+ # @return string representing rendered set of the questions / boolean true - stop further processing
 757+ function parseInput( $input ) {
 758+ global $wgTitle;
 759+ # Process the input
 760+ $output = $this->parseQuestions( $input );
 761+ # check whether the poll was successfully submitted
 762+ if ( $this->pollStore->stateComplete() ) {
 763+ # store user vote to the DB (when the poll is fine)
 764+ $this->pollStore->setLastUser( $this->username );
 765+ $this->pollStore->setUserVote();
 766+ }
 767+ if ( $this->pollStore->voteDone ) {
 768+ if ( qp_Setup::$cache_control ) {
 769+ $this->mResponse->setcookie( 'QPoll', 'clearCache', time()+20 );
 770+ }
 771+ $this->mResponse->header( 'HTTP/1.0 302 Found' );
 772+ $this->mResponse->header( 'Location: ' . $wgTitle->getFullURL() . self::getPollTitleFragment( $this->mPollId ) );
 773+ return true;
 774+ }
 775+ return $output;
 776+ }
527777
528 -/* renders output data */
 778+ # encloses the output of $this->parseQuestions() into the output tag wrappers
 779+ # @param $input - the output of $this->parseQuestions()
 780+ # @return rendered "final" html
 781+ function generateOutput( $input ) {
 782+ global $wgOut, $wgRequest;
 783+ # increase the order_id counter for the future successfully declared polls
 784+ # (remember, we're in declaration mode, where 'order_id' is important
 785+ self::$sOrderId++;
 786+ # Generates the output.
 787+ $qpoll_div = array( '__tag'=>'div', 'class'=>'qpoll' );
 788+ $qpoll_div[] = array( '__tag'=>'a', 'name'=>self::getPollTitleFragment( $this->mPollId, '' ), 0=>'' );
 789+ $qpoll_form = array( '__tag'=>'form', 'method'=>'post', 'action'=>self::getPollTitleFragment( $this->mPollId ), '__end'=>"\n" );
 790+ $qpoll_div[] = &$qpoll_form;
 791+ # Determine the content of the settings table.
 792+ $settings = Array();
 793+ if ( $this->mState != '' ) {
 794+ $settings[0][] = array( '__tag'=>'td', 'class'=>'margin', 'style'=>'background: ' . QP_CSS_ERROR_COLOR2 . ';' );
 795+ $settings[0][] = array( '__tag'=>'td', 0=>wfMsgHtml( 'qp_result_' . $this->mState ) );
 796+ }
 797+ # Build the settings table.
 798+ if ( count( $settings ) > 0 ) {
 799+ $settingsTable = array( '__tag'=>'table', 'class'=>'settings', '__end'=>"\n" );
 800+ foreach($settings as $settingsTr) {
 801+ $settingsTable[] = array( '__tag'=>'tr', 0=> $settingsTr, '__end'=>"\n" );
 802+ }
 803+ $qpoll_form[] = &$settingsTable;
 804+ }
 805+ $qpoll_form[] = array( '__tag'=>'input', 'type'=>'hidden', 'name'=>'pollId', 'value'=>$this->mPollId );
 806+ $qpoll_form[] = array( '__tag'=>'div', 'class'=>'pollQuestions', 0=>$input );
 807+ $submitBtn = array( '__tag'=>'input', 'type'=>'submit' );
 808+ $submitMsg = 'qp_vote_button';
 809+ if ( $this->pollStore->isAlreadyVoted() ) {
 810+ $submitMsg = 'qp_vote_again_button';
 811+ }
 812+ if ( $this->mBeingCorrected ) {
 813+ if ( $this->pollStore->getState() == "complete" ) {
 814+ $submitMsg = 'qp_vote_again_button';
 815+ }
 816+ } else {
 817+ if ( $this->pollStore->getState() == "error" ) {
 818+ $submitBtn[ 'disabled' ] = 'disabled';
 819+ }
 820+ }
 821+ # disable submit button in preview mode & printable version
 822+ if ( $wgRequest->getVal( 'action' ) == 'parse' || $wgOut->isPrintable() ) {
 823+ $submitBtn[ 'disabled' ] = 'disabled';
 824+ }
 825+ $submitBtn[ 'value' ] = wfMsgHtml( $submitMsg );
 826+ $p = array( '__tag'=>'p' );
 827+ $p[] = $submitBtn;
 828+ $qpoll_form[] = &$p;
 829+ return qp_Renderer::renderHTMLobject( $qpoll_div );
 830+ }
 831+
 832+ # check whether the poll is dependant on other polls
 833+ # @param $dependsOn - poll address on which the current (recursive) poll is dependant
 834+ # @param $nonVotedDepLink - maintains different logic for recursion
 835+ # value: string - link to the poll in chain which has not been voted yet OR
 836+ # value: boolean - false when there was no poll in the chain which has not been voted yet
 837+ # @return true when dependance is fulfilled, error message otherwise
 838+ private function checkDependance( $dependsOn, $nonVotedDepLink = false ) {
 839+ # check the headers for dependance to other polls
 840+ if ( $dependsOn !== '' ) {
 841+ $depPollStore = qp_PollStore::newFromAddr( $dependsOn );
 842+ if ( $depPollStore instanceof qp_PollStore ) {
 843+ # process recursive dependance
 844+ $depTitle = $depPollStore->getTitle();
 845+ $depPollId = $depPollStore->mPollId;
 846+ $depLink = self::$skin->link( $depTitle, $depTitle->getPrefixedText() . ' (' . $depPollStore->mPollId . ')' );
 847+ if ( $depPollStore->pid === null ) {
 848+ return self::fatalError( 'qp_error_missed_dependance_poll', $this->mPollId, $depLink, $depPollId );
 849+ }
 850+ if ( !$depPollStore->loadQuestions() ) {
 851+ return self::fatalError( 'qp_error_vote_dependance_poll', $depLink );
 852+ }
 853+ $depPollStore->setLastUser( $this->username, false );
 854+ if ( $depPollStore->loadUserAlreadyVoted() ) {
 855+ # user already voted in current the poll in chain
 856+ if ( $depPollStore->dependsOn === '' ) {
 857+ if ( $nonVotedDepLink === false ) {
 858+ # there was no non-voted deplinks in the chain at some previous level of recursion
 859+ return true;
 860+ } else {
 861+ # there is an non-voted deplink in the chain at some previous level of recursion
 862+ return self::fatalError( 'qp_error_vote_dependance_poll', $nonVotedDepLink );
 863+ }
 864+ } else {
 865+ return $this->checkDependance( $depPollStore->dependsOn, $nonVotedDepLink );
 866+ }
 867+ } else {
 868+ # user hasn't voted in current the poll in chain
 869+ if ( $depPollStore->dependsOn === '' ) {
 870+ # current element of chain is not voted and furthermore, doesn't depend on any other polls
 871+ return self::fatalError( 'qp_error_vote_dependance_poll', $depLink );
 872+ } else {
 873+ # current element of chain is not voted, BUT it has it's own dependance
 874+ # so we will check for the most deeply nested poll which hasn't voted, yet
 875+ return $this->checkDependance( $depPollStore->dependsOn, $depLink );
 876+ }
 877+ }
 878+ } else {
 879+ # process poll address errors
 880+ switch ( $depPollStore ) {
 881+ case QP_ERROR_INVALID_ADDRESS :
 882+ return self::fatalError( 'qp_error_invalid_dependance_value', $this->mPollId, $dependsOn );
 883+ case QP_ERROR_MISSED_TITLE :
 884+ $depSplit = self::getPrefixedPollAddress( $dependsOn );
 885+ if ( is_array( $depSplit ) ) {
 886+ list( $depTitleStr, $depPollId ) = $depSplit;
 887+ $depTitle = Title::newFromURL( $depTitleStr );
 888+ $depTitleStr = $depTitle->getPrefixedText();
 889+ $depLink = self::$skin->link( $depTitle, $depTitleStr );
 890+ return self::fatalError( 'qp_error_missed_dependance_title', $this->mPollId, $depLink, $depPollId );
 891+ } else {
 892+ return self::fatalError( 'qp_error_invalid_dependance_value', $this->mPollId, $dependsOn );
 893+ }
 894+ default :
 895+ throw new MWException( __METHOD__ . ' invalid dependance poll store found' );
 896+ }
 897+ }
 898+ } else {
 899+ return true;
 900+ }
 901+ }
 902+
 903+ # Replace questions from QPoll syntax to HTML
 904+ # @param $input - A question in QPoll syntax
 905+ # @return string representing rendered set of the questions / empty string "suggests" redirect
 906+ function parseQuestions($input) {
 907+ $write_row = Array();
 908+ $write_col = Array();
 909+ $questions = Array();
 910+ $splitPattern = '`(^|\n\s*)\n\s*{`u';
 911+ $unparsedQuestions = preg_split( $splitPattern, $input, -1, PREG_SPLIT_NO_EMPTY );
 912+ $questionPattern = '`(.*?[^|\}])\}[ \t]*(\n(.*)|$)`su';
 913+ # first pass: parse the headers
 914+ foreach( $unparsedQuestions as $unparsedQuestion ) {
 915+ # If this "unparsedQuestion" is not a full question,
 916+ # we put the text into a buffer to add it at the beginning of the next question.
 917+ if( !empty( $buffer ) ) {
 918+ $unparsedQuestion = "$buffer\n\n{" . $unparsedQuestion;
 919+ }
 920+ if( preg_match( $questionPattern, $unparsedQuestion, $matches ) ) {
 921+ $buffer = "";
 922+ $header = isset( $matches[1] ) ? $matches[1] : '';
 923+ $body = isset( $matches[3] ) ? $matches[3] : null;
 924+ $questions[] = $this->parseQuestionHeader( $header, $body );
 925+ } else {
 926+ $buffer = $unparsedQuestion;
 927+ }
 928+ }
 929+ # analyze question headers
 930+ # check for showresults attribute
 931+ $questions_set = Array();
 932+ foreach( $questions as &$question ) {
 933+ if ( $question->showResults['type'] != 0 &&
 934+ method_exists( 'qp_Question', 'addShowResults' . $question->showResults['type'] ) ) {
 935+ $questions_set[] = $question->mQuestionId;
 936+ }
 937+ }
 938+ # load the statistics for all/selective/none of questions
 939+ if ( count( $questions_set ) > 0 ) {
 940+ if ( count( $questions_set ) == count( $questions ) ) {
 941+ $this->pollStore->loadTotals();
 942+ } else {
 943+ $this->pollStore->loadTotals( $questions_set );
 944+ }
 945+ $this->pollStore->calculateStatistics();
 946+ }
 947+ # second pass: parse the body
 948+ foreach( $questions as &$question ) {
 949+ if ( $this->perRow > 1 ) {
 950+ $write_col[] = array( '__tag'=>'td', 'valign'=>'top', 0=>$this->parseQuestionBody( $question ), '__end'=>"\n" );
 951+ if ( $this->currCol == 1 ) {
 952+ $write_row[] = array( '__tag'=>'tr', 0=>$write_col, '__end'=>"\n" );
 953+ $write_col = Array();
 954+ }
 955+ if ( --$this->currCol < 1 ) {
 956+ $this->currCol = $this->perRow;
 957+ }
 958+ } else {
 959+ $write_row[] = $this->parseQuestionBody( $question );
 960+ }
 961+ # question object is not needed anymore
 962+ unset( $question );
 963+ }
 964+ if ( $this->perRow > 1 && $this->currCol != $this->perRow ) {
 965+ # add last incomplete row
 966+ $write_row[] = array( '__tag'=>'tr', '__end'=>"\n", 0=>$write_col );
 967+ }
 968+ if ( $this->perRow > 1 ) {
 969+ $question_table = array( '__tag'=>'table', 0=>array( '__tag'=>'tbody', 0=>&$write_row, '__end'=>"\n" ), '__end'=>"\n" );
 970+ return qp_Renderer::renderHTMLobject( $question_table );
 971+ } else {
 972+ return qp_Renderer::renderHTMLobject( $write_row );
 973+ }
 974+ }
 975+
 976+ # Convert a question on the page from QPoll syntax to HTML
 977+ # @param $header : the text of question "main" header (common question and XML-like attrs)
 978+ # $body : the text of question body (starting with body header which defines categories and spans, followed by proposal list)
 979+ # @return question object with parsed headers and no data loaded
 980+ function parseQuestionHeader( $header, $body ) {
 981+ $question = new qp_Question( $this->parser, $this->ppframe, $this->mBeingCorrected, ++$this->mQuestionId, $this->showResults );
 982+ # parse questions common question and XML attributes
 983+ $question->parseMainHeader( $header );
 984+ if ( $question->getState() != 'error' ) {
 985+ # load previous user choice, when it's available and DB header is compatible with parsed header
 986+ if ( $body === null || !method_exists( $question, $question->mType . 'ParseBody' ) ) {
 987+ $question->setState( 'error', wfMsgHtml( 'qp_error_question_not_implemented', qp_Setup::entities( $question->mType ) ) );
 988+ } else {
 989+ # parse the categories and spans (metacategories)
 990+ $question->parseBodyHeader( $body );
 991+ }
 992+ }
 993+ return $question;
 994+ }
 995+
 996+ # populate the question with data and build it's HTML representation
 997+ # returns HTML representation of the question
 998+ function parseQuestionBody( &$question ) {
 999+ if ( $question->getState() == 'error' ) {
 1000+ # error occured during the previously performed header parsing, do not process further
 1001+ $buffer = $question->getHeaderError();
 1002+ # http get: invalid question syntax, parse errors will cause submit button disabled
 1003+ $this->pollStore->stateError();
 1004+ } else {
 1005+ # populate $question with raw source values
 1006+ $question->getQuestionAnswer( $this->pollStore );
 1007+ # check whether the global showresults level prohibits to show statistical data
 1008+ # to the users who hasn't voted
 1009+ if ( qp_Setup::$global_showresults <= 1 && !$question->alreadyVoted ) {
 1010+ # suppress statistical results when the current user hasn't voted the question
 1011+ $question->showResults = Array( 'type'=>0 );
 1012+ }
 1013+ # parse the question body
 1014+ # store the html result into the buffer to determine some parameters before outputing it
 1015+ # warning! parameters are passed only by value, not the reference
 1016+ $buffer = $question->{$question->mType . 'ParseBody'}();
 1017+ if ( $this->mBeingCorrected ) {
 1018+ if ( $question->getState() == '' ) {
 1019+ # question is OK, store it into pollStore
 1020+ $question->store( $this->pollStore );
 1021+ } else {
 1022+ # http post: not every proposals were answered: do not update DB
 1023+ $this->pollStore->stateIncomplete();
 1024+ }
 1025+ } else {
 1026+ # this is the get, not the post: do not update DB
 1027+ if ( $question->getState() == '' ) {
 1028+ $this->pollStore->stateIncomplete();
 1029+ } else {
 1030+ # http get: invalid question syntax, parse errors will cause submit button disabled
 1031+ $this->pollStore->stateError();
 1032+ }
 1033+ }
 1034+ }
 1035+ $output_table = array( '__tag'=>'table', '__end'=>"\n", 'class'=>'object' );
 1036+ # Determine the side border color the question.
 1037+ if ( $question->getState() != "" ) {
 1038+ global $wgContLang;
 1039+ $style = $wgContLang->isRTL() ? 'border-right' : 'border-left';
 1040+ $style .= ': 3px solid ' . QP_CSS_ERROR_COLOR2 . ';';
 1041+ $output_table[ 'style' ] = $style;
 1042+ $this->mState = $question->getState();
 1043+ }
 1044+ $output_table[] = array( '__tag'=>'tbody', '__end'=>"\n", 0=>&$buffer );
 1045+ $tags = array( '__tag'=>'div', '__end'=>"\n", 'class'=>'question',
 1046+ 0=>array( '__tag'=>'div', '__end'=>"\n", 'class'=>'header',
 1047+ 0=>array( '__tag'=>'span', 'class'=>'questionId', 0=>$question->mQuestionId )
 1048+ ),
 1049+ 1=>array( '__tag'=>'div', 0=>$this->parser->recursiveTagParse( $question->mCommonQuestion, $this->ppframe ) )
 1050+ );
 1051+ $tags[] = &$output_table;
 1052+ return qp_Renderer::renderHTMLobject( $tags );
 1053+ }
 1054+
 1055+}
 1056+
 1057+/* render output data */
5291058 class qp_Renderer {
530 - # the stucture of $tag is like this:
531 - # array( "__tag"=>"td", "class"=>"myclass", 0=>"text before li", 1=>array( "__tag"=>"li", 0=>"text inside li" ), 2=>"text after li" )
532 - # both tagged and tagless lists are supported
 1059+ // the stucture of $tag is like this:
 1060+ // array( "__tag"=>"td", "class"=>"myclass", 0=>"text before li", 1=>array( "__tag"=>"li", 0=>"text inside li" ), 2=>"text after li" )
 1061+ // both tagged and tagless lists are supported
5331062 static function renderHTMLobject( &$tag ) {
5341063 $tag_open = "";
5351064 $tag_close = "";
@@ -705,7 +1234,7 @@
7061235 }
7071236 }
7081237 }
709 -} /* end of qp_Renderer class */
 1238+}
7101239
7111240 class qp_FunctionsHook {
7121241
@@ -721,7 +1250,6 @@
7221251 var $error_message = 'no_such_poll';
7231252
7241253 function qpuserchoice( &$parser, $frame, $args ) {
725 - qp_Setup::onLoadAllMessages();
7261254 $this->frame = &$frame;
7271255 $this->args = &$args;
7281256 if ( isset( $args[ 0 ] ) ) {
@@ -803,9 +1331,8 @@
8041332 }
8051333 }
8061334 }
807 - # do not need to wrap the result into qp_Setup::entities()
808 - # because the result is a wikitext (will be escaped by parser)
 1335+ # do not need to use qp_Setup::entities because the result is a wikitext (will be escaped by parser)
8091336 return $result;
8101337 }
8111338
812 -} /* end of qp_FunctionsHook class */
 1339+}
Index: trunk/extensions/QPoll/qp_i18n.php
@@ -0,0 +1,2639 @@
 2+<?php
 3+/**
 4+ * ***** BEGIN LICENSE BLOCK *****
 5+ * This file is part of QPoll.
 6+ * Uses parts of code from Quiz extension (c) 2007 Louis-Rémi BABE. All rights reserved.
 7+ *
 8+ * QPoll is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * QPoll is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License
 19+ * along with QPoll; if not, write to the Free Software
 20+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 21+ *
 22+ * ***** END LICENSE BLOCK *****
 23+ *
 24+ * QPoll is a poll tool for MediaWiki.
 25+ *
 26+ * To activate this extension :
 27+ * * Create a new directory named QPoll into the directory "extensions" of MediaWiki.
 28+ * * Place the files from the extension archive there.
 29+ * * Add this line at the end of your LocalSettings.php file :
 30+ * require_once "$IP/extensions/QPoll/qp_user.php";
 31+ *
 32+ * @file
 33+ * @version 0.7.0
 34+ * @link http://www.mediawiki.org/wiki/Extension:QPoll
 35+ * @author QuestPC <questpc@rambler.ru>
 36+ * @ingroup Extensions
 37+ */
 38+
 39+/**
 40+ * Messages list.
 41+ */
 42+
 43+$messages = array();
 44+
 45+/** English (English)
 46+ * @author QuestPC
 47+ */
 48+$messages['en'] = array(
 49+ 'pollresults' => 'Results of the polls on this site',
 50+ 'qp_parentheses' => '($1)',
 51+ 'qp_full_category_name' => '$1($2)',
 52+ 'qp_desc' => 'Allows creation of polls',
 53+ 'qp_desc-sp' => '[[Special:PollResults|Special page]] for viewing results of the polls',
 54+ 'qp_result_NA' => 'Not answered',
 55+ 'qp_result_error' => 'Syntax error',
 56+ 'qp_vote_button' => 'Vote',
 57+ 'qp_vote_again_button' => 'Change your vote',
 58+ 'qp_polls_list' => 'List all polls',
 59+ 'qp_users_list' => 'List all users',
 60+ 'qp_browse_to_poll' => 'Browse to $1',
 61+ 'qp_browse_to_user' => 'Browse to $1',
 62+ 'qp_votes_count' => '$1 {{PLURAL:$1|vote|votes}}',
 63+ 'qp_source_link' => 'Source',
 64+ 'qp_stats_link' => 'Statistics',
 65+ 'qp_users_link' => 'Users',
 66+ 'qp_voice_link' => 'User voice',
 67+ 'qp_voice_link_inv' => 'User voice?',
 68+ 'qp_user_polls_link' => 'Participated in $1 {{PLURAL:$1|poll|polls}}', // Supports use of GENDER with $2
 69+ 'qp_user_missing_polls_link' => 'No participation', // Supports use of GENDER with $1
 70+ 'qp_not_participated_link' => 'Not participated',
 71+ 'qp_order_by_username' => 'Order by username',
 72+ 'qp_order_by_polls_count' => 'Order by polls count',
 73+ 'qp_results_line_qupl' => 'Page "$1" Poll "$2": $3',
 74+ 'qp_results_line_qpl' => 'Page "$1" Poll "$2": $3, $4, $5, $6',
 75+ 'qp_header_line_qpul' => '$1 [ Page "$2" Poll "$3" ]',
 76+ 'qp_results_line_qpul' => '$1: $2',
 77+ 'qp_header_line_qucl' => '$1. $2<br />$3 ??? $4',
 78+ 'qp_results_line_qucl' => '$1: $2 $3',
 79+ 'qp_export_to_xls' => 'Export statistics into XLS format',
 80+ 'qp_voices_to_xls' => 'Export voices into XLS format',
 81+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|user|users}} answered to the questions',
 82+ 'qp_func_no_such_poll' => 'No such poll ($1)',
 83+ 'qp_func_missing_question_id' => 'Please specify an existing question id (starting from 1) for the poll $1',
 84+ 'qp_func_invalid_question_id' => 'Invalid question id=$2 (not a number) for the poll $1',
 85+ 'qp_func_missing_proposal_id' => 'Please specify an existing proposal id (starting from 0) for the poll $1, question $2',
 86+ 'qp_func_invalid_proposal_id' => 'Invalid proposal id=$3 (not a number) for the poll $1, question $2',
 87+ 'qp_error_no_such_poll' => 'No such poll ($1).
 88+Make sure that the poll declared and saved, also be sure to use address delimiter character #',
 89+ 'qp_error_in_question_header' => 'Invalid question header: $1',
 90+ 'qp_error_id_in_stats_mode' => 'Cannot declare an ID of the poll in statistical mode',
 91+ 'qp_error_dependance_in_stats_mode' => 'Cannot declare dependance chain of the poll in statistical mode',
 92+ 'qp_error_no_stats' => 'No statistical data is available, because no one has voted for this poll, yet (address=$1)',
 93+ 'qp_error_address_in_decl_mode' => 'Cannot get an address of the poll in declaration mode',
 94+ 'qp_error_question_not_implemented' => 'Questions of such type are not implemented: $1',
 95+ 'qp_error_invalid_question_type' => 'Invalid question type: $1',
 96+ 'qp_error_type_in_stats_mode' => 'Question type cannot be defined in statistical display mode: $1',
 97+ 'qp_error_no_poll_id' => 'Poll tag has no id attribute defined.',
 98+ 'qp_error_invalid_poll_id' => 'Invalid poll id (id=$1).
 99+Poll id may contain only letters, numbers and space character',
 100+ 'qp_error_already_used_poll_id' => 'The poll id has already been used on this page (id=$1).',
 101+ 'qp_error_invalid_dependance_value' => 'The poll (id=$1) dependance chain has invalid value of dependance attribute (dependance="$2")',
 102+ 'qp_error_missed_dependance_title' => 'The poll (id=$1) is dependant on the another poll (id=$3) from page [[$2]], but the title [[$2]] was not found.
 103+Either remove the dependance attribute, or restore [[$2]]',
 104+ 'qp_error_missed_dependance_poll' => 'The poll (id=$1) is dependant on the another poll (id=$3) at page $2, but that poll does not exists or has not been saved yet.
 105+Either remove the dependance attribute, or create the poll with id=$3 at the page $2 and save it.
 106+To save a poll, submit it while not answering to any proposal questions.',
 107+ 'qp_error_vote_dependance_poll' => 'Please vote for poll $1 first.',
 108+ 'qp_error_too_many_spans' => 'Too many category groups for the total number of subcategories defined',
 109+ 'qp_error_unanswered_span' => 'Unanswered subcategory',
 110+ 'qp_error_non_unique_choice' => 'This question requires unique proposal answer',
 111+ 'qp_error_category_name_empty' => 'Category name is empty',
 112+ 'qp_error_proposal_text_empty' => 'Proposal text is empty',
 113+ 'qp_error_too_few_categories' => 'At least two categories must be defined',
 114+ 'qp_error_too_few_spans' => 'Every category group must contain at least two subcategories',
 115+ 'qp_error_no_answer' => 'Unanswered proposal',
 116+ 'qp_error_unique' => 'Question of type unique() has more proposals than possible answers defined: impossible to complete'
 117+);
 118+
 119+/** Message documentation (Message documentation)
 120+ * @author Fryed-peach
 121+ * @author Hamilton Abreu
 122+ * @author IAlex
 123+ * @author Purodha
 124+ * @author Siebrand
 125+ */
 126+$messages['qqq'] = array(
 127+ 'pollresults' => 'Special page name in [[Special:SpecialPages]]',
 128+ 'qp_desc' => '{{desc}} Important notice: Categories can be grouped into category groups, which are internally referred as "spans". Such grouped categories become "subcategories". While the extension evolved, these groups were consequentially called as "spans", "metacategories", "category groups". Please read the on-line documentation carefully before translating.',
 129+ 'qp_result_error' => '{{Identical|Syntax error}}',
 130+ 'qp_vote_button' => '{{Identical|Vote}}',
 131+ 'qp_source_link' => '"Source" is the link text for a link to the page where the poll is defined.
 132+{{Identical|Source}}',
 133+ 'qp_stats_link' => '{{Identical|Statistics}}',
 134+ 'qp_users_link' => '{{Identical|User}}',
 135+ 'qp_voice_link_inv' => 'At the moment of query generation there was no user answer for the selected poll yet. Question mark encourages wiki administrator to re-submit the query again.',
 136+ 'qp_user_polls_link' => 'Parameters:
 137+* $1 is the number of polls participated in.
 138+* $2 is the name of the user this message refers to (optional - use for GENDER)',
 139+ 'qp_user_missing_polls_link' => 'Parameters:
 140+* $1 is the name of the user this message refers to (optional - use for GENDER)',
 141+ 'qp_results_line_qupl' => 'Parameters:
 142+* $1 is a link to the page page name the poll is on with the page title as link label
 143+* $2 is the poll name in plain text
 144+* $3 is a link to the poll statistics with link label {{msg-mw|qp_stats_link}}',
 145+ 'qp_results_line_qpl' => 'Parameters:
 146+* $1 is a link to the page page name the poll is on with the page title as link label
 147+* $2 is the poll name in plain text
 148+* $3 is a link to the poll with link label {{msg-mw|qp_source_link}}
 149+* $4 is a link to the poll statistics with link label {{msg-mw|qp_stats_link}}
 150+* $5 is a link to the users that participated in the poll with link label {{msg-mw|qp_users_link}}
 151+* $6 is a link to the with link label {{msg-mw|qp_not_participated_link}}',
 152+ 'qp_error_missed_dependance_poll' => 'Parameters:
 153+* $1 is the poll ID of the poll having an error.
 154+* $2 is a link to the page with the poll, that this erroneous poll depends on.
 155+* $3 is the poll ID of the poll, which this erroneous poll depends on.',
 156+ 'qp_error_too_many_spans' => 'There cannot be more category groups defined than the total count of subcategories.',
 157+ 'qp_error_too_few_spans' => 'Every category group should include at least two subcategories',
 158+);
 159+
 160+/** Afrikaans (Afrikaans)
 161+ * @author Naudefj
 162+ */
 163+$messages['af'] = array(
 164+ 'pollresults' => 'Resultate van die peilings op hierdie webwerf',
 165+ 'qp_desc' => 'Maak dit moontlik om peilings te skep',
 166+ 'qp_desc-sp' => '[[Special:PollResults|Speciale bladsy]] om die resultate van peilings te wys',
 167+ 'qp_result_NA' => 'Nie beantwoord nie',
 168+ 'qp_result_error' => 'Sintaksfout',
 169+ 'qp_vote_button' => 'Stem',
 170+ 'qp_vote_again_button' => 'Verander u stem',
 171+ 'qp_polls_list' => 'Wys alle peilings',
 172+ 'qp_users_list' => 'Lys alle gebruikers',
 173+ 'qp_browse_to_poll' => 'Wys peiling $1',
 174+ 'qp_browse_to_user' => 'Blaai na gebruiker $1',
 175+ 'qp_votes_count' => '$1 {{PLURAL:$1|stem|stemme}}',
 176+ 'qp_source_link' => 'Bron',
 177+ 'qp_stats_link' => 'Statistieke',
 178+ 'qp_users_link' => 'Gebruikers',
 179+ 'qp_voice_link' => 'Gebruikersstem',
 180+ 'qp_voice_link_inv' => 'Gebruikersstem',
 181+ 'qp_user_polls_link' => 'Het aan $1 {{PLURAL:$1|peiling|peilings}} deelgeneem',
 182+ 'qp_user_missing_polls_link' => 'Geen deelname',
 183+ 'qp_not_participated_link' => 'Nie deelgeneem nie',
 184+ 'qp_order_by_username' => 'Sorteer op gebruikersnaam',
 185+ 'qp_order_by_polls_count' => 'Sorteer op aantal peilings',
 186+ 'qp_results_line_qupl' => 'Bladsy "$1", peiling "$2": $3',
 187+ 'qp_results_line_qpl' => 'Bladsy "$1", peiling "$2": $3, $4, $5, $6',
 188+ 'qp_header_line_qpul' => '$1 [ bladsy "$2", peiling "$3" ]',
 189+ 'qp_export_to_xls' => 'Eksporteer statistieke na XLS-formaat',
 190+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|gebruiker|gebruikers}} het die vraag beantwoord',
 191+ 'qp_func_no_such_poll' => 'Die peiling bestaan nie ($1)',
 192+ 'qp_func_missing_question_id' => "Verskaf asseblief 'n vraag-ID (begin by 1) vir die peiling $1",
 193+ 'qp_func_invalid_question_id' => "Ongeldige vraag-ID ($2 - nie 'n getal nie) vir die peiling $1",
 194+ 'qp_func_missing_proposal_id' => "Verskaf asseblief 'n voorstel-ID (begin by 0) vir die peiling $1, vraag $2",
 195+ 'qp_func_invalid_proposal_id' => "Ongeldige voorstel-ID ($3 - nie 'n getal nie) vir die peiling $1, vraag $2",
 196+ 'qp_error_no_such_poll' => 'Die peiling bestaan nie ($1).
 197+Sorg dat die peiling opgestel en gestoor is, en dat "#" as skeidingskarakter in die adres gebruik word.',
 198+ 'qp_error_id_in_stats_mode' => "Dit is nie moontlik om 'n ID vir die peiling in die statistiese modus te verklaar nie",
 199+ 'qp_error_dependance_in_stats_mode' => "Dit is nie moontlik om 'n afhanklikheid-ketting vir die peiling in die statistiese modus te verklaar nie",
 200+ 'qp_error_no_stats' => 'Daar is geen statistiese data beskikbaar nie omdat nog geen gebruikers in hierdie peiling gestem het nie (adres $1)',
 201+ 'qp_error_address_in_decl_mode' => "Dit is nie moontlik om 'n adres van die peiling in die verklaar-modus aan te vra nie.",
 202+ 'qp_error_question_not_implemented' => 'Vrae van die tipe is nie geïmplementeer nie: $1',
 203+ 'qp_error_invalid_question_type' => 'Ongeldige vraagtipe: $1',
 204+ 'qp_error_type_in_stats_mode' => 'Die vraagtipe kan nie in die statistiese vertoon-modus gedefinieer word nie: $1',
 205+ 'qp_error_no_poll_id' => 'Die eienskap "id" is nie vir die peiling gedefinieer nie.',
 206+ 'qp_error_invalid_poll_id' => 'Ongeldig peiling-ID ($1).
 207+Die ID mag slegs letters, syfers en spasies bevat.',
 208+ 'qp_error_already_used_poll_id' => 'Die peilingsnommer word al reeds op hierdie bladsy gebruik (ID $1)',
 209+ 'qp_error_invalid_dependance_value' => 'Die peiling se afhanklikheid-ketting (ID $1) het \'n ongeldige waarde vir die afhanklikheid-eienskap (dependance "$2")',
 210+ 'qp_error_missed_dependance_title' => 'Die peiling (ID $1) is afhanklik van \'n ander peiling (ID $3) op bladsy [[$2]], maar die bladsy [[$2]] bestaan nie.
 211+Verwyder die eienskap "dependance" of plaas die bladsy [[$2]] terug.',
 212+ 'qp_error_missed_dependance_poll' => 'Die peiling (ID $1) is afhanklik van \'n ander peiling (ID $3) op bladsy $2, maar die peiling bestaan nie of is nog nie geskep nie.
 213+Verwyder die eienskap "dependance" of skep \'n peiling met ID $3 op bladsy $2.
 214+Om \'n peiling te stoor, stuur dit sonder dat enig voorstel beantwoord word.',
 215+ 'qp_error_vote_dependance_poll' => 'Stem asseblief eers in die peiling $1.',
 216+ 'qp_error_too_many_spans' => 'Daar is te veel kategorieklasse vir die subkategorieë gedefinieer',
 217+ 'qp_error_unanswered_span' => 'Onbeantwoorde subkategorie',
 218+ 'qp_error_non_unique_choice' => "Hierdie vraag vereis 'n unieke voorstel-antwoord",
 219+ 'qp_error_category_name_empty' => 'Kategorie se naam is leeg',
 220+ 'qp_error_proposal_text_empty' => 'Geen voorstelteks is verskaf nie',
 221+ 'qp_error_too_few_categories' => 'Ten minste twee kategorieë moet gedefinieer word',
 222+ 'qp_error_too_few_spans' => 'Vir elke kategorieklas moet daar ten minste twee moontlike antwoorde gedefinieerd wees',
 223+ 'qp_error_no_answer' => 'Onbeantwoorde voorstel',
 224+ 'qp_error_unique' => 'Vir die vraag van die tipe unique() is daar meer voorstelle as moontlike antwoorde gedefinieer. Dit is nie reg voorberei nie.',
 225+);
 226+
 227+/** Gheg Albanian (Gegë)
 228+ * @author Mdupont
 229+ */
 230+$messages['aln'] = array(
 231+ 'qp_votes_count' => '$1 {{PLURAL:$1|votuar|vota}}',
 232+ 'qp_source_link' => 'Burim',
 233+ 'qp_stats_link' => 'Statistika',
 234+ 'qp_users_link' => 'Përdorues',
 235+ 'qp_voice_link' => 'zëri i përdoruesit',
 236+ 'qp_voice_link_inv' => 'zë User?',
 237+ 'qp_user_polls_link' => 'Marrë pjesë në $1 {{PLURAL:$1|sondazhi|Sondazhet}}',
 238+ 'qp_user_missing_polls_link' => 'Nuk ka pjesëmarrje',
 239+ 'qp_not_participated_link' => 'Nuk ka marrë pjesë',
 240+ 'qp_order_by_username' => 'Rendit nga username',
 241+ 'qp_order_by_polls_count' => 'Rendit nga sondazhet numërimin e',
 242+ 'qp_results_line_qupl' => 'Faqja "$1" Hulumtimi i opinionit publik "$2": $3',
 243+ 'qp_results_line_qpl' => 'Faqja "$1" Hulumtimi i opinionit publik "$2": $3, $4, $5, $6',
 244+ 'qp_header_line_qpul' => '$1 [ Faqja "$2" Hulumtimi i opinionit publik "$3"]',
 245+ 'qp_export_to_xls' => 'Statistikat e eksportit në formatin XLS',
 246+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|përdorues|përdorues}} përgjigjur në pyetjet',
 247+ 'qp_func_no_such_poll' => 'Asnjë sondazh i tillë ($1)',
 248+ 'qp_func_missing_question_id' => 'Ju lutem specifikoni një pyetje id ekzistuese (duke filluar nga 1) për sondazhi i $1',
 249+ 'qp_func_invalid_question_id' => 'pyetje e pavlefshme id = $2 (nuk një numër) për sondazhi i $1',
 250+ 'qp_func_missing_proposal_id' => 'Ju lutem specifikoni një propozim id ekzistuese (duke filluar nga 0) për votimin e pyetjes $1, $2',
 251+ 'qp_func_invalid_proposal_id' => 'propozimin e pavlefshme id = $3 nuk (një numër) për votimin e pyetjes $1, $2',
 252+ 'qp_error_no_such_poll' => 'Asnjë sondazh i tillë ($1). Sigurohuni që sondazhi i deklaruar dhe ruhet, gjithashtu të jetë e sigurtë për të përdorur karakter adresën Kufi #',
 253+ 'qp_error_in_question_header' => 'Fillim i pavlefshëm pyetje: $1',
 254+ 'qp_error_id_in_stats_mode' => 'Nuk mund të deklarojë një ID të anketës në mënyrë statistikore',
 255+ 'qp_error_dependance_in_stats_mode' => 'Nuk mund të deklaroj zinxhir dependance e anketës në mënyrë statistikore',
 256+ 'qp_error_no_stats' => 'Nuk ka të dhëna statistikore është në dispozicion, sepse askush nuk ka votuar për këtë sondazh, por (adresa = $1)',
 257+ 'qp_error_address_in_decl_mode' => 'Nuk mund të merrni një adresë e anketës në deklaratë mode',
 258+ 'qp_error_question_not_implemented' => 'Pyetjet e tipit të tillë nuk janë zbatuar: $1',
 259+ 'qp_error_invalid_question_type' => 'Lloj i pavlefshëm pyetje: $1',
 260+ 'qp_error_type_in_stats_mode' => 'Lloji i Pyetja nuk mund të përcaktohet në mënyrë të shfaqur statistikore: $1',
 261+ 'qp_error_no_poll_id' => 'tag Anketa id ka asnjë atribut të përcaktuar.',
 262+ 'qp_error_invalid_poll_id' => 'Sondazhi id pavlefshme (id = $1). id Anketa mund të përmbajë vetëm shkronja, numra dhe karakterin hapësirë',
 263+ 'qp_error_already_used_poll_id' => 'Id sondazh është tashmë të përdorura në këtë faqe (id = $1).',
 264+ 'qp_error_invalid_dependance_value' => 'Anketa (id = 1 $) zinxhirit të dependance ka vlerë të pavlefshme e vetive dependance (dependance = "$2")',
 265+ 'qp_error_missed_dependance_title' => 'Anketa (id = $1) është i varur nga anketa e një tjetër (id = $3) nga faqja [[$2]], por titullin [[$2]] nuk u gjet.
 266+Ose hequr atribut dependance, ose rivendosjen e [[$2]]',
 267+ 'qp_error_missed_dependance_poll' => 'Anketa (id = $1) është i varur nga anketa e një tjetër (id = $3) në faqe $2, por se sondazhi nuk ekziston ose nuk është ruajtur akoma. Ose hequr atribut dependance, apo krijimi i anketës me id = $3 në faqe $2 dhe për të shpëtuar atë. Për të ruajtur një sondazh, i jepni kohë nuk iu përgjigjur ndonjë pyetje propozim.',
 268+ 'qp_error_vote_dependance_poll' => 'Ju lutemi të votojnë për sondazh $1 të parë.',
 269+ 'qp_error_too_many_spans' => 'Shumë grupe të kategorisë së për numrin e përgjithshëm të nën-kategori të përcaktuara',
 270+ 'qp_error_unanswered_span' => 'nënkategori pa përgjigje',
 271+ 'qp_error_non_unique_choice' => 'Kjo pyetje kërkon përgjigje unike propozim',
 272+ 'qp_error_category_name_empty' => 'Emri Kategoria është e zbrazët',
 273+ 'qp_error_proposal_text_empty' => 'tekstit Propozimi është e zbrazët',
 274+ 'qp_error_too_few_categories' => 'Së paku dy kategori duhet të përcaktohet',
 275+ 'qp_error_too_few_spans' => 'Çdo grup kategori Duhet të përmbajë të paktën dy nën-kategori',
 276+ 'qp_error_no_answer' => 'propozim pa përgjigje',
 277+ 'qp_error_unique' => 'Pyetje të tipit () ka unike propozimet më shumë se përgjigje të mundshme të përcaktuara: e pamundur për të kompletuar',
 278+);
 279+
 280+/** Arabic (العربية)
 281+ * @author Meno25
 282+ * @author OsamaK
 283+ */
 284+$messages['ar'] = array(
 285+ 'pollresults' => 'نتائج الاستقصاءات في هذا الموقع',
 286+ 'qp_desc' => 'يسمح بإنشاء اقتراعات',
 287+ 'qp_desc-sp' => '[[Special:PollResults|صفحة خاصة]] لرؤية نتائج الاقتراعات',
 288+ 'qp_result_NA' => 'غير مجاب عنه',
 289+ 'qp_result_error' => 'خطأ صياغة',
 290+ 'qp_vote_button' => 'تصويت',
 291+ 'qp_vote_again_button' => 'غير صوتك',
 292+ 'qp_polls_list' => 'عرض كل الاقتراعات',
 293+ 'qp_users_list' => 'عرض كل المستخدمين',
 294+ 'qp_browse_to_poll' => 'اذهب إلى $1',
 295+ 'qp_browse_to_user' => 'اذهب إلى $1',
 296+ 'qp_votes_count' => '$1 {{PLURAL:$1|صوت|أصوات}}',
 297+ 'qp_source_link' => 'مصدر',
 298+ 'qp_stats_link' => 'إحصاءات',
 299+ 'qp_users_link' => 'مستخدمون',
 300+ 'qp_voice_link' => 'صوت المستخدم',
 301+ 'qp_voice_link_inv' => 'صوت المستخدم؟',
 302+ 'qp_user_polls_link' => 'شارك في $1 {{PLURAL:$1|اقتراع|اقتراعات}}',
 303+ 'qp_user_missing_polls_link' => 'لا مشاركة',
 304+ 'qp_not_participated_link' => 'لم يشارك',
 305+ 'qp_order_by_username' => 'رتب حسب اسم المستخدم',
 306+ 'qp_order_by_polls_count' => 'رتب حسب عداد الاقتراعات',
 307+ 'qp_results_line_qupl' => 'الصفحة "$1" الاقتراع "$2": $3',
 308+ 'qp_results_line_qpl' => 'الصفحة "$1" الاقتراع "$2": $3, $4, $5, $6',
 309+ 'qp_header_line_qpul' => '$1 [ الصفحة "$2" الاقتراع "$3" ]',
 310+ 'qp_export_to_xls' => 'صدر الإحصاءات بصيغة XLS',
 311+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|مستخدم|مستخدم}} أجاب على الأسئلة',
 312+ 'qp_func_no_such_poll' => 'لا استطلاع كهذا ($1)',
 313+ 'qp_func_missing_question_id' => 'من فضلك حدد رقم سؤال موجود (بدءا من 1) للاقتراع $1',
 314+ 'qp_func_invalid_question_id' => 'سؤال غير صحيح id=$2 (ليس رقما) للاقتراع $1',
 315+ 'qp_func_missing_proposal_id' => 'من فضلك حدد رقم اقتراح موجود (بدءا من 0) للاقتراع $1, السؤال $2',
 316+ 'qp_func_invalid_proposal_id' => 'عرض غير صحيح id=$3 (ليس رقما) للاقتراع $1, السؤال $2',
 317+ 'qp_error_no_such_poll' => 'لا اقتراع كهذا ($1).
 318+تأكد من أن الاقتراع معلن عنه ومحفوظ، وتأكد أيضا من استخدام حرف فصل العنوان #',
 319+ 'qp_error_id_in_stats_mode' => 'لا يمكن إعلان رقم للاقتراع في نمط الإحصاءات',
 320+ 'qp_error_dependance_in_stats_mode' => 'لا يمكن الإعلان عن سلسلة اعتماد الاقتراع في نمط الإحصاءات',
 321+ 'qp_error_no_stats' => 'لا بيانات إحصائية متوفرة، لأنه لا أحد صوت في هذا الاقتراع بعد (address=$1)',
 322+ 'qp_error_address_in_decl_mode' => 'لا يمكن الحصول على عنوان في نمط الإعلان',
 323+ 'qp_error_question_not_implemented' => 'الأسئلة من هذا النوع غير مطبقة: $1',
 324+ 'qp_error_invalid_question_type' => 'نوع سؤال غير صالح: $1',
 325+ 'qp_error_type_in_stats_mode' => 'نوع السؤال لا يمكن تعريفه في نمط العرض الإحصائي: $1',
 326+ 'qp_error_no_poll_id' => 'وسم الاقتراع ليس به معرف رقم محدد.',
 327+ 'qp_error_invalid_poll_id' => 'رقم اقتراع غير صحيح (id=$1).
 328+رقم الاقتراع يمكن ان يحتوي فقط على حروف، أرقام وحرف الفراغ',
 329+ 'qp_error_already_used_poll_id' => 'رقم الاقتراع تم استخدامه بالفعل في هذه الصفحة (id=$1).',
 330+ 'qp_error_invalid_dependance_value' => 'سلسة اعتماد الاقتراع (id=$1) بها قيمة غير صحيحة لمحدد الاعتماد (dependance="$2")',
 331+ 'qp_error_missed_dependance_title' => 'الاقتراع (id=$1) معتمد على اقتراع آخر (id=$3) من الصفحة [[$2]]، لكن العنوان [[$2]] لم يتم العثور عليه.
 332+إما أن تزيل محدد الاعتماد، أو تسترجع [[$2]]',
 333+ 'qp_error_missed_dependance_poll' => 'الاقتراع (id=$1) معتمد على اقتراع آخر (id=$3) في الصفحة $2، لكن هذا الاقتراع غير موجود أو لم يتم حفظه بعد.
 334+إما أن تزيل محدد الاعتماد، أو تنشئ الاقتراع بالرقم id=$3 في الصفحة $2 وتحفظه.
 335+لحفظ اقتراع، نفذه مع عدم الإجابة على أي أسئلة مطروحة.',
 336+ 'qp_error_vote_dependance_poll' => 'من فضلك صوت للاقتراع $1 أولا.',
 337+ 'qp_error_too_many_spans' => 'عدد كبير من مجموعات التصنيفات للعدد الإجمالي المعرف من التصنيفات الفرعية',
 338+ 'qp_error_unanswered_span' => 'تصنيف فرعي غير مجاب عليه',
 339+ 'qp_error_non_unique_choice' => 'يجب أن يتوفر للسؤال إجابة مُقترحة فريدة',
 340+ 'qp_error_category_name_empty' => 'اسم التصنيف فارغ',
 341+ 'qp_error_proposal_text_empty' => 'نص الاقتراح فارغ',
 342+ 'qp_error_too_few_categories' => 'يجب أن تُعرّف تصنيفين على الأقل',
 343+ 'qp_error_too_few_spans' => 'كل مجموعة تصنيف يجب أن تحتوي على الأقل على تصنيفين فرعيين',
 344+ 'qp_error_no_answer' => 'اقتراح غير مجاب عليه',
 345+ 'qp_error_unique' => 'السؤال من نوع unique() لديه اقتراحات أكثر من الأجوبة المحتملة المعرفة: مستحيل الإكمال',
 346+);
 347+
 348+/** Aramaic (ܐܪܡܝܐ)
 349+ * @author 334a
 350+ * @author Basharh
 351+ * @author Michaelovic
 352+ */
 353+$messages['arc'] = array(
 354+ 'qp_vote_button' => 'ܝܗܒ ܩܠܐ',
 355+ 'qp_users_list' => 'ܚܘܝ ܟܠ ܡܦܠܚܢ̈ܐ',
 356+ 'qp_browse_to_poll' => 'ܙܠ ܠ $1',
 357+ 'qp_browse_to_user' => 'ܙܠ ܠ $1',
 358+ 'qp_votes_count' => '$1 {{PLURAL:$1|ܩܠܐ|ܩܠ̈ܐ}}',
 359+ 'qp_source_link' => 'ܡܒܘܥܐ',
 360+ 'qp_users_link' => 'ܡܦܠܚܢ̈ܐ',
 361+ 'qp_voice_link' => 'ܩܠܐ ܕܡܦܠܚܢܐ',
 362+ 'qp_voice_link_inv' => 'ܡܦܠܚܢܐ ܝܗܒ ܩܠܐ؟',
 363+ 'qp_error_category_name_empty' => 'ܫܡܐ ܕܣܕܪܐ ܣܦܝܩܐ ܗܘ',
 364+);
 365+
 366+/** Egyptian Spoken Arabic (مصرى)
 367+ * @author Meno25
 368+ */
 369+$messages['arz'] = array(
 370+ 'pollresults' => 'نتائج الاستقصاءات فى هذا الموقع',
 371+ 'qp_desc' => 'يسمح بإنشاء اقتراعات',
 372+ 'qp_desc-sp' => '[[Special:PollResults|صفحه خاصة]] لرؤيه نتائج الاقتراعات',
 373+ 'qp_result_NA' => 'غير مجاب عنه',
 374+ 'qp_result_error' => 'خطأ صياغة',
 375+ 'qp_vote_button' => 'تصويت',
 376+ 'qp_vote_again_button' => 'غير صوتك',
 377+ 'qp_polls_list' => 'عرض كل الاقتراعات',
 378+ 'qp_users_list' => 'عرض كل المستخدمين',
 379+ 'qp_browse_to_poll' => 'اذهب إلى $1',
 380+ 'qp_browse_to_user' => 'اذهب إلى $1',
 381+ 'qp_votes_count' => '$1 {{PLURAL:$1|صوت|أصوات}}',
 382+ 'qp_source_link' => 'مصدر',
 383+ 'qp_stats_link' => 'إحصاءات',
 384+ 'qp_users_link' => 'مستخدمون',
 385+ 'qp_voice_link' => 'صوت المستخدم',
 386+ 'qp_voice_link_inv' => 'صوت المستخدم؟',
 387+ 'qp_user_polls_link' => 'شارك فى $1 {{PLURAL:$1|اقتراع|اقتراعات}}',
 388+ 'qp_user_missing_polls_link' => 'لا مشاركة',
 389+ 'qp_not_participated_link' => 'لم يشارك',
 390+ 'qp_order_by_username' => 'رتب حسب اسم المستخدم',
 391+ 'qp_order_by_polls_count' => 'رتب حسب عداد الاقتراعات',
 392+ 'qp_results_line_qupl' => 'الصفحه "$1" الاقتراع "$2": $3',
 393+ 'qp_results_line_qpl' => 'الصفحه "$1" الاقتراع "$2": $3, $4, $5, $6',
 394+ 'qp_header_line_qpul' => '$1 [ الصفحه "$2" الاقتراع "$3" ]',
 395+ 'qp_export_to_xls' => 'صدر الإحصاءات بصيغه XLS',
 396+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|مستخدم|مستخدم}} أجاب على الأسئلة',
 397+ 'qp_func_no_such_poll' => 'لا استطلاع كهذا ($1)',
 398+ 'qp_func_missing_question_id' => 'من فضلك حدد رقم سؤال موجود (بدءا من 1) للاقتراع $1',
 399+ 'qp_func_invalid_question_id' => 'سؤال غير صحيح id=$2 (ليس رقما) للاقتراع $1',
 400+ 'qp_func_missing_proposal_id' => 'من فضلك حدد رقم اقتراح موجود (بدءا من 0) للاقتراع $1, السؤال $2',
 401+ 'qp_func_invalid_proposal_id' => 'عرض غير صحيح id=$3 (ليس رقما) للاقتراع $1, السؤال $2',
 402+ 'qp_error_no_such_poll' => 'لا اقتراع كهذا ($1).
 403+تأكد من أن الاقتراع معلن عنه ومحفوظ، وتأكد أيضا من استخدام حرف فصل العنوان #',
 404+ 'qp_error_id_in_stats_mode' => 'لا يمكن إعلان رقم للاقتراع فى نمط الإحصاءات',
 405+ 'qp_error_dependance_in_stats_mode' => 'لا يمكن الإعلان عن سلسله اعتماد الاقتراع فى نمط الإحصاءات',
 406+ 'qp_error_no_stats' => 'لا بيانات إحصائيه متوفره، لأنه لا أحد صوت فى هذا الاقتراع بعد (address=$1)',
 407+ 'qp_error_address_in_decl_mode' => 'لا يمكن الحصول على عنوان فى نمط الإعلان',
 408+ 'qp_error_question_not_implemented' => 'الأسئله من هذا النوع غير مطبقة: $1',
 409+ 'qp_error_invalid_question_type' => 'نوع سؤال غير صالح: $1',
 410+ 'qp_error_type_in_stats_mode' => 'نوع السؤال لا يمكن تعريفه فى نمط العرض الإحصائي: $1',
 411+ 'qp_error_no_poll_id' => 'وسم الاقتراع ليس به معرف رقم محدد.',
 412+ 'qp_error_invalid_poll_id' => 'رقم اقتراع غير صحيح (id=$1).
 413+رقم الاقتراع يمكن ان يحتوى فقط على حروف، أرقام وحرف الفراغ',
 414+ 'qp_error_already_used_poll_id' => 'رقم الاقتراع تم استخدامه بالفعل فى هذه الصفحه (id=$1).',
 415+ 'qp_error_invalid_dependance_value' => 'سلسه اعتماد الاقتراع (id=$1) بها قيمه غير صحيحه لمحدد الاعتماد (dependance="$2")',
 416+ 'qp_error_missed_dependance_title' => 'الاقتراع (id=$1) معتمد على اقتراع آخر (id=$3) من الصفحه [[$2]]، لكن العنوان [[$2]] لم يتم العثور عليه.
 417+إما أن تزيل محدد الاعتماد، أو تسترجع [[$2]]',
 418+ 'qp_error_missed_dependance_poll' => 'الاقتراع (id=$1) معتمد على اقتراع آخر (id=$3) فى الصفحه $2، لكن هذا الاقتراع غير موجود أو لم يتم حفظه بعد.
 419+إما أن تزيل محدد الاعتماد، أو تنشئ الاقتراع بالرقم id=$3 فى الصفحه $2 وتحفظه.
 420+لحفظ اقتراع، نفذه مع عدم الإجابه على أى أسئله مطروحه.',
 421+ 'qp_error_vote_dependance_poll' => 'من فضلك صوت للاقتراع $1 أولا.',
 422+ 'qp_error_too_many_spans' => 'عدد كبير من مجموعات التصنيفات للعدد الإجمالى المعرف من التصنيفات الفرعية',
 423+ 'qp_error_unanswered_span' => 'تصنيف فرعى غير مجاب عليه',
 424+ 'qp_error_non_unique_choice' => 'يجب أن يتوفر للسؤال إجابه مُقترحه فريدة',
 425+ 'qp_error_category_name_empty' => 'اسم التصنيف فارغ',
 426+ 'qp_error_proposal_text_empty' => 'نص الاقتراح فارغ',
 427+ 'qp_error_too_few_categories' => 'يجب أن تُعرّف تصنيفين على الأقل',
 428+ 'qp_error_too_few_spans' => 'كل مجموعه تصنيف يجب أن تحتوى على الأقل على تصنيفين فرعيين',
 429+ 'qp_error_no_answer' => 'اقتراح غير مجاب عليه',
 430+ 'qp_error_unique' => 'السؤال من نوع unique() لديه اقتراحات أكثر من الأجوبه المحتمله المعرفة: مستحيل الإكمال',
 431+);
 432+
 433+/** Azerbaijani (Azərbaycanca)
 434+ * @author Cekli829
 435+ */
 436+$messages['az'] = array(
 437+ 'qp_users_link' => 'İstifadəçilər',
 438+);
 439+
 440+/** Belarusian (Беларуская)
 441+ * @author Тест
 442+ */
 443+$messages['be'] = array(
 444+ 'qp_stats_link' => 'Статыстыка',
 445+);
 446+
 447+/** Belarusian (Taraškievica orthography) (‪Беларуская (тарашкевіца)‬)
 448+ * @author EugeneZelenko
 449+ * @author Jim-by
 450+ */
 451+$messages['be-tarask'] = array(
 452+ 'pollresults' => 'Вынікі апытаньняў на гэтым сайце',
 453+ 'qp_desc' => 'Дазваляе стварэньне апытаньняў',
 454+ 'qp_desc-sp' => '[[Special:PollResults|Спэцыяльная старонка]] для прагляду вынікаў апытаньняў',
 455+ 'qp_result_NA' => 'Няма адказу',
 456+ 'qp_result_error' => 'Сынтаксычная памылка',
 457+ 'qp_vote_button' => 'Прагаласаваць',
 458+ 'qp_vote_again_button' => 'Зьмяніць Ваш голас',
 459+ 'qp_polls_list' => 'Сьпіс усіх апытаньняў',
 460+ 'qp_users_list' => 'Сьпіс усіх удзельнікаў',
 461+ 'qp_browse_to_poll' => 'Перайсьці да $1',
 462+ 'qp_browse_to_user' => 'Перайсьці да $1',
 463+ 'qp_votes_count' => '$1 {{PLURAL:$1|голас|галасы|галасоў}}',
 464+ 'qp_source_link' => 'Крыніца',
 465+ 'qp_stats_link' => 'Статыстыка',
 466+ 'qp_users_link' => 'Удзельнікі',
 467+ 'qp_voice_link' => 'Голас удзельніка',
 468+ 'qp_voice_link_inv' => 'Голас удзельніка?',
 469+ 'qp_user_polls_link' => '{{GENDER:$2|Удзельнічаў|Удзельнічала}} у $1 {{PLURAL:$1|апытаньні|апытаньнях|апытаньнях}}',
 470+ 'qp_user_missing_polls_link' => 'Не {{GENDER:$1|ўдзельнічаў|ўдзельнічала}}',
 471+ 'qp_not_participated_link' => 'Сьпіс не прыняўшых удзел',
 472+ 'qp_order_by_username' => 'Сартаваць па імені ўдзельніка',
 473+ 'qp_order_by_polls_count' => 'Сартаваць па колькасьці апытаньняў',
 474+ 'qp_results_line_qupl' => 'Старонка «$1» Апытаньне «$2»: $3',
 475+ 'qp_results_line_qpl' => 'Старонка «$1» Апытаньне «$2»: $3, $4, $5, $6',
 476+ 'qp_header_line_qpul' => '$1 [ Старонка «$2» Апытаньне «$3» ]',
 477+ 'qp_export_to_xls' => 'Экспартаваць статыстыку ў фармат XLS',
 478+ 'qp_voices_to_xls' => 'Экспартаваць галасы ў фармат XLS',
 479+ 'qp_users_answered_questions' => 'На пытаньні {{PLURAL:$1|адказаў $1 удзельнік|адказалі $1 удзельнікі|адказалі $1 удзельнікаў}}',
 480+ 'qp_func_no_such_poll' => 'Няма такога апытаньня ($1)',
 481+ 'qp_func_missing_question_id' => 'Калі ласка, пазначце ідэнтыфікатар існуючага пытаньня (пачынаючы з 1) для апытаньня $1',
 482+ 'qp_func_invalid_question_id' => 'Няслушны ідэнтыфікатар апытаньня=$2 (ня лік) для апытаньня $1',
 483+ 'qp_func_missing_proposal_id' => 'Калі ласка, пазначце існуючы ідэнтыфікатар (пачынаючы з 0) для апытаньня $1, пытаньня $2',
 484+ 'qp_func_invalid_proposal_id' => 'Няслушны ідэнтыфікатар=$3 (ня лік) для апытаньня $1, пытаньня $2',
 485+ 'qp_error_no_such_poll' => 'Няма такога апытаньня ($1).
 486+Упэўніцеся што апытаньне вызначанае і захаванае, а таксама, што выкарыстоўваецца сымбаль падзелу адрасу #',
 487+ 'qp_error_in_question_header' => 'Няслушны загаловак пытаньня: $1',
 488+ 'qp_error_id_in_stats_mode' => 'Немагчыма вызначаць ідэнтыфікатар апытаньня ў статыстычным рэжыме',
 489+ 'qp_error_dependance_in_stats_mode' => 'Немагчыма вызначаць залежную пасьлядоўнасьць апытаньня ў статыстычным рэжыме',
 490+ 'qp_error_no_stats' => 'Няма статыстычных зьвестак, таму што ніхто яшчэ не падаў голас у гэтым апытаньні (адрас=$1)',
 491+ 'qp_error_address_in_decl_mode' => 'Немагчыма атрымаць адрас апытаньня ў рэжыме вызначэньня',
 492+ 'qp_error_question_not_implemented' => 'Пытаньні гэтага тыпу не рэалізаваныя: $1',
 493+ 'qp_error_invalid_question_type' => 'Няслушны тып пытаньня: $1',
 494+ 'qp_error_type_in_stats_mode' => 'Немагчыма вызначыць тып пытаньня ў статыстычным рэжыме: $1',
 495+ 'qp_error_no_poll_id' => 'Тэг апытаньня ня мае атрыбута ідэнтыфікацыі.',
 496+ 'qp_error_invalid_poll_id' => 'Няслушны ідэнтыфікатар апытаньня (id=$1).
 497+Ідэнтыфікатар апытаньня можа ўтрымліваць толькі літары, лічбы і сымбаль прагалу',
 498+ 'qp_error_already_used_poll_id' => 'Ідэнтыфікатар апытаньня ўжо быў выкарыстаны на гэтай старонцы (id=$1).',
 499+ 'qp_error_invalid_dependance_value' => 'У ланцугу залежнасьці апытаньня (id=$1) існуе няслушнае значэньне атрыбуту залежнасьці (dependance="$2")',
 500+ 'qp_error_missed_dependance_title' => 'Апытаньне (id=$1) залежыць ад іншага апытаньня (id=$3) са старонкі [[$2]], але назва [[$2]] не была знойдзеная.
 501+Неабходна выдаліць атрыбут залежнасьці ці аднавіць [[$2]]',
 502+ 'qp_error_missed_dependance_poll' => 'Апытаньне (id=$1) залежыць ад іншага апытаньня (id=$3) на старонцы $2, але гэта апытаньне не існуе ці яшчэ не было захаванае.
 503+Неабходна выдаліць атрыбут залежнасьці альбо стварыць апытаньне з ідэнтыфікатарам id=$3 на старонцы $2 і яго захаваць. Каб захаваць апытаньне можна націснуць кнопку «Прагаласаваць», не адказваючы на пытаньні.',
 504+ 'qp_error_vote_dependance_poll' => 'Калі ласка, спачатку прыміце ўдзел у апытаньні $1.',
 505+ 'qp_error_too_many_spans' => 'Вызначана зашмат клясаў катэгорыяў для падкатэгорыяў',
 506+ 'qp_error_unanswered_span' => 'Падкатэгорыя без адказу',
 507+ 'qp_error_non_unique_choice' => 'Гэта пытаньне патрабуе, каб варыянт адказу не выкарыстоўваўся раней',
 508+ 'qp_error_category_name_empty' => 'Пустая назва катэгорыі',
 509+ 'qp_error_proposal_text_empty' => 'Прапанаваны тэкст — пусты',
 510+ 'qp_error_too_few_categories' => 'Павінны быць вызначаныя хаця б дзьве катэгорыі',
 511+ 'qp_error_too_few_spans' => 'Кожная кляса катэгорыі патрабуе хаця б два варыянты адказу',
 512+ 'qp_error_no_answer' => 'Няма адказу на пытаньне',
 513+ 'qp_error_unique' => 'Пытаньне тыпу unique() мае больш адказаў чым гэта магчыма: немагчыма скончыць',
 514+);
 515+
 516+/** Bengali (বাংলা)
 517+ * @author Wikitanvir
 518+ */
 519+$messages['bn'] = array(
 520+ 'qp_vote_button' => 'ভোট',
 521+ 'qp_vote_again_button' => 'আপনার ভোট পরিবর্তন করুন',
 522+ 'qp_polls_list' => 'সকল নির্বাচন তালিকাভুক্ত করো',
 523+ 'qp_source_link' => 'উৎস',
 524+ 'qp_stats_link' => 'পরিসংখ্যান',
 525+ 'qp_users_link' => 'ব্যবহারকারীগণ',
 526+ 'qp_voice_link' => 'ব্যবহারকারীর কণ্ঠ',
 527+);
 528+
 529+/** Breton (Brezhoneg)
 530+ * @author Fohanno
 531+ * @author Fulup
 532+ * @author Y-M D
 533+ */
 534+$messages['br'] = array(
 535+ 'pollresults' => "Disoc'hoù ar sontadegoù el lec'hienn-mañ",
 536+ 'qp_desc' => 'Aotren krouiñ sontadegoù',
 537+ 'qp_desc-sp' => "[[Special:PollResults|Pajenn ispisial]] evit sellet ouzh disoc'hoù ar sontadegoù",
 538+ 'qp_result_NA' => 'Direspont',
 539+ 'qp_result_error' => 'Fazi ereadur',
 540+ 'qp_vote_button' => 'Mouezhiañ',
 541+ 'qp_vote_again_button' => 'Distreiñ war ho vot',
 542+ 'qp_polls_list' => 'Rollañ an holl sontadegoù',
 543+ 'qp_users_list' => 'Renabliñ an holl implijerien',
 544+ 'qp_browse_to_poll' => 'Mont betek $1',
 545+ 'qp_browse_to_user' => 'Mont betek $1',
 546+ 'qp_votes_count' => '$1 {{PLURAL:$1|vot|vot}}',
 547+ 'qp_source_link' => 'Mammenn',
 548+ 'qp_stats_link' => 'Stadegoù',
 549+ 'qp_users_link' => 'Implijerien',
 550+ 'qp_voice_link' => 'Mouezh an implijer',
 551+ 'qp_voice_link_inv' => 'Mouezh an implijer ?',
 552+ 'qp_user_polls_link' => 'En deus kemeret perzh e $1 sontadeg{{PLURAL:$1||}}',
 553+ 'qp_user_missing_polls_link' => 'Ne gemer ket perzh',
 554+ 'qp_not_participated_link' => "N'en deus ket kemeret perzh",
 555+ 'qp_order_by_username' => 'Urzhiañ dre anv implijer',
 556+ 'qp_order_by_polls_count' => 'Urzhiañ dre an niver a sontadegoù',
 557+ 'qp_results_line_qupl' => 'Pajenn "$1" Sontadeg "$2" : $3',
 558+ 'qp_results_line_qpl' => 'Pajenn "$1" Sontadeg "$2" : $3, $4, $5, $6',
 559+ 'qp_header_line_qpul' => '$1 [ Pajenn "$2" Votadeg "$3" ]',
 560+ 'qp_export_to_xls' => "Ezporzhiañ ar stadegoù d'ar furmad XLS",
 561+ 'qp_voices_to_xls' => "Ezporzhiañ ar votoù d'ar furmad XLS",
 562+ 'qp_users_answered_questions' => "$1 {{PLURAL:$1|implijer|implijer}} o deus respontet d'ar goulennoù",
 563+ 'qp_func_no_such_poll' => "N'eus ket eus ar votadeg-mañ ($1)",
 564+ 'qp_func_missing_question_id' => "Spisait un ID evit ur goulenn zo anezhañ c'hoazh (adalek 1) evit ar sontadeg $1",
 565+ 'qp_func_invalid_question_id' => 'Id direizh evit ar goulenn=$2 direizh (ket un niver) evit ar sontadeg $1',
 566+ 'qp_func_missing_proposal_id' => "Spisait un ID kinnig zo anezhañ c'hoazh (adalek 0) evit ar sontadeg $1, goulenn $2",
 567+ 'qp_func_invalid_proposal_id' => 'Id kinnig=$3 direizh (ket un niver) evit ar sontadeg $1, goulenn $2',
 568+ 'qp_error_no_such_poll' => "N'eus ket eus ar sontadeg ($1).
 569+Bezit sur eo bet disklêriet hag enrollet ar sontadeg ha na zisoñjit ket ober gant an arouezenn bevenniñ chomlec'hioù #",
 570+ 'qp_error_in_question_header' => 'Talbenn goulenn direizh : $1',
 571+ 'qp_error_id_in_stats_mode' => 'Dibosupl eo diskleriañ un ID eus ar sontadeg er mod stadegoù',
 572+ 'qp_error_dependance_in_stats_mode' => "Dibosupl eo diskleriañ ar chadenn amzalc'h d'ar sontadeg er mod stadegoù",
 573+ 'qp_error_no_stats' => "N'eus ket a roadennoù stadegel rak den ebet n'en deus respontet d'ar sontadeg evit c'hoazh (chomlec'h=$1)",
 574+ 'qp_error_address_in_decl_mode' => "N'haller ket tapout ur chomlec'h eus ar sontadeg er mod disklêriañ",
 575+ 'qp_error_question_not_implemented' => "N'eo ket emplementet ar goulennoù a-seurt gant $1",
 576+ 'qp_error_invalid_question_type' => 'Seurt goulenn direizh : $1',
 577+ 'qp_error_type_in_stats_mode' => "N'haller ket termeniñ doare ar goulennoù er mod diskwel stadegoù : $1",
 578+ 'qp_error_no_poll_id' => "N'eus ket a niverenn-anout termenet gant balizenn ar sontadeg.",
 579+ 'qp_error_invalid_poll_id' => "Direizh eo an niverenn-anaout (id=$1).
 580+N'hall bezañ en niverenn-anaout nemet lizherennoù, niverennoù hag an arouezenn esaouenn",
 581+ 'qp_error_already_used_poll_id' => 'Implijet eo bet choazh an niverenn-anaout sontadeg war ar bajenn (id=$1).',
 582+ 'qp_error_invalid_dependance_value' => 'Direizh eo talvoudenn chadennad amzalc\'h ar sontadeg (id=$1) evit an atribut amzalc\'h (amzalc\'h="$2")',
 583+ 'qp_error_missed_dependance_title' => "E dalc'h ur sontadeg all (id=$3) eus ar bajenn [[$2]] emañ ar sontadeg (i=$1), met an titl [[$2]] n'eo ket bet kavet.
 584+Diverkit an atribut amzalc'h pe assavit [[$2]]",
 585+ 'qp_error_missed_dependance_poll' => "Dindan dalc'h ur sontadeg all (id=$3) war pajenn $2 emañ ar sontadeg (id=$1), met n'eus ket eus ar sontadeg-se pe n'eo ket bet enrollet c'hoazh.
 586+Tennit an atribut amzalc'h pe krouit ar sontadeg $3 war ar bajenn $2 hag enrollit anezhi.
 587+Evit enrollañ ur sontadeg, kasit anezhi ha na respontit da goulenn kinnig ebet.",
 588+ 'qp_error_vote_dependance_poll' => 'Mar plij, votit evit ar sontadeg $1 da gentañ.',
 589+ 'qp_error_too_many_spans' => 'Re a strolladoù rummadoù evit an niver hollek a isrummadoù termenet',
 590+ 'qp_error_unanswered_span' => 'Is-rummad hep respont',
 591+ 'qp_error_non_unique_choice' => 'Ar goulenn-mañ he deus ezhomm ur respont gant un dibab hepken',
 592+ 'qp_error_category_name_empty' => 'Goullo eo anv ar rummad',
 593+ 'qp_error_proposal_text_empty' => "Goullo eo testenn ar c'hinnig",
 594+ 'qp_error_too_few_categories' => 'Daou rummad da nebeutañ a rank bezañ termenet',
 595+ 'qp_error_too_few_spans' => 'Pep strollad rummad a rank bezañ ennañ daou isrummad da nebeutañ',
 596+ 'qp_error_no_answer' => 'Kinnig direspont',
 597+ 'qp_error_unique' => 'Re a ginnigoù zo evit ar goulenn seurt nemetañ () eget an niver a respontoù posupl termenet : dibosupl eo klokaat',
 598+);
 599+
 600+/** Bosnian (Bosanski)
 601+ * @author CERminator
 602+ */
 603+$messages['bs'] = array(
 604+ 'pollresults' => 'Rezultati glasanja na ovoj stranici',
 605+ 'qp_desc' => 'Omogućuje pravljenje glasanja',
 606+ 'qp_desc-sp' => '[[Special:PollResults|Posebna stranica]] za pregled rezultata glasanja',
 607+ 'qp_result_NA' => 'Nije odgovoreno',
 608+ 'qp_result_error' => 'Sintaksna greška',
 609+ 'qp_vote_button' => 'Glasaj',
 610+ 'qp_vote_again_button' => 'Promijeni svoj glas',
 611+ 'qp_polls_list' => 'Prikaži sva glasanja',
 612+ 'qp_users_list' => 'Prikaži sve korisnike',
 613+ 'qp_browse_to_poll' => 'Pregledaj po $1',
 614+ 'qp_browse_to_user' => 'Pregledaj po $1',
 615+ 'qp_votes_count' => '$1 {{PLURAL:$1|glas|glasa|glasova}}',
 616+ 'qp_source_link' => 'Izvor',
 617+ 'qp_stats_link' => 'Statistika',
 618+ 'qp_users_link' => 'Korisnici',
 619+ 'qp_voice_link' => 'Korisnički glas',
 620+ 'qp_voice_link_inv' => 'Korisnički glas?',
 621+ 'qp_user_polls_link' => 'Učestvovao u $1 {{PLURAL:$1|glasanju|glasanja}}',
 622+ 'qp_user_missing_polls_link' => 'Bez učešća',
 623+ 'qp_not_participated_link' => 'Nije učestvovao',
 624+ 'qp_order_by_username' => 'Pregled po korisničkim imenima',
 625+ 'qp_order_by_polls_count' => 'Pregled po broju glasova',
 626+ 'qp_results_line_qupl' => 'Stranica "$1" Anketa "$2": $3',
 627+ 'qp_results_line_qpl' => 'Stranica "$1" Anketa "$2": $3, $4, $5, $6',
 628+ 'qp_header_line_qpul' => '$1 [ Stranica "$2" Anketa "$3" ]',
 629+ 'qp_func_no_such_poll' => 'Nema takve ankete ($1)',
 630+);
 631+
 632+/** Czech (Česky) */
 633+$messages['cs'] = array(
 634+ 'qp_source_link' => 'Zdroj',
 635+ 'qp_stats_link' => 'Statistika',
 636+ 'qp_users_link' => 'Uživatelé',
 637+);
 638+
 639+/** German (Deutsch)
 640+ * @author Imre
 641+ * @author Kghbln
 642+ * @author The Evil IP address
 643+ */
 644+$messages['de'] = array(
 645+ 'pollresults' => 'Abstimmungsergebnisse auf dieser Seite',
 646+ 'qp_desc' => 'Ermöglicht die Erstellung von Abstimmungen',
 647+ 'qp_desc-sp' => '[[Special:PollResults|Spezialseite]] zum Anzeigen von Abstimmungsergebnissen',
 648+ 'qp_result_NA' => 'Nicht beantwortet',
 649+ 'qp_result_error' => 'Syntaxfehler',
 650+ 'qp_vote_button' => 'Abstimmen',
 651+ 'qp_vote_again_button' => 'Stimme ändern',
 652+ 'qp_polls_list' => 'Alle Abstimmungen auflisten',
 653+ 'qp_users_list' => 'Alle Benutzer anzeigen',
 654+ 'qp_browse_to_poll' => 'Nach $1 wechseln',
 655+ 'qp_browse_to_user' => 'Nach $1 wechseln',
 656+ 'qp_votes_count' => '$1 {{PLURAL:$1|Stimme|Stimmen}}',
 657+ 'qp_source_link' => 'Quelle',
 658+ 'qp_stats_link' => 'Statistik',
 659+ 'qp_users_link' => 'Benutzer',
 660+ 'qp_voice_link' => 'Benutzerstimme',
 661+ 'qp_voice_link_inv' => 'Benutzerstimme?',
 662+ 'qp_user_polls_link' => 'Hat an $1 {{PLURAL:$1|Abstimmung|Abstimmungen}} teilgenommen',
 663+ 'qp_user_missing_polls_link' => 'Keine Teilnahme',
 664+ 'qp_not_participated_link' => 'Nicht teilgenommen',
 665+ 'qp_order_by_username' => 'Nach Benutzernamen ordnen',
 666+ 'qp_order_by_polls_count' => 'Nach Abstimmungszahl ordnen',
 667+ 'qp_results_line_qupl' => 'Seite „$1“ Abstimmung „$2“: $3',
 668+ 'qp_results_line_qpl' => 'Seite „$1“ Abstimmung „$2“: $3, $4, $5, $6',
 669+ 'qp_header_line_qpul' => '$1 [ Seite „$2“ Abstimmung „$3“ ]',
 670+ 'qp_export_to_xls' => 'Statistiken in das XLS-Format exportieren',
 671+ 'qp_voices_to_xls' => 'Stimmen im XLS-Format exportieren',
 672+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|Benutzer|Benutzer}} haben auf die Fragen geantwortet',
 673+ 'qp_func_no_such_poll' => 'Abstimmung nicht vorhanden ($1)',
 674+ 'qp_func_missing_question_id' => 'Bitte lege eine existierende Frage-ID (ab 1 aufwärts) für die Abstimmung $1 fest',
 675+ 'qp_func_invalid_question_id' => 'Ungültige Frage ID=$2 (keine Nummer) für die Abstimmung $1',
 676+ 'qp_func_missing_proposal_id' => 'Bitte lege eine existierende Vorschlagskennung für die Abstimmung $1 fest (ab 0 aufwärts), Frage $2.',
 677+ 'qp_func_invalid_proposal_id' => 'Ungültige Vorschlagskennung id=$3 (keine Nummer) für die Abstimmung $1, Frage $2',
 678+ 'qp_error_no_such_poll' => 'Abstimmung nicht vorhanden ($1).
 679+Stelle sicher, dass die Abstimmung festgelegt und gespeichert ist und dass # als Trennsymbol für Adressen verwendet wird',
 680+ 'qp_error_in_question_header' => 'Ungültige Bezeichnung: $1',
 681+ 'qp_error_id_in_stats_mode' => 'Kann keine Kennung für diese Abstimmung im Statistik-Modus festlegen.',
 682+ 'qp_error_dependance_in_stats_mode' => 'Kann Abhängigkeitskette der Abstimmung im statistischen Modus nicht festlegen',
 683+ 'qp_error_no_stats' => 'Es sind keine statistischen Daten verfügbar, da noch niemand für diese Abstimmung gestimmt hat (Adresse=$1)',
 684+ 'qp_error_address_in_decl_mode' => 'Kann keine Adresse der Abstimmung im Festlegungs-Modus ermitteln',
 685+ 'qp_error_question_not_implemented' => 'Fragen diesen Typs sind nicht implementiert: $1',
 686+ 'qp_error_invalid_question_type' => 'Ungültiger Fragetyp: $1',
 687+ 'qp_error_type_in_stats_mode' => 'Der Fragetyp kann im statistischen Anzeigemodus nicht definiert werden: $1',
 688+ 'qp_error_no_poll_id' => 'Für das Abstimmungs-Tag wurde keine Abstimmungskennung definiert.',
 689+ 'qp_error_invalid_poll_id' => 'Ungültige Abstimmungskennung (id=$1).
 690+Abstimmungskennung darf nur Buchstaben, Zahlen und Leerstellen enthalten.',
 691+ 'qp_error_already_used_poll_id' => 'Die Abstimmungskennung wurde bereits auf dieser Seite benutzt (id=$1).',
 692+ 'qp_error_invalid_dependance_value' => 'Die Abhängigkeitskette der Abstimmung (id=$1) hat einen ungültigen Wert in dem Abhängigkeits-Attribut (Abhängigkeit=„$2“)',
 693+ 'qp_error_missed_dependance_title' => 'Die Abstimmung (id=$1) ist abhängig von einer anderen Abstimmung (id=$3) auf der Seite [[$2]], aber der Titel [[$2]] wurde nicht gefunden.
 694+Entferne entweder die Abhängigkeits-Attribute, oder stelle [[$2]] wieder her',
 695+ 'qp_error_missed_dependance_poll' => 'Die Abstimmung (id=$1) ist abhängig von einer anderen Abstimmung (id=$3) auf Seite $2, aber diese Abstimmung existiert nicht oder wurde noch nicht gespeichert.
 696+Entferne entweder die Abhängigkeits-Attribute oder erstelle die Abstimmung mit id=$3 auf Seite $2 und speichere sie.
 697+Um die Abstimmung zu speichern, übermittle sie während du nicht auf eine Antragsanfrage antwortest.',
 698+ 'qp_error_vote_dependance_poll' => 'Bitte erst für $1 abstimmen.',
 699+ 'qp_error_too_many_spans' => 'Zu viele Kategoriegruppen für die Gesamtzahl der Unterkategorien definiert',
 700+ 'qp_error_unanswered_span' => 'Unbeantwortete Unterrubrik',
 701+ 'qp_error_non_unique_choice' => 'Diese Frage benötigt eindeutige Antragsbeantwortung',
 702+ 'qp_error_category_name_empty' => 'Kategoriename ist leer',
 703+ 'qp_error_proposal_text_empty' => 'Vorschlagstext ist leer',
 704+ 'qp_error_too_few_categories' => 'Es müssen mindestens zwei Kategorien festgelegt werden',
 705+ 'qp_error_too_few_spans' => 'Jede Kategoriengruppe muss mindestens zwei Unterrubriken enthalten',
 706+ 'qp_error_no_answer' => 'Unbeantworteter Vorschlag',
 707+ 'qp_error_unique' => 'Die Frage des Typs unique() hat mehr Vorschläge, als mögliche Antworten definiert sind: Ausführung unmöglich',
 708+);
 709+
 710+/** German (formal address) (‪Deutsch (Sie-Form)‬)
 711+ * @author Imre
 712+ */
 713+$messages['de-formal'] = array(
 714+ 'qp_func_missing_question_id' => 'Bitte legen Sie eine existierende Frage-ID (ab 1 aufwärts) für die Abstimmung $1 fest',
 715+ 'qp_error_no_such_poll' => 'Abstimmung nicht vorhanden ($1).
 716+Stellen Sie sicher, dass die Abstimmung festgelegt und gespeichert ist und dass # als Trennsymbol für Adressen verwendet wird',
 717+ 'qp_error_missed_dependance_title' => 'Die Abstimmung (id=$1) ist abhängig von einer anderen Abstimmung (id=$3) auf der Seite [[$2]], aber der Titel [[$2]] wurde nicht gefunden.
 718+Entfernen Sie entweder die Abhängigkeits-Attribute, oder stellen Sie [[$2]] wieder her',
 719+ 'qp_error_missed_dependance_poll' => 'Die Abstimmung (id=$1) ist abhängig von einer anderen Abstimmung (id=$3) auf Seite $2, aber diese Abstimmung existiert nicht oder wurde noch nicht gespeichert.
 720+Entfernen Sie entweder die Abhängigkeits-Attribute oder erstellen Sie die Abstimmung mit id=$3 auf Seite $2 und speichern Sie sie.
 721+Um die Abstimmung zu speichern, übermitteln Sie sie während Sie nicht auf eine Antragsanfrage antworten.',
 722+);
 723+
 724+/** Lower Sorbian (Dolnoserbski)
 725+ * @author Michawiki
 726+ */
 727+$messages['dsb'] = array(
 728+ 'pollresults' => 'Wuslědki napšašowanjow na toś tom sedle',
 729+ 'qp_desc' => 'Zmóžnja napóranje napšašowanjow',
 730+ 'qp_desc-sp' => '[[Special:PollResults|Specialny bok]] za woglědowanje wuslědkow napšašowanjow',
 731+ 'qp_result_NA' => 'Njewótgronjony',
 732+ 'qp_result_error' => 'Syntaksowa zmólka',
 733+ 'qp_vote_button' => 'Wótgłosowaś',
 734+ 'qp_vote_again_button' => 'Twójo wótgłosowanje změniś',
 735+ 'qp_polls_list' => 'Wše napšašowanja nalicyś',
 736+ 'qp_users_list' => 'Wšych wužywarjow nalicyś',
 737+ 'qp_browse_to_poll' => 'Dalej k $1',
 738+ 'qp_browse_to_user' => 'Dalej k $1',
 739+ 'qp_votes_count' => '$1 {{PLURAL:$1|głos|głosa|głose|głosow}}',
 740+ 'qp_source_link' => 'Žrědło',
 741+ 'qp_stats_link' => 'Statistika',
 742+ 'qp_users_link' => 'Wužywarje',
 743+ 'qp_voice_link' => 'Wužywarski głos',
 744+ 'qp_voice_link_inv' => 'Wužywarski głos?',
 745+ 'qp_user_polls_link' => 'Jo se wobźělił na $1 {{PLURAL:$1|napšašowanju|napšašowanjoma|napšašowanjach|napšašowanjach}}',
 746+ 'qp_user_missing_polls_link' => 'Žedno wobźělenje',
 747+ 'qp_not_participated_link' => 'Njewobźělony',
 748+ 'qp_order_by_username' => 'Pórěd pó wužywarskem mjenju',
 749+ 'qp_order_by_polls_count' => 'Pórěd pó licbje napšašowanjow',
 750+ 'qp_results_line_qupl' => 'Bok "$1" napšašowanje "$2": $3',
 751+ 'qp_results_line_qpl' => 'Bok "$1" napšašowanje "$2": $3, $4, $5, $6',
 752+ 'qp_header_line_qpul' => '$1 [ bok "$2" napšašowanje "$3" ]',
 753+ 'qp_export_to_xls' => 'Statistiku do XLS-formata eksportěrowaś',
 754+ 'qp_voices_to_xls' => 'Głose do XLS-formata eksportěrowaś',
 755+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|wužywaŕ jo wótegronił|wužywarja stej wótegroniłej|wužywarje su wótegronili|wužywarjow jo wótegroniło}}',
 756+ 'qp_func_no_such_poll' => 'Take napšašowanje njejo ($1)',
 757+ 'qp_func_missing_question_id' => 'Pšosym pódaj eksistěrujucy ID pšašanja (zachopinajucy wót 1) za napšašowanje $1',
 758+ 'qp_func_invalid_question_id' => 'Njepłaśiwy ID=$2 pšašanja (žedna licba) za napšašowanje $1',
 759+ 'qp_func_missing_proposal_id' => 'Pšosym pódaj eksistěrujucy ID naraźenja (zachopinajucy wót 0) za napšašowanje $1, pšašanje $2',
 760+ 'qp_func_invalid_proposal_id' => 'Njepłaśiwy ID=$3 naraźenja (žedna licba) za napšašowanje $1, pšašanje $2',
 761+ 'qp_error_no_such_poll' => 'Take napšašowanje ($1) njejo.
 762+Zawěsć, až napšašowanje se deklarěrujo a składujo, zawěsć se teke adresowe źěleńske znamuško # wužywaś',
 763+ 'qp_error_in_question_header' => 'Njepłaśiwy typ pšašanja: $1',
 764+ 'qp_error_id_in_stats_mode' => 'Njejo móžno ID napšašowanja w statistiskem modusu deklarěrowaś',
 765+ 'qp_error_dependance_in_stats_mode' => 'Njejo móžno rjeśak wótwisnosći napšašowanja w statistiskem modusu deklarěrowaś',
 766+ 'qp_error_no_stats' => 'Žedne statistiske daty k dispoziciji, dokulaž nichten njejo wótgłosował za toś to napšašowanje (adresa=$1)',
 767+ 'qp_error_address_in_decl_mode' => 'Njejo móžno adresu napšašowanja w deklaraciskem modusu dostaś',
 768+ 'qp_error_question_not_implemented' => 'Pšašanja takego typa njejsu implementěrowane: $1',
 769+ 'qp_error_invalid_question_type' => 'Njepłaśiwy typ pšašanja: $1',
 770+ 'qp_error_type_in_stats_mode' => 'Typ pšašanja njedajo se w statistiskem zwobraznjeńskem modusu definěrowaś: $1',
 771+ 'qp_error_no_poll_id' => 'Toflicka Poll njejo atribut ID definěrowana.',
 772+ 'qp_error_invalid_poll_id' => 'Njepłaśiwy napšašowański ID (ID=$1).
 773+Napšašowański ID smějo jano pismiki, licby a prozne znamje wopśimjeś',
 774+ 'qp_error_already_used_poll_id' => 'Napšašowański ID jo se južo wužył na toś tom boku (ID=$1).',
 775+ 'qp_error_invalid_dependance_value' => 'Rjeśazk wótwisnosći napšašowanja (ID=$1) ma njepłaśiwu gódnotu atributa dependance (dependance="$2")',
 776+ 'qp_error_missed_dependance_title' => 'Napšašowanje (ID=$1) jo wótwisne wót drugego napšašowanja (ID=$3) z boka [[$2]], ale titel [[$2]] njejo se namakał.
 777+Wótpóraj pak atribut dependance pak wótnow [[$2]]',
 778+ 'qp_error_missed_dependance_poll' => 'Napšašowanje (ID=$1) jo wótwisne wót drugego napšašowanja (ID=$3) na boku $2, ale to napšašowanje njeeksistěrujo abo njejo se doněnta składło.
 779+Wótpóraj pak atribut dependance pak napóraj napšašowanje z ID=$3 na boku $2 a składuj jo.
 780+Aby składował napšašowanje, wótpósćel jo, mimo až sy wótegronił na naraźeńske pšašanja.',
 781+ 'qp_error_vote_dependance_poll' => 'Pšosym wótgłosuj nejpjerwjej za napšašowanje $1.',
 782+ 'qp_error_too_many_spans' => 'Pśewjele kategorijowych klasow za pódkategorije definěrowane',
 783+ 'qp_error_unanswered_span' => 'Pódkategorija bźez wótegrona',
 784+ 'qp_error_non_unique_choice' => 'Toś to pšašanje trjeba jadnorazne wótegrono naraźenja',
 785+ 'qp_error_category_name_empty' => 'Mě kategorije jo prozne',
 786+ 'qp_error_proposal_text_empty' => 'Tekst naraźenja jo prozny',
 787+ 'qp_error_too_few_categories' => 'Nanejmjenjej dwě kategorji musytej se definěrować',
 788+ 'qp_error_too_few_spans' => 'Kužda kategorijowa klasa trjeba nanejmjenjej dwě móžnej wótegronje',
 789+ 'qp_error_no_answer' => 'Naraźenje bźez wótegrona',
 790+ 'qp_error_unique' => 'Pšašanje typa unique() ma wěcej naraźenjow ako móžne wótegrona su definěrowane: njemóžno pókšacowaś',
 791+);
 792+
 793+/** Greek (Ελληνικά)
 794+ * @author Egmontaz
 795+ * @author ZaDiak
 796+ */
 797+$messages['el'] = array(
 798+ 'qp_result_NA' => 'Αναπάντητο',
 799+ 'qp_result_error' => 'Συντακτικό σφάλμα',
 800+ 'qp_vote_button' => 'Ψήφισε',
 801+ 'qp_vote_again_button' => 'Αλλαγή ψήφου',
 802+ 'qp_polls_list' => 'Καταγραφή όλων των δημοσκοπήσεων',
 803+ 'qp_users_list' => 'Καταγραφή όλων των χρηστών',
 804+ 'qp_browse_to_poll' => 'Πλοήγηση σε $1',
 805+ 'qp_browse_to_user' => 'Πλοήγηση σε $1',
 806+ 'qp_votes_count' => '$1 {{PLURAL:$1|ψήφος|ψήφοι}}',
 807+ 'qp_source_link' => 'Πηγή',
 808+ 'qp_stats_link' => 'Στατιστικά',
 809+ 'qp_users_link' => 'Χρήστες',
 810+ 'qp_voice_link' => 'Φωνή χρήστη',
 811+ 'qp_voice_link_inv' => 'Φωνή χρήστη;',
 812+ 'qp_user_polls_link' => 'Συμμετοχή σε $1 {{PLURAL:$1|δημοσκόπηση|δημοσκοπήσεις}}',
 813+ 'qp_user_missing_polls_link' => 'Καμία συμμετοχή',
 814+ 'qp_not_participated_link' => 'Δεν συμμετείχε',
 815+ 'qp_order_by_username' => 'Ταξινόμηση κατά όνομα χρήστη',
 816+ 'qp_results_line_qupl' => 'Σελίδα "$1" Δημοσκόπηση "$2": $3',
 817+ 'qp_func_no_such_poll' => 'Καμιά τέτοια δημοσκόπηση ($1)',
 818+);
 819+
 820+/** Esperanto (Esperanto)
 821+ * @author Yekrats
 822+ */
 823+$messages['eo'] = array(
 824+ 'qp_result_error' => 'Sintaksa eraro',
 825+ 'qp_vote_button' => 'Voĉdoni',
 826+ 'qp_source_link' => 'Fonto',
 827+ 'qp_stats_link' => 'Statistikoj',
 828+ 'qp_users_link' => 'Uzantoj',
 829+);
 830+
 831+/** Spanish (Español)
 832+ * @author Imre
 833+ * @author Translationista
 834+ */
 835+$messages['es'] = array(
 836+ 'pollresults' => 'Resultados de las encuestas en esta página',
 837+ 'qp_desc' => 'Permite la creación de encuestas',
 838+ 'qp_desc-sp' => '[[Special:PollResults|Página especial]] para ver los resultados de las encuestas',
 839+ 'qp_result_NA' => 'No respondido',
 840+ 'qp_result_error' => 'Error de sintaxis',
 841+ 'qp_vote_button' => 'Vota',
 842+ 'qp_vote_again_button' => 'Cambia tu voto',
 843+ 'qp_polls_list' => 'Lista todas las encuestas',
 844+ 'qp_users_list' => 'Hacer una lista de todos los usuarios',
 845+ 'qp_browse_to_poll' => 'Navegar a $1',
 846+ 'qp_browse_to_user' => 'Navegar a $1',
 847+ 'qp_votes_count' => '$1 {{PLURAL:$1|voto|votos}}',
 848+ 'qp_source_link' => 'Fuente',
 849+ 'qp_stats_link' => 'Estadísticas',
 850+ 'qp_users_link' => 'Usuarios',
 851+ 'qp_voice_link' => 'Voz de usuario',
 852+ 'qp_voice_link_inv' => '¿Voz de usuario?',
 853+ 'qp_user_polls_link' => 'Ha participado en $1 {{PLURAL:$1|sondeo|sondeos}}',
 854+ 'qp_user_missing_polls_link' => 'No participación',
 855+ 'qp_not_participated_link' => 'No ha participado',
 856+ 'qp_order_by_username' => 'Organizar por nombre de usuario',
 857+ 'qp_order_by_polls_count' => 'Ordenar por conteo de encuestas',
 858+ 'qp_results_line_qupl' => 'Página "$1" Votación "$2": $3',
 859+ 'qp_results_line_qpl' => 'Página "$1" Votación "$2": $3, $4, $5, $6',
 860+ 'qp_header_line_qpul' => '$1 [ Página "$2" Votación "$3" ]',
 861+ 'qp_export_to_xls' => 'Exportar estadísticas a formato XLS',
 862+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|usuario ha|usuarios han}} respondido a las preguntas',
 863+ 'qp_func_no_such_poll' => 'No hay votación ($1)',
 864+ 'qp_func_missing_question_id' => 'Por favor, especifica un identificador de pregunta existente (a partir de 1) para la encuesta $1',
 865+ 'qp_func_invalid_question_id' => 'Pregunta inválida id=$2 (no es un número) para la encuesta $1',
 866+ 'qp_func_missing_proposal_id' => 'Por favor, especifica un identificador de propuesta que exista (comenzando a partir de 0) para la encuesta $1, pregunta $2',
 867+ 'qp_func_invalid_proposal_id' => 'Identificador de propuesta inválido=$3 (no es un número) para la encuesta $1, pregunta $2',
 868+ 'qp_error_no_such_poll' => 'No existe tal encuesta ($1).
 869+Asegúrate de que la encuesta está declarada y guardada, y no olvides usar el carácter delimitador de dirección #',
 870+ 'qp_error_in_question_header' => 'Encabezado de pregunta inválido: $1',
 871+ 'qp_error_id_in_stats_mode' => 'No se puede declarar una ID de encuesta en modo estadístico',
 872+ 'qp_error_dependance_in_stats_mode' => 'No se puede declarar una cadena de dependencia para la encuesta en modo estadístico',
 873+ 'qp_error_no_stats' => 'No hay datos estadísticos disponibles porque nadie ha votado aún en esta encuesta (dirección=$1)',
 874+ 'qp_error_address_in_decl_mode' => 'No se puede obtener una dirección de la encuesta en modo declarativo',
 875+ 'qp_error_question_not_implemented' => 'Las preguntas de este tipo no están implementadas: $1',
 876+ 'qp_error_invalid_question_type' => 'Tipo de pregunta inválido: $1',
 877+ 'qp_error_type_in_stats_mode' => 'El tipo de pregunta no puede definirse en modo de visualización estadística: $1',
 878+ 'qp_error_no_poll_id' => 'La etiqueta de la encuesta no tiene atributo de id definido.',
 879+ 'qp_error_invalid_poll_id' => 'El id de la encuesta no es válido (id=$1).
 880+El id sólo puede contener letras, números y espacios',
 881+ 'qp_error_already_used_poll_id' => 'El identificador de encuesta ya se ha utilizado en esta página (id=$1).',
 882+ 'qp_error_invalid_dependance_value' => 'La cadena de dependencia de la encuesta (id=$1) tiene un valor inválido de atributo de dependencia (dependencia="$2")',
 883+ 'qp_error_missed_dependance_title' => 'La encuesta (id=$1) es dependiente de otra encuesta, (id =$3), de la página [[$2]], pero el título de [[$2]] no se ha encontrado. Elimina el atributo de dependencia, o restaura [[$2] ]',
 884+ 'qp_error_missed_dependance_poll' => 'La encuesta (id=$1) es dependiente de la encuesta (id=$3) en la página $2, pero esa encuesta no existe o aún no se ha guardado. Elimina el atributo de la dependencia o crea la encuesta con id=$3 en la página de $2 y guárdala. Para guardar una encuesta, envíala sin responder a las preguntas.',
 885+ 'qp_error_vote_dependance_poll' => 'Por favor, vota primero en la encuesta $1.',
 886+ 'qp_error_too_many_spans' => 'Muchas clases de categorías para las subcategorías definidas',
 887+ 'qp_error_unanswered_span' => 'Subcategoría sin responder',
 888+ 'qp_error_non_unique_choice' => 'Esta pregunta requiere una propuesta de respuesta única',
 889+ 'qp_error_category_name_empty' => 'El nombre de categoría está vacío',
 890+ 'qp_error_proposal_text_empty' => 'El texto de propuesta está vacío',
 891+ 'qp_error_too_few_categories' => 'Se debe definir al menos dos categorías',
 892+ 'qp_error_too_few_spans' => 'Cada clase de categoría requiere de al menos dos respuestas possibles definidas',
 893+ 'qp_error_no_answer' => 'Propuesta no respondida',
 894+ 'qp_error_unique' => 'La pregunta de tipo único() tiene definidas más propuestas que respuestas posibles: imposible completar',
 895+);
 896+
 897+/** Finnish (Suomi)
 898+ * @author Crt
 899+ * @author Str4nd
 900+ * @author Tofu II
 901+ */
 902+$messages['fi'] = array(
 903+ 'qp_result_NA' => 'Ei vastattu',
 904+ 'qp_result_error' => 'Syntaksivirhe',
 905+ 'qp_vote_button' => 'Äänestä',
 906+ 'qp_vote_again_button' => 'Vaihda ääntäsi',
 907+ 'qp_users_list' => 'Lista kaikista käyttäjistä',
 908+ 'qp_votes_count' => '$1 {{PLURAL:$1|ääni|ääntä}}',
 909+ 'qp_source_link' => 'Lähde',
 910+ 'qp_stats_link' => 'Tilastot',
 911+ 'qp_users_link' => 'Käyttäjät',
 912+ 'qp_order_by_username' => 'Lajittele käyttäjänimen mukaan',
 913+ 'qp_export_to_xls' => 'Vie tilastot XLS-muotoon',
 914+ 'qp_error_category_name_empty' => 'Luokan nimi on tyhjä',
 915+ 'qp_error_proposal_text_empty' => 'Ehdotusteksti on tyhjä',
 916+ 'qp_error_too_few_categories' => 'Ainakin kaksi luokkaa pitää määritellä',
 917+ 'qp_error_no_answer' => 'Vastaamaton ehdotus',
 918+);
 919+
 920+/** French (Français)
 921+ * @author IAlex
 922+ * @author Jean-Frédéric
 923+ * @author McDutchie
 924+ * @author PieRRoMaN
 925+ * @author Sherbrooke
 926+ * @author Urhixidur
 927+ */
 928+$messages['fr'] = array(
 929+ 'pollresults' => 'Résultats des sondages sur ce site',
 930+ 'qp_desc' => 'Permet la création de sondages',
 931+ 'qp_desc-sp' => '[[Special:PollResults|Page spéciale]] pour consulter les résultats des sondages',
 932+ 'qp_result_NA' => 'Pas de réponse',
 933+ 'qp_result_error' => 'Erreur de syntaxe',
 934+ 'qp_vote_button' => 'Vote',
 935+ 'qp_vote_again_button' => 'Changer votre vote',
 936+ 'qp_polls_list' => 'Lister tous les sondages',
 937+ 'qp_users_list' => 'Lister tous les utilisateurs',
 938+ 'qp_browse_to_poll' => 'Aller jusqu’à $1',
 939+ 'qp_browse_to_user' => 'Aller jusqu’à $1',
 940+ 'qp_votes_count' => '$1 {{PLURAL:$1|vote|votes}}',
 941+ 'qp_source_link' => 'Source',
 942+ 'qp_stats_link' => 'Statistiques',
 943+ 'qp_users_link' => 'Utilisateurs',
 944+ 'qp_voice_link' => 'Voix de l’utilisateur',
 945+ 'qp_voice_link_inv' => 'Voix de l’utilisateur ?',
 946+ 'qp_user_polls_link' => 'A participé à $1 {{PLURAL:$1|sondage|sondages}}',
 947+ 'qp_user_missing_polls_link' => 'Pas de participation',
 948+ 'qp_not_participated_link' => 'Pas de participation',
 949+ 'qp_order_by_username' => 'Trier par nom d’utilisateur',
 950+ 'qp_order_by_polls_count' => 'Trier par nombre de sondages',
 951+ 'qp_results_line_qupl' => 'Page « $1 » Sondage « $2 » : $3',
 952+ 'qp_results_line_qpl' => 'Page « $1 » Sondage « $2 » : $3, $4, $5, $6',
 953+ 'qp_header_line_qpul' => '$1 [ Page « $2 » Sondage « $3 » ]',
 954+ 'qp_export_to_xls' => 'Exporter les statistiques au format XLS',
 955+ 'qp_voices_to_xls' => 'Exporter les votes au format XLS',
 956+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|utilisateur a|utilisateurs ont}} répondu aux questions',
 957+ 'qp_func_no_such_poll' => 'Ce sondage n’existe pas ($1)',
 958+ 'qp_func_missing_question_id' => 'Veuillez spécifier un id question existant (à partir de 1) pour le sondage $1',
 959+ 'qp_func_invalid_question_id' => 'id question=$2 invalide (pas un nombre) pour le sondage $1',
 960+ 'qp_func_missing_proposal_id' => 'Veuillez spécifier un id proposition existant (à partir de 0) pour le sondage $1, question $2',
 961+ 'qp_func_invalid_proposal_id' => 'id proposition=$3 invalide (pas un nombre) pour le sondage $1, question $2',
 962+ 'qp_error_no_such_poll' => 'Ce sondage n’existe pas ($1).
 963+Assurez-vous que le sondage soit déclaré et sauvegardé. Vérifiez également si vous utilisez le caractère délimiteur d’adresse #',
 964+ 'qp_error_in_question_header' => 'En-tête de question incorrect : $1',
 965+ 'qp_error_id_in_stats_mode' => 'Impossible de déclarer un ID du sondage dans le mode statistique',
 966+ 'qp_error_dependance_in_stats_mode' => 'Impossible de déclarer la chaîne de dépendance du sondage en mode statistique',
 967+ 'qp_error_no_stats' => 'Aucune donnée statistique n’est disponible, car personne n’a répondu à ce sondage pour l’instant (address=$1)',
 968+ 'qp_error_address_in_decl_mode' => 'Impossible d’obtenir une adresse du sondage en mode déclaratif',
 969+ 'qp_error_question_not_implemented' => 'Les questions de ce type ne sont pas implémentées : $1',
 970+ 'qp_error_invalid_question_type' => 'Type de question invalide : $1',
 971+ 'qp_error_type_in_stats_mode' => 'Le type de question ne peut pas être défini en mode d’affichage statistique : $1',
 972+ 'qp_error_no_poll_id' => 'La balise du sondage n’a pas d’identifiant défini.',
 973+ 'qp_error_invalid_poll_id' => 'Identifiant de sondage invalide (id=$1).
 974+L’identifiant de sondage peut contenir uniquement des lettres, des nombres et le caractère espace',
 975+ 'qp_error_already_used_poll_id' => 'L’identifiant de sondage a déjà été utilisé sur cette page (id=$1).',
 976+ 'qp_error_invalid_dependance_value' => 'La chaîne de dépendance du sondage (id=$1) a une valeur invalide pour l’attribut de dépendance (dependance="$2")',
 977+ 'qp_error_missed_dependance_title' => 'Le sondage (i=$1) dépend d’un autre sondage (id=$3) de la page [[$2]], mais le titre [[$2]] n’a pas été trouvé.
 978+Supprimez l’attribut de dépendance, ou bien restaurez [[$2]]',
 979+ 'qp_error_missed_dependance_poll' => 'Le sondage (id=$1) dépend d’un autre sondage (id=$3) à la page $2, mais ce sondage n’existe pas ou n’a pas encore été enregistré.
 980+Supprimez l’attribut de dépendance, ou bien créez le sondage $3 à la page $2 et enregistrez-le.
 981+Pour enregistrer un sondage, soumettez-le en ne répondant à aucune question de proposition.',
 982+ 'qp_error_vote_dependance_poll' => 'Veuillez d’abord répondre au sondage $1.',
 983+ 'qp_error_too_many_spans' => 'Trop de classes de catégories pour les sous-catégories définies',
 984+ 'qp_error_unanswered_span' => 'Sous-catégorie sans réponse',
 985+ 'qp_error_non_unique_choice' => 'Cette question nécessite une réponse de proposition unique',
 986+ 'qp_error_category_name_empty' => 'Le nom de la catégorie est vide',
 987+ 'qp_error_proposal_text_empty' => 'Le texte de la proposition est vide',
 988+ 'qp_error_too_few_categories' => 'Au moins deux catégories doivent être définies',
 989+ 'qp_error_too_few_spans' => 'Toute classe de catégorie nécessite au moins deux réponses possibles définies',
 990+ 'qp_error_no_answer' => 'Proposition sans réponse',
 991+ 'qp_error_unique' => 'La question de type unique() a plus de propositions qu’il n’y a de réponses possibles définies : impossible de compléter',
 992+);
 993+
 994+/** Franco-Provençal (Arpetan)
 995+ * @author ChrisPtDe
 996+ */
 997+$messages['frp'] = array(
 998+ 'pollresults' => 'Rèsultats des sondâjos sur ceti seto',
 999+ 'qp_desc' => 'Pèrmèt la crèacion de sondâjos.',
 1000+ 'qp_desc-sp' => '[[Special:PollResults|Pâge spèciâla]] por vêre los rèsultats des sondâjos',
 1001+ 'qp_result_NA' => 'Pas rèpondu',
 1002+ 'qp_result_error' => 'Èrror de sintaxa',
 1003+ 'qp_vote_button' => 'Votar',
 1004+ 'qp_vote_again_button' => 'Changiér voutron voto',
 1005+ 'qp_polls_list' => 'Listar tôs los sondâjos',
 1006+ 'qp_users_list' => 'Listar tôs los utilisators',
 1007+ 'qp_browse_to_poll' => 'Navegar tant qu’a $1',
 1008+ 'qp_browse_to_user' => 'Navegar tant qu’a $1',
 1009+ 'qp_votes_count' => '$1 voto{{PLURAL:$1||s}}',
 1010+ 'qp_source_link' => 'Sôrsa',
 1011+ 'qp_stats_link' => 'Statistiques',
 1012+ 'qp_users_link' => 'Utilisators',
 1013+ 'qp_voice_link' => 'Vouèx a l’utilisator',
 1014+ 'qp_voice_link_inv' => 'Vouèx a l’utilisator ?',
 1015+ 'qp_user_polls_link' => 'At participâ a $1 sondâjo{{PLURAL:$1||s}}',
 1016+ 'qp_user_missing_polls_link' => 'Gins de participacion',
 1017+ 'qp_not_participated_link' => 'At pas participâ',
 1018+ 'qp_order_by_username' => 'Triyér per nom d’utilisator',
 1019+ 'qp_order_by_polls_count' => 'Triyér per nombro de sondâjos',
 1020+ 'qp_results_line_qupl' => 'Pâge « $1 » Sondâjo « $2 » : $3',
 1021+ 'qp_results_line_qpl' => 'Pâge « $1 » Sondâjo « $2 » : $3, $4, $5, $6',
 1022+ 'qp_header_line_qpul' => '$1 [ Pâge « $2 » Sondâjo « $3 » ]',
 1023+ 'qp_export_to_xls' => 'Èxportar les statistiques u format XLS',
 1024+ 'qp_voices_to_xls' => 'Èxportar los votos u format XLS',
 1025+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|utilisator a|utilisators on}}t rèpondu a les quèstions',
 1026+ 'qp_func_no_such_poll' => 'Lo sondâjo ègziste pas ($1)',
 1027+ 'qp_error_in_question_header' => 'En-téta de quèstion fôssa : $1',
 1028+ 'qp_error_invalid_question_type' => 'Tipo de quèstion envalido : $1',
 1029+ 'qp_error_vote_dependance_poll' => 'Volyéd d’abôrd rèpondre u sondâjo $1.',
 1030+ 'qp_error_unanswered_span' => 'Sot-catègorie sen rèponsa',
 1031+ 'qp_error_category_name_empty' => 'Lo nom de la catègorie est vouedo',
 1032+ 'qp_error_proposal_text_empty' => 'Lo tèxto de la proposicion est vouedo',
 1033+ 'qp_error_no_answer' => 'Proposicion sen rèponsa',
 1034+);
 1035+
 1036+/** Galician (Galego)
 1037+ * @author Toliño
 1038+ */
 1039+$messages['gl'] = array(
 1040+ 'pollresults' => 'Resultados das enquisas desta páxina',
 1041+ 'qp_desc' => 'Permite a creación de enquisas',
 1042+ 'qp_desc-sp' => '[[Special:PollResults|Páxina especial]] para ollar os resultados das enquisas',
 1043+ 'qp_result_NA' => 'Sen resposta',
 1044+ 'qp_result_error' => 'Erro de sintaxe',
 1045+ 'qp_vote_button' => 'Votar',
 1046+ 'qp_vote_again_button' => 'Cambiar o seu voto',
 1047+ 'qp_polls_list' => 'Lista de todas as enquisas',
 1048+ 'qp_users_list' => 'Lista de todos os usuarios',
 1049+ 'qp_browse_to_poll' => 'Navegar ata $1',
 1050+ 'qp_browse_to_user' => 'Navegar ata $1',
 1051+ 'qp_votes_count' => '$1 {{PLURAL:$1|voto|votos}}',
 1052+ 'qp_source_link' => 'Fonte',
 1053+ 'qp_stats_link' => 'Estatísticas',
 1054+ 'qp_users_link' => 'Usuarios',
 1055+ 'qp_voice_link' => 'Voz do usuario',
 1056+ 'qp_voice_link_inv' => 'Voz do usuario?',
 1057+ 'qp_user_polls_link' => 'Participou {{PLURAL:$1|nunha enquisa|en $1 enquisas}}',
 1058+ 'qp_user_missing_polls_link' => 'Non participou',
 1059+ 'qp_not_participated_link' => 'Non participou',
 1060+ 'qp_order_by_username' => 'Ordenar por nome de usuario',
 1061+ 'qp_order_by_polls_count' => 'Ordenar por número de enquisa',
 1062+ 'qp_results_line_qupl' => 'Páxina "$1", enquisa "$2": $3',
 1063+ 'qp_results_line_qpl' => 'Páxina "$1", enquisa "$2": $3, $4, $5, $6',
 1064+ 'qp_header_line_qpul' => '$1 [ Páxina "$2", enquisa "$3" ]',
 1065+ 'qp_export_to_xls' => 'Exportar as estatísticas en formato XLS',
 1066+ 'qp_voices_to_xls' => 'Exportar as voces en formato XLS',
 1067+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|usuario respondeu|usuarios responderon}} ás preguntas',
 1068+ 'qp_func_no_such_poll' => 'Non existe tal enquisa ($1)',
 1069+ 'qp_func_missing_question_id' => 'Por favor, especifique o id dunha pregunta existente (a partir de 1) para a enquisa $1',
 1070+ 'qp_func_invalid_question_id' => 'question id=$2 (non un número) non válido para a enquisa $1',
 1071+ 'qp_func_missing_proposal_id' => 'Por favor, especifique o id dunha proposta existente (a partir de 0) para a enquisa $1, pregunta $2',
 1072+ 'qp_func_invalid_proposal_id' => 'proposal id=$3 (non un número) non válido para a enquisa $1, pregunta $2',
 1073+ 'qp_error_no_such_poll' => 'Non existe tal enquisa ($1).
 1074+Asegúrese de que a enquisa está declarada e gardada, non esqueza usar o carácter delimitador de enderezo #',
 1075+ 'qp_error_in_question_header' => 'Cabeceira de pregunta inválida: $1',
 1076+ 'qp_error_id_in_stats_mode' => 'Non se pode declarar un ID da enquisa no modo de estatística',
 1077+ 'qp_error_dependance_in_stats_mode' => 'Non se pode declarar a cadea de dependencia da enquisa no modo de estatística',
 1078+ 'qp_error_no_stats' => 'Non hai datos estatísticos dispoñibles porque aínda ninguén votou nesta enquisa (address=$1)',
 1079+ 'qp_error_address_in_decl_mode' => 'Non se pode obter un enderezo da enquisa no modo de declaración',
 1080+ 'qp_error_question_not_implemented' => 'As preguntas deste tipo non están implementadas: $1',
 1081+ 'qp_error_invalid_question_type' => 'Tipo de pregunta non válido: $1',
 1082+ 'qp_error_type_in_stats_mode' => 'O tipo de pregunta non se pode definir no modo de vista estatística: $1',
 1083+ 'qp_error_no_poll_id' => 'A etiqueta da enquisa non ten ningún atributo id definido.',
 1084+ 'qp_error_invalid_poll_id' => 'O id da enquisa non é válido (id=$1).
 1085+O id só pode conter letras, números e espazos',
 1086+ 'qp_error_already_used_poll_id' => 'O id da enquisa xa se empregou nesta páxina (id=$1).',
 1087+ 'qp_error_invalid_dependance_value' => 'A cadea de dependencia da enquisa (id=$1) ten un valor non válido para o atributo de dependencia (dependance="$2")',
 1088+ 'qp_error_missed_dependance_title' => 'A enquisa (id=$1) depende doutra enquisa (id=$3) da páxina [[$2]], pero non se atopou o título [[$2]].
 1089+Elimine o atributo de dependencia ou restaure [[$2]]',
 1090+ 'qp_error_missed_dependance_poll' => 'A enquisa (id=$1) depende doutra enquisa (id=$3) na páxina $2, pero esa enquisa non existe ou aínda non foi gardada.
 1091+Elimine o atributo de dependencia ou cree a enquisa co id=$3 na páxina $2 e gárdea.
 1092+Para gardar unha enquisa, envíea sen responder a ningunha pregunta.',
 1093+ 'qp_error_vote_dependance_poll' => 'Por favor, vote primeiro na enquisa $1.',
 1094+ 'qp_error_too_many_spans' => 'Demasiadas clases de categoría para as subcategorías definidas',
 1095+ 'qp_error_unanswered_span' => 'Subcategoría sen resposta',
 1096+ 'qp_error_non_unique_choice' => 'Esta pregunta require unha resposta única',
 1097+ 'qp_error_category_name_empty' => 'O nome da categoría está baleiro',
 1098+ 'qp_error_proposal_text_empty' => 'O texto da proposta está baleiro',
 1099+ 'qp_error_too_few_categories' => 'Débense definir, polo menos, dúas categorías',
 1100+ 'qp_error_too_few_spans' => 'Cada clase de categoría necesita definidas, polo menos, dúas respostas posibles',
 1101+ 'qp_error_no_answer' => 'Proposta sen resposta',
 1102+ 'qp_error_unique' => 'A pregunta de tipo unique() ten definidas máis propostas que respostas posibles: imposible de completar',
 1103+);
 1104+
 1105+/** Swiss German (Alemannisch)
 1106+ * @author Als-Holder
 1107+ */
 1108+$messages['gsw'] = array(
 1109+ 'pollresults' => 'Ergebnis vu dr Abstimmige uf däm Site',
 1110+ 'qp_desc' => 'Erlaubt s Aalege vu Abstimmige',
 1111+ 'qp_desc-sp' => '[[Special:PollResults|Spezialsyte]] zum Aalueg vu dr Ergebnis vu dr Abstimmige',
 1112+ 'qp_result_NA' => 'Kei Antwort',
 1113+ 'qp_result_error' => 'Syntaxfähler',
 1114+ 'qp_vote_button' => 'Abstimme',
 1115+ 'qp_vote_again_button' => 'Dyy Stimm ändere',
 1116+ 'qp_polls_list' => 'Alli Abstimmige uflischte',
 1117+ 'qp_users_list' => 'Alli Benutzer uflischte',
 1118+ 'qp_browse_to_poll' => 'Wyter zue $1',
 1119+ 'qp_browse_to_user' => 'Wyter zue $1',
 1120+ 'qp_votes_count' => '$1 {{PLURAL:$1|Stimm|Stimme}}',
 1121+ 'qp_source_link' => 'Quälle',
 1122+ 'qp_stats_link' => 'Statischtik',
 1123+ 'qp_users_link' => 'Benutzer',
 1124+ 'qp_voice_link' => 'Benutzerstimm',
 1125+ 'qp_voice_link_inv' => 'Benutzerstimm?',
 1126+ 'qp_user_polls_link' => 'Mitgmacht bi $1 {{PLURAL:$1|Abstimmig|Abstimmige}}',
 1127+ 'qp_user_missing_polls_link' => 'Niene mitgmacht',
 1128+ 'qp_not_participated_link' => 'Niene mitgmacht',
 1129+ 'qp_order_by_username' => 'No Benutzername gordnet',
 1130+ 'qp_order_by_polls_count' => 'No Abstimmigsaazahl gordnet',
 1131+ 'qp_results_line_qupl' => 'Syte „$1“ Abstimmig „$2“: $3',
 1132+ 'qp_results_line_qpl' => 'Syte „$1“ Abstimmig „$2“: $3, $4, $5, $6',
 1133+ 'qp_header_line_qpul' => '$1 [ Syte „$2“ Abstimmig „$3“ ]',
 1134+ 'qp_header_line_qucl' => '$1. $2<br />$3 ??? $4',
 1135+ 'qp_export_to_xls' => 'Statischtik im XLS-Format exportiere',
 1136+ 'qp_voices_to_xls' => 'Stimme im XLS-Format exportiere',
 1137+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|Benutzer het|Benutzer hän}} Antworte uf d Froge gee',
 1138+ 'qp_func_no_such_poll' => 'Kei sonigi Abstimmig ($1)',
 1139+ 'qp_func_missing_question_id' => 'Bitte spezifizier e Froge-Chännnummere (mit 1 aafange) fir d Abstimmig $1',
 1140+ 'qp_func_invalid_question_id' => 'Uugiltigi Froge-Chännnummere ($2, kei Zahl) fir d Abstimmig $1',
 1141+ 'qp_func_missing_proposal_id' => 'Bitte spezifiezier e Vorschlags-Chännnummere, wu s scho git (mit 0 aafange) fir d Abstimmig $1, Frog $2',
 1142+ 'qp_func_invalid_proposal_id' => 'Nit giltigi Vorschlags-Chännnummere ($3, kei Zahl) fir d Abstimmig $1, Frog $2',
 1143+ 'qp_error_no_such_poll' => 'Kei sonigi Abstimmig ($1).
 1144+Stell sicher, ass d Abstimmig verchindet un gspycheret woren isch, stell au sicher, ass as Trännzeiche in dr Adräss alliwyl # brucht wird',
 1145+ 'qp_error_in_question_header' => 'Nit giltige Frogechopf: $1',
 1146+ 'qp_error_id_in_stats_mode' => 'Cha dr Abstimmig kei Chännnummere zuewyyse im statistische Modus',
 1147+ 'qp_error_dependance_in_stats_mode' => 'Cha d Abhägikeits-Chette vu dr Abstimmig nit verchinde im statistische Modus',
 1148+ 'qp_error_no_stats' => 'Kei statistischi Date verfiegbar, wel no keini Benutzer abgstumme hän (Adräss $1)',
 1149+ 'qp_error_address_in_decl_mode' => 'Cha kei Adräss vu dr Abstimmig iberchuu im Verchindigs-Modus',
 1150+ 'qp_error_question_not_implemented' => 'Forge vu däm Typ sin nit vorgsäh: $1',
 1151+ 'qp_error_invalid_question_type' => 'Nit giltige Frogetyp: $1',
 1152+ 'qp_error_type_in_stats_mode' => 'Frogetyp cha nit im statistische Widergabmodus definiert wäre: $1',
 1153+ 'qp_error_no_poll_id' => 'D Eigeschaft „id“ (Chännnummere) isch nit definiert fir d Abstimmig.',
 1154+ 'qp_error_invalid_poll_id' => 'Nit giltigi Abstimmigs-Chännnummere ($1).
 1155+In dr Chännnummere derf s nume Buechstabe, Zahle un Läärstelle haa.',
 1156+ 'qp_error_already_used_poll_id' => 'Die Abstimmigs-Chännnummere wird schoi rbuc ht uf däre Syte ($1)',
 1157+ 'qp_error_invalid_dependance_value' => 'D Abhängigkeits-Chette vu dr Abstimmig (id=$1) het e nit giltige Wärt vu dr Abhängigkeitseigeschaft („$2“)',
 1158+ 'qp_error_missed_dependance_title' => 'D Abstimmig ($1) hangt aqb vun ere andere Abstimmig ($3) vu dr Syte [[$2]], aber dr Titel [[$2]] isch nit gfunde wore.
 1159+Entwäder due d Abhängigkeitseigeschaft uuseneh oder spychere [[$2]] um',
 1160+ 'qp_error_missed_dependance_poll' => 'D Abstimmig ($1) isch abhängig vun ere andere Abstimmig ($3) uf dr Syte $2, aber sälli Abstimmig git s nit oder si isch nonig gspycheret wore.
 1161+Entwäder due d Abhängigkeitseigeschaft uuseneh oder leg d Abstimmig aa mit dr Chännnummere $3 uf dr Syte $2 un due si spychere.
 1162+Go ne Abstimmig spychere due si ibertrage ohni ne Antwort gee uf irged e Vorschlagsfrog.',
 1163+ 'qp_error_vote_dependance_poll' => 'Bitte stimm zerscht ab in dr Abstimmig $1.',
 1164+ 'qp_error_too_many_spans' => 'S sin zvyl Kategorieklasse definiert fir d Unterkategorie',
 1165+ 'qp_error_unanswered_span' => 'Unterkategori ohni Antwort',
 1166+ 'qp_error_non_unique_choice' => 'D Frog brucht ei einzige Vorschlags-Antwort',
 1167+ 'qp_error_category_name_empty' => 'Kei Kategoriname aagee',
 1168+ 'qp_error_proposal_text_empty' => 'Kei Vorschlagstext aagee',
 1169+ 'qp_error_too_few_categories' => 'Zmindescht zwo Kategorie mien definiert wäre',
 1170+ 'qp_error_too_few_spans' => 'Fir jedi Kategorieklasse brucht s zmindescht zwo definierti Antworte',
 1171+ 'qp_error_no_answer' => 'Vorschlag ohni Antwort',
 1172+ 'qp_error_unique' => 'Fir d Frog vum Typ unique() git s meh Vorschleg wie Antworte definiert sin: cha nit abgschlosse wäre',
 1173+);
 1174+
 1175+/** Hebrew (עברית)
 1176+ * @author Amire80
 1177+ * @author YaronSh
 1178+ */
 1179+$messages['he'] = array(
 1180+ 'pollresults' => 'תוצאות הסקרים באתר',
 1181+ 'qp_desc' => 'מאפשר יצירת סקרים',
 1182+ 'qp_desc-sp' => '[[Special:PollResults|דף מיוחד]] לצפייה בתוצאות הסקרים',
 1183+ 'qp_result_NA' => 'לא נענה',
 1184+ 'qp_result_error' => 'שגיאת תחביר',
 1185+ 'qp_vote_button' => 'הצבעה',
 1186+ 'qp_vote_again_button' => 'שינוי הצבעתכם',
 1187+ 'qp_polls_list' => 'הצגת כל הסקרים',
 1188+ 'qp_users_list' => 'הצגת כל המשתמשים',
 1189+ 'qp_browse_to_poll' => 'עיון בסקר $1',
 1190+ 'qp_browse_to_user' => 'עיון בחשבון $1',
 1191+ 'qp_votes_count' => '{{PLURAL:$1|הצבעה אחת|$1 הצבעות}}',
 1192+ 'qp_source_link' => 'מקור',
 1193+ 'qp_stats_link' => 'סטטיסטיקה',
 1194+ 'qp_users_link' => 'משתמשים',
 1195+ 'qp_voice_link' => 'קול המשתמש',
 1196+ 'qp_voice_link_inv' => 'קול המשתמש?',
 1197+ 'qp_user_polls_link' => 'השתתף ב{{PLURAL:$1|סקר אחד|־$1 סקרים}}',
 1198+ 'qp_user_missing_polls_link' => 'אין השתתפות',
 1199+ 'qp_not_participated_link' => 'לא השתתף',
 1200+ 'qp_order_by_username' => 'מיון לפי שם משתמש',
 1201+ 'qp_order_by_polls_count' => 'מיון לפי מספר הסקרים',
 1202+ 'qp_results_line_qupl' => 'הדף "$1" סקר "$2": $3',
 1203+ 'qp_results_line_qpl' => 'הדף "$1" סקר "$2": $3‏, $4‏, $5‏, $6',
 1204+ 'qp_header_line_qpul' => '$1 [ דף "$2" סקר "$3" ]',
 1205+ 'qp_export_to_xls' => 'ייצוא הסטטיסטיקה לקובץ מסוג XLS',
 1206+ 'qp_voices_to_xls' => 'ייצוא קולות לתסדיר XLS',
 1207+ 'qp_users_answered_questions' => '{{PLURAL:$1|משתמש אחד ענה|$1 משתמשים ענו}} על השאלות',
 1208+ 'qp_func_no_such_poll' => 'אין כזה סקר ($1)',
 1209+ 'qp_func_missing_question_id' => "יש לציין מס' שאלה קיים (החל מ־1) עבור הסקר $1",
 1210+ 'qp_func_invalid_question_id' => 'מזהה שאלה לא תקין=$2 (לא מספר) בסקר $1',
 1211+ 'qp_func_missing_proposal_id' => 'נא להגדיר מזהה תשובה אפשירת קיים (מתחיל 0) לסקר $1, שאלה $2',
 1212+ 'qp_func_invalid_proposal_id' => 'מזהה תשובה מוצעת לא תקין=$3 (לא מספר) בסקר $1, שאלה $2',
 1213+ 'qp_error_no_such_poll' => 'אין סקר כזה ($1).
 1214+נא לוודא שהסקר מוכרז ושמור, ולוודא שנעשה שימוש בתו המפריד # בכתובת',
 1215+ 'qp_error_in_question_header' => 'כותרת שאלה לא תקינה: $1',
 1216+ 'qp_error_id_in_stats_mode' => "לא ניתן להצהיר על מס' עבור הסקר במצב סטטיסטי",
 1217+ 'qp_error_dependance_in_stats_mode' => 'לא ניתן להכריז על שרשרת תלות של הסקר במצב סטטיסטיקה',
 1218+ 'qp_error_no_stats' => 'אין נתונים סטטיסטיים זמינים כיוון שאף אחד עוד לא הצביע בסקר הזה, עדיין (כתובת=$1)',
 1219+ 'qp_error_address_in_decl_mode' => 'לא ניתן לאחזר את כתובת הסקר במצב הצהרה',
 1220+ 'qp_error_question_not_implemented' => 'שאלות מהסוג הזה אינן מיושמות: $1',
 1221+ 'qp_error_invalid_question_type' => 'סוג השאלה שגוי: $1',
 1222+ 'qp_error_type_in_stats_mode' => 'סוג השאלה לא ניתן להגדרה במצב תצוגה סטטיסטית: $1',
 1223+ 'qp_error_no_poll_id' => 'לא מוגדר מאפיין id לתג סקר.',
 1224+ 'qp_error_invalid_poll_id' => 'מזהה סקר לא תקין (id=$1).
 1225+מזהה הסקר יכול להכיל רק אותיות, ספרות ותו רווח',
 1226+ 'qp_error_already_used_poll_id' => 'כבר נעשה שימוש במזהה הסקר בדף הזה (id=$1).',
 1227+ 'qp_error_invalid_dependance_value' => 'לשרשרת התלות של הסקר (id=$1) יש ערך בלתי תקין של מאפיין dependance‏ (dependance="$2")',
 1228+ 'qp_error_missed_dependance_title' => 'הסקר (id=$1) תלוי בסקר אחר (id=$3) מהדף [[$2]], אבל הכותרת [[$2]] לא נמצאה.
 1229+הסירו את מאפיין התלות או שחזרו את [[$2]]',
 1230+ 'qp_error_missed_dependance_poll' => 'הסקר (id=$1) תלוי בסקר אחר (id=$3) בדף $2, אבל הסקר ההוא אינו קיים או שהוא עדיין לא נשמר.
 1231+הסירו את מאפיין התלות או צרו סקר עם id=$3 בדף $2 ושִמרו אותו.
 1232+כדי לשמור סקר, שלחו אותו בלי לענות על השאלות.',
 1233+ 'qp_error_vote_dependance_poll' => 'יש להצביע עבור הסקר $1 תחילה.',
 1234+ 'qp_error_too_many_spans' => 'הוגדרו קבוצות קטגוריות רבות מדי עבור המספר הכולל של קטגוריות משנה',
 1235+ 'qp_error_unanswered_span' => 'קטגוריית משנה ללא מענה',
 1236+ 'qp_error_non_unique_choice' => 'שאלה זו מחייבת תשובה הצעה ייחודית',
 1237+ 'qp_error_category_name_empty' => 'שם הקטגוריה ריק',
 1238+ 'qp_error_proposal_text_empty' => 'טקסט ההצעה ריק',
 1239+ 'qp_error_too_few_categories' => 'יש להגדיר לפחות שתי קטגוריות',
 1240+ 'qp_error_too_few_spans' => 'כל קבוצת קטגוריות חייבת להכיל לפחות שתי תת־קטגוריות',
 1241+ 'qp_error_no_answer' => 'הצעה שלא נענתה',
 1242+ 'qp_error_unique' => 'לשאלה מסוג unique()‎ יש יותר הצעות ממספר התשובות האפשריות מוגדרות: אי־אפשר להשלים',
 1243+);
 1244+
 1245+/** Upper Sorbian (Hornjoserbsce)
 1246+ * @author Michawiki
 1247+ */
 1248+$messages['hsb'] = array(
 1249+ 'pollresults' => 'Wuslědki wothłosowanjow na tutym sydle',
 1250+ 'qp_desc' => 'Zmóžnja wutworjenje wothłosowanjow',
 1251+ 'qp_desc-sp' => '[[Special:PollResults|Specialna strona]] za wobhladowanje wuslědkow wothłosowanjow',
 1252+ 'qp_result_NA' => 'Njewotmołwjeny',
 1253+ 'qp_result_error' => 'Syntaksowy zmylk',
 1254+ 'qp_vote_button' => 'Hłosować',
 1255+ 'qp_vote_again_button' => 'Twoje wothłosowanje změnić',
 1256+ 'qp_polls_list' => 'Wšě wothłosowanja nalistować',
 1257+ 'qp_users_list' => 'Wšěch wužiwarjow nalistować',
 1258+ 'qp_browse_to_poll' => 'Dale k $1',
 1259+ 'qp_browse_to_user' => 'Dale k $1',
 1260+ 'qp_votes_count' => '$1 {{PLURAL:$1|hłós|hłosaj|hłosy|hłosow}}',
 1261+ 'qp_source_link' => 'Žórło',
 1262+ 'qp_stats_link' => 'Statistika',
 1263+ 'qp_users_link' => 'Wužiwarjo',
 1264+ 'qp_voice_link' => 'Wužiwarski hłós',
 1265+ 'qp_voice_link_inv' => 'Wužiwarski hłós?',
 1266+ 'qp_user_polls_link' => 'Wobdźěli so na $1 {{PLURAL:$1|wothłosownju|wothłosowanjomaj|wothłosowanjach|wothłosowanjach}}',
 1267+ 'qp_user_missing_polls_link' => 'Žane wobdźělenje',
 1268+ 'qp_not_participated_link' => 'Njewobdźěleny',
 1269+ 'qp_order_by_username' => 'Porjad po wužiwarskim mjenje',
 1270+ 'qp_order_by_polls_count' => 'Porjad po ličbje wothłosowanjow',
 1271+ 'qp_results_line_qupl' => 'Strona "$1" wothłosowanje "$2": $3',
 1272+ 'qp_results_line_qpl' => 'Strona "$1" wothłosowanje "$2": $3, $4, $5, $6',
 1273+ 'qp_header_line_qpul' => '$1 [ strona "$2" wothłosowanje "$3" ]',
 1274+ 'qp_export_to_xls' => 'Statistiku do XLS-formata eksportować',
 1275+ 'qp_voices_to_xls' => 'Hłosy do XLS-formata eksportować',
 1276+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|wužiwar je|wužiwarjej staj|wužiwarjo su|wužiwarjow je}} na prašenja {{PLURAL:$1|wotmołwił|wotmołwiłoj|wotmołwili|wotmołwiło}}',
 1277+ 'qp_func_no_such_poll' => 'Žane tajke wothłosowanje ($1)',
 1278+ 'qp_func_missing_question_id' => 'Prošu podaj eksistowacy prašenski ID (započinajo wot 1) za wothłosowanje $1',
 1279+ 'qp_func_invalid_question_id' => 'Njepłaćiwe prašenje id=$2 (žana ličba) za wothłosowanje $1',
 1280+ 'qp_func_missing_proposal_id' => 'Prošu podaj eksistowacy namjetowy ID (započinajo wot 0) za naprašowanje $1, prašenje $2',
 1281+ 'qp_func_invalid_proposal_id' => 'Njepłaćiwy namjet id=$3 (žana ličba) za wothłosowanje $1, prašenje $2',
 1282+ 'qp_error_no_such_poll' => 'Tajke wothłosowanje njeje ($1).
 1283+Zawěsć, zo wothłosowanje bu deklarowane a składowane, přeswědč so, zo wužiwaš adresowe dźělatko #',
 1284+ 'qp_error_in_question_header' => 'Njepłaćiwy prašenski typ: $1',
 1285+ 'qp_error_id_in_stats_mode' => 'Njeje móžno ID wothłosowanja w statistiskim modusu deklarowác',
 1286+ 'qp_error_dependance_in_stats_mode' => 'Njeje móžno wotwisnosćowy rjećazk wothłosowanja w statistiskim modusu deklarować',
 1287+ 'qp_error_no_stats' => 'Žane statistiske daty k dispoziciji, dokelž dotal nichtó njeje za tute wothłosowanje hłosował (adresa=$1)',
 1288+ 'qp_error_address_in_decl_mode' => 'Njeje móžno adresu wothłosowanja w deklaraciskim modusu dóstać',
 1289+ 'qp_error_question_not_implemented' => 'Prašenja tutoho typa njejsu implementowane: $1',
 1290+ 'qp_error_invalid_question_type' => 'Njepłaćiwy prašenski typ: $1',
 1291+ 'qp_error_type_in_stats_mode' => 'Prašenski typ njeda so w statistiskim zwobraznjenskim modusu definować: $1',
 1292+ 'qp_error_no_poll_id' => 'Taflička Poll njeje atribut ID definował.',
 1293+ 'qp_error_invalid_poll_id' => 'Njepłaćiwy Id wothłosowanja (ID=$1).
 1294+ID wothłosowanja smě jenož pismiki, ličby a mjezeru wobsahować',
 1295+ 'qp_error_already_used_poll_id' => 'ID wothłosowanja wužiwa so hižo na tutej stronje (ID=$1).',
 1296+ 'qp_error_invalid_dependance_value' => 'Wotwisnosćowy rjećazk wothłosowanja (id=$1) ma njepłaćiwu hódnotu atributa dependance (dependance="$2")',
 1297+ 'qp_error_missed_dependance_title' => 'Wothłosowanje (ID=$1) je wot druheho wothłosowanja (ID=$3) ze strony [[$2]] wotwisne, ale titul [[$2]] njebu namakany. Wotstroń pak atribut dependance pak wobnow [[$2]]',
 1298+ 'qp_error_missed_dependance_poll' => 'Wothłosowanje (ID=$1) je wot druheho wothłosowanja (ID=$3) na stronje $2 wotwisne, ale te wothłosowanje njeeksistuje abo njeje so składowało.
 1299+Wotstroń pak atribut dependance pak wutwor wothłosowanje z ID=$3 na stronje $2 a składuj jo.
 1300+Zo by wothłosowanje składował, wotpósćel jo, bjeztoho zo by na namjetowe prašenja wotmołwił.',
 1301+ 'qp_error_vote_dependance_poll' => 'Prošu hłosuj najprjedy za wothłosowanje $1.',
 1302+ 'qp_error_too_many_spans' => 'Přewjele kategorijowych klasow za podkategorije definowane',
 1303+ 'qp_error_unanswered_span' => 'Njewotmołwjena podkategorija',
 1304+ 'qp_error_non_unique_choice' => 'Tute prašenje trjeba jónkróćnu namjetowu wotmołwu',
 1305+ 'qp_error_category_name_empty' => 'Kategorijowe mjeno je prózdne',
 1306+ 'qp_error_proposal_text_empty' => 'Namjetowy tekst je prózdny',
 1307+ 'qp_error_too_few_categories' => 'Znajmjeńša dwě kategoriji dyrbitej so definować',
 1308+ 'qp_error_too_few_spans' => 'Kóžda kategorijowa klasa trjeba znajmjeńša dwě móžnej definowanej wotmołwje',
 1309+ 'qp_error_no_answer' => 'Njewotmołwjeny namjet',
 1310+ 'qp_error_unique' => 'Prašenje typa unique() ma wjace namjetow hač su móžne wotmołwy definowane: njemóžno pokročować',
 1311+);
 1312+
 1313+/** Hungarian (Magyar)
 1314+ * @author Dani
 1315+ * @author Glanthor Reviol
 1316+ */
 1317+$messages['hu'] = array(
 1318+ 'pollresults' => 'Az oldal szavazásainak eredményei',
 1319+ 'qp_desc' => 'Lehetővé teszi szavazások készítését',
 1320+ 'qp_desc-sp' => '[[Special:PollResults|Speciális lap]] a szavazások eredményeinek megtekintésére',
 1321+ 'qp_result_NA' => 'Nem válaszolt',
 1322+ 'qp_result_error' => 'Szintaktikai hiba',
 1323+ 'qp_vote_button' => 'Szavazás',
 1324+ 'qp_vote_again_button' => 'Szavazat megváltoztatása',
 1325+ 'qp_polls_list' => 'Szavazások listája',
 1326+ 'qp_users_list' => 'Felhasználók listája',
 1327+ 'qp_browse_to_poll' => 'Ugrás a szavazás helyére: $1',
 1328+ 'qp_browse_to_user' => 'A felhasználó lapja: $1',
 1329+ 'qp_votes_count' => '$1 szavazat',
 1330+ 'qp_source_link' => 'Forrás',
 1331+ 'qp_stats_link' => 'Statisztika',
 1332+ 'qp_users_link' => 'Felhasználók',
 1333+ 'qp_voice_link' => 'A felhasználó szavazatai',
 1334+ 'qp_voice_link_inv' => 'A felhasználó szavazatai?',
 1335+ 'qp_user_polls_link' => '$1 szavazáson vett részt',
 1336+ 'qp_user_missing_polls_link' => 'Nem vett részt',
 1337+ 'qp_not_participated_link' => 'Nem vett részt',
 1338+ 'qp_order_by_username' => 'Rendezés felhasználónév szerint',
 1339+ 'qp_order_by_polls_count' => 'Rendezés a szavazások száma szerint',
 1340+ 'qp_results_line_qupl' => 'Lap: „$1”, szavazás: „$2”: $3',
 1341+ 'qp_results_line_qpl' => 'Lap: „$1”, szavazás: „$2”: $3, $4, $5, $6',
 1342+ 'qp_header_line_qpul' => '$1 [ Lap: „$2”, szavazás: „$3” ]',
 1343+ 'qp_export_to_xls' => 'Statisztikák exportálása XLS-formátumban',
 1344+ 'qp_users_answered_questions' => '$1 felhasználó válaszolt a kérdésekre',
 1345+ 'qp_func_no_such_poll' => 'Nincs ilyen szavazás ($1)',
 1346+ 'qp_func_missing_question_id' => 'Add meg egy létező kérdés azonosítóját (1-től kezdve) a(z) $1 szavazáshoz',
 1347+ 'qp_func_invalid_question_id' => 'Érvénytelen kérdés id=$2 (nem szám) a(z) $1 szavazáshoz',
 1348+ 'qp_func_missing_proposal_id' => 'Add meg egy létező javaslat azonosítóját (0-tól kezdve) a(z) $1 szavazás $2 kérdéséhez',
 1349+ 'qp_func_invalid_proposal_id' => 'Érvénytelen javaslat id=$3 (nem szám) a(z) $1 szavazás $2 kérdéséhez',
 1350+ 'qp_error_no_such_poll' => 'Nincs ilyen szavazás ($1).
 1351+Győződj meg róla, hogy a szavazás deklarálva van, és elmentetted, valamint hogy használtad-e a címhatároló karaktert (#)',
 1352+ 'qp_error_in_question_header' => 'Érvénytelen kérdés-fejléc: $1',
 1353+ 'qp_error_id_in_stats_mode' => 'Nem deklarálható egy szavazás azonosítója statisztikai módban',
 1354+ 'qp_error_dependance_in_stats_mode' => 'Nem deklarálható a szavazás függőségi lánca statisztikai módban',
 1355+ 'qp_error_no_stats' => 'A statisztikai adatok nem elérhetőek, mert még senki sem szavazott ezen a szavazáson (address=$1)',
 1356+ 'qp_error_address_in_decl_mode' => 'A szavazás címe nem kérhető le deklarációs módban',
 1357+ 'qp_error_question_not_implemented' => 'Az ilyen típusú kérdések nincsenek implementálva: $1',
 1358+ 'qp_error_invalid_question_type' => 'Érvénytelen kérdéstípus: $1',
 1359+ 'qp_error_type_in_stats_mode' => 'A kérdés típusát nem lehet megadni statisztikai módban: $1',
 1360+ 'qp_error_no_poll_id' => 'A szavazás tagnek nincs azonosító (id) attribútuma megadva.',
 1361+ 'qp_error_invalid_poll_id' => 'Érvénytelen szavazásazonosító (id=$1).
 1362+A szavazásazonosító csak betűket, számokat és szóközt tartalmazhat',
 1363+ 'qp_error_already_used_poll_id' => 'Ez a szavazásazonosító már használva volt korábban ezen a lapon (id=$1).',
 1364+ 'qp_error_invalid_dependance_value' => 'A szavazás (id=$1) függőségi lánca érvénytelen függőségi attribútum-értékkel rendelkezik (dependance="$2")',
 1365+ 'qp_error_missed_dependance_title' => 'A szavazás (id=$1) függ a(z) [[$2]] lapon található másik szavazástól (id=$3), de ez a lap nem található.
 1366+Vagy távolítsd el a függőségi attribútumot, vagy állítsd helyre a(z) [[$2]] lapot.',
 1367+ 'qp_error_missed_dependance_poll' => 'A szavazás (id=$1) függ egy, a(z) $2 lapon található másik szavazástól (id=$3), de ez a szavazás nem létezik, vagy még nem lett elmentve.
 1368+Távolítsd el a függőségi attribútumot, vagy készítsd el a(z) id=$3 azonosítóval rendelkező szavazást a(z) $2 lapon, és mentsd el.
 1369+A szavazás elmentéséhez küldd el azt anélkül, hogy válaszolnál bármelyik kérdésre.',
 1370+ 'qp_error_vote_dependance_poll' => 'Először szavazz a(z) $1 szavazáson.',
 1371+ 'qp_error_too_many_spans' => 'Túl sok kategóriaosztály lett az alkategóriák számára megadva.',
 1372+ 'qp_error_unanswered_span' => 'Megválaszolatlan alkategória',
 1373+ 'qp_error_non_unique_choice' => 'Ennek kérdésnek egyedi javasolt válaszra van szüksége',
 1374+ 'qp_error_category_name_empty' => 'A kategória neve üres',
 1375+ 'qp_error_proposal_text_empty' => 'A javaslat szövege üres',
 1376+ 'qp_error_too_few_categories' => 'Legalább két kategóriát kell megadni',
 1377+ 'qp_error_too_few_spans' => 'Mindegyik kategóriaosztályhoz meg kell adni legalább két lehetséges választ',
 1378+ 'qp_error_no_answer' => 'Megválaszolatlan javaslat',
 1379+ 'qp_error_unique' => 'A unique() típus kérdése több javaslattal rendelkezik, mint a megadott lehetséges válaszol száma: nem lehet befejezni',
 1380+);
 1381+
 1382+/** Interlingua (Interlingua)
 1383+ * @author McDutchie
 1384+ */
 1385+$messages['ia'] = array(
 1386+ 'pollresults' => 'Resultatos del sondages in iste sito',
 1387+ 'qp_desc' => 'Permitte le creation de sondages',
 1388+ 'qp_desc-sp' => '[[Special:PollResults|Pagina special]] pro vider le resultatos del sondages',
 1389+ 'qp_result_NA' => 'Sin responsa',
 1390+ 'qp_result_error' => 'Error de syntaxe',
 1391+ 'qp_vote_button' => 'Votar',
 1392+ 'qp_vote_again_button' => 'Modificar tu voto',
 1393+ 'qp_polls_list' => 'Listar tote le sondages',
 1394+ 'qp_users_list' => 'Listar tote le usatores',
 1395+ 'qp_browse_to_poll' => 'Navigar verso $1',
 1396+ 'qp_browse_to_user' => 'Navigar verso $1',
 1397+ 'qp_votes_count' => '$1 {{PLURAL:$1|voto|votos}}',
 1398+ 'qp_source_link' => 'Origine',
 1399+ 'qp_stats_link' => 'Statisticas',
 1400+ 'qp_users_link' => 'Usatores',
 1401+ 'qp_voice_link' => 'Voce del usator',
 1402+ 'qp_voice_link_inv' => 'Voce de usator?',
 1403+ 'qp_user_polls_link' => 'Participava in $1 {{PLURAL:$1|sondage|sondages}}',
 1404+ 'qp_user_missing_polls_link' => 'Nulle participation',
 1405+ 'qp_not_participated_link' => 'Non participate',
 1406+ 'qp_order_by_username' => 'Ordinar per nomine de usator',
 1407+ 'qp_order_by_polls_count' => 'Ordinar per numero de sondages',
 1408+ 'qp_results_line_qupl' => 'Pagina "$1" Sondage "$2": $3',
 1409+ 'qp_results_line_qpl' => 'Pagina "$1" Sondage "$2": $3, $4, $5, $6',
 1410+ 'qp_header_line_qpul' => '$1 [ Pagina "$2" Sondage "$3" ]',
 1411+ 'qp_export_to_xls' => 'Exportar statisticas in formato XLS',
 1412+ 'qp_voices_to_xls' => 'Exportar voces in formato XLS',
 1413+ 'qp_users_answered_questions' => 'usatores respondeva al questiones',
 1414+ 'qp_func_no_such_poll' => 'Sondage non existe ($1)',
 1415+ 'qp_func_missing_question_id' => 'Per favor specifica le ID de un question existente (a partir de 1) pro le sondage $1',
 1416+ 'qp_func_invalid_question_id' => 'Question invalide id=$2 (non un numero) pro le sondage $1',
 1417+ 'qp_func_missing_proposal_id' => 'Per favor specifica un ID de proposition existente (a partir de 0) pro le sondage $1, question $2',
 1418+ 'qp_func_invalid_proposal_id' => 'ID de proposition invalide "$3" (non un numero) pro le sondage $1, question $2',
 1419+ 'qp_error_no_such_poll' => 'Sondage non existe ($1).
 1420+Verifica que le sondage ha essite declarate e salveguardate, e que le character # es usate como delimitator de adresse.',
 1421+ 'qp_error_in_question_header' => 'Titulo de question invalide: $1',
 1422+ 'qp_error_id_in_stats_mode' => 'Non pote declarar un ID del sondage in modo statistic',
 1423+ 'qp_error_dependance_in_stats_mode' => 'Non pote declarar le catena de dependentia del sondage in modo statistic',
 1424+ 'qp_error_no_stats' => 'Nulle dato statistic es disponibile, proque necuno ha ancora votate pro iste sondage (adresse=$1)',
 1425+ 'qp_error_address_in_decl_mode' => 'Non pote obtener un adresse del sondage in modo declarative',
 1426+ 'qp_error_question_not_implemented' => 'Le questiones de iste typo non es implementate: $1',
 1427+ 'qp_error_invalid_question_type' => 'Typo de question invalide: $1',
 1428+ 'qp_error_type_in_stats_mode' => 'Le typo de question non pote esser definite in modo de presentation statistic: $1',
 1429+ 'qp_error_no_poll_id' => 'Le etiquetta del sondage non ha un attributo "id" definite.',
 1430+ 'qp_error_invalid_poll_id' => 'ID de sondage invalide (id=$1).
 1431+Le ID del sondage pote continer solmente litteras, numeros e le character de spatio.',
 1432+ 'qp_error_already_used_poll_id' => 'Le ID del sondage ha ja essite usate in iste pagina (id=$1).',
 1433+ 'qp_error_invalid_dependance_value' => 'Le catena de dependentia del sondage (id=$1) ha un valor invalide del attributo de dependentia (dependance="$2")',
 1434+ 'qp_error_missed_dependance_title' => 'Le sondage (id=$1) depende de un altere sondage (id=$3) del pagina [[$2]], ma le titulo [[$2]] non ha essite trovate.
 1435+O remove le attributo de dependentia, o restaura [[$2]].',
 1436+ 'qp_error_missed_dependance_poll' => 'Le sondage (id=$1) depende de un altere sondage (id=$3) al pagina $2, ma ille sondage non existe o non ha ancora essite salveguardate.
 1437+O remove le attributo de dependentia, o crea le sondage con id=$3 al pagina $2 e salveguarda lo.
 1438+Pro salveguardar un sondage, submitte lo sin responder a alcun question de proposition.',
 1439+ 'qp_error_vote_dependance_poll' => 'Per favor vota primo pro le sondage $1.',
 1440+ 'qp_error_too_many_spans' => 'Troppo de classes de categoria pro le subcategorias definite',
 1441+ 'qp_error_unanswered_span' => 'Subcategoria sin responsa',
 1442+ 'qp_error_non_unique_choice' => 'Iste question require un responsa de proposition unic',
 1443+ 'qp_error_category_name_empty' => 'Le nomine del categoria es vacue',
 1444+ 'qp_error_proposal_text_empty' => 'Le texto del proposition es vacue',
 1445+ 'qp_error_too_few_categories' => 'Al minus duo categorias debe esser definite',
 1446+ 'qp_error_too_few_spans' => 'Cata classe de categoria require le definition de al minus duo responsas possibile',
 1447+ 'qp_error_no_answer' => 'Proposition sin responsa',
 1448+ 'qp_error_unique' => 'Pro le question de typo unique() es definite plus propositiones que responsas possibile: non pote completar',
 1449+);
 1450+
 1451+/** Indonesian (Bahasa Indonesia)
 1452+ * @author Farras
 1453+ * @author IvanLanin
 1454+ */
 1455+$messages['id'] = array(
 1456+ 'pollresults' => 'Hasil pemilihan di situs ini',
 1457+ 'qp_desc' => 'Izinkan pembuatan pemilihan',
 1458+ 'qp_desc-sp' => '[[Special:PollResults|Halaman khusus]] untuk melihat hasil pemilihan',
 1459+ 'qp_result_NA' => 'Tak dijawab',
 1460+ 'qp_result_error' => 'Kesalahan sintaks',
 1461+ 'qp_vote_button' => 'Pilih',
 1462+ 'qp_vote_again_button' => 'Ubah pilihan Anda',
 1463+ 'qp_polls_list' => 'Daftar semua pemilihan',
 1464+ 'qp_users_list' => 'Daftar semua pengguna',
 1465+ 'qp_browse_to_poll' => 'Cari ke $1',
 1466+ 'qp_browse_to_user' => 'Tamban ke $1',
 1467+ 'qp_votes_count' => '$1 {{PLURAL:$1|suara|suara}}',
 1468+ 'qp_source_link' => 'Sumber',
 1469+ 'qp_stats_link' => 'Statistik',
 1470+ 'qp_users_link' => 'Pengguna',
 1471+ 'qp_voice_link' => 'Suara pengguna',
 1472+ 'qp_voice_link_inv' => 'Suara pengguna?',
 1473+ 'qp_user_polls_link' => 'Berpartisipasi dalam $1 {{PLURAL:$1|pemilihan|pemilihan}}',
 1474+ 'qp_user_missing_polls_link' => 'Tak ada partisipasi',
 1475+ 'qp_not_participated_link' => 'Tidak berpartisipasi',
 1476+ 'qp_order_by_username' => 'Urutan menurut nama pengguna',
 1477+ 'qp_order_by_polls_count' => 'Urutan menurut jumlah pemilihan',
 1478+ 'qp_results_line_qupl' => 'Halaman "$1" Pemilihan "$2": $3',
 1479+ 'qp_results_line_qpl' => 'Halaman "$1" Pemilihan "$2": $3, $4, $5, $6',
 1480+ 'qp_header_line_qpul' => '$1 [ Halaman "$2" Pemilihan "$3" ]',
 1481+ 'qp_export_to_xls' => 'Ekspor statistik ke dalam format XLS',
 1482+ 'qp_voices_to_xls' => 'Ekspor suara ke format XLS',
 1483+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|pengguna|pengguna}} telah menjawab pertanyaan',
 1484+ 'qp_func_no_such_poll' => 'Tidak ada pemilihan ($1)',
 1485+ 'qp_func_missing_question_id' => 'Silakan masukkan suatu nomor pertanyaan yang ada (mulai dari 1) untuk pemilihan $1',
 1486+ 'qp_func_invalid_question_id' => 'Pertanyaan salah id=$2 (bukan angka) untuk pemilihan $1',
 1487+ 'qp_func_missing_proposal_id' => 'Silakan masukkan suatu nomor proposal yang ada (mulai dari 0) untuk pemilihan $1, pertanyaan $2',
 1488+ 'qp_func_invalid_proposal_id' => 'Proposal salah id=$3 (bukan angka) untuk pemilihan $1, pertanyaan $2',
 1489+ 'qp_error_no_such_poll' => 'Pemilihan tidak ditemukan ($1).
 1490+Pastikan bahwa pemilihan telah dibuat dan disimpan. Pastikan untuk menggunakan karakter penanda alamat #',
 1491+ 'qp_error_in_question_header' => 'Kepala pertanyaan tidak sah: $1',
 1492+ 'qp_error_id_in_stats_mode' => 'Tidak dapat menetapkan ID pemilihan dalam mode statistik',
 1493+ 'qp_error_dependance_in_stats_mode' => 'Tidak dapat menetapkan rantai dependensi pemilihan dalam modus statistik',
 1494+ 'qp_error_no_stats' => 'Tidak ada data statistik tersedia, karena belum ada yang memilih pada pemilihan ini (address=$1)',
 1495+ 'qp_error_address_in_decl_mode' => 'Tidak dapat memperoleh alamat pemilihan dalam modus deklarasi',
 1496+ 'qp_error_question_not_implemented' => 'Pertanyaan dengan jenis itu belum diberlakukan: $1',
 1497+ 'qp_error_invalid_question_type' => 'Jenis pertanyaan salah: $1',
 1498+ 'qp_error_type_in_stats_mode' => 'Jenis pertanyaan tak dapat ditetapkan dalam mode tampilan statistik: $1',
 1499+ 'qp_error_no_poll_id' => 'Tag pemilihan tidak memiliki atribut nomor.',
 1500+ 'qp_error_invalid_poll_id' => 'ID pemilihan salah (id=$1)
 1501+ID pemilihan hanya boleh berisi huruf, angka dan spasi',
 1502+ 'qp_error_already_used_poll_id' => 'ID pemilihan telah digunakan di halaman ini (id=$1)',
 1503+ 'qp_error_invalid_dependance_value' => 'Rantai dependensi pemilihan (nomor=$1) memiliki nilai atribut dependensi tidak sah (dependensi="$2")',
 1504+ 'qp_error_missed_dependance_title' => 'Pemilihan (nomor=$1) tergantung kepada pemilihan lain (nomor=$3) dari halaman [[$2]], tetapi judul [[$2]] tidak ditemukan.
 1505+Hapus atribut dependensi atau pulihkan [[$2]]',
 1506+ 'qp_error_missed_dependance_poll' => 'Pemilihan (id=$1) tergantung kepada pemilihan lain (id=$3) pada halaman $2, tetapi pemilihan tersebut tidak ada atau belum disimpan.
 1507+Hapus atribut dependensi atau buat dan simpan pemilihan dengan id=$3 pada halaman $2.
 1508+Untuk menyimpan pemilihan, kirimkan tanpa menjawab pertanyaan proposal.',
 1509+ 'qp_error_vote_dependance_poll' => 'Mohon pilih pada pemilihan $1 dahulu.',
 1510+ 'qp_error_too_many_spans' => 'Terlalu banyak kelas kategori untuk subkategori yang ditetapkan',
 1511+ 'qp_error_unanswered_span' => 'Subkategori belum terjawab',
 1512+ 'qp_error_non_unique_choice' => 'Pertanyaan ini membutuhkan jawaban proposal yang unik',
 1513+ 'qp_error_category_name_empty' => 'Nama kategori kosong',
 1514+ 'qp_error_proposal_text_empty' => 'Teks proposal kosong',
 1515+ 'qp_error_too_few_categories' => 'Sedikitnya dua kategori harus ditetapkan',
 1516+ 'qp_error_too_few_spans' => 'Setiap kelas kategori membutuhkan sedikitnya dua jawaban',
 1517+ 'qp_error_no_answer' => 'Proposal belum terjawab',
 1518+ 'qp_error_unique' => 'Pertanyaan dari jenis unique() memiliki lebih banyak proposal daripada kemungkinan jawaban yang didefinisikan: mustahil untuk menyelesaikan',
 1519+);
 1520+
 1521+/** Italian (Italiano) */
 1522+$messages['it'] = array(
 1523+ 'qp_result_error' => 'Errore di sintassi',
 1524+ 'qp_vote_button' => 'Vota',
 1525+ 'qp_source_link' => 'Fonte',
 1526+ 'qp_stats_link' => 'Statistiche',
 1527+ 'qp_users_link' => 'Utenti',
 1528+);
 1529+
 1530+/** Japanese (日本語)
 1531+ * @author Aotake
 1532+ * @author Fryed-peach
 1533+ * @author Whym
 1534+ */
 1535+$messages['ja'] = array(
 1536+ 'pollresults' => 'このサイトでの投票結果',
 1537+ 'qp_desc' => '投票を実施できるようにする',
 1538+ 'qp_desc-sp' => '投票結果を見るための[[Special:PollResults|特別ページ]]',
 1539+ 'qp_result_NA' => '回答されていません',
 1540+ 'qp_result_error' => '構文エラー',
 1541+ 'qp_vote_button' => '投票',
 1542+ 'qp_vote_again_button' => 'あなたの票を変更',
 1543+ 'qp_polls_list' => '全投票一覧',
 1544+ 'qp_users_list' => '全利用者一覧',
 1545+ 'qp_browse_to_poll' => '$1 を閲覧',
 1546+ 'qp_browse_to_user' => '$1 を閲覧',
 1547+ 'qp_votes_count' => '$1{{PLURAL:$1|票}}',
 1548+ 'qp_source_link' => '投票場所',
 1549+ 'qp_stats_link' => '統計',
 1550+ 'qp_users_link' => '利用者',
 1551+ 'qp_voice_link' => '利用者の声',
 1552+ 'qp_voice_link_inv' => '利用者の声?',
 1553+ 'qp_user_polls_link' => '$1件の{{PLURAL:$1|投票}}に参加',
 1554+ 'qp_user_missing_polls_link' => '参加なし',
 1555+ 'qp_not_participated_link' => '未参加',
 1556+ 'qp_order_by_username' => '利用者名順に整列',
 1557+ 'qp_order_by_polls_count' => '投票数順に整列',
 1558+ 'qp_results_line_qupl' => 'ページ「$1」投票「$2」: $3',
 1559+ 'qp_results_line_qpl' => 'ページ「$1」投票「$2」: $3、$4、$5、$6',
 1560+ 'qp_header_line_qpul' => '$1 [ ページ「$2」投票「$3」]',
 1561+ 'qp_export_to_xls' => '統計を XLS 形式でエクスポート',
 1562+ 'qp_voices_to_xls' => 'すべての投票をXLS形式でエクスポートする',
 1563+ 'qp_users_answered_questions' => '$1{{PLURAL:$1|人}}の利用者がこの質問に答えました',
 1564+ 'qp_func_no_such_poll' => 'そのような投票はありません ($1)',
 1565+ 'qp_func_missing_question_id' => '投票 $1 に存在する質問 ID を指定してください (1から始まります)',
 1566+ 'qp_func_invalid_question_id' => '投票 $1 に対して無効な質問 ID ($2 は数値ではありません)',
 1567+ 'qp_func_missing_proposal_id' => '投票 $1、質問 $2 に存在する提案 ID を指定してください (1から始まります)',
 1568+ 'qp_func_invalid_proposal_id' => '投票 $1、質問 $2 に対して無効な提案 ID ($3 は数値ではありません)',
 1569+ 'qp_error_no_such_poll' => 'そのような投票はありません ($1)。
 1570+その投票が宣言され保存されていること、およびアドレス区切り記号 # を使っていることを確認してください。',
 1571+ 'qp_error_in_question_header' => '無効な質問見出し: $1',
 1572+ 'qp_error_id_in_stats_mode' => '統計モードでは投票の ID を宣言できません',
 1573+ 'qp_error_dependance_in_stats_mode' => '統計モードでは投票の依存性チェーンを宣言できません',
 1574+ 'qp_error_no_stats' => 'まだ誰もこの投票に投票していないので、統計データはありません (アドレス $1)',
 1575+ 'qp_error_address_in_decl_mode' => '宣言モードでは投票のアドレスを取得できません',
 1576+ 'qp_error_question_not_implemented' => 'そのタイプの質問は実装されていません: $1',
 1577+ 'qp_error_invalid_question_type' => '無効な質問タイプ: $1',
 1578+ 'qp_error_type_in_stats_mode' => '質問タイプは統計表示モードでは定義できません: $1',
 1579+ 'qp_error_no_poll_id' => '投票タグに id 属性がありません。',
 1580+ 'qp_error_invalid_poll_id' => '無効な投票 ID (id=$1)。
 1581+投票 ID はアルファベット、数字、スペースのみを含むことができます。',
 1582+ 'qp_error_already_used_poll_id' => 'その投票 ID は既にこのページで使われています (id=$1)。',
 1583+ 'qp_error_invalid_dependance_value' => 'この投票 (id=$1) の依存性チェーンには依存性属性に不正な値があります (dependance="$2")',
 1584+ 'qp_error_missed_dependance_title' => 'この投票 (id=$1) はページ [[$2]] の別の投票 (id=$3) に依存していますが、ページ名 [[$2]] は見つかりませんでした。依存性属性を削除するか、[[$2]] を復帰させてください',
 1585+ 'qp_error_missed_dependance_poll' => 'この投票 (id=$1) はページ $2 の別の投票 (id=$3) に依存していますが、その投票が存在しないかまだ保存されていません。依存性属性を削除するか、ページ $2 で id=$3 の投票を作成してください。投票を保存するには、どの提案質問にも答えずに投稿してください。',
 1586+ 'qp_error_vote_dependance_poll' => '初めに投票 $1 に投票してください。',
 1587+ 'qp_error_too_many_spans' => 'このサブカテゴリーに対して定義されているカテゴリーが多すぎます',
 1588+ 'qp_error_unanswered_span' => '未回答のサブカテゴリー',
 1589+ 'qp_error_non_unique_choice' => 'この質問には答えとして独自の提案が必要です',
 1590+ 'qp_error_category_name_empty' => 'カテゴリー名が空です',
 1591+ 'qp_error_proposal_text_empty' => '提案文が空です',
 1592+ 'qp_error_too_few_categories' => '最低でも2つのカテゴリーが定義されなければなりません',
 1593+ 'qp_error_too_few_spans' => 'どのカテゴリーも最低でも2つの回答がとり得るように定義されなければなりません',
 1594+ 'qp_error_no_answer' => '未回答の提案',
 1595+ 'qp_error_unique' => 'タイプが unique() の質問には回答可能なものより多くの質問が定義されています。すべてに記入することはできません',
 1596+);
 1597+
 1598+/** Colognian (Ripoarisch)
 1599+ * @author Purodha
 1600+ */
 1601+$messages['ksh'] = array(
 1602+ 'pollresults' => 'Wat bei dä Affschtemmunge en heh däm Wiki eruß gekumme es',
 1603+ 'qp_parentheses' => '(<code>$1</code>)',
 1604+ 'qp_full_category_name' => '$1(<code>$2</code>)',
 1605+ 'qp_desc' => 'Määt Affschtemmunge müjjelesch.',
 1606+ 'qp_desc-sp' => '[[Special:PollResults|{{int:nstab-special}}]] för aanzeloore, wat bei Affschtemmunge erus kohm.',
 1607+ 'qp_result_NA' => 'Kein Antwoot jejovve',
 1608+ 'qp_result_error' => 'Ene Fähler en dä Syntax es opjefalle',
 1609+ 'qp_vote_button' => 'Afschtemme!',
 1610+ 'qp_vote_again_button' => 'Donn Ding Shtemm ändere',
 1611+ 'qp_polls_list' => 'Alle Affschtemmunge opleste',
 1612+ 'qp_users_list' => 'Alle Metmaacher opleste',
 1613+ 'qp_browse_to_poll' => 'Bes $1 bläddere',
 1614+ 'qp_browse_to_user' => 'Bes $1 bläddere',
 1615+ 'qp_votes_count' => '{{PLURAL:$1|ein Schtemm|$1 Schtemme|Kein Schtemm}}',
 1616+ 'qp_source_link' => 'Beschrevve',
 1617+ 'qp_stats_link' => 'Schtatistike',
 1618+ 'qp_users_link' => 'Metmaacher',
 1619+ 'qp_voice_link' => 'Enem Metmaacher sing Stemm',
 1620+ 'qp_voice_link_inv' => 'Enem Metmaacher sing Stemm?',
 1621+ 'qp_user_polls_link' => 'Hät beij {{PLURAL:$1|eine Affschtemmung|$1 Affschtemmunge|keine Affschtemmung}} metjemaat',
 1622+ 'qp_user_missing_polls_link' => 'Keine hät metjemaat',
 1623+ 'qp_not_participated_link' => 'Nit metjmaat',
 1624+ 'qp_order_by_username' => 'Noh de Metmaacher iere Name zoteere',
 1625+ 'qp_order_by_polls_count' => 'Noh e Affschtemmunge ier Zahle zoteere',
 1626+ 'qp_results_line_qupl' => 'Sigg „$1“ Affschtemmung „$2“: $3',
 1627+ 'qp_results_line_qpl' => 'Sigg „$1“ Affschtemmung „$2“: $3, $4, $5, $6',
 1628+ 'qp_header_line_qpul' => '$1 [ Sigg „$2“ Affschtemmung „$3“ ]',
 1629+ 'qp_results_line_qpul' => '$1: $2',
 1630+ 'qp_header_line_qucl' => '$1. $2<br />$3 ??? $4',
 1631+ 'qp_results_line_qucl' => '$1: $2 $3',
 1632+ 'qp_export_to_xls' => 'Donn de Schtatistike em <i lang="en">XLS</i> Fommaat äxpotteere',
 1633+ 'qp_voices_to_xls' => 'Donn de Shtemme em <i lang="en">XLS</i> Fommaat äxpotteere',
 1634+ 'qp_users_answered_questions' => '{{PLURAL:$1|Eine|$1|Keine}} Metmaacher {{PLURAL:$1|hät|han|hät}} op di Froore jeantwoot \\',
 1635+ 'qp_func_no_such_poll' => 'Esu en Affschtemmung ham_mer nit ($1)',
 1636+ 'qp_func_missing_question_id' => 'Bes esu joot, un jif en Kännong aan, di et jitt,för en Frooch (vun 1 aan jezallt) för de Affschtemmung $1',
 1637+ 'qp_func_invalid_question_id' => 'Dat es en onjöltijje Frooch (<code lang="en">id=$2</code>), nämmlesch kein Nommer, för de Affschtemmung $1',
 1638+ 'qp_func_missing_proposal_id' => 'Bes esu joot, un jif en Kännong aan, di et jitt,för ene Vörschlaach (vun 0 aan jezallt) för de Affschtemmung $1 un de Frooch $2',
 1639+ 'qp_func_invalid_proposal_id' => 'Dat es en onjöltijje Kännong för ene Vörschlaach (<code lang="en">id=$3</code>), nämmlesch kein Nommer, för de Affschtemmung $1 un de Frooch $2',
 1640+ 'qp_error_no_such_poll' => 'Mer hann kein esu en Affschtemmung ($1).
 1641+Bes sescher, dat di Affschtemmung wennjerescht es un affjeschpeijschert, un bes sescher, dat De dat Bejränzungszeijsche # en dä Addräß bruche deihß.',
 1642+ 'qp_error_in_question_header' => 'Dat es en onjöltijje Övverschreff vun en Frooch: $1',
 1643+ 'qp_error_id_in_stats_mode' => 'Mer künne kein Kännung (<code lang="en">id=</code>) fö di Affschtemmung en de Enschtellung för de Schtatistike faßlääje',
 1644+ 'qp_error_dependance_in_stats_mode' => 'Mer künne kein Kett vun Affhängeschkeite fö di Affschtemmung en de Enschtellung för de Schtatistike faßlääje',
 1645+ 'qp_error_no_stats' => 'Ner han kein schtatistesche Daate, weil noch keiner för heh di Affjeschtemmung affjeschtemmp hät. (<code>address=$1</code>)',
 1646+ 'qp_error_address_in_decl_mode' => 'Mer künne kein Addräß vun dä Affschtemmung beij em Fäßlääje vun de Enschtellung un Eijeschaffte krijje',
 1647+ 'qp_error_question_not_implemented' => 'Froore vun dä Zoot sin nit em Projramm: $1',
 1648+ 'qp_error_invalid_question_type' => 'Dat es en onjöltijje Zoot Frooch: $1',
 1649+ 'qp_error_type_in_stats_mode' => 'Froore ier Zoot kam_mer nit en de Enschtellung för de Schtatistike faßlääje: $1',
 1650+ 'qp_error_no_poll_id' => 'Dä Befähl för en Affschtemmung hät kein Kännung (<code>id=</code>) aanjejovve.',
 1651+ 'qp_error_invalid_poll_id' => 'Dat es en onjöltijje Kännung för en Affschtemmung (<code>id=$1</code>)
 1652+Doh dörfe nur Bochschtabe, Zeffere, un Affschtänd dren sin.',
 1653+ 'qp_error_already_used_poll_id' => 'Di Kännung för en Affschtemmung (<code>id=$1</code>) es ald ens op heh dä Sigg jebruch woode.',
 1654+ 'qp_error_invalid_dependance_value' => 'Di Affschtemmung fö di Kännung (<code>id=$1</code>) ier Kett vun Afhängeschkeite hät en onjöltesch Eijeschaff (dependance="$2")',
 1655+ 'qp_error_missed_dependance_title' => 'Di Affschtemmung met dä Kännung (<code>id=$1</code>) hängk aff vun ene andere Affschtemmung met dä Kännung (<code>id=$3</code>) op dä Sigg „[[$2]]“, ävver di ham_mer nit jefonge.
 1656+Entweder donn die Eijeschaff met dä Affhängeschkeit fott, udder holl di Sigg „[[$2]]“ wider en et Wiki,',
 1657+ 'qp_error_missed_dependance_poll' => 'Di Affschtemmung met dä Kännung (<code>id=$1</code>) hängk aff vun ene andere Affschtemmung met dä Kännung (<code>id=$3</code>) op dä Sigg „$2“, ävver di Affschtemmung ham_mer doh nit jefonge.
 1658+Entweder donn die Eijeschaff met dä Affhängeschkeit fott, udder donn en Affschtemmung met dä Kännung (<code>id=$3</code>) op di Sigg „$2“ un donn se afschpeijschere.
 1659+Öm en Afschtemmung reschtesch ze schpeijschere, donn dat, der ohne op en Frooch jeantwoot ze han.',
 1660+ 'qp_error_vote_dependance_poll' => 'Bes esu joot un donn övver „$1“ et eets affschtemme',
 1661+ 'qp_error_too_many_spans' => 'Et sinn_er zoh vill Zoote-Jroppe för de Ongerknubbelle aanjejovve',
 1662+ 'qp_error_unanswered_span' => 'Ongerknubbel oohne Antwoot',
 1663+ 'qp_error_non_unique_choice' => 'Di Frooch bruch ene einzelne Vörschlaach för en Antwoot',
 1664+ 'qp_error_category_name_empty' => 'Dä Name för dä Knubbel es läddesch',
 1665+ 'qp_error_proposal_text_empty' => 'En däm Täx för dä Vörschlaach schteiht nix dren',
 1666+ 'qp_error_too_few_categories' => 'Winnischsdens zweij Knubbelle möße doh sin',
 1667+ 'qp_error_too_few_spans' => 'För jeede Zoote-Knubbel möte winnischsdens zweij müjjelesche Ongerzoote doh sin',
 1668+ 'qp_error_no_answer' => 'Ene Vörschlaach ohne Antwoot',
 1669+ 'qp_error_unique' => 'En Frooch vun dä Zoot <code>unique()</code> hät mieh Vörschlääsch, wi müjjelesche Antwoote aanjejovve: Dat kam_mer nit ußfölle.',
 1670+);
 1671+
 1672+/** Luxembourgish (Lëtzebuergesch)
 1673+ * @author Robby
 1674+ */
 1675+$messages['lb'] = array(
 1676+ 'pollresults' => 'Resultater vun der Ëmfro op dësem Site',
 1677+ 'qp_desc' => "Erlaabt et Ëmfroen z'organiséieren",
 1678+ 'qp_desc-sp' => "[[Special:PollResults|Spezialsäit]] fir d'Resultater vun der Ëmfro ze gesinn",
 1679+ 'qp_result_NA' => 'Keng Äntwert',
 1680+ 'qp_result_error' => 'Syntaxfeeler',
 1681+ 'qp_vote_button' => 'Ofstëmmen',
 1682+ 'qp_vote_again_button' => 'Ännert Är Ofstëmmung',
 1683+ 'qp_polls_list' => 'All Ëmfroe weisen',
 1684+ 'qp_users_list' => 'All Benotzer opzielen',
 1685+ 'qp_browse_to_poll' => 'Op $1 goen',
 1686+ 'qp_browse_to_user' => 'Bäi de(n) $1 goen',
 1687+ 'qp_votes_count' => '$1 {{PLURAL:$1|Stëmm|Stëmmen}}',
 1688+ 'qp_source_link' => 'Quell',
 1689+ 'qp_stats_link' => 'Statistiken',
 1690+ 'qp_users_link' => 'Benotzer',
 1691+ 'qp_voice_link' => 'Stëmm vum Benotzer',
 1692+ 'qp_voice_link_inv' => 'Stëmm vum Benotzer?',
 1693+ 'qp_user_polls_link' => 'huet {{PLURAL:$1|un enger Ëmfro|u(n) $1 Ëmfroen}} deelgeholl',
 1694+ 'qp_user_missing_polls_link' => 'Keng Bedeelegung',
 1695+ 'qp_not_participated_link' => 'Net matgemaach',
 1696+ 'qp_order_by_username' => 'Nom Benotzernumm zortéieren',
 1697+ 'qp_order_by_polls_count' => 'No der Zuel vun den Ënfroen zortéieren',
 1698+ 'qp_results_line_qupl' => 'Säit "$1" Ëmfro "$2": $3',
 1699+ 'qp_results_line_qpl' => 'Säit "$1" Ëmfro "$2": $3, $4, $5, $6',
 1700+ 'qp_header_line_qpul' => '$1 [ Säit "$2" Ëmfro "$3" ]',
 1701+ 'qp_export_to_xls' => "Exportéiert d'Statistiken am XLS-Format",
 1702+ 'qp_users_answered_questions' => "$1 {{PLURAL:$1|Benotzer huet|Benotzer hun}} op d'Froe geäntwert",
 1703+ 'qp_func_no_such_poll' => 'Et gëtt keng esou eng Ëmfro ($1)',
 1704+ 'qp_func_missing_question_id' => "Gitt w.e.g. d'Id vun enger Fro un déi et gëtt (ugefaang mat 1) fir d'Ëmfro $1",
 1705+ 'qp_func_invalid_question_id' => "id vun der Fro=$2 ass net valabel (et ass keng Zuel) fir d'Ëmfro $1",
 1706+ 'qp_error_in_question_header' => 'Iwwerschrëft vun der Fro net valabel: $1',
 1707+ 'qp_error_no_stats' => 'Et gëtt keng statistesch Donnéeën, well bis elo (Adress=$1) kee fir dës Ëmfro gestëmmt huet.',
 1708+ 'qp_error_question_not_implemented' => 'Froe vun esou engem Typ sinn net implementéiert: $1',
 1709+ 'qp_error_invalid_question_type' => 'Net-valabelen Typ vu Fro: $1',
 1710+ 'qp_error_already_used_poll_id' => "D'Ëmfro-Nummer (poll id) gouf op dëser Säit scho benotzt (id=$1).",
 1711+ 'qp_error_vote_dependance_poll' => "Stëmmt w.e.g. fir d'éischt bäi der Ëmfro $1 of.",
 1712+ 'qp_error_unanswered_span' => 'Ënnerkategorie ouni Äntwert',
 1713+ 'qp_error_non_unique_choice' => 'Dës Fro brauch eng Äntwert mat enger eenzeger Propos',
 1714+ 'qp_error_category_name_empty' => 'Den Numm vun der Kategorie ass eidel',
 1715+ 'qp_error_proposal_text_empty' => 'Den Text vum Virschlag ass eidel',
 1716+ 'qp_error_too_few_categories' => 'Et musse mindestens zwou Kategorien definéiert sinn',
 1717+ 'qp_error_too_few_spans' => 'All Kategoriegrupp muss mindestens aus zwou Ënnerkategorie bestoen',
 1718+ 'qp_error_no_answer' => 'Propos ouni Äntwert',
 1719+);
 1720+
 1721+/** Malagasy (Malagasy)
 1722+ * @author Jagwar
 1723+ */
 1724+$messages['mg'] = array(
 1725+ 'qp_export_to_xls' => 'Avoaka rakitra XLS ny statistika',
 1726+);
 1727+
 1728+/** Macedonian (Македонски)
 1729+ * @author Bjankuloski06
 1730+ * @author Brest
 1731+ */
 1732+$messages['mk'] = array(
 1733+ 'pollresults' => 'Резултати од анкетите на ова мрежно место',
 1734+ 'qp_desc' => 'Овозможува создавање на анкети',
 1735+ 'qp_desc-sp' => '[[Special:PollResults|Специјална страница]] за преглед на резултати од анкетите',
 1736+ 'qp_result_NA' => 'Без одговор',
 1737+ 'qp_result_error' => 'Синтаксна грешка',
 1738+ 'qp_vote_button' => 'Гласај',
 1739+ 'qp_vote_again_button' => 'Прегласај',
 1740+ 'qp_polls_list' => 'Список на сите анкети',
 1741+ 'qp_users_list' => 'Список на сите корисници',
 1742+ 'qp_browse_to_poll' => 'Прелистај до $1',
 1743+ 'qp_browse_to_user' => 'Прелистај до $1',
 1744+ 'qp_votes_count' => '$1 {{PLURAL:$1|глас|гласа}}',
 1745+ 'qp_source_link' => 'Извор',
 1746+ 'qp_stats_link' => 'Статистики',
 1747+ 'qp_users_link' => 'Корисници',
 1748+ 'qp_voice_link' => 'Кориснички глас',
 1749+ 'qp_voice_link_inv' => 'Кориснички глас?',
 1750+ 'qp_user_polls_link' => 'Учествувал во $1 {{PLURAL:$1|анкета|анкети}}',
 1751+ 'qp_user_missing_polls_link' => 'Без одзив',
 1752+ 'qp_not_participated_link' => 'Не учествувале',
 1753+ 'qp_order_by_username' => 'Подреди по корисничко име',
 1754+ 'qp_order_by_polls_count' => 'Подреди по број на анкети',
 1755+ 'qp_results_line_qupl' => 'Страница „$1“ Анкета „$2“: $3',
 1756+ 'qp_results_line_qpl' => 'Страница „$1“ Анкета „$2“: $3, $4, $5, $6',
 1757+ 'qp_header_line_qpul' => '$1 [ Страница „$2“ Анкета „$3“ ]',
 1758+ 'qp_export_to_xls' => 'Извези ги статистиките во XLS формат',
 1759+ 'qp_voices_to_xls' => 'Извези гласови во XLS-формат',
 1760+ 'qp_users_answered_questions' => 'На прашањата $1 {{PLURAL:$1|одговорил $1 корисник|одговориле $1 корисници}}',
 1761+ 'qp_func_no_such_poll' => 'Нема таква анкета ($1)',
 1762+ 'qp_func_missing_question_id' => 'Назначете постоечка назнака за прашањето (започнувајќи со 1) за анкетата $1',
 1763+ 'qp_func_invalid_question_id' => 'Неважечка назнака на прашањето id=$2 (не е број) за анкетата $1',
 1764+ 'qp_func_missing_proposal_id' => 'Назначете постоечки id-број за предлогот (започнувајќи со 0) за анкетата $1, прашање $2',
 1765+ 'qp_func_invalid_proposal_id' => 'Неважечки предлог id=$3 на предлог (не е број) за анкетата $1, прашање $2',
 1766+ 'qp_error_no_such_poll' => 'Нема таква анкета ($1).
 1767+Проверете дали анкетата е утврдена и зачувана, и осигурајте се дека во адресата користите разграничен знак #',
 1768+ 'qp_error_in_question_header' => 'Погрешно заглавие за прашањето: $1',
 1769+ 'qp_error_id_in_stats_mode' => 'Не може да се утврди ID-број за анкетата во статистички режим',
 1770+ 'qp_error_dependance_in_stats_mode' => 'Не можете да утврдите ланец на зависност за анкетата во статистички режим',
 1771+ 'qp_error_no_stats' => 'Нема достапни статистички податоци, бидејќи сè уште никој нема гласано на оваа анкета (address=$1)',
 1772+ 'qp_error_address_in_decl_mode' => 'Не може да се дава адреса на анкетата во утврдувачки режим',
 1773+ 'qp_error_question_not_implemented' => 'Прашањата од таков тип не се имплементираат: $1',
 1774+ 'qp_error_invalid_question_type' => 'Неважечки тип на прашање: $1',
 1775+ 'qp_error_type_in_stats_mode' => 'Не може да се определува тип на прашање во статистички режим: $1',
 1776+ 'qp_error_no_poll_id' => 'Ознаката на анкетата нема определено атрибут за id-број.',
 1777+ 'qp_error_invalid_poll_id' => 'Неважечки id-број на анкетата (id=$1).
 1778+id-бројот може да содржи само букви, бројки и знак за место (проред)',
 1779+ 'qp_error_already_used_poll_id' => 'id-бројот на анкетата веќе се користи на оваа страница (id=$1).',
 1780+ 'qp_error_invalid_dependance_value' => 'Ланецот на зависност за анкетата (id=$1) има неважечка вредност во атрибутот за зависност (dependance="$2")',
 1781+ 'qp_error_missed_dependance_title' => 'Анкетата (id=$1) е зависна од друга анкета (id=$3) од страницата [[$2]], но насловот [[$2]] не беше најден.
 1782+Или отстранете го атрибутот за зависност, или вратете ја страницата [[$2]]',
 1783+ 'qp_error_missed_dependance_poll' => 'Анкетата (id=$1) е зависна од друга анкета (id=$3) на страницата $2, но таа анкета не постои или сè уште не е зачувана.
 1784+Или отстранете го атрибутот за зависност, или создајде анкета со id=$3 на страницата $2 и зачувајте ја.
 1785+За да зачувате анкета, притиснете на „Гласај“ но притоа без да одговорите на ниеден предлог (прашање).',
 1786+ 'qp_error_vote_dependance_poll' => 'Прво одговорете на анкетата $1.',
 1787+ 'qp_error_too_many_spans' => 'Премногу категориски групи за вкупниот број на утврдени поткатегории',
 1788+ 'qp_error_unanswered_span' => 'Неодговорена поткатегорија',
 1789+ 'qp_error_non_unique_choice' => 'Ова прашање бара одговор кој не е даден претходно',
 1790+ 'qp_error_category_name_empty' => 'Името на категоријата е празно',
 1791+ 'qp_error_proposal_text_empty' => 'Текстот за предлог е празен',
 1792+ 'qp_error_too_few_categories' => 'Мора да определите барем две категории',
 1793+ 'qp_error_too_few_spans' => 'Секоја класа на категории бара да определите барем два можни одговора',
 1794+ 'qp_error_no_answer' => 'Неодговорен предлог',
 1795+ 'qp_error_unique' => 'Прашањето од типот unique() има определено повеќе предлози од можни одговори: одговарањето на прашањето е неизводливо',
 1796+);
 1797+
 1798+/** Malay (Bahasa Melayu)
 1799+ * @author Anakmalaysia
 1800+ */
 1801+$messages['ms'] = array(
 1802+ 'qp_source_link' => 'Sumber',
 1803+);
 1804+
 1805+/** Dutch (Nederlands)
 1806+ * @author McDutchie
 1807+ * @author Purodha
 1808+ * @author Siebrand
 1809+ */
 1810+$messages['nl'] = array(
 1811+ 'pollresults' => 'Resultaten van de stemmingen op deze site',
 1812+ 'qp_desc' => 'Maakt het aanmaken van peilingen mogelijk',
 1813+ 'qp_desc-sp' => '[[Special:PollResults|Speciale pagina]] voor het bekijken van de resultaten van peilingen',
 1814+ 'qp_result_NA' => 'Niet beantwoord',
 1815+ 'qp_result_error' => 'Er zit een fout in de syntaxis',
 1816+ 'qp_vote_button' => 'Stemmen',
 1817+ 'qp_vote_again_button' => 'Stem wijzigen',
 1818+ 'qp_polls_list' => 'Alle peilingen weergeven',
 1819+ 'qp_users_list' => 'Alle gebruikers weergeven',
 1820+ 'qp_browse_to_poll' => 'Naar de peiling $1',
 1821+ 'qp_browse_to_user' => 'Naar gebruiker $1',
 1822+ 'qp_votes_count' => '$1 {{PLURAL:$1|stem|stemmen}}',
 1823+ 'qp_source_link' => 'Bron',
 1824+ 'qp_stats_link' => 'Statistieken',
 1825+ 'qp_users_link' => 'Gebruikers',
 1826+ 'qp_voice_link' => 'Gebruikersstem',
 1827+ 'qp_voice_link_inv' => 'Gebruikersstem?',
 1828+ 'qp_user_polls_link' => 'Heeft deelgenomen aan $1 {{PLURAL:$1|peiling|peilingen}}',
 1829+ 'qp_user_missing_polls_link' => 'Geen deelname',
 1830+ 'qp_not_participated_link' => 'Niet deelgenomen',
 1831+ 'qp_order_by_username' => 'Sorteren op gebruikersnaam',
 1832+ 'qp_order_by_polls_count' => 'Sorteren op peilingenaantal',
 1833+ 'qp_results_line_qupl' => 'Pagina "$1", peiling "$2": $3',
 1834+ 'qp_results_line_qpl' => 'Pagina "$1", peiling "$2": $3, $4, $5, $6',
 1835+ 'qp_header_line_qpul' => '$1 [ pagina "$2", peiling "$3" ]',
 1836+ 'qp_header_line_qucl' => '$1. $2<br />$3 ??? $4',
 1837+ 'qp_export_to_xls' => 'Statistieken naar XLS-formaat exporteren',
 1838+ 'qp_voices_to_xls' => 'Stemmen in XLS-formaat exporteren',
 1839+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|gebruiker heeft|gebruikers hebben}} de vragen beantwoord',
 1840+ 'qp_func_no_such_poll' => 'Die peiling bestaat niet ($1)',
 1841+ 'qp_func_missing_question_id' => 'Geef alstublieft een vraag-ID op (begin bij 1) voor de peiling $1',
 1842+ 'qp_func_invalid_question_id' => 'Ongeldig vraag-ID ($2 - geen getal) voor de peiling $1',
 1843+ 'qp_func_missing_proposal_id' => 'Geef alstublieft een voorstel-ID op (begin bij 0) voor de peiling $1, vraag $2',
 1844+ 'qp_func_invalid_proposal_id' => 'Ongeldig voorstel-ID ($3 - geen getal) voor de peiling $1, vraag $2',
 1845+ 'qp_error_no_such_poll' => 'Die peiling bestaat niet ($1).
 1846+Zorg dat de peiling is ingesteld en opgeslagen, en dat het adresscheidingsteken "#" is gebruikt.',
 1847+ 'qp_error_in_question_header' => 'Ongeldige kop voor vraag: $1',
 1848+ 'qp_error_id_in_stats_mode' => 'Het is niet mogelijk een ID voor de peiling te declareren in de statistische modus',
 1849+ 'qp_error_dependance_in_stats_mode' => 'Het is niet mogelijk een afhankelijkheidsketen voor de peiling te declareren in de statistische modus',
 1850+ 'qp_error_no_stats' => 'Er zijn geen statistische gegevens beschikbaar omdat er nog geen gebruikers hebben gestemd in deze peiling (adres $1)',
 1851+ 'qp_error_address_in_decl_mode' => 'Het is niet mogelijk een adres van de peiling op te vragen in de declaratiemodus',
 1852+ 'qp_error_question_not_implemented' => 'Vragen van dit type zijn niet beschikbaar: $1',
 1853+ 'qp_error_invalid_question_type' => 'Ongeldig vraagtype: $1',
 1854+ 'qp_error_type_in_stats_mode' => 'Het vraagtype kan niet gedefinieerd wordne in de statistische weergavemodus: $1',
 1855+ 'qp_error_no_poll_id' => 'De eigenschap "id" is niet gedefinieerd voor de peiling.',
 1856+ 'qp_error_invalid_poll_id' => 'Ongeldig peiling-ID ($1)
 1857+Het ID mag alleen letters, cijfers en spaties bevatten.',
 1858+ 'qp_error_already_used_poll_id' => 'Het peilingsnummer wordt al gebruikt op deze pagina (ID $1)',
 1859+ 'qp_error_invalid_dependance_value' => 'De peilingafhankelijkheidsketen (ID $1) heeft een ongeldige waarde voor de afhankelijkheidseigenschap (dependance "$2")',
 1860+ 'qp_error_missed_dependance_title' => 'De peiling (ID $1) is afhankelijk van een andere peiling (ID $3) op pagina [[$2]], maar de pagina [[$2]] bestaat niet.
 1861+Verwijder de eigenschap "dependance" of plaats de pagina [[$2]] terug.',
 1862+ 'qp_error_missed_dependance_poll' => 'De peiling (ID $1) is afhankelijk van een andere peiling (ID $3) op pagina $2, maar die peiling bestaat niet of is nog niet opgeslagen.
 1863+Verwijder de eigenschap "dependance" of maak een peiling aan met het ID $3 op pagina $2.
 1864+Sla een peiling op door deze op te slaan zonder dat enig voorstel is beantwoord.',
 1865+ 'qp_error_vote_dependance_poll' => 'Stem alstublieft eerst in de peiling $1.',
 1866+ 'qp_error_too_many_spans' => 'Er zijn te veel categorieklassen voor de subcategorieën gedefinieerd',
 1867+ 'qp_error_unanswered_span' => 'Onbeantwoorde subcategorie',
 1868+ 'qp_error_non_unique_choice' => 'Voor deze vraag is een uniek voorstelantwoord nodig',
 1869+ 'qp_error_category_name_empty' => 'Er is geen categorienaam opgegeven',
 1870+ 'qp_error_proposal_text_empty' => 'Er is geen voorsteltekst opgegeven',
 1871+ 'qp_error_too_few_categories' => 'Er moeten tenminste twee categorieën gedefinieerd worden.',
 1872+ 'qp_error_too_few_spans' => 'Voor iedere categorieklasse dienen tenminste twee mogelijk antwoorden gedefinieerd te zijn',
 1873+ 'qp_error_no_answer' => 'Onbeantwoord voorstel',
 1874+ 'qp_error_unique' => 'Voor de vraag van het type unique() zijn meer voorstellen dan mogelijke antwoorden gedefinieerd. Dat is niet recht te breien.',
 1875+);
 1876+
 1877+/** Norwegian Nynorsk (‪Norsk (nynorsk)‬)
 1878+ * @author Gunnernett
 1879+ */
 1880+$messages['nn'] = array(
 1881+ 'qp_result_NA' => 'Ikkje svar',
 1882+ 'qp_users_list' => 'List opp alle brukarar',
 1883+ 'qp_source_link' => 'Kjelde',
 1884+ 'qp_stats_link' => 'Statistikk',
 1885+);
 1886+
 1887+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 1888+ * @author Nghtwlkr
 1889+ */
 1890+$messages['no'] = array(
 1891+ 'pollresults' => 'Resultater fra spørreundersøkelsen på denne siden',
 1892+ 'qp_desc' => 'Tillater opprettelse av spørreundersøkelser',
 1893+ 'qp_desc-sp' => '[[Special:PollResults|Spesialside]] for visning av resultater fra spørreundersøkelsene',
 1894+ 'qp_result_NA' => 'Ikke besvart',
 1895+ 'qp_result_error' => 'Syntaksfeil',
 1896+ 'qp_vote_button' => 'Stem',
 1897+ 'qp_vote_again_button' => 'Endre din stemme',
 1898+ 'qp_polls_list' => 'List opp alle spørreundersøkelser',
 1899+ 'qp_users_list' => 'List opp alle brukere',
 1900+ 'qp_browse_to_poll' => 'Bla igjennom til $1',
 1901+ 'qp_browse_to_user' => 'Bla igjennom til $1',
 1902+ 'qp_votes_count' => '{{PLURAL:$1|Én stemme|$1 stemmer}}',
 1903+ 'qp_source_link' => 'Kilde',
 1904+ 'qp_stats_link' => 'Statistikk',
 1905+ 'qp_users_link' => 'Brukere',
 1906+ 'qp_voice_link' => 'Brukerstemme',
 1907+ 'qp_voice_link_inv' => 'Brukerstemme?',
 1908+ 'qp_user_polls_link' => 'Deltok i {{PLURAL:$1|én spørreundersøkelse|$1 spørreundersøkelser}}',
 1909+ 'qp_user_missing_polls_link' => 'Ingen deltakelse',
 1910+ 'qp_not_participated_link' => 'Ikke deltatt',
 1911+ 'qp_order_by_username' => 'Sorter etter brukernavn',
 1912+ 'qp_order_by_polls_count' => 'Sorter etter antall spørreundersøkelser',
 1913+ 'qp_results_line_qupl' => 'Side «$1» Spørreundersøkelse «$2»: $3',
 1914+ 'qp_results_line_qpl' => 'Side «$1» Spørreundersøkelse «$2»: $3, $4, $5, $6',
 1915+ 'qp_header_line_qpul' => '$1 [ Side «$2» Spørreundersøkelse «$3» ]',
 1916+ 'qp_export_to_xls' => 'Eksporter statistikk til XLS-format',
 1917+ 'qp_voices_to_xls' => 'Eksporter stemmer til XLS-format',
 1918+ 'qp_users_answered_questions' => '{{PLURAL:$1|Én bruker|$1 brukere}} besvarte spørsmålene',
 1919+ 'qp_func_no_such_poll' => 'Ingen slik spørreundersøkelse ($1)',
 1920+ 'qp_func_missing_question_id' => 'Vennligst oppgi en eksisterende spørsmåls-ID (starter fra 1) for spørreundersøkelsen $1',
 1921+ 'qp_func_invalid_question_id' => 'Ugyldig spørsmåls-id=$2 (ikke et tall) for spørreundersøkelsen $1',
 1922+ 'qp_func_missing_proposal_id' => 'Vennligst oppgi en eksisterende forslags-id (starter fra 0) for spørreundersøkelsen $1, spørsmål $2',
 1923+ 'qp_func_invalid_proposal_id' => 'Ugyldig forslags-id=$3 (ikke et tall) for spørreundersøkelsen $1, spørsmål $2',
 1924+ 'qp_error_no_such_poll' => 'Ingen slik spørreundersøkelse ($1).
 1925+Vær sikker på at spørreundersøkelsen ble deklarert og lagret, vær også sikker på at tegnet # blir brukt som addresse avgrenser',
 1926+ 'qp_error_in_question_header' => 'Ugyldig spørsmålsoverskrift: $1',
 1927+ 'qp_error_id_in_stats_mode' => 'Kan ikke deklarere en ID for spørreundersøkelsen i statistikkmodus',
 1928+ 'qp_error_dependance_in_stats_mode' => 'Kan ikke deklarere kjede av avhengigheter for spørreundersøkelsen i statistikkmodus',
 1929+ 'qp_error_no_stats' => 'Ingen statistiske data er tilgjengelig fordi ingen har stemt for denne spørreundersøkelsen enda (address=$1)',
 1930+ 'qp_error_address_in_decl_mode' => 'Kan ikke få en adresse for spørreundersøkelsen i deklareringsmodus',
 1931+ 'qp_error_question_not_implemented' => 'Spørsmål av en slik type er ikke implementert: $1',
 1932+ 'qp_error_invalid_question_type' => 'Ugyldig spørsmålstype: $1',
 1933+ 'qp_error_type_in_stats_mode' => 'Spørsmålstypen kan ikke defineres i statistisk visningsmodus: $1',
 1934+ 'qp_error_no_poll_id' => 'Spørreundersøkelsesmerkelappen har ingen definerte id-atributter.',
 1935+ 'qp_error_invalid_poll_id' => 'Ugyldig spørreundersøkelses-id (id=$1).
 1936+Spørreundersøkelses-id kan kun inneholde bokstaver, tall og mellomrom',
 1937+ 'qp_error_already_used_poll_id' => 'Spørreundersøkelses-id-en har allerede blitt brukt på denne siden (id=$1).',
 1938+ 'qp_error_invalid_dependance_value' => 'Spørreundersøkelsens (id=$1) kjede av avhengigheter har en ugyldig verdi av avhengighetsatributter (dependance="$2")',
 1939+ 'qp_error_missed_dependance_title' => 'Spørreundersøkelsen (id=$1) avhenger av en annen spørreundersøkelse (id=$3) fra side [[$2]], men tittelen [[$2]] ble ikke funnet.
 1940+Enten fjern avhengighetsatributten, eller gjenopprett [[$2]]',
 1941+ 'qp_error_missed_dependance_poll' => 'Spørreundersøkelsen (id=$1) avhenger av en annen spørreundersøkelse (id=$3) på side $2, men den spørreundersøkelsen finnes ikke eller har ikke blitt lagret enda.
 1942+Enten fjern avhengighetsatributten eller opprett spørreundersøkelsen med id=$3 på siden $2 og lagre den.
 1943+For å lagre en spørreundersøkelse, send den mens du ikke svarer på noen forslagsspørsmål.',
 1944+ 'qp_error_vote_dependance_poll' => 'Vennligst stem for spørreundersøkelsen $1 først.',
 1945+ 'qp_error_too_many_spans' => 'For mange kategorigrupper for det totale antall underkategorier definert',
 1946+ 'qp_error_unanswered_span' => 'Ubesvart underkategori',
 1947+ 'qp_error_non_unique_choice' => 'Dette spørsmålet krever unikt forslagssvar',
 1948+ 'qp_error_category_name_empty' => 'Kategorinavn er tomt',
 1949+ 'qp_error_proposal_text_empty' => 'Forslagstekst er tom',
 1950+ 'qp_error_too_few_categories' => 'Minst to kategorier må defineres',
 1951+ 'qp_error_too_few_spans' => 'Hver kategorigruppe må inneholde minst to underkategorier',
 1952+ 'qp_error_no_answer' => 'Ubesvart forslag',
 1953+ 'qp_error_unique' => 'Spørsmål av typen unique() har flere forslag enn mulige definerte svar: umulig å gjennomføre',
 1954+);
 1955+
 1956+/** Pälzisch (Pälzisch)
 1957+ * @author Xqt
 1958+ */
 1959+$messages['pfl'] = array(
 1960+ 'qp_stats_link' => 'Schdadischdik',
 1961+);
 1962+
 1963+/** Polish (Polski)
 1964+ * @author Odder
 1965+ * @author Sp5uhe
 1966+ */
 1967+$messages['pl'] = array(
 1968+ 'pollresults' => 'Wyniki ankiet na tej witrynie',
 1969+ 'qp_desc' => 'Pozwala na tworzenie ankiet',
 1970+ 'qp_desc-sp' => '[[Special:PollResults|Strona specjalna]] z wynikami ankiet',
 1971+ 'qp_result_NA' => 'Brak odpowiedzi',
 1972+ 'qp_result_error' => 'Błąd składni',
 1973+ 'qp_vote_button' => 'Zapisz głos',
 1974+ 'qp_vote_again_button' => 'Zmień głos',
 1975+ 'qp_polls_list' => 'Spis wszystkich ankiet',
 1976+ 'qp_users_list' => 'Spis wszystkich użytkowników',
 1977+ 'qp_browse_to_poll' => 'Przeglądaj do $1',
 1978+ 'qp_browse_to_user' => 'Przeglądaj do $1',
 1979+ 'qp_votes_count' => '$1 {{PLURAL:$1|głos|głosy|głosów}}',
 1980+ 'qp_source_link' => 'źródło',
 1981+ 'qp_stats_link' => 'statystyki',
 1982+ 'qp_users_link' => 'użytkownicy',
 1983+ 'qp_voice_link' => 'Głos użytkownika',
 1984+ 'qp_voice_link_inv' => 'Głos użytkownika?',
 1985+ 'qp_user_polls_link' => 'Brał udział w $1 {{PLURAL:$1|ankiecie|ankietach}}',
 1986+ 'qp_user_missing_polls_link' => '{{GENDER:$1|Nie brał|Nie brała|Brak}} udziału',
 1987+ 'qp_not_participated_link' => 'brak udziału',
 1988+ 'qp_order_by_username' => 'Posortowane względem nazwy użytkownika',
 1989+ 'qp_order_by_polls_count' => 'Posortowane względem liczby uczestników ankiety',
 1990+ 'qp_results_line_qupl' => 'Strona „$1” ankieta „$2” – $3',
 1991+ 'qp_results_line_qpl' => 'Strona „$1” ankieta „$2” – $3, $4, $5, $6',
 1992+ 'qp_header_line_qpul' => '$1 [ Strona „$2” ankieta „$3” ]',
 1993+ 'qp_export_to_xls' => 'Eksport statystyk w formacie XLS',
 1994+ 'qp_voices_to_xls' => 'Eksport głosów w formacie XLS',
 1995+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|użytkownik odpowiedział|użytkowników odpowiedziało}} na pytania',
 1996+ 'qp_func_no_such_poll' => 'Brak takiej ankiety ($1)',
 1997+ 'qp_func_missing_question_id' => 'Określ istniejący identyfikator pytania (zaczynając od 1) dla ankiety $1',
 1998+ 'qp_func_invalid_question_id' => 'Nieprawidłowy identyfikator $2 pytania (nie jest to numer) dla ankiety $1',
 1999+ 'qp_func_missing_proposal_id' => 'Określ identyfikator istniejącej propozycji (zaczynając od 0) dla pytania $2 z ankiety $1',
 2000+ 'qp_func_invalid_proposal_id' => 'Nieprawidłowy identyfikator $3 propozycji (to nie jest numer) pytania $2 w ankiecie $1',
 2001+ 'qp_error_no_such_poll' => 'Brak takiej ankiety ($1).
 2002+Upewnij się, że ankieta została zadeklarowana i zapisana oraz, że użyłeś jako ogranicznika adresu znaku #',
 2003+ 'qp_error_in_question_header' => 'Nieprawidłowy nagłówek pytania – $1',
 2004+ 'qp_error_id_in_stats_mode' => 'Nie można zadeklarować identyfikatora ankiety w trybie statycznym',
 2005+ 'qp_error_dependance_in_stats_mode' => 'Nie można zadeklarować łańcucha zależności ankiety w trybie statystycznym',
 2006+ 'qp_error_no_stats' => 'Brak danych statystycznych, ponieważ nikt jeszcze nie brał udziału w tej ankiecie (adres=$1)',
 2007+ 'qp_error_address_in_decl_mode' => 'Nie można uzyskać adresu ankiety w trybie deklaracji',
 2008+ 'qp_error_question_not_implemented' => 'Pytania tego typu nie zostały jeszcze zaimplementowane – $1',
 2009+ 'qp_error_invalid_question_type' => 'Nieprawidłowy typ pytania – $1',
 2010+ 'qp_error_type_in_stats_mode' => 'Typ pytania nie może być definiowany w trybie wyświetlania statystyki – $1',
 2011+ 'qp_error_no_poll_id' => 'Znacznik ankiety nie ma zdefiniowanego atrybutu identyfikatora.',
 2012+ 'qp_error_invalid_poll_id' => 'Nieprawidłowy identyfikator ankiety (id=$1).
 2013+Identyfikator ankiety może zawierać wyłączanie litery, cyfry i znak odstępu',
 2014+ 'qp_error_already_used_poll_id' => 'Identyfikator ankiety został już użyty na tej stronie (id=$1).',
 2015+ 'qp_error_invalid_dependance_value' => 'Łańcuch zależności ankiety (id=$1) ma nieprawidłową wartość atrybutu zależności (dependence=„$2”)',
 2016+ 'qp_error_missed_dependance_title' => 'Ankieta (id=$1) jest uzależniona od innej ankiety (id=$3) ze strony [[$2]], ale tytuł [[$2]] nie został odnaleziony.
 2017+Należy usunąć atrybut zależności lub przywrócić [[$2]]',
 2018+ 'qp_error_missed_dependance_poll' => 'Ankieta (id=$1) jest uzależniona od innej ankiety (id=$3) na stronie $2, ale ankieta nie istnieje lub nie została jeszcze zapisana.
 2019+Należy usunąć atrybut zależności lub utworzyć ankietę z id=$3 na stronie $2 i ją zapisać.
 2020+Aby zapisać ankietę, zapisz ją bez odpowiadania na jakiekolwiek proponowane pytania.',
 2021+ 'qp_error_vote_dependance_poll' => 'Najpierw weź udział w ankiecie $1.',
 2022+ 'qp_error_too_many_spans' => 'Zbyt wiele grup kategorii dla ogólnej liczby zdefiniowanych podkategorii',
 2023+ 'qp_error_unanswered_span' => 'Podkategoria bez odpowiedzi',
 2024+ 'qp_error_non_unique_choice' => 'To pytanie wymaga udzielenia unikalnej odpowiedzi',
 2025+ 'qp_error_category_name_empty' => 'Nazwa kategorii jest pusta',
 2026+ 'qp_error_proposal_text_empty' => 'Tekst odpowiedzi jest pusty',
 2027+ 'qp_error_too_few_categories' => 'Należy wybrać co najmniej dwie kategorie',
 2028+ 'qp_error_too_few_spans' => 'Każda grupa kategorii musi zawierać co najmniej dwie podkategorie',
 2029+ 'qp_error_no_answer' => 'Pytanie bez odpowiedzi',
 2030+ 'qp_error_unique' => 'Pytanie typu unique() ma więcej propozycji odpowiedzi niż zdefiniowano jako dopuszczalne – brak możliwości zakończenia',
 2031+);
 2032+
 2033+/** Piedmontese (Piemontèis)
 2034+ * @author Borichèt
 2035+ * @author Dragonòt
 2036+ */
 2037+$messages['pms'] = array(
 2038+ 'pollresults' => 'Arzultà dij sondagi an sto sit-sì',
 2039+ 'qp_desc' => 'A përmet la creassion ëd sondagi',
 2040+ 'qp_desc-sp' => "[[Special:PollResults|Pàgina special]] për vëdde j'arzultà dij sondagi",
 2041+ 'qp_result_NA' => 'Pa arspondù',
 2042+ 'qp_result_error' => 'Eror ëd sintassi',
 2043+ 'qp_vote_button' => 'Vot',
 2044+ 'qp_vote_again_button' => 'Cangia tò vot',
 2045+ 'qp_polls_list' => 'Lista tùit ij sondagi',
 2046+ 'qp_users_list' => "Lista tùit j'utent",
 2047+ 'qp_browse_to_poll' => 'Andé fin-a a $1',
 2048+ 'qp_browse_to_user' => 'Andé fin-a a $1',
 2049+ 'qp_votes_count' => '$1 {{PLURAL:$1|vot|vot}}',
 2050+ 'qp_source_link' => 'Sorgiss',
 2051+ 'qp_stats_link' => 'Statìstiche',
 2052+ 'qp_users_link' => 'Utent',
 2053+ 'qp_voice_link' => "Vos ëd l'utent",
 2054+ 'qp_voice_link_inv' => "Vos ëd l'utent?",
 2055+ 'qp_user_polls_link' => 'Partessipà a $1 {{PLURAL:$1|sondagi|sondagi}}',
 2056+ 'qp_user_missing_polls_link' => 'Gnun-e partessipassion',
 2057+ 'qp_not_participated_link' => 'Pa partessipà',
 2058+ 'qp_order_by_username' => 'Ordiné për nòm utent',
 2059+ 'qp_order_by_polls_count' => 'Ordiné për nùmer ëd sondagi',
 2060+ 'qp_results_line_qupl' => 'Pàgina "$1" Sondagi "$2": "$3"',
 2061+ 'qp_results_line_qpl' => 'Pàgina "$1" Sondagi "$2": $3, $4, $5, $6',
 2062+ 'qp_header_line_qpul' => '$1 [ Pàgina "$2" Sondagi "$3" ]',
 2063+ 'qp_export_to_xls' => 'Espòrta statìstiche an formà XLS',
 2064+ 'qp_voices_to_xls' => 'Espòrta ij vot an formà XLS',
 2065+ 'qp_users_answered_questions' => "$1 {{PLURAL:$1|utent|utent}} a l'han arspondù a la custion",
 2066+ 'qp_func_no_such_poll' => 'Ël sondagi a esist pa ($1)',
 2067+ 'qp_func_missing_question_id' => "Për piasì specìfica n'id ëd custion esistent (partend da 1) për ël sondagi $1",
 2068+ 'qp_func_invalid_question_id' => 'Id custion=$2 pa bon (pa un nùmer) për ël sondagi $1',
 2069+ 'qp_func_missing_proposal_id' => "Për piasì specifica n'id propòsta esistent (an partend da 0) për ël sondagi $1, chestion $2",
 2070+ 'qp_func_invalid_proposal_id' => 'Id propòsta=$3 pa bon (pa un nùmer) për ël sondagi $1, chestion $2',
 2071+ 'qp_error_no_such_poll' => "Sondagi pa esistent ($1).
 2072+Sicurte che ël sondagi a sia diciarà e salvà, ëdcò sicurte ëd dovré ël caràter delimitador d'adrësse #",
 2073+ 'qp_error_in_question_header' => 'Antestassion dla chestion pa bon-a: $1',
 2074+ 'qp_error_id_in_stats_mode' => "As peul pa diciaresse n'ID ëd sondagi an manera statìstica",
 2075+ 'qp_error_dependance_in_stats_mode' => 'As peul pa diciaresse na caden-a ëd dipendensa dël sondagi an manera statìstica',
 2076+ 'qp_error_no_stats' => "Pa gnun dat statìstich a son disponìbij, përchè gnun a l'ha votà për sto sondagi-sì, për adess (adrëssa=$1)",
 2077+ 'qp_error_address_in_decl_mode' => "As peul pa pijé n'adrëssa dël sondagi an manera diciarativa",
 2078+ 'qp_error_question_not_implemented' => 'Chestion dë sta sòrt-sì a son pa sostnùe: $1',
 2079+ 'qp_error_invalid_question_type' => 'Sòrt ëd custion pa bon-a: $1',
 2080+ 'qp_error_type_in_stats_mode' => 'Le Sòrt ëd custion a peulo pa esse definìe an manera statìstica: $1',
 2081+ 'qp_error_no_poll_id' => "L'etichëtta dël sondagi a l'ha gnun atribù definì.",
 2082+ 'qp_error_invalid_poll_id' => "Id dël sondagi pa bon (id=$1).
 2083+L'id dël sondagi a peul conten-e mach litre, nùmer e caràter dë spassi",
 2084+ 'qp_error_already_used_poll_id' => "L'id dël sondagi a l'é già stàit dovrà an sta pàgina (id=$1).",
 2085+ 'qp_error_invalid_dependance_value' => 'La caden-a ëd dipendensa dël sondagi (id=$1) a l\'ha valor pa bon ëd l\'atribù ëd dipendensa (dipendensa="$2")',
 2086+ 'qp_error_missed_dependance_title' => "Ël sondagi (id=$1) a l'é dipendent da n'àutr sondagi (id=$3) ëd pàgina [[$2]], ma ël tìtol [[$2]] a l'é pa stàit trovà.
 2087+Ch'a gava l'atribù ëd dipendensa, o ch'a buta torna [[$2]]",
 2088+ 'qp_error_missed_dependance_poll' => "Ël sondagi (id=$1) a l'é dipendent da n'àutr sondagi (id=$3) a pàgina $2, ma ël sondagi a esist pa o a l'é pa stàit ancor salvà.
 2089+Ch'a gava l'atribù ëd dipendensa, o ch'a crea ël sondagi con id=$3 a la pàgina $2 e ch'a lo salva.
 2090+Për salvé un sondagi, ch'a lo spedissa sensa arsponde a gnun-e custion ëd propòsta.",
 2091+ 'qp_error_vote_dependance_poll' => 'Për piasì vòta për ël sondagi $1 prima.',
 2092+ 'qp_error_too_many_spans' => 'Tròpe partìe ëd categorìe për ël nùmer total ëd sot-categorìe definìe',
 2093+ 'qp_error_unanswered_span' => 'Sotcategorìe pa arspondùe',
 2094+ 'qp_error_non_unique_choice' => 'Sta custion-sì a veul na sola arspòsta ëd propòsta',
 2095+ 'qp_error_category_name_empty' => "Ël nòm categorìa a l'é veuid",
 2096+ 'qp_error_proposal_text_empty' => "Ël test ëd propòsta a l'é veuid",
 2097+ 'qp_error_too_few_categories' => 'Almanch doe categorìe a devo esse definìe',
 2098+ 'qp_error_too_few_spans' => 'Minca partìa ëd categorìe a deuv conten-e almanch doe sot-categorìe',
 2099+ 'qp_error_no_answer' => 'Propòsta sensa rispòsta',
 2100+ 'qp_error_unique' => "La custion ëd sòrt ùnica() a l'ha pi propòste che arspòste possìbij definìe: impossìbil da completé",
 2101+);
 2102+
 2103+/** Pashto (پښتو)
 2104+ * @author Ahmed-Najib-Biabani-Ibrahimkhel
 2105+ */
 2106+$messages['ps'] = array(
 2107+ 'qp_result_NA' => 'بې ځوابه',
 2108+ 'qp_vote_button' => 'رايه ورکول',
 2109+ 'qp_vote_again_button' => 'خپله رايه بدلول',
 2110+ 'qp_users_list' => 'د ټولو کارنانو لړليک جوړول',
 2111+ 'qp_votes_count' => '$1 {{PLURAL:$1|رايه|رايې}}',
 2112+ 'qp_source_link' => 'سرچينه',
 2113+ 'qp_users_link' => 'کارنان',
 2114+ 'qp_order_by_username' => 'د کارن-نوم له مخې اوډل',
 2115+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|کارن|کارنانو}} پوښتنې ځواب کړې',
 2116+ 'qp_error_invalid_question_type' => 'د ناسمې پوښتنې ډول: $1',
 2117+ 'qp_error_unanswered_span' => 'بې ځوابه څېرمه وېشنيزه',
 2118+ 'qp_error_category_name_empty' => 'د وېشنيزې نوم تش دی',
 2119+ 'qp_error_no_answer' => 'بې ځوابه وړانديز',
 2120+);
 2121+
 2122+/** Portuguese (Português)
 2123+ * @author Hamilton Abreu
 2124+ */
 2125+$messages['pt'] = array(
 2126+ 'pollresults' => 'Resultados das sondagens neste síte',
 2127+ 'qp_desc' => 'Permite a criação de sondagens',
 2128+ 'qp_desc-sp' => '[[Special:PollResults|Página especial]] para ver os resultados das sondagens',
 2129+ 'qp_result_NA' => 'Sem resposta',
 2130+ 'qp_result_error' => 'Erro sintáctico',
 2131+ 'qp_vote_button' => 'Vote',
 2132+ 'qp_vote_again_button' => 'Altere o seu voto',
 2133+ 'qp_polls_list' => 'Listar todas as sondagens',
 2134+ 'qp_users_list' => 'Listar todos os utilizadores',
 2135+ 'qp_browse_to_poll' => 'Navegar para $1',
 2136+ 'qp_browse_to_user' => 'Navegar para $1',
 2137+ 'qp_votes_count' => '$1 {{PLURAL:$1|voto|votos}}',
 2138+ 'qp_source_link' => 'Fonte',
 2139+ 'qp_stats_link' => 'Estatísticas',
 2140+ 'qp_users_link' => 'Utilizadores',
 2141+ 'qp_voice_link' => 'Voz do utilizador',
 2142+ 'qp_voice_link_inv' => 'Voz do utilizador?',
 2143+ 'qp_user_polls_link' => 'Participou {{PLURAL:$1|numa sondagem|em $1 sondagens}}',
 2144+ 'qp_user_missing_polls_link' => 'Nenhuma participação',
 2145+ 'qp_not_participated_link' => 'Não participada',
 2146+ 'qp_order_by_username' => 'Ordenar por utilizador',
 2147+ 'qp_order_by_polls_count' => 'Ordenar por contagem de sondagens',
 2148+ 'qp_results_line_qupl' => 'Página "$1" Sondagem "$2": $3',
 2149+ 'qp_results_line_qpl' => 'Página "$1" Sondagem "$2": $3, $4, $5, $6',
 2150+ 'qp_header_line_qpul' => '$1 [ Página "$2" Sondagem "$3" ]',
 2151+ 'qp_export_to_xls' => 'Exportar estatísticas para o formato XLS',
 2152+ 'qp_voices_to_xls' => 'Exportar vozes para o formato XLS',
 2153+ 'qp_users_answered_questions' => '{{PLURAL:$1|Um utilizador respondeu|$1 utilizadores responderam}} às questões',
 2154+ 'qp_func_no_such_poll' => 'Sondagem inexistente ($1)',
 2155+ 'qp_func_missing_question_id' => 'Por favor, especifique o número de uma pergunta existente (começando a partir de 1) para a sondagem $1',
 2156+ 'qp_func_invalid_question_id' => 'Número de pergunta=$2 é inválido (não é numérico) para a sondagem $1',
 2157+ 'qp_func_missing_proposal_id' => 'Por favor, especifique o número de uma proposta existente (começando a partir de 0) para a sondagem $1, pergunta $2',
 2158+ 'qp_func_invalid_proposal_id' => 'Número de proposta=$3 é inválido (não é numérico) para a sondagem $1, pergunta $2',
 2159+ 'qp_error_no_such_poll' => 'Sondagem inexistente ($1).
 2160+Verifique que a sondagem foi declarada e gravada, certifique-se também de que foi usado o carácter delimitador #',
 2161+ 'qp_error_in_question_header' => 'Cabeçalho de pergunta inválido: $1',
 2162+ 'qp_error_id_in_stats_mode' => 'Não é possível declarar um identificador da sondagem em modo estatístico',
 2163+ 'qp_error_dependance_in_stats_mode' => 'Não é possível declarar uma cadeia de dependências da sondagem em modo estatístico',
 2164+ 'qp_error_no_stats' => 'Não estão disponíveis dados estatísticos, porque ainda ninguém votou nesta sondagem (endereço=$1)',
 2165+ 'qp_error_address_in_decl_mode' => 'Não é possível obter um endereço da sondagem em modo declarativo',
 2166+ 'qp_error_question_not_implemented' => 'Não estão implementadas perguntas do tipo: $1',
 2167+ 'qp_error_invalid_question_type' => 'Tipo de pergunta inválido: $1',
 2168+ 'qp_error_type_in_stats_mode' => 'Não é possível definir no modo de visionamento estatístico o tipo de pergunta: $1',
 2169+ 'qp_error_no_poll_id' => "Não foi definido um atributo de identificação no marcador ''(tag)'' da sondagem",
 2170+ 'qp_error_invalid_poll_id' => 'Identificador de sondagem inválido (id=$1).
 2171+O identificador só pode conter letras, números e espaços',
 2172+ 'qp_error_already_used_poll_id' => 'O identificador da sondagem (id=$1) já foi usado nesta página',
 2173+ 'qp_error_invalid_dependance_value' => 'A cadeia de dependências da sondagem (id=$1) tem um valor inválido no atributo da dependência (dependance="$2")',
 2174+ 'qp_error_missed_dependance_title' => 'A sondagem (id=$1) está dependente de outra sondagem (id=$3) da página [[$2]], mas o título [[$2]] não foi encontrado.
 2175+Remova o atributo da dependência ou restaure a página [[$2]]',
 2176+ 'qp_error_missed_dependance_poll' => 'A sondagem (id=$1) está dependente de outra sondagem (id=$3) da página $2, mas essa sondagem não existe ou ainda não foi gravada.
 2177+Remova o atributo da dependência ou crie a sondagem com id=$3 na página $2 e grave-a.
 2178+Para gravar uma sondagem, submeta-a sem ter respondido a nenhuma pergunta.',
 2179+ 'qp_error_vote_dependance_poll' => 'Por favor, vote na sondagem $1 antes.',
 2180+ 'qp_error_too_many_spans' => 'Demasiadas classes de categorias para as subcategorias definidas',
 2181+ 'qp_error_unanswered_span' => 'Subcategoria sem resposta',
 2182+ 'qp_error_non_unique_choice' => 'Esta pergunta requer resposta a uma única proposta',
 2183+ 'qp_error_category_name_empty' => 'O nome da categoria está vazio',
 2184+ 'qp_error_proposal_text_empty' => 'O texto da proposta está vazio',
 2185+ 'qp_error_too_few_categories' => 'Deve definir pelo menos duas categorias',
 2186+ 'qp_error_too_few_spans' => 'Cada classe de categorias requer pelo menos duas respostas possíveis definidas',
 2187+ 'qp_error_no_answer' => 'Proposta sem resposta',
 2188+ 'qp_error_unique' => 'Pergunta do tipo unique() tem mais propostas definidas do que respostas possíveis: impossível de completar',
 2189+);
 2190+
 2191+/** Brazilian Portuguese (Português do Brasil)
 2192+ * @author Giro720
 2193+ * @author Helder.wiki
 2194+ * @author Heldergeovane
 2195+ * @author Luckas Blade
 2196+ * @author Raylton P. Sousa
 2197+ */
 2198+$messages['pt-br'] = array(
 2199+ 'pollresults' => "Resultados de enquetes neste ''site''",
 2200+ 'qp_desc' => 'Habilita a criação de enquetes',
 2201+ 'qp_desc-sp' => '[[Special:PollResults|Página especial]] para visulizar os resultados das enquetes',
 2202+ 'qp_result_NA' => 'Não respondido',
 2203+ 'qp_result_error' => 'Erro de sintaxe',
 2204+ 'qp_vote_button' => 'Votar',
 2205+ 'qp_vote_again_button' => 'Alterar o seu voto',
 2206+ 'qp_polls_list' => 'Listar todas as enquetes',
 2207+ 'qp_users_list' => 'Listar todos os usuários',
 2208+ 'qp_browse_to_poll' => 'Navegar para $1',
 2209+ 'qp_browse_to_user' => 'Navegar para $1',
 2210+ 'qp_votes_count' => '$1 {{PLURAL:$1|voto|votos}}',
 2211+ 'qp_source_link' => 'Fonte',
 2212+ 'qp_stats_link' => 'Estatísticas',
 2213+ 'qp_users_link' => 'Usuários',
 2214+ 'qp_voice_link' => 'Voz do usuário',
 2215+ 'qp_voice_link_inv' => 'Voz do usuário?',
 2216+ 'qp_user_polls_link' => 'Participou {{PLURAL:$1|numa sondagem|em $1 sondagens}}',
 2217+ 'qp_user_missing_polls_link' => 'Nenhuma participação',
 2218+ 'qp_not_participated_link' => 'Não participada',
 2219+ 'qp_order_by_username' => 'Ordenar por nome de usuário',
 2220+ 'qp_order_by_polls_count' => 'Ordenar por contagem de sondagens',
 2221+ 'qp_results_line_qupl' => 'Página "$1" Sondagem "$2": $3',
 2222+ 'qp_results_line_qpl' => 'Página "$1" Sondagem "$2": $3, $4, $5, $6',
 2223+ 'qp_header_line_qpul' => '$1 [ Página "$2" Sondagem "$3" ]',
 2224+ 'qp_export_to_xls' => 'Exportar estatísticas para o formato XLS',
 2225+ 'qp_voices_to_xls' => 'Exportar vozes para o formato XLS',
 2226+ 'qp_users_answered_questions' => '{{PLURAL:$1|Um usuário respondeu|$1 usuários responderam}} às questões',
 2227+ 'qp_func_no_such_poll' => 'Sondagem inexistente ($1)',
 2228+ 'qp_func_missing_question_id' => 'Por favor, especifique o número de uma pergunta existente (começando a partir de 1) para a sondagem $1',
 2229+ 'qp_func_invalid_question_id' => 'Número de pergunta=$2 é inválido (não é numérico) para a sondagem $1',
 2230+ 'qp_func_missing_proposal_id' => 'Por favor, especifique o número de uma proposta existente (começando a partir de 0) para a sondagem $1, pergunta $2',
 2231+ 'qp_func_invalid_proposal_id' => 'Número de proposta=$3 é inválido (não é numérico) para a sondagem $1, pergunta $2',
 2232+ 'qp_error_no_such_poll' => 'Sondagem inexistente ($1).
 2233+Verifique que a sondagem foi declarada e gravada, certifique-se também de que foi usado o carácter delimitador #',
 2234+ 'qp_error_in_question_header' => 'Cabeçalho de pergunta inválido: $1',
 2235+ 'qp_error_id_in_stats_mode' => 'Não é possível declarar um identificador da sondagem em modo estatístico',
 2236+ 'qp_error_dependance_in_stats_mode' => 'Não é possível declarar uma cadeia de dependências da sondagem em modo estatístico',
 2237+ 'qp_error_no_stats' => 'Não estão disponíveis dados estatísticos, porque ainda ninguém votou nesta sondagem (endereço=$1)',
 2238+ 'qp_error_address_in_decl_mode' => 'Não é possível obter um endereço da sondagem em modo declarativo',
 2239+ 'qp_error_question_not_implemented' => 'Não estão implementadas perguntas do tipo: $1',
 2240+ 'qp_error_invalid_question_type' => 'Tipo de pergunta inválido: $1',
 2241+ 'qp_error_type_in_stats_mode' => 'Não é possível definir no modo de visualização estatística o tipo de pergunta: $1',
 2242+ 'qp_error_no_poll_id' => 'Não foi definido um atributo de identificação no marcador da sondagem',
 2243+ 'qp_error_invalid_poll_id' => 'Identificador de sondagem inválido (id=$1).
 2244+O identificador só pode conter letras, números e espaços',
 2245+ 'qp_error_already_used_poll_id' => 'O identificador da sondagem (id=$1) já foi usado nesta página',
 2246+ 'qp_error_invalid_dependance_value' => 'A cadeia de dependências da sondagem (id=$1) tem um valor inválido no atributo da dependência (dependance="$2")',
 2247+ 'qp_error_missed_dependance_title' => 'A sondagem (id=$1) está dependente de outra sondagem (id=$3) da página [[$2]], mas o título [[$2]] não foi encontrado.
 2248+Remova o atributo da dependência ou restaure a página [[$2]]',
 2249+ 'qp_error_missed_dependance_poll' => 'A sondagem (id=$1) está dependente de outra sondagem (id=$3) da página $2, mas essa sondagem não existe ou ainda não foi salva.
 2250+Remova o atributo da dependência ou crie a sondagem com id=$3 na página $2 e salve-a.
 2251+Para gravar uma sondagem, submeta-a sem ter respondido a nenhuma pergunta.',
 2252+ 'qp_error_vote_dependance_poll' => 'Por favor, vote na sondagem $1 antes.',
 2253+ 'qp_error_too_many_spans' => 'Demasiadas classes de categorias para as subcategorias definidas',
 2254+ 'qp_error_unanswered_span' => 'Subcategoria sem resposta',
 2255+ 'qp_error_non_unique_choice' => 'Esta pergunta requer resposta a uma única proposta',
 2256+ 'qp_error_category_name_empty' => 'O nome da categoria está vazio',
 2257+ 'qp_error_proposal_text_empty' => 'O texto da proposta está vazio',
 2258+ 'qp_error_too_few_categories' => 'Pelo menos duas categorias devem ser definidas',
 2259+ 'qp_error_too_few_spans' => 'Cada classe de categorias requer pelo menos duas respostas possíveis definidas',
 2260+ 'qp_error_no_answer' => 'Proposta sem resposta',
 2261+ 'qp_error_unique' => 'Pergunta do tipo unique() tem mais propostas definidas do que respostas possíveis: impossível de completar',
 2262+);
 2263+
 2264+/** Romanian (Română)
 2265+ * @author Firilacroco
 2266+ * @author Stelistcristi
 2267+ */
 2268+$messages['ro'] = array(
 2269+ 'qp_result_error' => 'Eroare de sintaxă',
 2270+ 'qp_vote_button' => 'Votați',
 2271+ 'qp_polls_list' => 'Arătați toate sondajele',
 2272+ 'qp_users_list' => 'Arătați toți utilizatorii',
 2273+ 'qp_source_link' => 'Sursa',
 2274+ 'qp_stats_link' => 'Statistici',
 2275+ 'qp_users_link' => 'Utilizatori',
 2276+ 'qp_voice_link' => 'Vocea utilizatorului',
 2277+ 'qp_voice_link_inv' => 'Vocea utilizatorului?',
 2278+ 'qp_order_by_username' => 'Ordonează după numele utilizatorilor',
 2279+);
 2280+
 2281+/** Tarandíne (Tarandíne)
 2282+ * @author Joetaras
 2283+ */
 2284+$messages['roa-tara'] = array(
 2285+ 'qp_vote_button' => 'Vote',
 2286+ 'qp_stats_link' => 'Statisteche',
 2287+ 'qp_users_link' => 'Utinde',
 2288+);
 2289+
 2290+/** Russian (Русский)
 2291+ * @author QuestPC
 2292+ * @author Александр Сигачёв
 2293+ */
 2294+$messages['ru'] = array(
 2295+ 'pollresults' => 'Результаты опросов на сайте',
 2296+ 'qp_desc' => 'Позволяет создавать опросы',
 2297+ 'qp_desc-sp' => '[[Special:PollResults|Специальная страница]] для просмотра результатов опросов',
 2298+ 'qp_result_NA' => 'Нет ответа',
 2299+ 'qp_result_error' => 'Синтаксическая ошибка',
 2300+ 'qp_vote_button' => 'Проголосовать',
 2301+ 'qp_vote_again_button' => 'Переголосовать',
 2302+ 'qp_polls_list' => 'Список всех опросов',
 2303+ 'qp_users_list' => 'Список всех участников',
 2304+ 'qp_browse_to_poll' => 'Перейти к $1',
 2305+ 'qp_browse_to_user' => 'Перейти к $1',
 2306+ 'qp_votes_count' => '$1 {{PLURAL:$1|голос|голоса|голосов}}',
 2307+ 'qp_source_link' => 'Исходный код',
 2308+ 'qp_stats_link' => 'Статистика',
 2309+ 'qp_users_link' => 'Участники',
 2310+ 'qp_voice_link' => 'Голос участника',
 2311+ 'qp_voice_link_inv' => 'Голос участника?',
 2312+ 'qp_user_polls_link' => 'Участвовал в $1 {{PLURAL:$1|опросе|опросах|опросах}}',
 2313+ 'qp_user_missing_polls_link' => 'Неучастие в опросах',
 2314+ 'qp_not_participated_link' => 'Список неучаствовавших',
 2315+ 'qp_order_by_username' => 'Сортировать по имени пользователя',
 2316+ 'qp_order_by_polls_count' => 'Сортировать по количеству опросов',
 2317+ 'qp_results_line_qupl' => 'Страница "$1" Опрос "$2": $3',
 2318+ 'qp_results_line_qpl' => 'Страница "$1" Опрос "$2": $3, $4, $5, $6',
 2319+ 'qp_header_line_qpul' => '$1 [ Страница "$2" Опрос "$3" ]',
 2320+ 'qp_results_line_qpul' => '$1: $2',
 2321+ 'qp_header_line_qucl' => '$1. $2<br />$3 ??? $4',
 2322+ 'qp_results_line_qucl' => '$1: $2 $3',
 2323+ 'qp_export_to_xls' => 'Экспортировать статистику в XLS формате',
 2324+ 'qp_voices_to_xls' => 'Экспортировать голоса в XLS формате',
 2325+ 'qp_users_answered_questions' => 'На вопросы {{PLURAL:$1|ответил $1 участник|ответило $1 участника|ответили $1 участников}}',
 2326+ 'qp_func_no_such_poll' => 'Опрос не найден ($1)',
 2327+ 'qp_func_missing_question_id' => 'Укажите существующий идентификатор вопроса (начинающийся с единицы) для опроса $1',
 2328+ 'qp_func_invalid_question_id' => 'Ошибочный идентификатор вопроса (question id=$2 - требуется числовое значение) для опроса $1',
 2329+ 'qp_func_missing_proposal_id' => 'Укажите идентификатор строки (начинающийся с нуля) для опроса $1, вопроса $2',
 2330+ 'qp_func_invalid_proposal_id' => 'Ошибочный идентификатор строки (proposal id=$3 - требуется числовое значение) для опроса $1, вопроса $2',
 2331+ 'qp_error_no_such_poll' => 'Опрос не найден ($1). Убедитесь что заданный опрос определён и сохранён, а также что используется символ разделителя адреса #',
 2332+ 'qp_error_in_question_header' => 'Неверный заголовок вопроса: $1',
 2333+ 'qp_error_id_in_stats_mode' => 'Недопустимо определять идентификатор опроса (id) в статистическом режиме вывода',
 2334+ 'qp_error_dependance_in_stats_mode' => 'Недопустимо определять атрибут зависимости опроса (dependance) в статистическом режиме',
 2335+ 'qp_error_no_stats' => 'Статистика голосования недоступна, так как еще никто не голосовал в этом опросе (address=$1)',
 2336+ 'qp_error_address_in_decl_mode' => 'Недопустимо задавать адрес опроса (address) в режиме определения',
 2337+ 'qp_error_question_not_implemented' => 'Вопросы данного типа не реализованы в коде расширения: $1',
 2338+ 'qp_error_invalid_question_type' => 'Недопустимый тип вопроса: $1',
 2339+ 'qp_error_type_in_stats_mode' => 'Недопустимо определять тип вопроса в статистическом режиме: $1',
 2340+ 'qp_error_no_poll_id' => 'Тэг опроса не имеет атрибута id.',
 2341+ 'qp_error_invalid_poll_id' => 'Недопустимый идентификатор опроса (id=$1). Идентификатор опроса может содержать только буквы, цифры и символ пробела',
 2342+ 'qp_error_already_used_poll_id' => 'Установленный атрибут id опроса уже используется другим опросом на данной странице (id=$1).',
 2343+ 'qp_error_invalid_dependance_value' => 'В цепочке зависимости опросов для опроса (id=$1) было найдено синтаксически неверное значение атрибута зависимости (dependance="$2")',
 2344+ 'qp_error_missed_dependance_title' => 'Опрос с идентификатором id=$1 имеет атрибут зависимости от другого опроса (id=$3), находящегося на отсутствующей странице [[$2]]. Необходимо убрать атрибут зависимости от другого опроса, либо восстановить страницу [[$2]]',
 2345+ 'qp_error_missed_dependance_poll' => 'Опрос с идентификатором id=$1 требует прохождения другого опроса с идентификатором id=$3, находящегося на странице $2. Однако же, последний не был найден. Необходимо удалить атрибут зависимости из опроса (id=$1), либо создать опрос с идентификатором id=$3 на странице $2 и сохранить его. Для сохранения опроса будет достаточно нажать кнопку "Проголосовать", не отвечая ни на один вопрос.',
 2346+ 'qp_error_vote_dependance_poll' => 'Пожалуйста ответьте сначала на опрос $1.',
 2347+ 'qp_error_too_many_spans' => 'Определено слишком много классов для подкатегорий вопросов',
 2348+ 'qp_error_unanswered_span' => 'Подкатегория вопроса без ответа',
 2349+ 'qp_error_non_unique_choice' => 'Данный вопрос требует чтобы выбранный вариант ответа не использовался ранее',
 2350+ 'qp_error_category_name_empty' => 'Отсутствует название варианта ответа',
 2351+ 'qp_error_proposal_text_empty' => 'Отсутствует текст строки вопроса',
 2352+ 'qp_error_too_few_categories' => 'Каждый вопрос должен иметь по крайней мере два варианта ответа',
 2353+ 'qp_error_too_few_spans' => 'Каждая подкатегория вопроса требует по меньшей мере два варианта ответа',
 2354+ 'qp_error_no_answer' => 'Нет ответа на вопрос',
 2355+ 'qp_error_unique' => 'Опрос, имеющий тип unique(), не должен иметь больше ответов чем вопросов',
 2356+);
 2357+
 2358+/** Rusyn (Русиньскый)
 2359+ * @author Gazeb
 2360+ */
 2361+$messages['rue'] = array(
 2362+ 'qp_stats_link' => 'Штатістікы',
 2363+ 'qp_users_link' => 'Хоснователї',
 2364+);
 2365+
 2366+/** Serbian Cyrillic ekavian (‪Српски (ћирилица)‬)
 2367+ * @author Rancher
 2368+ * @author Михајло Анђелковић
 2369+ */
 2370+$messages['sr-ec'] = array(
 2371+ 'qp_desc' => 'Омогућава покретање анкета',
 2372+ 'qp_result_NA' => 'Није одговорено',
 2373+ 'qp_result_error' => 'Синтаксна грешка',
 2374+ 'qp_vote_button' => 'Гласај',
 2375+ 'qp_vote_again_button' => 'Промените свој глас',
 2376+ 'qp_polls_list' => 'Прикажи све анкете',
 2377+ 'qp_users_list' => 'Прикажи све кориснике',
 2378+ 'qp_votes_count' => '$1 {{PLURAL:$1|глас|гласа|гласа|гласа|гласова}}',
 2379+ 'qp_stats_link' => 'Статистика',
 2380+ 'qp_users_link' => 'Корисници',
 2381+ 'qp_user_polls_link' => 'Учествовао у $1 {{PLURAL:$1|анкети|анкета}}',
 2382+);
 2383+
 2384+/** Serbian Latin ekavian (‪Srpski (latinica)‬) */
 2385+$messages['sr-el'] = array(
 2386+ 'qp_desc' => 'Omogućava pokretanje anketa',
 2387+ 'qp_result_NA' => 'Nije odgovoreno',
 2388+ 'qp_result_error' => 'Sintaksna greška',
 2389+ 'qp_vote_button' => 'Glasaj',
 2390+ 'qp_vote_again_button' => 'Promenite svoj glas',
 2391+ 'qp_polls_list' => 'Prikaži sve ankete',
 2392+ 'qp_users_list' => 'Prikaži sve korisnike',
 2393+ 'qp_votes_count' => '$1 {{PLURAL:$1|glas|glasa|glasa|glasa|glasova}}',
 2394+ 'qp_stats_link' => 'Statistike',
 2395+ 'qp_users_link' => 'Korisnici',
 2396+ 'qp_user_polls_link' => 'Učestvovao u $1 {{PLURAL:$1|anketi|anketa}}',
 2397+);
 2398+
 2399+/** Swedish (Svenska)
 2400+ * @author Ozp
 2401+ * @author Per
 2402+ */
 2403+$messages['sv'] = array(
 2404+ 'pollresults' => 'Resultat av omröstningarna på denna sida',
 2405+ 'qp_desc' => 'Tillåter skapandet av frågeundersökningar',
 2406+ 'qp_desc-sp' => '[[Special:PollResults|Specialsida]] för visning av resultat av omröstningarna',
 2407+ 'qp_result_NA' => 'Inte besvarad',
 2408+ 'qp_result_error' => 'Syntaxfel',
 2409+ 'qp_vote_button' => 'Rösta',
 2410+ 'qp_vote_again_button' => 'Ändra din röst',
 2411+ 'qp_polls_list' => 'Lista alla röstningar',
 2412+ 'qp_users_list' => 'Lista alla användare',
 2413+ 'qp_browse_to_poll' => 'Bläddra till $1',
 2414+ 'qp_browse_to_user' => 'Bläddra till $1',
 2415+ 'qp_votes_count' => '$1 {{PLURAL:$1|röst|röster}}',
 2416+ 'qp_source_link' => 'Källa',
 2417+ 'qp_stats_link' => 'Statistik',
 2418+ 'qp_users_link' => 'Användare',
 2419+ 'qp_voice_link' => 'Användaråsikt',
 2420+ 'qp_voice_link_inv' => 'Användaråsikt?',
 2421+ 'qp_user_polls_link' => 'Deltagit i $1 {{PLURAL:$1|omröstning|omröstningar}}',
 2422+ 'qp_user_missing_polls_link' => 'Ingen deltagelse',
 2423+ 'qp_not_participated_link' => 'Inte deltagit',
 2424+ 'qp_order_by_username' => 'Sortera efter användarnanm',
 2425+ 'qp_order_by_polls_count' => 'Sortera efter antal omröstningar',
 2426+ 'qp_results_line_qupl' => 'Sida "$1" Undersökning "$2": $3',
 2427+ 'qp_results_line_qpl' => 'Sida "$1" Undersökning "$2": $3, $4, $5, $6',
 2428+ 'qp_header_line_qpul' => '$1 [ Sida "$2" Frågeundersökning "$3" ]',
 2429+ 'qp_export_to_xls' => 'Exportera statistik till XLS-format',
 2430+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|användare|användare}} besvarade frågorna',
 2431+ 'qp_func_no_such_poll' => 'Ingen sådan undersökning ($1)',
 2432+ 'qp_error_no_such_poll' => 'Ingen sådan omröstning ($1).
 2433+Var säker på att omröstningen deklarerades och sparades, var också med att använda adressavgränsar-tecknet #',
 2434+ 'qp_error_no_stats' => 'Ingen statistik är tillgänglig eftersom ingen ännu har röstat på denna undersökning (adress=$1)',
 2435+ 'qp_error_question_not_implemented' => 'Frågor av den typen är inte implementerade: $1',
 2436+ 'qp_error_invalid_question_type' => 'Ogiltig frågetyp:$1',
 2437+ 'qp_error_already_used_poll_id' => 'Detta omröstnings-id har redan använts på denna sida (id=$1).',
 2438+ 'qp_error_vote_dependance_poll' => 'Vänligen rösta i undersökningen $1 först.',
 2439+ 'qp_error_too_many_spans' => 'För många kategorigrupper för det totala antalet underkategorier definerade',
 2440+ 'qp_error_unanswered_span' => 'Obesvarad underkategori',
 2441+ 'qp_error_non_unique_choice' => 'Denna fråga kräver unika svarsförslag',
 2442+ 'qp_error_category_name_empty' => 'Kategorinamn är tomt',
 2443+ 'qp_error_proposal_text_empty' => 'Förslagstext är tom',
 2444+ 'qp_error_too_few_categories' => 'Minst två kategorier måste definieras',
 2445+ 'qp_error_too_few_spans' => 'Varje kategorigrupp måste innehålla minst två underkategorier',
 2446+ 'qp_error_no_answer' => 'Obesvarat förslag',
 2447+);
 2448+
 2449+/** Telugu (తెలుగు)
 2450+ * @author Veeven
 2451+ */
 2452+$messages['te'] = array(
 2453+ 'qp_votes_count' => '$1 {{PLURAL:$1|వోటు|వోట్లు}}',
 2454+ 'qp_stats_link' => 'గణాంకాలు',
 2455+ 'qp_users_link' => 'వాడుకరులు',
 2456+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|వాడుకరి|గురు వాడుకరులు}} ప్రశ్నలకు జవాబిచ్చారు',
 2457+ 'qp_error_category_name_empty' => 'వర్గం పేరు ఖాళీగా ఉంది',
 2458+);
 2459+
 2460+/** Turkmen (Türkmençe)
 2461+ * @author Hanberke
 2462+ */
 2463+$messages['tk'] = array(
 2464+ 'qp_users_link' => 'Ulanyjylar',
 2465+);
 2466+
 2467+/** Tagalog (Tagalog)
 2468+ * @author AnakngAraw
 2469+ */
 2470+$messages['tl'] = array(
 2471+ 'pollresults' => 'Mga resulta ng halalan sa sityong ito',
 2472+ 'qp_desc' => 'Nagpapahintulot sa paglikha ng mga halalan',
 2473+ 'qp_desc-sp' => '[[Special:PollResults|Natatnging pahina]] para sa pagtingin sa mga resulta ng mga halalan',
 2474+ 'qp_result_NA' => 'Hindi sinagutan',
 2475+ 'qp_result_error' => 'Kamalian sa palaugnayan',
 2476+ 'qp_vote_button' => 'Bumoto',
 2477+ 'qp_vote_again_button' => 'Baguhin ang boto mo',
 2478+ 'qp_polls_list' => 'Talaan ng lahat ng mga pagboto',
 2479+ 'qp_users_list' => 'Itala ang lahat ng mga tagagamit',
 2480+ 'qp_browse_to_poll' => 'Tumingin-tingin sa $1',
 2481+ 'qp_browse_to_user' => 'Tumingin-tingin sa $1',
 2482+ 'qp_votes_count' => '$1 {{PLURAL:$1|boto|mga boto}}',
 2483+ 'qp_source_link' => 'Pinagmulan',
 2484+ 'qp_stats_link' => 'Estadistika',
 2485+ 'qp_users_link' => 'Mga tagagamit',
 2486+ 'qp_voice_link' => 'Tinig ng tagagamit',
 2487+ 'qp_voice_link_inv' => 'Tinig ng tagagamit?',
 2488+ 'qp_user_polls_link' => 'Nakilahok sa $1 {{PLURAL:$1|botohan|mga botohan}}',
 2489+ 'qp_user_missing_polls_link' => 'Walang pakikilahok',
 2490+ 'qp_not_participated_link' => 'Hindi lumahok',
 2491+ 'qp_order_by_username' => 'Pagkakasunud-sunod ayon sa pangalan ng tagagamit',
 2492+ 'qp_order_by_polls_count' => 'Pagkakasunud-sunod ayon sa bilang ng botohan',
 2493+ 'qp_results_line_qupl' => 'Pahina "$1" Botohan "$2": $3',
 2494+ 'qp_results_line_qpl' => 'Pahina "$1" Botohan "$2": $3, $4, $5, $6',
 2495+ 'qp_header_line_qpul' => '$1 [ Pahina "$2" Botohan "$3" ]',
 2496+ 'qp_export_to_xls' => 'Iluwas ang estadistika sa anyong XLS',
 2497+ 'qp_voices_to_xls' => 'Iluwas ang mga tinig papaloob sa anyong XLS',
 2498+ 'qp_users_answered_questions' => '$1 {{PLURAL:$1|tagagamit|mga tagagamit}} sumagot sa mga tanong',
 2499+ 'qp_func_no_such_poll' => 'Walang ganyang botohan ($1)',
 2500+ 'qp_func_missing_question_id' => 'Mangyaring tukuyin ang isang umiiral na id ng tanong (simula sa 1) para sa botohang $1',
 2501+ 'qp_func_invalid_question_id' => 'Hindi tanggap na tanong na id=$2 (hindi isang bilang) para sa botohang $1',
 2502+ 'qp_func_missing_proposal_id' => 'Mangyaring tukuyin ang isang umiiral na iminungkahing id (simula sa 0) para sa botohang $1, tanong $2',
 2503+ 'qp_func_invalid_proposal_id' => 'Hindi tanggap na mungkahing id=$3 (hindi isang bilang) para sa botohang $1, tanong $2',
 2504+ 'qp_error_no_such_poll' => 'Walang ganyang botohan ($1).
 2505+Tiyaking na nagpahayag ang botohan at nasagip, tiyakin ding ginamit ang panghanggang tirahan ng panitik na #',
 2506+ 'qp_error_in_question_header' => 'Hindi tanggap na paulo ng tanong: $1',
 2507+ 'qp_error_id_in_stats_mode' => 'Hindi maipahayag ang ID ng botohan sa modalidad ng pang-estadistika',
 2508+ 'qp_error_dependance_in_stats_mode' => 'Hindi maipahayag ang tanikalang pangsandig ng botohan sa modalidad na pang-estadistika',
 2509+ 'qp_error_no_stats' => 'Walang makuhang datong pang-estadistika, dahil wala pang bumoboto para sa halalang ito, (tirahan=$1)',
 2510+ 'qp_error_address_in_decl_mode' => 'Hindi makakuha ng tirahan ng botohan sa modalidad ng pagpapahayag',
 2511+ 'qp_error_question_not_implemented' => 'Hindi ipinapatupad ang ganyang uri ng mga tanong: $1',
 2512+ 'qp_error_invalid_question_type' => 'Hindi tanggap na uri ng tanong: $1',
 2513+ 'qp_error_type_in_stats_mode' => 'Hindi mabigyang kahulugan ang uri ng tanong sa modalidad ng nagpapakita ng estadistika: $1',
 2514+ 'qp_error_no_poll_id' => 'Walang tinukoy na id ng katangian ng tatak ng botohan.',
 2515+ 'qp_error_invalid_poll_id' => 'Hindi tanggap na id ng botohan (id=$1).
 2516+Maaaring maglaman lang ang id ng botohan ng mga titik, mga bilang at patlang na panitik',
 2517+ 'qp_error_already_used_poll_id' => 'Nagamit na ang id ng botohan sa pahinang ito (id=$1).',
 2518+ 'qp_error_invalid_dependance_value' => 'Ang tanikala ng pagsandig ng botohan (id=$1) ay may hindi tanggap na halaga ng katangian ng pagsandig (pagsandig="$2")',
 2519+ 'qp_error_missed_dependance_title' => 'Ang botohan (id=$1) ay nakasandig sa ibang botohan (id=$3) mula sa pahinang [[$2]], subalit hindi natagpuan ang pamagat na [[$2]].
 2520+Maaaring tanggalin ang katangian ng pagsandig, o ibalik ang [[$2]]',
 2521+ 'qp_error_missed_dependance_poll' => 'Ang botohang (id=$1) ay nakasandig sa ibang botohan (id=$3) sa pahinang $2, subalit hindi umiiral ang botohang iyon o hindi pa nasasagip.
 2522+Maaaring tanggalin ang katangian ng pagsandig, o likhain ang botohan na may id=$3 sa pahinang $2 at sagipin ito.
 2523+To save a poll, submit it while not answering to any proposal questions.',
 2524+ 'qp_error_vote_dependance_poll' => 'Mangyaring bumoto muna para sa botohang $1.',
 2525+ 'qp_error_too_many_spans' => 'Napakaraming tinukoy na mga pangkat ng kategorya para sa kabuoang bilang ng kabahaging mga kategorya',
 2526+ 'qp_error_unanswered_span' => 'Hindi sinagot na kabahaging kategorya',
 2527+ 'qp_error_non_unique_choice' => 'Nangangailangan ang tanong na ito ng natatanging sagot na pangmungkahi',
 2528+ 'qp_error_category_name_empty' => 'Walang laman ang pangalan ng kategorya',
 2529+ 'qp_error_proposal_text_empty' => 'Walang laman ang teksto ng mungkahi',
 2530+ 'qp_error_too_few_categories' => 'Dapat na tumukoy ng kahit na dalawang mga kategorya',
 2531+ 'qp_error_too_few_spans' => 'Dapat na maglaman ang bawat pangkat ng kategorya ng kahit na dalawang kabahaging mga kategorya',
 2532+ 'qp_error_no_answer' => 'Hindi tinugunang mungkahi',
 2533+ 'qp_error_unique' => 'Ang tanong ng uring natatangi() ay may mas maraming mga mungkahi kaysa tinukoy na maaaring mga tugon: hindi maaaring makumpleto',
 2534+);
 2535+
 2536+/** Turkish (Türkçe)
 2537+ * @author Vito Genovese
 2538+ */
 2539+$messages['tr'] = array(
 2540+ 'pollresults' => 'Bu sitedeki anketlerin sonuçları',
 2541+ 'qp_desc' => 'Anket oluşturulmasını mümkün kılar',
 2542+ 'qp_desc-sp' => 'Anketlerin sonuçlarının görüntülenmesi amaçlı [[Special:PollResults|özel sayfa]]',
 2543+ 'qp_result_NA' => 'Cevaplanmadı',
 2544+ 'qp_result_error' => 'Sözdizimi hatası',
 2545+ 'qp_vote_button' => 'Oy ver',
 2546+ 'qp_vote_again_button' => 'Oyunu değiştir',
 2547+ 'qp_polls_list' => 'Tüm anketleri listele',
 2548+ 'qp_users_list' => 'Tüm kullanıcıları listele',
 2549+ 'qp_browse_to_poll' => '$1 adlı sayfaya gözat',
 2550+ 'qp_browse_to_user' => '$1 adlı sayfaya gözat',
 2551+ 'qp_votes_count' => '$1 {{PLURAL:$1|oy|oy}}',
 2552+ 'qp_source_link' => 'Kaynak',
 2553+ 'qp_stats_link' => 'İstatistikler',
 2554+ 'qp_users_link' => 'Kullanıcılar',
 2555+ 'qp_user_polls_link' => '$1 {{PLURAL:$1|ankete|ankete}} katılmış',
 2556+ 'qp_user_missing_polls_link' => 'Katılım yok',
 2557+ 'qp_not_participated_link' => 'Katılmadı',
 2558+ 'qp_order_by_username' => 'Kullanıcı adına göre sırala',
 2559+ 'qp_order_by_polls_count' => 'Anket sayılarına göre sırala',
 2560+ 'qp_results_line_qupl' => 'Sayfa "$1" Anket "$2": $3',
 2561+ 'qp_export_to_xls' => 'İstatistikleri XLS formatına aktar',
 2562+ 'qp_users_answered_questions' => 'Sorulara $1 {{PLURAL:$1|kullanıcı|kullanıcı}} cevap verdi',
 2563+ 'qp_func_no_such_poll' => 'Böyle bir anket yok ($1)',
 2564+ 'qp_error_dependance_in_stats_mode' => 'İstatistik modunda anketin bağımlılık zinciri bildirilemiyor',
 2565+ 'qp_error_no_stats' => 'İstatistiksel veri mevcut değil, çünkü hiç kimse bu anket için oy vermemiş (adres=$1)',
 2566+ 'qp_error_question_not_implemented' => 'Bu türdeki sorular uygulamaya koyulmamaktadır: $1',
 2567+ 'qp_error_invalid_question_type' => 'Geçersiz soru türü: $1',
 2568+ 'qp_error_no_poll_id' => 'Anket etiketinin tanımlanmış bir kimlik değeri yok.',
 2569+ 'qp_error_already_used_poll_id' => 'Anket kimliği bu sayfada önceden kullanılmış (kimlik=$1).',
 2570+ 'qp_error_vote_dependance_poll' => 'Lütfen ilk olarak $1. anket için oy verin.',
 2571+ 'qp_error_unanswered_span' => 'Cevaplanmamış alt kategori',
 2572+ 'qp_error_category_name_empty' => 'Kategori adı boş',
 2573+ 'qp_error_proposal_text_empty' => 'Teklif metni boş',
 2574+ 'qp_error_too_few_categories' => 'En az iki kategori tanımlanmalı',
 2575+ 'qp_error_too_few_spans' => 'Tüm kategori grupları en az iki alt kategori içermelidir',
 2576+ 'qp_error_no_answer' => 'Cevaplanmamış teklif',
 2577+);
 2578+
 2579+/** Tatar (Cyrillic) (Татарча/Tatarça (Cyrillic))
 2580+ * @author Ильнар
 2581+ */
 2582+$messages['tt-cyrl'] = array(
 2583+ 'qp_user_missing_polls_link' => 'Сорауларда катнашмау',
 2584+ 'qp_not_participated_link' => 'Сорауларда катнашмаучылар исемлеге',
 2585+ 'qp_order_by_username' => 'Кулланучы исеме буенча тәртипкә салу',
 2586+ 'qp_order_by_polls_count' => 'Сорау алулар саны буенча тәртипкә салу',
 2587+ 'qp_results_line_qupl' => '"$1" бит "$2": $3 сорау алу',
 2588+ 'qp_results_line_qpl' => '"$1" бит "$2": $3, $4, $5, $6 сорау алу',
 2589+ 'qp_header_line_qpul' => '$1 [ "$2" бит "$3" сорау алу ]',
 2590+);
 2591+
 2592+/** Ukrainian (Українська)
 2593+ * @author NickK
 2594+ * @author Prima klasy4na
 2595+ * @author Тест
 2596+ */
 2597+$messages['uk'] = array(
 2598+ 'qp_desc' => 'Дозволяє створювати опитування',
 2599+ 'qp_result_error' => 'Синтаксична помилка',
 2600+ 'qp_vote_button' => 'Проголосувати',
 2601+ 'qp_source_link' => 'Джерело',
 2602+ 'qp_stats_link' => 'Статистика',
 2603+ 'qp_users_link' => 'Користувачі',
 2604+ 'qp_users_answered_questions' => 'На питання {{PLURAL:$1|відповів $1 користувач|відповіли $1 користувачі|відповіли $1 користувачів}}',
 2605+);
 2606+
 2607+/** Yiddish (ייִדיש)
 2608+ * @author פוילישער
 2609+ */
 2610+$messages['yi'] = array(
 2611+ 'qp_vote_button' => 'שטימען',
 2612+ 'qp_source_link' => 'מקור',
 2613+);
 2614+
 2615+/** Simplified Chinese (‪中文(简体)‬)
 2616+ * @author Hydra
 2617+ */
 2618+$messages['zh-hans'] = array(
 2619+ 'qp_vote_button' => '投票',
 2620+ 'qp_vote_again_button' => '改变您的投票',
 2621+ 'qp_source_link' => '来源',
 2622+ 'qp_stats_link' => '统计',
 2623+ 'qp_users_link' => '用户',
 2624+);
 2625+
 2626+/** Traditional Chinese (‪中文(繁體)‬)
 2627+ * @author Mark85296341
 2628+ */
 2629+$messages['zh-hant'] = array(
 2630+ 'qp_result_NA' => '未回答',
 2631+ 'qp_result_error' => '語法錯誤',
 2632+ 'qp_vote_button' => '投票',
 2633+ 'qp_vote_again_button' => '修改你的投票',
 2634+ 'qp_polls_list' => '所有投票名單',
 2635+ 'qp_users_list' => '列出所有使用者',
 2636+ 'qp_source_link' => '來源',
 2637+ 'qp_stats_link' => '統計',
 2638+ 'qp_users_link' => '用戶',
 2639+);
 2640+
Property changes on: trunk/extensions/QPoll/qp_i18n.php
___________________________________________________________________
Added: svn:eol-style
12641 + native
Index: trunk/extensions/QPoll/qp_user.css
@@ -9,7 +9,7 @@
1010 .qpoll table.object .spans { color:gray; }
1111 .qpoll table.object .categories { color:#444455; }
1212 .qpoll table.object .proposal { }
13 -.qpoll .proposalerror { color:red; font-weight:600; }
 13+.qpoll .proposalerror { color:red; }
1414 .qpoll .settings td { padding: 0.1em 0.4em 0.1em 0.4em }
1515 .qpoll table.settings { background-color:transparent; }
1616 /* Part for the basic types's inputs. */
@@ -26,27 +26,17 @@
2727 .qpoll .signl { text-align:center; border-bottom:1px solid gray; border-top: 1px solid gray; border-left: 1px solid gray; }
2828 .qpoll .signc { text-align:center; border-bottom:1px solid gray; border-top: 1px solid gray; }
2929 .qpoll .signr { text-align:center; border-bottom:1px solid gray; border-top: 1px solid gray; border-right: 1px solid gray; }
30 -.qpoll .signt { text-align:center; border-left: 1px solid gray; border-right: 1px solid gray; border-top: 1px solid gray; }
31 -.qpoll .signm { text-align:center; border-left: 1px solid gray; border-right: 1px solid gray; }
 30+.qpoll .signt { text-align:center; border-left: 1px solid gray; border-right: 1px solid gray; border-top:1px solid gray; }
 31+.qpoll .signm { text-align:center; border-left: 1px solid gray; border-right:1px solid gray; }
3232 .qpoll .signb { text-align:center; border-left: 1px solid gray; border-right: 1px solid gray; border-bottom:1px solid gray; }
3333 /* Part for the inputfields */
34 -.qpoll a.input, .qpoll a.input:hover, .qpoll a.input:active, .qpoll a.input:visited { text-decoration:none; color:black; outline: 0 }
 34+.qpoll a.input, .qpoll a.input:hover, .qpoll a.input:active, .qpoll a.input:visited { text-decoration:none; color:black; outline:0 }
3535 .qpoll a.input span { outline:#7F9DB9 solid 1px; border:1px solid #7F9DB9; } /* *border is for IE6/7 star is removed due to ff console error */
36 -.qpoll .interp_error { border: 2px solid gray; padding: 0.5em; color: white; background-color: red; }
37 -.qpoll .interp_answer { border: 2px solid gray; padding: 0.5em; color: black; background-color: lightblue; }
3836
39 -.qpoll .cell_errror { background-color: #D700D7; }
40 -
41 -/* script view */
42 -.qpoll .line_numbers { font-family: monospace, "Courier New"; white-space:pre; color:green; background-color: lightgray; float:left; border-left: 1px solid darkgray; border-top: 1px solid darkgray; border-bottom: 1px solid darkgray; padding: 0.5em; }
43 -.qpoll .script_view { font-family: monospace, "Courier New"; white-space:pre; overflow:auto; color:black; background-color: lightgray; border-right: 1px solid darkgray; border-top: 1px solid darkgray; border-bottom: 1px solid darkgray; padding: 0.5em; }
44 -
4537 /* LTR part (RTL is included from separate file */
46 -.qpoll .no_more_attempts { border: 1px solid gray; padding: 0.1em 0.5em 0.1em 0.5em; color: black; background-color: lightblue; margin-left: 1em; }
4738 .qpoll .question { margin-left:2em; }
4839 .qpoll .margin { padding-left:20px; }
4940 .qpoll .header .questionId { font-size: 1.1em; font-weight: bold; float: left; }
5041 .qpoll .header .questionId { *padding-right: 0.5em; } /* applies to IE7 and below */
5142 .qpoll a.input em { color:black; background-color:#DFDFDF; margin-right:1px; }
5243 .qpoll a.input input { padding-left:2px; border:0; }
53 -.qpoll .error_mark { border-left: 3px solid #D700D7; }
Index: trunk/extensions/QPoll/qpoll.sql
@@ -0,0 +1,75 @@
 2+/* WARNING: do not use directly in case your wiki DB setup uses table prefixes
 3+ * use Special:PollResults page instead
 4+ * this file is primarily for debugging
 5+ */
 6+
 7+DROP TABLE IF EXISTS `qp_poll_desc`;
 8+CREATE TABLE `qp_poll_desc` (
 9+ `pid` int unsigned NOT NULL auto_increment,
 10+ `article_id` int unsigned NOT NULL,
 11+ `poll_id` tinytext NOT NULL,
 12+ `order_id` int unsigned NOT NULL,
 13+ `dependance` mediumtext NOT NULL,
 14+ PRIMARY KEY poll (pid),
 15+ UNIQUE INDEX article_poll (article_id,poll_id(128))
 16+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 17+
 18+DROP TABLE IF EXISTS `qp_question_desc`;
 19+CREATE TABLE `qp_question_desc` (
 20+ `pid` int unsigned NOT NULL,
 21+ `question_id` int unsigned NOT NULL,
 22+ `type` tinytext NOT NULL,
 23+ `common_question` mediumtext NOT NULL,
 24+ PRIMARY KEY question (pid,question_id),
 25+ INDEX poll (pid)
 26+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 27+
 28+/* spans are going there, too - separated with | */
 29+DROP TABLE IF EXISTS `qp_question_categories`;
 30+CREATE TABLE `qp_question_categories` (
 31+ `pid` int unsigned NOT NULL,
 32+ `question_id` int unsigned NOT NULL,
 33+ `cat_id` int unsigned NOT NULL,
 34+ `cat_name` tinytext NOT NULL,
 35+ PRIMARY KEY category (pid,question_id,cat_id),
 36+ INDEX poll (pid)
 37+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 38+
 39+DROP TABLE IF EXISTS `qp_question_proposals`;
 40+CREATE TABLE `qp_question_proposals` (
 41+ `pid` int unsigned NOT NULL,
 42+ `question_id` int unsigned NOT NULL,
 43+ `proposal_id` int unsigned NOT NULL,
 44+ `proposal_text` tinytext NOT NULL,
 45+ PRIMARY KEY proposal (pid,question_id,proposal_id),
 46+ INDEX poll (pid)
 47+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 48+
 49+DROP TABLE IF EXISTS `qp_question_answers`;
 50+CREATE TABLE `qp_question_answers` (
 51+ `uid` int unsigned NOT NULL,
 52+ `pid` int unsigned NOT NULL,
 53+ `question_id` int unsigned NOT NULL,
 54+ `proposal_id` int unsigned NOT NULL,
 55+ `cat_id` int unsigned NOT NULL,
 56+ `text_answer` mediumtext,
 57+ PRIMARY KEY answer (uid,pid,question_id,proposal_id,cat_id),
 58+ INDEX user_vote (uid,pid),
 59+ INDEX poll_question (pid,question_id)
 60+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 61+
 62+DROP TABLE IF EXISTS `qp_users_polls`;
 63+CREATE TABLE `qp_users_polls` (
 64+ `uid` int unsigned NOT NULL,
 65+ `pid` int unsigned NOT NULL,
 66+ PRIMARY KEY user_poll (uid,pid)
 67+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 68+
 69+DROP TABLE IF EXISTS `qp_users`;
 70+CREATE TABLE `qp_users` (
 71+ `uid` int unsigned NOT NULL auto_increment,
 72+ `name` tinytext NOT NULL,
 73+ PRIMARY KEY unique_name (uid,name(64)),
 74+ INDEX user_id (uid),
 75+ INDEX username (name(64))
 76+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Property changes on: trunk/extensions/QPoll/qpoll.sql
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: trunk/extensions/QPoll/INSTALL
@@ -1,4 +1,4 @@
2 -MediaWiki extension QPoll, version 0.8.0a
 2+MediaWiki extension QPoll, version 0.7.0
33
44 * download the latest available version and extract it to your wiki extension directory.
55 * add the following line to LocalSettings.php
@@ -7,7 +7,4 @@
88 * check out Special:Version page to verify the installation
99 * login as user that has administrative rights, and go to Special:PollResults page. Database tables will be set up. Alternatively, you may load qpoll.sql to mysql database manually (remember that $wgDBprefix for the tables won't be used!).
1010
11 -=== Upgrade ===
12 -Do not forget to open Special:Pollresults page to update DB schema (the script runs just once).
13 -
1411 See http://mediawiki.org/wiki/Extension:QPoll for further details.
\ No newline at end of file
Index: trunk/extensions/QPoll/qp_user_rtl.css
@@ -1,8 +1,5 @@
2 -.qpoll .no_more_attempts { border: 1px solid gray; padding: 0.1em 0.5em 0.1em 0.5em; color: black; background-color: lightblue; margin-right: 1em; }
32 .qpoll .question { margin-right:2em; }
43 .qpoll .margin { padding-right:20px; }
54 .qpoll .header .questionId {font-size: 1.1em; font-weight: bold; float: right;}
6 -.qpoll .header .questionId { *padding-left: 0.5em; } /* applies to IE7 and below */
75 .qpoll a.input em { color:black; background-color:#DFDFDF; margin-left:1px; }
86 .qpoll a.input input { padding-right:2px; border:0; }
9 -.qpoll .error_mark { border-right: 3px solid #D700D7; }
Index: trunk/extensions/QPoll/qp_results.php
@@ -28,11 +28,10 @@
2929 * * Add this line at the end of your LocalSettings.php file :
3030 * require_once "$IP/extensions/QPoll/qp_user.php";
3131 *
32 - * @version 0.8.0a
 32+ * @version 0.7.0
3333 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3434 * @author QuestPC <questpc@rambler.ru>
3535 */
36 -
3736 if ( !defined( 'MEDIAWIKI' ) ) {
3837 die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
3938 }
@@ -40,50 +39,28 @@
4140 class PollResults extends SpecialPage {
4241
4342 public function __construct() {
44 - parent::__construct( 'PollResults', 'read' );
 43+ global $wgVersion;
 44+ parent::__construct( 'PollResults', 'delete' );
4545 # for MW 1.15 (still being used by many customers)
46 - # please do not remove until 2012
47 - if ( self::mediaWikiVersionCompare( '1.16' ) ) {
48 - wfLoadExtensionMessages( 'QPoll' );
 46+ if ( version_compare( $wgVersion, '1.16', '<' ) ) {
 47+
4948 }
5049 }
5150
52 - static $accessPermissions = array( 'read', 'showresults' );
53 -
5451 static $skin = null;
5552 static $UsersLink = "";
5653 static $PollsLink = "";
5754
58 - /**
59 - * Checks if the given user (identified by an object) can execute this special page
60 - * @param $user User: the user to check
61 - * @return Boolean: does the user have permission to view the page?
62 - */
63 - public function userCanExecute( $user ) {
64 - # this fn is used to decide whether to show the page link at Special:Specialpages
65 - foreach ( self::$accessPermissions as $permission ) {
66 - if ( !$user->isAllowed( $permission ) ) {
67 - return false;
68 - }
69 - }
70 - return true;
71 - }
72 -
7355 public function execute( $par ) {
7456 global $wgOut, $wgRequest;
7557 global $wgServer; // "http://www.yourserver.org"
7658 // (should be equal to 'http://'.$_SERVER['SERVER_NAME'])
7759 global $wgScript; // "/subdirectory/of/wiki/index.php"
7860 global $wgUser;
79 -
80 - # check whether the user has sufficient permissions
81 - foreach ( self::$accessPermissions as $permission ) {
82 - if ( !$wgUser->isAllowed( $permission ) ) {
83 - $wgOut->permissionRequired( $permission );
84 - return;
85 - }
 61+ if ( !$wgUser->isAllowed( 'delete' ) ) {
 62+ $wgOut->permissionRequired('delete');
 63+ return;
8664 }
87 -
8865 if ( class_exists( 'ResourceLoader' ) ) {
8966 # MW 1.17+
9067 // $wgOut->addModules( 'jquery' );
@@ -104,7 +81,8 @@
10582 $wgOut->addHTML( '<div class="qpoll">' );
10683 $output = "";
10784 $this->setHeaders();
108 - if ( ( $result = $this->checkTables() ) !== true ) {
 85+ $db = & wfGetDB( DB_SLAVE );
 86+ if ( ( $result = $this->checkTables( $db ) ) !== true ) {
10987 # tables check failed
11088 $wgOut->addHTML( $result );
11189 return;
@@ -191,30 +169,10 @@
192170 $wgOut->addHTML( $output . '</div>' );
193171 }
194172
195 - /**
196 - * check for the existence of multiple fields in the selected database table
197 - * @param $table table name
198 - * @param $fields field names
199 - */
200 - private function fieldsExists( $table, $fields ) {
201 - $db = & wfGetDB( DB_SLAVE );
202 - if ( !is_array( $fields ) ) {
203 - $fields = array( $fields );
204 - }
205 - foreach( $fields as $field ) {
206 - if ( !$db->fieldExists( $table, $field ) ) {
207 - return false;
208 - }
209 - }
210 - return true;
211 - }
212 -
213 - /**
214 - * check whether the extension tables exist in DB
215 - * @return true if tables are found, string with error message otherwise
216 - */
217 - private function checkTables() {
218 - $db = & wfGetDB( DB_SLAVE );
 173+ # check whether the extension tables exist in DB
 174+ # @param $db - MediaWiki database object
 175+ # @return true if tables are found, string with error message otherwise
 176+ private function checkTables( $db ) {
219177 $sql_tables = array(
220178 "qp_poll_desc",
221179 "qp_question_desc",
@@ -223,78 +181,33 @@
224182 "qp_question_answers",
225183 "qp_users_polls",
226184 "qp_users");
227 - $addFields = array(
228 - 'qpoll_interpretation.src' => array(
229 - 'qp_poll_desc' => array( 'interpretation_namespace', 'interpretation_title' ),
230 - 'qp_users_polls' => array( 'attempts', 'short_interpretation', 'long_interpretation' )
231 - )
232 - );
233185 // check whether the tables were initialized
234186 $tablesFound = 0;
235187 $result = true;
236188 foreach ( $sql_tables as $table ) {
237 - if ( $db->tableExists( $table ) ) {
 189+ $tname = str_replace( "`", "'", $db->tableName( $table ) );
 190+ $res = $db->query( "SHOW TABLE STATUS LIKE $tname" );
 191+ if ( $db->numRows( $res ) > 0 ) {
238192 $tablesFound++;
239193 }
240194 }
241 - if ( $tablesFound != count( $sql_tables ) ) {
242 - # some tables are missing, serious DB error
243 - return "Some of the extension database tables are missing.<br />Please restore from backup or drop the remaining extension tables, then reload this page.";
244 - }
245195 if ( $tablesFound == 0 ) {
246 - # no tables were found, initialize the DB completely with minimal version
247 - if ( ( $r = $db->sourceFile( qp_Setup::$ExtDir . '/tables/qpoll_0.7.0.src' ) ) !== true ) {
248 - return $r;
 196+ # no tables were found, initialize the DB completely
 197+ $r = $db->sourceFile( qp_Setup::$ExtDir . "/qpoll.src" );
 198+ if ( $r === true ) {
 199+ $result = 'Tables were initialized.<br />Please <a href="#" onclick="window.location.reload()">reload</a> this page to view future page edits.';
 200+ } else {
 201+ $result = $r;
249202 }
 203+ } else {
 204+ if ( $tablesFound != count( $sql_tables ) ) {
 205+ # some tables are missing, serious DB error
 206+ $result = "Some of the extension database tables are missing.<br />Please restore from backup or drop the remaining extension tables, then reload this page.";
 207+ }
250208 }
251 - /* start of SQL updates */
252 - $scriptsToRun = array();
253 - foreach( $addFields as $script => &$table_list ) {
254 - foreach( $table_list as $table => &$fields_list ) {
255 - if ( !$this->fieldsExists( $table, $fields_list ) ) {
256 - $scriptsToRun[$script] = true;
257 - }
258 - }
259 - }
260 - foreach( $scriptsToRun as $script => $val ) {
261 - if ( ( $r = $db->sourceFile( qp_Setup::$ExtDir . "/archives/{$script}" ) ) !== true ) {
262 - return $r;
263 - }
264 - }
265 - /* end of SQL updates */
266 - if ( $tablesFound == 0 ) {
267 - $result = 'Tables were initialized.';
268 - }
269 - if ( count( $scriptsToRun ) > 0 ) {
270 - $result = 'Tables were upgraded.';
271 - }
272 - if ( is_string( $result ) ) {
273 - $result .= '<br />Please <a href="#" onclick="window.location.reload()">reload</a> this page to view future page edits.';
274 - }
275209 return $result;
276210 }
277211
278 - private function showAnswerHeader( qp_PollStore $pollStore ) {
279 - $out = '<div style="font-weight:bold;">' . wfMsg( 'qp_results_submit_attempts', intval( $pollStore->attempts ) ) . '</div>';
280 - $interpTitle = $pollStore->getInterpTitle();
281 - if ( $interpTitle === null ) {
282 - $out .= wfMsg( 'qp_poll_has_no_interpretation' );
283 - return $out;
284 - }
285 - /*
286 - # currently, error is not stored in DB, only the vote and long / short interpretations
287 - # todo: is it worth to store it?
288 - if ( $pollStore->interpAnswer->error != '' ) {
289 - return '<strong class="error">' . qp_Setup::specialchars( $pollStore->interpAnswer->error ) . '</strong>';
290 - }
291 - */
292 - $out .= '<div class="interp_answer">' . wfMsg( 'qp_results_interpretation_header' ) .
293 - '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_short_interpretation', qp_Setup::specialChars( $pollStore->interpAnswer->short ) ) ) . '</div>' .
294 - '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_long_interpretation', qp_Setup::specialChars( $pollStore->interpAnswer->long ) ) ) . '</div>' .
295 - '</div>';
296 - return $out;
297 - }
298 -
299212 private function showUserVote( $pid, $uid ) {
300213 $output = "";
301214 if ( $pid !== null && $uid !== null ) {
@@ -308,11 +221,10 @@
309222 $pollStore->setLastUser( $userName, false );
310223 if ( $pollStore->loadUserVote() ) {
311224 $poll_title = $pollStore->getTitle();
312 - # 'parentheses' is unavailable in MediaWiki 1.15.x
 225+ # 'parentheses' is unavailable in 1.14.x
313226 $poll_link = self::$skin->link( $poll_title, $poll_title->getPrefixedText() . wfMsg( 'word-separator' ) . wfMsg( 'qp_parentheses', $pollStore->mPollId ) );
314227 $output .= wfMsg( 'qp_browse_to_user', $user_link ) . "<br />\n";
315228 $output .= wfMsg( 'qp_browse_to_poll', $poll_link ) . "<br />\n";
316 - $output .= $this->showAnswerHeader( $pollStore );
317229 foreach ( $pollStore->Questions as $qkey => &$qdata ) {
318230 $output .= "<br />\n<b>" . $qkey . ".</b> " . qp_Setup::entities( $qdata->CommonQuestion ) . "<br />\n";
319231 $output .= $this->displayUserQuestionVote( $qdata );
@@ -894,7 +806,7 @@
895807
896808 function formatResult( $skin, $result ) {
897809 global $wgLang, $wgContLang;
898 - $poll_title = Title::makeTitle( $result->ns, $result->title, qp_AbstractPoll::s_getPollTitleFragment( $result->poll_id, '' ) );
 810+ $poll_title = Title::makeTitle( $result->ns, $result->title, qp_AbstractPoll::getPollTitleFragment( $result->poll_id, '' ) );
899811 $pagename = qp_Setup::specialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
900812 $pollname = qp_Setup::specialchars( $result->poll_id );
901813 $goto_link = self::$skin->link( $poll_title, wfMsg( 'qp_source_link' ) );
Index: trunk/extensions/QPoll/qp_results.css
@@ -6,5 +6,3 @@
77 .qpoll table.pollresults td.stats {background-color: Azure;}
88 .qpoll table.pollresults td.spaneven {background-color: Aquamarine;}
99 .qpoll table.pollresults td.spanodd {background-color: Moccasin;}
10 -.qpoll .interp_answer { border: 1px solid gray; padding: 0; margin: 0; color: black; background-color: lightgray; font-weight:bold; line-height:2em; }
11 -.qpoll .interp_answer_body { border: none; border-top: 1px solid gray; padding: 0.5em; margin-top: 0; color: black; background-color: Azure; font-weight: normal; line-height:normal; }
Index: trunk/extensions/QPoll/qp_pollstore.php
@@ -106,115 +106,24 @@
107107 return true;
108108 }
109109
110 -} /* end of qp_QuestionData class */
 110+}
111111
112 -class qp_InterpAnswer {
113 - # short answer. it is supposed to be sortable and accountable in statistics
114 - # blank value means short answer is unavailable
115 - var $short = '';
116 - # long answer. it is supposed to be understandable by amateur users
117 - # blank value means long answer is unavailable
118 - var $long = '';
119 - # error message. non-blank value indicates interpretation script error
120 - # either due to incorrect script code, or a script-generated one
121 - var $error = '';
122 - # 2d array of errors generated for [question][proposal], false if no errors
123 - var $qpErrors = false;
124 -
125 - /**
126 - * @param $init - optional array of properties to be initialized
127 - */
128 - function __construct( $init = null ) {
129 - $props = array( 'short', 'long', 'error' );
130 - if ( is_array( $init ) ) {
131 - foreach ( $props as $prop ) {
132 - if ( array_key_exists( $prop, $init ) ) {
133 - $this->{$prop} = $init[$prop];
134 - }
135 - }
136 - return;
137 - }
138 - }
139 -
140 - /**
141 - * "global" error message
142 - */
143 - function setError( $msg ) {
144 - $this->error = $msg;
145 - return $this;
146 - }
147 -
148 - /**
149 - * set question / proposal error message (for quizes)
150 - *
151 - * @param $qidx int index of poll's question
152 - * @param $pidx int index of question's proposal
153 - * @param $msg string error message for [question][proposal] pair
154 - */
155 - function setQPerror( $qidx, $pidx, $msg ) {
156 - if ( !is_array( $this->qpErrors ) ) {
157 - $this->qpErrors = array();
158 - }
159 - if ( !isset( $this->qpErrors[$qidx] ) ) {
160 - $this->qpErrors[$qidx] = array();
161 - }
162 - $this->qpErrors[$qidx][$pidx] = $msg;
163 - }
164 -
165 - function isError() {
166 - return $this->error != '' || is_array( $this->qpErrors );
167 - }
168 -
169 -} /* end of qp_InterpAnswer class */
170 -
171 -/**
172 - * poll storage and retrieval using DB
 112+/* poll storage and retrieval using DB
173113 * one poll may contain several questions
174114 */
175115 class qp_PollStore {
176116
177117 static $db = null;
178 - /// DB keys
 118+ // DB keys
179119 var $pid = null;
180120 var $last_uid = null;
181 - /// common properties
 121+ // common properties
182122 var $mArticleId = null;
183 - # unique id of poll, used for addressing, also with 'qp_' prefix as the fragment part of the link
184 - var $mPollId = null;
185 - # order of poll on the page
186 - var $mOrderId = null;
187 - # dependance from other poll address in the following format: "page#otherpollid"
188 - var $dependsOn = null;
189 - # attempts of voting (passing the quiz). number of resubmits
190 - # note: resubmits are counted for syntax-correct answer (the vote is stored),
191 - # yet the answer still might be logically incorrect (quiz is not passed / partially passed)
192 - var $attempts = 0;
193 -
194 - # NS & DBkey of Title object representing interpretation template for Special:Pollresults page
195 - var $interpNS = 0;
196 - var $interpDBkey = null;
197 - # interpretation of user answer
198 - var $interpAnswer;
199 -
200 - # array of QuestionData instances (data from/to DB)
201 - var $Questions = null;
202 - # poll processing state, read with getState()
203 - #
204 - # 'NA' - object just was created
205 - #
206 - # 'incomplete', self::stateIncomplete()
207 - # http post: not every proposals were answered: do not update DB
208 - # http get: this is not the post: do not update DB
209 - #
210 - # 'error', self::stateError()
211 - # http get: invalid question syntax, parse errors will cause submit button disabled
212 - #
213 - # 'complete', self::stateComplete()
214 - # check whether the poll was successfully submitted
215 - # store user vote to the DB (when the poll is fine)
216 - #
 123+ var $mPollId = null; // unique id of poll, used for addressing, also with 'qp_' prefix as the fragment part of the link
 124+ var $mOrderId = null; // order of poll on the page
 125+ var $dependsOn = null; // dependance from other poll address in the following format: "page#otherpollid"
 126+ var $Questions = null; // array of QuestionData instances (data from/to DB)
217127 var $mCompletedPostData;
218 - # true, after the poll results have been successfully stored to DB
219128 var $voteDone = false;
220129
221130 /* $argv[ 'from' ] indicates type of construction, other elements of $argv vary according to 'from'
@@ -222,9 +131,8 @@
223132 function __construct( $argv = null ) {
224133 global $wgParser;
225134 if ( self::$db == null ) {
226 - self::$db = & wfGetDB( DB_MASTER );
 135+ self::$db = & wfGetDB( DB_SLAVE );
227136 }
228 - $this->interpAnswer = new qp_InterpAnswer();
229137 if ( is_array($argv) && array_key_exists( "from", $argv ) ) {
230138 $this->Questions = Array();
231139 $this->mCompletedPostData = 'NA';
@@ -248,18 +156,6 @@
249157 $argv[ 'dependance' ] !== false ) {
250158 $this->dependsOn = $argv[ 'dependance' ];
251159 }
252 - if ( array_key_exists( 'interpretation', $argv ) ) {
253 - # (0,'') indicates that interpretation template does not exists
254 - $this->interpNS = 0;
255 - $this->interpDBkey = '';
256 - if ( $argv['interpretation'] != '' ) {
257 - $interp = Title::newFromText( $argv['interpretation'], NS_QP_INTERPRETATION );
258 - if ( $interp instanceof Title ) {
259 - $this->interpNS = $interp->getNamespace();
260 - $this->interpDBkey = $interp->getDBkey();
261 - }
262 - }
263 - }
264160 if ( $is_post ) {
265161 $this->setPid();
266162 } else {
@@ -270,7 +166,7 @@
271167 if ( array_key_exists( 'pid', $argv ) ) {
272168 $pid = intval( $argv[ 'pid' ] );
273169 $res = self::$db->select( 'qp_poll_desc',
274 - array( 'article_id', 'poll_id','order_id', 'dependance', 'interpretation_namespace', 'interpretation_title' ),
 170+ array( 'article_id', 'poll_id','order_id', 'dependance' ),
275171 array( 'pid'=>$pid ),
276172 __METHOD__ . ":create from pid" );
277173 $row = self::$db->fetchObject( $res );
@@ -280,8 +176,6 @@
281177 $this->mPollId = $row->poll_id;
282178 $this->mOrderId = $row->order_id;
283179 $this->dependsOn = $row->dependance;
284 - $this->interpNS = $row->interpretation_namespace;
285 - $this->interpDBkey = $row->interpretation_title;
286180 }
287181 }
288182 break;
@@ -305,13 +199,13 @@
306200 'title'=>$pollTitle,
307201 'poll_id'=>$pollId ) );
308202 } else {
309 - return qp_Setup::ERROR_MISSED_TITLE;
 203+ return QP_ERROR_MISSED_TITLE;
310204 }
311205 } else {
312 - return qp_Setup::ERROR_MISSED_TITLE;
 206+ return QP_ERROR_MISSED_TITLE;
313207 }
314208 } else {
315 - return qp_Setup::ERROR_INVALID_ADDRESS;
 209+ return QP_ERROR_INVALID_ADDRESS;
316210 }
317211 }
318212
@@ -324,19 +218,11 @@
325219 $res = null;
326220 if ( $this->mArticleId !==null && $this->mPollId !== null ) {
327221 $res = Title::newFromID( $this->mArticleId );
328 - $res->setFragment( qp_AbstractPoll::s_getPollTitleFragment( $this->mPollId ) );
 222+ $res->setFragment( qp_AbstractPoll::getPollTitleFragment( $this->mPollId ) );
329223 }
330224 return $res;
331225 }
332226
333 - /**
334 - * @return Title instance of interpretation template
335 - */
336 - function getInterpTitle() {
337 - $title = Title::newFromText( $this->interpDBkey, $this->interpNS );
338 - return ( $title instanceof Title ) ? $title : null;
339 - }
340 -
341227 // warning: will work only after successful loadUserAlreadyVoted() or loadUserVote()
342228 function isAlreadyVoted() {
343229 if ( is_array( $this->Questions ) && count( $this->Questions > 0 ) ) {
@@ -471,7 +357,6 @@
472358 }
473359
474360 // load single user vote
475 - // also loads short & long answer interpretation, when available
476361 // will be written into self::Questions[]->ProposalCategoryId,ProposalCategoryText,alreadyVoted
477362 // may be used only after loadQuestions()
478363 // returns true when any of currently defined questions has the votes, false otherwise
@@ -667,32 +552,20 @@
668553 }
669554
670555 function setLastUser( $username, $store_new_user_to_db = true ) {
671 - if ( $this->pid === null ) {
672 - return;
673 - }
674 - $res = self::$db->select( 'qp_users','uid','name=' . self::$db->addQuotes( $username ), __METHOD__ );
675 - $row = self::$db->fetchObject( $res );
676 - if ( $row == false ) {
677 - if ( $store_new_user_to_db ) {
678 - self::$db->insert( 'qp_users', array( 'name'=>$username ), __METHOD__ . ':UpdateUser' );
679 - $this->last_uid = self::$db->insertId();
 556+ if ( $this->pid !== null ) {
 557+ $res = self::$db->select( 'qp_users','uid','name=' . self::$db->addQuotes( $username ), __METHOD__ );
 558+ $row = self::$db->fetchObject( $res );
 559+ if ( $row==false ) {
 560+ if ( $store_new_user_to_db ) {
 561+ self::$db->insert( 'qp_users', array( 'name'=>$username ), __METHOD__ . ':UpdateUser' );
 562+ $this->last_uid = self::$db->insertId();
 563+ } else {
 564+ $this->last_uid = null;
 565+ }
680566 } else {
681 - $this->last_uid = null;
 567+ $this->last_uid = $row->uid;
682568 }
683 - } else {
684 - $this->last_uid = $row->uid;
685569 }
686 - $res = self::$db->select( 'qp_users_polls',
687 - array( 'attempts', 'short_interpretation', 'long_interpretation' ),
688 - array( 'pid'=>$this->pid, 'uid'=>$this->last_uid ),
689 - __METHOD__ . ':load short & long answer interpretation' );
690 - if ( self::$db->numRows( $res ) != 0 ) {
691 - $row = self::$db->fetchObject( $res );
692 - $this->attempts = $row->attempts;
693 - $this->interpAnswer = new qp_InterpAnswer();
694 - $this->interpAnswer->short = $row->short_interpretation;
695 - $this->interpAnswer->long = $row->long_interpretation;
696 - }
697570 // todo: change to "insert ... on duplicate key update ..." when last_insert_id() bugs will be fixed
698571 }
699572
@@ -709,7 +582,7 @@
710583
711584 private function loadPid() {
712585 $res = self::$db->select( 'qp_poll_desc',
713 - array( 'pid', 'order_id', 'dependance', 'interpretation_namespace', 'interpretation_title' ),
 586+ array( 'pid', 'order_id', 'dependance' ),
714587 'article_id=' . self::$db->addQuotes( $this->mArticleId ) . ' and ' .
715588 'poll_id=' . self::$db->addQuotes( $this->mPollId ),
716589 __METHOD__ );
@@ -723,23 +596,19 @@
724597 if ( $this->dependsOn === null ) {
725598 $this->dependsOn = $row->dependance;
726599 }
727 - if ( $this->interpDBkey === null ) {
728 - $this->interpNS = $row->interpretation_namespace;
729 - $this->interpDBkey = $row->interpretation_title;
730 - }
731600 $this->updatePollAttributes( $row );
732601 }
733602 }
734603
735604 private function setPid() {
736605 $res = self::$db->select( 'qp_poll_desc',
737 - array( 'pid', 'order_id', 'dependance', 'interpretation_namespace', 'interpretation_title' ),
 606+ array( 'pid', 'order_id', 'dependance' ),
738607 'article_id=' . self::$db->addQuotes( $this->mArticleId ) . ' and ' .
739608 'poll_id=' . self::$db->addQuotes( $this->mPollId ) );
740609 $row = self::$db->fetchObject( $res );
741 - if ( $row == false ) {
 610+ if ( $row==false ) {
742611 self::$db->insert( 'qp_poll_desc',
743 - array( 'article_id'=>$this->mArticleId, 'poll_id'=>$this->mPollId, 'order_id'=>$this->mOrderId, 'dependance'=>$this->dependsOn, 'interpretation_namespace'=>$this->interpNS, 'interpretation_title'=>$this->interpDBkey ),
 612+ array( 'article_id'=>$this->mArticleId, 'poll_id'=>$this->mPollId, 'order_id'=>$this->mOrderId, 'dependance'=>$this->dependsOn ),
744613 __METHOD__ . ':update poll' );
745614 $this->pid = self::$db->insertId();
746615 } else {
@@ -750,13 +619,10 @@
751620 }
752621
753622 private function updatePollAttributes( $row ) {
754 - if ( $this->mOrderId != $row->order_id ||
755 - $this->dependsOn != $row->dependance ||
756 - $this->interpNS != $row->interpretation_namespace ||
757 - $this->interpDBkey != $row->interpretation_title ) {
 623+ if ( $this->mOrderId != $row->order_id || $this->dependsOn != $row->dependance ) {
758624 $res = self::$db->replace( 'qp_poll_desc',
759625 '',
760 - array( 'pid'=>$this->pid, 'article_id'=>$this->mArticleId, 'poll_id'=>$this->mPollId, 'order_id'=>$this->mOrderId, 'dependance'=>$this->dependsOn, 'interpretation_namespace'=>$this->interpNS, 'interpretation_title'=>$this->interpDBkey ),
 626+ array( 'pid'=>$this->pid, 'article_id'=>$this->mArticleId, 'poll_id'=>$this->mPollId, 'order_id'=>$this->mOrderId, 'dependance'=>$this->dependsOn ),
761627 __METHOD__ . ':poll attributes update'
762628 );
763629 }
@@ -808,41 +674,6 @@
809675 }
810676 }
811677
812 - /**
813 - * Prepares an array of user answer to the current poll and interprets these
814 - * Stores the result in $this->interpAnswer
815 - */
816 - private function interpretVote() {
817 - $this->interpAnswer = new qp_InterpAnswer();
818 - $interpTitle = $this->getInterpTitle();
819 - if ( $interpTitle === null ) {
820 - return;
821 - }
822 - $interpArticle = new Article( $interpTitle, 0 );
823 - if ( !$interpArticle->exists() ) {
824 - return;
825 - }
826 - # prepare array of user answers that will be passed to the interpreter
827 - $poll_answer = array();
828 - foreach ( $this->Questions as $qkey => &$qdata ) {
829 - $questions = array();
830 - foreach( $qdata->ProposalText as $propkey => &$proposal_text ) {
831 - $proposals = array();
832 - foreach ( $qdata->Categories as $catkey => &$cat_name ) {
833 - $text_answer = '';
834 - if ( array_key_exists( $propkey, $qdata->ProposalCategoryId ) &&
835 - ( $id_key = array_search( $catkey, $qdata->ProposalCategoryId[ $propkey ] ) ) !== false ) {
836 - $proposals[$catkey] = $qdata->ProposalCategoryText[ $propkey ][ $id_key ];
837 - }
838 - }
839 - $questions[] = $proposals;
840 - }
841 - $poll_answer[] = $questions;
842 - }
843 - # interpret the poll answer to get interpretation answer
844 - $this->interpAnswer = qp_Interpret::getAnswer( $interpArticle, $poll_answer );
845 - }
846 -
847678 // warning: requires qp_PollStorage::last_uid to be set
848679 private function setAnswers() {
849680 $insert = Array();
@@ -860,40 +691,32 @@
861692 __METHOD__ . ':delete previous answers of current user to the same poll'
862693 );
863694 # vote
 695+ $old_user_abort = ignore_user_abort( true );
864696 if ( count( $insert ) > 0 ) {
865697 self::$db->replace( 'qp_question_answers',
866698 '',
867699 $insert,
868700 __METHOD__ );
869 - $this->interpretVote();
870 - # update interpretation result and number of syntax-valid resubmit attempts
871 - $qp_users_polls = self::$db->tableName( 'qp_users_polls' );
872 - $short = self::$db->addQuotes( $this->interpAnswer->short );
873 - $long = self::$db->addQuotes( $this->interpAnswer->long );
874 - $stmt = "INSERT INTO {$qp_users_polls} (uid,pid,short_interpretation,long_interpretation)\n VALUES ( " . intval( $this->last_uid ) . ", " . intval( $this->pid ) . ", {$short}, {$long} )\n ON DUPLICATE KEY UPDATE attempts = attempts + 1, short_interpretation = {$short} , long_interpretation = {$long}";
875 - self::$db->query( $stmt, __METHOD__ );
 701+ self::$db->replace( 'qp_users_polls',
 702+ '',
 703+ array( 'uid'=>$this->last_uid, 'pid'=>$this->pid ),
 704+ __METHOD__ );
876705 }
 706+ ignore_user_abort( $old_user_abort );
877707 }
878708
879 - /**
880 - * Please call after the poll has been loaded but before it's being submitted
881 - */
882 - function noMoreAttempts() {
883 - return qp_Setup::$max_submit_attempts > 0 && $this->attempts >= qp_Setup::$max_submit_attempts;
884 - }
885 -
886 - # when the user votes and poll wasn't previousely voted yet, it also creates the poll structures in DB
 709+ # when the user votes and poll wasn't previousely voted yet, it also creates the poll in DB
887710 function setUserVote() {
888711 if ( $this->pid !==null &&
889712 $this->last_uid !== null &&
890713 $this->mCompletedPostData == "complete" &&
891714 is_array( $this->Questions ) && count( $this->Questions ) > 0 ) {
892 - self::$db->begin();
 715+ $old_user_abort = ignore_user_abort( true );
893716 $this->setQuestionDesc();
894717 $this->setCategories();
895718 $this->setProposals();
896719 $this->setAnswers();
897 - self::$db->commit();
 720+ ignore_user_abort( $old_user_abort );
898721 $this->voteDone = true;
899722 }
900723 }
Index: trunk/extensions/QPoll/qp_user.js
@@ -27,7 +27,7 @@
2828 * * Add this line at the end of your LocalSettings.php file :
2929 * require_once "$IP/extensions/QPoll/qp_user.php";
3030 *
31 - * @version 0.8.0a
 31+ * @version 0.7.0
3232 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3333 * @author QuestPC <questpc@rambler.ru>
3434 */
Index: trunk/extensions/QPoll/README
@@ -1,4 +1,4 @@
2 -MediaWiki extension QPoll, version 0.8.0a
 2+MediaWiki extension QPoll, version 0.7.0
33
44 This extension allows to create polls embedded into the wikipages. Every poll
55 may contain a set of the questions of various types. The polls can be "chained"
@@ -10,14 +10,4 @@
1111 proposal text on the user's choice of category in another previously voted
1212 poll.
1313
14 -=== v0.8.0a ===
15 -Now it is possible to:
16 -
17 -* Create interpretation scripts for psychological tests and quizes
18 -* Generate and store interpretations / marks / scores
19 -* Highlight wrong answers to question proposals
20 -* Log and limit number of answer attempts
21 -
22 -which allows to use the extension as education tool.
23 -
2414 See http://mediawiki.org/wiki/Extension:QPoll for further details.
\ No newline at end of file
Index: trunk/extensions/QPoll/qp_question.php
@@ -0,0 +1,1206 @@
 2+<?php
 3+
 4+if ( !defined( 'MEDIAWIKI' ) ) {
 5+ die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
 6+}
 7+
 8+abstract class qp_AbstractQuestion {
 9+
 10+ var $parser; // an instance of parser from parser tag hook
 11+ var $ppframe; // an instance of PPFrame (parser context)
 12+ var $mState = ''; // current state of question parsing (no error)
 13+ # error message which occured during the question header parsing that will be output later at rendering stage
 14+ var $headerErrorMessage = 'Unknown error';
 15+ # default type and subtype of the question; should always be properly initialized in $this->parseParameters();
 16+ var $mType = 'unknown';
 17+ var $mSubType = ''; // some questions has a subtype, see $this->parseParameters()
 18+ var $mCategories = Array();
 19+ var $mCategorySpans = Array();
 20+ var $mCommonQuestion = ''; // GET common question of the poll
 21+ var $mProposalText = Array(); // an array of question proposals
 22+ var $mBeingCorrected = false; // true, when user is posting this question via the poll's form
 23+ var $alreadyVoted = false; // whether the selected user has already voted this question ?
 24+
 25+ # whether to show the current stats to the users
 26+ # the following values are defined:
 27+ # false - use value of pollShowResults, Array(0) - suppress, Array(1) - percents, Array(2) - bars
 28+ var $showResults = false;
 29+ var $pollShowResults;
 30+ // display layout
 31+ var $proposalsFirst = false;
 32+ var $transposed = false;
 33+ var $spanType = 'colspan';
 34+ var $categoriesStyle = '';
 35+ var $proposalTextStyle = 'padding-left: 10px;';
 36+ var $textInputStyle = '';
 37+ // statistics
 38+ var $Percents = null;
 39+ var $mRenderTable = Array();
 40+
 41+ # Constructor
 42+ # @public
 43+ # @param $parser an instance of parser from parser tag hook
 44+ # @param $frame an instance of PPFrame (parser context)
 45+ # @param $beingCorrected boolean
 46+ # @param $questionId the identifier of the question used to gernerate input names
 47+ # @param $showResults poll's showResults (may be overriden in the question)
 48+ function __construct( &$parser, &$frame, $beingCorrected, $questionId, $showResults ) {
 49+ global $wgRequest;
 50+ $this->parser = &$parser;
 51+ $this->ppframe = &$frame;
 52+ $this->mRequest = &$wgRequest;
 53+ $this->mQuestionId = $questionId;
 54+ $this->mBeingCorrected = $beingCorrected;
 55+ $this->pollShowResults = $showResults;
 56+ $this->mProposalPattern = '`^[^\|\!].*`u';
 57+ $this->mCategoryPattern = '`^\|(\n|[^\|].*\n)`u';
 58+ }
 59+
 60+ /**
 61+ * Mutator of the question state
 62+ *
 63+ * @protected
 64+ * @param $pState - state of the question
 65+ * @param $error_message - optional main_header_parsing error message
 66+ */
 67+ function setState( $pState, $error_message = null ) {
 68+ if ( $this->mState != 'error' ) {
 69+ $this->mState = $pState;
 70+ }
 71+ if ( $error_message !== null ) {
 72+ # store header error message that cannot be output now, but will be displayed at later stage
 73+ $this->headerErrorMessage = $error_message;
 74+ }
 75+ }
 76+
 77+ /**
 78+ * Accessor of the question state.
 79+ *
 80+ * @protected
 81+ */
 82+ function getState() {
 83+ return $this->mState;
 84+ }
 85+
 86+ function getHeaderError() {
 87+ return '<div class="proposalerror">' . $this->headerErrorMessage . '</div>';
 88+ }
 89+
 90+ # outputs question body parser error/warning message
 91+ # @param $msg - text of message
 92+ # @param $state - sets new question state (note that the 'error' state cannot be changed)
 93+ function bodyErrorMessage( $msg, $state ) {
 94+ $prev_state = $this->getState();
 95+ $this->setState( $state, $msg );
 96+ # return the message only for the first error occured
 97+ # (this one has to be short, that's why title attribute is being used)
 98+ return ( $prev_state == '' ) ? '<span class="proposalerror" title="' . $msg . '">???</span> ' : '';
 99+ }
 100+
 101+ # builds internal & visual representation of question attributes (all attributes but type)
 102+ # @param $attr_str - source text with question attributes
 103+ # @return string : type of the question, empty when not defined
 104+ function parseAttributes( $attr_str ) {
 105+ $paramkeys = array( 't[yi]p[eo]'=>null, 'layout'=>null, 'textwidth'=>null, 'showresults'=>null );
 106+ foreach( $paramkeys as $key=>&$val ) {
 107+ preg_match( '`' . $key . '?="(.*?)"`u', $attr_str, $val );
 108+ }
 109+ $type = $paramkeys[ 't[yi]p[eo]' ];
 110+ $type = isset( $type[1] ) ? trim( $type[1] ) : '';
 111+ $layout = $paramkeys[ 'layout' ];
 112+ $textwidth = $paramkeys[ 'textwidth' ];
 113+ $showresults = $paramkeys[ 'showresults' ];
 114+ if ( count( $layout ) > 0 ) {
 115+ $this->transposed = strpos( $layout[1], 'transpose' ) !== false;
 116+ $this->proposalsFirst = strpos( $layout[1], 'proposals' ) !== false;
 117+ }
 118+ # setup question layout parameters
 119+ if ( $this->transposed ) {
 120+ $this->spanType = 'rowspan';
 121+ $this->categoriesStyle = 'text-align:left; vertical-align:middle; ';
 122+ $this->signClass = array( 'first'=>'signt', 'middle'=>'signm', 'last'=>'signb' );
 123+ $this->proposalTextStyle = 'text-align:center; padding-left: 5px; padding-right: 5px; ';
 124+ $this->proposalTextStyle .= ( $this->proposalsFirst ) ? ' vertical-align: bottom;' : 'vertical-align:top;';
 125+ } else {
 126+ $this->spanType = 'colspan';
 127+ $this->categoriesStyle = '';
 128+ $this->signClass = array( 'first'=>'signl', 'middle'=>'signc', 'last'=>'signr' );
 129+ $this->proposalTextStyle = 'vertical-align:middle; ';
 130+ $this->proposalTextStyle .= ( $this->proposalsFirst ) ? 'padding-right: 10px;' : 'padding-left: 10px;';
 131+ }
 132+ if ( count( $textwidth ) > 0 ) {
 133+ $textwidth = intval( $textwidth[1] );
 134+ if ( $textwidth > 0 ) {
 135+ $this->textInputStyle = 'width:' . $textwidth . 'em;';
 136+ }
 137+ }
 138+ # setup question's showresults when global showresults != 0
 139+ if ( qp_Setup::$global_showresults != 0 && count( $showresults ) > 0 ) {
 140+ # use the value from the question
 141+ $this->showResults = qp_AbstractPoll::parse_ShowResults( $showresults[1] );
 142+ # apply undefined attributes from the poll's showresults definition
 143+ foreach( $this->pollShowResults as $attr => $val ) {
 144+ if ( $attr != 'type' && !isset( $this->showResults[$attr] ) ) {
 145+ $this->showResults[$attr] = $val;
 146+ }
 147+ }
 148+ } else {
 149+ # use the value "inherited" from the poll
 150+ $this->showResults = $this->pollShowResults;
 151+ }
 152+ # initialize cell template for the selected showresults
 153+ # this can be moved to {$this->mType}ParseBody in the future,
 154+ # if needed to setup templates depending on question type
 155+ # right now, cell templates depends only on input type and showresults type
 156+ if ( $this->showResults['type'] != 0 ) {
 157+ $this->{'cellTemplate' . $this->showResults['type']}();
 158+ }
 159+ return $type;
 160+ }
 161+
 162+ function addRow( $row, $rowattrs = "", $celltag = "td", $attribute_maps = null ) {
 163+ if ( $this->transposed ) {
 164+ qp_Renderer::addColumn( $this->mRenderTable, $row, $rowattrs, $celltag, $attribute_maps );
 165+ } else {
 166+ qp_Renderer::addRow( $this->mRenderTable, $row, $rowattrs, $celltag, $attribute_maps );
 167+ }
 168+ }
 169+
 170+ # function to draw borders via css in the question table according to category spans (metacategories)
 171+ function renderSpan( &$name, $catDesc, &$text, &$rawClass, &$spanState ) {
 172+ if ( array_key_exists( 'spanId', $catDesc ) ) {
 173+ $spanState->id = $catDesc[ 'spanId' ];
 174+ $name .= 's' . $spanState->id;
 175+ # there can't be more category spans than the categories
 176+ if ( $this->mCategorySpans[ $spanState->id ]['count'] > count( $this->mCategories ) ) {
 177+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_too_many_spans' ), 'error' ) . $text;
 178+ $rawClass = 'proposalerror';
 179+ }
 180+ if ( $spanState->prevId != $spanState->id ) {
 181+ # begin of new span
 182+ $spanState->wasChecked = false;
 183+ $spanState->prevId = $spanState->id;
 184+ $spanState->cellsLeft = $this->mCategorySpans[ $spanState->id ]['count'];
 185+ if ( $spanState->cellsLeft < 2 ) {
 186+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_too_few_spans' ), 'error' ) . $text;
 187+ QP_Renderer::addClass( $row[ $catId ], 'error' );
 188+ }
 189+ $spanState->isDrawing = $spanState->cellsLeft != 1 && $spanState->cellsLeft != count( $this->mCategories );
 190+ # hightlight only spans of count != 1 and count != count(categories)
 191+ if ( $spanState->isDrawing ) {
 192+ $spanState->className = $this->signClass[ 'first' ];
 193+ }
 194+ } else {
 195+ $spanState->cellsLeft--;
 196+ if ( $spanState->isDrawing ) {
 197+ $spanState->className = ( $spanState->cellsLeft > 1 ) ? $this->signClass[ 'middle' ] : $this->signClass[ 'last' ];
 198+ }
 199+ }
 200+ }
 201+ }
 202+
 203+ function getPercents( $proposalId, $catId ) {
 204+ if ( is_array( $this->Percents ) && array_key_exists( $proposalId, $this->Percents ) &&
 205+ is_array( $this->Percents[ $proposalId ] ) && array_key_exists( $catId, $this->Percents[ $proposalId ] ) ) {
 206+ return intval( round( 100 * $this->Percents[ $proposalId ][ $catId ] ) );
 207+ } else {
 208+ return false;
 209+ }
 210+ }
 211+
 212+}
 213+
 214+/* parsing, checking ans visualisation of Question in statistical display mode (UI input/output)
 215+ */
 216+class qp_QuestionStats extends qp_AbstractQuestion {
 217+
 218+ # Constructor
 219+ # @public
 220+ # @param $parser an instance of parser from parser tag hook
 221+ # @param $frame an instance of PPFrame (parser context)
 222+ # @param $type type of question (taken from DB)
 223+ # @param $questionId the identifier of the question used to gernerate input names
 224+ # @param $showResults poll's showResults (may be overriden in the question)
 225+ function __construct( &$parser, &$frame, $type, $questionId, $showResults ) {
 226+ parent::__construct( $parser, $frame, false, $questionId, $showResults );
 227+ $this->mType = $type;
 228+ }
 229+
 230+ # load some question fields from qp_QuestionData given
 231+ # (usually qp_QuestionData is an array property of qp_PollStore instance)
 232+ # @param $qdata - an instance of qp_QuestionData
 233+ function loadAnswer( qp_QuestionData &$qdata ) {
 234+ $this->alreadyVoted = $qdata->alreadyVoted;
 235+ $this->mCommonQuestion = $qdata->CommonQuestion;
 236+ $this->mProposalText = $qdata->ProposalText;
 237+ $this->mCategories = $qdata->Categories;
 238+ $this->mCategorySpans = $qdata->CategorySpans;
 239+ if ( isset( $qdata->Percents ) && is_array( $qdata->Percents ) ) {
 240+ $this->Percents = $qdata->Percents;
 241+ } else {
 242+ # no percents - no stats
 243+ $this->showResults = Array( 'type'=>0 );
 244+ }
 245+ }
 246+
 247+ # populates an instance of qp_Question with data from qp_QuestionData
 248+ # input: the object of type qp_Question
 249+ function getQuestionAnswer( qp_PollStore &$pollStore ) {
 250+ if ( $pollStore->pid !== null ) {
 251+ if ( $pollStore->questionExists( $this->mQuestionId ) ) {
 252+ $qdata = $pollStore->Questions[ $this->mQuestionId ];
 253+ $this->loadAnswer( $qdata );
 254+ return true;
 255+ }
 256+ }
 257+ return false;
 258+ }
 259+
 260+ function parseCategories() {
 261+ $row = Array();
 262+ if ( $this->proposalsFirst ) {
 263+ // add empty <th> at the begin of row to "compensate" proposal text
 264+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 265+ }
 266+ foreach( $this->mCategories as &$cat ) {
 267+ $row[] = $this->parser->recursiveTagParse( $cat['name'], $this->ppframe );
 268+ }
 269+ if ( !$this->proposalsFirst ) {
 270+ // add empty <th> at the end of row to "compensate" proposal text
 271+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 272+ }
 273+ return $row;
 274+ }
 275+
 276+ function parseCategorySpans() {
 277+ $row = Array();
 278+ if ( $this->mType == 'singleChoice' ) {
 279+ # real category spans have sense only for radiobuttons
 280+ if ( $this->proposalsFirst ) {
 281+ // add empty <th> at the begin of row to "compensate" proposal text
 282+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 283+ }
 284+ foreach( $this->mCategorySpans as &$span ) {
 285+ $row[] = array( "count"=>$span['count'], 0=>$this->parser->recursiveTagParse( $span['name'], $this->ppframe ) );
 286+ }
 287+ if ( !$this->proposalsFirst ) {
 288+ // add empty <th> at the end of row to "compensate" proposal text
 289+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 290+ }
 291+ }
 292+ return $row;
 293+ }
 294+
 295+ function renderStats() {
 296+ if ( $this->getState() == 'error' ) {
 297+ return $this->getHeaderError();
 298+ }
 299+ $catRow = $this->parseCategories();
 300+ if ( count( $this->mCategorySpans ) > 0 ) {
 301+ $spansRow = $this->parseCategorySpans();
 302+ # if there are multiple spans, "turn on" borders for span and category cells
 303+ if ( count( $this->mCategorySpans ) > 1 ) {
 304+ $this->categoriesStyle .= 'border:1px solid gray;';
 305+ }
 306+ if ( $this->categoriesStyle != '' ) {
 307+ qp_Renderer::applyAttrsToRow( $spansRow, array( 'style'=>$this->categoriesStyle ) );
 308+ }
 309+ $this->addRow( $spansRow, array( 'class'=>'spans' ), 'th', array( 'count'=>$this->spanType, 'name'=>0 ) );
 310+ }
 311+ if ( $this->categoriesStyle != '' ) {
 312+ qp_Renderer::applyAttrsToRow( $catRow, array( 'style'=>$this->categoriesStyle ) );
 313+ }
 314+ $this->addRow( $catRow, array( 'class'=>'categories' ), 'th', array( 'name'=>0 ) );
 315+ foreach ( $this->mProposalText as $proposalId => $text ) {
 316+ $row = Array();
 317+ $rawClass = 'proposal';
 318+ $spanState = (object) array( 'id'=>0, 'prevId'=>-1, 'wasChecked'=>true, 'isDrawing'=>false, 'cellsLeft'=>0, 'className'=>'sign' );
 319+ foreach ( $this->mCategories as $catId => $catDesc ) {
 320+ $row[ $catId ] = Array();
 321+ $spanState->className = 'sign';
 322+ switch ( $this->mType ) {
 323+ case 'singleChoice' :
 324+ # category spans have sense only with single choice proposals
 325+ $this->renderSpan( $name, $catDesc, $text, $rawClass, $spanState );
 326+ break;
 327+ }
 328+ QP_Renderer::addClass( $row[ $catId ], $spanState->className );
 329+ if ( $this->showResults['type'] != 0 ) {
 330+ # there ars some stat in row (not necessarily all cells, because size of question table changes dynamically)
 331+ $row[ $catId ][ 0 ] = $this->{'addShowResults' . $this->showResults['type']}( $proposalId, $catId );
 332+ } else {
 333+ $row[ $catId ][ 0 ] = '';
 334+ }
 335+ }
 336+ $text = array( '__tag'=>'td', '__end'=>"\n", 'class'=>'proposaltext', 'style'=>$this->proposalTextStyle, 0=>$this->parser->recursiveTagParse( $text, $this->ppframe ) );
 337+ if ( $this->proposalsFirst ) {
 338+ # first element is proposaltext
 339+ array_unshift( $row, $text );
 340+ } else {
 341+ # last element is proposaltext
 342+ $row[] = $text;
 343+ }
 344+ $this->addRow( $row, array( 'class'=>$rawClass ), 'td' );
 345+ }
 346+ return qp_Renderer::renderHTMLobject( $this->mRenderTable );
 347+ }
 348+
 349+ /*** cell templates ***/
 350+
 351+ # cell templates for the selected showresults
 352+ var $cellTemplate = Array();
 353+ var $cellTemplateParam = Array( 'percents'=>'', 'bar1style'=>'', 'bar2style'=>'' );
 354+
 355+ # setup a template for showresults=1
 356+ # showresults=1 cellTemplate has only one variant
 357+ function cellTemplate1() {
 358+ $this->cellTemplate =
 359+ array(
 360+ 0=>array( '__tag'=>'div', 'class'=>'stats', 0=>&$this->cellTemplateParam['percents'] )
 361+ );
 362+ if ( isset( $this->showResults['color'] ) ) {
 363+ $this->cellTemplate[0]['style'] = 'color:' . $this->showResults['color'] . ';';
 364+ }
 365+ if ( isset( $this->showResults['background'] ) ) {
 366+ $this->cellTemplate[0]['style'] .= 'background:' . $this->showResults['background'] . ';';
 367+ }
 368+ }
 369+
 370+ # transform input according to showresults=1 (numerical percents)
 371+ # *** warning! parameters should be passed only by value, not by reference ***
 372+ function addShowResults1( $proposalId, $catId ) {
 373+ $this->cellTemplateParam['percents'] = '&#160;';
 374+ if ( ( $percents = $this->getPercents( $proposalId, $catId ) ) !== false ) {
 375+ # there is a stat in cell
 376+ $this->cellTemplateParam['percents'] = $percents . '%';
 377+ # template has to be rendered immediately, because $this->cellTemplateParam[] are used as pointers and thus,
 378+ # will always be overwritten
 379+ return QP_Renderer::renderHTMLobject( $this->cellTemplate );
 380+ } else {
 381+ return '';
 382+ }
 383+ }
 384+
 385+ # setup a template for showresults=2
 386+ function cellTemplate2() {
 387+ # statical styles
 388+ $percentstyle = '';
 389+ if ( isset( $this->showResults['textcolor'] ) ) {
 390+ $percentstyle = 'color:' . $this->showResults['textcolor'] . ';';
 391+ }
 392+ if ( isset( $this->showResults['textbackground'] ) ) {
 393+ $percentstyle .= 'background:' . $this->showResults['textbackground'] . ';';
 394+ }
 395+ # has one available template ('bar')
 396+ $this->cellTemplate = array(
 397+ 'bar'=>array( '__tag'=>'div', 'class'=>'stats2',
 398+ 0=>array( '__tag'=>'div', 'class'=>'bar1', 'style'=>&$this->cellTemplateParam['bar1style'], 0=>'&#160;' ),
 399+ 1=>array( '__tag'=>'div', 'class'=>'bar2', 'style'=>&$this->cellTemplateParam['bar2style'], 0=>'&#160;' ),
 400+ 2=>array( '__tag'=>'div', 'class'=>'bar3', 'style'=>$percentstyle, 0=>&$this->cellTemplateParam['percents'] )
 401+ ),
 402+ # the following entries are not real templates, but pre-calculated values of css attributes taken from showresults parameter
 403+ 'bar1showres'=>'',
 404+ 'bar2showres'=>''
 405+ );
 406+ # dynamical styles, width: in percents will be added during rendering in addShowResults
 407+ if ( isset( $this->showResults['color'] ) ) {
 408+ $this->cellTemplate['bar1showres'] .= 'background:' . $this->showResults['color'] . ';';
 409+ }
 410+ if ( isset( $this->showResults['background'] ) ) {
 411+ $this->cellTemplate['bar2showres'] .= 'background:' . $this->showResults['background'] . ';';
 412+ }
 413+ }
 414+
 415+ # transform input according to showresults=2 (bars)
 416+ # *** warning! parameters should be passed only by value, not by reference ***
 417+ function addShowResults2( $proposalId, $catId ) {
 418+ $this->cellTemplateParam['percents'] = '&#160;';
 419+ if ( ( $percents = $this->getPercents( $proposalId, $catId ) ) !== false ) {
 420+ # there is a stat in cell
 421+ $this->cellTemplateParam['percents'] = $percents . '%';
 422+ $this->cellTemplateParam['bar1style'] = 'width:' . $percents . 'px;' . $this->cellTemplate[ 'bar1showres' ];
 423+ $this->cellTemplateParam['bar2style'] = 'width:' . (100 - $percents) . 'px;' . $this->cellTemplate[ 'bar2showres' ];
 424+ return qp_Renderer::renderHTMLobject( $this->cellTemplate['bar'] );
 425+ } else {
 426+ return '';
 427+ }
 428+ }
 429+
 430+ /*** end of cell templates ***/
 431+
 432+}
 433+
 434+/* parsing, checking ans visualisation of Question in declaration/voting mode (UI input/output)
 435+ */
 436+class qp_Question extends qp_AbstractQuestion {
 437+
 438+ # current user voting taken from POST data (if available)
 439+ var $mProposalCategoryId = Array(); // user true/false answers to the question's proposal
 440+ var $mProposalCategoryText = Array(); // user text answers to the question's proposal
 441+ # previous user voting (if available) taken from DB
 442+ var $mPrevProposalCategoryId = Array(); // user true/false answers to the question's proposal from DB
 443+ var $mPrevProposalCategoryText = Array(); // user text answers to the question's proposal from DB
 444+
 445+ # load some question fields from qp_QuestionData given
 446+ # (usually qp_QuestionData is an array property of qp_PollStore instance)
 447+ # @param $qdata - an instance of qp_QuestionData
 448+ function loadAnswer( qp_QuestionData &$qdata ) {
 449+ $this->alreadyVoted = $qdata->alreadyVoted;
 450+ $this->mPrevProposalCategoryId = $qdata->ProposalCategoryId;
 451+ $this->mPrevProposalCategoryText = $qdata->ProposalCategoryText;
 452+ if ( isset( $qdata->Percents ) && is_array( $qdata->Percents ) ) {
 453+ $this->Percents = $qdata->Percents;
 454+ } else {
 455+ # no percents - no stats
 456+ $this->showResults = Array( 'type'=>0 );
 457+ }
 458+ }
 459+
 460+ # populates an instance of qp_Question with data from qp_QuestionData
 461+ # @param the object of type qp_Question
 462+ function getQuestionAnswer( qp_PollStore &$pollStore ) {
 463+ if ( $pollStore->pid !== null ) {
 464+ if ( $pollStore->questionExists( $this->mQuestionId ) ) {
 465+ $qdata = $pollStore->Questions[ $this->mQuestionId ];
 466+ if ( $qdata->IsCompatible( $this ) ) {
 467+ $this->loadAnswer( $qdata );
 468+ return true;
 469+ }
 470+ }
 471+ }
 472+ return false;
 473+ }
 474+
 475+ # checks, whether user had previousely selected the category of the proposal of this question
 476+ # returns true/false for 'checkbox' and 'radio' inputTypes
 477+ # text string/false for 'text' inputType
 478+ function answerExists( $inputType, $proposalId, $catId ) {
 479+ if ( $this->alreadyVoted ) {
 480+ if ( array_key_exists( $proposalId, $this->mPrevProposalCategoryId ) ) {
 481+ $id_key = array_search( $catId, $this->mPrevProposalCategoryId[ $proposalId ] );
 482+ if ( $id_key !== false ) {
 483+ if ( $inputType == 'text' ) {
 484+ if ( array_key_exists( $proposalId, $this->mPrevProposalCategoryText ) &&
 485+ array_key_exists( $id_key, $this->mPrevProposalCategoryText[ $proposalId ] ) ) {
 486+ $prev_text_answer = $this->mPrevProposalCategoryText[ $proposalId ][ $id_key ];
 487+ if ( $prev_text_answer != '' ) {
 488+ return $prev_text_answer;
 489+ }
 490+ }
 491+ } else {
 492+ return true;
 493+ }
 494+ }
 495+ }
 496+ }
 497+ return false;
 498+ }
 499+
 500+ # store the proper (checked) Question
 501+ # creates new qp_QuestionData in the given poll store
 502+ # and places it into the poll store Questions[] collection
 503+ # @param the object of type qp_PollStore
 504+ function store( qp_PollStore &$pollStore ) {
 505+ if ( $pollStore->pid !== null ) {
 506+ $pollStore->Questions[ $this->mQuestionId ] = new qp_QuestionData( array(
 507+ 'from'=>'postdata',
 508+ 'type'=>$this->mType,
 509+ 'common_question'=>$this->mCommonQuestion,
 510+ 'categories'=>$this->mCategories,
 511+ 'category_spans'=>$this->mCategorySpans,
 512+ 'proposal_text'=>$this->mProposalText,
 513+ 'proposal_category_id'=>$this->mProposalCategoryId,
 514+ 'proposal_category_text'=>$this->mProposalCategoryText ) );
 515+ }
 516+ }
 517+
 518+ # parses question main header (common question and XML attributes)
 519+ # initializes common question and question type/subtype
 520+ # @param $input the question's header in QPoll syntax
 521+ #
 522+ # internally, the header is split into
 523+ # main header (part inside curly braces) and
 524+ # body header (categories and metacategories defitions)
 525+ #
 526+ function parseMainHeader( $header ) {
 527+ # split common question and question attributes from the header
 528+ @list( $common_question, $attr_str ) = preg_split( '`\n\|([^\|].*)\s*$`u', $header, -1, PREG_SPLIT_DELIM_CAPTURE );
 529+ if ( !isset( $attr_str ) ) {
 530+ $this->setState( 'error', wfMsg( 'qp_error_in_question_header', qp_Setup::entities( $header ) ) );
 531+ return;
 532+ }
 533+ $this->mCommonQuestion = trim( $common_question );
 534+ $type = $this->parseAttributes( $attr_str );
 535+ # set question type property
 536+ # select the question type and subtype corresponding to the header 'type' attribute
 537+ switch ( $type ) {
 538+ case 'unique()':
 539+ $this->mSubType = 'unique';
 540+ $this->mType = 'singleChoice';
 541+ break;
 542+ case '()':
 543+ $this->mType = 'singleChoice';
 544+ break;
 545+ case '[]':
 546+ $this->mType = 'multipleChoice';
 547+ break;
 548+ case 'mixed' :
 549+ $this->mType = 'mixedChoice';
 550+ break;
 551+ default :
 552+ $this->setState( 'error', wfMsg( 'qp_error_invalid_question_type', qp_Setup::entities( $type ) ) );
 553+ }
 554+ }
 555+
 556+ # build categories and spans internal & visual representations according to
 557+ # definition of categories and spans (AKA metacategories) in the question body
 558+ # @param $input - the text of question body
 559+ #
 560+ # internally, the header is split into
 561+ # main header (part inside curly braces) and
 562+ # body header (categories and metacategories defitions)
 563+ #
 564+ function parseBodyHeader( $input ) {
 565+ $this->raws = preg_split( '`\n`su', $input, -1, PREG_SPLIT_NO_EMPTY );
 566+ $categorySpans = false;
 567+ if ( isset( $this->raws[1] ) ) {
 568+ $categorySpans = preg_match( $this->mCategoryPattern, $this->raws[1]."\n", $matches );
 569+ }
 570+ if ( !$categorySpans && isset( $this->raws[0] ) ) {
 571+ preg_match( $this->mCategoryPattern, $this->raws[0]."\n", $matches );
 572+ }
 573+ # parse the header - spans and categories
 574+ $catString = isset( $matches[1] ) ? $matches[1] : '';
 575+ $catRow = $this->parseCategories( $catString );
 576+ if ( $categorySpans ) {
 577+ $spansRow = $this->parseCategorySpans( $this->raws[0] );
 578+ # if there are multiple spans, "turn on" borders for span and category cells
 579+ if ( count( $this->mCategorySpans ) > 1 ) {
 580+ $this->categoriesStyle .= 'border:1px solid gray;';
 581+ }
 582+ if ( $this->categoriesStyle != '' ) {
 583+ qp_Renderer::applyAttrsToRow( $spansRow, array( 'style'=>$this->categoriesStyle ) );
 584+ }
 585+ $this->addRow( $spansRow, array( 'class'=>'spans' ), 'th', array( 'count'=>$this->spanType, 'name'=>0 ) );
 586+ }
 587+ # do not render single empty category at all (on user's request)
 588+ if ( count( $this->mCategories ) == 1 &&
 589+ $this->mCategories[0]['name'] == '&#160;' ) {
 590+ return;
 591+ }
 592+ # render category table row
 593+ if ( $this->categoriesStyle != '' ) {
 594+ qp_Renderer::applyAttrsToRow( $catRow, array( 'style'=>$this->categoriesStyle ) );
 595+ }
 596+ $this->addRow( $catRow, array( 'class'=>'categories' ), 'th', array( 'name'=>0 ) );
 597+ }
 598+
 599+ function singleChoiceParseBody() {
 600+ $this->questionParseBody( "radio" );
 601+ return qp_Renderer::renderHTMLobject( $this->mRenderTable );
 602+ }
 603+
 604+ function multipleChoiceParseBody() {
 605+ $this->questionParseBody( "checkbox" );
 606+ return qp_Renderer::renderHTMLobject( $this->mRenderTable );
 607+ }
 608+
 609+ function questionParseBody( $inputType ) {
 610+ # Parameters used in some special cases.
 611+ $proposalId = -1;
 612+ foreach( $this->raws as $raw ) {
 613+ if ( !preg_match( $this->mProposalPattern, $raw, $matches ) ) {
 614+ continue;
 615+ }
 616+ # empty proposal text and row
 617+ $text = null;
 618+ $row = Array();
 619+ $proposalId++;
 620+ $rawClass = 'proposal';
 621+ $text = array_pop( $matches );
 622+ $this->mProposalText[ $proposalId ] = trim( $text );
 623+ $spanState = (object) array( 'id'=>0, 'prevId'=>-1, 'wasChecked'=>true, 'isDrawing'=>false, 'cellsLeft'=>0, 'className'=>'sign' );
 624+ foreach ( $this->mCategories as $catId => $catDesc ) {
 625+ $row[ $catId ] = Array();
 626+ $inp = Array( '__tag'=>'input' );
 627+ $spanState->className = 'sign';
 628+ # Determine the input's name and value.
 629+ switch( $this->mType ) {
 630+ case 'multipleChoice':
 631+ $name = 'q' . $this->mQuestionId . 'p' . $proposalId . 's' . $catId;
 632+ $value = 's' . $catId;
 633+ break;
 634+ case 'singleChoice':
 635+ $name = 'q' . $this->mQuestionId . 'p' . $proposalId;
 636+ $value = 's' . $catId;
 637+ # category spans have sense only with single choice proposals
 638+ $this->renderSpan( $name, $catDesc, $text, $rawClass, $spanState );
 639+ if ( $spanState->cellsLeft <= 1 ) {
 640+ # end of new span
 641+ if ( $this->mBeingCorrected &&
 642+ !$spanState->wasChecked &&
 643+ $this->mRequest->getVal($name) != $value ) {
 644+ # the span (a part of proposal) was submitted but unanswered
 645+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_unanswered_span' ), 'NA' ) . $text;
 646+ # highlight current span to indicate an error
 647+ for ( $i = $catId, $j = $this->mCategorySpans[ $spanState->id ]['count']; $j > 0; $i--, $j-- ) {
 648+ QP_Renderer::addClass( $row[$i], 'error' );
 649+ }
 650+ $rawClass = 'proposalerror';
 651+ }
 652+ }
 653+ break;
 654+ }
 655+ # Determine if the input had to be checked.
 656+ if ( $this->mBeingCorrected && $this->mRequest->getVal( $name ) == $value ) {
 657+ $inp[ 'checked' ] = 'checked';
 658+ }
 659+ if ( $this->answerExists( $inputType, $proposalId, $catId ) !== false ) {
 660+ $inp[ 'checked' ] = 'checked';
 661+ }
 662+ if ( array_key_exists( 'checked', $inp ) ) {
 663+ if ( $this->mSubType == 'unique' ) {
 664+ if ( $this->mBeingCorrected && !$this->isUniqueProposalCategoryId( $proposalId, $catId ) ) {
 665+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_non_unique_choice' ), 'NA' ) . $text;
 666+ $rawClass = 'proposalerror';
 667+ unset( $inp[ 'checked' ] );
 668+ QP_Renderer::addClass( $row[ $catId ], 'error' );
 669+ }
 670+ } else {
 671+ $spanState->wasChecked = true;
 672+ }
 673+ }
 674+ if ( array_key_exists( 'checked', $inp ) ) {
 675+ # add category to the list of user answers for current proposal (row)
 676+ $this->mProposalCategoryId[ $proposalId ][] = $catId;
 677+ $this->mProposalCategoryText[ $proposalId ][] = '';
 678+ }
 679+ QP_Renderer::addClass( $row[ $catId ], $spanState->className );
 680+ if ( $this->mSubType == 'unique' ) {
 681+ # unique (question,category,proposal) "coordinate" for javascript
 682+ $inp[ 'id' ] = 'uq' . $this->mQuestionId . 'c' . $catId . 'p' . $proposalId;
 683+ # If type='unique()' question has more proposals than categories, such question is impossible to complete
 684+ if ( count( $this->mProposalText ) > count( $this->mCategories ) ) {
 685+ # if there was no previous errors, hightlight the whole row
 686+ if ( $this->getState() == '' ) {
 687+ foreach( $row as &$cell ) {
 688+ QP_Renderer::addClass( $cell, 'error' );
 689+ }
 690+ }
 691+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_unique' ), 'error' ) . $text;
 692+ $rawClass = 'proposalerror';
 693+ }
 694+ }
 695+ $inp[ 'class' ] = 'check';
 696+ $inp[ 'type' ] = $inputType;
 697+ $inp[ 'name' ] = $name;
 698+ $inp[ 'value' ] = $value;
 699+ if ( $this->showResults['type'] != 0 ) {
 700+ # there ars some stat in row (not necessarily all cells, because size of question table changes dynamically)
 701+ $row[ $catId ][ 0 ] = $this->{'addShowResults' . $this->showResults['type']}( $inp, $proposalId, $catId );
 702+ } else {
 703+ $row[ $catId ][ 0 ] = $inp;
 704+ }
 705+ }
 706+ # If the proposal text is empty, the question has a syntax error.
 707+ if( trim( $text ) == '' ) {
 708+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_proposal_text_empty' ), 'error' );
 709+ foreach( $row as &$cell ) {
 710+ QP_Renderer::addClass( $cell, 'error' );
 711+ }
 712+ $rawClass = 'proposalerror';
 713+ }
 714+ # If the proposal was submitted but unanswered
 715+ if ( $this->mBeingCorrected && !array_key_exists( $proposalId, $this->mProposalCategoryId ) ) {
 716+ # if there was no previous errors, hightlight the whole row
 717+ if ( $this->getState() == '' ) {
 718+ foreach( $row as &$cell ) {
 719+ QP_Renderer::addClass( $cell, 'error' );
 720+ }
 721+ }
 722+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_no_answer' ), 'NA' ) . $text;
 723+ $rawClass = 'proposalerror';
 724+ }
 725+ if ( $text !== null ) {
 726+ $text = array( '__tag'=>'td', '__end'=>"\n", 'class'=>'proposaltext', 'style'=>$this->proposalTextStyle, 0=>$this->parser->recursiveTagParse( $text, $this->ppframe ) );
 727+ if ( $this->proposalsFirst ) {
 728+ # first element is proposaltext
 729+ array_unshift( $row, $text );
 730+ } else {
 731+ # last element is proposaltext
 732+ $row[] = $text;
 733+ }
 734+ $this->addRow( $row, array( 'class'=>$rawClass ), 'td' );
 735+ }
 736+ }
 737+ }
 738+
 739+ function mixedChoiceParseBody() {
 740+ # Parameters used in some special cases.
 741+ $this->mProposalPattern = '`^';
 742+ foreach ( $this->mCategories as $catDesc ) {
 743+ $this->mProposalPattern .= '(\[\]|\(\)|<>)';
 744+ }
 745+ $this->mProposalPattern .= '(.*)`u';
 746+ $proposalId = -1;
 747+ foreach( $this->raws as $raw ) {
 748+ # empty proposal text and row
 749+ $text = null;
 750+ $row = Array();
 751+ if ( preg_match( $this->mProposalPattern, $raw, $matches ) ) {
 752+ $text = array_pop( $matches ); // current proposal text
 753+ array_shift( $matches ); // remove "at whole" match
 754+ $last_matches = $matches;
 755+ } else {
 756+ if ( $proposalId >= 0 ) {
 757+ # shortened syntax: use the pattern from the last row where it's been defined
 758+ $text = $raw;
 759+ $matches = $last_matches;
 760+ }
 761+ }
 762+ if ( $text === null ) {
 763+ continue;
 764+ }
 765+ $proposalId++;
 766+ $rawClass = 'proposal';
 767+ $this->mProposalText[ $proposalId ] = trim( $text );
 768+ # Determine a type ID, according to the questionType and the number of signes.
 769+ foreach ( $this->mCategories as $catId => $catDesc ) {
 770+ $typeId = $matches[ $catId ];
 771+ $row[ $catId ] = Array();
 772+ $inp = Array( '__tag'=>'input' );
 773+ # Determine the input's name and value.
 774+ switch ( $typeId ) {
 775+ case '<>':
 776+ $name = 'q' . $this->mQuestionId . 'p' . $proposalId . 's' . $catId;
 777+ $value = '';
 778+ $inputType = 'text';
 779+ break;
 780+ case '[]':
 781+ $name = 'q' . $this->mQuestionId . 'p' . $proposalId . 's' . $catId;
 782+ $value = 's' . $catId;
 783+ $inputType = 'checkbox';
 784+ break;
 785+ case '()':
 786+ $name = 'q' . $this->mQuestionId . 'p' . $proposalId . 's' . $catId;
 787+ $value = 's' . $catId;
 788+ $inputType = 'radio';
 789+ break;
 790+ }
 791+ # Determine if the input has to be checked.
 792+ $input_checked = false;
 793+ $text_answer = '';
 794+ if ( $this->mBeingCorrected && $this->mRequest->getVal( $name ) !== null ) {
 795+ if ( $inputType == 'text' ) {
 796+ $text_answer = trim( $this->mRequest->getText( $name ) );
 797+ if ( strlen( $text_answer ) > QP_MAX_TEXT_ANSWER_LENGTH ) {
 798+ $text_answer = substr( $text_answer, 0, QP_MAX_TEXT_ANSWER_LENGTH );
 799+ }
 800+ if ( $text_answer != '' ) {
 801+ $input_checked = true;
 802+ }
 803+ } else {
 804+ $inp[ 'checked' ] = 'checked';
 805+ $input_checked = true;
 806+ }
 807+ }
 808+ if ( ( $prev_text_answer = $this->answerExists( $inputType, $proposalId, $catId ) ) !== false ) {
 809+ $input_checked = true;
 810+ if ( $inputType == 'text' ) {
 811+ $text_answer = $prev_text_answer;
 812+ } else {
 813+ $inp[ 'checked' ] = 'checked';
 814+ }
 815+ }
 816+ if ( $input_checked === true ) {
 817+ # add category to the list of user answers for current proposal (row)
 818+ $this->mProposalCategoryId[ $proposalId ][] = $catId;
 819+ $this->mProposalCategoryText[ $proposalId ][] = $text_answer;
 820+ }
 821+ $row[ $catId ][ 'class' ] = 'sign';
 822+ # unique (question,proposal,category) "coordinate" for javascript
 823+ $inp[ 'id' ] = 'mx' . $this->mQuestionId . 'p' . $proposalId . 'c' . $catId;
 824+ $inp[ 'class' ] = 'check';
 825+ $inp[ 'type' ] = $inputType;
 826+ $inp[ 'name' ] = $name;
 827+ if ( $inputType == 'text' ) {
 828+ $inp[ 'value' ] = qp_Setup::specialchars( $text_answer );
 829+ if ( $this->textInputStyle != '' ) {
 830+ $inp[ 'style' ] = $this->textInputStyle;
 831+ }
 832+ } else {
 833+ $inp[ 'value' ] = $value;
 834+ }
 835+ if ( $this->showResults['type'] != 0 ) {
 836+ # there ars some stat in row (not necessarily all cells, because size of question table changes dynamically)
 837+ $row[ $catId ][ 0 ] = $this->{'addShowResults' . $this->showResults['type']}( $inp, $proposalId, $catId );
 838+ } else {
 839+ $row[ $catId ][ 0 ] = $inp;
 840+ }
 841+ }
 842+ try {
 843+ # if there is only one category defined and it is not a textfield,
 844+ # the question has a syntax error
 845+ if ( count( $matches ) < 2 && $matches[0] != '<>' ) {
 846+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_too_few_categories' ), 'error' );
 847+ throw new Exception( 'qp_error' );
 848+ }
 849+ # If the proposal text is empty, the question has a syntax error.
 850+ if( trim( $text ) == '' ) {
 851+ $text = $this->bodyErrorMessage( wfMsg( "qp_error_proposal_text_empty" ), "error" );
 852+ throw new Exception( 'qp_error' );
 853+ }
 854+ # If the proposal was submitted but unanswered
 855+ if ( $this->mBeingCorrected && !array_key_exists( $proposalId, $this->mProposalCategoryId ) ) {
 856+ $prev_state = $this->getState();
 857+ $text = $this->bodyErrorMessage( wfMsg( 'qp_error_no_answer' ), 'NA' ) . $text;
 858+ # if there was no previous errors, hightlight the whole row
 859+ if ( $prev_state == '' ) {
 860+ throw new Exception( 'qp_error' );
 861+ }
 862+ }
 863+ } catch( Exception $e ) {
 864+ if ( $e->getMessage() == 'qp_error' ) {
 865+ foreach( $row as &$cell ) {
 866+ QP_Renderer::addClass( $cell, 'error' );
 867+ }
 868+ $rawClass = 'proposalerror';
 869+ } else {
 870+ throw new MWException( $e->getMessage() );
 871+ }
 872+ }
 873+ $text = array( '__tag'=>'td', '__end'=>"\n", 'class'=>'proposaltext', 'style'=>$this->proposalTextStyle, 0=>$this->parser->recursiveTagParse( $text, $this->ppframe ) );
 874+ if ( $this->proposalsFirst ) {
 875+ # first element is proposaltext
 876+ array_unshift( $row, $text );
 877+ } else {
 878+ # last element is proposaltext
 879+ $row[] = $text;
 880+ }
 881+ $this->addRow( $row, array( 'class'=>$rawClass ), 'td' );
 882+ }
 883+ return qp_Renderer::renderHTMLobject( $this->mRenderTable );
 884+ }
 885+
 886+ /**
 887+ * build internal & visual representation of question categories
 888+ *
 889+ * @param $input the raw source of categories
 890+ */
 891+ function parseCategories( $input ) {
 892+ $row = Array();
 893+ if ( $this->proposalsFirst ) {
 894+ // add empty <th> at the begin of row to "compensate" proposal text
 895+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 896+ }
 897+ # build "raw" categories array
 898+ # split tokens
 899+ $cat_split = preg_split( '`({{|}}|\[\[|\]\]|\|)`u', $input, -1, PREG_SPLIT_DELIM_CAPTURE );
 900+ $matching_braces = Array();
 901+ $curr_elem = '';
 902+ $categories = Array();
 903+ foreach( $cat_split as $part ) {
 904+ switch ($part) {
 905+ case '|' :
 906+ if ( count( $matching_braces ) == 0 ) {
 907+ # delimeters are working only when braces are completely closed
 908+ $categories[] = $curr_elem;
 909+ $curr_elem = '';
 910+ $part = '';
 911+ }
 912+ break;
 913+ case '[[' :
 914+ case '{{' :
 915+ if ( $part == '[[' ) {
 916+ $last_brace = ']]';
 917+ } else {
 918+ $last_brace = '}}';
 919+ }
 920+ array_push( $matching_braces, $last_brace );
 921+ break;
 922+ case ']]' :
 923+ case '}}' :
 924+ if ( count( $matching_braces ) > 0 ) {
 925+ $last_brace = array_pop( $matching_braces );
 926+ if ( $last_brace != $part ) {
 927+ array_push( $matching_braces, $last_brace );
 928+ }
 929+ }
 930+ break;
 931+ }
 932+ $curr_elem .= $part;
 933+ }
 934+ if ( $curr_elem != '' ) {
 935+ $categories[] = $curr_elem;
 936+ }
 937+ $categories = array_map( 'trim', $categories );
 938+ # analyze previousely build "raw" categories array
 939+ # Less than two categories is a syntax error.
 940+ if ( $this->mType != 'mixedChoice' && count( $categories ) < 2 ) {
 941+ $categories[0] .= $this->bodyErrorMessage( wfMsg( 'qp_error_too_few_categories' ), 'error' );
 942+ }
 943+ foreach( $categories as $catkey => $category ) {
 944+ # If a category name is empty, the question has a syntax error.
 945+ if( $category == '' ) {
 946+ $category = $this->bodyErrorMessage( wfMsg( 'qp_error_category_name_empty' ), 'error' );
 947+ }
 948+ $this->mCategories[ $catkey ]["name"] = $category;
 949+ $row[] = $this->parser->recursiveTagParse( $category, $this->ppframe );
 950+ }
 951+
 952+ # cut unused categories rows which are presented in DB but were removed from article
 953+ $this->mCategories = array_slice( $this->mCategories, 0, count( $categories ) );
 954+ if ( !$this->proposalsFirst ) {
 955+ // add empty <th> at the end of row to "compensate" proposal text
 956+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 957+ }
 958+ return $row;
 959+ }
 960+
 961+ /**
 962+ * build internal & visual representation of question category spans
 963+ * ( also known as metacategories or "category groups" )
 964+ *
 965+ * @param $input the raw source of category spans
 966+ */
 967+ # warning: parseCategorySpans() should be called after parseCategories()
 968+ function parseCategorySpans( $input ) {
 969+ $row = Array();
 970+ if ( $this->mType == "singleChoice" ) {
 971+ # real category spans have sense only for radiobuttons
 972+ # build "raw" spans array
 973+ # split tokens
 974+ $span_split = preg_split( '`({{|}}|\[\[|\]\]|\||\!)`u', $input, -1, PREG_SPLIT_DELIM_CAPTURE );
 975+ $matching_braces = Array();
 976+ $curr_elem = null;
 977+ $spans = Array();
 978+ if ( isset( $span_split[0] ) && $span_split[0] == '' ) {
 979+ array_shift( $span_split );
 980+ if ( isset( $span_split[0] ) && in_array( $span_split[0], array( '!', '|' ) ) ) {
 981+ $delim = $span_split[0];
 982+ foreach( $span_split as $part ) {
 983+ if ( $part == $delim ) {
 984+ if ( count( $matching_braces ) == 0 ) {
 985+ # delimeters are working only when braces are completely closed
 986+ $spans[0][] = $part;
 987+ if ( $curr_elem !== null ) {
 988+ $spans[1][] = $curr_elem;
 989+ }
 990+ $curr_elem = '';
 991+ $part = '';
 992+ }
 993+ } else {
 994+ switch ( $part ) {
 995+ case '[[' :
 996+ case '{{' :
 997+ if ( $part == '[[' ) {
 998+ $last_brace = ']]';
 999+ } else {
 1000+ $last_brace = '}}';
 1001+ }
 1002+ array_push ( $matching_braces, $last_brace );
 1003+ break;
 1004+ case ']]' :
 1005+ case '}}' :
 1006+ if ( count( $matching_braces ) > 0 ) {
 1007+ $last_brace = array_pop( $matching_braces );
 1008+ if ( $last_brace != $part ) {
 1009+ array_push( $matching_braces, $last_brace );
 1010+ }
 1011+ }
 1012+ break;
 1013+ }
 1014+ }
 1015+ $curr_elem .= $part;
 1016+ }
 1017+ if ( $curr_elem !== null ) {
 1018+ $spans[1][] = $curr_elem;
 1019+ } else {
 1020+ $curr_elem = '';
 1021+ }
 1022+ }
 1023+ }
 1024+ # analyze previousely build "raw" spans array
 1025+ # Less than one span is a syntax error.
 1026+ if(!array_key_exists(0, $spans)) {
 1027+ return $this->bodyErrorMessage( wfMsg( "qp_error_too_few_spans" ), "error" );
 1028+ }
 1029+ # fill undefined spans with the last span value
 1030+ $SpanCategDelta = count( $this->mCategories ) - count( $spans[0] );
 1031+ # temporary var $diff used to avoid warning in E_STRICT mode
 1032+ $diff = array_diff( array_keys( $spans[1] ), array_keys( $spans[1], "", true ) );
 1033+ $lastDefinedSpanKey = array_pop( $diff );
 1034+ unset( $diff );
 1035+ if ($lastDefinedSpanKey !== null) {
 1036+ if ( $SpanCategDelta > 0 ) {
 1037+ # increase the length of last defined span value to match total lenth of categories
 1038+ $lastSpanType = $spans[0][$lastDefinedSpanKey];
 1039+ $spans[0] = array_merge( array_slice( $spans[0], 0, $lastDefinedSpanKey ),
 1040+ array_fill( 0, $SpanCategDelta, $lastSpanType ),
 1041+ array_slice( $spans[0], $lastDefinedSpanKey ) );
 1042+ $spans[1] = array_merge( array_slice( $spans[1], 0, $lastDefinedSpanKey ),
 1043+ array_fill( 0, $SpanCategDelta, "" ),
 1044+ array_slice( $spans[1], $lastDefinedSpanKey ) );
 1045+ } elseif ( $SpanCategDelta < 0 ) {
 1046+ # cut unused but defined extra spans
 1047+ $spans[0] = array_slice( $spans[0], count( $this->mCategories ), -$SpanCategDelta );
 1048+ $spans[1] = array_slice( $spans[1], count( $this->mCategories ), -$SpanCategDelta );
 1049+ }
 1050+ } else {
 1051+ # no valid category spans are defined
 1052+ return $this->bodyErrorMessage( wfMsg( 'qp_error_too_few_spans' ), 'error' );
 1053+ }
 1054+ # populate mCategorySpans and row
 1055+ if ( $this->proposalsFirst ) {
 1056+ // add empty <th> at the begin of row to "compensate" proposal text
 1057+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 1058+ }
 1059+ $colspanBase = ( $lastDefinedSpanKey == 0 ) ? 1 : 0;
 1060+ $colspan = 1;
 1061+ $categorySpanId = 0;
 1062+ foreach($spans[0] as $spanKey => $spanType) {
 1063+ $spanCategory = trim( $spans[1][$spanKey] );
 1064+ if ( $spanCategory=="" ) {
 1065+ $colspan++;
 1066+ } else {
 1067+ $row[] = array( "count"=>$colspan + $colspanBase, 0=>$this->parser->recursiveTagParse( $spanCategory, $this->ppframe ) );
 1068+ if ( $spanType == "|") { // "!" is a comment header, not a real category span
 1069+ $this->mCategorySpans[ $categorySpanId ]['name'] = $spanCategory;
 1070+ $this->mCategorySpans[ $categorySpanId ]['count'] = $colspan;
 1071+ for ( $i = $spanKey;
 1072+ $i >=0 && array_key_exists( $i, $this->mCategories ) && !array_key_exists( 'spanId', $this->mCategories[ $i ] );
 1073+ $i-- ) {
 1074+ $this->mCategories[$i]['spanId'] = $categorySpanId;
 1075+ }
 1076+ $categorySpanId++;
 1077+ }
 1078+ $colspan = 1;
 1079+ }
 1080+ }
 1081+ if ( !$this->proposalsFirst ) {
 1082+ // add empty <th> at the end of row to "compensate" proposal text
 1083+ $row[] = array( '__tag'=>'td', 0=>"", 'style'=>'border:none;', '__end'=>"\n" );
 1084+ }
 1085+ }
 1086+ return $row;
 1087+ }
 1088+
 1089+ function isUniqueProposalCategoryId( $proposalId, $catId ) {
 1090+ foreach( $this->mProposalCategoryId as $proposalCategoryId ) {
 1091+ if ( in_array( $catId, $proposalCategoryId ) ) {
 1092+ return false;
 1093+ }
 1094+ }
 1095+ return true;
 1096+ }
 1097+
 1098+ /*** cell templates ***/
 1099+
 1100+ # cell templates for the selected showresults
 1101+ var $cellTemplate = Array();
 1102+ var $cellTemplateParam = Array( 'inp'=>'', 'percents'=>'', 'bar1style'=>'', 'bar2style'=>'' );
 1103+
 1104+ # setup a template for showresults=1
 1105+ # showresults=1 cellTemplate has only one variant
 1106+ function cellTemplate1() {
 1107+ $this->cellTemplate =
 1108+ array(
 1109+ 0=>array( '__tag'=>'div', 0=>&$this->cellTemplateParam['inp'] ),
 1110+ 1=>array( '__tag'=>'div', 'class'=>'stats', 0=>&$this->cellTemplateParam['percents'] )
 1111+ );
 1112+ if ( isset( $this->showResults['color'] ) ) {
 1113+ $this->cellTemplate[1]['style'] = 'color:' . $this->showResults['color'] . ';';
 1114+ }
 1115+ if ( isset( $this->showResults['background'] ) ) {
 1116+ $this->cellTemplate[1]['style'] .= 'background:' . $this->showResults['background'] . ';';
 1117+ }
 1118+ }
 1119+
 1120+ # transform input according to showresults=1 (numerical percents)
 1121+ # *** warning! parameters should be passed only by value, not by reference ***
 1122+ function addShowResults1( $inp, $proposalId, $catId ) {
 1123+ $this->cellTemplateParam['inp'] = $inp;
 1124+ $this->cellTemplateParam['percents'] = '&#160;';
 1125+ if ( ( $percents = $this->getPercents( $proposalId, $catId ) ) !== false ) {
 1126+ # there is a stat in cell
 1127+ $this->cellTemplateParam['percents'] = $percents . '%';
 1128+ # template has to be rendered immediately, because $this->cellTemplateParam[] are used as pointers and thus,
 1129+ # will always be overwritten
 1130+ return QP_Renderer::renderHTMLobject( $this->cellTemplate );
 1131+ } else {
 1132+ return $inp;
 1133+ }
 1134+ }
 1135+
 1136+ # setup a template for showresults=2
 1137+ function cellTemplate2() {
 1138+ # statical styles
 1139+ $percentstyle = '';
 1140+ if ( isset( $this->showResults['textcolor'] ) ) {
 1141+ $percentstyle = 'color:' . $this->showResults['textcolor'] . ';';
 1142+ }
 1143+ if ( isset( $this->showResults['textbackground'] ) ) {
 1144+ $percentstyle .= 'background:' . $this->showResults['textbackground'] . ';';
 1145+ }
 1146+ # html arrays used in templates below
 1147+ $bar = array( '__tag'=>'div', 'class'=>'stats1',
 1148+ 0=>array( '__tag'=>'div', 'class'=>'bar0', 0=>&$this->cellTemplateParam['inp'] ),
 1149+ 1=>array( '__tag'=>'div', 'class'=>'bar1', 'style'=>&$this->cellTemplateParam['bar1style'], 0=>'&#160;' ),
 1150+ 2=>array( '__tag'=>'div', 'class'=>'bar2', 'style'=>&$this->cellTemplateParam['bar2style'], 0=>'&#160;' ),
 1151+ 3=>array( '__tag'=>'div', 'class'=>'bar0', 'style'=>$percentstyle, 0=>&$this->cellTemplateParam['percents'] )
 1152+ );
 1153+ $bar2 = array( '__tag'=>'div', 'class'=>'stats1',
 1154+ 0=>array( '__tag'=>'div', 'class'=>'bar0', 0=>'&#160;' ),
 1155+ 1=>&$bar[1],
 1156+ 2=>&$bar[2],
 1157+ 3=>&$bar[3]
 1158+ );
 1159+ # has two available templates ('bar','textinput')
 1160+ $this->cellTemplate = array(
 1161+ 'bar'=>$bar,
 1162+ 'textinput'=>array( '__tag'=>'table', 'class'=>'stats',
 1163+ 0=>array( '__tag'=>'tr',
 1164+ 0=>array( '__tag'=>'td', 0=>&$this->cellTemplateParam['inp'] ),
 1165+ ),
 1166+ 1=>array( '__tag'=>'tr',
 1167+ 0=>array( '__tag'=>'td',
 1168+ 0=>$bar2
 1169+ )
 1170+ )
 1171+ ),
 1172+ # the following entries are not real templates, but pre-calculated values of css attributes taken from showresults parameter
 1173+ 'bar1showres'=>'',
 1174+ 'bar2showres'=>''
 1175+ );
 1176+ # dynamical styles, width: in percents will be added during rendering in addShowResults
 1177+ if ( isset( $this->showResults['color'] ) ) {
 1178+ $this->cellTemplate['bar1showres'] .= 'background:' . $this->showResults['color'] . ';';
 1179+ }
 1180+ if ( isset( $this->showResults['background'] ) ) {
 1181+ $this->cellTemplate['bar2showres'] .= 'background:' . $this->showResults['background'] . ';';
 1182+ }
 1183+ }
 1184+
 1185+ # transform input according to showresults=2 (bars)
 1186+ # *** warning! parameters should be passed only by value, not by reference ***
 1187+ function addShowResults2( $inp, $proposalId, $catId ) {
 1188+ $this->cellTemplateParam['inp'] = $inp;
 1189+ $this->cellTemplateParam['percents'] = '&#160;';
 1190+ if ( ( $percents = $this->getPercents( $proposalId, $catId ) ) !== false ) {
 1191+ # there is a stat in cell
 1192+ $this->cellTemplateParam['percents'] = $percents . '%';
 1193+ $this->cellTemplateParam['bar1style'] = 'width:' . $percents . 'px;' . $this->cellTemplate[ 'bar1showres' ];
 1194+ $this->cellTemplateParam['bar2style'] = 'width:' . (100 - $percents) . 'px;' . $this->cellTemplate[ 'bar2showres' ];
 1195+ if ( $inp['type'] == 'text' ) {
 1196+ return qp_Renderer::renderHTMLobject( $this->cellTemplate['textinput'] );
 1197+ } else {
 1198+ return qp_Renderer::renderHTMLobject( $this->cellTemplate['bar'] );
 1199+ }
 1200+ } else {
 1201+ return $inp;
 1202+ }
 1203+ }
 1204+
 1205+ /*** end of cell templates ***/
 1206+
 1207+}
Property changes on: trunk/extensions/QPoll/qp_question.php
___________________________________________________________________
Added: svn:eol-style
11208 + native
Index: trunk/extensions/QPoll/qpoll.src
@@ -0,0 +1,62 @@
 2+CREATE TABLE /*$wgDBprefix*/qp_poll_desc (
 3+ `pid` int unsigned NOT NULL auto_increment,
 4+ `article_id` int unsigned NOT NULL,
 5+ `poll_id` tinytext NOT NULL,
 6+ `order_id` int unsigned NOT NULL,
 7+ `dependance` mediumtext NOT NULL,
 8+ PRIMARY KEY poll (pid),
 9+ UNIQUE INDEX article_poll (article_id,poll_id(128))
 10+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 11+
 12+CREATE TABLE /*$wgDBprefix*/qp_question_desc (
 13+ `pid` int unsigned NOT NULL,
 14+ `question_id` int unsigned NOT NULL,
 15+ `type` tinytext NOT NULL,
 16+ `common_question` mediumtext NOT NULL,
 17+ PRIMARY KEY question (pid,question_id),
 18+ INDEX poll (pid)
 19+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 20+
 21+CREATE TABLE /*$wgDBprefix*/qp_question_categories (
 22+ `pid` int unsigned NOT NULL,
 23+ `question_id` int unsigned NOT NULL,
 24+ `cat_id` int unsigned NOT NULL,
 25+ `cat_name` tinytext NOT NULL,
 26+ PRIMARY KEY category (pid,question_id,cat_id),
 27+ INDEX poll (pid)
 28+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 29+
 30+CREATE TABLE /*$wgDBprefix*/qp_question_proposals (
 31+ `pid` int unsigned NOT NULL,
 32+ `question_id` int unsigned NOT NULL,
 33+ `proposal_id` int unsigned NOT NULL,
 34+ `proposal_text` tinytext NOT NULL,
 35+ PRIMARY KEY proposal (pid,question_id,proposal_id),
 36+ INDEX poll (pid)
 37+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 38+
 39+CREATE TABLE /*$wgDBprefix*/qp_question_answers (
 40+ `uid` int unsigned NOT NULL,
 41+ `pid` int unsigned NOT NULL,
 42+ `question_id` int unsigned NOT NULL,
 43+ `proposal_id` int unsigned NOT NULL,
 44+ `cat_id` int unsigned NOT NULL,
 45+ `text_answer` mediumtext,
 46+ PRIMARY KEY answer (uid,pid,question_id,proposal_id,cat_id),
 47+ INDEX user_vote (uid,pid),
 48+ INDEX poll_question (pid,question_id)
 49+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 50+
 51+CREATE TABLE /*$wgDBprefix*/qp_users_polls (
 52+ `uid` int unsigned NOT NULL,
 53+ `pid` int unsigned NOT NULL,
 54+ PRIMARY KEY user_poll (uid,pid)
 55+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 56+
 57+CREATE TABLE /*$wgDBprefix*/qp_users (
 58+ `uid` int unsigned NOT NULL auto_increment,
 59+ `name` tinytext NOT NULL,
 60+ PRIMARY KEY unique_name (uid,name(64)),
 61+ INDEX user_id (uid),
 62+ INDEX username (name(64))
 63+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Property changes on: trunk/extensions/QPoll/qpoll.src
___________________________________________________________________
Added: svn:eol-style
164 + native

Status & tagging log