resources/jquery/jquery.hoverIntent.js
resources/jquery/jquery.js
resources/jquery/jquery.json.js
+resources/jquery/jquery.jStorage.js
resources/jquery/jquery.mockjax.js
resources/jquery/jquery.qunit.js
resources/jquery/jquery.validate.js
* (bug 39376) jquery.form upgraded to 3.14
* SVG files will now show the actual width in the SVG's specified units
in the metadata box.
+* Added ResourceLoader module "jquery.jStorage".
=== Bug fixes in 1.20 ===
* (bug 30245) Use the correct way to construct a log page title.
// Bail if PHP is too low
if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+ // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require( dirname( __FILE__ ) . '/includes/PHPVersionError.php' );
wfPHPVersionError( 'api.php' );
}
refers to the link source, NOT to the target! You should check the env
variable MW_INSTALL_PATH in case the extension is not in the default location.
-The following code snippet lets you override the default path:
+The following code snippet lets you override the default path:
$IP = getenv( 'MW_INSTALL_PATH' );
if( $IP === false ) {
# Split into three columns
$columns = array_chunk( $columns, ceil( count( $columns ) / 3 ), true /* preserve keys */ );
- $ret = '<table width="100%"><tr valign="top">';
+ $ret = '<table width="100%"><tr style="vertical-align: top;">';
$prevchar = null;
foreach ( $columns as $column ) {
*/
function logoText( $align = '' ) {
if ( $align != '' ) {
- $a = " align='{$align}'";
+ $a = " style='float: {$align};'";
} else {
$a = '';
}
"<table border='0' cellspacing='0' width='100%'>\n<tr>\n";
if ( $this->getSkin()->qbSetting() == 0 ) {
- $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
+ $s .= "<td class='top' style='text-align: left; vertical-align: top;' rowspan='{$rows}'>\n" .
$this->getSkin()->logoText( $wgLang->alignStart() ) . '</td>';
}
$l = $wgLang->alignStart();
- $s .= "<td {$borderhack} align='$l' valign='top'>\n";
+ $s .= "<td {$borderhack} style='text-align: $l; vertical-align: top;'>\n";
$s .= $this->topLinks();
$s .= '<p class="subtitle">' . $this->pageTitleLinks() . "</p>\n";
$r = $wgLang->alignEnd();
- $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
+ $s .= "</td>\n<td {$borderhack} style='text-align: $r; vertical-align: top;' nowrap='nowrap'>";
$s .= $this->nameAndLogin();
$s .= "\n<br />" . $this->searchForm() . '</td>';
if ( !$diff && !$otitle ) {
$header .= "
- <tr valign='top'>
+ <tr style='vertical-align: top;'>
<td class='diff-ntitle'>{$ntitle}</td>
</tr>";
$multiColspan = 1;
$multiColspan = 2;
}
$header .= "
- <tr valign='top'>
+ <tr style='vertical-align: top;'>
<td colspan='$colspan' class='diff-otitle'>{$otitle}</td>
<td colspan='$colspan' class='diff-ntitle'>{$ntitle}</td>
</tr>";
}
if ( $multi != '' ) {
- $header .= "<tr><td colspan='{$multiColspan}' align='center' class='diff-multi'>{$multi}</td></tr>";
+ $header .= "<tr><td colspan='{$multiColspan}' style='text-align: center;' class='diff-multi'>{$multi}</td></tr>";
}
if ( $notice != '' ) {
- $header .= "<tr><td colspan='{$multiColspan}' align='center'>{$notice}</td></tr>";
+ $header .= "<tr><td colspan='{$multiColspan}' style='text-align: center;'>{$notice}</td></tr>";
}
return $header . $diff . "</table>";
* - allowStale : Don't require the latest available data.
* This can increase performance for non-critical writes.
* This has no effect unless the 'force' flag is set.
+ * - preserveCache : Don't clear the process cache before checking files.
+ * This should only be used if all entries in the process
+ * cache were added after the files were already locked.
* - nonJournaled : Don't log this operation batch in the file journal.
* This limits the ability of recovery scripts.
* - parallelize : Try to do operations in parallel when possible.
}
// Clear any cache entries (after locks acquired)
$this->clearCache();
+ $opts['preserveCache'] = true; // only locked files are cached
// Do a consistency check to see if the backends agree
$status->merge( $this->consistencyCheck( $this->fileStoragePathsForOps( $ops ) ) );
if ( !$status->isOK() ) {
}
// Clear any file cache entries (after locks acquired)
- $this->clearCache();
+ if ( empty( $opts['preserveCache'] ) ) {
+ $this->clearCache();
+ }
// Load from the persistent file and container caches
$this->primeFileCache( $performOps );
: false;
$this->swiftCDNExpiry = isset( $config['swiftCDNExpiry'] )
? $config['swiftCDNExpiry']
- : 3600; // hour
+ : 12*3600; // 12 hours is safe (tokens last 24 hours per http://docs.openstack.org)
$this->swiftCDNPurgable = isset( $config['swiftCDNPurgable'] )
? $config['swiftCDNPurgable']
: true;
// See function "create_container_table" in common/db.py.
// If a directory is not "greater" than the last one,
// then it was already listed by the calling iterator.
- if ( $objectDir > $lastDir ) {
+ if ( strcmp( $objectDir, $lastDir ) > 0 ) {
$pDir = $objectDir;
do { // add dir and all its parent dirs
$dirs[] = "{$pDir}/";
$pDir = $this->getParentDir( $pDir );
} while ( $pDir !== false // sanity
- && $pDir > $lastDir // not done already
+ && strcmp( $pDir, $lastDir ) > 0 // not done already
&& strlen( $pDir ) > strlen( $dir ) // within $dir
);
}
if ( $e->getMessage() ) {
trigger_error( "$func: " . $e->getMessage(), E_USER_WARNING );
}
+ if ( $e instanceof InvalidResponseException ) { // possibly a stale token
+ $this->srvCache->delete( $this->getCredsCacheKey( $this->auth->username ) );
+ }
wfDebugLog( 'SwiftBackend',
get_class( $e ) . " in '{$func}' (given '" . FormatJson::encode( $params ) . "')" .
( $e->getMessage() ? ": {$e->getMessage()}" : "" )
* @since 1.20
*/
class DBFileJournal extends FileJournal {
+ /** @var DatabaseBase */
+ protected $dbw;
+
protected $wiki = false; // string; wiki DB name
/**
}
try {
- $dbw->begin();
$dbw->insert( 'filejournal', $data, __METHOD__ );
- $dbw->commit();
} catch ( DBError $e ) {
$status->fatal( 'filejournal-fail-dbquery', $this->backend );
return $status;
$dbw = $this->getMasterDB();
$dbCutoff = $dbw->timestamp( time() - 86400 * $this->ttlDays );
- $dbw->begin();
$dbw->delete( 'filejournal',
array( 'fj_timestamp < ' . $dbw->addQuotes( $dbCutoff ) ),
__METHOD__
);
- $dbw->commit();
return $status;
}
* @throws DBError
*/
protected function getMasterDB() {
- $lb = wfGetLBFactory()->newMainLB();
- return $lb->getConnection( DB_MASTER, array(), $this->wiki );
+ if ( !$this->dbw ) {
+ // Get a separate connection in autocommit mode
+ $lb = wfGetLBFactory()->newMainLB();
+ $this->dbw = $lb->getConnection( DB_MASTER, array(), $this->wiki );
+ $this->dbw->clearFlag( DBO_TRX );
+ }
+ return $this->dbw;
}
}
$dbw = wfGetDB( DB_MASTER );
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
if ( !$affected ) {
// Failed, someone else beat us to it
// Delete the random row
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
$affected = $dbw->affectedRows();
- $dbw->commit( __METHOD__ );
if ( !$affected ) {
// Random job gone before we exclusively deleted it
* @return string
*/
private static function fixBackgroundPosition( $css ) {
- $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage'],
+ $replaced = preg_replace_callback( self::$patterns['bg_horizontal_percentage'],
array( 'self', 'calculateNewBackgroundPosition' ), $css );
- $css = preg_replace_callback( self::$patterns['bg_horizontal_percentage_x'],
+ if ( $replaced !== null ) {
+ // Check for null; sometimes preg_replace_callback() returns null here for some weird reason
+ $css = $replaced;
+ }
+ $replaced = preg_replace_callback( self::$patterns['bg_horizontal_percentage_x'],
array( 'self', 'calculateNewBackgroundPosition' ), $css );
+ if ( $replaced !== null ) {
+ $css = $replaced;
+ }
return $css;
}
return "<li>" .
'<table class="searchResultImage">' .
'<tr>' .
- '<td width="120" align="center" valign="top">' .
+ '<td width="120" style="text-align: center; vertical-align: top;">' .
$thumb->toHtml( array( 'desc-link' => true ) ) .
'</td>' .
- '<td valign="top">' .
+ '<td style="vertical-align: top;">' .
$link .
$extract .
"<div class='mw-search-result-data'>{$score}{$desc} - {$date}{$related}</div>" .
"<col class='diff-marker' />" .
"<col class='diff-content' />" .
"<tr>" .
- "<td colspan='2' width='50%' align='center' class='diff-otitle'>" .
+ "<td colspan='2' width='50%' style='text-align: center' class='diff-otitle'>" .
$this->diffHeader( $previousRev, 'o' ) .
"</td>\n" .
- "<td colspan='2' width='50%' align='center' class='diff-ntitle'>" .
+ "<td colspan='2' width='50%' style='text-align: center' class='diff-ntitle'>" .
$this->diffHeader( $currentRev, 'n' ) .
"</td>\n" .
"</tr>" .
# PHP 4. Setup.php and ObjectCache.php have structures invalid in PHP 5.0 and
# 5.1, respectively.
if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+ // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require( dirname( __FILE__ ) . '/includes/PHPVersionError.php' );
wfPHPVersionError( 'index.php' );
}
'note' => "'''تێبینی:'''",
'previewnote' => "'''لە بیرت نەچێت ئەمە تەنیا پێشبینینە.'''
گۆڕانکارییەکانت ھێشتا پاشەکەوت نەکراون!",
+'continue-editing' => 'بەردەوام بە لەدەستکاریکردن',
'previewconflict' => 'ئەم پێشبینینە بە تۆ نیشان ئەدات ئەو دەقەی لە شوێنی دەستکاری سەرەوە داتناوە چۆن بەرچاو ئەکەوێت ئەگەر پاشەکەوتی بکەیت.',
'session_fail_preview' => "'''ببوورە! ناتوانین دەستکارییەکەت پێواژۆ بکەین بە ھۆی لەدەستدانی session data.'''
تکایە دیسان ھەوڵبدەوە.
**لادان لە مافەکانی بڵاوکردنەوە
***پەڕگەی دووبارەکراوە',
'filedelete-edit-reasonlist' => 'دەستکاری هۆکارەکانی سڕینەوە',
+'filedelete-maintenance-title' => 'ناتوانیت پەڕگە بسڕیتەوە',
# MIME search
'mimesearch' => 'گەڕانی MIME',
ئێستا ڕەوانکەرە بۆ [[$2]].',
'double-redirect-fixer' => 'چارەسەرکەری ڕەوانکەر',
-'brokenredirects' => 'ڕەوانەکراوە شکاوەکان',
+'brokenredirects' => 'ڕەوانەکەرە شکاوەکان',
'brokenredirectstext' => 'ئەم ڕەوانەکراوانە بەستەرن بۆ ئەو پەڕانە کە بوونیان نییە:',
'brokenredirects-edit' => 'دەستکاری',
'brokenredirects-delete' => 'سڕینەوە',
'allpages-bad-ns' => '{{SITENAME}} ناوبۆشایی نیە "$1".',
'allpages-hide-redirects' => 'ڕەوانەکراوەکان بشارەوە',
+# SpecialCachedPage
+'cachedspecial-refresh-now' => 'دواترین پیشانبدە',
+
# Special:Categories
'categories' => 'پۆلەكان',
'categoriespagetext' => 'ئەم {{PLURAL:$1|پۆلە پەڕە یان پەڕگەی|پۆلانە پەڕە یان پەڕگەیان}} لەخۆگرتە.
'protectedarticle' => '«[[$1]]»ی پاراست',
'modifiedarticleprotection' => 'ئاستی پاراستنی «[[$1]]»ی گۆڕا',
'unprotectedarticle' => 'پاراستنی لەسەر «[[$1]]» لابرد',
-'movedarticleprotection' => 'ڕێککارییەکانی پاراستن لە "[[$2]]" گوازرایەوە بۆ "[[$1]]"',
+'movedarticleprotection' => 'ڕێککارییەکانی پاراستن لە «[[$2]]» گوازرایەوە بۆ «[[$1]]»',
'protect-title' => 'گۆڕینی ئاستی پاراستنی "$1"',
'prot_1movedto2' => '[[$1]] گوازرایەوە بۆ [[$2]]',
'protect-legend' => 'پاراستن تەیید بکە',
'movepagebtn' => 'ئەم پەڕەیە بگوازەوە',
'pagemovedsub' => 'گواستنەوە بە سەرکەوتوویی جێبەجێ کرا',
'movepage-moved' => "'''«$1» گوازرایەوە بۆ «$2»'''",
-'movepage-moved-redirect' => 'ڕەوانکەرێک درووستکرا.',
+'movepage-moved-redirect' => 'ڕەوانەکەرێک دروست کرا.',
'movepage-moved-noredirect' => 'لە دانانی ڕەوانەکەر بەرگری کرا.',
'articleexists' => 'پەڕەیەک بەم ناوە ھەیە یان ئەو ناوەی تۆ ھەڵتبژاردووە ڕێگەی پێنەدراوە.
تکایە ناوێکی دیکە ھەڵبژێرە.',
'movedto' => 'گواسترایەوە بۆ',
'movetalk' => 'پەڕەی وتووێژی پەیوەندیدار بگوازەوە',
'move-subpages' => 'ژێرپەڕەکانی بگوازەوە (ھەتا $1 پەڕە)',
-'move-talk-subpages' => 'ژێرپەڕەکانی پەڕەی وتووێژی بگۆزەرەوە (ھەتاکوو $1)',
+'move-talk-subpages' => 'ژێرپەڕەکانی پەڕەی وتووێژ بگوازەوە (ھەتا $1 پەڕە)',
'movepage-page-exists' => 'پەڕەی $1 هەیە و ناتوانرێت خۆکار بخرێتە جێی.',
'movepage-page-moved' => 'پەڕەی $1 گۆزرایەوە بۆ $2.',
'movepage-page-unmoved' => 'ناکرێ پەڕەی $1 بگوێزرێتەوە بۆ $2.',
'movelogpagetext' => 'لە خوارەوەدا لیستی ھەموو پەڕە گواستنەوەکان دەبینن.',
'movesubpage' => '{{PLURAL:$1|ژێرپەڕە|ژێرپەڕە}}',
'movesubpagetext' => 'ئەم لاپەڕە $1 {{PLURAL:$1|ژێرلاپەڕەی|ژێرلاپەڕەی}} هەیە کە لەخوارە نیشان دراوە.',
-'movenosubpage' => 'ئەم پەڕە ھیچ ژێرپەڕەیەکی نییە.',
+'movenosubpage' => 'ئەم پەڕەیە ھیچ ژێرپەڕەیەکی نییە.',
'movereason' => 'ھۆکار:',
'revertmove' => 'پێچەوانەکردنەوە',
'delete_and_move' => 'بیسڕەوە و بیگوازەوە',
# Info page
'pageinfo-title' => 'زانیاری بۆ «$1»',
+'pageinfo-header-basic' => 'زانیاریی سەرەتایی',
'pageinfo-header-edits' => 'دەستکاریەکان',
'pageinfo-views' => 'ژمارەی بینینەکان',
'pageinfo-watchers' => 'ژمارەی چاودێران',
+'pageinfo-firstuser' => 'دروستکەری پەڕە',
'pageinfo-edits' => 'ژمارەی دەستکارییەکان',
# Skin names
'exif-imagelength' => 'بەرزی',
'exif-imagedescription' => 'ناونیشانی وێنە',
'exif-model' => 'جۆری کامێرا',
+'exif-software' => 'نەرمەواڵەی بەکارهاتوو',
'exif-artist' => 'نووسەر',
'exif-colorspace' => 'بۆشایی رهنگ',
+'exif-pixelydimension' => 'پانی وێنە',
+'exif-pixelxdimension' => 'بەرزی وێنە',
'exif-usercomment' => 'بۆچوونەکانی بەکارهێنەر',
'exif-relatedsoundfile' => 'فایلی دهنگی لێکچوو',
'exif-lightsource' => 'سەرچاوەی ڕووناکی',
'exif-gpstrack' => 'ئاڕاستەی جوڵان',
'exif-gpsimgdirection' => 'ئاڕاستەی وێنە',
'exif-gpsdatestamp' => 'ڕێکەوتی GPS',
+'exif-objectname' => 'سەردێری کورت',
+'exif-headline' => 'سەردێر',
+'exif-source' => 'سەرچاوە',
+'exif-copyrighted' => 'ڕەوشی مافی لەبەرگرتنەوە',
# EXIF attributes
'exif-compression-1' => 'نەپەستێنراو',
'exif-gpsspeed-k' => 'کیلۆمەتر هەر کاتژمێر',
'exif-gpsspeed-m' => 'مایل هەر کاتژمێر',
+# Pseudotags used for GPSDestDistanceRef
+'exif-gpsdestdistance-k' => 'کیلۆمەتر',
+'exif-gpsdestdistance-m' => 'میل',
+'exif-gpsdestdistance-n' => 'میکی دەریایی',
+
+'exif-dc-date' => 'ڕۆژ(ەکان)',
+'exif-dc-publisher' => 'بڵاوکار',
+'exif-dc-relation' => 'پەڕگەی پەیوەندیدار',
+'exif-dc-rights' => 'مافەکان',
+'exif-dc-source' => 'سەرچاوەی پەڕگە',
+'exif-dc-type' => 'جۆری پەڕگە',
+
'exif-iimcategory-hth' => 'تەندروستی',
'exif-iimcategory-sci' => 'زانست و تەکنۆلۆژیا',
'exif-iimcategory-soi' => 'بابەتە کۆمەڵایەتییەکان',
'shared-repo' => 'yew embarê repositoryî',
'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
'filepage.css' => '/* CSS placed here is included on the file description page, also included on foreign client wikis */',
+'upload-disallowed-here' => 'Nê asengi sero theba nênusneyêno.',
# File reversion
'filerevert' => '$1 reyna biyere',
'pageinfo-authors' => 'Amarina nuştekaran pêro',
'pageinfo-recent-edits' => 'Amariya vurnayışan ($1 ra nata)',
'pageinfo-recent-authors' => 'Amarina nuştekaran pêro',
-'pageinfo-restriction' => 'Xısusiyetê pela da (<code>$1</code>)',
+'pageinfo-restriction' => 'Xısusiyetê pela (<code>{{lcfirst:$1}}</code>)',
'pageinfo-magic-words' => '{{PLURAL:$1|Çekuya|Çekuyê}} ($1) sihırini',
'pageinfo-hidden-categories' => '{{PLURAL:$1|Kategoriye|Kategoriyan}} ($1) bınımne',
'pageinfo-templates' => '{{PLURAL:$1|Şablon|Şabloni}} ($1) açarneyayê',
'file-info-size-pages' => '$1 × $2 pikse, dergeya dosyay: $3, MIME tipiya cı: $4, $5 {{PLURAL:$5|pela|pela}}',
'file-nohires' => 'Rovıleşiyayışo berzêr çıniyo.',
'svg-long-desc' => 'SVG dosya, nominalin $1 × $2 piksels, ebatê dosya: $3',
+'svg-long-desc-animated' => 'SVG dosya, nominalin $1 × $2 piksela, ebatê dosya: $3',
'show-big-image' => 'Resolosyonê temami',
'show-big-image-preview' => "Verqayd dergiya: $1'i.",
'show-big-image-other' => 'Zewmi{{PLURAL:$2|Vılêşnayış|Vılêşnayışê}}: $1.',
'file-info-png-looped' => 'atlama biyo',
'file-info-png-repeat' => '$1 {{PLURAL:$1|hew|hew}} kay biyê',
'file-info-png-frames' => '$1 {{PLURAL:$1|çerçeve|çerçeveyi}}',
+'file-no-thumb-animation' => "'''Not: Dılet tekniko limit, gırd agozneya resm de qıckek de animasyoni miyan dı nêbo.'''",
+'file-no-thumb-animation-gif' => "'''Not: Dılet tekniko limit, gırd agozneya resm de qıckek de GIF imaci de animasyon do nêbo.'''",
# Special:NewFiles
'newimages' => 'Galeriya dosyayan dê newan',
'otherlanguages' => 'Ann an cànain eile',
'redirectedfrom' => '(Air ath-sheòladh o $1)',
'redirectpagesub' => 'Ath-sheòl an duilleag',
-'lastmodifiedat' => 'Chaidh an duilleag seo a mhùthadh $1, aig $2 turas mu dheireadh.',
+'lastmodifiedat' => 'Chaidh an duilleag seo a mhùthadh $1 aig $2 turas mu dheireadh.',
'viewcount' => 'Chaidh inntrigeadh a dhèanam dhan duilleag seo {{PLURAL:$1|aon turas|$1 thuras|$1 turas|$1 turais|$1 turas}}.',
'protectedpage' => 'Duilleag fo dhìon',
'jumpto' => 'Gearr leum gu:',
'''Mas e deasachadh dligheach a tha seo, feuch ris a-rithist.'''
Mur obraich e fhathast, feuch is [[Special:UserLogout|clàraich a-mach]] is a-steach a-rithist an uairsin.",
+'token_suffix_mismatch' => "'''Dhiùlt sinn na dheasaich thu a chionn 's gun do chuir an cliant agad na caractaran puingeachaidh tro chèile san tòcan deasachaidh.'''
+Dhiùlt sinn na dheasaich thu air eagal 's gun coirbeadh e teacsa na duilleige.
+Tachraidh seo uaireannan ma chleachdar seirbheis-lìn progsaidh gun urra a tha làn de mhearachdan.",
+'edit_form_incomplete' => "'''Cha do ràinig cuid dhen fhoirm deasachaidh am frithealaichte; dèan cinnteach gu bheil gach deasachadh agad slàn is feuch ris a-rithist.'''",
'editing' => "A' deasachadh $1",
'editingsection' => "A' deasachadh $1 (earrann)",
+'editingcomment' => "A' deasachadh $1 (earrann ùr)",
'editconflict' => 'Còmhstri deasachaidh: $1',
'explainconflict' => "Tha cuideigin eile air an duilleag seo a mhùthadh on a thòisich thu fhèin air a dheasachadh.
Tha am bogsa teacsa gu h-àrd a' nochdadh na duilleige mar a tha i an-dràsta.
Cha dèid '''ach an teacsa gu h-àrd''' a shàbhaladh nuair a bhriogas tu air \"{{int:savearticle}}\".",
'yourtext' => 'An teacsa agad',
'storedversion' => 'Lethbhreac taisgte',
+'nonunicodebrowser' => "'''Rabhadh: Chan eil am brabhsair agad co-chòrdail le Unicode.'''
+Chuir sinn gleus air dòigh dhut a nì cinnteach gun urrainn dhut duilleagan a shàbhaladh gu tèarainte: Nochdaidh caractaran taobh a-muigh ASCII mar chòd sia-dheicheach sa bhogsa deasachaidh.",
'editingold' => "'''RABHADH: Tha thu a' deasachadh lethbhreac seann-aimsireil na duilleige seo.
Ma shàbhalas tu seo, thèid gach mùthadh air chall a rinneadh a-mach on mhùthadh seo.'''",
'yourdiff' => 'Caochlaidhean',
Mur eil thu ag iarraidh an sgrìobhaidh agad a dheasaichear is a sgaoilear le càch, na cuir e.<br />
Ma dh'fhoilleachas tu rudeigin an seo, bidh tu a' dearbhadh gun do sgrìobh thu fhèin e, no gur ann às an raon phòballach a thàinig e; thoir aire '''nach eil''' sin a' gabhail a-staigh duilleagan-lìn mar as àbhaist (seall $1 airson barrachd fiosrachaidh). <br />
'''NA CLEACHDAIBH SAOTHAIR FO DHLIGHE-SGRÌOBHAIDH GUN CHEAD!'''",
+'longpageerror' => "'''Mearachd: Tha an teacsa a chur thu thugainn {{PLURAL:$1 kilobyte|$1 kilobyte|$1 kilobyte|$1 kilobyte|$1 kilobyte|$1 kilobyte|}} a dh'fhaid is tha sin nas fhaide na tha ceadaichte ({{PLURAL:$1 kilobyte|$2 kilobyte|$2 kilobyte|$2 kilobyte|$2 kilobyte|$2 kilobyte|}}).'''
+Cha ghabh a shàbhaladh.",
+'readonlywarning' => "'''Rabhadh: Chaidh an stòr-dàta a ghlasadh a chum obair-ghlèidhidh agus chan urrainn dhut na còraichean-deasachaidh agad a chur gu feum an-dràsta fhèin.'''
+'S mathaid gum b' fheairrde dhut lethbhreac a dhèanamh dhen teacsa agus a shàbhaladh ann am faidhle ach an urrainn dhut a chleachdadh as a dhèidh seo.
+
+Seo am mìneachadh a thug an rianaire a ghlais e: $1",
'protectedpagewarning' => "'''Rabhadh: Chaidh an duilleag seo a dhìon 's chan urrainn ach dhan fheadhainn aig a bheil ùghdarras rianaire a dheasachadh.'''
Chì thu an clàr mu dheireadh san loga mar fhiosrachadh dhut gu h-ìosal:",
+'semiprotectedpagewarning' => "'''An aire:''' Chaidh an duilleag seo a dhìon 's chan fhaod ach cleachdaichean clàraichte a dheasachadh.
+Seo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
+'cascadeprotectedwarning' => "'''Rabhadh:''' Chaidh an duilleag seo a dhìon 's chan fhaod ach rianairean a dheasachadh a chionn 's gun robh e am broinn {{PLURAL:$1|na duilleige|nan duilleagan}} a leanas a tha cascade-protected.",
+'titleprotectedwarning' => "'''Rabhadh: Chaidh an duilleag seo a dhìon 's feumar [[Special:ListGroupRights|còraichean sònraichte]] gus a dheasachadh.'''
+Seo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
'templatesused' => "Tha {{PLURAL:$1|teamplaid|theamplaid||teamplaid|theamplaid|teamplaidean|teamplaid}} 'gan cleachdadh air an duilleag seo:",
'templatesusedpreview' => "Tha {{PLURAL:$1|teamplaid 'ga cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh}} san ro-shealladh seo:",
+'templatesusedsection' => "Tha {{PLURAL:$1|teamplaid 'ga cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh|teamplaidean 'gan cleachdadh}} san earrann seo:",
'template-protected' => '(air a dhìon)',
'template-semiprotected' => '(air a leth-dhìon)',
'hiddencategories' => "Tha an duilleag seo 'na ball de {{PLURAL:$1|1 roinn-seòrsa fhalaichte|$1 roinn-seòrsa fhalaichte|1 roinn-seòrsa fhalaichte|$1 roinn-seòrsa fhalaichte|$1 roinnean-seòrsa falaichte|$1 roinn-seòrsa fhalaichte}}:",
L'ultimo elemento del registro dei blocchi è riportato di seguito per informazione:",
'clearyourcache' => "'''Nota:''' dopo aver salvato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.
*'''Firefox / Safari''': tenere premuto il tasto delle maiuscole e fare clic su ''Ricarica'', oppure premere ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' su Mac)
-*'''Google Chrome''': premere ''Ctrl-Shift-R'' (''⌘-Shift-R'' su un Mac)
+*'''Google Chrome''': fare clic su ''Ricarica'', oppure premere ''Ctrl-R'' o ''Ctrl-Shift-R'' (''⌘-Shift-R'' su un Mac)
*'''Internet Explorer''': tenere premuto il tasto ''Ctrl'' mentre si fa clic su ''Refresh'', oppure premere ''Ctrl-F5''
*'''Opera''': svuotare completamente la cache dal menu ''Strumenti → Preferenze''",
'usercssyoucanpreview' => "'''Suggerimento:''' usa il pulsante 'Visualizza anteprima' per provare il tuo nuovo CSS prima di salvarlo.",
'resetpass_announce' => 'メールでお送りした仮パスワードでログインしました。
ログインを完了するには、ここで新しいパスワードを設定する必要があります:',
'resetpass_text' => '<!-- ここに文を挿入 -->',
-'resetpass_header' => 'ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\82\92変更',
-'oldpassword' => '古いパスワード:',
-'newpassword' => '新しいパスワード:',
+'resetpass_header' => 'ã\82¢ã\82«ã\82¦ã\83³ã\83\88ã\81®ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®変更',
+'oldpassword' => '古いパスワード:',
+'newpassword' => '新しいパスワード:',
'retypenew' => '新しいパスワードを再入力:',
'resetpass_submit' => '再設定してログイン',
'resetpass_success' => 'パスワードの変更に成功しました!
手動で統合してください。'''",
'movedto' => '移動先:',
'movetalk' => '付随するトークページも移動',
-'move-subpages' => '下位ページも移動($1ページまで)',
-'move-talk-subpages' => 'トークページの下位ページも移動($1個まで)',
+'move-subpages' => '下位ページも移動($1 件まで)',
+'move-talk-subpages' => 'トークページの下位ページも移動($1 件まで)',
'movepage-page-exists' => 'ページ「$1」は既に存在するため、自動的な上書きはできませんでした。',
'movepage-page-moved' => 'ページ「$1」は「$2」に移動しました。',
'movepage-page-unmoved' => 'ページ「$1」は「$2」に移動できませんでした。',
'movelogpage' => '移動記録',
'movelogpagetext' => '以下はすべてのページ移動の一覧です。',
'movesubpage' => '{{PLURAL:$1|下位ページ}}',
-'movesubpagetext' => 'このページには{{PLURAL:$1|下位ページ}}が以下の $1 件あります。',
+'movesubpagetext' => 'このページには、以下の $1 {{PLURAL:$1|下位ページ}}があります。',
'movenosubpage' => 'このページに下位ページはありません。',
'movereason' => '理由:',
'revertmove' => '差し戻し',
'variantname-ike-latn' => 'イヌクティトゥット語 (ラテン文字)',
'variantname-iu' => 'イヌクティトゥット語',
+# Variants for Tachelhit language
+'variantname-shi-tfng' => 'シルハ語 (ティフィナグ文字)',
+'variantname-shi-latn' => 'シルハ語 (ラテン文字)',
+'variantname-shi' => 'シルハ語',
+
# Metadata
'metadata' => 'メタデータ',
'metadata-help' => 'このファイルには、追加情報があります(おそらく、作成やデジタル化する際に使用したデジタルカメラやスキャナーが追加したものです)。
* @author Junaidpv
* @author Jyothis
* @author Kaganer
+ * @author Krenair
* @author Manjith Joseph <manjithkaini@gmail.com>
* @author Naveen Sankar
* @author Praveen Prakash <me.praveen@gmail.com>
'newarticle' => '(പുതിയത്)',
'newarticletext' => 'ഇതുവരെ നിലവിലില്ലാത്ത ഒരു താൾ സൃഷ്ടിക്കാനുള്ള ശ്രമത്തിലാണ് താങ്കൾ. അതിനായി താഴെ ആവശ്യമുള്ള വിവരങ്ങൾ എഴുതിച്ചേർത്ത് സേവ് ചെയ്യുക (കൂടുതൽ വിവരങ്ങൾക്ക് [[{{MediaWiki:Helppage}}|സഹായം താൾ]] കാണുക). താങ്കളിവിടെ അബദ്ധത്തിൽ വന്നതാണെങ്കിൽ ബ്രൗസറിന്റെ ബാക്ക് ബട്ടൺ ഞെക്കിയാൽ തിരിച്ചുപോകാം.',
'anontalkpagetext' => "----
-{| class=\"messagebox standard-talk\" style=\"border: 1px solid #B3B300; background-color:#FFFFBF;\"
-|align=\"left\" |
+{| class=\"messagebox standard-talk\" style=\"border: 1px solid #B3B300; background-color:#FFFFBF; text-align: left;\"
+|
''ഇതുവരെ അംഗത്വം എടുക്കാതിരിക്കുകയോ, നിലവിലുള്ള അംഗത്വം ഉപയോഗിക്കാതിരിക്കുകയോ ചെയ്യുന്ന '''ഒരു അജ്ഞാത ഉപയോക്താവിന്റെ സംവാദം താളാണിത്'''.
അതിനാൽ അദ്ദേഹത്തെ തിരിച്ചറിയുവാൻ അക്കരൂപത്തിലുള്ള ഐ.പി. വിലാസം ഉപയോഗിക്കേണ്ടതുണ്ട്. ഇത്തരം ഒരു ഐ.പി. വിലാസം പല ഉപയോക്താക്കൾ പങ്കുവെക്കുന്നുണ്ടാവാം.
താങ്കൾ ഈ സന്ദേശം ലഭിച്ച ഒരു അജ്ഞാത ഉപയോക്താവാണെങ്കിൽ, ഭാവിയിൽ ഇതര ഉപയോക്താക്കളുമായി ഉണ്ടായേക്കാവുന്ന ആശയക്കുഴപ്പം ഒഴിവാക്കാൻ ദയവായി [[Special:UserLogin/signup|ഒരു അംഗത്വമെടുക്കുക]] അല്ലെങ്കിൽ [[Special:UserLogin|പ്രവേശിക്കുക]].
'spamprotectiontitle' => 'Spam ਸੁਰੱਖਿਆ ਫਿਲਟਰ',
# Info page
-'pageinfo-header-edits' => 'ਸੋਧਾਂ',
-'pageinfo-watchers' => 'ਨà¨\9c਼ਰ ਰੱà¨\96ਣ ਵਾਲ਼ਿà¨\86à¨\82 ਦà©\80 à¨\97ਿਣਤà©\80',
-'pageinfo-edits' => 'ਸà©\8bਧਾà¨\82 ਦà©\80 à¨\97ਿਣਤà©\80',
+'pageinfo-header-edits' => 'ਸੋਧਾਂ ਦਾ ਅਤੀਤ',
+'pageinfo-watchers' => 'ਸਫ਼à©\87 â\80\99ਤà©\87 ਨà¨\9c਼ਰ ਰੱà¨\96ਣ ਵਾਲ਼à©\87',
+'pageinfo-edits' => 'à¨\95à©\81ੱਲ ਸà©\8bਧਾà¨\82',
# Skin names
'skinname-standard' => 'ਕਲਾਸਿਕ',
'tooltip-t-permalink' => 'Anliura fissa a sta version-sì dla pàgina',
'tooltip-ca-nstab-main' => 'Vardé la pàgina ëd contnù.',
'tooltip-ca-nstab-user' => 'Vardé la pàgina Utent.',
-'tooltip-ca-nstab-media' => 'Vardé la pàgina dl',
+'tooltip-ca-nstab-media' => 'Vardé la pàgina dël mojen',
'tooltip-ca-nstab-special' => 'Costa a l',
'tooltip-ca-nstab-project' => 'Vardé la pàgina proteta.',
'tooltip-ca-nstab-image' => 'Vardé la pàgina dl',
* @ingroup Language
* @file
*
+ * @author Arjunaraoc
* @author Chaduvari
* @author Jprmvnvijay5
* @author Kaganer
# Special:ChangeEmail
'changeemail' => 'ఈ-మెయిలు చిరునామా మార్పు',
'changeemail-header' => 'ఖాతా ఈ-మెయిల్ చిరునామాని మార్చండి',
+'changeemail-text' => 'మీ ఈమెయిల్ చిరునామా మార్చుటకు ఈ ఫారము నింపండి. ఈ మార్పుని ఖచ్చితపరచుటకు మీ సంకేతపదం ప్రవేశపెట్టాలి.',
'changeemail-no-info' => 'ఈ పేజీని నేరుగా చూడటానికి మీరు లోనికి ప్రవేశించివుండాలి.',
'changeemail-oldemail' => 'ప్రస్తుత ఈ-మెయిలు చిరునామా:',
'changeemail-newemail' => 'కొత్త ఈ-మెయిలు చిరునామా:',
'contribslink' => 'kontribuisaun',
'block-log-flags-nocreate' => 'la bele kria konta foun',
'block-log-flags-noemail' => 'korreiu eletróniku blokeiu',
+'block-log-flags-nousertalk' => 'la bele edita pájina diskusaun rasik',
'ipb_already_blocked' => 'Ema ruma blokeiu "$1" tiha ona',
# Move page
'uploadlogpagetext' => 'درج ذیل میں حالیہ زبراثقال (اپ لوڈ) کی گئی املاف (فائلوں) کی فہرست دی گئی ہے۔',
'filedesc' => 'خلاصہ',
'fileuploadsummary' => 'خلاصہ :',
+'filesource' => 'ذرائع',
'uploadedfiles' => 'زبراثقال ملف (فائل اپ لوڈ)',
'ignorewarning' => 'انتباہ نظرانداز کرتے ہوۓ بہرصورت ملف (فائل) کو محفوظ کرلیا جاۓ۔',
'ignorewarnings' => 'ہر انتباہ نظرانداز کردیا جاۓ۔',
// Bail if PHP is too low
if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+ // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require( dirname( __FILE__ ) . '/includes/PHPVersionError.php' );
wfPHPVersionError( 'load.php' );
}
* @defgroup Maintenance Maintenance
*/
-// Make sure we're on PHP5 or better
+// Make sure we're on PHP5.3.2 or better
if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+ // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
require_once( dirname( __FILE__ ) . '/../includes/PHPVersionError.php' );
wfPHPVersionError( 'cli' );
}
$maintClass = false;
-
/**
* Abstract maintenance class for quickly writing and churning out
* maintenance scripts with minimal effort. All that _must_ be defined
'scripts' => 'resources/jquery/jquery.spinner.js',
'styles' => 'resources/jquery/jquery.spinner.css',
),
+ 'jquery.jStorage' => array(
+ 'scripts' => 'resources/jquery/jquery.jStorage.js',
+ 'dependencies' => 'jquery.json',
+ ),
'jquery.suggestions' => array(
'scripts' => 'resources/jquery/jquery.suggestions.js',
'styles' => 'resources/jquery/jquery.suggestions.css',
--- /dev/null
+/*
+ * ----------------------------- JSTORAGE -------------------------------------
+ * Simple local storage wrapper to save data on the browser side, supporting
+ * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
+ *
+ * Copyright (c) 2010 Andris Reinman, andris.reinman@gmail.com
+ * Project homepage: www.jstorage.info
+ *
+ * Taken from Github with slight modifications by Hoo man
+ * https://raw.github.com/andris9/jStorage/master/jstorage.js
+ *
+ * Licensed under MIT-style license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * $.jStorage
+ *
+ * USAGE:
+ *
+ * jStorage requires Prototype, MooTools or jQuery! If jQuery is used, then
+ * jQuery-JSON (http://code.google.com/p/jquery-json/) is also needed.
+ * (jQuery-JSON needs to be loaded BEFORE jStorage!)
+ *
+ * Methods:
+ *
+ * -set(key, value[, options])
+ * $.jStorage.set(key, value) -> saves a value
+ *
+ * -get(key[, default])
+ * value = $.jStorage.get(key [, default]) ->
+ * retrieves value if key exists, or default if it doesn't
+ *
+ * -deleteKey(key)
+ * $.jStorage.deleteKey(key) -> removes a key from the storage
+ *
+ * -flush()
+ * $.jStorage.flush() -> clears the cache
+ *
+ * -storageObj()
+ * $.jStorage.storageObj() -> returns a read-ony copy of the actual storage
+ *
+ * -storageSize()
+ * $.jStorage.storageSize() -> returns the size of the storage in bytes
+ *
+ * -index()
+ * $.jStorage.index() -> returns the used keys as an array
+ *
+ * -storageAvailable()
+ * $.jStorage.storageAvailable() -> returns true if storage is available
+ *
+ * -reInit()
+ * $.jStorage.reInit() -> reloads the data from browser storage
+ *
+ * <value> can be any JSON-able value, including objects and arrays.
+ *
+ **/
+
+(function($){
+ if(!$ || !($.toJSON || Object.toJSON || window.JSON)){
+ throw new Error("jQuery, MooTools or Prototype needs to be loaded before jStorage!");
+ }
+
+ var
+ /* This is the object, that holds the cached values */
+ _storage = {},
+
+ /* Actual browser storage (localStorage or globalStorage['domain']) */
+ _storage_service = {jStorage:"{}"},
+
+ /* DOM element for older IE versions, holds userData behavior */
+ _storage_elm = null,
+
+ /* How much space does the storage take */
+ _storage_size = 0,
+
+ /* function to encode objects to JSON strings */
+ json_encode = $.toJSON || Object.toJSON || (window.JSON && (JSON.encode || JSON.stringify)),
+
+ /* function to decode objects from JSON strings */
+ json_decode = $.evalJSON || (window.JSON && (JSON.decode || JSON.parse)) || function(str){
+ return String(str).evalJSON();
+ },
+
+ /* which backend is currently used */
+ _backend = false,
+
+ /* Next check for TTL */
+ _ttl_timeout,
+
+ /**
+ * XML encoding and decoding as XML nodes can't be JSON'ized
+ * XML nodes are encoded and decoded if the node is the value to be saved
+ * but not if it's as a property of another object
+ * Eg. -
+ * $.jStorage.set("key", xmlNode); // IS OK
+ * $.jStorage.set("key", {xml: xmlNode}); // NOT OK
+ */
+ _XMLService = {
+
+ /**
+ * Validates a XML node to be XML
+ * based on jQuery.isXML function
+ */
+ isXML: function(elm){
+ var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ },
+
+ /**
+ * Encodes a XML node to string
+ * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
+ */
+ encode: function(xmlNode) {
+ if(!this.isXML(xmlNode)){
+ return false;
+ }
+ try{ // Mozilla, Webkit, Opera
+ return new XMLSerializer().serializeToString(xmlNode);
+ }catch(E1) {
+ try { // IE
+ return xmlNode.xml;
+ }catch(E2){}
+ }
+ return false;
+ },
+
+ /**
+ * Decodes a XML node from string
+ * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
+ */
+ decode: function(xmlString){
+ var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) ||
+ (window.ActiveXObject && function(_xmlString) {
+ var xml_doc = new ActiveXObject('Microsoft.XMLDOM');
+ xml_doc.async = 'false';
+ xml_doc.loadXML(_xmlString);
+ return xml_doc;
+ }),
+ resultXML;
+ if(!dom_parser){
+ return false;
+ }
+ resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, 'text/xml');
+ return this.isXML(resultXML)?resultXML:false;
+ }
+ };
+
+ ////////////////////////// PRIVATE METHODS ////////////////////////
+
+ /**
+ * Initialization function. Detects if the browser supports DOM Storage
+ * or userData behavior and behaves accordingly.
+ * @returns undefined
+ */
+ function _init(){
+ /* Check if browser supports localStorage */
+ var localStorageReallyWorks = false;
+ if("localStorage" in window){
+ try {
+ window.localStorage.setItem('_tmptest', 'tmpval');
+ localStorageReallyWorks = true;
+ window.localStorage.removeItem('_tmptest');
+ } catch(BogusQuotaExceededErrorOnIos5) {
+ // Thanks be to iOS5 Private Browsing mode which throws
+ // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
+ }
+ }
+ if(localStorageReallyWorks){
+ try {
+ if(window.localStorage) {
+ _storage_service = window.localStorage;
+ _backend = "localStorage";
+ }
+ } catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */}
+ }
+ /* Check if browser supports globalStorage */
+ else if("globalStorage" in window){
+ try {
+ if(window.globalStorage) {
+ _storage_service = window.globalStorage[window.location.hostname];
+ _backend = "globalStorage";
+ }
+ } catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */}
+ }
+ /* Check if browser supports userData behavior */
+ else {
+ _storage_elm = document.createElement('link');
+ if(_storage_elm.addBehavior){
+
+ /* Use a DOM element to act as userData storage */
+ _storage_elm.style.behavior = 'url(#default#userData)';
+
+ /* userData element needs to be inserted into the DOM! */
+ document.getElementsByTagName('head')[0].appendChild(_storage_elm);
+
+ _storage_elm.load("jStorage");
+ var data = "{}";
+ try{
+ data = _storage_elm.getAttribute("jStorage");
+ }catch(E5){}
+ _storage_service.jStorage = data;
+ _backend = "userDataBehavior";
+ }else{
+ _storage_elm = null;
+ return;
+ }
+ }
+
+ _load_storage();
+
+ // remove dead keys
+ _handleTTL();
+ }
+
+ /**
+ * Loads the data from the storage based on the supported mechanism
+ * @returns undefined
+ */
+ function _load_storage(){
+ /* if jStorage string is retrieved, then decode it */
+ if(_storage_service.jStorage){
+ try{
+ _storage = json_decode(String(_storage_service.jStorage));
+ }catch(E6){_storage_service.jStorage = "{}";}
+ }else{
+ _storage_service.jStorage = "{}";
+ }
+ _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
+ }
+
+ /**
+ * This functions provides the "save" mechanism to store the jStorage object
+ * @returns undefined
+ */
+ function _save(){
+ try{
+ _storage_service.jStorage = json_encode(_storage);
+ // If userData is used as the storage engine, additional
+ if(_storage_elm) {
+ _storage_elm.setAttribute("jStorage",_storage_service.jStorage);
+ _storage_elm.save("jStorage");
+ }
+ _storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
+ }catch(E7){/* probably cache is full, nothing is saved this way*/}
+ }
+
+ /**
+ * Function checks if a key is set and is string or numberic
+ */
+ function _checkKey(key){
+ if(!key || (typeof key !== "string" && typeof key !== "number")){
+ throw new TypeError('Key name must be string or numeric');
+ }
+ if(key === "__jstorage_meta"){
+ throw new TypeError('Reserved key name');
+ }
+ return true;
+ }
+
+ /**
+ * Removes expired keys
+ */
+ function _handleTTL(){
+ var curtime, i, TTL, nextExpire = Infinity, changed = false;
+
+ clearTimeout(_ttl_timeout);
+
+ if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL !== "object"){
+ // nothing to do here
+ return;
+ }
+
+ curtime = +new Date();
+ TTL = _storage.__jstorage_meta.TTL;
+ for(i in TTL){
+ if(TTL.hasOwnProperty(i)){
+ if(TTL[i] <= curtime){
+ delete TTL[i];
+ delete _storage[i];
+ changed = true;
+ }else if(TTL[i] < nextExpire){
+ nextExpire = TTL[i];
+ }
+ }
+ }
+
+ // set next check
+ if(nextExpire != Infinity){
+ _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
+ }
+
+ // save changes
+ if(changed){
+ _save();
+ }
+ }
+
+ ////////////////////////// PUBLIC INTERFACE /////////////////////////
+
+ $.jStorage = {
+ /* Version number */
+ version: "0.1.7.0",
+
+ /**
+ * Sets a key's value.
+ *
+ * @param {String} key - Key to set. If this value is not set or not
+ * a string an exception is raised.
+ * @param {Mixed} value - Value to set. This can be any value that is JSON
+ * compatible (Numbers, Strings, Objects etc.).
+ * @param {Object} [options] - possible options to use
+ * @param {Number} [options.TTL] - optional TTL value
+ * @returns the used value
+ */
+ set: function(key, value, options){
+ _checkKey(key);
+
+ options = options || {};
+
+ if(_XMLService.isXML(value)){
+ value = {_is_xml:true,xml:_XMLService.encode(value)};
+ }else if(typeof value === "function"){
+ value = null; // functions can't be saved!
+ }else if(value && typeof value === "object"){
+ // clone the object before saving to _storage tree
+ value = json_decode(json_encode(value));
+ }
+ _storage[key] = value;
+
+ if(!isNaN(options.TTL)){
+ this.setTTL(key, options.TTL);
+ // also handles saving
+ }else{
+ _save();
+ }
+ return value;
+ },
+
+ /**
+ * Looks up a key in cache
+ *
+ * @param {String} key - Key to look up.
+ * @param {mixed} def - Default value to return, if key didn't exist.
+ * @returns the key value, default value or <null>
+ */
+ get: function(key, def){
+ _checkKey(key);
+ if(key in _storage){
+ if(_storage[key] && typeof _storage[key] === "object" &&
+ _storage[key]._is_xml &&
+ _storage[key]._is_xml){
+ return _XMLService.decode(_storage[key].xml);
+ }else{
+ return _storage[key];
+ }
+ }
+ return typeof(def) === 'undefined' ? null : def;
+ },
+
+ /**
+ * Deletes a key from cache.
+ *
+ * @param {String} key - Key to delete.
+ * @returns true if key existed or false if it didn't
+ */
+ deleteKey: function(key){
+ _checkKey(key);
+ if(key in _storage){
+ delete _storage[key];
+ // remove from TTL list
+ if(_storage.__jstorage_meta &&
+ typeof _storage.__jstorage_meta.TTL === "object" &&
+ key in _storage.__jstorage_meta.TTL){
+ delete _storage.__jstorage_meta.TTL[key];
+ }
+ _save();
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Sets a TTL for a key, or remove it if ttl value is 0 or below
+ *
+ * @param {String} key - key to set the TTL for
+ * @param {Number} ttl - TTL timeout in milliseconds
+ * @returns true if key existed or false if it didn't
+ */
+ setTTL: function(key, ttl){
+ var curtime = +new Date();
+ _checkKey(key);
+ ttl = Number(ttl) || 0;
+ if(key in _storage){
+
+ if(!_storage.__jstorage_meta){
+ _storage.__jstorage_meta = {};
+ }
+ if(!_storage.__jstorage_meta.TTL){
+ _storage.__jstorage_meta.TTL = {};
+ }
+
+ // Set TTL value for the key
+ if(ttl>0){
+ _storage.__jstorage_meta.TTL[key] = curtime + ttl;
+ }else{
+ delete _storage.__jstorage_meta.TTL[key];
+ }
+
+ _save();
+
+ _handleTTL();
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Deletes everything in cache.
+ *
+ * @return true
+ */
+ flush: function(){
+ _storage = {};
+ _save();
+ return true;
+ },
+
+ /**
+ * Returns a read-only copy of _storage
+ *
+ * @returns Object
+ */
+ storageObj: function(){
+ function F() {}
+ F.prototype = _storage;
+ return new F();
+ },
+
+ /**
+ * Returns an index of all used keys as an array
+ * ['key1', 'key2',..'keyN']
+ *
+ * @returns Array
+ */
+ index: function(){
+ var index = [], i;
+ for(i in _storage){
+ if(_storage.hasOwnProperty(i) && i !== "__jstorage_meta"){
+ index.push(i);
+ }
+ }
+ return index;
+ },
+
+ /**
+ * How much space in bytes does the storage take?
+ *
+ * @returns Number
+ */
+ storageSize: function(){
+ return _storage_size;
+ },
+
+ /**
+ * Which backend is currently in use?
+ *
+ * @returns String
+ */
+ currentBackend: function(){
+ return _backend;
+ },
+
+ /**
+ * Test if storage is available
+ *
+ * @returns Boolean
+ */
+ storageAvailable: function(){
+ return !!_backend;
+ },
+
+ /**
+ * Reloads the data from browser storage
+ *
+ * @returns undefined
+ */
+ reInit: function(){
+ var new_storage_elm, data;
+ if(_storage_elm && _storage_elm.addBehavior){
+ new_storage_elm = document.createElement('link');
+
+ _storage_elm.parentNode.replaceChild(new_storage_elm, _storage_elm);
+ _storage_elm = new_storage_elm;
+
+ /* Use a DOM element to act as userData storage */
+ _storage_elm.style.behavior = 'url(#default#userData)';
+
+ /* userData element needs to be inserted into the DOM! */
+ document.getElementsByTagName('head')[0].appendChild(_storage_elm);
+
+ _storage_elm.load("jStorage");
+ data = "{}";
+ try{
+ data = _storage_elm.getAttribute("jStorage");
+ }catch(E5){}
+ _storage_service.jStorage = data;
+ _backend = "userDataBehavior";
+ }
+
+ _load_storage();
+ }
+ };
+
+ // Initialize jStorage
+ _init();
+
+})(window.$ || window.jQuery);
wfProfileOut( __METHOD__ . '-1' );
wfProfileIn( __METHOD__ . '-2' );
$l = $this->getSkin()->getLanguage()->alignStart();
- $s .= "<td class='bottom' align='$l' valign='top'>";
+ $s .= "<td class='bottom' style='text-align: $l; vertical-align: top;'>";
$s .= $this->bottomLinks();
$s .= "\n<br />" . $this->getSkin()->getLanguage()->pipeList( array(