r47081 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r47080‎ | r47081 | r47082 >
Date:12:45, 10 February 2009
Author:mkroetzsch
Status:deferred
Tags:
Comment:
formats 'icalendar' and 'vcard' moved from SMW to SRF
Modified paths:
  • /trunk/extensions/SemanticResultFormats/INSTALL (modified) (history)
  • /trunk/extensions/SemanticResultFormats/README (modified) (history)
  • /trunk/extensions/SemanticResultFormats/RELEASE-NOTES (modified) (history)
  • /trunk/extensions/SemanticResultFormats/SRF_Messages.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/SRF_Settings.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/Timeline/SRF_Timeline.php (modified) (history)
  • /trunk/extensions/SemanticResultFormats/iCalendar (added) (history)
  • /trunk/extensions/SemanticResultFormats/iCalendar/SRF_iCalendar.php (added) (history)
  • /trunk/extensions/SemanticResultFormats/vCard (added) (history)
  • /trunk/extensions/SemanticResultFormats/vCard/SRF_vCard.php (added) (history)

Diff [purge]

Index: trunk/extensions/SemanticResultFormats/iCalendar/SRF_iCalendar.php
@@ -0,0 +1,161 @@
 2+<?php
 3+/**
 4+ * Create iCalendar exports
 5+ * @file
 6+ * @ingroup SemanticResultFormats
 7+ */
 8+
 9+/**
 10+ * Printer class for creating iCalendar exports
 11+ * @author Markus Krötzsch
 12+ * @author Denny Vrandecic
 13+ * @ingroup SemanticResultFormats
 14+ */
 15+class SRFiCalendar extends SMWResultPrinter {
 16+ protected $m_title = '';
 17+ protected $m_description = '';
 18+
 19+ protected function readParameters($params,$outputmode) {
 20+ SMWResultPrinter::readParameters($params,$outputmode);
 21+ if (array_key_exists('title', $this->m_params)) {
 22+ $this->m_title = trim($this->m_params['title']);
 23+ // for backward compatibility
 24+ } elseif (array_key_exists('icalendartitle', $this->m_params)) {
 25+ $this->m_title = trim($this->m_params['icalendartitle']);
 26+ }
 27+ if (array_key_exists('description', $this->m_params)) {
 28+ $this->m_description = trim($this->m_params['description']);
 29+ // for backward compatibility
 30+ } elseif (array_key_exists('icalendardescription', $this->m_params)) {
 31+ $this->m_description = trim($this->m_params['icalendardescription']);
 32+ }
 33+ }
 34+
 35+ public function getMimeType($res) {
 36+ return 'text/calendar';
 37+ }
 38+
 39+ public function getFileName($res) {
 40+ if ($this->m_title != '') {
 41+ return str_replace(' ', '_',$this->m_title) . '.ics';
 42+ } else {
 43+ return 'iCalendar.ics';
 44+ }
 45+ }
 46+
 47+ protected function getResultText($res, $outputmode) {
 48+ global $smwgIQRunningNumber, $wgSitename, $wgServer, $wgRequest;
 49+ $result = '';
 50+
 51+ if ($outputmode == SMW_OUTPUT_FILE) { // make RSS feed
 52+ if ($this->m_title == '') {
 53+ $this->m_title = $wgSitename;
 54+ }
 55+ $result .= "BEGIN:VCALENDAR\r\n";
 56+ $result .= "PRODID:-//SMW Project//Semantic Result Formats\r\n";
 57+ $result .= "VERSION:2.0\r\n";
 58+ $result .= "METHOD:PUBLISH\r\n";
 59+ $result .= "X-WR-CALNAME:" . $this->m_title . "\r\n";
 60+ if ($this->m_description !== '') {
 61+ $result .= "X-WR-CALDESC:" . $this->m_description . "\r\n";
 62+ }
 63+
 64+ $row = $res->getNext();
 65+ while ( $row !== false ) {
 66+ $wikipage = $row[0]->getNextObject(); // get the object
 67+ $startdate = false;
 68+ $enddate = false;
 69+ $location = '';
 70+ $description = '';
 71+ foreach ($row as $field) {
 72+ // later we may add more things like a generic
 73+ // mechanism to add whatever you want :)
 74+ // could include funny things like geo, description etc. though
 75+ $req = $field->getPrintRequest();
 76+ if ( (strtolower($req->getLabel()) == "start") && ($req->getTypeID() == "_dat") ) {
 77+ $startdate = current($field->getContent()); // save only the first
 78+ }
 79+ if ( (strtolower($req->getLabel()) == "end") && ($req->getTypeID() == "_dat") ) {
 80+ $enddate = current($field->getContent()); // save only the first
 81+ }
 82+ if (strtolower($req->getLabel()) == "location") {
 83+ $value = current($field->getContent()); // save only the first
 84+ if ($value !== false) {
 85+ $location = $value->getShortWikiText();
 86+ }
 87+ }
 88+ if (strtolower($req->getLabel()) == "description") {
 89+ $value = current($field->getContent()); // save only the first
 90+ if ($value !== false) {
 91+ $description = $value->getShortWikiText();
 92+ }
 93+ }
 94+ }
 95+ $title = $wikipage->getTitle();
 96+ $article = new Article($title);
 97+ $url = $title->getFullURL();
 98+ $result .= "BEGIN:VEVENT\r\n";
 99+ $result .= "SUMMARY:" . $wikipage->getShortWikiText() . "\r\n";
 100+ $result .= "URL:$url\r\n";
 101+ $result .= "UID:$url\r\n";
 102+ if ($startdate != false) $result .= "DTSTART:" . $this->parsedate($startdate) . "\r\n";
 103+ if ($enddate != false) $result .= "DTEND:" . $this->parsedate($enddate,true) . "\r\n";
 104+ if ($location != "") $result .= "LOCATION:$location\r\n";
 105+ if ($description != "") $result .= "DESCRIPTION:$description\r\n";
 106+ $t = strtotime(str_replace('T', ' ', $article->getTimestamp()));
 107+ $result .= "DTSTAMP:" . date("Ymd", $t) . "T" . date("His", $t) . "\r\n";
 108+ $result .= "SEQUENCE:" . $title->getLatestRevID() . "\r\n";
 109+ $result .= "END:VEVENT\r\n";
 110+ $row = $res->getNext();
 111+ }
 112+ $result .= "END:VCALENDAR\r\n";
 113+ } else { // just make link to feed
 114+ if ($this->getSearchLabel($outputmode)) {
 115+ $label = $this->getSearchLabel($outputmode);
 116+ } else {
 117+ wfLoadExtensionMessages('SemanticResultFormats');
 118+ $label = wfMsgForContent('srf_icalendar_link');
 119+ }
 120+ $link = $res->getQueryLink($label);
 121+ $link->setParameter('icalendar','format');
 122+ if ($this->m_title !== '') {
 123+ $link->setParameter($this->m_title,'title');
 124+ }
 125+ if ($this->m_description !== '') {
 126+ $link->setParameter($this->m_description,'description');
 127+ }
 128+ if (array_key_exists('limit', $this->m_params)) {
 129+ $link->setParameter($this->m_params['limit'],'limit');
 130+ } else { // use a reasonable default limit
 131+ $link->setParameter(20,'limit');
 132+ }
 133+
 134+ $result .= $link->getText($outputmode,$this->mLinker);
 135+ $this->isHTML = ($outputmode == SMW_OUTPUT_HTML); // yes, our code can be viewed as HTML if requested, no more parsing needed
 136+ }
 137+
 138+ return $result;
 139+ }
 140+
 141+ /**
 142+ * Extract a date string formatted for iCalendar from a SMWTimeValue object.
 143+ */
 144+ static private function parsedate(SMWTimeValue $dv, $isend=false) {
 145+ $year = $dv->getYear();
 146+ if ( ($year > 9999) || ($year<-9998) ) return ''; // ISO range is limited to four digits
 147+ $year = number_format($year, 0, '.', '');
 148+ $time = str_replace(':','', $dv->getTimeString(false));
 149+ if ( ($time == false) && ($isend) ) { // increment by one day, compute date to cover leap years etc.
 150+ $dv = SMWDataValueFactory::newTypeIDValue('_dat',$dv->getWikiValue() . 'T00:00:00+24:00');
 151+ }
 152+ $month = $dv->getMonth();
 153+ if (strlen($month) == 1) $month = '0' . $month;
 154+ $day = $dv->getDay();
 155+ if (strlen($day) == 1) $day = '0' . $day;
 156+ $result = $year . $month . $day;
 157+ if ($time != false) $result .= "T$time";
 158+ return $result;
 159+ }
 160+
 161+}
 162+
