New method to display meeting-requests for fmail and allow to (tentativ) accept or reject them

This commit is contained in:
Ralf Becker 2011-05-27 20:32:46 +00:00
parent e2cd10a286
commit 145cf9ce68
6 changed files with 211 additions and 30 deletions

View File

@ -1417,11 +1417,13 @@ class calendar_bo
* *
* @param string|int $id id of user or resource * @param string|int $id id of user or resource
* @param string|boolean $use_type=false type-letter or false * @param string|boolean $use_type=false type-letter or false
* @param boolean $append_email=false append email (Name <email>)
* @return string with name * @return string with name
*/ */
function participant_name($id,$use_type=false) function participant_name($id,$use_type=false, $append_email=false)
{ {
static $id2lid = array(); static $id2lid = array();
static $id2email = array();
if ($use_type && $use_type != 'u') $id = $use_type.$id; if ($use_type && $use_type != 'u') $id = $use_type.$id;
@ -1433,14 +1435,16 @@ class calendar_bo
if (($info = $this->resource_info($id))) if (($info = $this->resource_info($id)))
{ {
$id2lid[$id] = $info['name'] ? $info['name'] : $info['email']; $id2lid[$id] = $info['name'] ? $info['name'] : $info['email'];
if ($info['name']) $id2email[$id] = $info['email'];
} }
} }
else else
{ {
$id2lid[$id] = common::grab_owner_name($id); $id2lid[$id] = common::grab_owner_name($id);
$id2email[$id] = $GLOBALS['egw']->accounts->id2name($id,'account_email');
} }
} }
return $id2lid[$id]; return $id2lid[$id].($append_email && $id2email[$id] ? ' <'.$id2email[$id].'>' : '');
} }
/** /**

View File

@ -683,8 +683,15 @@ class calendar_boupdate extends calendar_bo
if ($old_event != False) $olddate = new egw_time($old_event['start']); if ($old_event != False) $olddate = new egw_time($old_event['start']);
foreach($to_notify as $userid => $statusid) foreach($to_notify as $userid => $statusid)
{ {
if ($this->debug > 0) error_log(__METHOD__." trying to notify $userid, with $statusid"); calendar_so::split_status($statusid, $quantity, $role);
if (!is_numeric($userid)) if ($this->debug > 0) error_log(__METHOD__." trying to notify $userid, with $statusid ($role)");
if (!is_numeric($userid) && $userid[0] == 'e')
{
if ($role != 'CHAIR' || $msg_type == MSG_ALARM) continue; // only notify "external" chairs, but not for alarms
$userid = substr($userid,1);
}
elseif (!is_numeric($userid))
{ {
$res_info = $this->resource_info($userid); $res_info = $this->resource_info($userid);
$userid = $res_info['responsible']; $userid = $res_info['responsible'];
@ -701,16 +708,24 @@ class calendar_boupdate extends calendar_bo
$user_prefs['calendar']['receive_own_updates']==1) || $user_prefs['calendar']['receive_own_updates']==1) ||
$msg_type == MSG_ALARM) $msg_type == MSG_ALARM)
{ {
$preferences = CreateObject('phpgwapi.preferences',$userid); if (is_numeric($userid))
$part_prefs = $preferences->read_repository();
if (!$this->update_requested($userid,$part_prefs,$msg_type,$old_event,$new_event))
{ {
continue; $preferences = CreateObject('phpgwapi.preferences',$userid);
} $part_prefs = $preferences->read_repository();
$GLOBALS['egw']->accounts->get_account_name($userid,$lid,$details['to-firstname'],$details['to-lastname']);
$details['to-fullname'] = $GLOBALS['egw']->common->display_fullname('',$details['to-firstname'],$details['to-lastname']);
if (!$this->update_requested($userid,$part_prefs,$msg_type,$old_event,$new_event))
{
continue;
}
$GLOBALS['egw']->accounts->get_account_name($userid,$lid,$details['to-firstname'],$details['to-lastname']);
$details['to-fullname'] = common::display_fullname('',$details['to-firstname'],$details['to-lastname']);
}
else // external email address: use current users preferences, plus some hardcoded settings (eg. ical notification)
{
$details['to-fullname'] = $userid;
$part_prefs = $GLOBALS['egw_info']['user']['preferences'];
$part_prefs['calendar']['update_format'] = 'ical'; // use ical format
}
// event is in user-time of current user, now we need to calculate the tz-difference to the notified user and take it into account // event is in user-time of current user, now we need to calculate the tz-difference to the notified user and take it into account
if (!isset($part_prefs['common']['tz'])) $part_prefs['common']['tz'] = $GLOBALS['egw_info']['server']['server_timezone']; if (!isset($part_prefs['common']['tz'])) $part_prefs['common']['tz'] = $GLOBALS['egw_info']['server']['server_timezone'];
$timezone = new DateTimeZone($part_prefs['common']['tz']); $timezone = new DateTimeZone($part_prefs['common']['tz']);
@ -746,27 +761,26 @@ class calendar_boupdate extends calendar_bo
switch($part_prefs['calendar']['update_format']) switch($part_prefs['calendar']['update_format'])
{ {
case 'ical': case 'ical':
if ($method == 'REQUEST') if (is_null($ics))
{ {
if (is_null($ics)) $calendar_ical = new calendar_ical();
{ $calendar_ical->setSupportedFields('full'); // full iCal fields+event TZ
$calendar_ical = new calendar_ical(); $ics = $calendar_ical->exportVCal(array($event),'2.0',$method);
$calendar_ical->setSupportedFields('full'); // full iCal fields+event TZ unset($calendar_ical);
$ics = $calendar_ical->exportVCal($event['id'],'2.0',$method);
unset($calendar_ical);
}
$attachment = array( 'string' => $ics,
'filename' => 'cal.ics',
'encoding' => '8bit',
'type' => 'text/calendar; method='.$method,
);
} }
$attachment = array(
'string' => $ics,
'filename' => 'cal.ics',
'encoding' => '8bit',
'type' => 'text/calendar; method='.$method,
);
// fall through // fall through
case 'extended': case 'extended':
$body .= "\n\n".lang('Event Details follow').":\n"; $body .= "\n\n".lang('Event Details follow').":\n";
foreach($event_arr as $key => $val) foreach($event_arr as $key => $val)
{ {
if(strlen($details[$key])) { if(!empty($details[$key]))
{
switch($key){ switch($key){
case 'access': case 'access':
case 'priority': case 'priority':
@ -781,7 +795,8 @@ class calendar_boupdate extends calendar_bo
break; break;
} }
// send via notification_app // send via notification_app
if($GLOBALS['egw_info']['apps']['notifications']['enabled']) { if($GLOBALS['egw_info']['apps']['notifications']['enabled'])
{
try { try {
$notification = new notifications(); $notification = new notifications();
$notification->set_receivers(array($userid)); $notification->set_receivers(array($userid));
@ -796,7 +811,9 @@ class calendar_boupdate extends calendar_bo
error_log(__METHOD__.' error while notifying user '.$userid.':'.$exception->getMessage()); error_log(__METHOD__.' error while notifying user '.$userid.':'.$exception->getMessage());
continue; continue;
} }
} else { }
else
{
error_log(__METHOD__.' cannot send any notifications because notifications is not installed'); error_log(__METHOD__.' cannot send any notifications because notifications is not installed');
} }
} }
@ -1482,7 +1499,7 @@ class calendar_boupdate extends calendar_bo
echo "<p>error opening '$this->log_file' !!!</p>\n"; echo "<p>error opening '$this->log_file' !!!</p>\n";
return false; return false;
} }
fwrite($f,$type.': '.$GLOBALS['egw']->common->grab_owner_name($this->user).': '.date('r')."\n"); fwrite($f,$type.': '.common::grab_owner_name($this->user).': '.date('r')."\n");
fwrite($f,"Time: time to save / saved time read back / old time before save\n"); fwrite($f,"Time: time to save / saved time read back / old time before save\n");
foreach(array('start','end') as $name) foreach(array('start','end') as $name)
{ {

View File

@ -31,6 +31,7 @@ class calendar_uiforms extends calendar_ui
'export' => true, 'export' => true,
'import' => true, 'import' => true,
'cat_acl' => true, 'cat_acl' => true,
'meeting' => true,
); );
/** /**
@ -1569,6 +1570,122 @@ function replace_eTemplate_onsubmit()
return $response->getXML(); return $response->getXML();
} }
/**
* Display a meeting request (iCal) for FMail and allow to accept, tentative or reject it
*
* @todo Handle situation when user is NOT invited, but eg. can view that mail ...
* @param array $event=null
* @param string $msg=''
*/
function meeting(array $event=null, $msg='')
{
$user = $GLOBALS['egw_info']['user']['account_id'];
if (!is_array($event))
{
$ical_string = $_GET['ical'] == 'session' ? egw_cache::getSession('calendar', 'ical') : $_GET['ical'];
$ical = new calendar_ical();
if (!($events = $ical->icaltoegw($ical_string, '', 'utf-8')) || count($events) != 1)
{
error_log(__METHOD__."('$_GET[ical]') error parsing iCal!");
$GLOBALS['egw']->framework->render(html::fieldset('<pre>'.htmlspecialchars($ical_string).'</pre>',
lang('Error: importing the iCal')));
return;
}
$event = array_shift($events);
if (($existing_event = $this->bo->read($event['uid'])) && !$existing_event['deleted'])
{
$event = $existing_event;
foreach((array)$event['participants'] as $uid => $status)
{
calendar_so::split_status($status, $quantity, $role);
if ($role == 'CHAIR')
{
$event['organizer'] = $this->bo->participant_name($uid,false,true);
break;
}
}
if (empty($event['organizer']))
{
$event['organizer'] = $this->bo->participant_name($event['owner'],false,true);
}
$msg = lang('Using already existing event on server.');
}
else
{
$event['participant_types'] = array();
foreach($event['participants'] as $uid => $status)
{
calendar_so::split_user($uid, $user_type, $user_id);
$event['participant_types'][$user_type][$user_id] = $status;
}
}
//error_log(__METHOD__."(...) parsed as ".array2string($event));
$event['recure'] = $this->bo->recure2string($event);
$event['all_participants'] = implode(",\n",$this->bo->participants($event, true));
if (!isset($event['participants'][$user]))
{
$msg .= ($msg ? "\n" : '').lang('You are not invited to that event!');
if ($event['id'])
{
$readonlys['button[accept]'] = $readonlys['button[tentativ]'] = $readonlys['button[reject]'] = true;
}
}
// ignore events in the past
if ($this->bo->date2ts($event['start']) < $this->bo->now_su)
{
$msg = lang('Requested meeting is in the past!');
$readonlys['button[accept]'] = $readonlys['button[tentativ]'] = $readonlys['button[reject]'] = true;
}
}
else
{
//_debug_array($event);
list($button) = each($event['button']);
unset($event['button']);
switch($button)
{
case 'reject':
if (!$event['id'])
{
// send reply to organizer
$this->bo->send_update(MSG_REJECTED,array('e'.$event['organizer'] => 'DCHAIR'),$event);
break; // no need to store rejected event
}
// fall-through
case 'accept':
case 'tentativ':
$status = strtoupper($button[0]); // A, R or T
if (!$event['id'])
{
// store event without notifications!
if (($event['id'] = $this->bo->update($event, $ignore_conflicts=true, true, false, true, $msg, true)))
{
$msg = lang('Event saved');
}
else
{
$msg = lang('Error: saving the event !!!');
break;
}
}
// set status and send notification / meeting response
if ($this->bo->set_status($event, $user, $status))
{
if (!$msg) $msg = lang('Status changed');
}
break;
}
}
$event['msg'] = $msg;
$readonlys['button[edit]'] = !$event['id'];
$tpl = new etemplate('calendar.meeting');
$tpl->exec('calendar.calendar_uiforms.meeting', $event, $sel_options, $readonlys, $event, 2);
}
/** /**
* displays a sheduling conflict * displays a sheduling conflict
* *

View File

@ -10,6 +10,7 @@
, stati of participants reset calendar de , Status der Teilnehmer zurückgesetzt , stati of participants reset calendar de , Status der Teilnehmer zurückgesetzt
<b>please note</b>: the calendar use the holidays of your country, which is set to %1. you can change it in your %2.<br />holidays are %3 automatic installed from %4. you can changed it in %5. calendar de <b>Bitte beachten</b>: Der Kalender verwendet die Feiertages des Landes, welches auf %1 eingestellt ist. Das können Sie in Ihren %2 ändern.<br />Feiertage werden %3 automatisch von %4 installiert, was in %5 änderbar ist. <b>please note</b>: the calendar use the holidays of your country, which is set to %1. you can change it in your %2.<br />holidays are %3 automatic installed from %4. you can changed it in %5. calendar de <b>Bitte beachten</b>: Der Kalender verwendet die Feiertages des Landes, welches auf %1 eingestellt ist. Das können Sie in Ihren %2 ändern.<br />Feiertage werden %3 automatisch von %4 installiert, was in %5 änderbar ist.
a non blocking event will not conflict with other events calendar de Ein nicht blockierender Termin ergibt keine Konflikt mit anderen Terminen a non blocking event will not conflict with other events calendar de Ein nicht blockierender Termin ergibt keine Konflikt mit anderen Terminen
accept calendar de Zusagen
accept or reject an invitation calendar de Einladung zu- oder absagen accept or reject an invitation calendar de Einladung zu- oder absagen
accepted calendar de Zugesagt accepted calendar de Zugesagt
access denied to the calendar of %1 !!! calendar de Zugriff zum Kalender von %1 verweigert !!! access denied to the calendar of %1 !!! calendar de Zugriff zum Kalender von %1 verweigert !!!
@ -290,6 +291,7 @@ make freebusy information available to not loged in persons? calendar de Die Bel
manage mapping calendar de Feldzuordnung bearbeiten manage mapping calendar de Feldzuordnung bearbeiten
max. number of entries to show (leave empty for no restriction) calendar de Max. Anzahl von Einträgen die angezeigt werden sollen (Kein Eintrag = Keine Beschränkung) max. number of entries to show (leave empty for no restriction) calendar de Max. Anzahl von Einträgen die angezeigt werden sollen (Kein Eintrag = Keine Beschränkung)
maximum available quantity of %1 exceeded! calendar de Maximale Anzahl von %1 erreicht! maximum available quantity of %1 exceeded! calendar de Maximale Anzahl von %1 erreicht!
meeting request calendar de Termineinladung
merge document... calendar de Dokument einfügen... merge document... calendar de Dokument einfügen...
minutes calendar de Minuten minutes calendar de Minuten
modified calendar de Geändert modified calendar de Geändert
@ -369,6 +371,7 @@ recover calendar de Wiederherstellen
recovered calendar de wieder hergestellt recovered calendar de wieder hergestellt
recurrence calendar de Wiederholung recurrence calendar de Wiederholung
recurring event calendar de Wiederholender Termin recurring event calendar de Wiederholender Termin
reject calendar de Absagen
rejected calendar de Abgesagt rejected calendar de Abgesagt
repeat days calendar de Wiederholungstage repeat days calendar de Wiederholungstage
repeat the event until which date (empty means unlimited) calendar de Bis zu welchen Datum soll der Termin wiederholt werden (leer bedeutet unbegrenzt) repeat the event until which date (empty means unlimited) calendar de Bis zu welchen Datum soll der Termin wiederholt werden (leer bedeutet unbegrenzt)
@ -379,6 +382,7 @@ repetition calendar de Wiederholung
repetitiondetails (or empty) calendar de Details der Wiederholung (oder leer) repetitiondetails (or empty) calendar de Details der Wiederholung (oder leer)
replacements for inserting events into documents calendar de Platzhalter für das Einfügen von Terminen in Dokumente replacements for inserting events into documents calendar de Platzhalter für das Einfügen von Terminen in Dokumente
requested calendar de Erforderlich requested calendar de Erforderlich
requested meeting is in the past! calendar de Termin, zu dem eingeladen wird, ist in der Vergangenheit!
require an acl grant to invite other users and groups admin de Freigabe um andere Benutzer oder Gruppen einzuladen erforderlich require an acl grant to invite other users and groups admin de Freigabe um andere Benutzer oder Gruppen einzuladen erforderlich
reset calendar de Zurücksetzen reset calendar de Zurücksetzen
reset participant stati on event shifts calendar de Rücksetzen des Teilnehmerstatus beim Verschieben von Terminen reset participant stati on event shifts calendar de Rücksetzen des Teilnehmerstatus beim Verschieben von Terminen
@ -466,6 +470,7 @@ this entry is currently opened by %1! calendar de Dieser Termin ist im Moment vo
this entry is opened by user: calendar de Dieser Eintrag ist von einem anderen Benutzer innerhalb des konfigurierten Zeitintervalls geöffnet worden: this entry is opened by user: calendar de Dieser Eintrag ist von einem anderen Benutzer innerhalb des konfigurierten Zeitintervalls geöffnet worden:
this event is part of a series calendar de Dieser Termin ist Teil einer Serie this event is part of a series calendar de Dieser Termin ist Teil einer Serie
this group that is preselected when you enter the planner. you can change it in the planner anytime you want. calendar de Diese Gruppe wird als Vorauswahl ausgewählt wenn Sie den Planer öffnen. Sie können die Gruppe jederzeit wechseln wenn Sie möchten. this group that is preselected when you enter the planner. you can change it in the planner anytime you want. calendar de Diese Gruppe wird als Vorauswahl ausgewählt wenn Sie den Planer öffnen. Sie können die Gruppe jederzeit wechseln wenn Sie möchten.
this mail contains a meeting request calendar de Diese Nachricht enthält eine Termineinladung
this message is sent for canceled or deleted events. calendar de Diese Benachrichtigung wird für stornierte oder gelöschte Termine versendet. this message is sent for canceled or deleted events. calendar de Diese Benachrichtigung wird für stornierte oder gelöschte Termine versendet.
this message is sent for modified or moved events. calendar de Diese Benachrichtigung wird für geänderte Termine versendet. this message is sent for modified or moved events. calendar de Diese Benachrichtigung wird für geänderte Termine versendet.
this message is sent to disinvited participants. calendar de Diese Nachricht wird ausgeladenen Teilnehmern gesendet. this message is sent to disinvited participants. calendar de Diese Nachricht wird ausgeladenen Teilnehmern gesendet.
@ -509,6 +514,7 @@ use weekday start calendar de Benutzer Start der Arbeitswoche
user or group calendar de Benutzer oder Gruppe user or group calendar de Benutzer oder Gruppe
user selectable css file for the calendar setup calendar de Benutzer können ausgwählte CSS Dateien aus dem Kalender Setup benutzen user selectable css file for the calendar setup calendar de Benutzer können ausgwählte CSS Dateien aus dem Kalender Setup benutzen
users + groups: inviting both allways requires an invite grant admin de Benutzer + Gruppen: Einladungen beider brauchen eine Freigabe users + groups: inviting both allways requires an invite grant admin de Benutzer + Gruppen: Einladungen beider brauchen eine Freigabe
using already existing event on server. calendar de Benutze bereits existierenden Termin auf dem Server.
view exception calendar de Ausnahme anzeigen view exception calendar de Ausnahme anzeigen
view series calendar de Terminserie anzeigen view series calendar de Terminserie anzeigen
view this event calendar de Diesen Termin anzeigen view this event calendar de Diesen Termin anzeigen
@ -542,6 +548,7 @@ yearview calendar de Jahresansicht
yes, only admins can purge deleted items admin de Ja, nur Administratoren können gelöschte Einträge bereinigen yes, only admins can purge deleted items admin de Ja, nur Administratoren können gelöschte Einträge bereinigen
yes, users can purge their deleted items admin de Ja, Benutzer können gelöschte Einträge selbst bereinigen yes, users can purge their deleted items admin de Ja, Benutzer können gelöschte Einträge selbst bereinigen
you are not allowed to book the resource selected: calendar de Sie sind nicht berechtigt die ausgewählte Ressource zu buchen. you are not allowed to book the resource selected: calendar de Sie sind nicht berechtigt die ausgewählte Ressource zu buchen.
you are not invited to that event! calendar de Sie sind zu diesem Termin nicht eingeladen!
you can either set a year or a occurence, not both !!! calendar de Sie können nur entweder das Jahr oder die Wiederholung angeben, nicht beides! you can either set a year or a occurence, not both !!! calendar de Sie können nur entweder das Jahr oder die Wiederholung angeben, nicht beides!
you can only set a year or a occurence !!! calendar de Sie können nur ein Jahr oder eine Wiederholung angeben ! you can only set a year or a occurence !!! calendar de Sie können nur ein Jahr oder eine Wiederholung angeben !
you do not have permission to read this record! calendar de Sie haben keine Berechtigung diesen Eintrag zu lesen! you do not have permission to read this record! calendar de Sie haben keine Berechtigung diesen Eintrag zu lesen!

View File

@ -10,6 +10,7 @@
, stati of participants reset calendar en , status of participants reset , stati of participants reset calendar en , status of participants reset
<b>please note</b>: the calendar use the holidays of your country, which is set to %1. you can change it in your %2.<br />holidays are %3 automatic installed from %4. you can changed it in %5. calendar en <b>Please note</b>: The calendar use the holidays of your country, which is set to %1. You can change it in your %2.<br />Holidays are %3 automatic installed from %4. You can change it in %5. <b>please note</b>: the calendar use the holidays of your country, which is set to %1. you can change it in your %2.<br />holidays are %3 automatic installed from %4. you can changed it in %5. calendar en <b>Please note</b>: The calendar use the holidays of your country, which is set to %1. You can change it in your %2.<br />Holidays are %3 automatic installed from %4. You can change it in %5.
a non blocking event will not conflict with other events calendar en A non blocking event will not conflict with other events a non blocking event will not conflict with other events calendar en A non blocking event will not conflict with other events
accept calendar en Accept
accept or reject an invitation calendar en Accept or reject an invitation accept or reject an invitation calendar en Accept or reject an invitation
accepted calendar en Accepted accepted calendar en Accepted
access denied to the calendar of %1 !!! calendar en Access denied to the calendar of %1 !!! access denied to the calendar of %1 !!! calendar en Access denied to the calendar of %1 !!!
@ -290,6 +291,7 @@ make freebusy information available to not loged in persons? calendar en Make Fr
manage mapping calendar en Manage mapping manage mapping calendar en Manage mapping
max. number of entries to show (leave empty for no restriction) calendar en Max. Number of entries to show (leave empty for no restriction) max. number of entries to show (leave empty for no restriction) calendar en Max. Number of entries to show (leave empty for no restriction)
maximum available quantity of %1 exceeded! calendar en Maximum available quantity of %1 exceeded! maximum available quantity of %1 exceeded! calendar en Maximum available quantity of %1 exceeded!
meeting request calendar en Meeting request
merge document... calendar en merge document... merge document... calendar en merge document...
minutes calendar en Minutes minutes calendar en Minutes
modified calendar en Modified modified calendar en Modified
@ -369,6 +371,7 @@ recover calendar en Recover
recovered calendar en recovered recovered calendar en recovered
recurrence calendar en Recurrence recurrence calendar en Recurrence
recurring event calendar en Recurring event recurring event calendar en Recurring event
reject calendar en Reject
rejected calendar en Rejected rejected calendar en Rejected
repeat days calendar en Repeat days repeat days calendar en Repeat days
repeat the event until which date (empty means unlimited) calendar en Repeat the event until which date (empty means unlimited) repeat the event until which date (empty means unlimited) calendar en Repeat the event until which date (empty means unlimited)
@ -379,6 +382,7 @@ repetition calendar en Repetition
repetitiondetails (or empty) calendar en Repetition details (or empty) repetitiondetails (or empty) calendar en Repetition details (or empty)
replacements for inserting events into documents calendar en Replacements for inserting events into documents replacements for inserting events into documents calendar en Replacements for inserting events into documents
requested calendar en Requested requested calendar en Requested
requested meeting is in the past! calendar en Requested meeting is in the past!
require an acl grant to invite other users and groups admin en Require an ACL grant to invite other users and groups require an acl grant to invite other users and groups admin en Require an ACL grant to invite other users and groups
reset calendar en Reset reset calendar en Reset
reset participant stati on event shifts calendar en Reset participant status on event shifts reset participant stati on event shifts calendar en Reset participant status on event shifts
@ -466,6 +470,7 @@ this entry is currently opened by %1! calendar en This entry is currently opened
this entry is opened by user: calendar en This entry was opened within the configured time interval by user: this entry is opened by user: calendar en This entry was opened within the configured time interval by user:
this event is part of a series calendar en This event is part of a series this event is part of a series calendar en This event is part of a series
this group that is preselected when you enter the planner. you can change it in the planner anytime you want. calendar en This group that is preselected when you enter the planner. You can change it in the planner anytime you want. this group that is preselected when you enter the planner. you can change it in the planner anytime you want. calendar en This group that is preselected when you enter the planner. You can change it in the planner anytime you want.
this mail contains a meeting request calendar en This mail contains a meeting request
this message is sent for canceled or deleted events. calendar en This message is sent for canceled or deleted events. this message is sent for canceled or deleted events. calendar en This message is sent for canceled or deleted events.
this message is sent for modified or moved events. calendar en This message is sent for modified or moved events. this message is sent for modified or moved events. calendar en This message is sent for modified or moved events.
this message is sent to disinvited participants. calendar en This message is sent to disinvited participants. this message is sent to disinvited participants. calendar en This message is sent to disinvited participants.
@ -509,6 +514,7 @@ use weekday start calendar en Use weekday start
user or group calendar en User or group user or group calendar en User or group
user selectable css file for the calendar setup calendar en User selectable CSS file for the calendar setup user selectable css file for the calendar setup calendar en User selectable CSS file for the calendar setup
users + groups: inviting both allways requires an invite grant admin en Users + groups: inviting both always requires an invite grant users + groups: inviting both allways requires an invite grant admin en Users + groups: inviting both always requires an invite grant
using already existing event on server. calendar en Using already existing event on server.
view exception calendar en View exception view exception calendar en View exception
view series calendar en View series view series calendar en View series
view this event calendar en View this event view this event calendar en View this event
@ -542,6 +548,7 @@ yearview calendar en Year view
yes, only admins can purge deleted items admin en Yes, only admins can purge deleted items yes, only admins can purge deleted items admin en Yes, only admins can purge deleted items
yes, users can purge their deleted items admin en Yes, users can purge their deleted items yes, users can purge their deleted items admin en Yes, users can purge their deleted items
you are not allowed to book the resource selected: calendar en You are not allowed to book the resource selected: you are not allowed to book the resource selected: calendar en You are not allowed to book the resource selected:
you are not invited to that event! calendar en You are not invited to that event!
you can either set a year or a occurence, not both !!! calendar en You can either set a Year or a Occurrence, not both !!! you can either set a year or a occurence, not both !!! calendar en You can either set a Year or a Occurrence, not both !!!
you can only set a year or a occurence !!! calendar en You can only set a year or a occurrence !!! you can only set a year or a occurence !!! calendar en You can only set a year or a occurrence !!!
you do not have permission to read this record! calendar en You do not have permission to read this record! you do not have permission to read this record! calendar en You do not have permission to read this record!

File diff suppressed because one or more lines are too long