r58543 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r58542‎ | r58543 | r58544 >
Date:14:21, 4 November 2009
Author:catrope
Status:deferred
Tags:
Comment:
acaifix branch: Add ClickTracking extension (trunk r58205, with r58224 merged in)
Modified paths:
  • /branches/usability/acaifix/ClickTracking (added) (history)

Diff [purge]

Index: branches/usability/acaifix/ClickTracking/SpecialClickTracking.php
@@ -0,0 +1,647 @@
 2+<?php
 3+/**
 4+ * Special:ClickTracking
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+class SpecialClickTracking extends SpecialPage {
 11+
 12+ private static $minimum_date = '20091009'; //YYYYMMDD (+1 for today)
 13+
 14+ private static $userTypes = array("basic" => 0, "intermediate" => 1, "expert" => 2);
 15+ private $user_defs = array();
 16+
 17+
 18+ function __construct() {
 19+ parent::__construct( 'ClickTracking' , 'clicktrack');
 20+ wfLoadExtensionMessages( 'ClickTracking' );
 21+ UsabilityInitiativeHooks::initialize();
 22+ UsabilityInitiativeHooks::addStyle( 'ClickTracking/SpecialClickTracking.css' );
 23+ UsabilityInitiativeHooks::addScript( 'ClickTracking/SpecialClickTracking.js' );
 24+ }
 25+
 26+
 27+ function setDefaults(){
 28+ $this->user_defs["basic"] = array(
 29+ "anonymous" => "1",
 30+ "total_contribs" => array(
 31+ array("operation" => "<=", "value" => "10"),
 32+ ),
 33+ );
 34+
 35+ $this->user_defs["intermediate"] = array(
 36+ "anonymous" => "0",
 37+ "total_contribs" => array(
 38+ array("operation" => "<", "value" => "400"),
 39+ array("operation" => ">", "value" => "10"),
 40+ ),
 41+ );
 42+
 43+ $this->user_defs["expert"] = array(
 44+ "anonymous" => "0",
 45+ "total_contribs" => array(
 46+ array("operation" => ">=", "value" => "400"),
 47+ ),
 48+ );
 49+
 50+
 51+ }
 52+
 53+
 54+
 55+ function execute( $par ) {
 56+ global $wgOut, $wgUser;
 57+
 58+ // Check permissions
 59+ if ( !$this->userCanExecute( $wgUser ) ) {
 60+ $this->displayRestrictionError();
 61+ return;
 62+ }
 63+
 64+
 65+ $this->setHeaders();
 66+ $this->setDefaults();
 67+
 68+ $wgOut->addScript('<script type="text/javascript">'. "var wgClickTrackUserDefs = ".json_encode($this->user_defs). '</script>');
 69+
 70+ $wgOut->setPageTitle( wfMsg( 'ct-title' ) );
 71+
 72+ $outputTable ="";
 73+
 74+
 75+ //grab top N
 76+ $events = $this->getTopEvents();
 77+
 78+ //open table
 79+ $outputTable .= Xml::openElement( "table", array( "class" =>"sortable click-data", "id" => "clicktrack_data_table" ) );
 80+
 81+ //create a row for every event
 82+ $i = 0;
 83+ $db_result;
 84+
 85+ //build row headers
 86+ $header_row = array();
 87+
 88+ $header_row["event_header"] = wfMsg( 'ct-event-name' );
 89+ $header_row["expert_header"] = wfMsg( 'ct-expert-header' );
 90+ $header_row["intermediate_header"] = wfMsg( 'ct-intermediate-header' );
 91+ $header_row["basic_header"] = wfMsg( 'ct-beginner-header' );
 92+ $header_row["total_header"] = wfMsg( 'ct-total-header' );
 93+ $outputTable .= Xml::buildTableRow( array( "class"=>"table_headers" ), $header_row );
 94+
 95+ //foreach event, build a row
 96+ while(($db_result = $events->fetchRow()) != null){
 97+ ++$i;
 98+ $outputTable .= $this->buildRow( $db_result, $i, $this->user_defs);
 99+ }
 100+
 101+
 102+ //close table
 103+ $outputTable .= Xml::closeElement("table");
 104+
 105+ $wgOut->addHTML( $outputTable );
 106+
 107+ $wgOut->addHTML($this->buildDateRange());
 108+
 109+ //build chart
 110+ $wgOut->addHTML($this->buildChart("advanced.hide",10, "20090815", "20090902", 1));
 111+
 112+ //$wgOut->addHTML($this->buildControlBox());
 113+
 114+ $wgOut->addHTML($this->buildChartDialog());
 115+ $wgOut->addHTML($this->buildUserDefBlankDialog());
 116+
 117+ }
 118+
 119+
 120+ /**
 121+ * Gets the data to build a chart for PHP or JS purposes
 122+ * @param $event_id event id this chart is for
 123+ * @param $minTime minimum day
 124+ * @param $maxTime maximum day
 125+ * @param $increment number of day(s) to increment in units
 126+ * @param $userDefs user defintions
 127+ * @param $isUserDefsJSON true if userDefs is JSON
 128+ * @return array with chart info
 129+ */
 130+ static function getChartData($event_id, $minTime, $maxTime, $increment, $userDefs, $isUserDefsJSON=true){
 131+ //get data
 132+ date_default_timezone_set('UTC');
 133+
 134+ if($maxTime == 0){
 135+ $maxTime = gmdate("Ymd",time()); //today
 136+ }
 137+ if($minTime == 0){
 138+ $minTime = self::$minimum_date;
 139+ }
 140+
 141+
 142+ //FIXME: On PHP 5.3+, this will be MUCH cleaner
 143+ $currBeginDate = new DateTime( $minTime );
 144+ $currEndDate = new DateTime( $minTime );
 145+ $endDate = new DateTime( $maxTime );
 146+
 147+
 148+ //get user definitions
 149+ if($isUserDefsJSON){
 150+ $userDefs = json_decode($userDefs, true);
 151+ }
 152+
 153+ $basicUserData = array();
 154+ $intermediateUserData = array();
 155+ $expertUserData = array();
 156+
 157+ // PHP 5.3...hurry!
 158+ $plural = ( $increment == 1 ? "" : "s" );
 159+
 160+ while( $currEndDate->format( "U" ) < $endDate->format( "U" ) ){
 161+ $currEndDate->modify( "+$increment day$plural" );
 162+
 163+ $minDate = $currBeginDate->format("Ymd");
 164+ $maxDate = $currEndDate->format("Ymd");
 165+
 166+ $basicUserData[] = self::getTableValue( $event_id, $userDefs['basic'], $minDate, $maxDate );
 167+ $intermediateUserData[] = self::getTableValue( $event_id, $userDefs['intermediate'], $minDate, $maxDate );
 168+ $expertUserData[] = self::getTableValue( $event_id, $userDefs['expert'], $minDate, $maxDate );
 169+ $currBeginDate->modify( "+$increment day$plural" );
 170+ }
 171+ return array("expert" => $expertUserData, "basic" => $basicUserData, "intermediate" => $intermediateUserData);
 172+ }
 173+
 174+ function buildChart($event_name, $event_id, $minTime, $maxTime, $increment){
 175+ $chartData = self::getChartData($event_id, $minTime, $maxTime, $increment, $this->user_defs, false);
 176+ $chartSrc = $this->getGoogleChartParams( $event_id, $event_name, $minTime, $maxTime, $chartData["basic"], $chartData["intermediate"], $chartData["expert"]);
 177+ return Xml::element( 'img', array( 'src' => $chartSrc , 'id' => 'chart_img' ) );
 178+ }
 179+
 180+
 181+ function getGoogleChartParams( $event_id, $event_name, $minDate, $maxDate, $basicUserData, $intermediateUserData, $expertUserData ) {
 182+ $max = max( max($basicUserData), max($intermediateUserData), max($expertUserData));
 183+ return "http://chart.apis.google.com/chart?" . wfArrayToCGI(
 184+ array(
 185+ 'chs' => '400x400',
 186+ 'cht' => 'lc',
 187+ 'chco' => 'FF0000,0000FF,00FF00',
 188+ 'chtt' => "$event_name from $minDate to $maxDate",
 189+ 'chdl' => 'Expert|Intermediate|Beginner',
 190+ 'chxt' => 'x,y',
 191+ 'chd' => 't:' . implode( "," , $expertUserData ) . "|" .
 192+ implode( "," , $intermediateUserData ) . "|" . implode( "," , $basicUserData ),
 193+ 'chds' => "0,$max,0,$max,0,$max"
 194+ ));
 195+ }
 196+
 197+
 198+ function buildUserDefBlankDialog(){
 199+ $control = "";
 200+ $control .= Xml::openElement("div", array("id" => "user_def_dialog", "class" => "dialog"));
 201+
 202+ //currently editing...----|
 203+ $control .= Xml::openElement("form", array("id" => "user_definition_form", "class" => "user_def_form"));
 204+ $control .= Xml::openElement("fieldset", array("id" => "user_def_alter_fieldset"));
 205+ $control .= Xml::openElement("legend", array("id" => "user_def_alter_legend"));
 206+ $control .= wfMsg( "editing" );
 207+ $control .= Xml::closeElement("legend");
 208+
 209+ //[] anonymous users?
 210+ $control .= Xml::openElement("div", array("id" => "anon_users_div", "class" => "checkbox_div control_div"));
 211+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "anon_users_checkbox", "class" => "user_def_checkbox"));
 212+ $control .= Xml::closeElement("input");
 213+ $control .= wfMsg("anon-users");
 214+ $control .= Xml::closeElement("div");
 215+
 216+ // ----------------
 217+ $control .= Xml::openElement("hr");
 218+ $control .= Xml::closeElement("hr");
 219+ $control .= Xml::openElement("div", array("id" => "contrib_opts_container"));
 220+
 221+ // [] users with contributions [>=V] [n ]
 222+ $control .= Xml::openElement("div", array("id" => "total_users_contrib_div", "class" => "checkbox_div control_div"));
 223+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_checkbox", "class" => "user_def_checkbox"));
 224+ $control .= Xml::closeElement("input");
 225+ $control .= wfMsg("user-contribs");
 226+
 227+
 228+ $control .= Xml::closeElement("div");
 229+
 230+ // [] contributions in timespan 1
 231+ $control .= Xml::openElement("div", array("id" => "contrib_span_1_div", "class" => "checkbox_div control_div"));
 232+
 233+ $control .= Xml::openElement("div", array("id" => "contrib_span_1_text_div", "class" => "checkbox_div"));
 234+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_1_checkbox", "class" => "user_def_checkbox"));
 235+ $control .= Xml::closeElement("input");
 236+ $control .= wfMsg("user-span") . " 1";
 237+ $control .= Xml::closeElement("div");
 238+ $control .= Xml::closeElement("div");
 239+
 240+ // [] contributions in timespan 2
 241+ $control .= Xml::openElement("div", array("id" => "contrib_span_2_div", "class" => "checkbox_div control_div"));
 242+
 243+ $control .= Xml::openElement("div", array("id" => "contrib_span_2_text_div", "class" => "checkbox_div"));
 244+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_2_checkbox", "class" => "user_def_checkbox"));
 245+ $control .= Xml::closeElement("input");
 246+ $control .= wfMsg("user-span") . " 2";
 247+ $control .= Xml::closeElement("div");
 248+ $control .= Xml::closeElement("div");
 249+
 250+ // [] contributions in timespan 3
 251+ $control .= Xml::openElement("div", array("id" => "contrib_span_3_div", "class" => "checkbox_div control_div"));
 252+
 253+ $control .= Xml::openElement("div", array("id" => "contrib_span_3_text_div", "class" => "checkbox_div"));
 254+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "contrib_span_3_checkbox", "class" => "user_def_checkbox"));
 255+ $control .= Xml::closeElement("input");
 256+ $control .= wfMsg("user-span") . " 3";
 257+ $control .= Xml::closeElement("div");
 258+ $control .= Xml::closeElement("div");
 259+
 260+
 261+
 262+
 263+ $control .= Xml::closeElement("div");//close contrib opts
 264+
 265+ $control .= Xml::closeElement("fieldset");
 266+ $control .= Xml::closeElement("form");
 267+ $control .= Xml::closeElement("div");
 268+ return $control;
 269+ }
 270+
 271+
 272+
 273+ function buildUserDefNumberSelect($include_checkbox, $include_and, $ids){
 274+ $control = "";
 275+ if($include_checkbox){
 276+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "{$ids}_checkbox", "class" => "number_select_checkbox"));
 277+ $control .= Xml::closeElement("input");
 278+ }
 279+
 280+ if($include_and){
 281+ $control .= wfMsg("ct-and");
 282+ }
 283+
 284+ $control .= Xml::openElement("select", array("id" => "{$ids}_ltgt", "class" => "number_select_ltgt"));
 285+ $control .= Xml::openElement("option", array("id" => "{$ids}_lt", "class" => "number_select_ltgt_opt", "value" => "lt"));
 286+ $control .= "&lt;=";
 287+ $control .= Xml::closeElement("option");
 288+ $control .= Xml::openElement("option", array("id" => "{$ids}_gt", "class" => "number_select_ltgt_opt", "value" => "gt"));
 289+ $control .= "&gt;=";
 290+ $control .= Xml::closeElement("option");
 291+ $control .= Xml::closeElement("select");
 292+ $control .= Xml::openElement("input", array("type" => "text", "id" => "{$ids}_text", "class" => "number_select_text"));
 293+ $control .= Xml::closeElement("input");
 294+ return $control;
 295+ }
 296+
 297+
 298+ function buildChartDialog(){
 299+ $control = "";
 300+ $control .= Xml::openElement("div", array("id" => "chart_dialog", "class" => "dialog"));
 301+
 302+ $control .= Xml::openElement("form", array("id" => "chart_dialog_form", "class" => "chart_form"));
 303+ $control .= Xml::openElement("fieldset", array("id" => "chart_dialog_alter_fieldset"));
 304+ $control .= Xml::openElement("legend", array("id" => "chart_dialog_alter_legend"));
 305+ $control .= wfMsg( "ct-increment-by" );
 306+ $control .= Xml::closeElement("legend");
 307+
 308+ $control .= Xml::openElement("table", array("id" => "chart_dialog_increment_table"));
 309+ $control .= Xml::openElement("tbody", array("id" => "chart_dialog_increment_tbody"));
 310+
 311+ $control .= Xml::openElement("tr", array("id" => "chart_dialog_increment_row"));
 312+
 313+ $control .= Xml::openElement("td", array("id" => "chart_dialog_increment_cell"));
 314+ $control .= Xml::openElement("input", array("type" => "text", "id" => "chart_increment", "class" => "chart_dialog_area", "value" => '1'));
 315+ $control .= Xml::closeElement("input");
 316+ $control .= Xml::closeElement("td");
 317+
 318+ $control .= Xml::openElement("td", array("id" => "chart_dialog_button_cell"));
 319+ $control .= Xml::openElement("input", array("type" => "button", "id" => "change_graph", "value" => wfMsg( "ct-change-graph" ) ) );
 320+ $control .= Xml::closeElement("input");
 321+ $control .= Xml::closeElement("td");
 322+
 323+ $control .= Xml::closeElement("tr");
 324+
 325+ $control .= Xml::closeElement("tbody");
 326+ $control .= Xml::closeElement("table");
 327+ $control .= Xml::closeElement("fieldset");
 328+ $control .= Xml::closeElement("form");
 329+ $control .= Xml::closeElement("div");
 330+ return $control;
 331+ }
 332+
 333+
 334+ function buildDateRange(){
 335+ $control = Xml::openElement("form", array("id" => "date_range"));
 336+
 337+ $control .= Xml::openElement("fieldset", array("id" => "date_range_fieldset"));
 338+ $control .= Xml::openElement("legend", array("id" => "date_range_legend"));
 339+ $control .= wfMsg('ct-date-range');
 340+ $control .= Xml::closeElement("legend");
 341+
 342+
 343+
 344+ $control .= Xml::openElement("table", array("id" => "date_range_table"));
 345+ $control .= Xml::openElement("tbody", array("id" => "date_range_tbody"));
 346+
 347+
 348+ $control .= Xml::openElement("tr", array("id" => "start_date_row"));
 349+
 350+ $control .= Xml::openElement("td", array("id" => "start_date_label", "class" => "date_range_label"));
 351+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "start_date_checkbox", "class" => "date_range_checkbox", "checked" => ""));
 352+ $control .= Xml::closeElement("input");
 353+ $control .= wfMsg( "ct-start-date" );
 354+ $control .= Xml::closeElement("td");
 355+
 356+ $control .= Xml::openElement("td", array("id" => "start_date_textarea"));
 357+ $control .= Xml::openElement("input", array("type" => "text", "id" => "start_date", "class" => "date_range_input"));
 358+ $control .= Xml::closeElement("input");
 359+ $control .= Xml::closeElement("td");
 360+
 361+ $control .= Xml::closeElement("tr");
 362+
 363+ $control .= Xml::openElement("tr", array("id" => "end_date_row"));
 364+
 365+ $control .= Xml::openElement("td", array("id" => "end_date_label", "class" => "date_range_label"));
 366+ $control .= Xml::openElement("input", array("type" => "checkbox", "id" => "end_date_checkbox", "class" => "date_range_checkbox", "checked" => ""));
 367+ $control .= Xml::closeElement("input");
 368+ $control .= wfMsg( "ct-end-date" );
 369+ $control .= Xml::closeElement("td");
 370+
 371+ $control .= Xml::openElement("td", array("id" => "end_date_textarea"));
 372+ $control .= Xml::openElement("input", array("type" => "text", "id" => "end_date", "class" => "date_range_input"));
 373+ $control .= Xml::closeElement("input");
 374+ $control .= Xml::closeElement("td");
 375+
 376+ $control .= Xml::closeElement("tr");
 377+
 378+
 379+ $control .= Xml::openElement("tr", array("id" => "update_row"));
 380+
 381+ $control .= Xml::openElement("td");
 382+ $control .= Xml::closeElement("td");
 383+
 384+ $control .= Xml::openElement("td", array("id" => "update_table_button_td"));
 385+ $control .= Xml::openElement("input", array("type" => "button", "id" => "update_table_button", "class" => "update_button", "value" =>wfMsg("ct-update-table")));
 386+ $control .= Xml::closeElement("input");
 387+ $control .= Xml::closeElement("td");
 388+
 389+ $control .= Xml::closeElement("tr");
 390+
 391+ $control .= Xml::closeElement("tbody");
 392+ $control .= Xml::closeElement("table");
 393+ $control .= Xml::closeElement("fieldset");
 394+
 395+ $control .= Xml::closeElement("form");
 396+
 397+ return $control;
 398+ }
 399+
 400+
 401+ /**
 402+ *
 403+ * @param $minTime
 404+ * @param $maxTime
 405+ * @param $userDefs
 406+ * @param $is_JSON
 407+ * @return unknown_type
 408+ */
 409+ public static function buildRowArray($minTime, $maxTime, $userDefs, $is_JSON= true){
 410+
 411+
 412+ if($minTime == 0){
 413+ $minTime = self::$minimum_date;
 414+ }
 415+ if($maxTime == 0){
 416+ $maxTime = gmdate("Ymd",time()); //today
 417+ }
 418+
 419+ if($is_JSON){
 420+ $userDefs = json_decode($userDefs, true);
 421+ }
 422+
 423+
 424+ $events = self::getTopEvents($minTime, $maxTime);
 425+
 426+ $returnArray = array();
 427+
 428+ while(($data_result = $events->fetchRow()) != null){
 429+ $outputArray = array();
 430+ $outputArray['event_name'] = $data_result['event_name'];
 431+ $outputArray['event_id'] = $data_result['event_id'];
 432+ $outputArray['expert'] = self::getTableValue($data_result['event_id'], $userDefs["expert"]);
 433+ $outputArray['intermediate'] = self::getTableValue($data_result['event_id'], $userDefs["intermediate"]);
 434+ $outputArray['basic'] = self::getTableValue($data_result['event_id'], $userDefs["basic"]);
 435+ $outputArray['total'] = $data_result["totalevtid"];
 436+ $returnArray[] = $outputArray;
 437+ }
 438+
 439+ return $returnArray;
 440+
 441+ }
 442+
 443+ function buildRow($data_result, $row_count, $userDefs){
 444+
 445+ $outputRow = Xml::openElement("tr", array("class" => "table_data_row"));
 446+
 447+ //event name
 448+ $outputRow .=Xml::openElement("td",
 449+ array("class" => "event_name", "id" => "event_name_$row_count", "value" =>$data_result['event_id']));
 450+ $outputRow .= $data_result['event_name'];
 451+ $outputRow .=Xml::closeElement("td");
 452+
 453+ //advanced users
 454+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["expert"]);
 455+ $outputRow .=Xml::openElement("td",
 456+ array("class" => "event_data expert_data", "id" => "event_expert_$row_count",
 457+ "value" => $cellValue));
 458+ $outputRow .= $cellValue;
 459+ $outputRow .=Xml::closeElement("td");
 460+
 461+ //intermediate users
 462+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["intermediate"]);
 463+ $outputRow .=Xml::openElement("td",
 464+ array("class" => "event_data intermediate_data", "id" => "event_intermediate_$row_count",
 465+ "value" => $cellValue));
 466+ $outputRow .= $cellValue;
 467+ $outputRow .=Xml::closeElement("td");
 468+
 469+ //basic users
 470+ $cellValue = self::getTableValue($data_result['event_id'], $userDefs["basic"]);
 471+ $outputRow .=Xml::openElement("td",
 472+ array("class" => "event_data basic_data", "id" => "event_basic_$row_count",
 473+ "value" => $cellValue));
 474+ $outputRow .= $cellValue;
 475+ $outputRow .=Xml::closeElement("td");
 476+
 477+ //totals
 478+ $cellValue = $data_result["totalevtid"];
 479+ $outputRow .=Xml::openElement("td",
 480+ array("class" => "event_data total_data", "id" => "total_$row_count",
 481+ "value" => $cellValue));
 482+ $outputRow .= $cellValue;
 483+ $outputRow .=Xml::closeElement("td");
 484+
 485+
 486+ $outputRow .= Xml::closeElement("tr");
 487+
 488+ return $outputRow;
 489+
 490+ }
 491+
 492+ /*
 493+ * get time constraints
 494+ * @param minTime minimum day (YYYYMMDD)
 495+ * @param maxTime max day (YYYYMMDD)
 496+ * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
 497+ */
 498+ static function getTimeConstraintsStatement( $minTime, $maxTime ){
 499+ if($minTime == 0 || $maxTime == 0){
 500+ return '';
 501+ }
 502+ else {
 503+
 504+ return "WHERE `action_time` >= '$minTime' AND `action_time` <= '$maxTime'";
 505+ }
 506+
 507+ }
 508+
 509+
 510+ /**
 511+ * Gets the top N events as set in the page pref
 512+ * @param $time_constraint_statement
 513+ * @return unknown_type
 514+ * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
 515+ */
 516+ public static function getTopEvents($minTime = "", $maxTime = "", $normalize_top_results = false){
 517+
 518+ $normalize = "click_tracking";
 519+ //escaped
 520+
 521+ $time_constraint_statement = self::getTimeConstraintsStatement($minTime,$maxTime);
 522+ $time_constraint = $time_constraint_statement;
 523+
 524+ if($normalize_top_results){
 525+ $normalize = "(select distinct session_id, event_id from click_tracking $time_constraint_statement) as t1";
 526+ $time_constraint = "";
 527+ }
 528+ $join = " ";
 529+ $sql = "select count(event_id) as totalevtid, event_id,event_name from $normalize" .
 530+ " LEFT JOIN click_tracking_events ON event_id=click_tracking_events.id".
 531+ " $time_constraint group by event_id order by totalevtid desc";
 532+
 533+ //returns count(event_id),event_id, event_name, top one first
 534+ $dbr = wfGetDB( DB_SLAVE );
 535+ $dbresult = $dbr->query($sql);
 536+
 537+ return $dbresult;
 538+ }
 539+
 540+ /**
 541+ * Gets a table value for a given User ID
 542+ * NOTE: once some of the constraints have been finalized, this will use more of the Database functions and not raw SQL
 543+ */
 544+ static function getTableValue($event_id, $userDef, $minTime = '', $maxTime = '', $normalize_results = false){
 545+
 546+ $normalize = "click_tracking";
 547+ //escaped
 548+ $time_constraint_statement = self::getTimeConstraintsStatement($minTime,$maxTime);
 549+ $time_constraint = $time_constraint_statement;
 550+ if($normalize_results){
 551+ $normalize = "(select distinct session_id, event_id, user_total_contribs, user_contribs_span1, user_contribs_span2, user_contribs_span3, is_logged_in from click_tracking $time_constraint_statement) as t1";
 552+ $time_constraint = "";
 553+ }
 554+
 555+ $user_conditions = SpecialClickTracking::buildUserDefQuery($userDef);
 556+
 557+ $where = ($time_constraint == "" ? "where" : "");
 558+
 559+ $and = ($time_constraint == "" ? "": "and");
 560+
 561+ $sql ="select count(*) as totalcount from $normalize $where $time_constraint $and ($user_conditions) and event_id=$event_id";
 562+
 563+ $dbr = wfGetDB( DB_SLAVE );
 564+ $result = $dbr->query($sql);
 565+ $resRow = $result->fetchRow();
 566+ return $resRow["totalcount"];
 567+ }
 568+
 569+ /**
 570+ * Generates a query for a user type definition
 571+ * @param $include_anon_users boolean, include anon users or not
 572+ * @param $total_contribs array, nonempty if total contribs to be included
 573+ * @param $contrib_1 array, nonempty AND conditions for user_contribs_1
 574+ * @param $contrib_2 array, nonempty AND conditions for user_contribs_1
 575+ * @param $contrib_3 array, nonempty AND conditions for user_contribs_1
 576+ * @return unknown_type query
 577+ */
 578+ public static function buildUserDefQuery($def){
 579+
 580+ $include_anon_users = (empty($def['anonymous'])?array():$def['anonymous']);
 581+ $total_contribs = (empty($def['total_contribs'])?array():$def['total_contribs']);
 582+ $contrib_1 = (empty($def['contrib_1'])?array():$def['contrib_1']);
 583+ $contrib_2 = (empty($def['contrib_2'])?array():$def['contrib_2']);
 584+ $contrib_3 = (empty($def['contrib_3'])?array():$def['contrib_3']);
 585+
 586+ $or_conds = array();
 587+ $and_conds = array();
 588+ $sql = "";
 589+
 590+
 591+ if( (boolean)$include_anon_users ){
 592+ $or_conds[] = array("field" => "is_logged_in", "operation" => "=", "value" =>"0");
 593+ }
 594+
 595+ if(!empty($total_contribs)){
 596+ foreach($total_contribs as $contribs){
 597+ $and_conds[] = array("field" => "user_total_contribs", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
 598+ }
 599+ }
 600+
 601+ if(!empty($contrib_1)){
 602+ foreach($contrib_1 as $contribs){
 603+ $and_conds[] = array("field" => "user_contribs_span1", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
 604+ }
 605+ }
 606+ if(!empty($contrib_2)){
 607+ foreach($contrib_2 as $contribs){
 608+ $and_conds[] = array("field" => "user_contribs_span2", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
 609+ }
 610+ }
 611+ if(!empty($contrib_3)){
 612+ foreach($contrib_3 as $contribs){
 613+ $and_conds[] = array("field" => "user_contribs_span3", "operation" => SpecialClickTracking::validate_oper($contribs["operation"]), "value" => intval($contribs["value"]));
 614+ }
 615+ }
 616+
 617+ foreach($and_conds as $cond){
 618+ if(!empty($sql)){
 619+ $sql .= " AND ";
 620+ }
 621+ $sql .= $cond["field"] . " " . $cond["operation"] . " " . $cond["value"];
 622+ }
 623+ foreach($or_conds as $cond){
 624+ if(!empty($sql)){
 625+ $sql .= " OR ";
 626+ }
 627+ $sql .= $cond["field"] . " " . $cond["operation"] . " " . $cond["value"];
 628+ }
 629+
 630+ return $sql;
 631+ }
 632+
 633+ public static function validate_oper($operation){
 634+ $o_trim = trim($operation);
 635+ switch($o_trim){ //valid operations
 636+ case ">":
 637+ case "<":
 638+ case "<=":
 639+ case ">=":
 640+ case "=":
 641+ return $o_trim;
 642+ default:
 643+ return "=";
 644+ }
 645+ }
 646+
 647+
 648+}
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/SpecialClickTracking.php
___________________________________________________________________
Name: svn:eol-style
1649 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.hooks.php
@@ -0,0 +1,182 @@
 2+<?php
 3+
 4+/**
 5+ * Hooks for Usability Initiative ClickTracking extension
 6+ *
 7+ * @file
 8+ * @ingroup Extensions
 9+ */
 10+
 11+class ClickTrackingHooks {
 12+
 13+ /* Static Functions */
 14+
 15+ /* initializations */
 16+
 17+ /* 3 tables for click tracking */
 18+ public static function schema() {
 19+ global $wgExtNewTables;
 20+
 21+ $wgExtNewTables[] = array(
 22+ 'click_tracking',
 23+ dirname( __FILE__ ) . '/ClickTracking.sql'
 24+ );
 25+
 26+ $wgExtNewTables[] = array(
 27+ 'click_tracking_events',
 28+ dirname( __FILE__ ) . '/ClickTrackingEvents.sql'
 29+ );
 30+
 31+ return true;
 32+ }
 33+
 34+ /**
 35+ * Make sure the table exists for parser tests
 36+ * @param $tables
 37+ * @return unknown_type
 38+ */
 39+ public static function parserTestTables( &$tables ) {
 40+ $tables[] = 'click_tracking';
 41+ $tables[] = 'click_tracking_events';
 42+ return true;
 43+ }
 44+
 45+ /**
 46+ * Check to see if user is throttled
 47+ */
 48+ public static function isUserThrottled() {
 49+ global $wgClickTrackThrottle;
 50+ return !( $wgClickTrackThrottle >= 0 && rand() % $wgClickTrackThrottle == 0 );
 51+ }
 52+
 53+ /**
 54+ * Adds JavaScript
 55+ */
 56+ public static function addJS() {
 57+ global $wgClickTrackingStyleVersion;
 58+
 59+ UsabilityInitiativeHooks::initialize();
 60+ UsabilityInitiativeHooks::addScript( 'ClickTracking/ClickTracking.js', $wgClickTrackingStyleVersion );
 61+ UsabilityInitiativeHooks::addVariables(
 62+ array(
 63+ 'wgTrackingToken' => ClickTrackingHooks::get_session_id(),
 64+ 'wgClickTrackingIsThrottled' => ClickTrackingHooks::isUserThrottled()
 65+ )
 66+ );
 67+
 68+ return true;
 69+ }
 70+
 71+ /**
 72+ * Gets the session ID...we just want a unique random ID for the page load
 73+ * @return session ID
 74+ */
 75+ public static function get_session_id() {
 76+ global $wgUser;
 77+ return wfGenerateToken( array( $wgUser->getName(), time() ) );
 78+ }
 79+
 80+ /**
 81+ * Get the number of revisions a user has made since a given time
 82+ * @param $ts beginning timestamp
 83+ * @return number of revsions this user has made
 84+ */
 85+ public static function getEditCountSince( $ts ) {
 86+ global $wgUser;
 87+
 88+ // convert to just the day
 89+ $time = gmdate( 'Y-m-d', wfTimestamp( TS_UNIX, $ts ) );
 90+
 91+ $dbr = wfGetDB( DB_SLAVE );
 92+
 93+ $edits = $dbr->selectField(
 94+ 'user_daily_contribs',
 95+ 'SUM(contribs)',
 96+ array(
 97+ 'user_id' => $wgUser->getId(),
 98+ "day >= '$time'"
 99+ ),
 100+ __METHOD__
 101+ );
 102+
 103+ // user hasn't made any edits in whatever amount of time
 104+ if ( $edits == null ) {
 105+ $edits = 0;
 106+ }
 107+
 108+ return $edits;
 109+ }
 110+
 111+ /**
 112+ * Get event ID from name
 113+ * @param $event_name String: name of the event to get
 114+ * @return integer
 115+ */
 116+ public static function getEventIDFromName( $event_name ) {
 117+ $dbw = wfGetDB( DB_MASTER ); // replication lag means sometimes a new event will not exist in the table yet
 118+
 119+ $id_num = $dbw->selectField(
 120+ 'click_tracking_events',
 121+ 'id',
 122+ array(
 123+ 'event_name' => $event_name
 124+ ),
 125+ __METHOD__
 126+ );
 127+
 128+ // if this entry doesn't exist...
 129+ // this will be incredibly rare as the whole database will only have a few hundred entries in it at most
 130+ // and getting DB_MASTER up top would be wasteful
 131+ // FIXME: Use replace() instead of this selectField --> insert or update logic
 132+ if( $id_num === false ) {
 133+ $dbw->insert(
 134+ 'click_tracking_events',
 135+ array( 'event_name' => (string) $event_name ),
 136+ __METHOD__
 137+ );
 138+ $id_num = $dbw->insertId();
 139+ }
 140+
 141+ if( $id_num === false ){
 142+ return 0;
 143+ }
 144+
 145+ return $id_num;
 146+ }
 147+
 148+ /**
 149+ * Track particular event
 150+ * @param $session_id String: unique session id for this editing sesion
 151+ * @param $is_logged_in Boolean: whether or not the user is logged in
 152+ * @param $namespace Integer: namespace the user is editing
 153+ * @param $event_id Integer: event type
 154+ * @param $contribs Integer: contributions the user has made (or NULL if user not logged in)
 155+ * @param $contribs_in_timespan1 Integer: number of contributions user has made in timespan of granularity 1 (defined by ClickTracking/$wgClickTrackContribGranularity1)
 156+ * @param $contribs_in_timespan2 Integer: number of contributions user has made in timespan of granularity 2 (defined by ClickTracking/$wgClickTrackContribGranularity2)
 157+ * @param $contribs_in_timespan3 Integer: number of contributions user has made in timespan of granularity 3 (defined by ClickTracking/$wgClickTrackContribGranularity3)
 158+ * @return true if the event was stored in the DB
 159+ */
 160+ public static function trackEvent( $session_id, $is_logged_in, $namespace, $event_id, $contribs = 0,
 161+ $contribs_in_timespan1 = 0, $contribs_in_timespan2 = 0, $contribs_in_timespan3 = 0 ) {
 162+ $dbw = wfGetDB( DB_MASTER );
 163+
 164+ $dbw->begin();
 165+
 166+ // Builds insert information
 167+ $data = array(
 168+ 'action_time' => $dbw->timestamp(),
 169+ 'session_id' => (string) $session_id,
 170+ 'is_logged_in' => (bool) $is_logged_in,
 171+ 'user_total_contribs' => ( $is_logged_in ? (int) $contribs : null ),
 172+ 'user_contribs_span1' => ( $is_logged_in ? (int) $contribs_in_timespan1 : null ),
 173+ 'user_contribs_span2' => ( $is_logged_in ? (int) $contribs_in_timespan2 : null ),
 174+ 'user_contribs_span3' => ( $is_logged_in ? (int) $contribs_in_timespan3 : null ),
 175+ 'namespace' => (int) $namespace,
 176+ 'event_id' => (int) $event_id
 177+ );
 178+
 179+ $db_status = $dbw->insert( 'click_tracking', $data, __METHOD__ );
 180+ $dbw->commit();
 181+ return $db_status;
 182+ }
 183+}
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.hooks.php
___________________________________________________________________
Name: svn:eol-style
1184 + native
Index: branches/usability/acaifix/ClickTracking/SpecialClickTracking.css
@@ -0,0 +1,63 @@
 2+@CHARSET "UTF-8";
 3+
 4+.table_headers{
 5+ font-weight: bold;
 6+ border: bottom;
 7+}
 8+
 9+.table_data_row{
 10+ text-align: center;
 11+}
 12+
 13+.table_data_row .event_name{
 14+ text-align: left;
 15+ font-weight: bold;
 16+}
 17+
 18+#clicktrack_data_table {
 19+ float: left;
 20+}
 21+
 22+#chart_img {
 23+ float: left;
 24+ margin-left: 90px;
 25+}
 26+
 27+#change_graph_cell {
 28+ text-align: right;
 29+}
 30+
 31+.disabled_option {
 32+ color: #999999;
 33+}
 34+
 35+.hidden {
 36+ display: none;
 37+}
 38+
 39+.control_div {
 40+ margin: 10px;
 41+ clear: both;
 42+}
 43+
 44+.sub_option_div{
 45+ margin-top: 4px;
 46+ margin-left: 15px;
 47+}
 48+
 49+.sub_option_div input[type="text"]{
 50+ width: 20px;
 51+ margin-left: 10px;
 52+}
 53+
 54+#date_range{
 55+ display:inline;
 56+ float:left;
 57+ width:200px;
 58+}
 59+
 60+.add_condition_button{
 61+ float: right;
 62+ color: blue;
 63+ cursor: pointer;
 64+}
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/SpecialClickTracking.css
___________________________________________________________________
Name: svn:eol-style
165 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.js
@@ -0,0 +1,21 @@
 2+(function($) {
 3+ if( !wgClickTrackingIsThrottled ) {
 4+ // creates 'track action' function to call the clicktracking API and send the ID
 5+ $.trackAction = function ( id ) {
 6+ $j.post( wgScriptPath + '/api.php', { 'action': 'clicktracking', 'eventid': id, 'token': wgTrackingToken } );
 7+ };
 8+
 9+ // Clicktrack the left sidebar links
 10+ $(document).ready( function() {
 11+ $( '#p-logo a, #p-navigation a, #p-tb a' ).click( function() {
 12+ var id = 'leftnav-' + skin + '-' +
 13+ ( $(this).attr( 'id' ) || $(this).parent().attr( 'id' ) );
 14+ window.location = wgScriptPath +
 15+ '/api.php?action=clicktracking&eventid=' + id + '&token=' +
 16+ wgTrackingToken +
 17+ '&redirectto=' + escape( $(this).attr( 'href' ) );
 18+ });
 19+ });
 20+ }
 21+
 22+})(jQuery);
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.js
___________________________________________________________________
Name: svn:eol-style
123 + native
Index: branches/usability/acaifix/ClickTracking/SpecialClickTracking.js
@@ -0,0 +1,509 @@
 2+(function($) {
 3+ /* Very limited JSON encoder */
 4+ $.json_encode = function( js_obj ) {
 5+ var returnstr = "{ ";
 6+
 7+ // trailing commas and json don't mix
 8+ var propertynum = 0;
 9+ for( property in js_obj ) {
 10+ if( propertynum > 0 ) {
 11+ returnstr +=", ";
 12+ }
 13+ returnstr += "\"" + property + "\"" + " : ";
 14+ if( typeof js_obj[property] == 'object' ) {
 15+ returnstr += $.json_encode( js_obj[property] );
 16+ } else {
 17+ returnstr += "\"" + js_obj[property] + "\" ";
 18+ }
 19+ propertynum++;
 20+ }
 21+
 22+ returnstr += " }";
 23+ return returnstr;
 24+ };
 25+
 26+ $.getUserDefsFromDialog = function() {
 27+ var currUserDefs = new Array();
 28+ if( $("#anon_users_checkbox").is( ":checked" ) ) {
 29+ currUserDefs['anonymous'] = 1;
 30+ } else {
 31+ currUserDefs['anonymous'] = 0;
 32+ }
 33+
 34+ var getCheckBoxData = function( contribName ) {
 35+ if( $("#"+ contribName + "_checkbox").is( ":checked" ) ) {
 36+ currUserDefs[contribName] = new Array();
 37+ } else {
 38+ return;
 39+ }
 40+ var totalConds = $("#" + contribName + "_div").data("totalConditions");
 41+ var i;
 42+
 43+ for( i = 1; i <= totalConds; i++ ) {
 44+ if( $("#" + contribName + "_" + i + "_checkbox").is( ":checked" ) ) {
 45+ $("#" + contribName + "_" + i + "_ltgt").children().each(function() {
 46+ if( $(this).is( ":selected" ) ) {
 47+ var currentCond = new Array();
 48+ switch( $(this).attr("value") ) {
 49+ case 'lt':
 50+ currentCond['operation'] = '<';
 51+ break;
 52+ case 'lteq':
 53+ currentCond['operation'] = '<=';
 54+ break;
 55+ case 'gt':
 56+ currentCond['operation'] = '>';
 57+ break;
 58+ case 'gteq':
 59+ currentCond['operation'] = '>=';
 60+ break;
 61+ default:
 62+ currentCond['operation'] = '<';
 63+ break;
 64+ }
 65+ currentCond['value'] = $("#" + contribName + "_" + i + "_text").val();
 66+ currUserDefs[contribName].push(currentCond);
 67+ }
 68+ });
 69+ } // ifchecked
 70+ } // forloop
 71+ };
 72+
 73+ getCheckBoxData("total_contribs");
 74+ getCheckBoxData("contribs_span_1");
 75+ getCheckBoxData("contribs_span_2");
 76+ getCheckBoxData("contribs_span_3");
 77+ wgClickTrackUserDefs[$("#user_def_alter_legend").data("currentlyEditing")] = currUserDefs;
 78+ };
 79+
 80+ $.renderUserDefDialogWith = function( userDef, defName ) {
 81+ // change name
 82+ $("#user_def_alter_legend").text($("#user_def_alter_legend").data("defaultChangeText") + " " + defName);
 83+ $("#user_def_alter_legend").data("currentlyEditing", defName);
 84+
 85+ var setContribs = function( conditionArray, contribName ) {
 86+ initialDiv = $("<div></div>").attr('id', contribName + '_div');
 87+ initialDiv.addClass('checkbox_div');
 88+ initialDiv.addClass('control_div');
 89+
 90+ textDiv = $("<div></div>").attr('id', contribName + '_text_div');
 91+ mainCheckbox = $("<input>").attr('id', contribName + '_checkbox');
 92+ mainCheckbox.attr('type', 'checkbox');
 93+ mainCheckbox.addClass('user_def_checkbox');
 94+
 95+ if( conditionArray.length > 0 ) {
 96+ mainCheckbox.attr( 'checked', true );
 97+ }
 98+
 99+ textDiv.append( mainCheckbox );
 100+ textDiv.text( contribName ); // i18n txt here
 101+ textDiv.css( 'display', 'inline' );
 102+ initialDiv.append( mainCheckbox );
 103+ initialDiv.append( textDiv );
 104+
 105+ var buildConditionDiv = function( condition, counter, isChecked ) {
 106+ conditionDiv = $("<div></div>").attr('id', contribName + '_range_' + counter + '_div');
 107+ conditionDiv.addClass( 'checkbox_div' );
 108+ conditionDiv.addClass( 'sub_option_div' );
 109+
 110+ //initialDiv.append(conditionDiv);
 111+ cCheckbox = $("<input></input>").attr('id', contribName + '_' + counter + '_checkbox');
 112+ cCheckbox.attr('type', 'checkbox');
 113+ if( isChecked ) {
 114+ cCheckbox.attr( 'checked', true );
 115+ }
 116+ cCheckbox.addClass( 'number_select_checkbox' );
 117+ conditionDiv.append( cCheckbox );
 118+
 119+ cSelect = $("<select></select>").attr('id', contribName + '_' + counter + '_ltgt');
 120+ cSelect.addClass( 'number_select_ltgt' );
 121+
 122+ cOpt1 = $("<option></option>").attr('id', contribName + '_' + counter + '_lt');
 123+ cOpt1.addClass( 'number_select_ltgt_opt' );
 124+ cOpt1.attr( 'value', 'lt' );
 125+ cOpt1.text( '<' );
 126+ if( condition['operation'] == '<' ) {
 127+ cOpt1.attr( 'selected', true );
 128+ }
 129+
 130+ cOpt2 = $("<option></option>").attr('id', contribName + '_' + counter + '_gt');
 131+ cOpt2.addClass( 'number_select_ltgt_opt' );
 132+ cOpt2.attr( 'value', 'gt' );
 133+ cOpt2.text( '>' );
 134+ if( condition['operation'] == '>' ) {
 135+ cOpt2.attr( 'selected', true );
 136+ }
 137+
 138+ cOpt3 = $("<option></option>").attr('id', contribName + '_' + counter + '_lteq');
 139+ cOpt3.addClass( 'number_select_ltgt_opt' );
 140+ cOpt3.attr( 'value', 'lteq' );
 141+ cOpt3.text( '<=' );
 142+ if( condition['operation'] == '<=' ) {
 143+ cOpt3.attr( 'selected', true );
 144+ }
 145+
 146+ cOpt4 = $("<option></option>").attr('id', contribName + '_' + counter + '_gteq');
 147+ cOpt4.addClass( 'number_select_ltgt_opt' );
 148+ cOpt4.attr( 'value', 'gteq' );
 149+ cOpt4.text( '>=' );
 150+ if( condition['operation'] == '>=' ) {
 151+ cOpt4.attr( 'selected', true );
 152+ }
 153+
 154+ cSelect.append( cOpt1 );
 155+ cSelect.append( cOpt2 );
 156+ cSelect.append( cOpt3 );
 157+ cSelect.append( cOpt4 );
 158+ conditionDiv.append( cSelect );
 159+
 160+ cTextInput = $("<input></input>").attr('id', contribName + '_' + counter + '_text');
 161+ cTextInput.addClass( 'number_select_text' );
 162+ cTextInput.attr( 'value', condition['value'] );
 163+ conditionDiv.append( cTextInput );
 164+ return conditionDiv;
 165+ };
 166+
 167+ var i = 0;
 168+ for( var condition in conditionArray ) {
 169+ i++;
 170+ var conditionDiv = buildConditionDiv( conditionArray[condition], i, true );
 171+ initialDiv.append( conditionDiv );
 172+ } // forloop
 173+ initialDiv.data( 'totalConditions', i );
 174+ addConditions = $("<div></div>").attr('id', contribName + '_addbutton');
 175+ addConditions.data( 'contribName', contribName );
 176+ addConditions.addClass( 'add_condition_button' );
 177+ addConditions.text( '+' );
 178+ initialDiv.append( addConditions );
 179+ addConditions.click( function() {
 180+ var initDiv = $("#" + $(this).data('contribName') + '_div');
 181+ var totalConds = initDiv.data( 'totalConditions' );
 182+ totalConds++;
 183+ initDiv.data( 'totalConditions', totalConds );
 184+ var tmpCond = new Array();
 185+ tmpCond['operation'] = ' ';
 186+ tmpCond['value'] = ' ';
 187+
 188+ buildConditionDiv(tmpCond, totalConds).insertBefore($(this));
 189+ initDiv.data( 'totalConditions', totalConds, false );
 190+ });
 191+
 192+ return initialDiv;
 193+ }; // setcontribs
 194+
 195+ // check anonymous
 196+ var anon = false;
 197+ if( parseInt( userDef['anonymous'] ) == 1 ) {
 198+ anon = true;
 199+ }
 200+ $("#anon_users_checkbox").attr('checked', anon);
 201+
 202+ // clear out old contents
 203+ $("#contrib_opts_container").empty();
 204+
 205+ var setup_set_contribs = function( contribName ) {
 206+ var current_contribs = userDef[contribName];
 207+ if( current_contribs == undefined ) {
 208+ current_contribs = new Array();
 209+ }
 210+ $("#contrib_opts_container").append( setContribs( current_contribs, contribName ) );
 211+ };
 212+
 213+ // total contribs
 214+ setup_set_contribs( 'total_contribs' );
 215+ setup_set_contribs( 'contribs_span_1' );
 216+ setup_set_contribs( 'contribs_span_2' );
 217+ setup_set_contribs( 'contribs_span_3' );
 218+
 219+ // OK button
 220+ var okButton = $("<input>").attr('id', 'ok_button');
 221+ okButton.attr( 'type', 'button' );
 222+ okButton.attr( 'value', 'ok' );
 223+ okButton.click(function() {
 224+ $.getUserDefsFromDialog();
 225+ $("#user_def_dialog").dialog('close');
 226+ });
 227+ $("#contrib_opts_container").append(okButton);
 228+ }; // renderUserDefDialogWith
 229+
 230+ // functions
 231+ $.updateChart = function() {
 232+ event_name = $("#chart_img").data('event_name');
 233+
 234+ var processChartJSON = function( data, status ) {
 235+
 236+ var getMax = function( findMax ) {
 237+ var retval = Number.MIN_VALUE;
 238+ for( var i in findMax ) {
 239+ if( findMax[i] > retval ) {
 240+ retval = findMax[i];
 241+ }
 242+ }
 243+ return retval;
 244+ };
 245+
 246+ max1 = getMax( data['datapoints']['expert'] );
 247+ max2 = getMax( data['datapoints']['intermediate'] );
 248+ max3 = getMax( data['datapoints']['basic'] );
 249+ max = Math.max( max3, Math.max( max1, max2 ) );
 250+ chartURL = 'http://chart.apis.google.com/chart?' +
 251+ 'chs=400x400&' +
 252+ 'cht=lc&' +
 253+ 'chco=FF0000,0000FF,00FF00&' +
 254+ 'chtt=' + event_name + ' from ' + $("#start_date").val() +' to ' +$("#end_date").val() + "&" +
 255+ 'chdl=' + 'Expert|Intermediate|Beginner' + "&" +
 256+ 'chxt=x,y&' +
 257+ 'chd=t:' + data['datapoints']['expert'].join(',') + "|" +
 258+ data['datapoints']['intermediate'].join(',') + "|" + data['datapoints']['basic'].join(',') + "&" +
 259+ 'chds=0,'+ max +',0,'+ max +',0,'+ max
 260+ ;
 261+ $("#chart_img").attr( 'src', chartURL );
 262+ };
 263+
 264+ start_date = $("#start_date").val();
 265+ if( $("#start_date").hasClass( 'hidden' ) ) {
 266+ start_date = '0';
 267+ }
 268+
 269+ end_date = $("#end_date").val();
 270+ if( $("#end_date").hasClass( 'hidden' ) ) {
 271+ end_date = '0';
 272+ }
 273+
 274+ // post relevant info
 275+ $j.post( wgScriptPath + '/api.php',
 276+ { 'action': 'specialclicktracking', 'format': 'json',
 277+ 'eventid': $("#chart_img").data( 'eventid' ), 'increment': $("#chart_increment").val(),
 278+ 'startdate': start_date, 'enddate': end_date, 'userdefs': $.json_encode( wgClickTrackUserDefs ) },
 279+ processChartJSON, 'json'
 280+ );
 281+ };
 282+
 283+ // pretty colors for the table
 284+ $.colorizeTable = function() {
 285+ // expert
 286+
 287+ // get totals
 288+ var expert_total = 0;
 289+
 290+ $(".expert_data").each(function() {
 291+ expert_total += parseInt( $(this).attr( 'value' ) );
 292+ });
 293+
 294+ // set proper red shade
 295+ $(".expert_data").each(function() {
 296+ var rval = 255;
 297+ var gval = ( expert_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / expert_total ) );
 298+ var bval = gval;
 299+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 300+ $(this).data('rgb', rgbString);
 301+ $(this).css('color', rgbString);
 302+ $(this).css('background-color', rgbString);
 303+ });
 304+
 305+ // intermediate
 306+
 307+ // total
 308+ var intermediate_total = 0;
 309+ $(".intermediate_data").each(function() {
 310+ intermediate_total += parseInt( $(this).attr( 'value' ) );
 311+ });
 312+
 313+ // blue shade
 314+ $(".intermediate_data").each(function() {
 315+ var rval = ( intermediate_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / intermediate_total ) );
 316+ var gval = rval;
 317+ var bval = 255;
 318+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 319+ $(this).data('rgb', rgbString);
 320+ $(this).css('color', rgbString);
 321+ $(this).css('background-color', rgbString);
 322+ });
 323+
 324+ // total
 325+ var basic_total = 0;
 326+ $(".basic_data").each(function() {
 327+ basic_total += parseInt( $(this).attr( 'value' ) );
 328+ });
 329+
 330+ // green shade
 331+ $(".basic_data").each(function() {
 332+ var rval = ( basic_total == 0 ? 255 : 255 - ( 255 * $(this).attr( 'value' ) / basic_total ) );
 333+ var gval = 255;
 334+ var bval = rval;
 335+ rgbString = "rgb(" + parseInt( rval ) + "," + parseInt( gval ) + "," + parseInt( bval ) + ")";
 336+ $(this).data('rgb', rgbString);
 337+ $(this).css('color', rgbString);
 338+ $(this).css('background-color', rgbString);
 339+ });
 340+
 341+ // I wanted to do this with classes, but the element's style rule wins over class rule
 342+ // and each element has its own alternative color
 343+ $(".event_data").mouseover(function() {
 344+ $(this).css('color', '#000000');
 345+ $(this).css('background-color', '#FFFFFF');
 346+ });
 347+
 348+ $(".event_data").mouseout(function() {
 349+ rgbString = $(this).data("rgb");
 350+ $(this).css('color', rgbString);
 351+ $(this).css('background-color', rgbString);
 352+ });
 353+
 354+ }; // colorize
 355+
 356+ $.updateTable = function() {
 357+ var processTableJSON = function( data, status ) {
 358+ // clear
 359+ $(".table_data_row").each( function() { $(this).remove(); } );
 360+
 361+ var row_count = 0;
 362+ for( var row_iter in data['tablevals']['vals'] ) {
 363+ var row = data['tablevals']['vals'][row_iter]; // really, JS?
 364+ row_count++;
 365+
 366+ var outputRow = $("<tr></tr>");
 367+ outputRow.addClass( 'table_data_row' );
 368+
 369+ var cell =$("<td></td>").attr('id', 'event_name_' + row_count);
 370+ cell.addClass( 'event_name' );
 371+ cell.attr( 'value', row['event_id'] );
 372+ cell.text( row['event_name']);
 373+ outputRow.append( cell );
 374+
 375+ var createClassCell = function( userclass ) {
 376+ var newcell = $("<td></td>").attr('id', 'event_' + userclass + '_' + row_count);
 377+ newcell.addClass( 'event_data' );
 378+ newcell.addClass( userclass + '_data' );
 379+ newcell.text( row[userclass] );
 380+ newcell.attr( 'value', row[userclass] );
 381+ outputRow.append( newcell );
 382+ };
 383+
 384+ createClassCell( 'expert' );
 385+ createClassCell( 'intermediate' );
 386+ createClassCell( 'basic' );
 387+ createClassCell( 'total' );
 388+ $("#clicktrack_data_table").append( outputRow );
 389+ }
 390+
 391+ $.colorizeTable();
 392+ };
 393+
 394+ start_date = $("#start_date").val();
 395+ if( $("#start_date").hasClass( 'hidden' ) ) {
 396+ start_date = '0';
 397+ }
 398+
 399+ end_date = $("#end_date").val();
 400+ if( $("#end_date").hasClass( 'hidden' ) ) {
 401+ end_date = '0';
 402+ }
 403+
 404+ // post relevant info
 405+ $j.post( wgScriptPath + '/api.php',
 406+ { 'action': 'specialclicktracking', 'format': 'json',
 407+ 'eventid': 1, 'increment': $("#chart_increment").val(),
 408+ 'startdate': start_date, 'enddate': end_date, 'userdefs': $.json_encode( wgClickTrackUserDefs ), 'tabledata': 1 },
 409+ processTableJSON, 'json'
 410+ );
 411+
 412+ }; // updateTable
 413+
 414+ $.setUIControls = function() {
 415+ // SET UP DATE RANGES
 416+
 417+ // date-pickers for start and end dates
 418+ $('.date_range_input').each(function() {
 419+ $(this).datepicker();
 420+ $(this).datepicker( 'option', 'dateFormat', 'yymmdd' );
 421+ });
 422+ var startDate = new Date();
 423+ $('#start_date').val("20091009"); // click_tracking start date as default
 424+
 425+ var toggleDateInput = function( tableRow ) {
 426+ var checked = false;
 427+ tableRow.children().each( function() {
 428+ if( checked == false ) {
 429+ checked = $(this).children("input:checkbox").eq(0).is(":checked");
 430+ }
 431+ });
 432+
 433+ if( checked ) {
 434+ tableRow.removeClass( 'disabled_option' );
 435+ tableRow.children("td").each(function() {
 436+ $(this).children(".date_range_input").removeClass( 'hidden' );
 437+ });
 438+ } else {
 439+ tableRow.children("td").each(function() {
 440+ $(this).children(".date_range_input").addClass( 'hidden' );
 441+ });
 442+ tableRow.addClass( 'disabled_option' );
 443+ }
 444+ };
 445+
 446+ $('.date_range_checkbox').click(function() {
 447+ toggleDateInput( $(this).closest( 'tr' ) );
 448+ });
 449+
 450+ // update table
 451+ $('#update_table_button').click($.updateTable);
 452+
 453+ // CHART DIALOG
 454+ $("#chart_dialog").dialog({ autoOpen: false, width: 400 });
 455+ $("#chart_img").css('cursor', 'pointer');
 456+ $("#chart_img").click(function() {
 457+ $("#chart_dialog").dialog('open');
 458+ });
 459+
 460+ $("#chart_increment").data( 'value', $("#chart_increment").val() );
 461+
 462+ $("#change_graph").click(function() {
 463+ $("#chart_dialog").dialog('close');
 464+
 465+ // check if the value actually changed, if so, update and increment things accordingly
 466+ if( $("#chart_increment").data( 'value' ) != $("#chart_increment").val() ) {
 467+ $("#chart_increment").data( 'value', $("#chart_increment").val() );
 468+ $.updateChart();
 469+ }
 470+
 471+ });
 472+
 473+ // CHANGE USER INFO DIALOG
 474+ $("#user_def_dialog").dialog({ autoOpen: false, width: 400 });
 475+ $("#user_def_alter_legend").data( 'defaultChangeText', $("#user_def_alter_legend").text() );
 476+
 477+ // CHANGE USER/INTERMEDIATE/EXPERT DIALOGS
 478+ var loadHeaderInfo = function( headerName ) {
 479+ $("#" + headerName + "_header").css('cursor', 'pointer');
 480+ $("#" + headerName + "_header").click(function() {
 481+ $.renderUserDefDialogWith( wgClickTrackUserDefs[headerName], headerName );
 482+ $("#user_def_dialog").dialog('open');
 483+ });
 484+ }; // headername
 485+
 486+ loadHeaderInfo( 'basic' );
 487+ loadHeaderInfo( 'intermediate' );
 488+ loadHeaderInfo( 'expert' );
 489+
 490+ };
 491+
 492+ $.changeDataLinks = function() {
 493+ $(".event_name").each(function() {
 494+ $(this).css('cursor', 'pointer');
 495+
 496+ $(this).click(function() {
 497+ $("#chart_img").data( 'eventid', $(this).attr( 'value' ) );
 498+ $("#chart_img").data( 'event_name', $(this).text() );
 499+ $.updateChart();
 500+ }); // click
 501+ }); // each
 502+ }; // addlink
 503+
 504+return $(this);
 505+})(jQuery);
 506+
 507+// colorize the table on document.ready
 508+js2AddOnloadHook( $j.colorizeTable );
 509+js2AddOnloadHook( $j.changeDataLinks );
 510+js2AddOnloadHook( $j.setUIControls );
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/SpecialClickTracking.js
___________________________________________________________________
Name: svn:eol-style
1511 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.alias.php
@@ -0,0 +1,14 @@
 2+<?php
 3+/**
 4+ * Special page aliases for Usability Initiative ClickTracking extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$aliases = array();
 11+
 12+$aliases['en'] = array(
 13+ 'ClickTracking' => array( 'ClickTracking' ),
 14+);
 15+
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.alias.php
___________________________________________________________________
Name: svn:eol-style
116 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.sql
@@ -0,0 +1,32 @@
 2+--
 3+-- Schema for ClickTracking
 4+--
 5+
 6+CREATE TABLE IF NOT EXISTS /*_*/click_tracking (
 7+ -- Timestamp
 8+ action_time char(14) NOT NULL,
 9+
 10+ -- session id
 11+ session_id varbinary(255) NOT NULL,
 12+
 13+ -- true if the user is logged in
 14+ is_logged_in tinyint NOT NULL,
 15+
 16+ -- total user contributions
 17+ user_total_contribs integer,
 18+
 19+ -- user contributions over a specified timespan of granularity 1
 20+ user_contribs_span1 integer,
 21+
 22+ -- user contributions over a specified timespan of granularity 2
 23+ user_contribs_span2 integer,
 24+
 25+ -- user contributions over a specified timespan of granularity 3
 26+ user_contribs_span3 integer,
 27+
 28+ -- namespace being edited
 29+ namespace integer NOT NULL,
 30+
 31+ -- event ID (not unique)
 32+ event_id integer NOT NULL
 33+) /*$wgDBTableOptions*/;
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.sql
___________________________________________________________________
Name: svn:eol-style
134 + native
Index: branches/usability/acaifix/ClickTracking/ApiClickTracking.php
@@ -0,0 +1,97 @@
 2+<?php
 3+/**
 4+ * Extend the API for click tracking
 5+ *
 6+ * @file
 7+ * @ingroup API
 8+ */
 9+
 10+class ApiClickTracking extends ApiBase {
 11+
 12+ /**
 13+ * runs when the API is called with "clicktracking", takes in "eventid" and an edit token given to the user, "token"
 14+ * @see includes/api/ApiBase#execute()
 15+ */
 16+ public function execute() {
 17+ global $wgUser, $wgTitle, $wgClickTrackContribGranularity1, $wgClickTrackContribGranularity2, $wgClickTrackContribGranularity3;
 18+
 19+ $params = $this->extractRequestParams();
 20+ $this->validateParams( $params );
 21+ $eventid_to_lookup = $params['eventid'];
 22+ $session_id = $params['token'];
 23+
 24+ // Event ID lookup table
 25+ $event_id = ClickTrackingHooks::getEventIDFromName( urldecode( $eventid_to_lookup ) );
 26+
 27+ $is_logged_in = $wgUser->isLoggedIn();
 28+ $now = time();
 29+ $granularity1 = $is_logged_in ?
 30+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity1 ) : 0;
 31+
 32+ $granularity2 = $is_logged_in ?
 33+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity2 ) : 0;
 34+
 35+ $granularity3 = $is_logged_in ?
 36+ ClickTrackingHooks::getEditCountSince( $now - $wgClickTrackContribGranularity3 ) : 0;
 37+
 38+ ClickTrackingHooks::trackEvent(
 39+ $session_id, // randomly generated session ID
 40+ $is_logged_in, // is the user logged in?
 41+ $wgTitle->getNamespace(), // what namespace are they editing?
 42+ $event_id, // event ID passed in
 43+ ( $is_logged_in ? $wgUser->getEditCount() : 0 ), // total edit count or 0 if anonymous
 44+ $granularity1, //contributions made in granularity 1 time frame
 45+ $granularity2, //contributions made in granularity 2 time frame
 46+ $granularity3 //contributions made in granularity 3 time frame
 47+ );
 48+
 49+ // For links that go off the page, redirect the user
 50+ // FIXME: The API should have a proper infrastructure for this
 51+ if ( !is_null( $params['redirectto'] ) ) {
 52+ global $wgOut;
 53+ $wgOut->enable();
 54+ $wgOut->redirect( $params['redirectto'] );
 55+ $wgOut->output();
 56+ }
 57+ }
 58+
 59+ /**
 60+ * Required parameter check
 61+ * @param $params params extracted from the POST
 62+ */
 63+ protected function validateParams( $params ) {
 64+ $required = array( 'eventid', 'token' );
 65+ foreach( $required as $arg ) {
 66+ if ( !isset( $params[$arg] ) ) {
 67+ $this->dieUsageMsg( array( 'missingparam', $arg ) );
 68+ }
 69+ }
 70+ }
 71+
 72+ public function getParamDescription() {
 73+ return array(
 74+ 'eventid' => 'string of eventID',
 75+ 'token' => 'unique edit ID for this edit session',
 76+ 'redirectto' => 'URL to redirect to (only used for links that go off the page)'
 77+ );
 78+ }
 79+
 80+ public function getDescription() {
 81+ return array(
 82+ 'Track user clicks on JavaScript items.'
 83+ );
 84+ }
 85+
 86+ public function getAllowedParams() {
 87+ return array(
 88+ 'eventid' => null,
 89+ 'token' => null,
 90+ 'redirectto' => null
 91+ );
 92+ }
 93+
 94+ public function getVersion() {
 95+ return __CLASS__ . ': $Id$';
 96+ }
 97+
 98+}
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/ApiClickTracking.php
___________________________________________________________________
Name: svn:keywords
199 + Id
Name: svn:eol-style
2100 + native
Index: branches/usability/acaifix/ClickTracking/ApiSpecialClickTracking.php
@@ -0,0 +1,132 @@
 2+<?php
 3+/**
 4+ * Extend the API for click tracking visualization in the special:clicktracking page
 5+ *
 6+ * @file
 7+ * @ingroup API
 8+ */
 9+
 10+class ApiSpecialClickTracking extends ApiBase {
 11+
 12+ /**
 13+ * runs when the API is called with "specialclicktracking", takes in "startdate" and "enddate" as YYYYMMDD , "eventid" as the event ID,
 14+ * and "increment" as how many days to increment
 15+ * @see includes/api/ApiBase#execute()
 16+ */
 17+ public function execute() {
 18+ $params = $this->extractRequestParams();
 19+ $this->validateParams( $params );
 20+ $event_id = $params['eventid'];
 21+ $startdate = $params['startdate'];
 22+ $enddate = $params['enddate'];
 23+ $increment = $params['increment'];
 24+ $userDefString = $params['userdefs'];
 25+
 26+ // this is if it's asking for tableData
 27+ if( isset( $params['tabledata'] ) ) {
 28+ $tableData = SpecialClickTracking::buildRowArray( $startdate, $enddate, $userDefString );
 29+ $this->getResult()->addValue( array( 'tablevals' ), 'vals', $tableData );
 30+ } else{ //chart data
 31+ $click_data = array();
 32+ try {
 33+ $click_data = SpecialClickTracking::getChartData( $event_id, $startdate, $enddate, $increment, $userDefString );
 34+ $this->getResult()->addValue( array( 'datapoints' ), 'expert', $click_data['expert'] );
 35+ $this->getResult()->addValue( array( 'datapoints' ), 'basic', $click_data['basic'] );
 36+ $this->getResult()->addValue( array( 'datapoints' ), 'intermediate', $click_data['intermediate'] );
 37+ } catch( Exception $e ) { /* no result */ }
 38+ }
 39+ }
 40+
 41+ /**
 42+ * Required parameter check
 43+ * @param $params params extracted from the POST
 44+ */
 45+ protected function validateParams( $params ) {
 46+ $required = array( 'eventid', 'startdate', 'enddate', 'increment', 'userdefs');
 47+ foreach( $required as $arg ) {
 48+ if ( !isset( $params[$arg] ) ) {
 49+ $this->dieUsageMsg( array( 'missingparam', $arg ) );
 50+ }
 51+ }
 52+
 53+ // check if event id parses to an int greater than zero
 54+ if( (int) $params['eventid'] < 0 ) {
 55+ $this->dieUsage( 'Invalid event ID', 'badeventid' );
 56+ }
 57+
 58+ // check start and end date are of proper format
 59+ if( $params['startdate'] != 0 && strptime( $this->space_out_date( $params['startdate'] ), "%Y %m %d" ) === false ) {
 60+ $this->dieUsage( "startdate not in YYYYMMDD format: <<{$params['startdate']}>>", 'badstartdate' );
 61+ }
 62+ if( $params['enddate'] != 0 && strptime( $this->space_out_date( $params['enddate'] ), "%Y %m %d" ) === false ) {
 63+ $this->dieUsage( "enddate not in YYYYMMDD format:<<{$params['enddate']}>>", 'badenddate' );
 64+ }
 65+
 66+ // check if increment is a positive int
 67+ if( (int) $params['increment'] <= 0 ) {
 68+ $this->dieUsage( 'Invalid increment', 'badincrement' );
 69+ }
 70+
 71+ if( json_decode( $params['userdefs'] ) == null ) {
 72+ $this->dieUsage( "Invalid JSON encoding <<{$params['userdefs']}>>", 'badjson' );
 73+ }
 74+ }
 75+
 76+ /**
 77+ * Space out the dates
 78+ * @param $datewithnospaces date with no spaces
 79+ * @return date with spaces
 80+ */
 81+ public function space_out_date( $datewithnospaces ) {
 82+ return ( substr( $datewithnospaces, 0, 4 ) . ' ' .substr( $datewithnospaces, 4, 2 ) . ' ' . substr( $datewithnospaces, 6, 2 ) );
 83+ }
 84+
 85+ public function getParamDescription() {
 86+ return array(
 87+ 'eventid' => 'event ID (number)',
 88+ 'startdate' => 'start date for data in YYYYMMDD format',
 89+ 'enddate' =>'end date for the data in YYYYMMDD format',
 90+ 'increment' => 'increment interval (in days) for data points',
 91+ 'userdefs' => 'JSON object to encode user definitions',
 92+ 'tabledata' => 'set to 1 for table data instead of chart data'
 93+ );
 94+ }
 95+
 96+ public function getDescription() {
 97+ return array(
 98+ 'Returns data to the Special:ClickTracking visualization page'
 99+ );
 100+ }
 101+
 102+ public function getAllowedParams() {
 103+ return array(
 104+ 'eventid' => array(
 105+ ApiBase::PARAM_TYPE => 'integer',
 106+ ApiBase::PARAM_MIN => 1
 107+ ),
 108+ 'startdate' => array(
 109+ ApiBase::PARAM_TYPE => 'timestamp'
 110+ ),
 111+ 'enddate' => array(
 112+ ApiBase::PARAM_TYPE => 'timestamp'
 113+ ),
 114+ 'increment' => array(
 115+ ApiBase::PARAM_TYPE => 'integer',
 116+ ApiBase::PARAM_MIN => 1,
 117+ ApiBase::PARAM_MAX => 365 //1 year
 118+ ),
 119+ 'userdefs' => array(
 120+ ApiBase::PARAM_TYPE => 'string'
 121+ ),
 122+ 'tabledata' => array(
 123+ ApiBase::PARAM_TYPE => 'integer'
 124+ ),
 125+ );
 126+ }
 127+
 128+ // TODO: create a more useful 'version number'
 129+ public function getVersion() {
 130+ return __CLASS__ . ': $Id: $';
 131+ }
 132+
 133+}
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/ApiSpecialClickTracking.php
___________________________________________________________________
Name: svn:eol-style
1134 + native
Index: branches/usability/acaifix/ClickTracking/ClickTrackingEvents.sql
@@ -0,0 +1,16 @@
 2+--
 3+-- Schema for ClickTrackingEvents
 4+--
 5+-- Used to keep track of the various click events by ID
 6+--
 7+
 8+CREATE TABLE IF NOT EXISTS /*_*/click_tracking_events (
 9+ -- event name
 10+ event_name VARBINARY(255) unique,
 11+
 12+ -- day
 13+ id INTEGER AUTO_INCREMENT,
 14+
 15+ -- keyed on event, sql makes you use the id as a primary key
 16+ PRIMARY KEY(id)
 17+) /*$wgDBTableOptions*/;