Property changes on: trunk/extensions/SemanticResultFormats/iCalendar/SRF_iCalendar.php
___________________________________________________________________
Name: svn:eol-style
1163 + native
Index: trunk/extensions/SemanticResultFormats/README
@@ -10,8 +10,20 @@
1111 same second level version number as Semantic Result Formats, i.e. SRF 1.4.1
1212 requires SMW 1.4.0.
1313
 14+For more information, see http://semantic-mediawiki.org/wiki/SRF
 15+
1416 == Included formats ==
1517
 18+=== icalendar ===
 19+
 20+Enable exports of calendar entries (events) using the iCalendar format.
 21+Using this format creates an according download link in the wiki.
 22+
 23+=== vcard ===
 24+
 25+Enable exports of contact data (email, phone, address, etc.) using the vCard
 26+format. Using this format creates an according download link in the wiki.
 27+
1628 === calendar ===
1729
1830 Displays query results in a monthly calendar interface.
@@ -26,16 +38,39 @@
2739 Displays query results in interactive timelines, displaying an arbitrary number
2840 of individual dates per query result.
2941
 42+
 43+=== sum ===
 44+
 45+Displays the sum of the numeric values of the queried property.
 46+
 47+=== average ===
 48+
 49+Displays the average of the numeric values of the queried property.
 50+
 51+=== min ===
 52+
 53+Displays the smallest of the numeric values of the queried property.
 54+
 55+=== max ===
 56+
 57+Displays the largest of the numeric values of the queried property.
 58+
3059 === googlepie ===
3160
3261 Creates a pie chart out of the numeric value of a specific property using
33 -the Google Charts API.
 62+the Google Charts API. This format sends data to Google for formatting.
3463
3564 === googlebar ===
3665
3766 Creates a bar chart out of the numeric value of a specific property using
38 -the Google Charts API.
 67+the Google Charts API. This format sends data to Google for formatting.
3968
 69+=== exhibit ===
 70+
 71+Creates an interactive browsing/filtering interface for displaying query
 72+results. Various display modes are supported. One is Google Maps, which
 73+requires data to be transmitted to Google.
 74+
4075 === ploticus ===
4176
4277 Creates a variety of graph types using the Ploticus application, which must be
@@ -46,26 +81,11 @@
4782 Creates a graph based on the relations in the wiki. Requires the GraphViz
4883 extension.
4984
50 -=== sum ===
5185
52 -Displays the sum of the numeric values of the queried property.
53 -
54 -=== average ===
55 -
56 -Displays the average of the numeric values of the queried property.
57 -
58 -=== min ===
59 -
60 -Displays the smallest of the numeric values of the queried property.
61 -
62 -=== max ===
63 -
64 -Displays the largest of the numeric values of the queried property.
65 -
6686 == Contact ==
6787
6888 If you have remarks, questions, or suggestions, please send them to
69 -semediawiki-users@lists.sourceforge.net. You can subscribe to this
 89+semediawiki-users@lists.sourceforge.net. You can subscribe to this
7090 list at
7191 http://sourceforge.net/mailarchive/forum.php?forum_name=semediawiki-user.
7292
@@ -107,5 +127,5 @@
108128
109129 Translations to various languages are provided and maintained by many people.
110130 In general, main contributors can be found in the message file. Special thanks
111 -are due to Siebrand Mazeland and the Betawiki project for their excellent
 131+are due to Siebrand Mazeland and the Betawiki project for their excellent
