diff --git a/calendar.php b/calendar.php
index a24f353..242fcc0 100644
--- a/calendar.php
+++ b/calendar.php
@@ -1975,8 +1975,8 @@ class calendar extends rcube_plugin
private function write_preprocess(&$event, $action)
{
// convert dates into DateTime objects in user's current timezone
- $event['start'] = new DateTime($event['start'], $this->timezone);
- $event['end'] = new DateTime($event['end'], $this->timezone);
+ $event['start'] = new DateTime($event['start'], $this->timezone);
+ $event['end'] = new DateTime($event['end'], $this->timezone);
$event['allday'] = (bool)$event['allday'];
// start/end is all we need for 'move' action (#1480)
@@ -2026,7 +2026,7 @@ class calendar extends rcube_plugin
foreach ((array)$event['attendees'] as $i => $attendee) {
if ($attendee['role'] == 'ORGANIZER')
$organizer = $i;
- if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails))
+ if ($attendee['email'] == in_array(strtolower($attendee['email']), $emails))
$owner = $i;
if (!isset($attendee['rsvp']))
$event['attendees'][$i]['rsvp'] = true;
@@ -2189,7 +2189,6 @@ class calendar extends rcube_plugin
// if the backend has free-busy information
$fblist = $this->driver->get_freebusy_list($email, $start, $end);
-
if (is_array($fblist)) {
$status = 'FREE';
@@ -2239,26 +2238,13 @@ class calendar extends rcube_plugin
$dts = new DateTime('@'.$start);
$dts->setTimezone($this->timezone);
}
-
+
$fblist = $this->driver->get_freebusy_list($email, $start, $end);
- $slots = '';
-
- // prepare freebusy list before use (for better performance)
- if (is_array($fblist)) {
- foreach ($fblist as $idx => $slot) {
- list($from, $to, ) = $slot;
-
- // check for possible all-day times
- if (gmdate('His', $from) == '000000' && gmdate('His', $to) == '235959') {
- // shift into the user's timezone for sane matching
- $fblist[$idx][0] -= $this->gmt_offset;
- $fblist[$idx][1] -= $this->gmt_offset;
- }
- }
- }
-
+ $slots = array();
+
// build a list from $start till $end with blocks representing the fb-status
for ($s = 0, $t = $start; $t <= $end; $s++) {
+ $status = self::FREEBUSY_UNKNOWN;
$t_end = $t + $interval * 60;
$dt = new DateTime('@'.$t);
$dt->setTimezone($this->timezone);
@@ -2266,10 +2252,16 @@ class calendar extends rcube_plugin
// determine attendee's status
if (is_array($fblist)) {
$status = self::FREEBUSY_FREE;
-
foreach ($fblist as $slot) {
list($from, $to, $type) = $slot;
+ // check for possible all-day times
+ if (gmdate('His', $from) == '000000' && gmdate('His', $to) == '235959') {
+ // shift into the user's timezone for sane matching
+ $from -= $this->gmt_offset;
+ $to -= $this->gmt_offset;
+ }
+
if ($from < $t_end && $to > $t) {
$status = isset($type) ? $type : self::FREEBUSY_BUSY;
if ($status == self::FREEBUSY_BUSY) // can't get any worse :-)
@@ -2277,12 +2269,9 @@ class calendar extends rcube_plugin
}
}
}
- else {
- $status = self::FREEBUSY_UNKNOWN;
- }
-
- // use most compact format, assume $status is one digit/character
- $slots .= $status;
+
+ $slots[$s] = $status;
+ $times[$s] = $dt->format($strformat);
$t = $t_end;
}
@@ -2298,6 +2287,7 @@ class calendar extends rcube_plugin
'end' => $dte->format('c'),
'interval' => $interval,
'slots' => $slots,
+ 'times' => $times,
));
exit;
}
diff --git a/calendar_ui.js b/calendar_ui.js
index 5e34d86..8db9b2e 100644
--- a/calendar_ui.js
+++ b/calendar_ui.js
@@ -1242,7 +1242,7 @@ function rcube_calendar_ui(settings)
freebusy_data = { required:{}, all:{} };
freebusy_ui.loading = 1; // prevent render_freebusy_grid() to load data yet
freebusy_ui.numdays = Math.max(allday.checked ? 14 : 1, Math.ceil(duration * 2 / 86400));
- freebusy_ui.interval = allday.checked ? 1440 : (60 / (settings.timeslots || 1));
+ freebusy_ui.interval = allday.checked ? 1440 : 60;
freebusy_ui.start = fb_start;
freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays);
render_freebusy_grid(0);
@@ -1349,7 +1349,7 @@ function rcube_calendar_ui(settings)
// adjust dialog size to fit grid without scrolling
var gridw = $('#schedule-freebusy-times').width();
- var overflow = gridw - $('#attendees-freebusy-table td.times').width();
+ var overflow = gridw - $('#attendees-freebusy-table td.times').width() + 1;
me.dialog_resize($dialog.get(0), $dialog.height() + (bw.ie ? 20 : 0), 800 + Math.max(0, overflow));
// fetch data from server
@@ -1379,12 +1379,10 @@ function rcube_calendar_ui(settings)
var lastdate, datestr, css,
curdate = new Date(),
allday = (freebusy_ui.interval == 1440),
- interval = allday ? 1440 : (freebusy_ui.interval * (settings.timeslots || 1));
times_css = (allday ? 'allday ' : ''),
dates_row = '
').attr(attr));
-
- // also update total row if all data was loaded
- if (!freebusy_ui.loading && freebusy_data.all[ts] && all_cell) {
- var all_status = freebusy_data.all[ts][2] ? 'busy' : 'unknown',
- req_status = freebusy_data.required[ts][2] ? 'busy' : 'free';
-
- for (j=1; j < status_classes.length; j++) {
- if (freebusy_ui.numrequired && freebusy_data.required[ts][j] >= freebusy_ui.numrequired)
- req_status = status_classes[j];
- if (freebusy_data.all[ts][j] == event_attendees.length)
- all_status = status_classes[j];
- }
-
- attr['class'] = req_status + ' all-' + all_status;
-
- // these elements use some specific styling, so we want to minimize their number
- if (last && last.attr('class') == attr['class'])
- last.css('width', (percent + parseFloat(last.css('width').replace('%', ''))).toFixed(2) + '%');
- else {
- last = $('
').attr(attr);
- all_slots.push(last);
- }
+ // also update total row if all data was loaded
+ if (freebusy_ui.loading == 0 && freebusy_data.all[ts] && (cell = rowall.get(i))) {
+ var workinghours = cell.className.indexOf('workinghours') >= 0;
+ var all_status = freebusy_data.all[ts][2] ? 'busy' : 'unknown';
+ req_status = freebusy_data.required[ts][2] ? 'busy' : 'free';
+ for (var j=1; j < status_classes.length; j++) {
+ if (freebusy_ui.numrequired && freebusy_data.required[ts][j] >= freebusy_ui.numrequired)
+ req_status = status_classes[j];
+ if (freebusy_data.all[ts][j] == event_attendees.length)
+ all_status = status_classes[j];
}
-
- t += freebusy_ui.interval * 60000;
+
+ cell.className = (workinghours ? 'workinghours ' : 'offhours ') + req_status + ' all-' + all_status;
}
-
- $(cell).html('').append(slots);
- if (all_slots.length)
- $(all_cell).html('').append(all_slots);
+
+ t += freebusy_ui.interval * 60000;
});
}
};
@@ -1749,20 +1716,17 @@ function rcube_calendar_ui(settings)
sinterval = freebusy_data.interval * 60000,
intvlslots = 1,
numslots = Math.ceil(duration / sinterval),
- fb_start = freebusy_data.start.getTime(),
- fb_end = freebusy_data.end.getTime(),
- checkdate, slotend, email, ts, slot, slotdate = new Date(),
- candidatecount = 0, candidatestart = false, success = false;
+ checkdate, slotend, email, ts, slot, slotdate = new Date();
// shift event times to next possible slot
eventstart += sinterval * intvlslots * dir;
eventend += sinterval * intvlslots * dir;
// iterate through free-busy slots and find candidates
- for (slot = dir > 0 ? fb_start : fb_end - sinterval;
- (dir > 0 && slot < fb_end) || (dir < 0 && slot >= fb_start);
- slot += sinterval * dir
- ) {
+ var candidatecount = 0, candidatestart = candidateend = success = false;
+ for (slot = dir > 0 ? freebusy_data.start.getTime() : freebusy_data.end.getTime() - sinterval;
+ (dir > 0 && slot < freebusy_data.end.getTime()) || (dir < 0 && slot >= freebusy_data.start.getTime());
+ slot += sinterval * dir) {
slotdate.setTime(slot);
// fix slot if just crossed a DST change
if (event.allDay) {
@@ -1774,10 +1738,10 @@ function rcube_calendar_ui(settings)
if ((dir > 0 && slotend <= eventstart) || (dir < 0 && slot >= eventend)) // skip
continue;
- // respect workinghours setting
+ // respect workingours setting
if (freebusy_ui.workinhoursonly) {
if (is_weekend(slotdate) || (freebusy_data.interval <= 60 && !is_workinghour(slotdate))) { // skip off-hours
- candidatestart = false;
+ candidatestart = candidateend = false;
candidatecount = 0;
continue;
}
@@ -1786,12 +1750,11 @@ function rcube_calendar_ui(settings)
if (!candidatestart)
candidatestart = slot;
- ts = date2timestring(slotdate, freebusy_data.interval > 60);
-
// check freebusy data for all attendees
+ ts = date2timestring(slotdate, freebusy_data.interval > 60);
for (var i=0; i < event_attendees.length; i++) {
if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT' && (email = freebusy_ui.attendees[i].email) && freebusy_data[email] && freebusy_data[email][ts] > 1) {
- candidatestart = false;
+ candidatestart = candidateend = false;
break;
}
}
@@ -1802,15 +1765,22 @@ function rcube_calendar_ui(settings)
candidatecount = 0;
continue;
}
- else if (dir < 0)
- candidatestart = slot;
+ // set candidate end to slot end time
candidatecount++;
+ if (dir < 0 && !candidateend)
+ candidateend = slotend;
// if candidate is big enough, this is it!
if (candidatecount == numslots) {
- event.start.setTime(candidatestart);
- event.end.setTime(candidatestart + duration);
+ if (dir > 0) {
+ event.start.setTime(candidatestart);
+ event.end.setTime(candidatestart + duration);
+ }
+ else {
+ event.end.setTime(candidateend);
+ event.start.setTime(candidateend - duration);
+ }
success = true;
break;
}
@@ -1840,6 +1810,7 @@ function rcube_calendar_ui(settings)
}
};
+
// update event properties and attendees availability if event times have changed
var event_times_changed = function()
{
@@ -1854,6 +1825,7 @@ function rcube_calendar_ui(settings)
}
};
+
// add the given list of participants
var add_attendees = function(names, params)
{
diff --git a/drivers/kolab/kolab_calendar.php b/drivers/kolab/kolab_calendar.php
index fe2ede5..107a764 100644
--- a/drivers/kolab/kolab_calendar.php
+++ b/drivers/kolab/kolab_calendar.php
@@ -763,25 +763,11 @@ class kolab_calendar extends kolab_storage_folder_api
private function _from_driver_event($event, $old = array())
{
// set current user as ORGANIZER
- if ($identity = $this->cal->rc->user->list_emails(true)) {
- $event['attendees'] = (array) $event['attendees'];
- $found = false;
+ $identity = $this->cal->rc->user->list_emails(true);
+ if (empty($event['attendees']) && $identity['email'])
+ $event['attendees'] = array(array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email']));
- // there can be only resources on attendees list (T1484)
- // let's check the existence of an organizer
- foreach ($event['attendees'] as $attendee) {
- if ($attendee['role'] == 'ORGANIZER') {
- $found = true;
- break;
- }
- }
-
- if (!$found) {
- $event['attendees'][] = array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email']);
- }
-
- $event['_owner'] = $identity['email'];
- }
+ $event['_owner'] = $identity['email'];
// remove EXDATE values if RDATE is given
if (!empty($event['recurrence']['RDATE'])) {
@@ -806,6 +792,7 @@ class kolab_calendar extends kolab_storage_folder_api
});
}
+
// remove some internal properties which should not be saved
unset($event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_folder_id'],
$event['recurrence_id'], $event['attachments'], $event['deleted_attachments'], $event['className']);
diff --git a/localization/da_DK.inc b/localization/da_DK.inc
index 4e70bf6..45dd35d 100644
--- a/localization/da_DK.inc
+++ b/localization/da_DK.inc
@@ -1,4 +1,5 @@
CalDAV-klientprogram (eks. Evolution eller Mozilla Thunderbird) for at synkronisere denne kalender komplet med din computer eller mobilenhed.';
$labels['findcalendars'] = 'Find kalendere ...';
-$labels['searchterms'] = 'Search terms';
+$labels['searchterms'] = 'Søgetermer';
$labels['calsearchresults'] = 'Tilgængelige kalendere';
-$labels['calendarsubscribe'] = 'List permanently';
+$labels['calendarsubscribe'] = 'List permanent';
$labels['nocalendarsfound'] = 'Der blev ikke fundet nogen kalender';
$labels['nrcalendarsfound'] = '$nr kalendere blev fundet';
$labels['quickview'] = 'Vis kun denne kalender';
@@ -115,6 +122,8 @@ $labels['invitationspending'] = 'Afventende invitationer';
$labels['invitationsdeclined'] = 'Afviste invitationer';
$labels['changepartstat'] = 'Skift deltagerstatus';
$labels['rsvpcomment'] = 'Invitationstekst';
+
+// agenda view
$labels['listrange'] = 'Interval som skal vises:';
$labels['listsections'] = 'Del op i:';
$labels['smartsections'] = 'Smarte sektioner';
@@ -129,9 +138,13 @@ $labels['nextmonth'] = 'Næste måned';
$labels['weekofyear'] = 'Uge';
$labels['pastevents'] = 'Tidligere';
$labels['futureevents'] = 'Fremtid';
-$labels['showalarms'] = 'Show reminders';
+
+// alarm/reminder settings
+$labels['showalarms'] = 'Vis påmindelser';
$labels['defaultalarmtype'] = 'Standardindstilling for påmindelse';
$labels['defaultalarmoffset'] = 'Standardtidspunkt for påmindelse';
+
+// attendees
$labels['attendee'] = 'Deltager';
$labels['role'] = 'Rolle';
$labels['availability'] = 'Tilg.';
@@ -151,8 +164,8 @@ $labels['availbusy'] = 'Optaget';
$labels['availunknown'] = 'Ukendt';
$labels['availtentative'] = 'Forsøgsvis';
$labels['availoutofoffice'] = 'Ikke på kontoret';
-$labels['delegatedto'] = 'Delegated to: ';
-$labels['delegatedfrom'] = 'Delegated from: ';
+$labels['delegatedto'] = 'Delegere til:';
+$labels['delegatedfrom'] = 'Delegere fra:';
$labels['scheduletime'] = 'Find ledigt tidspunkt';
$labels['sendinvitations'] = 'Send invitationer';
$labels['sendnotifications'] = 'Gør deltagere opmærksom på ændringer';
@@ -169,18 +182,24 @@ $labels['invitationattendlinks'] = "Hvis dit e-postprogram ikke understøtter iT
$labels['eventupdatesubject'] = '"$title" er blevet opdateret';
$labels['eventupdatesubjectempty'] = 'Et arrangement der vedrører dig er blevet opdateret';
$labels['eventupdatemailbody'] = "*\$title*\n\nTidspunkt: \$date\n\nInviterede: \$attendees\n\nBemærk venligst vedhæftede iCalendar-fil med alle detaljer om arrangementet, som du kan importere til dit kalenderprogram.";
+$labels['eventcancelsubject'] = '"$title" er blevet annulleret';
$labels['eventcancelmailbody'] = "*\$title*\n\nTidspunkt: \$date\n\nInviterede: \$attendees\n\nDette arrangement er blevet aflyst af \$organizer.\n\nBemærk venligst vedhæftede iCalendard-fil med de opdaterede detaljer om arrangementet.";
+
+// invitation handling (overrides labels from libcalendaring)
$labels['itipobjectnotfound'] = 'Begivenheden som denne besked henviser til, blev ikke fundet i din kalender.';
+
$labels['itipmailbodyaccepted'] = "\$sender har accepteret invitationen til det følgende arrangement:\n\n*\$title*\n\nTidspunkt: \$date\n\nInviterede: \$attendees";
$labels['itipmailbodytentative'] = "\$sender har forsøgsvist accepteret invitationen til det følgende arrangement:\n\n*\$title*\n\nTidspunkt: \$date\n\nInviterede: \$attendees";
$labels['itipmailbodydeclined'] = "\$sender har afvist invitationen til det følgende arrangement:\n\n*\$title*\n\nTidspunkt: \$date\n\nInviterede: \$attendees";
$labels['itipmailbodycancel'] = "\$sender har afvist din deltagelse i følgende begivenhed:\n\n*\$title*\n\nTidspunkt: \$date";
$labels['itipmailbodydelegated'] = "\$sender har delegeret deltagelsen i følgende begivenhed:\n\n*\$title*\n\nTidspunkt: \$date";
$labels['itipmailbodydelegatedto'] = "\$sender har delegeret deltagelsen i følgende begivenhed til dig:\n\n*\$title*\n\nTidspunkt: \$date";
+
$labels['itipdeclineevent'] = 'Sikker på at du vil afvise dette arrangement?';
$labels['declinedeleteconfirm'] = 'Vil du også slette dette afviste arrangement fra din kalender?';
$labels['itipcomment'] = 'Invitation/notification comment';
$labels['itipcommenttitle'] = 'Denne kommentar vil blive føjet til den besked med invitation/notifikation, der sendes til deltagerne';
+
$labels['notanattendee'] = 'Du er ikke opført som deltager for dette arrangement';
$labels['eventcancelled'] = 'Arrangementet er blevet aflyst';
$labels['saveincalendar'] = 'gem i';
@@ -189,6 +208,8 @@ $labels['savetocalendar'] = 'Gem til kalender';
$labels['openpreview'] = 'Tjek kalender';
$labels['noearlierevents'] = 'Ingen tidligere begivenheder';
$labels['nolaterevents'] = 'Ingen senere begivenheder';
+
+// resources
$labels['resource'] = 'Ressource';
$labels['addresource'] = 'Booking af ressource';
$labels['findresources'] = 'Find ressourcer';
@@ -196,12 +217,16 @@ $labels['resourcedetails'] = 'Detaljer';
$labels['resourceavailability'] = 'Tilgængelighed';
$labels['resourceowner'] = 'Ejer';
$labels['resourceadded'] = 'Ressourcen til føjet til din begivenhed';
+
+// event dialog tabs
$labels['tabsummary'] = 'Resumé';
$labels['tabrecurrence'] = 'Gentagelse';
$labels['tabattendees'] = 'Deltagere';
$labels['tabresources'] = 'Ressourcer';
$labels['tabattachments'] = 'Vedhæftninger';
$labels['tabsharing'] = 'Deling';
+
+// messages
$labels['deleteobjectconfirm'] = 'Sikker på at du vil slette dette arrangement?';
$labels['deleteventconfirm'] = 'Sikker på at du vil slette dette arrangement?';
$labels['deletecalendarconfirm'] = 'Sikker på at du vil slette denne kalender med alle dets arrangementer?';
@@ -231,6 +256,7 @@ $labels['importsuccess'] = 'Gennemførte import af $nr arrangementer';
$labels['importnone'] = 'Fandt ingen arrangementer som kunne importeres';
$labels['importerror'] = 'Der opstod en fejl under import';
$labels['aclnorights'] = 'Du har ikke administratorrettigheder for denne kalender.';
+
$labels['changeeventconfirm'] = 'Tilpas arrangement';
$labels['removeeventconfirm'] = 'Slet begivenhed';
$labels['changerecurringeventwarning'] = 'Dette er et tilbagevendende arrangement. Ønsker du kun at redige det aktuelle arrangement, dette og alle fremtidige forekomster, alle forekomster eller gemme det som et nyt arrangement?';
@@ -240,12 +266,16 @@ $labels['currentevent'] = 'Nuværende';
$labels['futurevents'] = 'Fremtid';
$labels['allevents'] = 'Alle';
$labels['saveasnew'] = 'Gem som ny';
+
+// birthdays calendar
$labels['birthdays'] = 'Fødselsdage';
$labels['birthdayscalendar'] = 'Fødselsdagskalender';
$labels['displaybirthdayscalendar'] = 'Vis fødselsdagskalender';
$labels['birthdayscalendarsources'] = 'Fra disse adressebøger';
$labels['birthdayeventtitle'] = '$name har fødselsdag';
$labels['birthdayage'] = '$age år';
+
+// history dialog
$labels['objectchangelog'] = 'Ændringshistorik';
$labels['objectdiff'] = 'Ændringer fra $rev1 til $rev2';
$labels['objectnotfound'] = 'Kunne ikke indlæse begivenhedsdata';
@@ -254,6 +284,9 @@ $labels['objectdiffnotavailable'] = 'Det er ikke muligt at sammenligne de valgte
$labels['revisionrestoreconfirm'] = 'Sikker på at du vil genskabe revision $rev af denne begivenhed? Dette vil erstatte den nuværende begivenhed med den tidligere version.';
$labels['objectrestoresuccess'] = 'Revision $rev blev genskabt';
$labels['objectrestoreerror'] = 'Mislykkedes med at genskabe den gamle revision';
+
+
+// (hidden) titles and labels for accessibility annotations
$labels['arialabelminical'] = 'Valg af kalenderdato';
$labels['arialabelcalendarview'] = 'Kalendervisning';
$labels['arialabelsearchform'] = 'Søgeformular for begivenheder';
@@ -264,4 +297,5 @@ $labels['arialabeleventattendees'] = 'Deltagerliste for begivenhed';
$labels['arialabeleventresources'] = 'Ressourceliste for begivenhed';
$labels['arialabelresourcesearchform'] = 'Søgeformular for ressourcer';
$labels['arialabelresourceselection'] = 'Tilgængelige ressourcer';
+
?>
diff --git a/localization/de_DE.inc b/localization/de_DE.inc
index f9ff3b4..619fb09 100644
--- a/localization/de_DE.inc
+++ b/localization/de_DE.inc
@@ -1,4 +1,5 @@
CalDAV-Klienten (z.B. Evolution oder Mozilla Thunderbird) kopieren, um den Kalender in Gänze mit einem mobilen Gerät zu synchronisieren.';
-$labels['findcalendars'] = 'Kalender finden...';
+$labels['findcalendars'] = 'Kalender finden …';
$labels['searchterms'] = 'Suchbegriffe';
$labels['calsearchresults'] = 'Verfügbare Kalender';
$labels['calendarsubscribe'] = 'Permanent anzeigen';
@@ -115,6 +122,8 @@ $labels['invitationspending'] = 'Ausstehende Einladungen';
$labels['invitationsdeclined'] = 'Abgelehnte Einladungen';
$labels['changepartstat'] = 'Teilnehmerstatus ändern';
$labels['rsvpcomment'] = 'Einladungstext';
+
+// agenda view
$labels['listrange'] = 'Angezeigter Bereich:';
$labels['listsections'] = 'Unterteilung:';
$labels['smartsections'] = 'Intelligent';
@@ -129,9 +138,13 @@ $labels['nextmonth'] = 'Nächsten Monat';
$labels['weekofyear'] = 'Woche';
$labels['pastevents'] = 'Vergangene';
$labels['futureevents'] = 'Zukünftige';
+
+// alarm/reminder settings
$labels['showalarms'] = 'Erinnerungen anzeigen';
$labels['defaultalarmtype'] = 'Standard-Erinnerungseinstellung';
$labels['defaultalarmoffset'] = 'Standard-Erinnerungszeit';
+
+// attendees
$labels['attendee'] = 'Teilnehmer';
$labels['role'] = 'Rolle';
$labels['availability'] = 'Verfüg.';
@@ -163,25 +176,30 @@ $labels['prevslot'] = 'Vorheriger Vorschlag';
$labels['nextslot'] = 'Nächster Vorschlag';
$labels['suggestedslot'] = 'Empfohlener Slot';
$labels['noslotfound'] = 'Es konnten keine freien Zeiten gefunden werden';
-$labels['invitationsubject'] = 'Sie wurden zu "$title" eingeladen';
+$labels['invitationsubject'] = 'Sie wurden zu »$title« eingeladen';
$labels['invitationmailbody'] = "*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees\n\nIm Anhang finden Sie eine iCalendar-Datei mit allen Details des Termins. Diese können Sie in Ihre Kalenderanwendung importieren.";
$labels['invitationattendlinks'] = "Falls Ihr E-Mail-Programm keine iTip-Anfragen unterstützt, können Sie den folgenden Link verwenden, um den Termin zu bestätigen oder abzulehnen:\n\$url";
-$labels['eventupdatesubject'] = '"$title" wurde aktualisiert';
+$labels['eventupdatesubject'] = '»$title« wurde aktualisiert';
$labels['eventupdatesubjectempty'] = 'Termin wurde aktualisiert';
$labels['eventupdatemailbody'] = "*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees\n\nIm Anhang finden Sie eine iCalendar-Datei mit den aktualisiereten Termindaten. Diese können Sie in Ihre Kalenderanwendung importieren.";
-$labels['eventcancelsubject'] = '"$title" wurde abgesagt';
+$labels['eventcancelsubject'] = '»$title« wurde abgesagt';
$labels['eventcancelmailbody'] = "*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees\n\nDer Termin wurde von \$organizer abgesagt.\n\nIm Anhang finden Sie eine iCalendar-Datei mit den Termindaten.";
+
+// invitation handling (overrides labels from libcalendaring)
$labels['itipobjectnotfound'] = 'Der Termin auf den sich diese Nachricht bezieht, wurde in Ihrem Kalender nicht gefunden.';
+
$labels['itipmailbodyaccepted'] = "\$sender hat die Einladung zum folgenden Termin angenommen:\n\n*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees";
$labels['itipmailbodytentative'] = "\$sender hat die Einladung mit Vorbehalt zum folgenden Termin angenommen:\n\n*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees";
$labels['itipmailbodydeclined'] = "\$sender hat die Einladung zum folgenden Termin abgelehnt:\n\n*\$title*\n\nWann: \$date\n\nTeilnehmer: \$attendees";
$labels['itipmailbodycancel'] = "\$sender hat Ihre Teilnahme bei der folgenden Veranstaltung zurückgewiesen:\n\n*\$title*\n\nWann: \$date";
$labels['itipmailbodydelegated'] = "\$sender hat die Teilnahme an folgendem Event delegiert:\n\n*\$title*\n\nWhen: \$date";
$labels['itipmailbodydelegatedto'] = "\$sender hat die Teilnahme an folgendem Event an Sie delegiert:\n\n*\$title*\n\nWann: \$date";
+
$labels['itipdeclineevent'] = 'Möchten Sie die Einladung zu diesem Termin ablehnen?';
$labels['declinedeleteconfirm'] = 'Soll der abgelehnte Termin zusätzlich aus dem Kalender gelöscht werden?';
$labels['itipcomment'] = 'Kommentar zur Einladungs-/Benachrichtigungsnachricht';
$labels['itipcommenttitle'] = 'Dieser Kommentar wird an die Einladungs-/Benachrichtigungsnachricht angehängt, die an die Teilnehmer verschickt wird';
+
$labels['notanattendee'] = 'Sie sind nicht in der Liste der Teilnehmer aufgeführt';
$labels['eventcancelled'] = 'Der Termin wurde vom Organisator abgesagt';
$labels['saveincalendar'] = 'speichern in';
@@ -190,6 +208,8 @@ $labels['savetocalendar'] = 'In Kalender übernehmen';
$labels['openpreview'] = 'Kalender überprüfen';
$labels['noearlierevents'] = 'Keine früheren Ereignisse';
$labels['nolaterevents'] = 'Keine späteren Ereignisse';
+
+// resources
$labels['resource'] = 'Ressource';
$labels['addresource'] = 'Ressource buchen';
$labels['findresources'] = 'Ressourcen finden';
@@ -197,17 +217,21 @@ $labels['resourcedetails'] = 'Details';
$labels['resourceavailability'] = 'Verfügbarkeit';
$labels['resourceowner'] = 'Eigentümer';
$labels['resourceadded'] = 'Diese Ressource wurde Ihrem Termin hinzugefügt';
+
+// event dialog tabs
$labels['tabsummary'] = 'Übersicht';
$labels['tabrecurrence'] = 'Wiederholung';
$labels['tabattendees'] = 'Teilnehmer';
$labels['tabresources'] = 'Ressourcen';
$labels['tabattachments'] = 'Anhänge';
$labels['tabsharing'] = 'Freigabe';
+
+// messages
$labels['deleteobjectconfirm'] = 'Möchten Sie diesen Termin wirklich löschen?';
$labels['deleteventconfirm'] = 'Möchten Sie diesen Termin wirklich löschen?';
$labels['deletecalendarconfirm'] = 'Möchten Sie diesen Kalender mit allen Terminen wirklich löschen?';
$labels['deletecalendarconfirmrecursive'] = 'Soll dieser Kalender wirklich mit allen Terminen und Unterkalendern gelöscht werden?';
-$labels['savingdata'] = 'Speichere Daten...';
+$labels['savingdata'] = 'Daten werden gespeichert …';
$labels['errorsaving'] = 'Fehler beim Speichern.';
$labels['operationfailed'] = 'Die Aktion ist fehlgeschlagen.';
$labels['invalideventdates'] = 'Ungültige Daten eingegeben! Bitte überprüfen Sie die Eingaben.';
@@ -220,8 +244,8 @@ $labels['errorimportingevent'] = 'Fehler beim Importieren';
$labels['importwarningexists'] = 'Eine Kopie dieses Termins existiert bereits in Ihrem Kalender.';
$labels['newerversionexists'] = 'Eine neuere Version dieses Termins exisitert bereits! Import abgebrochen.';
$labels['nowritecalendarfound'] = 'Kein Kalender zum Speichern gefunden';
-$labels['importedsuccessfully'] = 'Der Termin wurde erfolgreich in \'$calendar\' gespeichert';
-$labels['updatedsuccessfully'] = 'Der Termin wurde erfolgreich in \'$calendar\' geändert';
+$labels['importedsuccessfully'] = 'Der Termin wurde erfolgreich in »$calendar« gespeichert';
+$labels['updatedsuccessfully'] = 'Der Termin wurde erfolgreich in »$calendar« geändert';
$labels['attendeupdateesuccess'] = 'Teilnehmerstatus erfolgreich aktualisiert';
$labels['itipsendsuccess'] = 'Einladung an Teilnehmer versendet.';
$labels['itipresponseerror'] = 'Die Antwort auf diese Einladung konnte nicht versendet werden';
@@ -232,6 +256,7 @@ $labels['importsuccess'] = 'Es wurden $nr Termine erfolgreich importiert';
$labels['importnone'] = 'Keine Termine zum Importieren gefunden';
$labels['importerror'] = 'Fehler beim Importieren';
$labels['aclnorights'] = 'Der Zugriff auf diesen Kalender erfordert Administrator-Rechte.';
+
$labels['changeeventconfirm'] = 'Termin ändern';
$labels['removeeventconfirm'] = 'Termin löschen';
$labels['changerecurringeventwarning'] = 'Dies ist eine Terminreihe. Möchten Sie nur den aktuellen, diesen und alle zukünftigen oder alle Termine bearbeiten oder die Änderungen als neuen Termin speichern?';
@@ -241,13 +266,17 @@ $labels['currentevent'] = 'Aktuellen';
$labels['futurevents'] = 'Zukünftige';
$labels['allevents'] = 'Alle';
$labels['saveasnew'] = 'Als neu speichern';
+
+// birthdays calendar
$labels['birthdays'] = 'Geburtstage';
-$labels['birthdayscalendar'] = 'Geburtstags-Kalender';
-$labels['displaybirthdayscalendar'] = 'Geburtstags-Kalender anzeigen';
+$labels['birthdayscalendar'] = 'Geburtstagskalender';
+$labels['displaybirthdayscalendar'] = 'Geburtstagskalender anzeigen';
$labels['birthdayscalendarsources'] = 'Für diese Adressbücher';
$labels['birthdayeventtitle'] = '$names Geburtstag';
$labels['birthdayage'] = 'Alter $age';
-$labels['objectchangelog'] = 'Änderungshistorie';
+
+// history dialog
+$labels['objectchangelog'] = 'Änderungsverlauf';
$labels['objectdiff'] = 'Änderungen aus $rev1 nach $rev2';
$labels['objectnotfound'] = 'Termindaten sind leider nicht vergübar';
$labels['objectchangelognotavailable'] = 'Änderungshistorie ist nicht verfügbar für diesen Termin';
@@ -255,6 +284,9 @@ $labels['objectdiffnotavailable'] = 'Vergleich für die gewählten Versionen nic
$labels['revisionrestoreconfirm'] = 'Wollen Sie wirklich die Version $rev dieses Termins wiederherstellen? Diese Aktion wird die aktuelle Kopie mit der älteren Version ersetzen.';
$labels['objectrestoresuccess'] = 'Revision $rev erfolgreich wiederhergestellt';
$labels['objectrestoreerror'] = 'Fehler beim Wiederherstellen der alten Revision';
+
+
+// (hidden) titles and labels for accessibility annotations
$labels['arialabelminical'] = 'Kalender Datumswahl';
$labels['arialabelcalendarview'] = 'Kalender Ansicht';
$labels['arialabelsearchform'] = 'Suchformular für Termine';
@@ -265,4 +297,5 @@ $labels['arialabeleventattendees'] = 'Teilehmerliste';
$labels['arialabeleventresources'] = 'Liste der Terminressourcen';
$labels['arialabelresourcesearchform'] = 'Suchformular für Ressourcen';
$labels['arialabelresourceselection'] = 'Verfügbare Ressourcen';
+
?>
diff --git a/localization/ru_RU.inc b/localization/ru_RU.inc
index 716af10..cce82d6 100644
--- a/localization/ru_RU.inc
+++ b/localization/ru_RU.inc
@@ -1,4 +1,5 @@
diff --git a/skins/larry/calendar.css b/skins/larry/calendar.css
index 4a035cb..71b2575 100644
--- a/skins/larry/calendar.css
+++ b/skins/larry/calendar.css
@@ -115,7 +115,6 @@ body.calendarmain #mainscreen {
width: 6px;
top: 40px !important;
bottom: 0;
- height: auto;
background: url(images/toggle.gif) -1px 48% no-repeat transparent;
}
@@ -1247,44 +1246,44 @@ td.topalign {
background: url(images/loading_blue.gif) center no-repeat;
}
-#schedule-freebusy-times td div.unknown,
+#schedule-freebusy-times td.unknown,
.availability img.availabilityicon.unknown {
background: #ddd;
}
-#schedule-freebusy-times td div.free,
+#schedule-freebusy-times td.free,
.availability img.availabilityicon.free {
background: #abd640;
}
-#schedule-freebusy-times td div.busy,
+#schedule-freebusy-times td.busy,
.availability img.availabilityicon.busy {
background: #e26569;
}
-#schedule-freebusy-times td div.tentative,
+#schedule-freebusy-times td.tentative,
.availability img.availabilityicon.tentative {
background: #8383fc;
}
-#schedule-freebusy-times td div.out-of-office,
+#schedule-freebusy-times td.out-of-office,
.availability img.availabilityicon.out-of-office {
background: #fbaa68;
}
-#schedule-freebusy-times td div.all-busy,
-#schedule-freebusy-times td div.all-tentative,
-#schedule-freebusy-times td div.all-out-of-office {
+#schedule-freebusy-times td.all-busy,
+#schedule-freebusy-times td.all-tentative,
+#schedule-freebusy-times td.all-out-of-office {
background-image: url(images/freebusy-colors.png);
background-position: top right;
background-repeat: no-repeat;
}
-#schedule-freebusy-times td div.all-tentative {
+#schedule-freebusy-times td.all-tentative {
background-position: right -40px;
}
-#schedule-freebusy-times td div.all-out-of-office {
+#schedule-freebusy-times td.all-out-of-office {
background-position: right -80px;
}
@@ -1412,8 +1411,7 @@ td.topalign {
.attendees-list .spacer,
#schedule-freebusy-times tr.spacer td {
background: 0;
- padding: 0;
- height: 10px;
+ font-size: 50%;
}
#schedule-freebusy-times {
@@ -1426,15 +1424,6 @@ td.topalign {
border: 1px solid #ccc;
}
-#schedule-freebusy-times tbody td {
- padding: 0;
- height: 20px;
-}
-
-#schedule-freebusy-times tbody td div {
- height: 100%;
-}
-
#attendees-freebusy-table div.timesheader,
#schedule-freebusy-times tr.times td {
min-width: 30px;
@@ -1452,10 +1441,6 @@ td.topalign {
cursor: pointer;
}
-#schedule-freebusy-times #fbrowall td {
- border-bottom: none;
-}
-
#schedule-event-time {
position: absolute;
border: 2px solid #333;