Property changes on: branches/usability/acaifix/ClickTracking/ClickTrackingEvents.sql
___________________________________________________________________
Name: svn:eol-style
118 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.i18n.php
@@ -0,0 +1,1242 @@
 2+<?php
 3+/**
 4+ * Internationalisation for Usability Initiative Click Tracking extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Nimish Gautam
 14+ */
 15+$messages['en'] = array(
 16+ 'clicktracking' => 'Usability Initiative click tracking',
 17+ 'clicktracking-desc' => 'Click tracking for tracking events that do not cause a page refresh',
 18+ 'ct-title' => 'Aggregated user clicks',
 19+ 'ct-event-name' => 'Event name',
 20+ 'ct-expert-header' => '"Expert" clicks',
 21+ 'ct-intermediate-header' => '"Intermediate" clicks',
 22+ 'ct-beginner-header' => '"Beginner" clicks',
 23+ 'ct-total-header' => 'Total clicks',
 24+ 'ct-start-date' => 'Start Date (YYYYMMDD)',
 25+ 'ct-end-date' => 'End Date (YYYYMMDD)',
 26+ 'ct-increment-by' =>'Number of days each data point represents',
 27+ 'ct-change-graph' =>'Change graph',
 28+ 'ct-beginner' => 'Beginner',
 29+ 'ct-intermediate' => 'Intermediate',
 30+ 'ct-expert' => 'Expert',
 31+ 'ct-date-range' => 'Date range',
 32+ 'ct-editing' => 'Currently editing:',
 33+ 'ct-anon-users' => 'Anonymous users',
 34+ 'ct-user-contribs' => 'Total user contributions',
 35+ 'ct-user-span' => 'User contributions in timespan',
 36+ 'ct-and' => 'and',
 37+ 'ct-update-table' => 'Update table',
 38+);
 39+
 40+/** Message documentation (Message documentation)
 41+ * @author EugeneZelenko
 42+ * @author Fryed-peach
 43+ */
 44+$messages['qqq'] = array(
 45+ 'clicktracking-desc' => '{{desc}}',
 46+ 'ct-expert-header' => '"Expert" is a user-definable category, these will show the number of clicks that fall into that category',
 47+ 'ct-intermediate-header' => '"Intermediate" is a user-definable category, these will show the number of clicks that fall into that category',
 48+ 'ct-beginner-header' => '"Beginner" is a user-definable category, these will show the number of clicks that fall into that category',
 49+ 'ct-total-header' => 'total',
 50+ 'ct-start-date' => 'YYYYMMDD refers to the date format (4-digit year, 2-digit month, 2-digit day)
 51+
 52+{{Identical|Start date}}',
 53+ 'ct-end-date' => 'YYYYMMDD refers to the date format (4-digit year, 2-digit month, 2-digit day)
 54+
 55+{{Identical|End date}}',
 56+ 'ct-beginner' => 'label for a user at beginner skill level',
 57+ 'ct-intermediate' => 'label for a user at intermediate skill level',
 58+ 'ct-expert' => 'label for a user at expert skill level',
 59+ 'ct-date-range' => 'range of dates being shown currently
 60+{{Identical|Date range}}',
 61+ 'ct-and' => '{{Identical|And}}',
 62+);
 63+
 64+/** Afrikaans (Afrikaans)
 65+ * @author Naudefj
 66+ */
 67+$messages['af'] = array(
 68+ 'ct-start-date' => 'Begindatum (JJJJMMDD)',
 69+ 'ct-end-date' => 'Einddatum (JJJJMMDD)',
 70+ 'ct-date-range' => 'Periode',
 71+ 'ct-and' => 'en',
 72+);
 73+
 74+/** Arabic (العربية)
 75+ * @author Meno25
 76+ * @author OsamaK
 77+ */
 78+$messages['ar'] = array(
 79+ 'clicktracking' => 'تتبع نقرات مبادرة الاستخدامية',
 80+ 'ct-event-name' => 'اسم الحدث',
 81+ 'ct-expert-header' => 'نقرات "الخبراء"',
 82+ 'ct-intermediate-header' => 'نقرات "المتوسطين"',
 83+ 'ct-beginner-header' => 'نقرات "المبتدئين"',
 84+ 'ct-total-header' => 'مجموع النقرات',
 85+ 'ct-beginner' => 'مبتدئ',
 86+ 'ct-intermediate' => 'متوسط',
 87+ 'ct-expert' => 'خبير',
 88+ 'ct-date-range' => 'نطاق التاريخ',
 89+ 'ct-editing' => 'يحرر حاليًا:',
 90+ 'ct-anon-users' => 'المستخدمون المجهولون',
 91+ 'ct-user-contribs' => 'مجموع مساهمات المستخدم',
 92+ 'ct-user-span' => 'مساهمات المستخدم في فترة زمنية',
 93+ 'ct-and' => 'و',
 94+ 'ct-update-table' => 'حدّث الجدول',
 95+);
 96+
 97+/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
 98+ * @author EugeneZelenko
 99+ * @author Jim-by
 100+ * @author Red Winged Duck
 101+ */
 102+$messages['be-tarask'] = array(
 103+ 'clicktracking' => 'Сачэньне за націскамі кампутарнай мышшу ў межах ініцыятывы па паляпшэньні зручнасьці і прастаты выкарыстаньня',
 104+ 'clicktracking-desc' => 'Сачэньне за націскамі кампутарнай мышшу, прызначанае для сачэньня за здарэньнямі, якія не вядуць да абнаўленьня старонкі',
 105+ 'ct-title' => 'Групаваныя націскі мышшу ўдзельнікам',
 106+ 'ct-event-name' => 'Назва падзеі',
 107+ 'ct-expert-header' => 'Націскі мышшу для «Экспэрта»',
 108+ 'ct-intermediate-header' => 'Націскі мышшу для «Сярэдняга»',
 109+ 'ct-beginner-header' => 'Націскі мышшу для «Пачынаючага»',
 110+ 'ct-total-header' => 'Усяго націскаў мышшу',
 111+ 'ct-start-date' => 'Дата пачатку (ГГГГММДзДз)',
 112+ 'ct-end-date' => 'Дата сканчэньня (ГГГГММДзДз)',
 113+ 'ct-increment-by' => 'Колькасьць дзён, якія адлюстроўваюцца ў кожным пункце зьвестак',
 114+ 'ct-change-graph' => 'Зьмяніць графік',
 115+ 'ct-beginner' => 'Пачынаючы',
 116+ 'ct-intermediate' => 'Сярэдні',
 117+ 'ct-expert' => 'Экспэрт',
 118+ 'ct-date-range' => 'Дыяпазон датаў',
 119+ 'ct-editing' => 'Цяперашняе рэдагаваньне:',
 120+ 'ct-anon-users' => 'Ананімныя ўдзельнікі',
 121+ 'ct-user-contribs' => 'Агульны ўнёсак удзельніка',
 122+ 'ct-user-span' => 'Унёсак удзельніка за адлегласьць часу',
 123+ 'ct-and' => 'і',
 124+ 'ct-update-table' => 'Абнавіць табліцу',
 125+);
 126+
 127+/** Bengali (বাংলা)
 128+ * @author Bellayet
 129+ */
 130+$messages['bn'] = array(
 131+ 'clicktracking' => 'ইউজাবিলিটি ইনিসিয়াটিভ ক্লিক ট্র্যাকিং',
 132+ 'ct-event-name' => 'ইভেন্টের নাম',
 133+ 'ct-expert-header' => '"দক্ষ" ক্লিক',
 134+ 'ct-intermediate-header' => '"মাধ্যমিক" ক্লিক',
 135+ 'ct-beginner-header' => '"নবাগত" ক্লিক',
 136+ 'ct-total-header' => 'মোট ক্লিক',
 137+ 'ct-start-date' => 'শুরুর তারিখ (YYYYMMDD)',
 138+ 'ct-end-date' => 'শেষ তারিখ (YYYYMMDD)',
 139+ 'ct-increment-by' => 'প্রতিটি ডাটা পয়েন্ট দিনের সংখ্যা বোঝায়',
 140+ 'ct-change-graph' => 'লেখচিত্র পরিবর্তন',
 141+ 'ct-beginner' => 'নবাগত',
 142+ 'ct-intermediate' => 'মাধ্যমিক',
 143+ 'ct-expert' => 'দক্ষ',
 144+);
 145+
 146+/** Breton (Brezhoneg)
 147+ * @author Fulup
 148+ */
 149+$messages['br'] = array(
 150+ 'clicktracking' => 'Heuliañ klikoù an intrudu implijadusted',
 151+ 'clicktracking-desc' => "Heuliañ klikoù, talvezout a ra da heuliañ an darvoudoù na vez ket adkarget ur bajenn d'ho heul",
 152+ 'ct-title' => "Sammad ar c'hlikoù implijerien",
 153+ 'ct-event-name' => 'Anv an darvoud',
 154+ 'ct-total-header' => "Hollad ar c'hlikoù",
 155+ 'ct-start-date' => 'Deiziad kregiñ (AAAAMMJJ)',
 156+ 'ct-end-date' => 'Deiziad echuiñ (AAAAMMJJ)',
 157+ 'ct-beginner' => 'Deraouad',
 158+ 'ct-intermediate' => 'Etre',
 159+ 'ct-expert' => 'Mailh',
 160+ 'ct-editing' => "Oc'h aozañ er mare-mañ :",
 161+ 'ct-anon-users' => 'implijerien dizanv',
 162+ 'ct-and' => 'ha(g)',
 163+);
 164+
 165+/** Bosnian (Bosanski)
 166+ * @author CERminator
 167+ */
 168+$messages['bs'] = array(
 169+ 'clicktracking' => 'Praćenje klikova u Inicijativi upotrebljivosti',
 170+ 'clicktracking-desc' => 'Praćenje klikova, napravljeno za praćenje događaja koji ne proizvode osvježavanje stanice',
 171+ 'ct-title' => 'Akumulirani korisnički klikovi',
 172+ 'ct-event-name' => 'Naziv događaja',
 173+ 'ct-expert-header' => "''Stručnjački'' klikovi",
 174+ 'ct-intermediate-header' => "''Napredni'' klikovi",
 175+ 'ct-beginner-header' => "''Početnički'' klikovi",
 176+ 'ct-total-header' => 'Ukupno klikova',
 177+ 'ct-start-date' => 'Početni datum (YYYYMMDD)',
 178+ 'ct-end-date' => 'Završni datum (YYYYMMDD)',
 179+ 'ct-increment-by' => 'Broj dana koje svaka tačka podataka predstavlja',
 180+ 'ct-change-graph' => 'Promijeni grafikon',
 181+ 'ct-beginner' => 'Početnik',
 182+ 'ct-intermediate' => 'Napredni',
 183+ 'ct-expert' => 'Stručnjak',
 184+ 'ct-date-range' => 'Raspon podataka',
 185+ 'ct-editing' => 'Trenutno se uređuje:',
 186+ 'ct-anon-users' => 'Anonimni korisnici',
 187+ 'ct-user-contribs' => 'Ukupni doprinosi korisnika',
 188+ 'ct-user-span' => 'Korisnički doprinosi u vremenskom periodu',
 189+ 'ct-and' => 'i',
 190+);
 191+
 192+/** Catalan (Català)
 193+ * @author SMP
 194+ */
 195+$messages['ca'] = array(
 196+ 'ct-total-header' => 'Clics totals',
 197+ 'ct-start-date' => "Data d'inici (AAAAMMDD)",
 198+ 'ct-end-date' => 'Data de finalització (AAAAMMDD)',
 199+ 'ct-anon-users' => 'Usuaris anònims',
 200+);
 201+
 202+/** Czech (Česky)
 203+ * @author Mormegil
 204+ */
 205+$messages['cs'] = array(
 206+ 'clicktracking' => 'Sledování kliknutí pro Iniciativu použitelnosti',
 207+ 'clicktracking-desc' => 'Sledování kliknutí pro sledování událostí, které nezpůsobují znovunačtení stránky',
 208+ 'ct-event-name' => 'Název události',
 209+ 'ct-expert-header' => 'Kliknutí „expertů“',
 210+ 'ct-intermediate-header' => 'Kliknutí „pokročilých“',
 211+ 'ct-beginner-header' => 'Kliknutí „začátečníků“',
 212+ 'ct-total-header' => 'Celkem kliknutí',
 213+ 'ct-start-date' => 'Datum začátku (RRRRMMDD)',
 214+ 'ct-end-date' => 'Datum konce (RRRRMMDD)',
 215+ 'ct-increment-by' => 'Počet dní reprezentovaných každým bodem',
 216+ 'ct-change-graph' => 'Změnit graf',
 217+ 'ct-beginner' => 'Začátečník',
 218+ 'ct-intermediate' => 'Pokročilý',
 219+ 'ct-expert' => 'Expert',
 220+ 'ct-date-range' => 'Časový rozsah',
 221+ 'ct-editing' => 'Aktivní uživatelé:',
 222+ 'ct-anon-users' => 'Anonymní uživatelé',
 223+ 'ct-user-contribs' => 'Celkem příspěvků uživatele',
 224+ 'ct-user-span' => 'Příspěvků uživatele během',
 225+ 'ct-and' => 'a zároveň',
 226+);
 227+
 228+/** German (Deutsch)
 229+ * @author Metalhead64
 230+ * @author Umherirrender
 231+ */
 232+$messages['de'] = array(
 233+ 'clicktracking' => 'Benutzerfreundlichkeitsinitiative Klickverfolgung',
 234+ 'clicktracking-desc' => 'Klickverfolgung, gedacht für die Aufzeichnung von Aktionen, die nicht zu einer Seitenaktualisierung führen',
 235+ 'ct-title' => 'Gesamtsumme aller Benutzerklicks',
 236+ 'ct-event-name' => 'Ereignisname',
 237+ 'ct-expert-header' => 'Expertenklicks',
 238+ 'ct-intermediate-header' => 'Klicks von Mittleren',
 239+ 'ct-beginner-header' => 'Anfängerklicks',
 240+ 'ct-total-header' => 'Gesamtklicks',
 241+ 'ct-start-date' => 'Start (JJJJMMTT)',
 242+ 'ct-end-date' => 'Ende (JJJJMMTT)',
 243+ 'ct-increment-by' => 'Anzahl der Tage, die von jedem Datenpunkt repräsentiert werden',
 244+ 'ct-change-graph' => 'Grafik ändern',
 245+ 'ct-beginner' => 'Anfänger',
 246+ 'ct-intermediate' => 'Mittlere',
 247+ 'ct-expert' => 'Experte',
 248+ 'ct-date-range' => 'Datumsbereich',
 249+ 'ct-editing' => 'Derzeit bearbeitet von:',
 250+ 'ct-anon-users' => 'Anonyme Benutzer',
 251+ 'ct-user-contribs' => 'Gesamte Benutzerbeiträge',
 252+ 'ct-user-span' => 'Benutzerbeiträge in Zeitspanne',
 253+ 'ct-and' => 'und',
 254+ 'ct-update-table' => 'Tabelle aktualisieren',
 255+);
 256+
 257+/** Zazaki (Zazaki)
 258+ * @author Aspar
 259+ * @author Xoser
 260+ */
 261+$messages['diq'] = array(
 262+ 'clicktracking' => 'tıknayiş u temaşakerdışê teşebbusê şuxul biyayişi',
 263+ 'clicktracking-desc' => 'Eka yew pele ke reciwane nibeno, ay ser gocekê trackingî rê bitekne',
 264+ 'ct-title' => 'tıknayişê karberê kombiyayeyi',
 265+ 'ct-event-name' => 'nameyê meselayi',
 266+ 'ct-expert-header' => 'tıknayişê "tecrubeyınan"',
 267+ 'ct-intermediate-header' => 'tıknayişê "seviyeya weseti"',
 268+ 'ct-beginner-header' => 'tıknayişê "ecemiyani"',
 269+ 'ct-total-header' => 'heme tıknayişi',
 270+ 'ct-start-date' => 'tarixê destpêkerdışi (YYYYMMDD)',
 271+ 'ct-end-date' => 'tarixê qediyayişi (YYYYMMDD)',
 272+ 'ct-increment-by' => 'Number of days each data point represents',
 273+ 'ct-change-graph' => 'Grafiki bıvurnê',
 274+ 'ct-beginner' => 'ecemi',
 275+ 'ct-intermediate' => 'seviyeya weseti',
 276+ 'ct-expert' => 'tecrubeyın',
 277+ 'ct-date-range' => 'tarix de',
 278+ 'ct-editing' => 'nıka vurneno',
 279+ 'ct-anon-users' => 'karberê anonimi',
 280+ 'ct-user-contribs' => 'heme ardimê karberi',
 281+ 'ct-user-span' => 'ardimê karberi',
 282+ 'ct-and' => 'u',
 283+ 'ct-update-table' => 'tabloya rocaneyi',
 284+);
 285+
 286+/** Lower Sorbian (Dolnoserbski)
 287+ * @author Michawiki
 288+ */
 289+$messages['dsb'] = array(
 290+ 'clicktracking' => 'Kliknjeńske pśeslědowanje iniciatiwy wužywajobnosći',
 291+ 'clicktracking-desc' => 'Kliknjeńske pśeslědowanje, myslone za slědowanje tšojenjow, kótarež njezawinuju aktualizaciju boka',
 292+ 'ct-title' => 'Nakopjone wužywarske kliknjenja',
 293+ 'ct-event-name' => 'Mě tšojenja',
 294+ 'ct-expert-header' => 'Kliknjenja "ekspertow"',
 295+ 'ct-intermediate-header' => 'Kliknjenja "pókšacanych"',
 296+ 'ct-beginner-header' => 'Kliknjenja "zachopjeńkarjow"',
 297+ 'ct-total-header' => 'Kliknjenja dogromady',
 298+ 'ct-start-date' => 'Zachopny datum (YYYYMMDD)',
 299+ 'ct-end-date' => 'Kóńcny datum (YYYYMMDD)',
 300+ 'ct-increment-by' => 'Licba dnjow, kótaruž kuždy datowy dypk reprezentěrujo',
 301+ 'ct-change-graph' => 'Grafisku liniju změniś',
 302+ 'ct-beginner' => 'Zachopjeńkaŕ',
 303+ 'ct-intermediate' => 'Pókšacony',
 304+ 'ct-expert' => 'Ekspert',
 305+ 'ct-date-range' => 'Datumowy wobcerk',
 306+ 'ct-editing' => 'Tuchylu so wobźěłujo:',
 307+ 'ct-anon-users' => 'Anonymne wužywarje',
 308+ 'ct-user-contribs' => 'Wužywarske pśinoski dogromady',
 309+ 'ct-user-span' => 'Wužywarske pśinoski w casowem wótrězku',
 310+ 'ct-and' => 'a',
 311+ 'ct-update-table' => 'Tabelu aktualizěrowaś',
 312+);
 313+
 314+/** Greek (Ελληνικά)
 315+ * @author Consta
 316+ * @author Crazymadlover
 317+ * @author Omnipaedista
 318+ * @author ZaDiak
 319+ */
 320+$messages['el'] = array(
 321+ 'clicktracking' => 'Πατήστε παρακολούθηση της Πρωτοβουλίας Χρηστικότητας',
 322+ 'clicktracking-desc' => 'Πατήστε παρακολούθηση, προορίζεται για την παρακολούθηση εκδηλώσεων που δεν προκαλούν ανανέωση σελίδας',
 323+ 'ct-event-name' => 'Όνομα γεγονότος',
 324+ 'ct-expert-header' => 'Κλικ "ειδικοί"',
 325+ 'ct-intermediate-header' => 'Κλικ "μέτριοι"',
 326+ 'ct-beginner-header' => 'Κλικ "αρχάριοι"',
 327+ 'ct-total-header' => 'Συνολικά κλικ',
 328+ 'ct-start-date' => 'Ημερομηνία έναρξης (ΕΕΕΕΜΜΗΗ)',
 329+ 'ct-end-date' => 'Ημερομηνία λήξης (ΕΕΕΕΜΜΗΗ)',
 330+ 'ct-change-graph' => 'Αλλαγή γραφήματος',
 331+ 'ct-beginner' => 'Αρχάριος',
 332+ 'ct-intermediate' => 'Μέτριος',
 333+ 'ct-expert' => 'Ειδικός',
 334+ 'ct-and' => 'και',
 335+);
 336+
 337+/** Esperanto (Esperanto)
 338+ * @author Lucas
 339+ * @author Yekrats
 340+ */
 341+$messages['eo'] = array(
 342+ 'clicktracking-desc' => 'Sekvado de klakoj, por sekvi klakeventojn kiu ne kaŭzas paĝan refreŝigon',
 343+ 'ct-event-name' => 'Eventa nomo',
 344+ 'ct-expert-header' => 'Klakoj de "Spertuloj"',
 345+ 'ct-intermediate-header' => 'Klakoj de "progresantoj"',
 346+ 'ct-beginner-header' => 'Klakoj de "novuloj"',
 347+ 'ct-total-header' => 'Sumo de klakoj',
 348+ 'ct-start-date' => 'Komenca Dato (JJJJMMTT)',
 349+ 'ct-end-date' => 'Fina Dato (JJJJMMTT)',
 350+ 'ct-beginner' => 'Novulo',
 351+ 'ct-intermediate' => 'Progresanto',
 352+ 'ct-expert' => 'Spertulo',
 353+ 'ct-editing' => 'Nune redaktante:',
 354+ 'ct-anon-users' => 'Sennomaj uzantoj',
 355+ 'ct-and' => 'kaj',
 356+);
 357+
 358+/** Spanish (Español)
 359+ * @author Antur
 360+ * @author Crazymadlover
 361+ * @author Dalton2
 362+ * @author Locos epraix
 363+ * @author Translationista
 364+ */
 365+$messages['es'] = array(
 366+ 'clicktracking' => 'Iniciativa de usabilidad de seguimiento mediante clics',
 367+ 'clicktracking-desc' => 'Seguimiento mediante clics de eventos que no producen refresco de página',
 368+ 'ct-title' => 'Clics de usuario agregados',
 369+ 'ct-event-name' => 'Nombre de evento',
 370+ 'ct-expert-header' => 'Clics "de experto"',
 371+ 'ct-intermediate-header' => 'Clics "de usuario intermedio"',
 372+ 'ct-beginner-header' => 'Clics "de principiante"',
 373+ 'ct-total-header' => 'Clics totales',
 374+ 'ct-start-date' => 'Fecha de inicio (AAMMDD)',
 375+ 'ct-end-date' => 'Fecha de fin (AAMMDD)',
 376+ 'ct-increment-by' => 'Número de días que cada punto representa',
 377+ 'ct-change-graph' => 'Gráfico de cambio',
 378+ 'ct-beginner' => 'Principiante',
 379+ 'ct-intermediate' => 'Intemedio',
 380+ 'ct-expert' => 'Experto',
 381+ 'ct-date-range' => 'Rango de fecha',
 382+ 'ct-editing' => 'Actualmente editando:',
 383+ 'ct-anon-users' => 'Usuarios anónimos',
 384+ 'ct-user-contribs' => 'Total de contribuciones de los usuarios',
 385+ 'ct-user-span' => 'Contribuciones de usuario en lapso de tiempo',
 386+ 'ct-and' => 'y',
 387+ 'ct-update-table' => 'Actualizar tabla',
 388+);
 389+
 390+/** Estonian (Eesti)
 391+ * @author Pikne
 392+ */
 393+$messages['et'] = array(
 394+ 'clicktracking' => 'Kasutushõlpsuse algatuse klõpsujälitus',
 395+ 'ct-event-name' => 'Sündmuse nimi',
 396+ 'ct-expert-header' => 'Asjatundjaklõpsud',
 397+ 'ct-intermediate-header' => 'Edasijõudnuklõpsud',
 398+ 'ct-beginner-header' => 'Algajaklõpsud',
 399+ 'ct-start-date' => 'Alguskuupäev (AAAAKKPP)',
 400+ 'ct-end-date' => 'Lõpukuupäev (AAAAKKPP)',
 401+ 'ct-beginner' => 'Algaja',
 402+ 'ct-intermediate' => 'Edasijõudnu',
 403+ 'ct-expert' => 'Asjatundja',
 404+ 'ct-date-range' => 'Kuupäevavahemik',
 405+ 'ct-editing' => 'Parajasti muutmisel:',
 406+ 'ct-anon-users' => 'Nimetud kasutajad',
 407+ 'ct-and' => 'ja',
 408+);
 409+
 410+/** Basque (Euskara)
 411+ * @author An13sa
 412+ */
 413+$messages['eu'] = array(
 414+ 'ct-event-name' => 'Ekintzaren izena',
 415+ 'ct-expert-header' => '"Aditu" klikak',
 416+ 'ct-intermediate-header' => '"Maila ertaineko" klikak',
 417+ 'ct-beginner-header' => '"Hasiberri" klikak',
 418+ 'ct-total-header' => 'Klikak guztira',
 419+ 'ct-start-date' => 'Hasiera Data (UUUUHHEE)',
 420+ 'ct-end-date' => 'Amaiera Data (UUUUHHEE)',
 421+ 'ct-change-graph' => 'Grafikoa aldatu',
 422+ 'ct-beginner' => 'Hasiberria',
 423+ 'ct-intermediate' => 'Maila ertainekoa',
 424+ 'ct-expert' => 'Aditua',
 425+);
 426+
 427+/** Finnish (Suomi)
 428+ * @author Cimon Avaro
 429+ * @author Crt
 430+ * @author Str4nd
 431+ */
 432+$messages['fi'] = array(
 433+ 'clicktracking' => 'Käytettävyyshankkeen klikkausten seuranta',
 434+ 'clicktracking-desc' => 'Klikkausten seuranta, tarkoituksena seurata tapahtumia, jotka eivät aiheuta sivun uudelleenlataamista.',
 435+ 'ct-title' => 'Käyttäjän napsautuksien yhteenlaskettu määrä',
 436+ 'ct-event-name' => 'Tapahtuman nimi',
 437+ 'ct-total-header' => 'Napsautuksia yhteensä',
 438+ 'ct-start-date' => 'Alkamispäivä (VVVVKKPP)',
 439+ 'ct-end-date' => 'Lopetuspäivä (VVVVKKPP)',
 440+ 'ct-beginner' => 'Aloittelija',
 441+ 'ct-intermediate' => 'Keskitaso',
 442+ 'ct-expert' => 'Asiantuntija',
 443+ 'ct-anon-users' => 'Anonyymit käyttäjät',
 444+ 'ct-and' => 'ja',
 445+);
 446+
 447+/** French (Français)
 448+ * @author McDutchie
 449+ * @author PieRRoMaN
 450+ */
 451+$messages['fr'] = array(
 452+ 'clicktracking' => "Suivi de clics de l'initiative d'utilisabilité",
 453+ 'clicktracking-desc' => 'Suivi de clics, visant à traquer les événements qui ne causent pas un rechargement de page',
 454+ 'ct-title' => "Agrégation des clics d'utilisateurs",
 455+ 'ct-event-name' => "Nom de l'événement",
 456+ 'ct-expert-header' => 'Clics « experts »',
 457+ 'ct-intermediate-header' => 'Clics « intermédiaires »',
 458+ 'ct-beginner-header' => 'Clics « débutants »',
 459+ 'ct-total-header' => 'Total des clics',
 460+ 'ct-start-date' => 'Date de début (AAAAMMJJ)',
 461+ 'ct-end-date' => 'Date de fin (AAAAMMJJ)',
 462+ 'ct-increment-by' => 'Nombre de jours que représente chaque point de donnée',
 463+ 'ct-change-graph' => 'Changer le graphe',
 464+ 'ct-beginner' => 'Débutant',
 465+ 'ct-intermediate' => 'Intermédiaire',
 466+ 'ct-expert' => 'Expert',
 467+ 'ct-date-range' => 'Portée de la date',
 468+ 'ct-editing' => 'En cours de modification :',
 469+ 'ct-anon-users' => 'Utilisateurs anonymes',
 470+ 'ct-user-contribs' => 'Contributions totales des utilisateurs',
 471+ 'ct-user-span' => "Contributions de l'utilisateur sur la durée",
 472+ 'ct-and' => 'et',
 473+ 'ct-update-table' => 'Mettre à jour la table',
 474+);
 475+
 476+/** Galician (Galego)
 477+ * @author Toliño
 478+ */
 479+$messages['gl'] = array(
 480+ 'clicktracking' => 'Seguimento dos clics da Iniciativa de usabilidade',
 481+ 'clicktracking-desc' => 'Seguimento dos clics, co obxectivo de seguir os acontecementos que non causan unha actualización da páxina',
 482+ 'ct-title' => 'Clics de usuario engadidos',
 483+ 'ct-event-name' => 'Nome do evento',
 484+ 'ct-expert-header' => 'Clics "expertos"',
 485+ 'ct-intermediate-header' => 'Clics "intermedios"',
 486+ 'ct-beginner-header' => 'Clics "principiantes"',
 487+ 'ct-total-header' => 'Total de clics',
 488+ 'ct-start-date' => 'Data de inicio (AAAAMMDD)',
 489+ 'ct-end-date' => 'Data de fin (AAAAMMDD)',
 490+ 'ct-increment-by' => 'Número de días que representa cada punto de datos',
 491+ 'ct-change-graph' => 'Cambiar a gráfica',
 492+ 'ct-beginner' => 'Principiante',
 493+ 'ct-intermediate' => 'Intermedio',
 494+ 'ct-expert' => 'Experto',
 495+ 'ct-date-range' => 'Intervalo de datas',
 496+ 'ct-editing' => 'Editando nestes intres:',
 497+ 'ct-anon-users' => 'Usuarios anónimos',
 498+ 'ct-user-contribs' => 'Contribucións totais do usuario',
 499+ 'ct-user-span' => 'Contribucións do usuario nun período de tempo',
 500+ 'ct-and' => 'e',
 501+ 'ct-update-table' => 'Actualizar a táboa',
 502+);
 503+
 504+/** Swiss German (Alemannisch)
 505+ * @author Als-Holder
 506+ */
 507+$messages['gsw'] = array(
 508+ 'clicktracking' => 'D Klickverfolgig vu dr Benutzerfrejndligkeits-Initiative',
 509+ 'clicktracking-desc' => 'Klickverfolgig, fir Aktione, wu kei Syteaktualisierig verursache',
 510+ 'ct-title' => 'Aggregierti Benutzerklicks',
 511+ 'ct-event-name' => 'Ereignis',
 512+ 'ct-expert-header' => '„Experte“-Klicks',
 513+ 'ct-intermediate-header' => 'Klicks vu „Mittlere“',
 514+ 'ct-beginner-header' => '„Aafänger“-Klicks',
 515+ 'ct-total-header' => 'Klicks insgsamt',
 516+ 'ct-start-date' => 'Startdatum (JJJJMMTT)',
 517+ 'ct-end-date' => 'Änddatum (JJJJMMTT)',
 518+ 'ct-increment-by' => 'Aazahl vu Täg, wu ne jede Punkt derfir stoht',
 519+ 'ct-change-graph' => 'Abbildig ändere',
 520+ 'ct-beginner' => 'Aafänger',
 521+ 'ct-intermediate' => 'Mittlere',
 522+ 'ct-expert' => 'Expert',
 523+ 'ct-date-range' => 'Datumsberyych',
 524+ 'ct-editing' => 'Am bearbeite:',
 525+ 'ct-anon-users' => 'Anonymi Benutzer',
 526+ 'ct-user-contribs' => 'Gsamti Benutzerbyytreg',
 527+ 'ct-user-span' => 'Benutzerbyytreg in Zytspanne',
 528+ 'ct-and' => 'un',
 529+ 'ct-update-table' => 'Tabälle aktualisiere',
 530+);
 531+
 532+/** Hebrew (עברית)
 533+ * @author Rotem Liss
 534+ * @author Rotemliss
 535+ * @author YaronSh
 536+ */
 537+$messages['he'] = array(
 538+ 'clicktracking' => 'מעקב לחיצות במיזם השימושיות',
 539+ 'clicktracking-desc' => 'מעקב לחיצות עבור בדיקת אירועים שאינם גורמים לרענון דף',
 540+ 'ct-title' => 'הכמות המצטברת של לחיצות המשתמשים',
 541+ 'ct-event-name' => 'שם האירוע',
 542+ 'ct-expert-header' => 'לחיצות של "מומחים"',
 543+ 'ct-intermediate-header' => 'לחיצות של "בינוניים"',
 544+ 'ct-beginner-header' => 'לחיצות של "מתחילים"',
 545+ 'ct-total-header' => 'סך כל הלחיצות',
 546+ 'ct-start-date' => 'תאריך התחלה (YYYYMMDD)',
 547+ 'ct-end-date' => 'תאריך סיום (YYYYMMDD)',
 548+ 'ct-increment-by' => 'מספר הימים שמייצגת כל נקודת מידע',
 549+ 'ct-change-graph' => 'שינוי הגרף',
 550+ 'ct-beginner' => 'מתחיל',
 551+ 'ct-intermediate' => 'בינוני',
 552+ 'ct-expert' => 'מומחה',
 553+ 'ct-date-range' => 'טווח התאריכים',
 554+ 'ct-editing' => 'כרגע בעריכה:',
 555+ 'ct-anon-users' => 'משתמשים אנונימיים',
 556+ 'ct-user-contribs' => 'סך כל תרומות המשתמשים',
 557+ 'ct-user-span' => 'תרומות המשתמשים לאורך הזמן',
 558+ 'ct-and' => 'וגם',
 559+ 'ct-update-table' => 'עדכון הטבלה',
 560+);
 561+
 562+/** Croatian (Hrvatski)
 563+ * @author Mvrban
 564+ * @author Suradnik13
 565+ */
 566+$messages['hr'] = array(
 567+ 'clicktracking' => 'Praćenje klikova u Inicijativi za uporabljivosti',
 568+ 'clicktracking-desc' => 'Praćenje klikova, napravljeno za praćenje događaja koji ne dovode do osvježavanja stanice',
 569+ 'ct-start-date' => 'Početni datum (DDMMYYYY)',
 570+);
 571+
 572+/** Upper Sorbian (Hornjoserbsce)
 573+ * @author Michawiki
 574+ */
 575+$messages['hsb'] = array(
 576+ 'clicktracking' => 'Kliknjenske přesćěhanje iniciatiwy wužiwajomnosće',
 577+ 'clicktracking-desc' => 'Kliknjenske přesćěhanje, myslene za přesćěhowanje podawkow, kotrež aktualizaciju strony njezawinuja',
 578+ 'ct-title' => 'Nakopjene wužiwarske kliknjenja',
 579+ 'ct-event-name' => 'Mjenp podawka',
 580+ 'ct-expert-header' => 'Kliknjenja "ekspertow"',
 581+ 'ct-intermediate-header' => 'Kliknjenja "pokročenych"',
 582+ 'ct-beginner-header' => 'Kliknjenja "započatkarjow"',
 583+ 'ct-total-header' => 'Kliknjenja dohromady',
 584+ 'ct-start-date' => 'Spočatny datum (YYYYMMDD)',
 585+ 'ct-end-date' => 'Kónčny datum (YYYYMMDD)',
 586+ 'ct-increment-by' => 'Ličba dnjow, kotruž kóždy datowy dypk reprezentuje',
 587+ 'ct-change-graph' => 'Grafisku liniju změnić',
 588+ 'ct-beginner' => 'Započatkar',
 589+ 'ct-intermediate' => 'Pokročeny',
 590+ 'ct-expert' => 'Ekspert',
 591+ 'ct-date-range' => 'Datumowy rozsah',
 592+ 'ct-editing' => 'Tuchwilu so wobdźěłuje:',
 593+ 'ct-anon-users' => 'Anonymni wužiwarjo',
 594+ 'ct-user-contribs' => 'Wužiwarske přinoški dohromady',
 595+ 'ct-user-span' => 'Wužiwarske přinoški w časowym wotrězku',
 596+ 'ct-and' => 'a',
 597+ 'ct-update-table' => 'Tabelu aktualizować',
 598+);
 599+
 600+/** Hungarian (Magyar)
 601+ * @author Bdamokos
 602+ * @author Dani
 603+ * @author Glanthor Reviol
 604+ */
 605+$messages['hu'] = array(
 606+ 'clicktracking' => 'Usability Initiative kattintásszámláló',
 607+ 'clicktracking-desc' => 'Kattintásszámláló, az olyan események rögzítésére, melyekhez nem szükséges a lap frissítése',
 608+ 'ct-title' => 'Aggregált felhasználói kattintások',
 609+ 'ct-event-name' => 'Esemény neve',
 610+ 'ct-expert-header' => '„Szakértők” kattintásai',
 611+ 'ct-intermediate-header' => '„Középhaladók” kattintásai',
 612+ 'ct-beginner-header' => '„Kezdők” kattintásai',
 613+ 'ct-total-header' => 'Összes kattintás',
 614+ 'ct-start-date' => 'Kezdődátum (ÉÉÉÉHHNN)',
 615+ 'ct-end-date' => 'Végdátum (ÉÉÉÉHHNN)',
 616+ 'ct-increment-by' => 'Az egyes adatpontok által jelölt napok száma',
 617+ 'ct-change-graph' => 'Változásgrafikon',
 618+ 'ct-beginner' => 'Kezdő',
 619+ 'ct-intermediate' => 'Középhaladó',
 620+ 'ct-expert' => 'Szakértő',
 621+ 'ct-date-range' => 'Időszak',
 622+ 'ct-editing' => 'Jelenleg szerkesztők:',
 623+ 'ct-anon-users' => 'Névtelen szerkesztők',
 624+ 'ct-user-contribs' => 'Összes szerkesztői közreműködés',
 625+ 'ct-user-span' => 'A szerkesztő közreműködései az időszakon belül',
 626+ 'ct-and' => 'és',
 627+ 'ct-update-table' => 'Táblázat frissítése',
 628+);
 629+
 630+/** Interlingua (Interlingua)
 631+ * @author McDutchie
 632+ */
 633+$messages['ia'] = array(
 634+ 'clicktracking' => 'Traciamento de clics del Initiativa de Usabilitate',
 635+ 'clicktracking-desc' => 'Traciamento de clics, pro traciar eventos que non causa un recargamento de pagina',
 636+ 'ct-title' => 'Clics de usator aggregate',
 637+ 'ct-event-name' => 'Nomine del evento',
 638+ 'ct-expert-header' => 'Clics "experte"',
 639+ 'ct-intermediate-header' => 'Clics "intermedie"',
 640+ 'ct-beginner-header' => 'Clics "comenciante"',
 641+ 'ct-total-header' => 'Total de clics',
 642+ 'ct-start-date' => 'Data de initio (AAAAMMDD)',
 643+ 'ct-end-date' => 'Data de fin (AAAAMMDD)',
 644+ 'ct-increment-by' => 'Numero de dies representate per cata puncto de datos',
 645+ 'ct-change-graph' => 'Cambiar graphico',
 646+ 'ct-beginner' => 'Comenciante',
 647+ 'ct-intermediate' => 'Intermedie',
 648+ 'ct-expert' => 'Experte',
 649+ 'ct-date-range' => 'Intervallo de datas',
 650+ 'ct-editing' => 'Actualmente modificante:',
 651+ 'ct-anon-users' => 'Usatores anonyme',
 652+ 'ct-user-contribs' => 'Total de contributiones de usatores',
 653+ 'ct-user-span' => 'Contributiones de usatores in intervallo de tempore',
 654+ 'ct-and' => 'e',
 655+ 'ct-update-table' => 'Actualisar tabella',
 656+);
 657+
 658+/** Indonesian (Bahasa Indonesia)
 659+ * @author Bennylin
 660+ * @author Irwangatot
 661+ */
 662+$messages['id'] = array(
 663+ 'clicktracking' => 'Pelacak klik Inisiatif Kebergunaan',
 664+ 'clicktracking-desc' => "Pelacak klik, digunakan untuk melacak kejadian yang tidak menyebabkan ''refresh'' halaman",
 665+ 'ct-title' => 'Total klik pengguna',
 666+ 'ct-event-name' => 'Nama even',
 667+ 'ct-expert-header' => 'Klik "mahir"',
 668+ 'ct-intermediate-header' => 'Klik "menengah"',
 669+ 'ct-beginner-header' => 'Klik "pemula"',
 670+ 'ct-total-header' => 'Klik total',
 671+ 'ct-start-date' => 'Tanggal Mulai (YYYYMMDD)',
 672+ 'ct-end-date' => 'Tanggal selesai (YYYYMMDD)',
 673+ 'ct-increment-by' => 'Setiap poin mencerminkan jumlah hari',
 674+ 'ct-change-graph' => 'Ganti grafik',
 675+ 'ct-beginner' => 'Pemula',
 676+ 'ct-intermediate' => 'Menengah',
 677+ 'ct-expert' => 'Mahir',
 678+ 'ct-date-range' => 'Interval tanggal',
 679+ 'ct-editing' => 'Saat ini menyunting:',
 680+ 'ct-anon-users' => 'Pengguna anonim',
 681+ 'ct-user-contribs' => 'Total kontribusi pengguna',
 682+ 'ct-user-span' => 'Kontribusi pengguna dalam rentang waktu',
 683+ 'ct-and' => 'dan',
 684+ 'ct-update-table' => 'Pemutahiran tabel',
 685+);
 686+
 687+/** Japanese (日本語)
 688+ * @author Fryed-peach
 689+ * @author 青子守歌
 690+ */
 691+$messages['ja'] = array(
 692+ 'clicktracking' => 'Usability Initiative クリック追跡',
 693+ 'clicktracking-desc' => 'クリック追跡:ページの再描画を引き起こさないイベントを追跡記録する機能',
 694+ 'ct-title' => '利用者クリック集計',
 695+ 'ct-event-name' => 'イベント名',
 696+ 'ct-expert-header' => '「上級者」のクリック数',
 697+ 'ct-intermediate-header' => '「中級者」のクリック数',
 698+ 'ct-beginner-header' => '「初級者」のクリック数',
 699+ 'ct-total-header' => 'クリック回数合計',
 700+ 'ct-start-date' => '開始日 (YYYYMMDD)',
 701+ 'ct-end-date' => '終了日 (YYYYMMDD)',
 702+ 'ct-increment-by' => '各データ点が表す日数',
 703+ 'ct-change-graph' => 'グラフ変更',
 704+ 'ct-beginner' => '初級者',
 705+ 'ct-intermediate' => '中級者',
 706+ 'ct-expert' => '上級者',
 707+ 'ct-date-range' => '日付範囲',
 708+ 'ct-editing' => '現在編集中:',
 709+ 'ct-anon-users' => '匿名利用者',
 710+ 'ct-user-contribs' => '利用者投稿の合計',
 711+ 'ct-user-span' => '期間ごとの利用者投稿',
 712+ 'ct-and' => 'および',
 713+ 'ct-update-table' => 'テーブルを更新',
 714+);
 715+
 716+/** Georgian (ქართული)
 717+ * @author Temuri rajavi
 718+ */
 719+$messages['ka'] = array(
 720+ 'ct-beginner' => 'დამწყები',
 721+);
 722+
 723+/** Khmer (ភាសាខ្មែរ)
 724+ * @author វ័ណថារិទ្ធ
 725+ */
 726+$messages['km'] = array(
 727+ 'ct-event-name' => 'ឈ្មោះព្រឹត្តិការណ៍​',
 728+ 'ct-total-header' => 'ចំនួនចុចសរុប​',
 729+ 'ct-start-date' => 'កាលបរិច្ឆេទ​ចាប់ផ្ដើម (YYYYMMDD)',
 730+ 'ct-end-date' => 'កាលបរិច្ឆេទ​បញ្ចប់ (YYYYMMDD)',
 731+ 'ct-and' => 'និង​',
 732+);
 733+
 734+/** Korean (한국어)
 735+ * @author Klutzy
 736+ * @author Kwj2772
 737+ */
 738+$messages['ko'] = array(
 739+ 'clicktracking' => 'Usability Initiative 사용자 클릭 추적기',
 740+ 'clicktracking-desc' => '마우스 클릭 이벤트 중에서 웹 페이지 새로고침과 관계없는 것들을 추적합니다.',
 741+ 'ct-event-name' => '이벤트 이름',
 742+ 'ct-start-date' => '시작 날짜 (YYYYMMDD)',
 743+ 'ct-end-date' => '마지막 날짜 (YYYYMMDD)',
 744+ 'ct-beginner' => '초보자',
 745+ 'ct-intermediate' => '중급 사용자',
 746+ 'ct-expert' => '전문가',
 747+ 'ct-date-range' => '날짜 범위',
 748+ 'ct-and' => '그리고',
 749+ 'ct-update-table' => '표 업데이트',
 750+);
 751+
 752+/** Ripoarisch (Ripoarisch)
 753+ * @author Purodha
 754+ */
 755+$messages['ksh'] = array(
 756+ 'clicktracking' => 'Dä <i lang="en">Wikipedia Usability Initiative</i> ier Kleckverfolljung',
 757+ 'clicktracking-desc' => 'Klecks un Akßuhne Verfollje, di kein neu Sigg afroofe donn.',
 758+ 'ct-title' => 'Metmaacher ier jesampte Klecks',
 759+ 'ct-event-name' => 'Da Name vun dämm, wat passeet es',
 760+ 'ct-expert-header' => 'Klecks vun „{{int:Expert}}“',
 761+ 'ct-intermediate-header' => 'Klecks vun „{{int:Intermediate}}“',
 762+ 'ct-beginner-header' => 'Klecks vun „{{int:Beginner}}e“',
 763+ 'ct-total-header' => 'Jesampzahl aan Kleks',
 764+ 'ct-start-date' => 'Et Dattum vum Aanfang (en dä Forrem: JJJJMMDD)',
 765+ 'ct-end-date' => 'Et Dattum vum Engk (en dä Forrem: JJJJMMDD)',
 766+ 'ct-increment-by' => 'De Aanzahl Dääsch, woh jede Pungk em Diajramm daashtälle sull',
 767+ 'ct-change-graph' => 'Dat Diajramm ändere',
 768+ 'ct-beginner' => 'Aanfänger udder Neuling',
 769+ 'ct-intermediate' => 'Meddel',
 770+ 'ct-expert' => 'Mer kännt sesch uß',
 771+ 'ct-date-range' => 'Zick',
 772+ 'ct-editing' => 'Aam Ändere',
 773+ 'ct-anon-users' => 'Nameloose Metmaacher',
 774+ 'ct-user-contribs' => 'Em Metmaacher sing Beidrääsch enßjesamp',
 775+ 'ct-user-span' => 'Em Metmaacher sing Beidrääsch en dä Zick',
 776+ 'ct-and' => ', un',
 777+);
 778+
 779+/** Luxembourgish (Lëtzebuergesch)
 780+ * @author Robby
 781+ */
 782+$messages['lb'] = array(
 783+ 'clicktracking' => 'Benotzerfrëndlechkeetsinitiative Suivi vun de Klicken',
 784+ 'clicktracking-desc' => "Suivi vun de Klicken, fir déi Aktiounen z'erfaassen déi net zu engem neie Luede vun der Säit féieren",
 785+ 'ct-title' => 'Opgezeechent Benotzerklicken',
 786+ 'ct-event-name' => 'Numm vum Evenement',
 787+ 'ct-expert-header' => '"Expert"-Klicken',
 788+ 'ct-intermediate-header' => '"Duerschnëtt"-Klicken',
 789+ 'ct-beginner-header' => '"Ufänker"-Klicken',
 790+ 'ct-total-header' => 'Total vun de Klicken',
 791+ 'ct-start-date' => 'Ufanksdatum (YYYYMMDD)',
 792+ 'ct-end-date' => 'Schlussdatum (YYYYMMDD)',
 793+ 'ct-increment-by' => 'Zuel vun Deeg déi vun all Datepunkt duergestallt ginn',
 794+ 'ct-change-graph' => 'Ännerungs-Grafik',
 795+ 'ct-beginner' => 'Ufänger',
 796+ 'ct-intermediate' => 'Dertëschent',
 797+ 'ct-expert' => 'Expert',
 798+ 'ct-date-range' => 'Datumsberäich',
 799+ 'ct-editing' => 'Ännert elo:',
 800+ 'ct-anon-users' => 'Anonym Benotzer',
 801+ 'ct-user-contribs' => 'Total vun de Benotzer-Kontributiounen',
 802+ 'ct-user-span' => 'Benotzerkontributiounen am Zäitraum',
 803+ 'ct-and' => 'an',
 804+ 'ct-update-table' => 'Tabell aktualiséieren',
 805+);
 806+
 807+/** Macedonian (Македонски)
 808+ * @author Bjankuloski06
 809+ */
 810+$messages['mk'] = array(
 811+ 'clicktracking' => 'Следење на кликнувања на Иницијативата за употребливост',
 812+ 'clicktracking-desc' => 'Следење на кликнувања, наменето за следење на постапки кои не предизвикуваат превчитување на страницата',
 813+ 'ct-title' => 'Насобрани кориснички кликови',
 814+ 'ct-event-name' => 'Име на настанот',
 815+ 'ct-expert-header' => '„Експертски“ кликови',
 816+ 'ct-intermediate-header' => '„Средно-учеснички“ кликови',
 817+ 'ct-beginner-header' => '„Почетнички“ кликови',
 818+ 'ct-total-header' => 'Вкупно кликови',
 819+ 'ct-start-date' => 'Почетен датум (ГГГГММДД)',
 820+ 'ct-end-date' => 'Завршен датум (ГГГГММДД)',
 821+ 'ct-increment-by' => 'Број на денови што ги претставува секоја податочна точка',
 822+ 'ct-change-graph' => 'Промени го графикот',
 823+ 'ct-beginner' => 'Почетник',
 824+ 'ct-intermediate' => 'Среден',
 825+ 'ct-expert' => 'Експерт',
 826+ 'ct-date-range' => 'Датуми',
 827+ 'ct-editing' => 'Моментално уредувате:',
 828+ 'ct-anon-users' => 'Анонимни корисници',
 829+ 'ct-user-contribs' => 'Вкупно кориснички придонеси',
 830+ 'ct-user-span' => 'Ккориснички придонеси за период',
 831+ 'ct-and' => 'и',
 832+ 'ct-update-table' => 'Ажурирај ја таблицата',
 833+);
 834+
 835+/** Malayalam (മലയാളം)
 836+ * @author Praveenp
 837+ */
 838+$messages['ml'] = array(
 839+ 'ct-start-date' => 'തുടങ്ങുന്ന തീയതി (YYYYMMDD)',
 840+ 'ct-end-date' => 'അവസാനിക്കുന്ന തീയതി (YYYYMMDD)',
 841+ 'ct-change-graph' => 'ഗ്രാഫിൽ മാറ്റംവരുത്തുക',
 842+ 'ct-editing' => 'ഇപ്പോൾ തിരുത്തുന്നത്:',
 843+ 'ct-anon-users' => 'അജ്ഞാത ഉപയോക്താക്കൾ',
 844+ 'ct-user-contribs' => 'ഉപയോക്താവിന്റെ ആകെ സേവനങ്ങൾ',
 845+ 'ct-user-span' => 'ഉപയോക്താവിന്റെ സേവനങ്ങൾ സമയക്രമത്തിൽ',
 846+ 'ct-and' => 'ഒപ്പം',
 847+ 'ct-update-table' => 'പട്ടിക പുതുക്കുക',
 848+);
 849+
 850+/** Malay (Bahasa Melayu)
 851+ * @author Kurniasan
 852+ */
 853+$messages['ms'] = array(
 854+ 'clicktracking' => 'Pengesanan klik Inisiatif Kebolehgunaan',
 855+ 'clicktracking-desc' => 'Pengesanan klik, bertujuan untuk mengesan peristiwa-peristiwa yang tidak menyebabkan penyegaran semula sebuah laman.',
 856+);
 857+
 858+/** Dutch (Nederlands)
 859+ * @author Siebrand
 860+ */
 861+$messages['nl'] = array(
 862+ 'clicktracking' => 'Klikvolgen voor het Bruikbaarheidsinitiatief',
 863+ 'clicktracking-desc' => 'Klikvolgen voor het volgens van handelingen die niet het oproepen van een nieuwe pagina tot gevolg hebben',
 864+ 'ct-title' => 'Samengevoegde gebruikerskliks',
 865+ 'ct-event-name' => 'Gebeurtenis',
 866+ 'ct-expert-header' => '"Expert"-kliks',
 867+ 'ct-intermediate-header' => '"Gemiddeld"-kliks',
 868+ 'ct-beginner-header' => '"Beginner"-kliks',
 869+ 'ct-total-header' => 'Kliktotaal',
 870+ 'ct-start-date' => 'Startdatum (JJJJMMDD)',
 871+ 'ct-end-date' => 'Einddatum (JJJJMMDD)',
 872+ 'ct-increment-by' => 'Aantal dagen dat ieder punt representeert',
 873+ 'ct-change-graph' => 'Grafiek wijzigen',
 874+ 'ct-beginner' => 'Beginner',
 875+ 'ct-intermediate' => 'Gemiddeld',
 876+ 'ct-expert' => 'Expert',
 877+ 'ct-date-range' => 'Periode',
 878+ 'ct-editing' => 'Bezig met het bewerken van:',
 879+ 'ct-anon-users' => 'Anonieme gebruikers',
 880+ 'ct-user-contribs' => 'Totaal aantal gebruikersbijdragen',
 881+ 'ct-user-span' => 'Gebruikersbijdragen in periode',
 882+ 'ct-and' => 'en',
 883+ 'ct-update-table' => 'Tabel bijwerken',
 884+);
 885+
 886+/** Norwegian Nynorsk (‪Norsk (nynorsk)‬)
 887+ * @author Gunnernett
 888+ */
 889+$messages['nn'] = array(
 890+ 'ct-start-date' => 'Startdato (ÅÅÅÅMMDD)',
 891+ 'ct-expert' => 'Ekspert',
 892+ 'ct-anon-users' => 'Anonyme brukarar',
 893+);
 894+
 895+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 896+ * @author Jon Harald Søby
 897+ */
 898+$messages['no'] = array(
 899+ 'clicktracking' => 'Klikksporing for brukervennlighetsprosjektet.',
 900+ 'clicktracking-desc' => 'Sporer klikk som ikke forårsaker lasting av ny side.',
 901+ 'ct-expert-header' => '«Ekspertklikk»',
 902+ 'ct-intermediate-header' => '«Mellomnivåbrukerklikk»',
 903+ 'ct-beginner-header' => '«Nybegynnerklikk»',
 904+ 'ct-total-header' => 'Totalt antall klikk',
 905+ 'ct-start-date' => 'Fra (ÅÅÅÅMMDD)',
 906+ 'ct-end-date' => 'Til (ÅÅÅÅMMDD)',
 907+ 'ct-increment-by' => 'Antall dager representert i hvert datapunkt.',
 908+ 'ct-change-graph' => 'Endre graf',
 909+ 'ct-beginner' => 'Nybegynner',
 910+ 'ct-intermediate' => 'Mellomnivåbruker',
 911+ 'ct-expert' => 'Ekspert',
 912+ 'ct-date-range' => 'Datoer som vises',
 913+ 'ct-editing' => 'Redigerer:',
 914+ 'ct-anon-users' => 'Anonyme brukere',
 915+ 'ct-user-contribs' => 'Totalt antall bidrag',
 916+ 'ct-user-span' => 'Bidrag i tid',
 917+ 'ct-and' => 'og',
 918+);
 919+
 920+/** Occitan (Occitan)
 921+ * @author Cedric31
 922+ */
 923+$messages['oc'] = array(
 924+ 'clicktracking' => "Seguit de clics de l'iniciativa d'utilizabilitat",
 925+ 'clicktracking-desc' => 'Seguit de clics, visant a tracar los eveniments que causan pas un recargament de pagina',
 926+ 'ct-title' => "Agregacion dels clics d'utilizaires",
 927+ 'ct-event-name' => "Nom de l'eveniment",
 928+ 'ct-expert-header' => 'Clics « expèrts »',
 929+ 'ct-intermediate-header' => 'Clics « intermediaris »',
 930+ 'ct-beginner-header' => 'Clics « debutants »',
 931+ 'ct-total-header' => 'Total dels clics',
 932+ 'ct-start-date' => 'Data de començament (AAAAMMJJ)',
 933+ 'ct-end-date' => 'Data de fin (AAAAMMJJ)',
 934+ 'ct-increment-by' => 'Nombre de jorns que representa cada punt de donada',
 935+ 'ct-change-graph' => 'Graf de cambi',
 936+ 'ct-beginner' => 'Debutant',
 937+ 'ct-intermediate' => 'Intermediari',
 938+ 'ct-expert' => 'Expèrt',
 939+ 'ct-date-range' => 'Portada de la data',
 940+ 'ct-editing' => 'En cors de modificacion :',
 941+ 'ct-anon-users' => 'Utilizaires anonims',
 942+ 'ct-user-contribs' => 'Contribucions totalas dels utilizaires',
 943+ 'ct-user-span' => "Contribucions de l'utilizaire sus la durada",
 944+ 'ct-and' => 'e',
 945+ 'ct-update-table' => 'Metre a jorn la taula',
 946+);
 947+
 948+/** Polish (Polski)
 949+ * @author Leinad
 950+ * @author Sp5uhe
 951+ */
 952+$messages['pl'] = array(
 953+ 'clicktracking' => 'Śledzenie kliknięć dla inicjatywy użyteczności',
 954+ 'clicktracking-desc' => 'Śledzenie kliknięć, przeznaczone do poszukiwania zdarzeń, które nie powodują odświeżenia strony',
 955+ 'ct-title' => 'Zestawienie kliknięć użytkowników',
 956+ 'ct-event-name' => 'Nazwa zdarzenia',
 957+ 'ct-expert-header' => 'Kliknięcia „specjalistów”',
 958+ 'ct-intermediate-header' => 'Kliknięcia „zaawansowanych”',
 959+ 'ct-beginner-header' => 'Kliknięcia „nowicjuszy”',
 960+ 'ct-total-header' => 'Wszystkich kliknięć',
 961+ 'ct-start-date' => 'Data rozpoczęcia (RRRRMMDD)',
 962+ 'ct-end-date' => 'Data zakończenia (RRRRMMDD)',
 963+ 'ct-increment-by' => 'Liczba dni, którą oznacza każdy punkt danych',
 964+ 'ct-change-graph' => 'Wykres zmian',
 965+ 'ct-beginner' => 'Nowicjusz',
 966+ 'ct-intermediate' => 'Zaawansowany',
 967+ 'ct-expert' => 'Specjalista',
 968+ 'ct-date-range' => 'Zakres dat',
 969+ 'ct-editing' => 'Teraz edytują:',
 970+ 'ct-anon-users' => 'Anonimowi użytkownicy',
 971+ 'ct-user-contribs' => 'Ogółem wkład użytkownika',
 972+ 'ct-user-span' => 'Wkład użytkownika w przedziale czasu',
 973+ 'ct-and' => 'i',
 974+ 'ct-update-table' => 'Uaktualnij tabelę',
 975+);
 976+
 977+/** Piedmontese (Piemontèis)
 978+ * @author Dragonòt
 979+ */
 980+$messages['pms'] = array(
 981+ 'clicktracking' => "Trassadura dij click ëd l'Usability Initiative",
 982+ 'clicktracking-desc' => "Trassadura dij click, për trassé dj'event cha a causo pa ël refresh ëd na pàgina",
 983+ 'ct-title' => "Clich agregà ëd l'utent",
 984+ 'ct-event-name' => "Nòm ëd l'event",
 985+ 'ct-expert-header' => 'Click d\'"Espert"',
 986+ 'ct-intermediate-header' => 'Click dj\'"antërmedi"',
 987+ 'ct-beginner-header' => 'Click ëd "prinsipiant"',
 988+ 'ct-total-header' => 'Click totaj',
 989+ 'ct-start-date' => 'Data ëd partensa (AAAAMMDD)',
 990+ 'ct-end-date' => 'Data ëd fin (AAAAMMDD)',
 991+ 'ct-increment-by' => 'Nùmer ëd di che minca pont a arpresenta',
 992+ 'ct-change-graph' => 'Cambia ël graf',
 993+ 'ct-beginner' => 'Prinsipiant',
 994+ 'ct-intermediate' => 'Antërmedi',
 995+ 'ct-expert' => 'Espert',
 996+ 'ct-date-range' => 'Antërval ëd date',
 997+ 'ct-editing' => 'Al moment an modìfica:',
 998+ 'ct-anon-users' => 'Utent anònim',
 999+ 'ct-user-contribs' => "Contribussion totaj ëd l'utent",
 1000+ 'ct-user-span' => "Contribussion ëd l'utent ant l'interval",
 1001+ 'ct-and' => 'e',
 1002+);
 1003+
 1004+/** Portuguese (Português)
 1005+ * @author Giro720
 1006+ * @author Lijealso
 1007+ */
 1008+$messages['pt'] = array(
 1009+ 'ct-change-graph' => 'Mudar gráfico',
 1010+ 'ct-beginner' => 'Iniciante',
 1011+ 'ct-intermediate' => 'Intermediário',
 1012+ 'ct-expert' => 'Experiente',
 1013+ 'ct-date-range' => 'Intervalo de datas',
 1014+ 'ct-editing' => 'A editar actualmente:',
 1015+ 'ct-anon-users' => 'Usuários anónimos',
 1016+ 'ct-and' => 'e',
 1017+);
 1018+
 1019+/** Brazilian Portuguese (Português do Brasil)
 1020+ * @author Eduardo.mps
 1021+ */
 1022+$messages['pt-br'] = array(
 1023+ 'clicktracking' => 'Monitoramento de cliques da Iniciativa de Usabilidade',
 1024+ 'clicktracking-desc' => 'Monitoramento de cliques, destinado ao monitoramento de eventos que não causem uma atualização de página',
 1025+);
 1026+
 1027+/** Russian (Русский)
 1028+ * @author HalanTul
 1029+ * @author Kv75
 1030+ * @author Александр Сигачёв
 1031+ */
 1032+$messages['ru'] = array(
 1033+ 'clicktracking' => 'Отслеживание нажатий в рамках Инициативы юзабилити',
 1034+ 'clicktracking-desc' => 'Отслеживание нажатий. Предназначается для отслеживания событий, не приводящих к обновлению страницы',
 1035+ 'ct-title' => 'Агрегированные щелчки мышью участников',
 1036+ 'ct-event-name' => 'Название события',
 1037+ 'ct-expert-header' => 'Нажатия «экспертов»',
 1038+ 'ct-intermediate-header' => 'Нажатия «средних участников»',
 1039+ 'ct-beginner-header' => 'Нажатия «новичков»',
 1040+ 'ct-total-header' => 'Всего нажатий',
 1041+ 'ct-start-date' => 'Дата начала (ГГГГММДД)',
 1042+ 'ct-end-date' => 'Дата окончания (ГГГГММДД)',
 1043+ 'ct-increment-by' => 'Количество дней, которое представляет каждая точка данных',
 1044+ 'ct-change-graph' => 'Изменить график',
 1045+ 'ct-beginner' => 'Новичок',
 1046+ 'ct-intermediate' => 'Средний участник',
 1047+ 'ct-expert' => 'Эксперт',
 1048+ 'ct-date-range' => 'Диапазон дат',
 1049+ 'ct-editing' => 'Текущее редактирование:',
 1050+ 'ct-anon-users' => 'Анонимные участники',
 1051+ 'ct-user-contribs' => 'Общий вклад участников',
 1052+ 'ct-user-span' => 'Вклад участников за период',
 1053+ 'ct-and' => 'и',
 1054+ 'ct-update-table' => 'Обновить таблицу',
 1055+);
 1056+
 1057+/** Yakut (Саха тыла)
 1058+ * @author HalanTul
 1059+ */
 1060+$messages['sah'] = array(
 1061+ 'clicktracking' => 'Баттааһыннары Табыгас Ситиһиитин иһинэн кэтээһин',
 1062+ 'clicktracking-desc' => 'Баттааһыны кэтээһин. Сирэйи саҥардыбат түбэлтэлэри кэтииргэ туттуллар',
 1063+ 'ct-event-name' => 'Түбэлтэ аата',
 1064+ 'ct-expert-header' => '"Экспертар" баттааһыннара (клик)',
 1065+ 'ct-intermediate-header' => '"Орто кыттааччылар" баттааһыннара (клик)',
 1066+ 'ct-beginner-header' => '"Саҕалааччылар" баттааһыннара (клик)',
 1067+ 'ct-total-header' => 'Баттааһын барытын ахсаана',
 1068+ 'ct-start-date' => 'Саҕаламмыт күнэ-ыйа (ССССЫЫКК)',
 1069+ 'ct-end-date' => 'Бүппүт күнэ-дьыла (ССССЫЫКК)',
 1070+ 'ct-change-graph' => 'Графигы уларытыы',
 1071+ 'ct-beginner' => 'Саҥа кыттааччы',
 1072+ 'ct-intermediate' => 'Бороохтуйбут кыттааччы',
 1073+ 'ct-expert' => 'Эксперт',
 1074+ 'ct-date-range' => 'Күн-дьыл диапазона',
 1075+ 'ct-anon-users' => 'Ааттамматах кыттааччылар',
 1076+ 'ct-and' => 'уонна',
 1077+);
 1078+
 1079+/** Slovak (Slovenčina)
 1080+ * @author Helix84
 1081+ */
 1082+$messages['sk'] = array(
 1083+ 'clicktracking' => 'Sledovanie kliknutí pre Iniciatívu použiteľnosti',
 1084+ 'clicktracking-desc' => 'Sledovanie kliknutí, na sledovanie udalostí, ktoré nespôsobujú opätovné načítanie stránky',
 1085+ 'ct-title' => 'Agregovaných kliknutí',
 1086+ 'ct-event-name' => 'Názov udalosti',
 1087+ 'ct-expert-header' => 'Kliknutia „expertov“',
 1088+ 'ct-intermediate-header' => 'Kliknutia „pokročilých“',
 1089+ 'ct-beginner-header' => 'Kliknutia „začiatočníkov“',
 1090+ 'ct-total-header' => 'Kliknutí celkom',
 1091+ 'ct-start-date' => 'Dátum začiatku (YYYYMMDD)',
 1092+ 'ct-end-date' => 'Dátum konca (YYYYMMDD)',
 1093+ 'ct-increment-by' => 'Počet dní, ktorý predstavuje každý z bodov v dátach',
 1094+ 'ct-change-graph' => 'Zmeniť graf',
 1095+ 'ct-beginner' => 'Začiatočník',
 1096+ 'ct-intermediate' => 'Pokročilý',
 1097+ 'ct-expert' => 'Expert',
 1098+ 'ct-date-range' => 'Rozsah dátumov',
 1099+ 'ct-editing' => 'Momentálne upravuje:',
 1100+ 'ct-anon-users' => 'Anonymní používatelia',
 1101+ 'ct-user-contribs' => 'Používateľských príspevkov celkom',
 1102+ 'ct-user-span' => 'Používateľských príspevkov za obdobie',
 1103+ 'ct-and' => 'a',
 1104+);
 1105+
 1106+/** Slovenian (Slovenščina)
 1107+ * @author Smihael
 1108+ */
 1109+$messages['sl'] = array(
 1110+ 'clicktracking' => 'Sledenje klikom Iniciative za uporabnost',
 1111+ 'clicktracking-desc' => 'Sledenje klikom, namenjeno odkrivanju dogodkov, ki preprečujejo osvežitev strani med urejanjem',
 1112+);
 1113+
 1114+/** Telugu (తెలుగు)
 1115+ * @author Veeven
 1116+ */
 1117+$messages['te'] = array(
 1118+ 'ct-event-name' => 'ఘటన పేరు',
 1119+ 'ct-total-header' => 'మొత్తం నొక్కులు',
 1120+ 'ct-start-date' => 'ప్రారంభ తేదీ (YYYYMMDD)',
 1121+ 'ct-end-date' => 'ముగింపు తేదీ (YYYYMMDD)',
 1122+ 'ct-editing' => 'ప్రస్తుతం మారుస్తున్నారు:',
 1123+ 'ct-anon-users' => 'అజ్ఞాత వాడుకరులు',
 1124+ 'ct-and' => 'మరియు',
 1125+);
 1126+
 1127+/** Turkish (Türkçe)
 1128+ * @author Joseph
 1129+ */
 1130+$messages['tr'] = array(
 1131+ 'clicktracking' => 'Kullanılabilirlik Girişimi tıklama izleme',
 1132+ 'clicktracking-desc' => 'Tıklama izleme, bir sayfa yenilemesine sebep olmadan olayları izleme amaçlı',
 1133+ 'ct-title' => 'Kümeli kullanıcı tıklamaları',
 1134+ 'ct-event-name' => 'Olay adı',
 1135+ 'ct-expert-header' => '"Deneyimli" tıklamaları',
 1136+ 'ct-intermediate-header' => '"Orta düzeyde" tıklamaları',
 1137+ 'ct-beginner-header' => '"Acemi" tıklamaları',
 1138+ 'ct-total-header' => 'Toplam tıklama',
 1139+ 'ct-start-date' => 'Başlangıç Tarihi (YYYYAAGG)',
 1140+ 'ct-end-date' => 'Bitiş tarihi (YYYYAAGG)',
 1141+ 'ct-increment-by' => 'Her veri noktasının temsil ettiği gün sayısı',
 1142+ 'ct-change-graph' => 'Grafiği değiştir',
 1143+ 'ct-beginner' => 'Acemi',
 1144+ 'ct-intermediate' => 'Orta düzeyde',
 1145+ 'ct-expert' => 'Deneyimli',
 1146+ 'ct-date-range' => 'Tarih aralığı',
 1147+ 'ct-editing' => 'Şuanda değiştiriyor:',
 1148+ 'ct-anon-users' => 'Anonim kullanıcılar',
 1149+ 'ct-user-contribs' => 'Toplam kullanıcı katkıları',
 1150+ 'ct-user-span' => 'Zaman içerisindeki kullanıcı katkıları',
 1151+ 'ct-and' => 've',
 1152+ 'ct-update-table' => 'Tabloyu güncelle',
 1153+);
 1154+
 1155+/** Vèneto (Vèneto)
 1156+ * @author Candalua
 1157+ */
 1158+$messages['vec'] = array(
 1159+ 'clicktracking' => "Traciamento click de l'Inissiativa par l'Usabilità",
 1160+ 'clicktracking-desc' => 'Traciamento dei click, par traciare i eventi che no provoca mia un refresh de la pagina.',
 1161+ 'ct-title' => 'Clic dei utenti messi insieme',
 1162+ 'ct-event-name' => "Nome de l'evento",
 1163+ 'ct-expert-header' => 'Clic de "esperti"',
 1164+ 'ct-intermediate-header' => 'Clic de "intermedi"',
 1165+ 'ct-beginner-header' => 'Clic de "prinsipianti"',
 1166+ 'ct-total-header' => 'Clic totali',
 1167+ 'ct-start-date' => 'Data de inissio (AAAAMMGG)',
 1168+ 'ct-end-date' => 'Data de fine(AAAAMMGG)',
 1169+ 'ct-increment-by' => 'Nùmaro de zorni che ogni ponto el rapresenta',
 1170+ 'ct-change-graph' => 'Canbiar el gràfico',
 1171+ 'ct-beginner' => 'Prinsipiante',
 1172+ 'ct-intermediate' => 'Intermedio',
 1173+ 'ct-expert' => 'Esperto',
 1174+ 'ct-date-range' => 'Interval de date',
 1175+ 'ct-editing' => 'En corso de modìfega:',
 1176+ 'ct-anon-users' => 'Utenti anonimi',
 1177+ 'ct-user-contribs' => 'Contributi utente totali',
 1178+ 'ct-user-span' => "Contributi de l'utente su la durata",
 1179+ 'ct-and' => 'e',
 1180+ 'ct-update-table' => 'Ajorna tabèla',
 1181+);
 1182+
 1183+/** Veps (Vepsan kel')
 1184+ * @author Игорь Бродский
 1185+ */
 1186+$messages['vep'] = array(
 1187+ 'ct-beginner' => 'Augotai',
 1188+ 'ct-expert' => 'Ekspert',
 1189+);
 1190+
 1191+/** Vietnamese (Tiếng Việt)
 1192+ * @author Minh Nguyen
 1193+ * @author Vinhtantran
 1194+ */
 1195+$messages['vi'] = array(
 1196+ 'clicktracking' => 'Theo dõi nhấn chuột Sáng kiến Khả dụng',
 1197+ 'clicktracking-desc' => 'Theo dõi hành vi nhấn chuột, dùng để theo dõi các hoạt động không làm tươi trang',
 1198+ 'ct-title' => 'Các lần nhấn chuột tập hợp lại',
 1199+ 'ct-event-name' => 'Tên sự kiện',
 1200+ 'ct-expert-header' => 'Cú nhấn "chuyên gia"',
 1201+ 'ct-intermediate-header' => 'Cú nhấn "trung bình"',
 1202+ 'ct-beginner-header' => 'Cú nhấn "người mới"',
 1203+ 'ct-total-header' => 'Tổng số lần nhấn',
 1204+ 'ct-start-date' => 'Ngày bắt đầu (YYYYMMDD)',
 1205+ 'ct-end-date' => 'Ngày kết thúc (YYYYMMDD)',
 1206+ 'ct-increment-by' => 'Số ngày mà mỗi điểm dữ liệu thể hiện',
 1207+ 'ct-change-graph' => 'Đồ thị thay đổi',
 1208+ 'ct-beginner' => 'Người mới',
 1209+ 'ct-intermediate' => 'Trung bình',
 1210+ 'ct-expert' => 'Chuyên gia',
 1211+ 'ct-date-range' => 'Dãy ngày',
 1212+ 'ct-editing' => 'Đang sửa đổi:',
 1213+ 'ct-anon-users' => 'Người dùng vô danh',
 1214+ 'ct-user-contribs' => 'Tổng số lần đóng góp',
 1215+ 'ct-user-span' => 'Số lần đóng góp trong thời gian',
 1216+ 'ct-and' => 'và',
 1217+ 'ct-update-table' => 'Cập nhật bảng',
 1218+);
 1219+
 1220+/** Yue (粵語)
 1221+ * @author Shinjiman
 1222+ */
 1223+$messages['yue'] = array(
 1224+ 'clicktracking' => '可用性倡議撳追蹤',
 1225+ 'clicktracking-desc' => '撳追蹤,響唔使重載版嘅情況之下追蹤撳',
 1226+);
 1227+
 1228+/** Simplified Chinese (‪中文(简体)‬)
 1229+ * @author Shinjiman
 1230+ */
 1231+$messages['zh-hans'] = array(
 1232+ 'clicktracking' => '可用性倡议点击追踪',
 1233+ 'clicktracking-desc' => '点击追踪,不在重载页面的情况中用来追踪点击',
 1234+);
 1235+
 1236+/** Traditional Chinese (‪中文(繁體)‬)
 1237+ * @author Shinjiman
 1238+ */
 1239+$messages['zh-hant'] = array(
 1240+ 'clicktracking' => '可用性倡議點擊追蹤',
 1241+ 'clicktracking-desc' => '點擊追蹤,不在重載頁面的情況中用來追蹤點擊',
 1242+);
 1243+
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.i18n.php
___________________________________________________________________
Name: svn:eol-style
11244 + native
Index: branches/usability/acaifix/ClickTracking/ClickTracking.php
@@ -0,0 +1,69 @@
 2+<?php
 3+/**
 4+ * Usability Initiative Click Tracking extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ *
 9+ * This file contains the include file for the Click Tracking portion of the
 10+ * UsabilityInitiative extension of MediaWiki.
 11+ *
 12+ * Usage: Include the following line in your LocalSettings.php
 13+ * require_once( "$IP/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php" );
 14+ *
 15+ * @author Nimish Gautam <ngautam@wikimedia.org>
 16+ * @license GPL v2 or later
 17+ * @version 0.1.1
 18+ */
 19+
 20+/* Configuration */
 21+
 22+// Increment this value when you change ClickTracking.js
 23+$wgClickTrackingStyleVersion = 2;
 24+
 25+// click throttle, should be seen as "1 out of every $wgClickTrackThrottle users will have it enabled"
 26+// setting this to 1 means all users will have it enabled
 27+// setting to a negative number will disable it for all users
 28+$wgClickTrackThrottle = -1;
 29+
 30+// set the time window for what we consider 'recent' contributions, in days
 31+$wgClickTrackContribGranularity1 = 60 * 60 * 24 * 365 / 2; // half a year
 32+$wgClickTrackContribGranularity2 = 60 * 60 * 24 * 365 / 4; // 1/4 a year (3 months approx)
 33+$wgClickTrackContribGranularity3 = 60 * 60 * 24 * 30; //30 days (1 month approx)
 34+
 35+// Credits
 36+$wgExtensionCredits['other'][] = array(
 37+ 'path' => __FILE__,
 38+ 'name' => 'Click Tracking',
 39+ 'author' => 'Nimish Gautam',
 40+ 'version' => '0.1.1',
 41+ 'descriptionmsg' => 'clicktracking-desc',
 42+ 'url' => 'http://www.mediawiki.org/wiki/Extension:UsabilityInitiative'
 43+);
 44+
 45+// Includes parent extension
 46+require_once( dirname( dirname( __FILE__ ) ) . "/UsabilityInitiative.php" );
 47+
 48+// Adds Autoload Classes
 49+$dir = dirname( __FILE__ ) . '/';
 50+$wgAutoloadClasses['ClickTrackingHooks'] = $dir . 'ClickTracking.hooks.php';
 51+$wgAutoloadClasses['ApiClickTracking'] = $dir . 'ApiClickTracking.php';
 52+$wgAutoloadClasses['SpecialClickTracking'] = $dir . 'SpecialClickTracking.php';
 53+$wgAutoloadClasses['ApiSpecialClickTracking'] = $dir .'ApiSpecialClickTracking.php';
 54+
 55+// Hooked functions
 56+$wgHooks['LoadExtensionSchemaUpdates'][] = 'ClickTrackingHooks::schema';
 57+$wgHooks['AjaxAddScript'][] = 'ClickTrackingHooks::addJS';
 58+$wgHooks['ParserTestTables'][] = 'ClickTrackingHooks::parserTestTables';
 59+
 60+// Set up the new API module
 61+$wgAPIModules['clicktracking'] = 'ApiClickTracking';
 62+$wgAPIModules['specialclicktracking'] = 'ApiSpecialClickTracking';
 63+
 64+//Special page setup
 65+$wgSpecialPages['ClickTracking'] = 'SpecialClickTracking';
 66+$wgGroupPermissions['sysop']['clicktrack'] = true;
 67+
 68+// Adds Internationalized Messages
 69+$wgExtensionMessagesFiles['ClickTracking'] = $dir . 'ClickTracking.i18n.php';
 70+$wgExtensionAliasesFiles['ClickTracking'] = $dir . 'ClickTracking.alias.php';
\ No newline at end of file
Property changes on: branches/usability/acaifix/ClickTracking/ClickTracking.php
___________________________________________________________________
Name: svn:eol-style
171 + native

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r58205babaco support, Removed some unused code, refactored for MySQL 4.0, created m...nimishg17:42, 27 October 2009
r58224more reasonable defaultsnimishg21:23, 27 October 2009

Status & tagging log