112132 support in that matter.
Index: trunk/extensions/SemanticResultFormats/vCard/SRF_vCard.php
@@ -0,0 +1,538 @@
 2+<?php
 3+/**
 4+ * Create vCard exports
 5+ * @file
 6+ * @ingroup SemanticResultFormats
 7+ */
 8+
 9+/**
 10+ * Printer class for creating vCard exports
 11+ * @author Markus Krötzsch
 12+ * @author Denny Vrandecic
 13+ * @author Frank Dengler
 14+ * @ingroup SemanticResultFormats
 15+ */
 16+class SRFvCard extends SMWResultPrinter {
 17+ protected $m_title = '';
 18+ protected $m_description = '';
 19+
 20+ public function getMimeType($res) {
 21+ return 'text/x-vcard';
 22+ }
 23+
 24+ public function getFileName($res) {
 25+ if ($this->getSearchLabel(SMW_OUTPUT_WIKI) != '') {
 26+ return str_replace(' ', '_',$this->getSearchLabel(SMW_OUTPUT_WIKI)) . '.vcf';
 27+ } else {
 28+ return 'vCard.vcf';
 29+ }
 30+ }
 31+
 32+ protected function getResultText($res, $outputmode) {
 33+ global $smwgIQRunningNumber, $wgSitename, $wgServer, $wgRequest;
 34+ $result = '';
 35+ $items = array();
 36+ if ($outputmode == SMW_OUTPUT_FILE) { // make vCard file
 37+ if ($this->m_title == '') {
 38+ $this->m_title = $wgSitename;
 39+ }
 40+ $row = $res->getNext();
 41+ while ( $row !== false ) {
 42+ $wikipage = $row[0]->getNextObject(); // get the object
 43+ // name
 44+ $prefix = ''; // something like 'Dr.'
 45+ $firstname = ''; // given name
 46+ $additionalname = ''; // typically the "middle" name (second first name)
 47+ $lastname = ''; // family name
 48+ $suffix = ''; // things like "jun." or "sen."
 49+ $fullname = ''; // the "formatted name", may be independent from first/lastname & co.
 50+ // contacts
 51+ $emails = array();
 52+ $tels = array();
 53+ $addresses = array();
 54+ // organisational details:
 55+ $organization = ''; // any string
 56+ $jobtitle ='';
 57+ $role = '';
 58+ $department ='';
 59+ // other stuff
 60+ $category ='';
 61+ $birthday = ''; // a date
 62+ $url =''; // homepage, a legal URL
 63+ $note =''; // any text
 64+ $workaddress = false;
 65+ $homeaddress = false;
 66+
 67+ $workpostofficebox ='';
 68+ $workextendedaddress ='';
 69+ $workstreet ='';
 70+ $worklocality ='';
 71+ $workregion ='';
 72+ $workpostalcode ='';
 73+ $workcountry ='';
 74+
 75+
 76+ $homepostofficebox ='';
 77+ $homeextendedaddress ='';
 78+ $homestreet ='';
 79+ $homelocality ='';
 80+ $homeregion ='';
 81+ $homepostalcode ='';
 82+ $homecountry ='';
 83+
 84+ foreach ($row as $field) {
 85+ // later we may add more things like a generic
 86+ // mechanism to add non-standard vCard properties as well
 87+ // (could include funny things like geo, description etc.)
 88+ $req = $field->getPrintRequest();
 89+ $reqValue = (strtolower($req->getLabel()));
 90+ switch($reqValue) {
 91+ case "name":
 92+ $value = current($field->getContent()); // save only the first
 93+ if ($value !== false) {
 94+ $fullname = $value->getShortWikiText();
 95+ }
 96+ break;
 97+
 98+ case "prefix":
 99+ foreach ($field->getContent() as $value) {
 100+ $prefix .= ($prefix?',':'') . $value->getShortWikiText();
 101+ }
 102+ break;
 103+
 104+ case "suffix":
 105+ foreach ($field->getContent() as $value) {
 106+ $suffix .= ($suffix?',':'') . $value->getShortWikiText();
 107+ }
 108+ break;
 109+
 110+ case "firstname":
 111+ $value = current($field->getContent()); // save only the first
 112+ if ($value !== false) {
 113+ $firstname = $value->getShortWikiText();
 114+ }
 115+ break;
 116+
 117+ case "extraname":
 118+ foreach ($field->getContent() as $value) {
 119+ $additionalname .= ($additionalname?',':'') . $value->getShortWikiText();
 120+ }
 121+ break;
 122+
 123+ case "lastname":
 124+ $value = current($field->getContent()); // save only the first
 125+ if ($value !== false) {
 126+ $lastname = $value->getShortWikiText();
 127+ }
 128+ break;
 129+
 130+ case "note":
 131+ foreach ($field->getContent() as $value) {
 132+ $note .= ($note?', ':'') . $value->getShortWikiText();
 133+ }
 134+ break;
 135+
 136+ case "email":
 137+ foreach ($field->getContent() as $entry) {
 138+ $emails[] = new SRFvCardEmail('internet', $entry->getShortWikiText());
 139+ }
 140+ break;
 141+
 142+ case "workphone":
 143+ foreach ($field->getContent() as $entry) {
 144+ $tels[] = new SRFvCardTel('WORK',$entry->getShortWikiText());
 145+ }
 146+ break;
 147+
 148+ case "cellphone":
 149+ foreach ($field->getContent() as $entry) {
 150+ $tels[] = new SRFvCardTel('CELL',$entry->getShortWikiText());
 151+ }
 152+ break;
 153+
 154+ case "homephone":
 155+ foreach ($field->getContent() as $entry) {
 156+ $tels[] = new SRFvCardTel('HOME',$entry->getShortWikiText());
 157+ }
 158+ break;
 159+
 160+ case "organization":
 161+ $value = current($field->getContent()); // save only the first
 162+ if ($value !== false) {
 163+ $organization = $value->getShortWikiText();
 164+ }
 165+ break;
 166+
 167+ case "workpostofficebox":
 168+ $value = current($field->getContent()); // save only the first
 169+ if ($value !== false) {
 170+ $workpostofficebox = $value->getShortWikiText();
 171+ $workaddress = true;
 172+ }
 173+ break;
 174+
 175+ case "workextendedaddress":
 176+ $value = current($field->getContent()); // save only the first
 177+ if ($value !== false) {
 178+ $workextendedaddress = $value->getShortWikiText();
 179+ $workaddress = true;
 180+ }
 181+ break;
 182+
 183+ case "workstreet":
 184+ $value = current($field->getContent()); // save only the first
 185+ if ($value !== false) {
 186+ $workstreet = $value->getShortWikiText();
 187+ $workaddress = true;
 188+ }
 189+ break;
 190+
 191+ case "worklocality":
 192+ $value = current($field->getContent()); // save only the first
 193+ if ($value !== false) {
 194+ $worklocality = $value->getShortWikiText();
 195+ $workaddress = true;
 196+ }
 197+ break;
 198+
 199+ case "workregion":
 200+ $value = current($field->getContent()); // save only the first
 201+ if ($value !== false) {
 202+ $workregion = $value->getShortWikiText();
 203+ $workaddress = true;
 204+ }
 205+ break;
 206+
 207+ case "workpostalcode":
 208+ $value = current($field->getContent()); // save only the first
 209+ if ($value !== false) {
 210+ $workpostalcode = $value->getShortWikiText();
 211+ $workaddress = true;
 212+ }
 213+ break;
 214+
 215+ case "workcountry":
 216+ $value = current($field->getContent()); // save only the first
 217+ if ($value !== false) {
 218+ $workcountry = $value->getShortWikiText();
 219+ $workaddress = true;
 220+ }
 221+ break;
 222+
 223+ case "homepostofficebox":
 224+ $value = current($field->getContent()); // save only the first
 225+ if ($value !== false) {
 226+ $homepostofficebox = $value->getShortWikiText();
 227+ $homeaddress = true;
 228+ }
 229+ break;
 230+
 231+ case "homeextendedaddress":
 232+ $value = current($field->getContent()); // save only the first
 233+ if ($value !== false) {
 234+ $homeextendedaddress = $value->getShortWikiText();
 235+ $homeaddress = true;
 236+ }
 237+ break;
 238+
 239+ case "homestreet":
 240+ $value = current($field->getContent()); // save only the first
 241+ if ($value !== false) {
 242+ $homestreet = $value->getShortWikiText();
 243+ $homeaddress = true;
 244+ }
 245+ break;
 246+
 247+ case "homelocality":
 248+ $value = current($field->getContent()); // save only the first
 249+ if ($value !== false) {
 250+ $homelocality = $value->getShortWikiText();
 251+ $homeaddress = true;
 252+ }
 253+ break;
 254+
 255+ case "homeregion":
 256+ $value = current($field->getContent()); // save only the first
 257+ if ($value !== false) {
 258+ $homeregion = $value->getShortWikiText();
 259+ $homeaddress = true;
 260+ }
 261+ break;
 262+
 263+ case "homepostalcode":
 264+ $value = current($field->getContent()); // save only the first
 265+ if ($value !== false) {
 266+ $homepostalcode = $value->getShortWikiText();
 267+ $homeaddress = true;
 268+ }
 269+ break;
 270+
 271+ case "homecountry":
 272+ $value = current($field->getContent()); // save only the first
 273+ if ($value !== false) {
 274+ $homecountry = $value->getShortWikiText();
 275+ $homeaddress = true;
 276+ }
 277+ break;
 278+
 279+ case "birthday":
 280+ if ($req->getTypeID() == "_dat") {
 281+ $value = current($field->getContent()); // save only the first
 282+ if ($value !== false) {
 283+ $birthday = $value->getXMLSchemaDate();
 284+ }
 285+ }
 286+ break;
 287+
 288+ case "homepage":
 289+ if ($req->getTypeID() == "_uri") {
 290+ $value = current($field->getContent()); // save only the first
 291+ if ($value !== false) {
 292+ $url = $value->getWikiValue();
 293+ }
 294+ }
 295+ break;
 296+ }
 297+ }
 298+ $pagetitle = $wikipage->getTitle();
 299+ if ($workaddress) $addresses[] = new SRFvCardAddress ('WORK', $workpostofficebox, $workextendedaddress, $workstreet, $worklocality, $workregion, $workpostalcode, $workcountry);
 300+ if ($homeaddress) $addresses[] = new SRFvCardAddress ('HOME', $homepostofficebox, $homeextendedaddress, $homestreet, $homelocality, $homeregion, $homepostalcode, $homecountry);
 301+ $items[] = new SRFvCardEntry($pagetitle, $prefix, $firstname, $lastname, $additionalname, $suffix, $fullname, $tels, $addresses, $emails, $birthday, $jobtitle, $role, $organization, $department, $category, $url, $note);
 302+ $row = $res->getNext();
 303+ }
 304+ foreach ($items as $item) {
 305+ $result .= $item->text();
 306+ }
 307+ } else { // just make link to vcard
 308+ if ($this->getSearchLabel($outputmode)) {
 309+ $label = $this->getSearchLabel($outputmode);
 310+ } else {
 311+ wfLoadExtensionMessages('SemanticResultFormats');
 312+ $label = wfMsgForContent('srf_vcard_link');
 313+ }
 314+ $link = $res->getQueryLink($label);
 315+ $link->setParameter('vcard','format');
 316+ if ($this->getSearchLabel(SMW_OUTPUT_WIKI) != '') {
 317+ $link->setParameter($this->getSearchLabel(SMW_OUTPUT_WIKI),'searchlabel');
 318+ }
 319+ if (array_key_exists('limit', $this->m_params)) {
 320+ $link->setParameter($this->m_params['limit'],'limit');
 321+ } else { // use a reasonable default limit
 322+ $link->setParameter(20,'limit');
 323+ }
 324+ $result .= $link->getText($outputmode,$this->mLinker);
 325+ $this->isHTML = ($outputmode == SMW_OUTPUT_HTML); // yes, our code can be viewed as HTML if requested, no more parsing needed
 326+ }
 327+ return $result;
 328+ }
 329+
 330+}
 331+
 332+/**
 333+ * Represents a single entry in an vCard
 334+ * @ingroup SemanticResultFormats
 335+ */
 336+class SRFvCardEntry {
 337+ private $uri;
 338+ private $label;
 339+ private $fullname;
 340+ private $firstname;
 341+ private $lastname;
 342+ private $additionalname;
 343+ private $prefix;
 344+ private $suffix;
 345+ private $tels = array();
 346+ private $addresses = array();
 347+ private $emails = array();
 348+ private $birthday;
 349+ private $dtstamp;
 350+ private $title;
 351+ private $role;
 352+ private $organization;
 353+ private $department;
 354+ private $category;
 355+ private $note;
 356+
 357+ /**
 358+ * Constructor for a single item in the vcard. Requires the URI of the item.
 359+ */
 360+ public function __construct(Title $t, $prefix, $firstname, $lastname, $additionalname, $suffix, $fullname, $tels, $addresses, $emails, $birthday, $jobtitle, $role, $organization, $department, $category, $url, $note) {
 361+ global $wgServer;
 362+ $this->uri = $t->getFullURL();
 363+ $this->url = $url;
 364+ // read fullname or guess it in a simple way from other names that are given
 365+ if ($fullname != '') {
 366+ $this->label = $fullname;
 367+ } elseif ($firstname . $lastname != '') {
 368+ $this->label = $firstname . (( ($firstname!='') && ($lastname!='') )?' ':'') . $lastname;
 369+ } else {
 370+ $this->label = $t->getText();
 371+ }
 372+ $this->label = SRFVCardEntry::vCardEscape($this->label);
 373+ // read firstname and lastname, or guess it from other names that are given
 374+ if ($firstname . $lastname == '') { // guessing needed
 375+ $nameparts = explode(' ', $this->label);
 376+ // Accepted forms for guessing:
 377+ // "Lastname"
 378+ // "Firstname Lastname"
 379+ // "Firstname <Additionalnames> Lastname"
 380+ $this->lastname = SRFvCardEntry::vCardEscape(array_pop($nameparts));
 381+ if (count($nameparts)>0) $this->firstname = SRFvCardEntry::vCardEscape(array_shift($nameparts));
 382+ foreach ($nameparts as $name) {
 383+ $this->additionalname .= ($this->additionalname!=''?',':'') . SRFvCardEntry::vCardEscape($name);
 384+ }
 385+ } else {
 386+ $this->firstname = SRFvCardEntry::vCardEscape($firstname);
 387+ $this->lastname = SRFvCardEntry::vCardEscape($lastname);
 388+ }
 389+ if ($additionalname != '') $this->additionalname = $additionalname; // no escape, can be a value list
 390+ // ^ overwrite above guessing in that case
 391+ $this->prefix = SRFvCardEntry::vCardEscape($prefix);
 392+ $this->suffix = SRFvCardEntry::vCardEscape($suffix);
 393+ $this->tels = $tels;
 394+ $this->addresses = $addresses;
 395+ $this->emails = $emails;
 396+ $this->birthday = $birthday;
 397+ $this->title = SRFvCardEntry::vCardEscape($jobtitle);
 398+ $this->role = SRFvCardEntry::vCardEscape($role);
 399+ $this->organization = SRFvCardEntry::vCardEscape($organization);
 400+ $this->department = SRFvCardEntry::vCardEscape($department);
 401+ $this->category = $category; // allow non-escaped "," in here for making a list of categories
 402+ $this->note = SRFvCardEntry::vCardEscape($note);
 403+
 404+ $article = new Article($t);
 405+ $this->dtstamp = $article->getTimestamp();
 406+ }
 407+
 408+
 409+ /**
 410+ * Creates the vCard output for a single item.
 411+ */
 412+ public function text() {
 413+ $text = "BEGIN:VCARD\r\n";
 414+ $text .= "VERSION:3.0\r\n";
 415+ // N and FN are required properties in vCard 3.0, we need to write something there
 416+ $text .= "N;CHARSET=UTF-8:$this->lastname;$this->firstname;$this->additionalname;$this->prefix;$this->suffix\r\n";
 417+ $text .= "FN;CHARSET=UTF-8:$this->label\r\n";
 418+ // heuristic for setting confidentiality level of vCard:
 419+ global $wgGroupPermissions;
 420+ if ( (array_key_exists('*', $wgGroupPermissions)) &&
 421+ (array_key_exists('read', $wgGroupPermissions['*'])) ) {
 422+ $public = $wgGroupPermissions['*']['read'];
 423+ } else {
 424+ $public = true;
 425+ }
 426+ $text .= ($public?'CLASS:PUBLIC':'CLASS:CONFIDENTIAL') . "\r\n";
 427+ if ($this->birthday !== "") $text .= "BDAY:$this->birthday\r\n";
 428+ if ($this->title !== "") $text .= "TITLE;CHARSET=UTF-8:$this->title\r\n";
 429+ if ($this->role !== "") $text .= "ROLE;CHARSET=UTF-8:$this->role\r\n";
 430+ if ($this->organization !== "") $text .= "ORG;CHARSET=UTF-8:$this->organization;$this->department\r\n";
 431+ if ($this->category !== "") $text .= "CATEGORIES;CHARSET=UTF-8:$this->category\r\n";
 432+ foreach ($this->emails as $entry) $text .= $entry->createVCardEmailText();
 433+ foreach ($this->addresses as $entry) $text .= $entry->createVCardAddressText();
 434+ foreach ($this->tels as $entry) $text .= $entry->createVCardTelText();
 435+ if ($this->note !== "") $text .= "NOTE;CHARSET=UTF-8:$this->note\r\n";
 436+ $text .= "SOURCE;CHARSET=UTF-8:$this->uri\r\n";
 437+ $text .= "PRODID:-////Semantic MediaWiki\r\n";
 438+ $text .= "REV:$this->dtstamp\r\n";
 439+ $text .= "URL:" . ($this->url?$this->url:$this->uri) . "\r\n";
 440+ $text .= "UID:$this->uri\r\n";
 441+ $text .= "END:VCARD\r\n";
 442+ return $text;
 443+ }
 444+
 445+ public static function vCardEscape($text) {
 446+ return str_replace(array('\\',',',':',';'), array('\\\\','\,','\:','\;'),$text);
 447+ }
 448+
 449+}
 450+
 451+/**
 452+ * Represents a single address entry in an vCard entry.
 453+ * @ingroup SemanticResultFormats
 454+ */
 455+class SRFvCardAddress{
 456+ private $type;
 457+ private $postofficebox;
 458+ private $extendedaddress;
 459+ private $street;
 460+ private $locality;
 461+ private $region;
 462+ private $postalcode;
 463+ private $country;
 464+
 465+ /**
 466+ * Constructor for a single address item in the vcard item.
 467+ */
 468+ public function __construct($type, $postofficebox, $extendedaddress, $street, $locality, $region, $postalcode, $country) {
 469+ $this->type = $type;
 470+ $this->postofficebox = SRFvCardEntry::vCardEscape($postofficebox);
 471+ $this->extendedaddress = SRFvCardEntry::vCardEscape($extendedaddress);
 472+ $this->street = SRFvCardEntry::vCardEscape($street);
 473+ $this->locality = SRFvCardEntry::vCardEscape($locality);
 474+ $this->region = SRFvCardEntry::vCardEscape($region);
 475+ $this->postalcode = SRFvCardEntry::vCardEscape($postalcode);
 476+ $this->country = SRFvCardEntry::vCardEscape($country);
 477+ }
 478+
 479+ /**
 480+ * Creates the vCard output for a single address item.
 481+ */
 482+ public function createVCardAddressText(){
 483+ if ($this->type == "") $this->type="work";
 484+ $text = "ADR;TYPE=$this->type;CHARSET=UTF-8:$this->postofficebox;$this->extendedaddress;$this->street;$this->locality;$this->region;$this->postalcode;$this->country\r\n";
 485+ return $text;
 486+ }
 487+}
 488+
 489+/**
 490+ * Represents a single telephone entry in an vCard entry.
 491+ * @ingroup SemanticResultFormats
 492+ */
 493+class SRFvCardTel{
 494+ private $type;
 495+ private $telnumber;
 496+
 497+ /**
 498+ * Constructor for a single telephone item in the vcard item.
 499+ */
 500+ public function __construct($type, $telnumber) {
 501+ $this->type = $type; // may be a vCard value list using ",", no escaping
 502+ $this->telnumber = SRFvCardEntry::vCardEscape($telnumber); // escape to be sure
 503+ }
 504+
 505+ /**
 506+ * Creates the vCard output for a single telephone item.
 507+ */
 508+ public function createVCardTelText(){
 509+ if ($this->type == "") $this->type="work";
 510+ $text = "TEL;TYPE=$this->type:$this->telnumber\r\n";
 511+ return $text;
 512+ }
 513+}
 514+
 515+/**
 516+ * Represents a single email entry in an vCard entry.
 517+ * @ingroup SemanticResultFormats
 518+ */
 519+class SRFvCardEmail{
 520+ private $type;
 521+ private $emailaddress;
 522+
 523+ /**
 524+ * Constructor for a email telephone item in the vcard item.
 525+ */
 526+ public function __construct($type, $emailaddress) {
 527+ $this->type = $type;
 528+ $this->emailaddress = $emailaddress; // no escape, normally not needed anyway
 529+ }
 530+
 531+ /**
 532+ * Creates the vCard output for a single email item.
 533+ */
 534+ public function createVCardEmailText(){
 535+ if ($this->type == "") $this->type="internet";
 536+ $text = "EMAIL;TYPE=$this->type:$this->emailaddress\r\n";
 537+ return $text;
 538+ }
 539+}
