r86964 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86963‎ | r86964 | r86965 >
Date:18:29, 26 April 2011
Author:nimishg
Status:ok
Tags:
Comment:
various clicktracking bugfixes and augments from trunk
Modified paths:
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/ApiClickTracking.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.hooks.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.i18n.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/modules/ext.UserBuckets.js (added) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/modules/jquery.clickTracking.js (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/modules/sampleCampaign.js (added) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/patches/ClickTracking.sql (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/ClickTracking/patches/ClickTrackingUserProperties.sql (added) (history)

Diff [purge]

Index: branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.hooks.php
@@ -21,6 +21,7 @@
2222 global $wgExtNewTables, $wgExtNewIndexes, $wgExtNewFields;
2323 $wgExtNewTables[] = array( 'click_tracking', $dir . 'patches/ClickTracking.sql' );
2424 $wgExtNewTables[] = array( 'click_tracking_events', $dir . 'patches/ClickTrackingEvents.sql' );
 25+ $wgExtNewTables[] = array( 'click_tracking_user_properties', $dir . 'patches/ClickTrackingUserProperties.sql' );
2526 $wgExtNewIndexes[] = array(
2627 'click_tracking',
2728 'click_tracking_action_time',
@@ -36,6 +37,8 @@
3738 $dir . 'patches/ClickTracking.sql', true ) );
3839 $updater->addExtensionUpdate( array( 'addTable', 'click_tracking_events',
3940 $dir . 'patches/ClickTrackingEvents.sql', true ) );
 41+ $updater->addExtensionUpdate( array( 'addTable', 'click_tracking_user_properties',
 42+ $dir . 'patches/ClickTrackingUserProperties.sql', true ) );
4043 $updater->addExtensionUpdate( array( 'addIndex', 'click_tracking', 'click_tracking_action_time',
4144 $dir . 'patches/patch-action_time.sql', true ) );
4245 $updater->addExtensionUpdate( array( 'addField', 'click_tracking', 'additional_info',
@@ -53,6 +56,7 @@
5457 public static function parserTestTables( &$tables ) {
5558 $tables[] = 'click_tracking';
5659 $tables[] = 'click_tracking_events';
 60+ $tables[] = 'click_tracking_user_properties';
5761 return true;
5862 }
5963
@@ -66,6 +70,7 @@
6771 */
6872 public static function beforePageDisplay( $out, $skin ) {
6973 global $wgClickTrackThrottle;
 74+ $out->addModules( 'ext.UserBuckets' );
7075
7176 if ( $wgClickTrackThrottle >= 0 && rand() % $wgClickTrackThrottle == 0 ) {
7277 $out->addModules( 'ext.clickTracking' );
@@ -86,6 +91,26 @@
8792 return true;
8893 }
8994
 95+
 96+ //adds a bucket-testing campaign to the active campaigns
 97+ public static function addCampaign($localBasePath, $remoteExtPath, $name ){
 98+ global $wgResourceModules;
 99+
 100+ $cusResourceTemplate = array(
 101+ 'localBasePath' => $localBasePath,
 102+ 'remoteExtPath' => $remoteExtPath,
 103+ );
 104+ $wgResourceModules["ext.UserBuckets.$name"] = array(
 105+ 'scripts' => "$name.js",
 106+ 'dependencies' => 'jquery.clickTracking',
 107+ ) + $cusResourceTemplate;
 108+ $wgResourceModules['ext.UserBuckets']['dependencies'] = array_merge(
 109+ ( array ) $wgResourceModules['ext.UserBuckets']['dependencies'],
 110+ array("ext.UserBuckets.$name"));
 111+ }
 112+
 113+
 114+
90115 /**
91116 * Get event ID from name
92117 *
@@ -115,7 +140,36 @@
116141 return $id_num === false ? 0 : $id_num;
117142 }
118143
 144+
 145+
 146+
119147 /**
 148+ * Returns bucket information
 149+ * @return Array array of buckets, or null
 150+ */
 151+ public static function unpackBucketInfo(){
 152+ global $wgRequest;
 153+
 154+ //JSON-encoded because it's simple, can be replaced with any other encoding scheme
 155+ return json_decode($wgRequest->getCookie('userbuckets',""), true);
 156+ }
 157+
 158+ /**
 159+ * Takes in an array of buckets
 160+ * @param unknown_type $buckets
 161+ * @return unknown_type
 162+ */
 163+ public static function packBucketInfo( $buckets ){
 164+ global $wgRequest;
 165+ //Can be another encoding scheme, just needs to match unpackBucketInfo
 166+ $packedBuckets = json_encode( $buckets );
 167+
 168+ //NOTE: $wgRequest->response setCookie sets it with a prefix and httponly by default
 169+ setcookie( 'userbuckets' , $packedBuckets ,
 170+ time() + 60 * 60 * 24 * 365 ); //expire in 1 year
 171+ }
 172+
 173+ /**
120174 * Track particular event
121175 *
122176 * @param $sessionId String: unique session id for this editing sesion
@@ -129,10 +183,13 @@
130184 * (defined by ClickTracking/$wgClickTrackContribGranularity2)
131185 * @param $contribs_in_timespan3 Integer: number of contributions user has made in timespan of granularity 3
132186 * (defined by ClickTracking/$wgClickTrackContribGranularity3)
 187+ * @param $additional String: catch-all for any additional information we want to record about this click
 188+ * @param $relevantBucket String: name/index of the particular bucket we're concerned with for this event
133189 * @return Boolean: true if the event was stored in the DB
134190 */
135191 public static function trackEvent( $sessionId, $isLoggedIn, $namespace, $eventId, $contribs = 0,
136 - $contribs_in_timespan1 = 0, $contribs_in_timespan2 = 0, $contribs_in_timespan3 = 0, $additional = null ) {
 192+ $contribs_in_timespan1 = 0, $contribs_in_timespan2 = 0, $contribs_in_timespan3 = 0, $additional = null, $recordBucketInfo = true ) {
 193+
137194 $dbw = wfGetDB( DB_MASTER );
138195 $dbw->begin();
139196 // Builds insert information
@@ -148,9 +205,33 @@
149206 'event_id' => (int) $eventId,
150207 'additional_info' => ( isset( $additional ) ? (string) $additional : null )
151208 );
 209+ $db_status_buckets = true;
152210 $db_status = $dbw->insert( 'click_tracking', $data, __METHOD__ );
153211 $dbw->commit();
154 - return $db_status;
 212+
 213+ if( $recordBucketInfo && $db_status ){
 214+ $buckets = self::unpackBucketInfo();
 215+ if( $buckets ){
 216+ foreach( $buckets as $bucketName => $bucketValue ){
 217+ $db_current_bucket_insert = $dbw->insert( 'click_tracking_user_properties',
 218+ array(
 219+ 'session_id' => (string) $sessionId,
 220+ 'property_name' => (string) $bucketName,
 221+ 'property_value' => (string) $bucketValue[0],
 222+ 'property_version' => (int) $bucketValue[1]
 223+ ),
 224+ __METHOD__,
 225+ array( 'IGNORE' )
 226+ );
 227+ $db_status_buckets = $db_status_buckets && $db_current_bucket_insert;
 228+ }
 229+ }//ifbuckets
 230+ }//ifrecord
 231+
 232+ $dbw->commit();
 233+ return ($db_status && $db_status_buckets);
 234+
 235+
155236 }
156237
157238 public static function editPageShowEditFormFields( $editPage, $output ) {
@@ -159,36 +240,40 @@
160241 // Add clicktracking fields to form, if given
161242 $session = $wgRequest->getVal( 'clicktrackingsession' );
162243 $event = $wgRequest->getVal( 'clicktrackingevent' );
 244+ $info = $wgRequest->getVal( 'clicktrackinginfo' );
163245 if ( $session !== null && $event !== null ) {
164246 $editPage->editFormTextAfterContent .= Html::hidden( 'clicktrackingsession', $session );
165247 $editPage->editFormTextAfterContent .= Html::hidden( 'clicktrackingevent', $event );
 248+ $editPage->editFormTextAfterContent .= Html::hidden( 'clicktrackinginfo', $info );
166249 }
167250
168251 return true;
169252 }
170253
171254 public static function articleSave( $editpage ) {
172 - self::trackRequest( 'save-attempt' );
 255+ self::trackRequest( '-save-attempt' );
173256 return true;
174257 }
175258
176259 public static function articleSaveComplete( $article, $user, $text, $summary, $minoredit,
177260 $watchthis, $sectionanchor, $flags, $revision, $baseRevId ) {
178 - self::trackRequest( 'save-complete' );
 261+ self::trackRequest( '-save-complete' );
179262 return true;
180263 }
181264
182 - protected static function trackRequest( $info ) {
183 - global $wgRequest;
 265+ protected static function trackRequest( $suffix ) {
 266+ global $wgRequest, $wgTitle;
184267
185268 $session = $wgRequest->getVal( 'clicktrackingsession' );
186269 $event = $wgRequest->getVal( 'clicktrackingevent' );
 270+ $info = $wgRequest->getVal( 'clicktrackinginfo' );
187271 if ( $session !== null && $event !== null ) {
188272 $params = new FauxRequest( array(
189273 'action' => 'clicktracking',
190 - 'eventid' => $event,
 274+ 'eventid' => $event . $suffix,
191275 'token' => $session,
192 - 'additional' => $info,
 276+ 'info' => $info,
 277+ 'namespacenumber' => $wgTitle->getNamespace(),
193278 ) );
194279 $api = new ApiMain( $params, true );
195280 $api->execute();
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/patches/ClickTrackingUserProperties.sql
@@ -0,0 +1,23 @@
 2+--
 3+-- Schema for ClickTrackingUserProperties
 4+--
 5+
 6+CREATE TABLE IF NOT EXISTS /*_*/click_tracking_user_properties (
 7+
 8+ -- session id from clicktracking table
 9+ session_id varbinary(255) NOT NULL,
 10+
 11+ -- property name
 12+ property_name varbinary(255),
 13+
 14+ -- property value
 15+ property_value varbinary(255),
 16+
 17+ -- property version
 18+ property_version INTEGER
 19+
 20+) /*$wgDBTableOptions*/;
 21+
 22+CREATE INDEX /*i*/click_tracking_user_properties_session_idx ON /*_*/click_tracking_user_properties (session_id);
 23+
 24+CREATE UNIQUE INDEX ct_user_prop_id_name_value_version ON /*_*/click_tracking_user_properties(session_id, property_name, property_value, property_version);
\ No newline at end of file
Property changes on: branches/wmf/1.17wmf1/extensions/ClickTracking/patches/ClickTrackingUserProperties.sql
___________________________________________________________________
Added: svn:eol-style
125 + native
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/patches/ClickTracking.sql
@@ -36,3 +36,5 @@
3737 ) /*$wgDBTableOptions*/;
3838
3939 CREATE INDEX /*i*/click_tracking_action_time ON /*_*/click_tracking (action_time);
 40+CREATE INDEX /*i*/click_tracking_event_id ON /*_*/click_tracking (event_id);
 41+CREATE INDEX /*i*/click_tracking_session_id ON /*_*/click_tracking (session_id);
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/ApiClickTracking.php
@@ -25,7 +25,8 @@
2626 $this->validateParams( $params );
2727 $eventid_to_lookup = $params['eventid'];
2828 $sessionId = $params['token'];
29 -
 29+ $namespace = $params['namespacenumber'];
 30+
3031 $additional = null;
3132
3233 if ( isset( $params['additional'] ) && strlen( $params['additional'] ) > 0 ) {
@@ -50,7 +51,7 @@
5152 ClickTrackingHooks::trackEvent(
5253 $sessionId, // randomly generated session ID
5354 $isLoggedIn, // is the user logged in?
54 - $wgTitle->getNamespace(), // what namespace are they editing?
 55+ (int)$namespace, // what namespace are they editing?
5556 $eventId, // event ID passed in
5657 ( $isLoggedIn ? $wgUser->getEditCount() : 0 ), // total edit count or 0 if anonymous
5758 $granularity1, // contributions made in granularity 1 time frame
@@ -85,7 +86,7 @@
8687 * @param $params params extracted from the POST
8788 */
8889 protected function validateParams( $params ) {
89 - $required = array( 'eventid', 'token' );
 90+ $required = array( 'eventid', 'token', 'namespacenumber' );
9091 foreach ( $required as $arg ) {
9192 if ( !isset( $params[$arg] ) ) {
9293 $this->dieUsageMsg( array( 'missingparam', $arg ) );
@@ -97,6 +98,7 @@
9899 return array(
99100 'eventid' => 'string of eventID',
100101 'token' => 'unique edit ID for this edit session',
 102+ 'namespacenumber' => 'the namespace number being edited',
101103 'redirectto' => 'URL to redirect to (only used for links that go off the page)',
102104 'additional' => 'additional info for the event, like state information'
103105 );
@@ -112,12 +114,14 @@
113115 return array_merge( parent::getPossibleErrors(), array(
114116 array( 'missingparam', 'eventid' ),
115117 array( 'missingparam', 'token' ),
 118+ array( 'missingparam', 'namespacenumber'),
116119 ) );
117120 }
118121
119122 public function getAllowedParams() {
120123 return array(
121124 'eventid' => null,
 125+ 'namespacenumber' => null,
122126 'token' => null,
123127 'redirectto' => null,
124128 'additional' => null
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/modules/jquery.clickTracking.js
@@ -28,6 +28,7 @@
2929 $.post(
3030 mediaWiki.config.get( 'wgScriptPath' ) + '/api.php', {
3131 'action': 'clicktracking',
 32+ 'namespacenumber': mediaWiki.config.get( 'wgNamespaceNumber' ),
3233 'eventid': id,
3334 'token': $.cookie( 'clicktracking-session' )
3435 }
@@ -44,6 +45,7 @@
4546 mediaWiki.config.get( 'wgScriptPath' ) + '/api.php', {
4647 'action': 'clicktracking',
4748 'eventid': id,
 49+ 'namespacenumber': mediaWiki.config.get( 'wgNamespaceNumber' ),
4850 'token': $.cookie( 'clicktracking-session' ),
4951 'additional': info
5052 }
@@ -60,6 +62,7 @@
6163 return mediaWiki.config.get( 'wgScriptPath' ) + '/api.php?' + $.param( {
6264 'action': 'clicktracking',
6365 'eventid': id,
 66+ 'namespacenumber': mediaWiki.config.get( 'wgNamespaceNumber' ),
6467 'token': $.cookie( 'clicktracking-session' ),
6568 'redirectto': url
6669 } );
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/modules/ext.UserBuckets.js
@@ -0,0 +1,107 @@
 2+
 3+var JSON;
 4+if (!JSON) {
 5+ JSON = {};
 6+
 7+ if(!JSON.stringify){
 8+ /* Very limited JSON encoder */
 9+ JSON.stringify = function( js_obj ) {
 10+ var returnstr = "{ ";
 11+
 12+ // trailing commas and json don't mix
 13+ var propertynum = 0;
 14+ for ( property in js_obj ) {
 15+ if ( propertynum > 0 ) {
 16+ returnstr += ", ";
 17+ }
 18+ returnstr += "\"" + property + "\"" + " : ";
 19+ if ( typeof js_obj[property] == 'object' ) {
 20+ returnstr += JSON.stringify( js_obj[property] );
 21+ } else {
 22+ returnstr += "\"" + js_obj[property] + "\" ";
 23+ }
 24+ propertynum++;
 25+ }
 26+
 27+ returnstr += " }";
 28+ return returnstr;
 29+ };
 30+ }
 31+}
 32+
 33+( function( $ ) {
 34+//lazy-load
 35+$.getBuckets = function (force){
 36+ if (typeof($j.userBuckets) == 'undefined' || force ){
 37+ $j.userBuckets = $.parseJSON( $.cookie('userbuckets') );
 38+ }
 39+ return $j.userBuckets;
 40+};
 41+
 42+$.setBucket = function ( bucketName, bucketValue, bucketVersion ){
 43+ var bucketCookies = $.getBuckets();
 44+ if(!bucketCookies) { bucketCookies ={};}
 45+ bucketCookies[ bucketName ] = [ bucketValue, bucketVersion ];
 46+ $j.cookie('userbuckets', JSON.stringify( bucketCookies ) , { expires: 365 }); //expires in 1 year
 47+ bucketCookies = $.getBuckets(true); //force it to rerun and update
 48+};
 49+
 50+$.setupActiveBuckets = function(){
 51+ var buckets = $.getBuckets();
 52+ for(iter in MW.activeCampaigns){
 53+ var campaign = MW.activeCampaigns[iter];
 54+ // if bucket has been set, or bucket version is out of date,
 55+ // set up a user bucket
 56+ if(campaign.all){
 57+ campaign.all();
 58+ }
 59+
 60+ if(campaign.preferences && !campaign.preferences.setBuckets){
 61+ continue;
 62+ }
 63+
 64+ if(!buckets || !buckets[campaign.name] || buckets[campaign.name][1] < campaign.version){
 65+ //add up all rates
 66+ var bucketTotal = 0;
 67+ for ( var rate in campaign.rates ){
 68+ bucketTotal += campaign.rates[rate];
 69+ }
 70+
 71+ //give the user a random number in those rates
 72+ var currentUser = Math.floor(Math.random() * (bucketTotal+1));
 73+
 74+ // recurse through the rates until we get into the range the user falls in,
 75+ // assign them to that range
 76+ var prev_val = -1;
 77+ var next_val = 0;
 78+ for( rate in campaign.rates ){
 79+ next_val += campaign.rates[rate];
 80+ if(prev_val <= currentUser && currentUser < next_val){
 81+ $.setBucket(campaign.name, rate, campaign.version);
 82+ break;
 83+ }
 84+ prev_val = next_val;
 85+ }
 86+ }
 87+
 88+ // do the actual code in the campaign based on the bucket
 89+ if($.getBuckets() && $.getBuckets()[campaign.name] && $.getBuckets()[campaign.name][0] != "none"){
 90+ if(typeof(campaign[$.getBuckets()[campaign.name][0]]) == "function"){
 91+ campaign[$.getBuckets()[campaign.name][0]](); //function to execute
 92+ }
 93+ if(campaign.allActive){
 94+ campaign.allActive();
 95+ }
 96+ }
 97+
 98+ }
 99+
 100+};
 101+
 102+//no need to do any of this if there are no active campaigns
 103+if( (typeof(MW) != "undefined") && MW.activeCampaigns){
 104+ $j( document ).ready( jQuery.setupActiveBuckets );
 105+}
 106+
 107+
 108+} )( jQuery );
Property changes on: branches/wmf/1.17wmf1/extensions/ClickTracking/modules/ext.UserBuckets.js
___________________________________________________________________
Added: svn:eol-style
1109 + native
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/modules/sampleCampaign.js
@@ -0,0 +1,53 @@
 2+
 3+//checks
 4+if(typeof(MW) == "undefined"){ MW={};}
 5+if(!MW.activeCampaigns){ MW.activeCampaigns ={}; }
 6+
 7+//define new active campaign
 8+MW.activeCampaigns.ArticleSave =
 9+
 10+{
 11+ //Treatment name
 12+ "name": "ArticleSave",
 13+
 14+ //Treatment version. Increment this when altering rates
 15+ "version": 2,
 16+
 17+ // Rates are calculated out of the total sum, so
 18+ // rates of x:10000, y:3, and z:1 mean users have a
 19+ // chance of being in bucket x at 10000/10004,
 20+ // y at 3/10004 and z at 1/10004
 21+ // The algorithm is faster if these are ordered in descending order,
 22+ // particularly if there are orders of magnitude differences in the
 23+ // bucket sizes
 24+ // "none" is reserved for control
 25+ "rates": {"none": 10000, "Bold": 3, "Italics": 1 },
 26+
 27+ // individual changes, function names corresponding
 28+ // to what is in "rates" object
 29+ // (note: "none" function not needed or used)
 30+
 31+ "Bold": function(){
 32+ //change edit button to bold
 33+ $j("#wpSave").css("font-weight", "bolder");
 34+
 35+ },
 36+ "Italics": function(){
 37+ //change edit button to italics
 38+ $j("#wpSave").css("font-weight", "normal")
 39+ .css("font-style", "italic");
 40+
 41+ },
 42+
 43+ // "allActive" is reserved.
 44+ // If this function exists, it will be apply to every user not in the "none" bucket
 45+ "allActive": function(){
 46+ //add click tracking to save
 47+ $j("#wpSave").click(function(){ $j.trackAction('save'); });
 48+ //add click tracking to preview
 49+ $j("#wpPreview").click(function(){ $j.trackAction('preview'); });
 50+ $j("#editpage-copywarn").click(function(){ $j.trackAction('copywarn'); });
 51+
 52+ }
 53+
 54+};
\ No newline at end of file
Property changes on: branches/wmf/1.17wmf1/extensions/ClickTracking/modules/sampleCampaign.js
___________________________________________________________________
Added: svn:eol-style
155 + native
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.i18n.php
@@ -60,6 +60,14 @@
6161 'ct-and' => '{{Identical|And}}',
6262 );
6363
 64+/** کھوار (کھوار)
 65+ * @author Rachitrali
 66+ */
 67+$messages['khw'] = array(
 68+ 'ct-beginner' => 'شروع کوراک',
 69+ 'ct-and' => 'وا',
 70+);
 71+
6472 /** Afrikaans (Afrikaans)
6573 * @author Adriaan
6674 * @author Naudefj
@@ -184,7 +192,7 @@
185193 'ct-update-table' => 'حدّث الجدول',
186194 );
187195
188 -/** Bashkir (Башҡорт)
 196+/** Bashkir (Башҡортса)
189197 * @author Assele
190198 */
191199 $messages['ba'] = array(
@@ -212,7 +220,7 @@
213221 'ct-update-table' => 'Таблицаны яңыртырға',
214222 );
215223
216 -/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца))
 224+/** Belarusian (Taraškievica orthography) (‪Беларуская (тарашкевіца)‬)
217225 * @author EugeneZelenko
218226 * @author Jim-by
219227 * @author Red Winged Duck
@@ -1258,14 +1266,29 @@
12591267 );
12601268
12611269 /** Khmer (ភាសាខ្មែរ)
 1270+ * @author គីមស៊្រុន
12621271 * @author វ័ណថារិទ្ធ
12631272 */
12641273 $messages['km'] = array(
12651274 'ct-event-name' => 'ឈ្មោះព្រឹត្តិការណ៍​',
 1275+ 'ct-expert-header' => 'ចំនួនការចុចរបស់ «អ្នកជំនាញ»',
 1276+ 'ct-intermediate-header' => 'ចំនួនការចុចរបស់ «អ្នកមធ្យម»',
 1277+ 'ct-beginner-header' => 'ចំនួនការចុចរបស់ «អ្នកដំបូង»',
12661278 'ct-total-header' => 'ចំនួនចុចសរុប​',
12671279 'ct-start-date' => 'កាលបរិច្ឆេទ​ចាប់ផ្ដើម (YYYYMMDD)',
12681280 'ct-end-date' => 'កាលបរិច្ឆេទ​បញ្ចប់ (YYYYMMDD)',
 1281+ 'ct-increment-by' => 'ចំនួនថ្ងៃដែលចំនុចទិន្នន័យនីមួយៗតំណាងអោយ',
 1282+ 'ct-change-graph' => 'ផ្លាស់ប្ដូរក្រាហ្វ',
 1283+ 'ct-beginner' => 'អ្នកដំបូង',
 1284+ 'ct-intermediate' => 'អ្នកមធ្យម',
 1285+ 'ct-expert' => 'អ្នកជំនាញ',
 1286+ 'ct-date-range' => 'ដែនកំណត់កាលបរិច្ឆេទ',
 1287+ 'ct-editing' => 'បច្ចុប្បន្នកំពុង​កែប្រែ៖',
 1288+ 'ct-anon-users' => 'អ្នកប្រើប្រាស់អនាមិក',
 1289+ 'ct-user-contribs' => 'ការរួមចំណែកសរុបរបស់អ្នកប្រើប្រាស់',
 1290+ 'ct-user-span' => 'ការរួមចំណែករបស់អ្នកប្រើប្រាស់ក្នុងរយៈកាលមួយ',
12691291 'ct-and' => 'និង​',
 1292+ 'ct-update-table' => 'អាប់ដេតតារាង',
12701293 );
12711294
12721295 /** Kannada (ಕನ್ನಡ)
@@ -1360,6 +1383,13 @@
13611384 'ct-update-table' => 'De Tabäll op der neuste Schtand bränge',
13621385 );
13631386
 1387+/** Kurdish (Latin) (Kurdî (Latin))
 1388+ * @author George Animal
 1389+ */
 1390+$messages['ku-latn'] = array(
 1391+ 'ct-and' => 'û',
 1392+);
 1393+
13641394 /** Luxembourgish (Lëtzebuergesch)
13651395 * @author Robby
13661396 */
@@ -1462,14 +1492,14 @@
14631493 * @author Bjankuloski06
14641494 */
14651495 $messages['mk'] = array(
1466 - 'clicktracking' => 'Следење на кликнувања на Иницијативата за употребливост',
1467 - 'clicktracking-desc' => 'Следење на кликнувања, наменето за следење на постапки кои не предизвикуваат превчитување на страницата',
 1496+ 'clicktracking' => 'Следење на стискања на Иницијативата за употребливост',
 1497+ 'clicktracking-desc' => 'Следење на стискања, наменето за следење на постапки кои не предизвикуваат превчитување на страницата',
14681498 'ct-title' => 'Насобрани кориснички кликови',
14691499 'ct-event-name' => 'Име на настанот',
1470 - 'ct-expert-header' => '„Експертски“ кликови',
1471 - 'ct-intermediate-header' => '„Средно-учеснички“ кликови',
1472 - 'ct-beginner-header' => '„Почетнички“ кликови',
1473 - 'ct-total-header' => 'Вкупно кликови',
 1500+ 'ct-expert-header' => 'Стискања на „експерти“',
 1501+ 'ct-intermediate-header' => 'Стискања на „средни корисници“',
 1502+ 'ct-beginner-header' => 'Стискања на „почетници“',
 1503+ 'ct-total-header' => 'Вкупно стискања',
14741504 'ct-start-date' => 'Почетен датум (ГГГГММДД)',
14751505 'ct-end-date' => 'Завршен датум (ГГГГММДД)',
14761506 'ct-increment-by' => 'Број на денови што ги претставува секоја податочна точка',
@@ -1483,7 +1513,7 @@
14841514 'ct-user-contribs' => 'Вкупно кориснички придонеси',
14851515 'ct-user-span' => 'Ккориснички придонеси за период',
14861516 'ct-and' => 'и',
1487 - 'ct-update-table' => 'Ажурирај ја таблицата',
 1517+ 'ct-update-table' => 'Поднови ја табелата',
14881518 );
14891519
14901520 /** Malayalam (മലയാളം)
@@ -1602,9 +1632,10 @@
16031633
16041634 /** Nahuatl (Nāhuatl)
16051635 * @author Ricardo gs
 1636+ * @author Teòtlalili
16061637 */
16071638 $messages['nah'] = array(
1608 - 'ct-and' => 'īhuān',
 1639+ 'ct-and' => 'wàn',
16091640 );
16101641
16111642 /** Nedersaksisch (Nedersaksisch)
@@ -1615,6 +1646,14 @@
16161647 'ct-expert-header' => '"Expert"-kliks',
16171648 );
16181649
 1650+/** Nepali (नेपाली)
 1651+ * @author Bhawani Gautam Rhk
 1652+ */
 1653+$messages['ne'] = array(
 1654+ 'ct-and' => 'अनि',
 1655+ 'ct-update-table' => 'तालिका अद्यतन गर्ने',
 1656+);
 1657+
16191658 /** Dutch (Nederlands)
16201659 * @author Siebrand
16211660 */
@@ -1733,6 +1772,7 @@
17341773 * @author Xqt
17351774 */
17361775 $messages['pdc'] = array(
 1776+ 'ct-beginner' => 'Aafaenger',
17371777 'ct-and' => 'unn',
17381778 );
17391779
@@ -2146,7 +2186,7 @@
21472187 'ct-update-table' => 'Posodobi tabelo',
21482188 );
21492189
2150 -/** Serbian Cyrillic ekavian (Српски (ћирилица))
 2190+/** Serbian Cyrillic ekavian (‪Српски (ћирилица)‬)
21512191 * @author Rancher
21522192 * @author Михајло Анђелковић
21532193 */
@@ -2161,16 +2201,16 @@
21622202 'ct-change-graph' => 'Промени графикон',
21632203 'ct-beginner' => 'Почетник',
21642204 'ct-intermediate' => 'Напредни',
2165 - 'ct-expert' => 'Експерт',
 2205+ 'ct-expert' => 'Стручњак',
21662206 'ct-date-range' => 'Опсег датума',
21672207 'ct-editing' => 'Тренутно мења:',
21682208 'ct-anon-users' => 'Анонимни корисници',
2169 - 'ct-user-contribs' => 'Укупно корисничких доприноса',
 2209+ 'ct-user-contribs' => 'Укупно прилога',
21702210 'ct-and' => 'и',
21712211 'ct-update-table' => 'Ажурирај табелу',
21722212 );
21732213
2174 -/** Serbian Latin ekavian (Srpski (latinica)) */
 2214+/** Serbian Latin ekavian (‪Srpski (latinica)‬) */
21752215 $messages['sr-el'] = array(
21762216 'ct-expert-header' => 'Klikovi "eksperata"',
21772217 'ct-intermediate-header' => 'Klikovi "naprednih"',
@@ -2559,6 +2599,7 @@
25602600 /** Cantonese (粵語)
25612601 * @author Horacewai2
25622602 * @author Shinjiman
 2603+ * @author Waihorace
25632604 */
25642605 $messages['yue'] = array(
25652606 'clicktracking' => '可用性倡議撳追蹤',
@@ -2641,7 +2682,7 @@
26422683 'ct-anon-users' => '匿名用戶',
26432684 'ct-user-contribs' => '用戶貢獻合計',
26442685 'ct-user-span' => '時間範圍內的用戶貢獻',
2645 - 'ct-and' => '和',
 2686+ 'ct-and' => '&#32;和&#32;',
26462687 'ct-update-table' => '更新表格',
26472688 );
26482689
Index: branches/wmf/1.17wmf1/extensions/ClickTracking/ClickTracking.php
@@ -87,4 +87,11 @@
8888 'styles' => 'ext.clickTracking.special.css',
8989 'dependencies' => array( 'jquery.ui.datepicker', 'jquery.ui.dialog' ),
9090 ) + $ctResourceTemplate;
 91+$wgResourceModules['ext.UserBuckets'] = array(
 92+ 'scripts' => 'ext.UserBuckets.js',
 93+ 'dependencies' => array('jquery.clickTracking', 'jquery.cookie'),
 94+) + $ctResourceTemplate;
9195
 96+//uncomment for sample campaign
 97+//ClickTrackingHooks::addCampaign($dir. 'modules', 'ClickTracking/modules', 'sampleCampaign' );
 98+

Status & tagging log