Property changes on: trunk/extensions/SemanticResultFormats/vCard/SRF_vCard.php
___________________________________________________________________
Name: svn:eol-style
1540 + native
Index: trunk/extensions/SemanticResultFormats/SRF_Settings.php
@@ -16,7 +16,7 @@
1717 $wgExtensionMessagesFiles['SemanticResultFormats'] = $srfgIP . '/SRF_Messages.php';
1818 $wgExtensionFunctions[] = 'srffSetup';
1919
20 -$srfgFormats = array('calendar', 'eventline', 'timeline', 'sum', 'average', 'min', 'max');
 20+$srfgFormats = array('icalendar', 'vcard', 'calendar', 'eventline', 'timeline', 'sum', 'average', 'min', 'max');
2121
2222 function srffSetup() {
2323 global $srfgFormats, $wgExtensionCredits;
@@ -37,39 +37,49 @@
3838
3939 $class = '';
4040 $file = '';
41 - if ($format == 'graph') {
42 - $class = 'SRFGraph';
43 - $file = $srfgIP . '/GraphViz/SRF_Graph.php';
 41+ switch ($format) {
 42+ case 'timeline': case 'eventline':
 43+ $class = 'SRFTimeline';
 44+ $file = $srfgIP . '/Timeline/SRF_Timeline.php';
 45+ break;
 46+ case 'vcard':
 47+ $class = 'SRFvCard';
 48+ $file = $srfgIP . '/vCard/SRF_vCard.php';
 49+ break;
 50+ case 'icalendar':
 51+ $class = 'SRFiCalendar';
 52+ $file = $srfgIP . '/iCalendar/SRF_iCalendar.php';
 53+ break;
 54+ case 'calendar':
 55+ $class = 'SRFCalendar';
 56+ $file = $srfgIP . '/Calendar/SRF_Calendar.php';
 57+ breaK;
 58+ case 'sum': case 'average': case 'min': case 'max':
 59+ $class = 'SRFMath';
 60+ $file = $srfgIP . '/Math/SRF_Math.php';
 61+ break;
 62+ case 'exhibit':
 63+ $class = 'SRFExhibit';
 64+ $file = $srfgIP . '/Exhibit/SRF_Exhibit.php';
 65+ break;
 66+ case 'googlebar':
 67+ $class = 'SRFGoogleBar';
 68+ $file = $srfgIP . '/GoogleCharts/SRF_GoogleBar.php';
 69+ break;
 70+ case 'googlepie':
 71+ $class = 'SRFGooglePie';
 72+ $file = $srfgIP . '/GoogleCharts/SRF_GooglePie.php';
 73+ break;
 74+ case 'ploticus':
 75+ $class = 'SRFPloticus';
 76+ $file = $srfgIP . '/Ploticus/SRF_Ploticus.php';
 77+ break;
 78+ case 'graph':
 79+ $class = 'SRFGraph';
 80+ $file = $srfgIP . '/GraphViz/SRF_Graph.php';
 81+ break;
4482 }
45 - if ($format == 'googlebar') {
46 - $class = 'SRFGoogleBar';
47 - $file = $srfgIP . '/GoogleCharts/SRF_GoogleBar.php';
48 - }
49 - if ($format == 'googlepie') {
50 - $class = 'SRFGooglePie';
51 - $file = $srfgIP . '/GoogleCharts/SRF_GooglePie.php';
52 - }
53 - if ($format == 'ploticus') {
54 - $class = 'SRFPloticus';
55 - $file = $srfgIP . '/Ploticus/SRF_Ploticus.php';
56 - }
57 - if ($format == 'timeline' || $format == 'eventline') {
58 - $class = 'SRFTimeline';
59 - $file = $srfgIP . '/Timeline/SRF_Timeline.php';
60 - }
61 - if ($format == 'calendar') {
62 - $class = 'SRFCalendar';
63 - $file = $srfgIP . '/Calendar/SRF_Calendar.php';
64 - }
65 - if ($format == 'exhibit') {
66 - $class = 'SRFExhibit';
67 - $file = $srfgIP . '/Exhibit/SRF_Exhibit.php';
68 - }
69 - if ($format == 'sum' || $format == 'average' || $format == 'min' || $format == 'max') {
70 - $class = 'SRFMath';
71 - $file = $srfgIP . '/Math/SRF_Math.php';
72 - }
73 - if (($class != '') && ($file)) {
 83+ if (($class) && ($file)) {
7484 $smwgResultFormats[$format] = $class;
7585 $wgAutoloadClasses[$class] = $file;
7686 }
Index: trunk/extensions/SemanticResultFormats/INSTALL
@@ -12,17 +12,28 @@
1313
1414 require_once("$IP/extensions/SemanticResultFormats/SRF_Settings.php");
1515
16 -If nothing else is added, the following formats will be enabled: 'calendar',
17 -'timeline', 'eventline', 'sum', 'average', 'min' and 'max'. To add more
18 -formats to this list, you can add lines like:
 16+If nothing else is added, a default set of formats is enabled. These are the
 17+the formats that satisfy the following criteria:
1918
 19+* they do not require further software to be installed (besides SMW),
 20+* they do not transmit any data to external websites, not even by making client
 21+ browsers request any static external resouorces (such as an externally hosted
 22+ image file),
 23+* they are considered reasonably stable and secure.
 24+
 25+Currently, these default formats thus are:
 26+'vcard', 'icalendar', 'calendar', 'timeline', 'eventline', 'sum', 'average',
 27+'min', 'max'.
 28+
 29+To add more formats to this list, you can add lines like:
 30+
2031 $srfgFormats[] = 'googlebar';
2132
22 -...or you can override the set of formats entirely, with a call like:
 33+... or you can override the set of formats entirely, with a call like:
2334
2435 $srfgFormats = array('calendar', 'timeline');
2536
26 -...using one or more of the following values:
 37+... using one or more of the following values:
2738
2839 average, calendar, eventline, googlebar, googlepie, graph, ploticus,
2940 max, min, sum, timeline
Index: trunk/extensions/SemanticResultFormats/RELEASE-NOTES
@@ -1,25 +1,19 @@
22 For a documentation of all features, see
33 http://semantic-mediawiki.org/wiki/Semantic_Result_Formats
44
5 -== SRF 1.4.0 ==
65
7 -Released on November 26 2008.
 6+== SRF 1.4.2 ==
87
9 -This is the initial release of Semantic Result Formats. The version number
10 -was chosen in order to be aligned to the Semantic MediaWiki core distribution.
11 -SRF 1.4.0 is compatible to SMW 1.4.0 and thus equally versioned.
 8+Released on February 10 2009.
129
13 -The initial sets of Semantic Result Formats are:
14 -* calendar (written by Yaron Koren)
15 -* eventline (written by Markus Kr�tzsch and based on code by MIT's Simile group)
16 -* googlebar (written by Denny Vrandecic)
17 -* googlepie (written by Denny Vrandecic)
18 -* graph (written by Frank Dengler)
19 -* timeline (written by Markus Kr�tzsch and based on code by MIT's Simile group)
 10+* new 'ploticus' format, written by Joel Natividad
 11+* new 'exhibit' format, written by Fabian Howahl and using code from MIT CSAIL
 12+* moved existing formats 'vcard' and 'icalendar' from SMW
2013
 14+
2115 == SRF 1.4.1 ==
2216
23 -Released on December 9 2008.
 17+State of December 9 2008. No file release was issued for SRF 1.4.1.
2418
2519 The initialization of formats was changed to use the global $srfgFormats
2620 variable, instead of the srfInit() function.
@@ -30,8 +24,19 @@
3125 * max (written by Yaron Koren)
3226 * sum (written by Nathan Yergler)
3327
34 -== SRF 1.4.2 ==
3528
36 -Released on January 12 2008.
 29+== SRF 1.4.0 ==
3730
38 -The 'ploticus' format, written by Joel Natividad, was added in this version.
 31+Released on November 26 2008.
 32+
 33+This is the initial release of Semantic Result Formats. The version number
 34+was chosen in order to be aligned to the Semantic MediaWiki core distribution.
 35+SRF 1.4.0 is compatible to SMW 1.4.0 and thus equally versioned.
 36+
 37+The initial sets of Semantic Result Formats are:
 38+* calendar (written by Yaron Koren)
 39+* eventline (written by Markus Krötzsch and based on code by MIT's Simile group)
 40+* googlebar (written by Denny Vrandecic)
 41+* googlepie (written by Denny Vrandecic)
 42+* graph (written by Frank Dengler)
 43+* timeline (written by Markus Krötzsch and based on code by MIT's Simile group)
Index: trunk/extensions/SemanticResultFormats/Timeline/SRF_Timeline.php
@@ -3,10 +3,12 @@
44 * Print query results in interactive timelines.
55 * @author Markus Krötzsch
66 * @file
 7+ * @ingroup SemanticResultFormats
78 */
89
910 /**
1011 * Result printer for timeline data.
 12+ * @ingroup SemanticResultFormats
1113 */
1214 class SRFTimeline extends SMWResultPrinter {
1315
@@ -26,13 +28,13 @@
2729 $this->m_tlend = smwfNormalTitleDBKey($params['timelineend']);
2830 }
2931 if (array_key_exists('timelinesize', $params)) {
30 - $this->m_tlsize = htmlspecialchars(str_replace(';', ' ', strtolower(trim($params['timelinesize']))));
 32+ $this->m_tlsize = htmlspecialchars(str_replace(';', ' ', strtolower(trim($params['timelinesize']))));
3133 // str_replace makes sure this is only one value, not mutliple CSS fields (prevent CSS attacks)
3234 /// FIXME: this is either unsafe or redundant, since Timeline is Wiki-compatible. If the JavaScript makes user inputs to CSS then it is bad even if we block this injection path.
3335 } else {
3436 $this->m_tlsize = '300px';
3537 }
36 - if (array_key_exists('timelinebands', $params)) {
 38+ if (array_key_exists('timelinebands', $params)) {
3739 //check for band parameter, should look like "DAY,MONTH,YEAR"
3840 $this->m_tlbands = preg_split('/[,][\s]*/u',trim($params['timelinebands']));
3941 } else {
@@ -111,7 +113,7 @@
112114 $header = $pr->getText($outputmode,$this->mLinker) . ' ';
113115 }
114116 // is this a start date?
115 - if ( ($pr->getMode() == SMWPrintRequest::PRINT_PROP) &&
 117+ if ( ($pr->getMode() == SMWPrintRequest::PRINT_PROP) &&
116118 ($pr->getData()->getXSDValue() == $this->m_tlstart) ) {
117119 //FIXME: Timeline scripts should support XSD format explicitly. They
118120 //currently seem to implement iso8601 which deviates from XSD in cases.
@@ -121,7 +123,7 @@
122124 $hastime = true;
123125 }
124126 // is this the end date?
125 - if ( ($pr->getMode() == SMWPrintRequest::PRINT_PROP) &&
 127+ if ( ($pr->getMode() == SMWPrintRequest::PRINT_PROP) &&
126128 ($pr->getData()->getXSDValue() == $this->m_tlend) ) {
127129 //NOTE: We can assume $object to be an SMWDataValue in this case.
128130 $curmeta .= '<span class="smwtlend">' . $object->getXMLSchemaDate(false) . '</span>';
Index: trunk/extensions/SemanticResultFormats/SRF_Messages.php
@@ -12,17 +12,28 @@
1313 */
1414 $messages['en'] = array(
1515 // user messages
 16+ // format "calendar"
1617 'srfc_previousmonth' => 'Previous month',
1718 'srfc_nextmonth' => 'Next month',
1819 'srfc_today' => 'Today',
1920 'srfc_gotomonth' => 'Go to month',
 21+ // format "vCard"
 22+ 'srf_vcard_link' => 'vCard',
 23+ // format "iCalendar"
 24+ 'srf_icalendar_link' => 'iCalendar',
2025 );
2126
 27+$messages['qqq'] = array(
 28+ 'srf_icalendar_link' => '{{optional}}',
 29+ 'srf_vcard_link' => '{{optional}}',
 30+);
 31+
2232 /** Afrikaans (Afrikaans)
2333 * @author SPQRobin
2434 */
2535 $messages['af'] = array(
2636 'srfc_gotomonth' => 'Gaan na maand',
 37+ 'srf_icalendar_link' => 'iKalender',
2738 );
2839
2940 /** Amharic (አማርኛ)
@@ -40,6 +51,8 @@
4152 'srfc_nextmonth' => 'الشهر التالي',
4253 'srfc_today' => 'اليوم',
4354 'srfc_gotomonth' => 'اذهب إلى شهر',
 55+ 'srf_icalendar_link' => 'آي كالندر',
 56+ 'srf_vcard_link' => 'في كارد',
4457 );
4558
4659 /** Egyptian Spoken Arabic (مصرى)
@@ -50,6 +63,8 @@
5164 'srfc_nextmonth' => 'الشهر التالي',
5265 'srfc_today' => 'اليوم',
5366 'srfc_gotomonth' => 'اذهب إلى شهر',
 67+ 'srf_icalendar_link' => 'آى كالندر',
 68+ 'srf_vcard_link' => 'فى كارد',
5469 );
5570
5671 /** Bulgarian (Български)
@@ -79,6 +94,8 @@
8095 'srfc_nextmonth' => 'Nächster Monat',
8196 'srfc_today' => 'Heute',
8297 'srfc_gotomonth' => 'Gehe zu Monat',
 98+ 'srf_icalendar_link' => 'iCalendar',
 99+ 'srf_vcard_link' => 'vCard',
83100 );
84101
85102 /** Lower Sorbian (Dolnoserbski)
@@ -108,6 +125,7 @@
109126 'srfc_nextmonth' => 'Posta monato',
110127 'srfc_today' => 'Hodiaŭ',
111128 'srfc_gotomonth' => 'Iru al monato',
 129+ 'srf_icalendar_link' => 'iKalendaro',
112130 );
113131
114132 /** Spanish (Español)
@@ -155,6 +173,8 @@
156174 'srfc_nextmonth' => 'Mois suivant',
157175 'srfc_today' => "Aujourd'hui",
158176 'srfc_gotomonth' => 'Aller vers le mois',
 177+ 'srf_icalendar_link' => 'iCalendrier',
 178+ 'srf_vcard_link' => 'vCarte',
159179 );
160180
161181 /** Galician (Galego)
@@ -166,6 +186,8 @@
167187 'srfc_nextmonth' => 'Mes seguinte',
168188 'srfc_today' => 'Hoxe',
169189 'srfc_gotomonth' => 'Ir ao mes',
 190+ 'srf_icalendar_link' => 'iCalendario',
 191+ 'srf_vcard_link' => 'vTarxeta',
170192 );
171193
172194 /** Ancient Greek (Ἀρχαία ἑλληνικὴ)
@@ -212,6 +234,7 @@
213235 'srfc_nextmonth' => 'अगला महिना',
214236 'srfc_today' => 'आज़',
215237 'srfc_gotomonth' => 'महिनेपर चलें',
 238+ 'srf_icalendar_link' => 'आइकैलेंडर',
216239 );
217240
218241 /** Upper Sorbian (Hornjoserbsce)
@@ -224,6 +247,14 @@
225248 'srfc_gotomonth' => 'Dźi k měsacej',
226249 );
227250
 251+/** Haitian (Kreyòl ayisyen)
 252+ * @author Jvm
 253+ * @author Masterches
 254+ */
 255+$messages['ht'] = array(
 256+ 'srf_icalendar_link' => 'iKalandrye',
 257+);
 258+
228259 /** Hungarian (Magyar)
229260 * @author Dani
230261 */
@@ -240,6 +271,8 @@
241272 'srfc_nextmonth' => 'Mense sequente',
242273 'srfc_today' => 'Hodie',
243274 'srfc_gotomonth' => 'Ir al mense',
 275+ 'srf_icalendar_link' => 'iCalendar',
 276+ 'srf_vcard_link' => 'vCard',
244277 );
245278
246279 /** Italian (Italiano)
@@ -250,6 +283,8 @@
251284 'srfc_nextmonth' => 'Mese successivo',
252285 'srfc_today' => 'Oggi',
253286 'srfc_gotomonth' => 'Vai al mese',
 287+ 'srf_icalendar_link' => 'iCalendar',
 288+ 'srf_vcard_link' => 'vCard',
254289 );
255290
256291 /** Japanese (日本語)
@@ -270,6 +305,7 @@
271306 'srfc_nextmonth' => 'Sasi sabanjuré',
272307 'srfc_today' => 'Dina iki',
273308 'srfc_gotomonth' => 'Tumuju menyang sasi',
 309+ 'srf_icalendar_link' => 'iKalèndher',
274310 );
275311
276312 /** Khmer (ភាសាខ្មែរ)
@@ -291,6 +327,8 @@
292328 'srfc_nextmonth' => 'Jangk nohm näkßte Moohnd',
293329 'srfc_today' => 'Hück',
294330 'srfc_gotomonth' => 'Jangk noh däm Moohnd',
 331+ 'srf_icalendar_link' => '<i lang="en">iCalendar</i>',
 332+ 'srf_vcard_link' => '<i lang="en">vCard</i>',
295333 );
296334
297335 /** Luxembourgish (Lëtzebuergesch)
@@ -301,6 +339,7 @@
302340 'srfc_nextmonth' => 'Nächste Mount',
303341 'srfc_today' => 'Haut',
304342 'srfc_gotomonth' => 'Géi op de Mount',
 343+ 'srf_icalendar_link' => 'iKalenner',
305344 );
306345
307346 /** Lithuanian (Lietuvių)
@@ -321,6 +360,7 @@
322361 'srfc_nextmonth' => 'അടുത്ത മാസം',
323362 'srfc_today' => 'ഇന്ന്',
324363 'srfc_gotomonth' => 'മാസത്തിലേക്ക് പോവുക',
 364+ 'srf_icalendar_link' => 'iകലണ്ടര്‍',
325365 );
326366
327367 /** Marathi (मराठी)
@@ -331,6 +371,7 @@
332372 'srfc_nextmonth' => 'पुढचा महीना',
333373 'srfc_today' => 'आज',
334374 'srfc_gotomonth' => 'महीन्याकडे चला',
 375+ 'srf_icalendar_link' => 'इ-कैलेंडर',
335376 );
336377
337378 /** Erzya (Эрзянь)
@@ -361,6 +402,8 @@
362403 'srfc_nextmonth' => 'Volgende maand',
363404 'srfc_today' => 'Vandaag',
364405 'srfc_gotomonth' => 'Ga naar maand',
 406+ 'srf_icalendar_link' => 'iCalendar',
 407+ 'srf_vcard_link' => 'vCard',
365408 );
366409
367410 /** Norwegian Nynorsk (‪Norsk (nynorsk)‬)
@@ -381,6 +424,8 @@
382425 'srfc_nextmonth' => 'Neste måned',
383426 'srfc_today' => 'I dag',
384427 'srfc_gotomonth' => 'Gå til måned',
 428+ 'srf_icalendar_link' => 'iKalender',
 429+ 'srf_vcard_link' => 'vCard',
385430 );
386431
387432 /** Occitan (Occitan)
@@ -391,6 +436,8 @@
392437 'srfc_nextmonth' => 'Mes seguent',
393438 'srfc_today' => 'Uèi',
394439 'srfc_gotomonth' => 'Anar cap al mes',
 440+ 'srf_icalendar_link' => 'iCalendièr',
 441+ 'srf_vcard_link' => 'vCarta',
395442 );
396443
397444 /** Polish (Polski)
@@ -421,6 +468,8 @@
422469 'srfc_nextmonth' => 'Mês seguinte',
423470 'srfc_today' => 'Hoje',
424471 'srfc_gotomonth' => 'Ir para mês',
 472+ 'srf_icalendar_link' => 'iCalendário',
 473+ 'srf_vcard_link' => 'vCard',
425474 );
426475
427476 /** Brazilian Portuguese (Português do Brasil)
@@ -460,6 +509,8 @@
461510 'srfc_nextmonth' => 'Следующий месяц',
462511 'srfc_today' => 'Сегодня',
463512 'srfc_gotomonth' => 'Перейти к месяцу',
 513+ 'srf_icalendar_link' => 'iКалендарь',
 514+ 'srf_vcard_link' => 'vCard',
464515 );
465516
466517 /** Slovak (Slovenčina)
@@ -470,6 +521,8 @@
471522 'srfc_nextmonth' => 'Ďalší mesiac',
472523 'srfc_today' => 'Dnes',
473524 'srfc_gotomonth' => 'Prejsť na mesiac',
 525+ 'srf_icalendar_link' => 'iCalendar',
 526+ 'srf_vcard_link' => 'vCard',
474527 );
475528
476529 /** Swedish (Svenska)
@@ -480,6 +533,8 @@
481534 'srfc_nextmonth' => 'Nästa månad',
482535 'srfc_today' => 'Idag',
483536 'srfc_gotomonth' => 'Gå till månad',
 537+ 'srf_icalendar_link' => 'iKalender',
 538+ 'srf_vcard_link' => 'vCard',
484539 );
485540
486541 /** Telugu (తెలుగు)
@@ -531,6 +586,7 @@
532587 'srfc_nextmonth' => 'Tháng sau',
533588 'srfc_today' => 'Hôm nay',
534589 'srfc_gotomonth' => 'Đến tháng',
 590+ 'srf_icalendar_link' => 'iCalendar',
535591 );
536592
537593 /** Volapük (Volapük)

Follow-up revisions

RevisionCommit summaryAuthorDate
r47087Follow up r47080/r47081: Remove translations which are identical to 'en'...raymond14:33, 10 February 2009

Status & tagging log