From a5ec30327ef43d0e0340b869ed3ae0ead176a0b6 Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Fri, 29 Mar 2024 18:25:24 +0200 Subject: [PATCH 01/14] no message --- assets/js/pages/booking.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index fab6f9cc75..8d2277c0eb 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -417,6 +417,10 @@ App.Pages.Booking = (function () { $('#step-' + nextTabIndex).addClass('active-step'); $('#wizard-frame-' + nextTabIndex).fadeIn(); }); + + // Scroll to the top of the page. Especially on a mobile device this is very useful. + const scrollingElement = (document.scrollingElement || document.body); + scrollingElement.scrollTop = 0; }); /** From d87026a6e9507a0f6cea4ae58d821142e33c2f2e Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Fri, 29 Mar 2024 18:25:24 +0200 Subject: [PATCH 02/14] no message --- assets/js/pages/booking.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index 8d2277c0eb..ffe7c5bf5c 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -668,7 +668,7 @@ App.Pages.Booking = (function () {
${serviceOptionText} -
+
${providerOptionText}
@@ -679,16 +679,16 @@ App.Pages.Booking = (function () {
${formattedSelectedDate} -
+
${timezoneOptionText} -
+
${Number(service.price).toFixed(2)} ${service.currency}
- + `); // Render the customer information From c45e36b92362ea44132dc7c6bc516f6375ec48ed Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:10:49 +0300 Subject: [PATCH 03/14] Done: Add a check so that this happens if the window.innerWidth is less than 576 --- assets/js/pages/booking.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index ffe7c5bf5c..bbc26d47f1 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -419,8 +419,10 @@ App.Pages.Booking = (function () { }); // Scroll to the top of the page. Especially on a mobile device this is very useful. - const scrollingElement = (document.scrollingElement || document.body); - scrollingElement.scrollTop = 0; + if (window.innerWidth < 576) { + const scrollingElement = (document.scrollingElement || document.body); + scrollingElement.scrollTop = 0; + } }); /** From 6e452fa8f529480232332ca6bbb17fade0120773 Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:47:23 +0300 Subject: [PATCH 04/14] Update booking.js It is not the width that is important, it is the height. This way it works on a mobile screen no matter whether it is in portrait or landscape position, and also on other devices where window height is less than document height, even on a desktop computer when browser is not running fullscreen. --- assets/js/pages/booking.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index bbc26d47f1..6939754500 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -419,8 +419,8 @@ App.Pages.Booking = (function () { }); // Scroll to the top of the page. Especially on a mobile device this is very useful. - if (window.innerWidth < 576) { - const scrollingElement = (document.scrollingElement || document.body); + const scrollingElement = (document.scrollingElement || document.body); + if (window.innerHeight < scrollingElement.scrollHeight) { scrollingElement.scrollTop = 0; } }); From 7a014c417bfd5577ee777a62fc14aa2e66f7839a Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:54:21 +0300 Subject: [PATCH 05/14] Update booking.js --- assets/js/pages/booking.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index 6939754500..cf0e231544 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -418,7 +418,7 @@ App.Pages.Booking = (function () { $('#wizard-frame-' + nextTabIndex).fadeIn(); }); - // Scroll to the top of the page. Especially on a mobile device this is very useful. + // Scroll to the top of the page. On a small screen, especially on a mobile device, this is very useful. const scrollingElement = (document.scrollingElement || document.body); if (window.innerHeight < scrollingElement.scrollHeight) { scrollingElement.scrollTop = 0; From 8ddcacf3087e6ce1f2f794eb6a125c8363a58276 Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Tue, 16 Apr 2024 07:02:07 +0300 Subject: [PATCH 06/14] Update booking.js --- assets/js/pages/booking.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index 6939754500..cf0e231544 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -418,7 +418,7 @@ App.Pages.Booking = (function () { $('#wizard-frame-' + nextTabIndex).fadeIn(); }); - // Scroll to the top of the page. Especially on a mobile device this is very useful. + // Scroll to the top of the page. On a small screen, especially on a mobile device, this is very useful. const scrollingElement = (document.scrollingElement || document.body); if (window.innerHeight < scrollingElement.scrollHeight) { scrollingElement.scrollTop = 0; From 0f55e8384e086445436b12482d088e56554804a3 Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:44:10 +0300 Subject: [PATCH 07/14] Update array_helper.php --- application/helpers/array_helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/helpers/array_helper.php b/application/helpers/array_helper.php index 1f47c14e39..2381f89495 100644 --- a/application/helpers/array_helper.php +++ b/application/helpers/array_helper.php @@ -48,7 +48,7 @@ function array_find(array $array, callable $callback): mixed throw new InvalidArgumentException('No filter function provided.'); } - return array_filter($array, $callback)[0] ?? null; + return array_values(array_filter($array, $callback))[0] ?? null; } } From 92b01b492f7a37912c53123d5ee8a6f3f89d750c Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Sun, 12 May 2024 10:00:53 +0300 Subject: [PATCH 08/14] no message --- .../language/finnish/translations_lang.php | 102 +++++++++--------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/application/language/finnish/translations_lang.php b/application/language/finnish/translations_lang.php index e69534ebbe..b268289a04 100755 --- a/application/language/finnish/translations_lang.php +++ b/application/language/finnish/translations_lang.php @@ -1,9 +1,9 @@ '; -$lang['click_to_toggle'] = 'Klikkaa kytkeäksesi'; -$lang['week_short'] = 'vk'; -$lang['scroll_to_increment'] = 'Vieritä kohtaan Lisäys'; +$lang['click_to_toggle'] = 'Vaihda klikkaamalla'; +$lang['week_short'] = 'vko'; +$lang['scroll_to_increment'] = 'Kasvata hiiren rullalla'; $lang['year'] = 'vuosi'; -$lang['make_non_working_day'] = 'Tämä palveluntarjoaja ei ole käytettävissä töihin valittuna päivänä.'; -$lang['no_breaks'] = 'Ei taukoja'; -$lang['service_categories'] = 'Palveluluokat'; -$lang['service_category'] = 'Palveluluokka'; -$lang['blocked_period_saved'] = 'Estetty ajanjakso tallennettu onnistuneesti.'; -$lang['blocked_period_deleted'] = 'Estetty ajanjakso poistettu onnistuneesti.'; -$lang['delete_blocked_period'] = 'Poistettu estetty ajanjakso'; -$lang['blocked_period'] = 'Estetty ajanjakso'; -$lang['blocked_periods'] = 'Estetyt ajanjaksot'; -$lang['blocked_period_save'] = 'Tallenna estetty ajanjakso'; -$lang['blocked_period_delete'] = 'Poista estetty ajanjakso'; -$lang['blocked_periods_hint'] = 'Määritä ajanjaksot, jolloin julkiset varaukset poistetaan käytöstä kaikilta palveluntarjoajilta (esim. suljetut päivämäärät, lomat jne.).'; +$lang['make_non_working_day'] = 'Tämä palveluntuottaja ei ole saatavilla valittuna päivänä.'; +$lang['no_breaks'] = 'Ei taukoja.'; +$lang['service_categories'] = 'Palvelujen kategoriat'; +$lang['service_category'] = 'Palvelun kategoria'; +$lang['blocked_period_saved'] = 'Estetty jakso tallennettiin onnistuneesti.'; +$lang['blocked_period_deleted'] = 'Estetty jakso poistettiin onnistuneesti.'; +$lang['delete_blocked_period'] = 'Poista estetty jakso'; +$lang['blocked_period'] = 'Estetty jakso'; +$lang['blocked_periods'] = 'Estetyt jaksot'; +$lang['blocked_period_save'] = 'Tallenna estetty jakso'; +$lang['blocked_period_delete'] = 'Poista estetty jakso'; +$lang['blocked_periods_hint'] = 'Määrittele ajanjaksot jolloin varauksia ei voi tehdä lainkaan (esim. pyhäpäivät jne).'; $lang['custom_field'] = 'Mukautettu kenttä'; $lang['custom_fields'] = 'Mukautetut kentät'; -$lang['label'] = 'Merkki'; -$lang['webhook_saved'] = 'Webhook tallennettu onnistuneesti.'; -$lang['webhook_deleted'] = 'Webhook poistettu onnistuneesti.'; -$lang['delete_webhook'] = 'Poista Webhook'; +$lang['label'] = 'Otsikko'; +$lang['webhook_saved'] = 'Webhook tallennettiin onnistuneesti.'; +$lang['webhook_deleted'] = 'Webhook poistettiin onnistuneesti.'; +$lang['delete_webhook'] = 'Poista webhook'; $lang['contact_info'] = 'Yhteystiedot'; +$lang['customer_is_already_booked'] = 'Sinulla on jo varaus valitsemallasi hetkellä.'; +$lang['invalid_credentials_provided'] = 'Tunnukset olivat virheelliset, ole hyvä ja yritä uudelleen.'; +$lang['working_plan_exception_start_before_end'] = 'Työsuunnitelman poikkeuksen alkamisajan on oltava ennen päättymisaikaa.'; $lang['hide_from_public'] = 'Hide From Public'; $lang['matomo_analytics_site_id'] = 'Matomo Analytics Site ID'; $lang['matomo_analytics_site_id_hint'] = 'Set the site ID that will be tracked by Matomo (the default site has the ID "1").'; -$lang['default_timezone'] = 'Default Timezone'; -$lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; -$lang['default_language'] = 'Default Language'; -$lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['default_timezone'] = 'Oletusaikavyöhyke'; +$lang['default_timezone_hint'] = 'Tämä tulee uusien käyttäjien ja varausten oletusaikavyöhykkeeksi'; +$lang['default_language'] = 'Oletuskieli'; +$lang['default_language_hint'] = 'Tämä tulee uusien käyttäjien oletuskieleksi'; // End From 00e64f19b9aff42e7834464ff52c4d8a30f82d07 Mon Sep 17 00:00:00 2001 From: tm8544 <15167679+tm8544@users.noreply.github.com> Date: Mon, 13 May 2024 10:10:46 +0300 Subject: [PATCH 09/14] no message --- CHANGELOG.md | 1 + application/controllers/Caldav.php | 377 ++++++++++++++ application/controllers/Calendar.php | 18 +- application/controllers/Console.php | 8 +- application/controllers/Google.php | 24 +- application/core/EA_Controller.php | 1 + .../language/arabic/translations_lang.php | 25 +- .../language/bulgarian/translations_lang.php | 23 +- .../language/catalan/translations_lang.php | 19 +- .../language/chinese/translations_lang.php | 19 +- .../language/croatian/translations_lang.php | 19 +- .../language/czech/translations_lang.php | 19 +- .../language/danish/translations_lang.php | 23 +- .../language/dutch/translations_lang.php | 19 +- .../language/english/translations_lang.php | 23 +- .../language/estonian/translations_lang.php | 19 +- .../language/finnish/translations_lang.php | 17 +- .../language/french/translations_lang.php | 19 +- .../language/german/translations_lang.php | 19 +- .../language/greek/translations_lang.php | 19 +- .../language/hebrew/translations_lang.php | 19 +- .../language/hindi/translations_lang.php | 19 +- .../language/hungarian/translations_lang.php | 19 +- .../language/italian/translations_lang.php | 19 +- .../language/japanese/translations_lang.php | 19 +- .../luxembourgish/translations_lang.php | 19 +- .../language/marathi/translations_lang.php | 19 +- .../language/persian/translations_lang.php | 19 +- .../language/polish/translations_lang.php | 19 +- .../portuguese-br/translations_lang.php | 19 +- .../language/portuguese/translations_lang.php | 19 +- .../language/romanian/translations_lang.php | 19 +- .../language/russian/translations_lang.php | 19 +- .../language/serbian/translations_lang.php | 19 +- .../language/slovak/translations_lang.php | 19 +- .../language/spanish/translations_lang.php | 19 +- .../language/swedish/translations_lang.php | 19 +- .../language/turkish/translations_lang.php | 19 +- application/libraries/Caldav_sync.php | 478 ++++++++++++++++++ application/libraries/Ics_file.php | 49 +- application/libraries/Synchronization.php | 189 ++++--- ..._caldav_columns_to_user_settings_table.php | 112 ++++ ..._calendar_column_to_appointments_table.php | 43 ++ application/models/Appointments_model.php | 17 + application/models/Providers_model.php | 19 +- .../select_google_calendar_modal.php | 27 - application/views/pages/calendar.php | 66 ++- assets/js/http/caldav_http_client.js | 108 ++++ assets/js/pages/admins.js | 4 +- assets/js/pages/blocked_periods.js | 4 +- assets/js/pages/booking.js | 18 +- assets/js/pages/business_settings.js | 4 +- assets/js/pages/customers.js | 4 +- assets/js/pages/providers.js | 4 +- assets/js/pages/secretaries.js | 4 +- assets/js/pages/service_categories.js | 4 +- assets/js/pages/services.js | 4 +- assets/js/pages/webhooks.js | 4 +- assets/js/utils/calendar_default_view.js | 52 +- assets/js/utils/calendar_google_sync.js | 164 ------ assets/js/utils/calendar_sync.js | 441 ++++++++++++++++ assets/js/utils/calendar_table_view.js | 8 +- assets/js/utils/message.js | 6 +- composer.json | 4 +- composer.lock | 236 ++++++++- docs/docker.md | 2 + openapi.yml | 38 +- 67 files changed, 2481 insertions(+), 685 deletions(-) create mode 100644 application/controllers/Caldav.php create mode 100644 application/libraries/Caldav_sync.php create mode 100644 application/migrations/055_add_caldav_columns_to_user_settings_table.php create mode 100644 application/migrations/056_add_id_caldav_calendar_column_to_appointments_table.php delete mode 100644 application/views/components/select_google_calendar_modal.php create mode 100644 assets/js/http/caldav_http_client.js delete mode 100644 assets/js/utils/calendar_google_sync.js create mode 100644 assets/js/utils/calendar_sync.js diff --git a/CHANGELOG.md b/CHANGELOG.md index cbf49d494f..26594b2af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ developers to maintain and readjust their custom modifications on the main proje - Add support for custom fields on customers (#1133) - Add from email/name and reply-to settings in the email.php configuration file (#1465) - Create a new setting that will define the default timezone of the application (#1390) +- Integrate CalDAV Protocol for appointment syncing (#209) ### Changed diff --git a/application/controllers/Caldav.php b/application/controllers/Caldav.php new file mode 100644 index 0000000000..2e9d9257ed --- /dev/null +++ b/application/controllers/Caldav.php @@ -0,0 +1,377 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Caldav controller. + * + * Handles the Caldav Calendar synchronization related operations. + * + * @package Controllers + */ +class Caldav extends EA_Controller +{ + /** + * Caldav constructor. + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('caldav_sync'); + + $this->load->model('appointments_model'); + $this->load->model('unavailabilities_model'); + $this->load->model('providers_model'); + } + + /** + * Connect to the target CalDAV server + * + * @return void + */ + public function connect_to_server(): void + { + try { + $provider_id = request('provider_id'); + + $user_id = session('user_id'); + + if (cannot('edit', PRIV_USERS) && (int) $user_id !== (int) $provider_id) { + throw new RuntimeException('You do not have the required permissions for this task.'); + } + + $caldav_url = request('caldav_url'); + $caldav_username = request('caldav_username'); + $caldav_password = request('caldav_password'); + + $default_caldav_calendar = $this->caldav_sync->get_default_calendar( + $caldav_url, + $caldav_username, + $caldav_password, + ); + + if (!$default_caldav_calendar) { + json_response([ + 'success' => false, + ]); + + return; + } + + $provider = $this->providers_model->find($provider_id); + + $provider['settings']['caldav_sync'] = true; + $provider['settings']['caldav_url'] = $caldav_url; + $provider['settings']['caldav_username'] = $caldav_username; + $provider['settings']['caldav_password'] = $caldav_password; + $provider['settings']['caldav_calendar'] = $default_caldav_calendar; + + $this->providers_model->save($provider); + + json_response([ + 'success' => true, + ]); + } catch (Throwable $e) { + json_exception($e); + } + } + + /** + * Sync the provider events with the remote CalDAV calendar. + * + * @param string $provider_id Provider ID (String because this is used with HTTP and CLI) + * + * @return void + * + * @throws \Jsvrcek\ICS\Exception\CalendarEventException + * @throws Exception + * @throws Throwable + */ + public static function sync(string $provider_id): void + { + /** @var EA_Controller $CI */ + $CI = get_instance(); + + $CI->load->library('caldav_sync'); + + // Load the libraries as this method is called statically from the CLI command + + $CI->load->model('appointments_model'); + $CI->load->model('unavailabilities_model'); + $CI->load->model('providers_model'); + $CI->load->model('services_model'); + $CI->load->model('customers_model'); + $CI->load->model('settings_model'); + + $user_id = session('user_id'); + + if (!$user_id && !is_cli()) { + return; + } + + if (empty($provider_id)) { + throw new InvalidArgumentException('No provider ID provided.'); + } + + $provider = $CI->providers_model->find($provider_id); + + // Check whether the selected provider has the CalDAV Sync enabled. + + if (!$provider['settings']['caldav_sync']) { + return; // The selected provider does not have the CalDAV Sync enabled. + } + + // Fetch provider's appointments that belong to the sync time period. + + $sync_past_days = $provider['settings']['sync_past_days']; + + $sync_future_days = $provider['settings']['sync_future_days']; + + $start_date_time = date('Y-m-d H:i:s', strtotime('-' . $sync_past_days . ' days')); + + $end_date_time = date('Y-m-d H:i:s', strtotime('+' . $sync_future_days . ' days')); + + $where = [ + 'start_datetime >=' => $start_date_time, + 'end_datetime <=' => $end_date_time, + 'id_users_provider' => $provider['id'], + ]; + + $appointments = $CI->appointments_model->get($where); + + $unavailabilities = $CI->unavailabilities_model->get($where); + + $local_events = [...$appointments, ...$unavailabilities]; + + // Sync each appointment with CalDAV Calendar by following the project's sync protocol (see documentation). + + foreach ($local_events as $local_event) { + if (!$local_event['is_unavailability']) { + $service = $CI->services_model->find($local_event['id_services']); + $customer = $CI->customers_model->find($local_event['id_users_customer']); + $events_model = $CI->appointments_model; + } else { + $service = null; + $customer = null; + $events_model = $CI->unavailabilities_model; + } + + // If current appointment not synced yet, add to CalDAV Calendar. + + if (!$local_event['id_caldav_calendar']) { + if (!$local_event['is_unavailability']) { + $caldav_event_id = $CI->caldav_sync->save_appointment($local_event, $service, $provider, $customer); + } else { + $caldav_event_id = $CI->caldav_sync->save_unavailability($local_event, $provider); + } + + $local_event['id_caldav_calendar'] = $caldav_event_id; + + $events_model->save($local_event); // Save the CalDAV Calendar ID. + + continue; + } + + // Appointment is synced with CalDAV Calendar. + + try { + $caldav_event = $CI->caldav_sync->get_event($provider, $local_event['id_caldav_calendar']); + + if ($caldav_event['status'] === 'CANCELLED') { + throw new Exception('Event is cancelled, remove the record from Easy!Appointments.'); + } + + // If CalDAV Calendar event is different from Easy!Appointments appointment then update Easy!Appointments record. + $local_event_start = strtotime($local_event['start_datetime']); + $local_event_end = strtotime($local_event['end_datetime']); + + $caldav_event_start = new DateTime($caldav_event['start_datetime']); + $caldav_event_end = new DateTime($caldav_event['end_datetime']); + + $caldav_event_notes = $local_event['is_unavailability'] + ? $caldav_event['summary'] . ' ' . $caldav_event['description'] + : $caldav_event['description']; + + $is_different = + $local_event_start !== $caldav_event_start->getTimestamp() || + $local_event_end !== $caldav_event_end->getTimestamp() || + $local_event['notes'] !== $caldav_event_notes; + + if ($is_different) { + $local_event['start_datetime'] = $caldav_event_start->format('Y-m-d H:i:s'); + $local_event['end_datetime'] = $caldav_event_end->format('Y-m-d H:i:s'); + $local_event['notes'] = $caldav_event_notes; + $events_model->save($local_event); + } + } catch (Throwable) { + // Appointment not found on CalDAV Calendar, delete from Easy!Appointments. + $events_model->delete($local_event['id']); + + $local_event['id_caldav_calendar'] = null; + } + } + + // Add CalDAV Calendar events that do not exist in Easy!Appointments. + + try { + $caldav_events = $CI->caldav_sync->get_sync_events($provider, $start_date_time, $end_date_time); + } catch (Throwable $e) { + if ($e->getCode() === 404) { + log_message('error', 'CalDAV - Remote Calendar not found for provider ID: ' . $provider_id); + + return; // The remote calendar was not found. + } else { + throw $e; + } + } + + foreach ($caldav_events as $caldav_event) { + if ($caldav_event['status'] === 'CANCELLED') { + continue; + } + + if ($caldav_event['start_datetime'] === $caldav_event['end_datetime']) { + continue; // Cannot sync events with the same start and end date time value + } + + $appointment_results = $CI->appointments_model->get(['id_caldav_calendar' => $caldav_event['id']]); + + if (!empty($appointment_results)) { + continue; + } + + $unavailability_results = $CI->unavailabilities_model->get([ + 'id_caldav_calendar' => $caldav_event['id'], + ]); + + if (!empty($unavailability_results)) { + continue; + } + + // Record doesn't exist in the Easy!Appointments, so add the event now. + + $local_event = [ + 'start_datetime' => $caldav_event['start_datetime'], + 'end_datetime' => $caldav_event['end_datetime'], + 'location' => $caldav_event['location'], + 'notes' => $caldav_event['summary'] . ' ' . $caldav_event['description'], + 'id_users_provider' => $provider_id, + 'id_caldav_calendar' => $caldav_event['id'], + ]; + + $CI->unavailabilities_model->save($local_event); + } + + json_response([ + 'success' => true, + ]); + } + + /** + * Get CalDAV Calendars + * + * This method will return a list of the available CalDAV Calendars. + * + * @return void + */ + public function get_caldav_calendars(): void + { + try { + $provider_id = (int) request('provider_id'); + + $user_id = session('user_id'); + + if (cannot('edit', PRIV_USERS) && (int) $user_id !== (int) $provider_id) { + throw new RuntimeException('You do not have the required permissions for this task.'); + } + + $calendars = $this->caldav_sync->get_caldav_calendars($provider_id); + + json_response($calendars); + } catch (Throwable $e) { + json_exception($e); + } + } + + /** + * Select a specific caldav calendar for a provider. + * + * All the appointments will be synced with this particular calendar. + * + * @return void + */ + public function select_caldav_calendar(): void + { + try { + $provider_id = (int) request('provider_id'); + + $user_id = session('user_id'); + + if (cannot('edit', PRIV_USERS) && (int) $user_id !== (int) $provider_id) { + throw new RuntimeException('You do not have the required permissions for this task.'); + } + + $calendar_id = request('calendar_id'); + + $this->providers_model->set_setting($provider_id, 'caldav_calendar', $calendar_id); + + json_response([ + 'success' => true, + ]); + } catch (Throwable $e) { + json_exception($e); + } + } + + /** + * Disable a providers sync setting. + * + * This method resets the CalDAV related settings from the user_settings DB table. + * + * @return void + */ + public function disable_provider_sync(): void + { + try { + $provider_id = request('provider_id'); + + if (!$provider_id) { + throw new Exception('Provider id not specified.'); + } + + $user_id = session('user_id'); + + if (cannot('edit', PRIV_USERS) && (int) $user_id !== (int) $provider_id) { + throw new RuntimeException('You do not have the required permissions for this task.'); + } + + $provider = $this->providers_model->find($provider_id); + + $provider['settings']['caldav_sync'] = false; + $provider['settings']['caldav_url'] = null; + $provider['settings']['caldav_username'] = null; + $provider['settings']['caldav_password'] = null; + $provider['settings']['caldav_calendar'] = null; + + $this->providers_model->save($provider); + + $this->appointments_model->clear_caldav_sync_ids($provider_id); + + json_response([ + 'success' => true, + ]); + } catch (Throwable $e) { + json_exception($e); + } + } +} diff --git a/application/controllers/Calendar.php b/application/controllers/Calendar.php index e9b1dbf1b8..246be6cecc 100644 --- a/application/controllers/Calendar.php +++ b/application/controllers/Calendar.php @@ -177,6 +177,7 @@ public function index(string $appointment_hash = ''): void 'available_services' => $available_services, 'secretary_providers' => $secretary_providers, 'edit_appointment' => $edit_appointment, + 'google_sync_feature' => config('google_sync_feature'), 'customers' => $this->customers_model->get(null, 50, null, 'update_datetime DESC'), 'default_language' => setting('default_language'), 'default_timezone' => setting('default_timezone'), @@ -215,6 +216,7 @@ public function save_appointment(): void { try { $customer_data = request('customer_data'); + $appointment_data = request('appointment_data'); $this->check_event_permissions((int) $appointment_data['id_users_provider']); @@ -250,8 +252,8 @@ public function save_appointment(): void throw new RuntimeException('You do not have the required permissions for this task.'); } - // If the appointment does not contain the customer record id, then it means that is going to be - // inserted. + // If the appointment does not contain the customer record id, then it means that is going to be inserted. + if (!isset($appointment['id_users_customer'])) { $appointment['id_users_customer'] = $customer['id'] ?? $customer_data['id']; } @@ -713,12 +715,6 @@ public function get_calendar_appointments(): void $response['unavailabilities'] = $this->unavailabilities_model->get($where_clause); } - foreach ($response['unavailabilities'] as &$unavailability) { - $unavailability['provider'] = $this->providers_model->find($unavailability['id_users_provider']); - } - - unset($appointment); - $user_id = session('user_id'); $role_slug = session('role_slug'); @@ -765,6 +761,12 @@ public function get_calendar_appointments(): void $response['unavailabilities'] = array_values($response['unavailabilities']); } + foreach ($response['unavailabilities'] as &$unavailability) { + $unavailability['provider'] = $this->providers_model->find($unavailability['id_users_provider']); + } + + unset($unavailability); + // Add blocked periods to the response. $start_date = request('start_date'); $end_date = request('end_date'); diff --git a/application/controllers/Console.php b/application/controllers/Console.php index ce991d8779..380bab1eb1 100644 --- a/application/controllers/Console.php +++ b/application/controllers/Console.php @@ -138,11 +138,13 @@ public function sync(): void $providers = $this->providers_model->get(); foreach ($providers as $provider) { - if (!filter_var($provider['settings']['google_sync'], FILTER_VALIDATE_BOOLEAN)) { - continue; + if (filter_var($provider['settings']['google_sync'], FILTER_VALIDATE_BOOLEAN)) { + Google::sync((string) $provider['id']); } - Google::sync((string) $provider['id']); + if (filter_var($provider['settings']['caldav_sync'], FILTER_VALIDATE_BOOLEAN)) { + Caldav::sync((string) $provider['id']); + } } } diff --git a/application/controllers/Google.php b/application/controllers/Google.php index 1380edfda9..32f609af34 100644 --- a/application/controllers/Google.php +++ b/application/controllers/Google.php @@ -74,7 +74,7 @@ public static function sync(string $provider_id = null): void $google_sync = $CI->providers_model->get_setting($provider['id'], 'google_sync'); if (!$google_sync) { - return; // The selected provider does not have the Google Syncing enabled. + return; // The selected provider does not have the Google Sync enabled. } $google_token = json_decode($provider['settings']['google_token'], true); @@ -82,9 +82,9 @@ public static function sync(string $provider_id = null): void $CI->google_sync->refresh_token($google_token['refresh_token']); // Fetch provider's appointments that belong to the sync time period. - $sync_past_days = $CI->providers_model->get_setting($provider['id'], 'sync_past_days'); + $sync_past_days = $provider['settings']['sync_past_days']; - $sync_future_days = $CI->providers_model->get_setting($provider['id'], 'sync_future_days'); + $sync_future_days = $provider['settings']['sync_future_days']; $start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d'))); @@ -124,13 +124,17 @@ public static function sync(string $provider_id = null): void // If current appointment not synced yet, add to Google Calendar. if (!$local_event['id_google_calendar']) { - $google_event = $CI->google_sync->add_appointment( - $local_event, - $provider, - $service, - $customer, - $settings, - ); + if (!$local_event['is_unavailability']) { + $google_event = $CI->google_sync->add_appointment( + $local_event, + $provider, + $service, + $customer, + $settings, + ); + } else { + $google_event = $CI->google_sync->add_unavailability($provider, $local_event); + } $local_event['id_google_calendar'] = $google_event->getId(); diff --git a/application/core/EA_Controller.php b/application/core/EA_Controller.php index 23b600d11d..cec3966c47 100644 --- a/application/core/EA_Controller.php +++ b/application/core/EA_Controller.php @@ -60,6 +60,7 @@ * @property Email_messages $email_messages * @property Captcha_builder $captcha_builder * @property Google_Sync $google_sync + * @property Caldav_Sync $caldav_sync * @property Ics_file $ics_file * @property Instance $instance * @property Notifications $notifications diff --git a/application/language/arabic/translations_lang.php b/application/language/arabic/translations_lang.php index 749eeda2ff..10eb10849d 100755 --- a/application/language/arabic/translations_lang.php +++ b/application/language/arabic/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'الإسم'; $lang['appointment_link_title'] = 'رابط الموعد'; $lang['success'] = ' !تم بنجاح'; -$lang['appointment_added_to_google_calendar'] = 'تم اضافة الموعد الى تقويم جوجل الخاص بحسابك'; -$lang['view_appointment_in_google_calendar'] = ' اضغط هنا لمشاهدة الموعد على تقويم جوجل الخاص بحسابك '; $lang['appointment_added_to_your_plan'] = 'تم اضافة موعد الى خطتك'; $lang['appointment_link_description'] = 'تستطيع عمل اي تعديلات بالضغط على رابط الموعد أدناه'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'خلال الفترات الغير متوفرة لن يقبل المزود اي موعد'; $lang['new_appointment_hint'] = 'انشاء موعد جديد وتخزينه في قاعدة البيانات'; $lang['reload_appointments_hint'] = 'اعادة تحميل تقويم المواعيد'; -$lang['trigger_google_sync_hint'] = 'تشغيل عملية مزامنة تقويم جوجل.'; +$lang['trigger_sync_hint'] = 'Trigger the calendar synchronization process.'; $lang['appointment_updated'] = 'تم تحديث الموعد بنجاح.'; $lang['undo'] = 'تراجع'; $lang['appointment_details_changed'] = 'تم تعديل تفاصيل الموعد بنجاح'; @@ -265,13 +263,12 @@ $lang['time'] = 'الوقت'; $lang['hour'] = 'الساعة'; $lang['minute'] = 'الدقيقة'; -$lang['google_sync_completed'] = 'اكتملت مزامنة جوجل بنجاح .'; -$lang['google_sync_failed'] = 'فشلت المزامنة مع جوجل: تعذر انشاءالاتصال مع الخادم'; -$lang['select_google_calendar'] = 'اختيار تقويم جوجل'; -$lang['select_google_calendar_prompt'] = 'يرجى اختيار التقويم الذي تريد مزامنته مع مواعيدك. اذا لم تريد اختيار اي تقويم سيتم استخدام التقويم الافتراضي.'; -$lang['google_calendar_selected'] = 'تم اختيار تقويم جوجل بنجاح'; +$lang['calendar_sync_completed'] = 'اكتملت مزامنة جوجل بنجاح .'; +$lang['calendar_sync_failed'] = 'فشلت المزامنة مع جوجل: تعذر انشاءالاتصال مع الخادم'; +$lang['select_sync_calendar'] = 'اختيار تقويم جوجل'; +$lang['select_sync_calendar_prompt'] = 'يرجى اختيار التقويم الذي تريد مزامنته مع مواعيدك. اذا لم تريد اختيار اي تقويم سيتم استخدام التقويم الافتراضي.'; +$lang['sync_calendar_selected'] = 'تم اختيار تقويم جوجل بنجاح'; $lang['oops_something_went_wrong'] = 'للأسف ! حصل خطأ ما .'; -$lang['could_not_add_to_google_calendar'] = 'لا يمكن اضافة موعدك على تقويم جوجل'; $lang['ea_update_success'] = 'تم تحديث برنامج الحجوزات بنجاح'; $lang['require_captcha'] = 'مطلوب CAPTCHA'; $lang['require_captcha_hint'] = 'عند التمكين ، سيتوجب على الزبون ادخال رمز عشوائي عند الحجز او التعديل على الموعد '; @@ -305,7 +302,7 @@ $lang['website_using_cookies_to_ensure_best_experience'] = 'This website uses cookies to ensure you get the best experience on our website.'; $lang['read_and_agree_to_terms_and_conditions'] = 'I have read and agree to the {$link}Terms & Conditions{/$link}.'; $lang['read_and_agree_to_privacy_policy'] = 'I have read and agree to the {$link}Privacy Policy{/$link}.'; -$lang['delete_personal_information_hint'] = 'Delete all personal information from the system.'; +$lang['delete_personal_information_hint'] = 'Remove all your appointments and personal information from the system.'; $lang['delete_personal_information'] = 'Delete Personal Information'; $lang['delete_personal_information_prompt'] = 'Are you sure that you want to delete your personal information? This action cannot be undone.'; $lang['location'] = 'Location'; @@ -378,8 +375,8 @@ $lang['customer_delete'] = 'Customer Delete'; $lang['service_save'] = 'Service Save'; $lang['service_delete'] = 'Service Delete'; -$lang['service_category_save'] = 'Category Save'; -$lang['service_category_delete'] = 'Category Delete'; +$lang['service_category_save'] = 'Service Category Save'; +$lang['service_category_delete'] = 'Service Category Delete'; $lang['provider_save'] = 'Provider Save'; $lang['provider_delete'] = 'Provider Delete'; $lang['secretary_save'] = 'Secretary Save'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/bulgarian/translations_lang.php b/application/language/bulgarian/translations_lang.php index db6e4fb494..f95405f787 100755 --- a/application/language/bulgarian/translations_lang.php +++ b/application/language/bulgarian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Име'; $lang['appointment_link_title'] = 'Линк на часа'; $lang['success'] = 'Успех.'; -$lang['appointment_added_to_google_calendar'] = 'Вашият час бе успешно добавен във Вашият Google Calendar профил.'; -$lang['view_appointment_in_google_calendar'] = 'Натиснете тук за да прегледате часът си във Вашият Google Calendar профил.'; $lang['appointment_added_to_your_plan'] = 'Нов час бе добавен към Вашият график.'; $lang['appointment_link_description'] = 'Можете да нанесете промени на часа като използвате линкът по-долу.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'По време на периоди, в които изпълнителя не е на разположение, същият няма да приема нови часове.'; $lang['new_appointment_hint'] = 'Създаване на нов час и запазването му в базата данни.'; $lang['reload_appointments_hint'] = 'Презареждане на календарни часове.'; -$lang['trigger_google_sync_hint'] = 'Изпълнение на процес по синхронизация с Google Calendar.'; +$lang['trigger_sync_hint'] = 'Изпълнение на процес по синхронизация с Google Calendar.'; $lang['appointment_updated'] = 'Часът е актуализиран успешно.'; $lang['undo'] = 'Отмяна'; $lang['appointment_details_changed'] = 'Информацията относно часът е променена.'; @@ -199,14 +197,14 @@ $lang['enter_password_here'] = 'Въведете паролата си тук…'; $lang['login'] = 'Вход'; $lang['forgot_your_password'] = 'Забравена парола ?'; -$lang['login_failed'] = 'Вход неуспешен, моля въведете правилните данни и опитайте отново. '; +$lang['login_failed'] = 'Вход неуспешен, моля въведете правилните данни и опитайте отново. ';# $lang['type_username_and_email_for_new_password'] = 'Въведете потребителското си име и адрес на електронна поща за да получите новата си парола.'; $lang['enter_email_here'] = 'Въведете адресът на електронната Ви поща тук…'; $lang['regenerate_password'] = 'Генериране на парола'; $lang['go_to_login'] = 'Назад към страница за вход.'; $lang['new_password_sent_with_email'] = 'Вашата нова парола Ви бе изпратена чрез електронна поща.'; $lang['new_account_password'] = 'Нова парола на потребителски профил'; -$lang['new_password_is'] = 'Новата парола за потребителския профил е……… Моля запазете това електронно писмо за да може да намерите паролата си при нужда. Можете да промените паролата си в секцията за настройки на Вашия профил.'; +$lang['new_password_is'] = 'Новата парола за потребителския профил $password Моля запазете това електронно писмо за да може да намерите паролата си при нужда. Можете да промените паролата си в секцията за настройки на Вашия профил.'; $lang['delete_record_prompt'] = 'Сигурни ли Сте, че искате да заличите този запис? Това действие е необратимо'; $lang['delete_admin'] = 'Заличаване на администратор'; $lang['delete_customer'] = 'Заличаване на клиент'; @@ -265,13 +263,12 @@ $lang['time'] = 'Време'; $lang['hour'] = 'Час'; $lang['minute'] = 'Минута'; -$lang['google_sync_completed'] = 'Google синхронизацията приключи успешно.'; -$lang['google_sync_failed'] = 'Google синхронизацията неуспешна: не бе възможно да се осъществи връзка.'; -$lang['select_google_calendar'] = 'Избор на Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Изберете календарът, който искате да синхронизирате за часовете си. Ако не желаете да изберете специфичен календар, календар по подразбиране ще бъде използван.'; -$lang['google_calendar_selected'] = 'Google Calendar бе успешно избран.'; +$lang['calendar_sync_completed'] = 'Google синхронизацията приключи успешно.'; +$lang['calendar_sync_failed'] = 'Google синхронизацията неуспешна: не бе възможно да се осъществи връзка.'; +$lang['select_sync_calendar'] = 'Избор на Google Calendar'; +$lang['select_sync_calendar_prompt'] = 'Изберете календарът, който искате да синхронизирате за часовете си. Ако не желаете да изберете специфичен календар, календар по подразбиране ще бъде използван.'; +$lang['sync_calendar_selected'] = 'Google Calendar бе успешно избран.'; $lang['oops_something_went_wrong'] = 'Опааа! Нещо се обърка!Опааа! Нещо се обърка.'; -$lang['could_not_add_to_google_calendar'] = 'Вашият час не бе добавен във Вашият Google Calendar.'; $lang['ea_update_success'] = 'Системата Обновена успешно'; $lang['require_captcha'] = 'Изискване на CAPTCHA'; $lang['require_captcha_hint'] = 'Когато е активно, потребителя , ще трябва да въведе произволно генерирани символи за да запише или промени час.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/catalan/translations_lang.php b/application/language/catalan/translations_lang.php index 839648eb46..2e8dfe3519 100644 --- a/application/language/catalan/translations_lang.php +++ b/application/language/catalan/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nom'; $lang['appointment_link_title'] = 'Enllaç a la cita'; $lang['success'] = 'Correcte.'; -$lang['appointment_added_to_google_calendar'] = 'La vostra cita s\'ha afegit al vostre compte de Google Calendar.'; -$lang['view_appointment_in_google_calendar'] = 'Cliqueu aquí per veure la vostra cita al Google Calendar.'; $lang['appointment_added_to_your_plan'] = 'S\'ha afegit una nova cita a la vostra planificació.'; $lang['appointment_link_description'] = 'Podeu fer canvis clicant a l\'enllaç de la cita de sota.'; $lang['appointment_locked'] = 'La modificació no és possible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Durant els períodes de no disponibilitat el proveïdor no acceptarà noves cites.'; $lang['new_appointment_hint'] = 'Crea una nova cita i emmagatzema-la a la base de dades.'; $lang['reload_appointments_hint'] = 'Recarrega el calendari de cites.'; -$lang['trigger_google_sync_hint'] = 'Dispara el procés de sincronització amb el Google Calendar.'; +$lang['trigger_sync_hint'] = 'Dispara el procés de sincronització amb el Google Calendar.'; $lang['appointment_updated'] = 'La cita s\'ha actualitzat correctament.'; $lang['undo'] = 'Desfés'; $lang['appointment_details_changed'] = 'Els detalls de la cita han canviat.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Hora'; $lang['hour'] = 'Hora'; $lang['minute'] = 'Minut'; -$lang['google_sync_completed'] = 'La sincronització amb Google s\'ha completat correctament.'; -$lang['google_sync_failed'] = 'La sincronització amb Google ha fallat: no s\'ha pogut establir la connexió amb el servidor.'; -$lang['select_google_calendar'] = 'Selecciona un Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Seleccioneu el calendari que voleu sincronitzar amb les vostres cites. Si no seleccioneu un calendari específic, s\'usarà el calendari per defecte.'; -$lang['google_calendar_selected'] = 'El Google calendar s\'ha seleccionat correctament.'; +$lang['calendar_sync_completed'] = 'La sincronització amb Google s\'ha completat correctament.'; +$lang['calendar_sync_failed'] = 'La sincronització amb Google ha fallat: no s\'ha pogut establir la connexió amb el servidor.'; +$lang['select_sync_calendar'] = 'Selecciona un Google Calendar'; +$lang['select_sync_calendar_prompt'] = 'Seleccioneu el calendari que voleu sincronitzar amb les vostres cites. Si no seleccioneu un calendari específic, s\'usarà el calendari per defecte.'; +$lang['sync_calendar_selected'] = 'El Google calendar s\'ha seleccionat correctament.'; $lang['oops_something_went_wrong'] = 'Ups! Alguna cosa no ha funcionat bé.'; -$lang['could_not_add_to_google_calendar'] = 'La vostra cita no s\'ha pogut afegir al vostre compte de Google Calendar.'; $lang['ea_update_success'] = 'Easy!Appointments s\'ha actualitzat correctament.'; $lang['require_captcha'] = 'Requereix un CAPTCHA'; $lang['require_captcha_hint'] = 'Quan s\'habilita, els clients hauran de teclejar una cadena CAPTCHA generada aleatòriament abans de reservar o actualitzar una cita.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/chinese/translations_lang.php b/application/language/chinese/translations_lang.php index 84fe6aa4eb..9f66723a91 100755 --- a/application/language/chinese/translations_lang.php +++ b/application/language/chinese/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = '名字'; $lang['appointment_link_title'] = '预约连接'; $lang['success'] = '成功.'; -$lang['appointment_added_to_google_calendar'] = '您的预约已经添加到您的谷歌日历.'; -$lang['view_appointment_in_google_calendar'] = '点击查看在谷歌日历上的预约信息.'; $lang['appointment_added_to_your_plan'] = '新的预约添加到了您的计划。.'; $lang['appointment_link_description'] = '你可以点击下方预约链接做修改.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = '不可预约时间短内,服务人员将不能接受预约.'; $lang['new_appointment_hint'] = '在数据库中建立新的预约.'; $lang['reload_appointments_hint'] = '刷新日历.'; -$lang['trigger_google_sync_hint'] = '激活谷歌日历同步进程.'; +$lang['trigger_sync_hint'] = '激活谷歌日历同步进程.'; $lang['appointment_updated'] = '预约成功更新.'; $lang['undo'] = '撤销'; $lang['appointment_details_changed'] = '预约信息已经修改.'; @@ -265,13 +263,12 @@ $lang['time'] = '时间'; $lang['hour'] = '小时'; $lang['minute'] = '分钟'; -$lang['google_sync_completed'] = '谷歌同步成功.'; -$lang['google_sync_failed'] = '谷歌同步失败:不能建立与服务器的连接。.'; -$lang['select_google_calendar'] = '选择谷歌日历'; -$lang['select_google_calendar_prompt'] = '选择您想要同步的日历。如果您不希望选择特定的日历,那么将使用默认的日历。'; -$lang['google_calendar_selected'] = '谷歌日历被选定.'; +$lang['calendar_sync_completed'] = '谷歌同步成功.'; +$lang['calendar_sync_failed'] = '谷歌同步失败:不能建立与服务器的连接。.'; +$lang['select_sync_calendar'] = '选择谷歌日历'; +$lang['select_sync_calendar_prompt'] = '选择您想要同步的日历。如果您不希望选择特定的日历,那么将使用默认的日历。'; +$lang['sync_calendar_selected'] = '谷歌日历被选定.'; $lang['oops_something_went_wrong'] = '不好!出了一些问题.'; -$lang['could_not_add_to_google_calendar'] = '您的预约不能添加到谷歌日历.'; $lang['ea_update_success'] = '预约系统已经成功更新.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/croatian/translations_lang.php b/application/language/croatian/translations_lang.php index 4d2a519f23..bcd91cf8d5 100644 --- a/application/language/croatian/translations_lang.php +++ b/application/language/croatian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Ime'; $lang['appointment_link_title'] = 'Poveznica sastanka'; $lang['success'] = 'Uspješno.'; -$lang['appointment_added_to_google_calendar'] = 'Vaš sastanak dodan je u vaš Google kalendar.'; -$lang['view_appointment_in_google_calendar'] = 'Kliknite ovdje da biste vidjeli svoj sastanak u Google kalendaru.'; $lang['appointment_added_to_your_plan'] = 'Novi sastanak dodan je u vaš plan.'; $lang['appointment_link_description'] = 'Promjene možete napraviti klikom na poveznicu sastanka ispod.'; $lang['appointment_locked'] = 'Izmjena nemoguća.'; @@ -89,7 +87,7 @@ $lang['unavailable_periods_hint'] = 'Tijekom razdoblja kada je pružatelj nedostupan, neće prihvaćati nove sastanke.'; $lang['new_appointment_hint'] = 'Stvorite novi sastanak i pohranite ga u bazu podataka.'; $lang['reload_appointments_hint'] = 'Ponovno učitajte sastanke u kalendaru.'; -$lang['trigger_google_sync_hint'] = 'Pokrenite postupak sinkronizacije Google kalendara.'; +$lang['trigger_sync_hint'] = 'Pokrenite postupak sinkronizacije Google kalendara.'; $lang['appointment_updated'] = 'Sastanak uspješno ažuriran.'; $lang['undo'] = 'Poništi'; $lang['appointment_details_changed'] = 'Detalji sastanka su promijenjeni.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Vrijeme'; $lang['hour'] = 'Sat'; $lang['minute'] = 'Minuta'; -$lang['google_sync_completed'] = 'Google sinkronizacija uspješno završena.'; -$lang['google_sync_failed'] = 'Google sinkronizacija nije uspjela: Nije moguće uspostaviti vezu s poslužiteljem.'; -$lang['select_google_calendar'] = 'Odaberi Google Kalendar'; -$lang['select_google_calendar_prompt'] = 'Odaberite kalendar koji želite sinkronizirati s vašim terminima. Ako ne želite odabrati određeni kalendar, koristit će se zadani.'; -$lang['google_calendar_selected'] = 'Google kalendar je uspješno odabran.'; +$lang['calendar_sync_completed'] = 'Google sinkronizacija uspješno završena.'; +$lang['calendar_sync_failed'] = 'Google sinkronizacija nije uspjela: Nije moguće uspostaviti vezu s poslužiteljem.'; +$lang['select_sync_calendar'] = 'Odaberi Google Kalendar'; +$lang['select_sync_calendar_prompt'] = 'Odaberite kalendar koji želite sinkronizirati s vašim terminima. Ako ne želite odabrati određeni kalendar, koristit će se zadani.'; +$lang['sync_calendar_selected'] = 'Google kalendar je uspješno odabran.'; $lang['oops_something_went_wrong'] = 'Ups! Nešto je pošlo po zlu.'; -$lang['could_not_add_to_google_calendar'] = 'Vaš termin nije mogao biti dodan u vaš Google Kalendar račun.'; $lang['ea_update_success'] = 'Easy!Appointments je uspješno ažuriran.'; $lang['require_captcha'] = 'Zahtijevaj CAPTCHA'; $lang['require_captcha_hint'] = 'Kada je omogućeno, klijenti će morati unijeti nasumično generirani CAPTCHA niz prije rezervacije/ažuriranja termina.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/czech/translations_lang.php b/application/language/czech/translations_lang.php index 670e6f7f91..6937c19b49 100644 --- a/application/language/czech/translations_lang.php +++ b/application/language/czech/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Název'; $lang['appointment_link_title'] = 'Odkaz na schůzku'; $lang['success'] = 'Úspěch.'; -$lang['appointment_added_to_google_calendar'] = 'Vaše schůzka byla přidána do vašeho účtu v Kalendáři Google.'; -$lang['view_appointment_in_google_calendar'] = 'Pro zobrazení vaší schůzky v Kalendáři Google klikněte sem.'; $lang['appointment_added_to_your_plan'] = 'Do vašeho rozvrhu byla přidána nová schůzka.'; $lang['appointment_link_description'] = 'Editaci můžete provést kliknutím na níže uvedený odkaz na schůzku.'; $lang['appointment_locked'] = 'Nelze upravit.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'V době, kdy není poskytovatel dostupný, nelze rezervovat nové schůzky.'; $lang['new_appointment_hint'] = 'Vytvoření nové schůzky a uložení do databáze.'; $lang['reload_appointments_hint'] = 'Obnovit zobrazení schůzek v kalendáři.'; -$lang['trigger_google_sync_hint'] = 'Zahájit proces synchronizace s Kalendářem Google.'; +$lang['trigger_sync_hint'] = 'Zahájit proces synchronizace s Kalendářem Google.'; $lang['appointment_updated'] = 'Provedené změny schůzky byly úspěšně uloženy.'; $lang['undo'] = 'Zpět'; $lang['appointment_details_changed'] = 'Informace o schůzce byly změněny.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Čas'; $lang['hour'] = 'Hodina'; $lang['minute'] = 'Minuta'; -$lang['google_sync_completed'] = 'Synchronizace s Google byla úspěšně dokončena.'; -$lang['google_sync_failed'] = 'Synchronizace s Google selhala: nepodařilo se navázat spojení se serverem.'; -$lang['select_google_calendar'] = 'Vyberte Kalendář Google'; -$lang['select_google_calendar_prompt'] = 'Výberte kalendář, do kterého chcete synchronizovat vaše schůzky. Jestliže nechcete vybrat konkrétní kalendář, bude použit výchozí.'; -$lang['google_calendar_selected'] = 'Kalendář Google byl úspěšně vybrán.'; +$lang['calendar_sync_completed'] = 'Synchronizace s Google byla úspěšně dokončena.'; +$lang['calendar_sync_failed'] = 'Synchronizace s Google selhala: nepodařilo se navázat spojení se serverem.'; +$lang['select_sync_calendar'] = 'Vyberte Kalendář Google'; +$lang['select_sync_calendar_prompt'] = 'Výberte kalendář, do kterého chcete synchronizovat vaše schůzky. Jestliže nechcete vybrat konkrétní kalendář, bude použit výchozí.'; +$lang['sync_calendar_selected'] = 'Kalendář Google byl úspěšně vybrán.'; $lang['oops_something_went_wrong'] = 'Oops! Něco se pokazilo.'; -$lang['could_not_add_to_google_calendar'] = 'Vaše schůzka nemohla být přidána do vašeho Kalendáře Google.'; $lang['ea_update_success'] = 'Aplikace Easy!Appointments byla úspěšně aktualizována.'; $lang['require_captcha'] = 'Vyžadovat CAPTCHA'; $lang['require_captcha_hint'] = 'Pokud bude povolena, zákazníci budou muset před vytvořením/editací schůzky zadat náhodně vygenerovaný řetězec CAPTCHA.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/danish/translations_lang.php b/application/language/danish/translations_lang.php index ebf52a5c1a..45a6fee45c 100755 --- a/application/language/danish/translations_lang.php +++ b/application/language/danish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Navn'; $lang['appointment_link_title'] = 'Link til aftale.'; $lang['success'] = 'Gennemført.'; -$lang['appointment_added_to_google_calendar'] = 'Din aftale er blevet tilføjet til din Google kalender.'; -$lang['view_appointment_in_google_calendar'] = 'Klik her for at se din aftale i Google kalenderen. '; $lang['appointment_added_to_your_plan'] = 'En ny aftale er blevet tilføjet til din plan.'; $lang['appointment_link_description'] = 'Du kan lave ændringer ved at trykke på linket nedenfor'; $lang['appointment_locked'] = 'Ændring ikke mulig.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'I ikke tilgængelig periode kan leverandøren ikke accepertere nye aftaler.'; $lang['new_appointment_hint'] = 'Tilføj en ny aftale ller konto i databasen.'; $lang['reload_appointments_hint'] = 'Opdater kalender.'; -$lang['trigger_google_sync_hint'] = 'Udløs Google kalender synkroniseringen processen.'; +$lang['trigger_sync_hint'] = 'Trigger the calendar synchronization process.'; $lang['appointment_updated'] = 'Tiden er opdateret.'; $lang['undo'] = 'Fortryd'; $lang['appointment_details_changed'] = 'Tidens oplysninger er ændret.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tid'; $lang['hour'] = 'Time'; $lang['minute'] = 'Minutter'; -$lang['google_sync_completed'] = 'Google synkroniseringen gennemført.'; -$lang['google_sync_failed'] = 'Google synkroniseringen fejlede, kunne ikke oprette forbindelse til serveren.'; -$lang['select_google_calendar'] = 'Vælg Google kalender'; -$lang['select_google_calendar_prompt'] = 'vælg kalenderen du vile synkronisere med din bestilling. Hvis du ikke vil vælge en specifik kalender den normale vil blive brugt.'; -$lang['google_calendar_selected'] = 'Google kalender er blevet valgt.'; +$lang['calendar_sync_completed'] = 'Google synkroniseringen gennemført.'; +$lang['calendar_sync_failed'] = 'Google synkroniseringen fejlede, kunne ikke oprette forbindelse til serveren.'; +$lang['select_sync_calendar'] = 'Vælg Google kalender'; +$lang['select_sync_calendar_prompt'] = 'vælg kalenderen du vile synkronisere med din bestilling. Hvis du ikke vil vælge en specifik kalender den normale vil blive brugt.'; +$lang['sync_calendar_selected'] = 'Google kalender er blevet valgt.'; $lang['oops_something_went_wrong'] = 'Oops! Noget gik galt.'; -$lang['could_not_add_to_google_calendar'] = 'Din tid kunne ikke tilføjes din Google kalender konto'; $lang['ea_update_success'] = 'Easy!Appointments er blevet opdateret.'; $lang['require_captcha'] = 'Kræv CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -378,8 +375,8 @@ $lang['customer_delete'] = 'Customer Delete'; $lang['service_save'] = 'Service Save'; $lang['service_delete'] = 'Service Delete'; -$lang['service_category_save'] = 'Category Save'; -$lang['service_category_delete'] = 'Category Delete'; +$lang['service_category_save'] = 'Service Category Save'; +$lang['service_category_delete'] = 'Service Category Delete'; $lang['provider_save'] = 'Provider Save'; $lang['provider_delete'] = 'Provider Delete'; $lang['secretary_save'] = 'Secretary Save'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/dutch/translations_lang.php b/application/language/dutch/translations_lang.php index 8abb59b956..5ce508777b 100755 --- a/application/language/dutch/translations_lang.php +++ b/application/language/dutch/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Naam'; $lang['appointment_link_title'] = 'Afspraak link'; $lang['success'] = 'Succes.'; -$lang['appointment_added_to_google_calendar'] = 'Uw afspraak is toegevoegd aan het Google Agenda-account.'; -$lang['view_appointment_in_google_calendar'] = 'Klik hier om uw afspraak in Google Agenda bekijken.'; $lang['appointment_added_to_your_plan'] = 'Een nieuwe afspraak is toegevoegd aan uw agenda.'; $lang['appointment_link_description'] = 'U kunt wijzigingen aanbrengen door te klikken op onderstaande link van de afspraak.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Er kunnen geen nieuwe afspraken geaccepteerd worden als de medewerker niet beschikbaar is.'; $lang['new_appointment_hint'] = 'Een nieuwe afspraak maken en opslaan in de database.'; $lang['reload_appointments_hint'] = 'Herlaad de afspraken.'; -$lang['trigger_google_sync_hint'] = 'Start het Google Agenda synchronisatieproces.'; +$lang['trigger_sync_hint'] = 'Start het Google Agenda synchronisatieproces.'; $lang['appointment_updated'] = 'Afspraak succesvol bijgewerkt.'; $lang['undo'] = 'Ongedaan maken'; $lang['appointment_details_changed'] = 'Afspraakgegevens veranderd.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tijd'; $lang['hour'] = 'Uur'; $lang['minute'] = 'Minuut'; -$lang['google_sync_completed'] = 'Google synchronisatie is voltooid.'; -$lang['google_sync_failed'] = 'Google synchronisatie is mislukt: kan geen verbinding maken met de server.'; -$lang['select_google_calendar'] = 'Selecteer Google Agenda'; -$lang['select_google_calendar_prompt'] = 'Selecteer de agenda waarme uw afspraken wilt synchroniseren. Als u geen specifieke kalender selecteert zal de standaard worden gebruikt.'; -$lang['google_calendar_selected'] = 'Google Agenda is met succes geselecteerd.'; +$lang['calendar_sync_completed'] = 'Google synchronisatie is voltooid.'; +$lang['calendar_sync_failed'] = 'Google synchronisatie is mislukt: kan geen verbinding maken met de server.'; +$lang['select_sync_calendar'] = 'Selecteer Google Agenda'; +$lang['select_sync_calendar_prompt'] = 'Selecteer de agenda waarme uw afspraken wilt synchroniseren. Als u geen specifieke kalender selecteert zal de standaard worden gebruikt.'; +$lang['sync_calendar_selected'] = 'Google Agenda is met succes geselecteerd.'; $lang['oops_something_went_wrong'] = 'Oeps! Er is iets misgegaan.'; -$lang['could_not_add_to_google_calendar'] = 'Uw afspraak kon niet toegevoegd worden aan het Google Agenda-account.'; $lang['ea_update_success'] = 'Easy!Appointments is succesvol bijgewerkt.'; $lang['require_captcha'] = 'CAPTCHA vereist.'; $lang['require_captcha_hint'] = 'Indien ingeschakeld moeten de klanten een willekeurige tekenreeks invullen om een afspraak te bevestigen.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/english/translations_lang.php b/application/language/english/translations_lang.php index 0e84e0d049..d3e827abd8 100755 --- a/application/language/english/translations_lang.php +++ b/application/language/english/translations_lang.php @@ -37,7 +37,7 @@ $lang['appointment_removed_from_schedule'] = 'The following appointment was removed from the company\'s schedule.'; $lang['appointment_details_was_sent_to_you'] = 'An email with the appointment details has been sent to you.'; $lang['add_to_google_calendar'] = 'Add to Google Calendar'; -$lang['appointment_booked'] = 'Your appointment has been successfully booked.'; +$lang['appointment_booked'] = 'Your appointment has been successfully booked'; $lang['thank_you_for_appointment'] = 'Thank you for arranging an appointment with us. Below you can see the appointment details. Make changes by clicking the appointment link.'; $lang['appointment_details_title'] = 'Appointment Details'; $lang['customer_details_title'] = 'Customer Details'; @@ -49,8 +49,6 @@ $lang['name'] = 'Name'; $lang['appointment_link_title'] = 'Appointment Link'; $lang['success'] = 'Success'; -$lang['appointment_added_to_google_calendar'] = 'Your appointment has been added to your Google Calendar account.'; -$lang['view_appointment_in_google_calendar'] = 'Click here to view your appointment on Google Calendar.'; $lang['appointment_added_to_your_plan'] = 'A new appointment has been added to your plan.'; $lang['appointment_link_description'] = 'You can make changes by clicking the appointment link below.'; $lang['appointment_locked'] = 'Modification impossible!'; @@ -80,7 +78,7 @@ $lang['all_day'] = 'All Day'; $lang['manage_appointment_record_hint'] = 'Manage all the appointment records of the available providers and services.'; $lang['select_filter_item_hint'] = 'Select a provider or a service and view the appointments on the calendar.'; -$lang['enable_appointment_sync_hint'] = 'Enable appointment synchronization with provider\'s Google Calendar account.'; +$lang['enable_appointment_sync_hint'] = 'Enable appointment synchronization with an external calendar.'; $lang['manage_customers_hint'] = 'Manage the registered customers and view their booking history.'; $lang['manage_services_hint'] = 'Manage the available services and categories of the system.'; $lang['manage_users_hint'] = 'Manage the backend users (admins, providers, secretaries).'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'During unavailability periods the provider won\'t accept new appointments.'; $lang['new_appointment_hint'] = 'Create a new appointment and store it into the database.'; $lang['reload_appointments_hint'] = 'Reload calendar appointments.'; -$lang['trigger_google_sync_hint'] = 'Trigger the Google Calendar synchronization process.'; +$lang['trigger_sync_hint'] = 'Trigger the calendar synchronization process.'; $lang['appointment_updated'] = 'Appointment updated successfully.'; $lang['undo'] = 'Undo'; $lang['appointment_details_changed'] = 'Appointment details have changed'; @@ -265,13 +263,12 @@ $lang['time'] = 'Time'; $lang['hour'] = 'Hour'; $lang['minute'] = 'Minute'; -$lang['google_sync_completed'] = 'Google synchronization completed successfully.'; -$lang['google_sync_failed'] = 'Google synchronization failed: Could not establish server connection.'; -$lang['select_google_calendar'] = 'Select Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Select the calendar that you want to sync your appointments. If you do not want to select a specific calendar the default one will be used.'; -$lang['google_calendar_selected'] = 'Google calendar has been successfully selected.'; +$lang['calendar_sync_completed'] = 'Calendar synchronization completed successfully.'; +$lang['calendar_sync_failed'] = 'Calendar synchronization failed: Could not establish server connection.'; +$lang['select_sync_calendar'] = 'Select Calendar'; +$lang['select_sync_calendar_prompt'] = 'Select the calendar that you want to sync your appointments with.'; +$lang['sync_calendar_selected'] = 'Sync calendar has been successfully selected.'; $lang['oops_something_went_wrong'] = 'Oops! Something Went Wrong.'; -$lang['could_not_add_to_google_calendar'] = 'Your appointment could not be added to your Google Calendar account.'; $lang['ea_update_success'] = 'Easy!Appointments has been successfully updated.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/estonian/translations_lang.php b/application/language/estonian/translations_lang.php index f3b0164685..ad535629a7 100644 --- a/application/language/estonian/translations_lang.php +++ b/application/language/estonian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nimi'; $lang['appointment_link_title'] = 'Broneeringu link'; $lang['success'] = 'Õnnestus.'; -$lang['appointment_added_to_google_calendar'] = 'Broneering lisati Google\'i kalendrisse.'; -$lang['view_appointment_in_google_calendar'] = 'Vaata broneeringut Google\'i kalendris.'; $lang['appointment_added_to_your_plan'] = 'Kalendrisse on lisatud broneering.'; $lang['appointment_link_description'] = 'Muudatusi saad teha klõpsates allolevat broneeringu linki.'; $lang['appointment_locked'] = 'Muudatusi ei saa teha.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Teenusepakkuja äraolekujale ei saa broneeringuid teha.'; $lang['new_appointment_hint'] = 'Loo uus broneering ja salvesta see kalendrisse.'; $lang['reload_appointments_hint'] = 'Värskenda broneeringute kalendri vaadet.'; -$lang['trigger_google_sync_hint'] = 'Sünkroniseeri Google\'iga.'; +$lang['trigger_sync_hint'] = 'Sünkroniseeri Google\'iga.'; $lang['appointment_updated'] = 'Broneeringu muutmine õnnestus.'; $lang['undo'] = 'Võta tagasi'; $lang['appointment_details_changed'] = 'Broneeringu detailid on muutunud.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Aeg'; $lang['hour'] = 'Tund'; $lang['minute'] = 'Minut'; -$lang['google_sync_completed'] = 'Google\'iga sünkroniseerimine õnnestus.'; -$lang['google_sync_failed'] = 'Google\'iga sünkroniseerimine ebaõnnestus. Serveriga ei saadud ühendust.'; -$lang['select_google_calendar'] = 'Vali Google\'i kalender'; -$lang['select_google_calendar_prompt'] = 'Vali kalender kuhu broneeringud sünkroniseeristakse. Kui kalendrit ei vali, siis kasutatakse vaikimisi kalendrit.'; -$lang['google_calendar_selected'] = 'Google\'i kalender valitud.'; +$lang['calendar_sync_completed'] = 'Google\'iga sünkroniseerimine õnnestus.'; +$lang['calendar_sync_failed'] = 'Google\'iga sünkroniseerimine ebaõnnestus. Serveriga ei saadud ühendust.'; +$lang['select_sync_calendar'] = 'Vali Google\'i kalender'; +$lang['select_sync_calendar_prompt'] = 'Vali kalender kuhu broneeringud sünkroniseeristakse. Kui kalendrit ei vali, siis kasutatakse vaikimisi kalendrit.'; +$lang['sync_calendar_selected'] = 'Google\'i kalender valitud.'; $lang['oops_something_went_wrong'] = 'Ohhhoo! Midagi läks untsu.'; -$lang['could_not_add_to_google_calendar'] = 'Broneeringu lisamine Google\'i kalendrisse ebaõnnestus.'; $lang['ea_update_success'] = 'Easy!Appointments uuendus õnnestus.'; $lang['require_captcha'] = 'Nõua CAPTCHA-t'; $lang['require_captcha_hint'] = 'Kui see on sisse lülitatud, siis nõutakse kasutajalt CAPTCHA-t enne broneeringu lisamist/muutmist.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/finnish/translations_lang.php b/application/language/finnish/translations_lang.php index b268289a04..686923cec2 100755 --- a/application/language/finnish/translations_lang.php +++ b/application/language/finnish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nimi'; $lang['appointment_link_title'] = 'Varauslinkki'; $lang['success'] = 'Onnistui.'; -$lang['appointment_added_to_google_calendar'] = 'Varauksesi lisättiin Google-kalenteriisi.'; -$lang['view_appointment_in_google_calendar'] = 'Klikkaa näyttääksesi varaustiedot Google-kalenterissa.'; $lang['appointment_added_to_your_plan'] = 'Suunnitelmaasi lisättiin varaus.'; $lang['appointment_link_description'] = 'Voit tehdä muutoksia klikkaamalla alla olevaa varauslinkkiä.'; $lang['appointment_locked'] = 'Muokkaus ei ole mahdollista.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Aika'; $lang['hour'] = 'tunti'; $lang['minute'] = 'minuutti'; -$lang['google_sync_completed'] = 'Google synkronointi onnistui.'; -$lang['google_sync_failed'] = 'Google synkronointi epäonnistui: Palvelimeen ei saatu muodostettua yhteyttä.'; -$lang['select_google_calendar'] = 'Valitse Google-kalenteri'; -$lang['select_google_calendar_prompt'] = 'Valitse kalenteri johon varauksesi synkronoidaan. Jos et valitse kalenteria, käytetään oletuskalenteria.'; -$lang['google_calendar_selected'] = 'Google-kalenteri valittiin onnistuneesti.'; +$lang['calendar_sync_completed'] = 'Google synkronointi onnistui.'; +$lang['calendar_sync_failed'] = 'Google synkronointi epäonnistui: Palvelimeen ei saatu muodostettua yhteyttä.'; +$lang['select_sync_calendar'] = 'Valitse Google-kalenteri'; +$lang['select_sync_calendar_prompt'] = 'Valitse kalenteri johon varauksesi synkronoidaan. Jos et valitse kalenteria, käytetään oletuskalenteria.'; +$lang['sync_calendar_selected'] = 'Google-kalenteri valittiin onnistuneesti.'; $lang['oops_something_went_wrong'] = 'Oho! Jotain meni pieleen.'; -$lang['could_not_add_to_google_calendar'] = 'Varaustasi ei pystytty lisäämään Google-kalenteri tiliisi.'; $lang['ea_update_success'] = 'Easy!Appointments päivitettiin onnistuneesti.'; $lang['require_captcha'] = 'Vaadi CAPTCHA'; $lang['require_captcha_hint'] = 'Jos aktivoitu, asiakkaan pitää kirjoittaa satunnainen CAPTCHA varmennus ennen varauksen lisäämistä/päivittämistä.'; @@ -464,4 +461,8 @@ $lang['default_timezone_hint'] = 'Tämä tulee uusien käyttäjien ja varausten oletusaikavyöhykkeeksi'; $lang['default_language'] = 'Oletuskieli'; $lang['default_language_hint'] = 'Tämä tulee uusien käyttäjien oletuskieleksi'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/french/translations_lang.php b/application/language/french/translations_lang.php index 5549acd0e7..50131a441f 100755 --- a/application/language/french/translations_lang.php +++ b/application/language/french/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nom'; $lang['appointment_link_title'] = 'Lien du rendez-vous'; $lang['success'] = 'Succès.'; -$lang['appointment_added_to_google_calendar'] = 'Votre rendez-vous a été ajouté à votre compte calendrier Google.'; -$lang['view_appointment_in_google_calendar'] = 'Cliquez ici pour voir votre rendez-vous dans le calendrier Google.'; $lang['appointment_added_to_your_plan'] = 'Un nouveau rendez-vous a été ajouté à votre planning.'; $lang['appointment_link_description'] = 'Vous pouvez faire des modifications en cliquant sur le lien suivant.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Durant les périodes d’indisponibilité l’exécutant n’acceptera pas de nouvelle prestation.'; $lang['new_appointment_hint'] = 'Créer un nouveau rendez-vous et le stocker dans la base de données.'; $lang['reload_appointments_hint'] = 'Actualiser le calendrier des rendez-vous.'; -$lang['trigger_google_sync_hint'] = 'Démarrer la procédure de synchronisation du calendrier Google.'; +$lang['trigger_sync_hint'] = 'Démarrer la procédure de synchronisation du calendrier Google.'; $lang['appointment_updated'] = 'Rendez-vous mis à jour avec succès.'; $lang['undo'] = 'Annuler'; $lang['appointment_details_changed'] = 'Les détails du rendez-vous ont bien été modifiés.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Heure du RDV'; $lang['hour'] = 'Heure'; $lang['minute'] = 'Minute'; -$lang['google_sync_completed'] = 'La synchronisation Google s’est terminée avec succès.'; -$lang['google_sync_failed'] = 'La synchronisation Google a échoué : Échec de connexion avec le serveur.'; -$lang['select_google_calendar'] = 'Choisir un calendrier Google'; -$lang['select_google_calendar_prompt'] = 'Sélectionnez le calendrier souhaité pour synchroniser votre rendez-vous. Si vous ne sélectionnez pas de calendrier spécifique, le calendrier par défaut sera sélectionné pour vous.'; -$lang['google_calendar_selected'] = 'Le calendrier Google a été sélectionné avec succès.'; +$lang['calendar_sync_completed'] = 'La synchronisation Google s\'est terminée avec succès.'; +$lang['calendar_sync_failed'] = 'La synchronisation Google a échoué : Échec de connexion avec le serveur.'; +$lang['select_sync_calendar'] = 'Choisir un calendrier Google'; +$lang['select_sync_calendar_prompt'] = 'Sélectionnez le calendrier souhaité pour synchroniser votre rendez-vous. Si vous ne sélectionnez pas de calendrier spécifique, le calendrier par défaut sera sélectionné pour vous.'; +$lang['sync_calendar_selected'] = 'Le calendrier Google a été sélectionné avec succès.'; $lang['oops_something_went_wrong'] = 'Oups ! Une erreur s’est produite.'; -$lang['could_not_add_to_google_calendar'] = 'Votre rendez-vous ne peut pas être ajouté à votre calendrier Google.'; $lang['ea_update_success'] = 'Easy!Appointments à été mis à jour avec succès.'; $lang['require_captcha'] = 'CAPTCHA obligatoire'; $lang['require_captcha_hint'] = 'Lorsque l’option est activée, les clients doivent taper un code de vérification CAPTCHA avant de pouvoir réserver ou mettre à jour un rendez-vous.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/german/translations_lang.php b/application/language/german/translations_lang.php index 76f01fa14e..ca8f9894a0 100755 --- a/application/language/german/translations_lang.php +++ b/application/language/german/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Name'; $lang['appointment_link_title'] = 'Termin-Link'; $lang['success'] = 'Erfolg.'; -$lang['appointment_added_to_google_calendar'] = 'Ihr Termin ist zu Ihrem Google-Kalender Konto hinzugefügt worden.'; -$lang['view_appointment_in_google_calendar'] = 'Bitte klicken Sie hier, um Ihren Termin im Google-Kalender zu sehen.'; $lang['appointment_added_to_your_plan'] = 'Ein neuer Termin ist zu Ihrer Planung hinzugefügt worden.'; $lang['appointment_link_description'] = 'Sie können Änderungen durch Klicken auf den Termin-Link durchführen.'; $lang['appointment_locked'] = 'Änderungen unmöglich.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'In diesem Zeitraum werden neue Termine vom Anbieter nicht akzeptiert.'; $lang['new_appointment_hint'] = 'Bestimmen Sie einen neuen Termin und sichern Sie ihn in der Datenbank.'; $lang['reload_appointments_hint'] = 'Kalendertermine neu laden.'; -$lang['trigger_google_sync_hint'] = 'Starten Sie den Synchronisationsprozess von Google-Kalender.'; +$lang['trigger_sync_hint'] = 'Starten Sie den Synchronisationsprozess von Google-Kalender.'; $lang['appointment_updated'] = 'Die Termine sind erfolgreich erneuert worden.'; $lang['undo'] = 'Schritt zurück'; $lang['appointment_details_changed'] = 'Die Termindetails haben sich geändert.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Zeit'; $lang['hour'] = 'Uhr'; $lang['minute'] = 'Minute'; -$lang['google_sync_completed'] = 'Google-Synchronisation erfolgreich beendet.'; -$lang['google_sync_failed'] = 'Google-Synchronisation fehlgeschlagen: Server-Verbindung konnte nicht hergestellt werden.'; -$lang['select_google_calendar'] = 'Wählen Sie Google Kalender'; -$lang['select_google_calendar_prompt'] = 'Wählen Sie den Kalender, mit dem Sie Ihre Termine synchronisieren möchten. Wenn Sie das nicht wollen, wird ein Standard-Kalender verwendet.'; -$lang['google_calendar_selected'] = 'Google-Kalender wurde erfolgreich ausgewählt.'; +$lang['calendar_sync_completed'] = 'Google-Synchronisation erfolgreich beendet.'; +$lang['calendar_sync_failed'] = 'Google-Synchronisation fehlgeschlagen: Server-Verbindung konnte nicht hergestellt werden.'; +$lang['select_sync_calendar'] = 'Wählen Sie Google Kalender'; +$lang['select_sync_calendar_prompt'] = 'Wählen Sie den Kalender, mit dem Sie Ihre Termine synchronisieren möchten. Wenn Sie das nicht wollen, wird ein Standard-Kalender verwendet.'; +$lang['sync_calendar_selected'] = 'Google-Kalender wurde erfolgreich ausgewählt.'; $lang['oops_something_went_wrong'] = 'Oops! Etwas ist schiefgelaufen.'; -$lang['could_not_add_to_google_calendar'] = 'Ihr Termin konnte nicht im Google-Kalender-Konto hinzugefügt werden.'; $lang['ea_update_success'] = 'Easy!Appointments wurde erfolgreich aktualisiert.'; $lang['require_captcha'] = 'CAPTCHA erfordern'; $lang['require_captcha_hint'] = 'Wenn aktiv, werden die Kunden aufgefordert, eine zufällig generierte Zeichenfolge (CAPTCHA) einzutippen bevor Sie einen Termin buchen oder speichern können.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/greek/translations_lang.php b/application/language/greek/translations_lang.php index 00a8f0a320..7b1857207f 100755 --- a/application/language/greek/translations_lang.php +++ b/application/language/greek/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Όνομα'; $lang['appointment_link_title'] = 'Σύνδεσμος Ραντεβού'; $lang['success'] = 'Επιτυχία.'; -$lang['appointment_added_to_google_calendar'] = 'Το ραντεβού έχει προστεθεί στον λογαριασμό σας στο Google Calendar.'; -$lang['view_appointment_in_google_calendar'] = 'Πατήστε εδώ για να δείτε το ραντεβού στο Google Calendar.'; $lang['appointment_added_to_your_plan'] = 'Ένα νέο ραντεβού έχει προστεθεί στο πλάνο σας.'; $lang['appointment_link_description'] = 'Μπορείτε να πραγματοποιήσετε αλλαγές πατώντας στον σύνδεσμο του ραντεβού.'; $lang['appointment_locked'] = 'Αδύνατη η τροποποίηση.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Κατά την διάρκεια των μη διαθέσιμων διαστημάτων οι πάροχοι δε θα δέχονται νέα ραντεβού.'; $lang['new_appointment_hint'] = 'Δημιουργείστε ένα νέο ραντεβού και αποθηκεύστε το στην βάση δεδομένων.'; $lang['reload_appointments_hint'] = 'Επαναφορτώστε τα ραντεβού του ημερολογίου.'; -$lang['trigger_google_sync_hint'] = 'Εκκινήστε την διαδικασία συγχρονισμού με το Google Calendar.'; +$lang['trigger_sync_hint'] = 'Εκκινήστε την διαδικασία συγχρονισμού με το Google Calendar.'; $lang['appointment_updated'] = 'Το ραντεβού ενημερώθηκε επιτυχώς.'; $lang['undo'] = 'Αναίρεση'; $lang['appointment_details_changed'] = 'Τα στοιχεία του ραντεβού έχουν αλλάξει.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Χρόνος'; $lang['hour'] = 'Ώρα'; $lang['minute'] = 'Λεπτά'; -$lang['google_sync_completed'] = 'Ο συγχρονισμός με την Google ολοκληρώθηκε επιτυχώς.'; -$lang['google_sync_failed'] = 'Ο συγχρονισμός με την Google απέτυχε: Δεν μπόρεσε να πραγματοποιηθεί σύνδεση με τον server.'; -$lang['select_google_calendar'] = 'Επιλογή Ημερολογίου της Google'; -$lang['select_google_calendar_prompt'] = 'Επιλέξτε το ημερολόγιο στο οποίο θέλετε να συγχρονίζεται τα ραντεβού σας. Εάν δεν θελήσετε να επιλέξετε ένα συγκεκριμένο ημερολόγιο θα χρησιμοποιηθεί το προεπιλεγμένο.'; -$lang['google_calendar_selected'] = 'Το ημερολόγιο της Google επιλέχθηκε επιτυχώς.'; +$lang['calendar_sync_completed'] = 'Ο συγχρονισμός με την Google ολοκληρώθηκε επιτυχώς.'; +$lang['calendar_sync_failed'] = 'Ο συγχρονισμός με την Google απέτυχε: Δεν μπόρεσε να πραγματοποιηθεί σύνδεση με τον server.'; +$lang['select_sync_calendar'] = 'Επιλογή Ημερολογίου της Google'; +$lang['select_sync_calendar_prompt'] = 'Επιλέξτε το ημερολόγιο στο οποίο θέλετε να συγχρονίζεται τα ραντεβού σας. Εάν δεν θελήσετε να επιλέξετε ένα συγκεκριμένο ημερολόγιο θα χρησιμοποιηθεί το προεπιλεγμένο.'; +$lang['sync_calendar_selected'] = 'Το ημερολόγιο της Google επιλέχθηκε επιτυχώς.'; $lang['oops_something_went_wrong'] = 'Ώχ! Κάτι πήγε στραβά.'; -$lang['could_not_add_to_google_calendar'] = 'Το ραντεβού σας δεν μπόρεσε να προστεθεί στον λογαριασμό σας στο Google Calendar.'; $lang['ea_update_success'] = 'Το Easy!Appointments ενημερώθηκε με επιτυχία.'; $lang['require_captcha'] = 'Απαίτηση CAPTCHA'; $lang['require_captcha_hint'] = 'Όταν είναι ενεργοποιημένο, οι πελάτες θα χρειαστεί να πληκτρολογήσουν μια τυχαία παραγόμενη συμβολοσειρά CAPTCHA πριν κλείσουν/αποθηκεύσουν ένα ραντεβού.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/hebrew/translations_lang.php b/application/language/hebrew/translations_lang.php index 64a22fcb1e..6443a4b59d 100644 --- a/application/language/hebrew/translations_lang.php +++ b/application/language/hebrew/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'שם'; $lang['appointment_link_title'] = 'קישור לפרטי הפגישה'; $lang['success'] = 'הצלחה!'; -$lang['appointment_added_to_google_calendar'] = 'הפגישה שלך נוספה לחשבון יומן הגוגל שלך.'; -$lang['view_appointment_in_google_calendar'] = 'לחץ כאן לצפייה בפגישה שלך ביומן גוגל.'; $lang['appointment_added_to_your_plan'] = 'פגישה חדשה נוספה לתוכנית שלך.'; $lang['appointment_link_description'] = 'ניתן לבצע שינויים על ידי לחיצה על קישור הפגישה למטה.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'במהלך המועדים אשר אינם זמינים הספק לא יקבל פגישות חדשות.'; $lang['new_appointment_hint'] = 'צור פגישה חדשה ושמור אותה במסד הנתונים.'; $lang['reload_appointments_hint'] = 'ריענון יומן הפגישות.'; -$lang['trigger_google_sync_hint'] = 'הפעלת תהליך הסנכרון של יומן גוגל.'; +$lang['trigger_sync_hint'] = 'הפעלת תהליך הסנכרון של יומן גוגל.'; $lang['appointment_updated'] = 'הפגישה עודכנה בהצלחה!'; $lang['undo'] = 'לבטל'; $lang['appointment_details_changed'] = 'פרטי הפגישה השתנו.'; @@ -265,13 +263,12 @@ $lang['time'] = 'זמן'; $lang['hour'] = 'שעה'; $lang['minute'] = 'דקות'; -$lang['google_sync_completed'] = 'הסנכרון ל גוגל הושלם בהצלחה!'; -$lang['google_sync_failed'] = 'הסנכרון ל גוגל נכשל: לא ניתן היה ליצור חיבור שרת.'; -$lang['select_google_calendar'] = 'בחירת יומן גוגל'; -$lang['select_google_calendar_prompt'] = 'יש לבחור את יומן שברצונך לסנכרן אליו את הפגישות שלך. אם אינך רוצה לבחור יומן ספציפי, היומן הראשי ישמש את ברירת המחדל.'; -$lang['google_calendar_selected'] = 'יומן גוגל נבחר בהצלחה!'; +$lang['calendar_sync_completed'] = 'הסנכרון ל גוגל הושלם בהצלחה!'; +$lang['calendar_sync_failed'] = 'הסנכרון ל גוגל נכשל: לא ניתן היה ליצור חיבור שרת.'; +$lang['select_sync_calendar'] = 'בחירת יומן גוגל'; +$lang['select_sync_calendar_prompt'] = 'יש לבחור את יומן שברצונך לסנכרן אליו את הפגישות שלך. אם אינך רוצה לבחור יומן ספציפי, היומן הראשי ישמש את ברירת המחדל.'; +$lang['sync_calendar_selected'] = 'יומן גוגל נבחר בהצלחה!'; $lang['oops_something_went_wrong'] = 'אופס! משהו השתבש!'; -$lang['could_not_add_to_google_calendar'] = 'לא ניתן להוסיף את הפגישה לחשבון יומן הגוגל שלך.'; $lang['ea_update_success'] = 'Easy!Appointments עודכן בהצלחה!'; $lang['require_captcha'] = 'דרוש CAPTCHA'; $lang['require_captcha_hint'] = 'כאשר אפשרות זו מופעלת, הלקוחות יצטרכו להקליד מחרוזת CAPTCHA אקראית לפני שהם מזמינים / מעדכנים פגישה.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/hindi/translations_lang.php b/application/language/hindi/translations_lang.php index 68588f895a..46b6bebdff 100755 --- a/application/language/hindi/translations_lang.php +++ b/application/language/hindi/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'नाम'; $lang['appointment_link_title'] = 'अपॉइंटमेंट की लिंक'; $lang['success'] = 'सफलता.'; -$lang['appointment_added_to_google_calendar'] = 'आपकी अपॉइंटमेंट अपने गूगल कैलेंडर खाते में जोड़ दिया गया है.'; -$lang['view_appointment_in_google_calendar'] = 'गूगल कैलेंडर पर आपकी अपॉइंटमेंट को देखने के लिए यहां क्लिक करें.'; $lang['appointment_added_to_your_plan'] = 'एक नई अपॉइंटमेंट आपकी योजना के लिए जोड़ा गया है।'; $lang['appointment_link_description'] = 'आप नीचे दिए गए अपॉइंटमेंट लिंक पर क्लिक करके परिवर्तन कर सकते हैं।'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'अनुपलब्ध अवधि के दौरान प्रदाता नई अपॉइंटमेंट को स्वीकार नहीं करेगा.'; $lang['new_appointment_hint'] = 'एक नई अपॉइंटमेंट बनाएँ और डेटाबेस में स्टोर.'; $lang['reload_appointments_hint'] = 'कैलेंडर अपॉइंटमेंट को पुनः लोड करें.'; -$lang['trigger_google_sync_hint'] = 'गूगल कैलेंडर तुल्यकालन प्रक्रिया को ट्रिगर करें.'; +$lang['trigger_sync_hint'] = 'गूगल कैलेंडर तुल्यकालन प्रक्रिया को ट्रिगर करें.'; $lang['appointment_updated'] = 'अपॉइंटमेंट अप्डैटिड सक्सेस्फल.'; $lang['undo'] = 'अन्डू'; $lang['appointment_details_changed'] = 'अपॉइंटमेंट विवरण बदल गया है.'; @@ -265,13 +263,12 @@ $lang['time'] = 'समय'; $lang['hour'] = 'घंटा'; $lang['minute'] = 'मिनट'; -$lang['google_sync_completed'] = 'गूगल तुल्यकालन सफलतापूर्वक पूरा हुआ'; -$lang['google_sync_failed'] = 'गूगल तुल्यकालन विफल: सर्वर कनेक्शन स्थापित नहीं किया जा सका'; -$lang['select_google_calendar'] = 'गूगल कैलेंडर का चयन करें'; -$lang['select_google_calendar_prompt'] = 'आप अपने नियुक्तियों सिंक करना चाहते हैं कि कैलेंडर का चयन करें। यदि आप एक विशिष्ट कैलेंडर का चयन नहीं करना चाहते हैं, तो डिफ़ॉल्ट रूप से एक का प्रयोग किया जाएगा'; -$lang['google_calendar_selected'] = 'गूगल कैलेंडर सफलतापूर्वक चयनित किया गया है'; +$lang['calendar_sync_completed'] = 'गूगल तुल्यकालन सफलतापूर्वक पूरा हुआ'; +$lang['calendar_sync_failed'] = 'गूगल तुल्यकालन विफल: सर्वर कनेक्शन स्थापित नहीं किया जा सका'; +$lang['select_sync_calendar'] = 'गूगल कैलेंडर का चयन करें'; +$lang['select_sync_calendar_prompt'] = 'आप अपने नियुक्तियों सिंक करना चाहते हैं कि कैलेंडर का चयन करें। यदि आप एक विशिष्ट कैलेंडर का चयन नहीं करना चाहते हैं, तो डिफ़ॉल्ट रूप से एक का प्रयोग किया जाएगा'; +$lang['sync_calendar_selected'] = 'गूगल कैलेंडर सफलतापूर्वक चयनित किया गया है'; $lang['oops_something_went_wrong'] = 'उफ़! कुछ गलत हो गया'; -$lang['could_not_add_to_google_calendar'] = 'अपनी अपॉइंटमेंट अपने गूगल कैलेंडर खाते में जोड़ा नहीं जा सका'; $lang['ea_update_success'] = 'आसान! अपॉइंटमेंट सफलतापूर्वक अद्यतन किया गया है.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/hungarian/translations_lang.php b/application/language/hungarian/translations_lang.php index f5d8269ce6..dab5bb1fe3 100755 --- a/application/language/hungarian/translations_lang.php +++ b/application/language/hungarian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Név'; $lang['appointment_link_title'] = 'Link a foglaláshoz'; $lang['success'] = 'Sikerült.'; -$lang['appointment_added_to_google_calendar'] = 'Az időpontod hozzá lett adva a Google naptáradhoz.'; -$lang['view_appointment_in_google_calendar'] = 'Kattints ide, hogy megnézhesd az idopontod as Google naptárban.'; $lang['appointment_added_to_your_plan'] = 'Egy új időpont került a naptáradba.'; $lang['appointment_link_description'] = 'Változtatni az időpont linkjére kattintva tudsz.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Az foglalt időpontokban a szolgáltató nem fogad új bejelentkezéseket.'; $lang['new_appointment_hint'] = 'Új időpont készítése és adatbázisba történő mentése.'; $lang['reload_appointments_hint'] = 'Az időpontok újra töltése.'; -$lang['trigger_google_sync_hint'] = 'Google naptárral való szinkronizálás indítása.'; +$lang['trigger_sync_hint'] = 'Google naptárral való szinkronizálás indítása.'; $lang['appointment_updated'] = 'Az időpont sikeresen frissítve.'; $lang['undo'] = 'Undo'; $lang['appointment_details_changed'] = 'A foglalás részletei megváltoztak.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Idő'; $lang['hour'] = 'Idő'; $lang['minute'] = 'Perc'; -$lang['google_sync_completed'] = 'A Google szinkronizálás sikerült.'; -$lang['google_sync_failed'] = 'A Google szinkronizálás nem sikerült: nem jött létre a kapcsolat a szerverrel.'; -$lang['select_google_calendar'] = 'Válassz Google naptárat.'; -$lang['select_google_calendar_prompt'] = 'Válaszd ki az időpontokkal szinkronizálni kívánt naptárat. Amennyiben nem kívánsz naptárat választani úgy az alapértelmezett lesz használva.'; -$lang['google_calendar_selected'] = 'A Google naptár sikeresen kiválasztva.'; +$lang['calendar_sync_completed'] = 'A Google szinkronizálás sikerült.'; +$lang['calendar_sync_failed'] = 'A Google szinkronizálás nem sikerült: nem jött létre a kapcsolat a szerverrel.'; +$lang['select_sync_calendar'] = 'Válassz Google naptárat.'; +$lang['select_sync_calendar_prompt'] = 'Válaszd ki az időpontokkal szinkronizálni kívánt naptárat. Amennyiben nem kívánsz naptárat választani úgy az alapértelmezett lesz használva.'; +$lang['sync_calendar_selected'] = 'A Google naptár sikeresen kiválasztva.'; $lang['oops_something_went_wrong'] = 'Hoppá! Valami balul sült el.'; -$lang['could_not_add_to_google_calendar'] = 'Az időpontot nem tudtuk hozzá adni a Google naptáradhoz.'; $lang['ea_update_success'] = 'Foglalj időpontot a ...'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/italian/translations_lang.php b/application/language/italian/translations_lang.php index abada81e33..05027da730 100755 --- a/application/language/italian/translations_lang.php +++ b/application/language/italian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nome'; $lang['appointment_link_title'] = 'Link appuntamento'; $lang['success'] = 'Successo.'; -$lang['appointment_added_to_google_calendar'] = 'Il tuo appuntamento è stato aggiunto al tuo account Google Calendar.'; -$lang['view_appointment_in_google_calendar'] = 'Clicca qui per visualizzare il tuo appuntamento su Google Calendar.'; $lang['appointment_added_to_your_plan'] = 'Un nuovo appuntamento è stato aggiunto alla tua agenda.'; $lang['appointment_link_description'] = 'Puoi modificare l\'appuntamento facendo click sul link sotto.'; $lang['appointment_locked'] = 'Modifica impossibile.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Durante i periodi di indisponibilità il fornitore non vuole accettare nuovi appuntamenti.'; $lang['new_appointment_hint'] = 'Crea un nuovo appuntamento e memorizzalo nel database.'; $lang['reload_appointments_hint'] = 'Ricarica gli appuntamenti a calendario.'; -$lang['trigger_google_sync_hint'] = 'Avvia il processo di sincronizzazione con Google Calendar.'; +$lang['trigger_sync_hint'] = 'Avvia il processo di sincronizzazione con Google Calendar.'; $lang['appointment_updated'] = 'Appuntamento aggiornato con successo.'; $lang['undo'] = 'Annulla'; $lang['appointment_details_changed'] = 'I dettagli dell\'appuntamento sono cambiati.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tempo'; $lang['hour'] = 'Ora'; $lang['minute'] = 'Minuto'; -$lang['google_sync_completed'] = 'Sincronizzazione con Google completata con successo.'; -$lang['google_sync_failed'] = 'Sincronizzazione con Google fallita: Non è stato possibile stabilire una connessione col server.'; -$lang['select_google_calendar'] = 'Seleziona Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Seleziona il calendario con cui vuoi sincronizzare i tuoi appuntamenti. Se non vuoi selezionare un calendario specifico, sarà usato quello predefinito.'; -$lang['google_calendar_selected'] = 'Il calendario Google è stato selezionato con successo.'; +$lang['calendar_sync_completed'] = 'Sincronizzazione con Google completata con successo.'; +$lang['calendar_sync_failed'] = 'Sincronizzazione con Google fallita: Non è stato possibile stabilire una connessione col server.'; +$lang['select_sync_calendar'] = 'Seleziona Google Calendar'; +$lang['select_sync_calendar_prompt'] = 'Seleziona il calendario con cui vuoi sincronizzare i tuoi appuntamenti. Se non vuoi selezionare un calendario specifico, sarà usato quello predefinito.'; +$lang['sync_calendar_selected'] = 'Il calendario Google è stato selezionato con successo.'; $lang['oops_something_went_wrong'] = 'Oops! Qualcosa è andato storto.'; -$lang['could_not_add_to_google_calendar'] = 'Il tuo appuntamento potrebbe non essere stato aggiunto al tuo account Google Calendar.'; $lang['ea_update_success'] = 'Easy!Appointments è stato aggiornato con successo.'; $lang['require_captcha'] = 'Richiedi CAPTCHA'; $lang['require_captcha_hint'] = 'Quando abilitato, i clienti dovranno digitare il codice CAPTCHA prima di prenotare/aggiornare un appuntamento.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/japanese/translations_lang.php b/application/language/japanese/translations_lang.php index b50d51191a..38589f5f69 100755 --- a/application/language/japanese/translations_lang.php +++ b/application/language/japanese/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = '名前'; $lang['appointment_link_title'] = '予約へのリンク'; $lang['success'] = '成功'; -$lang['appointment_added_to_google_calendar'] = 'お客様の予約スケジュールがGoogleカレンダーに登録されました。'; -$lang['view_appointment_in_google_calendar'] = 'Googleカレンダーを確認するにはこちらをクリックしてください。'; $lang['appointment_added_to_your_plan'] = 'あなたへの新しい予約が追加されました。'; $lang['appointment_link_description'] = '予約リンクをクリックすると変更が可能です。'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = '都合が悪い期間は、担当者は新しい予約を受けられません。During unavailability periods the provider won\'t accept new appointments.'; $lang['new_appointment_hint'] = '新しい予約を作成してデータベースへ追加します。'; $lang['reload_appointments_hint'] = 'カレンダーを再読み込みします。'; -$lang['trigger_google_sync_hint'] = 'Googleカレンダーとの同期を開始します。'; +$lang['trigger_sync_hint'] = 'Googleカレンダーとの同期を開始します。'; $lang['appointment_updated'] = '予約情報が更新されました。'; $lang['undo'] = 'やり直し'; $lang['appointment_details_changed'] = '予約情報が変更されました。'; @@ -265,13 +263,12 @@ $lang['time'] = '時刻'; $lang['hour'] = '時間'; $lang['minute'] = '分'; -$lang['google_sync_completed'] = 'Googleカレンダーとの同期が 正しく完了しました。'; -$lang['google_sync_failed'] = 'Googleカレンダーとの同期が失敗しました。: サーバーとの接続ができませんでした。'; -$lang['select_google_calendar'] = 'Googleカレンダーの選択'; -$lang['select_google_calendar_prompt'] = 'あなたの予約と同期したい Googleカレンダーを選択してください。.特定のカレンダーを指定したくない場合には、デフォルトのカレンダーが使われます。'; -$lang['google_calendar_selected'] = 'Googleカレンダーが 選択されました。'; +$lang['calendar_sync_completed'] = 'Googleカレンダーとの同期が 正しく完了しました。'; +$lang['calendar_sync_failed'] = 'Googleカレンダーとの同期が失敗しました。: サーバーとの接続ができませんでした。'; +$lang['select_sync_calendar'] = 'Googleカレンダーの選択'; +$lang['select_sync_calendar_prompt'] = 'あなたの予約と同期したい Googleカレンダーを選択してください。.特定のカレンダーを指定したくない場合には、デフォルトのカレンダーが使われます。'; +$lang['sync_calendar_selected'] = 'Googleカレンダーが 選択されました。'; $lang['oops_something_went_wrong'] = 'おっと、なにか が うまく 行ってません。'; -$lang['could_not_add_to_google_calendar'] = 'あなたの予約をGoogleカレンダーに 追加することができませんでした。'; $lang['ea_update_success'] = 'Easy!Appointments の アップデートが成功しました。'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/luxembourgish/translations_lang.php b/application/language/luxembourgish/translations_lang.php index 5fcce88943..e0d3d77c98 100755 --- a/application/language/luxembourgish/translations_lang.php +++ b/application/language/luxembourgish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Numm'; $lang['appointment_link_title'] = 'Termäin Link'; $lang['success'] = 'Erfolleg.'; -$lang['appointment_added_to_google_calendar'] = 'Äre Termäin ass an Ärem Google Kalenner bäigesat ginn.'; -$lang['view_appointment_in_google_calendar'] = 'Klickt w.e.g. hei fir Äre Termäin am Google Kalenner ze kucken.'; $lang['appointment_added_to_your_plan'] = 'Een neie Termäin ass an Ärem Planning bäigesat ginn.'; $lang['appointment_link_description'] = 'Dir kënnt Ännerungen duerch klicken op de Termäin Link duerchféieren.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Während der Indisponibilitéitsperiod gi keng Termäiner ugeholl.'; $lang['new_appointment_hint'] = 'Wielt een neie Termäin a späichert en an der Datebank.'; $lang['reload_appointments_hint'] = 'Terminkalenner nei lueden.'; -$lang['trigger_google_sync_hint'] = 'Start de Synchronisatiounsprozess vum Google Kalenner.'; +$lang['trigger_sync_hint'] = 'Start de Synchronisatiounsprozess vum Google Kalenner.'; $lang['appointment_updated'] = 'D\'Termäiner sinn erfollegräich erneiert ginn.'; $lang['undo'] = 'Schrëtt zeréck'; $lang['appointment_details_changed'] = 'D\'Detailer vum Termäin si geännert ginn.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Zäit'; $lang['hour'] = 'Auer'; $lang['minute'] = 'Minutt'; -$lang['google_sync_completed'] = 'Google Synchronisation erfollegräich ofgeschloss.'; -$lang['google_sync_failed'] = 'Google Synchronisatioun schifgaang: D\'Verbindung mam Server konnt net hiergestallt ginn.'; -$lang['select_google_calendar'] = 'Wielt ee Google Kalenner'; -$lang['select_google_calendar_prompt'] = 'Wielt dee Kalenner, mat deem der Är Termäiner synchroniséiere wëllt. Wann der kee bestëmmte Kalenner auswiele wëllt, gëtt de Standard benotzt.'; -$lang['google_calendar_selected'] = 'Auswiele vum Google Kalenner erfollegräich.'; +$lang['calendar_sync_completed'] = 'Google Synchronisation erfollegräich ofgeschloss.'; +$lang['calendar_sync_failed'] = 'Google Synchronisatioun schifgaang: D\'Verbindung mam Server konnt net hiergestallt ginn.'; +$lang['select_sync_calendar'] = 'Wielt ee Google Kalenner'; +$lang['select_sync_calendar_prompt'] = 'Wielt dee Kalenner, mat deem der Är Termäiner synchroniséiere wëllt. Wann der kee bestëmmte Kalenner auswiele wëllt, gëtt de Standard benotzt.'; +$lang['sync_calendar_selected'] = 'Auswiele vum Google Kalenner erfollegräich.'; $lang['oops_something_went_wrong'] = 'Oops! Et ass eppes schif gaang.'; -$lang['could_not_add_to_google_calendar'] = 'Ären Termäin konnt nët am Google Kalenner bäigesat ginn.'; $lang['ea_update_success'] = 'Easy!Appointments gouf erfollegräich aktualiséiert.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/marathi/translations_lang.php b/application/language/marathi/translations_lang.php index 7df6c13d20..ade2d8efc5 100644 --- a/application/language/marathi/translations_lang.php +++ b/application/language/marathi/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'नाव'; $lang['appointment_link_title'] = 'नियुक्ती दुवा'; $lang['success'] = 'यश.'; -$lang['appointment_added_to_google_calendar'] = 'आपली भेट आपल्या Google कॅलेंडर खात्यात जोडली गेली आहे.'; -$lang['view_appointment_in_google_calendar'] = 'Google कॅलेंडरवर आपली भेट पाहण्यासाठी येथे क्लिक करा.'; $lang['appointment_added_to_your_plan'] = 'आपल्या योजनेत एक नवीन नियुक्ती जोडली गेली आहे.'; $lang['appointment_link_description'] = 'आपण खाली अपॉईंटमेंट लिंकवर क्लिक करून बदल करू शकता.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'प्रदाता अनुपलब्ध कालावधीत नवीन भेटी स्वीकारणार नाही.'; $lang['new_appointment_hint'] = 'नवीन अपॉईंटमेंट तयार करा आणि त्यास डेटाबेसमध्ये संचयित करा.'; $lang['reload_appointments_hint'] = 'कॅलेंडर अपॉईंटमेंट रीलोड करा.'; -$lang['trigger_google_sync_hint'] = 'Google कॅलेंडर संकालन प्रक्रिया ट्रिगर करा.'; +$lang['trigger_sync_hint'] = 'Google कॅलेंडर संकालन प्रक्रिया ट्रिगर करा.'; $lang['appointment_updated'] = 'नियुक्ती अद्यतनित यशस्वी.'; $lang['undo'] = 'पूर्ववत करा'; $lang['appointment_details_changed'] = 'भेटीचे तपशील बदलले आहेत.'; @@ -265,13 +263,12 @@ $lang['time'] = 'वेळ'; $lang['hour'] = 'तास'; $lang['minute'] = 'मिनिट'; -$lang['google_sync_completed'] = 'Google समक्रमण यशस्वीरित्या पूर्ण झाले'; -$lang['google_sync_failed'] = 'Google समक्रमण अयशस्वी: सर्व्हर कनेक्शन स्थापित केले जाऊ शकले नाही'; -$lang['select_google_calendar'] = 'गूगल कॅलेंडर निवडा'; -$lang['select_google_calendar_prompt'] = 'आपण आपल्या भेटी समक्रमित करू इच्छित कॅलेंडर निवडा. आपण एखादे विशिष्ट कॅलेंडर निवडू इच्छित नसल्यास, एक डीफॉल्टनुसार वापरले जाईल'; -$lang['google_calendar_selected'] = 'Google कॅलेंडर यशस्वीरित्या निवडले गेले आहे'; +$lang['calendar_sync_completed'] = 'Google समक्रमण यशस्वीरित्या पूर्ण झाले'; +$lang['calendar_sync_failed'] = 'Google समक्रमण अयशस्वी: सर्व्हर कनेक्शन स्थापित केले जाऊ शकले नाही'; +$lang['select_sync_calendar'] = 'गूगल कॅलेंडर निवडा'; +$lang['select_sync_calendar_prompt'] = 'आपण आपल्या भेटी समक्रमित करू इच्छित कॅलेंडर निवडा. आपण एखादे विशिष्ट कॅलेंडर निवडू इच्छित नसल्यास, एक डीफॉल्टनुसार वापरले जाईल'; +$lang['sync_calendar_selected'] = 'Google कॅलेंडर यशस्वीरित्या निवडले गेले आहे'; $lang['oops_something_went_wrong'] = 'अरेरे! काहीतरी चूक झाली'; -$lang['could_not_add_to_google_calendar'] = 'आपली भेट आपल्या Google कॅलेंडर खात्यात जोडली जाऊ शकत नाहीा'; $lang['ea_update_success'] = 'सुलभ! भेट यशस्वीरित्या अद्यतनित केली गेली आहे.'; $lang['require_captcha'] = 'कॅप्चा आवश्यक आहे'; $lang['require_captcha_hint'] = 'सक्षम केल्यावर, ग्राहकांना अपॉइंटमेंट बुक करण्यासाठी / अद्यतनित करण्यापूर्वी यादृच्छिक व्युत्पन्न कॅप्चा स्ट्रिंग टाईप करावी लागेल.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/persian/translations_lang.php b/application/language/persian/translations_lang.php index ee6c36fff6..93525f4bfd 100644 --- a/application/language/persian/translations_lang.php +++ b/application/language/persian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'نام'; $lang['appointment_link_title'] = 'لینک قرار'; $lang['success'] = 'موفق'; -$lang['appointment_added_to_google_calendar'] = 'قرار ملاقات به تقویم گوگل شما اضافه شد'; -$lang['view_appointment_in_google_calendar'] = 'برای مشاهده قرار روی تقویم گوگل، اینجا کلیک کنید'; $lang['appointment_added_to_your_plan'] = 'قرار جدیدی به برنامه شما اضافه گردید'; $lang['appointment_link_description'] = 'با کلیک بر لینک قرار، می توانید تغییراتی اعمال کنید'; $lang['appointment_locked'] = 'تغییر امکانپذیر نمی باشد'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'در طول زمان در دسترس نبودن، ارائه دهنده قرار جدیدی را نمی پذیرد'; $lang['new_appointment_hint'] = 'ایجاد قرار جدید و ذخیره آن در بانک اطلاعاتی'; $lang['reload_appointments_hint'] = 'بارگذاری مجدد ملاقات ها'; -$lang['trigger_google_sync_hint'] = 'همین حالا با تقویم گوگل همگام سازی انجام بده'; +$lang['trigger_sync_hint'] = 'همین حالا با تقویم گوگل همگام سازی انجام بده'; $lang['appointment_updated'] = 'قرار با موفقیت به روزرسانی شد'; $lang['undo'] = 'Undo'; $lang['appointment_details_changed'] = 'جزئیات قرار با موفقیت تغییر کرد'; @@ -265,13 +263,12 @@ $lang['time'] = 'زمان'; $lang['hour'] = 'ساعت'; $lang['minute'] = 'دقیقه'; -$lang['google_sync_completed'] = 'همگام سازی با تقویم گوگل با موفقیت انجام شد'; -$lang['google_sync_failed'] = 'همگام سازی با تقویم گوگل با شکست مواجه شد. سرور در دسترس نیست'; -$lang['select_google_calendar'] = 'انتخاب تقویم گوگل'; -$lang['select_google_calendar_prompt'] = 'تقویمی که می خواهید قرارها روی آن ذخیره شوند را انتخاب کنید. در صورتیکه که تقویم خاصی را انتخاب نکید، بصورت اتوماتیک روی تقویم پیش فرض ذخیره می شود'; -$lang['google_calendar_selected'] = 'تقویم گوگل با موفقیت انتخاب شد'; +$lang['calendar_sync_completed'] = 'همگام سازی با تقویم گوگل با موفقیت انجام شد'; +$lang['calendar_sync_failed'] = 'همگام سازی با تقویم گوگل با شکست مواجه شد. سرور در دسترس نیست'; +$lang['select_sync_calendar'] = 'انتخاب تقویم گوگل'; +$lang['select_sync_calendar_prompt'] = 'تقویمی که می خواهید قرارها روی آن ذخیره شوند را انتخاب کنید. در صورتیکه که تقویم خاصی را انتخاب نکید، بصورت اتوماتیک روی تقویم پیش فرض ذخیره می شود'; +$lang['sync_calendar_selected'] = 'تقویم گوگل با موفقیت انتخاب شد'; $lang['oops_something_went_wrong'] = 'اوه. مشکلی پیش آمد!'; -$lang['could_not_add_to_google_calendar'] = 'قراردادن ملاقات شما روی تقویم گوگل با شکست مواجه شد'; $lang['ea_update_success'] = 'Easy!Appointments با موفقیت به روز رسانی شد'; $lang['require_captcha'] = 'کد امنیتی لازم است'; $lang['require_captcha_hint'] = 'بعد از فعال کردن این گزینه، کاربران قبل از ایجاد یا تغییر یک قرار ملاقات، باید یک کد امنیتی شامل حروف تصادفی را تشخیص دهند.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/polish/translations_lang.php b/application/language/polish/translations_lang.php index db7a8042c9..6e4706aa0a 100755 --- a/application/language/polish/translations_lang.php +++ b/application/language/polish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nazwisko'; $lang['appointment_link_title'] = 'Link Wizyty'; $lang['success'] = 'Sukces.'; -$lang['appointment_added_to_google_calendar'] = 'Twoja wizyta została dodana do konta Kalendarza Google.'; -$lang['view_appointment_in_google_calendar'] = 'Kliknij aby dokonać podglądu wizyty w Kalendarzu Google'; $lang['appointment_added_to_your_plan'] = 'Nowa wizyta została dodana do twojego terminarza'; $lang['appointment_link_description'] = 'Możesz dokonać zmian klikając na link wizyty poniżej.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Podczas niedostępnych okresów personel nie akceptuje nowych wizyt.'; $lang['new_appointment_hint'] = 'Utwórz nową wizytę i przechowaj ją w bazie danych.'; $lang['reload_appointments_hint'] = 'Przeładuj wizyty kalendarza.'; -$lang['trigger_google_sync_hint'] = 'Przełącz proces synchronizacji Kalendarza Google'; +$lang['trigger_sync_hint'] = 'Przełącz proces synchronizacji Kalendarza Google'; $lang['appointment_updated'] = 'Wizyta zaktualizowana poprawnie.'; $lang['undo'] = 'Cofnij'; $lang['appointment_details_changed'] = 'Szczegóły wizyty zostały zmienione.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Godzina'; $lang['hour'] = 'Godzina'; $lang['minute'] = 'Minuta'; -$lang['google_sync_completed'] = 'Synchronizacja Google pomyślna.'; -$lang['google_sync_failed'] = 'Synchronizacja Google nieudana.'; -$lang['select_google_calendar'] = 'Wybierz Kalendarz Google'; -$lang['select_google_calendar_prompt'] = 'Wybierz kalendarz do synchronizacji wizyt. Brak wyboru spowoduje użycie kalendarza domyślnego.'; -$lang['google_calendar_selected'] = 'Kalendarz Google wybrany pomyślnie.'; +$lang['calendar_sync_completed'] = 'Synchronizacja Google pomyślna.'; +$lang['calendar_sync_failed'] = 'Synchronizacja Google nieudana.'; +$lang['select_sync_calendar'] = 'Wybierz Kalendarz Google'; +$lang['select_sync_calendar_prompt'] = 'Wybierz kalendarz do synchronizacji wizyt. Brak wyboru spowoduje użycie kalendarza domyślnego.'; +$lang['sync_calendar_selected'] = 'Kalendarz Google wybrany pomyślnie.'; $lang['oops_something_went_wrong'] = 'Ojj! Coś poszło nie tak.'; -$lang['could_not_add_to_google_calendar'] = 'Nie można dodać wizyty do Twojego Kalendarza Google'; $lang['ea_update_success'] = 'Easy!Appointment zaktualizowany pomyślnie'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/portuguese-br/translations_lang.php b/application/language/portuguese-br/translations_lang.php index 1ba9c5c798..b385117690 100755 --- a/application/language/portuguese-br/translations_lang.php +++ b/application/language/portuguese-br/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nome'; $lang['appointment_link_title'] = 'Link de agendamentos'; $lang['success'] = 'Sucesso.'; -$lang['appointment_added_to_google_calendar'] = 'O seu evento foi adicionado a sua conta do "Google Calendar".'; -$lang['view_appointment_in_google_calendar'] = 'Clique aqui para ver os seus compromissos no "Google Calendar".'; $lang['appointment_added_to_your_plan'] = 'Um novo evento foi adicionado ao seu plano.'; $lang['appointment_link_description'] = 'Para fazer alterações click no link.'; $lang['appointment_locked'] = 'Modificação impossível.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Durante os periodos indisponíveis o fornecedor não aceitar novos agendamentos.'; $lang['new_appointment_hint'] = 'Criar um novo agendamento e salvar na base de dados.'; $lang['reload_appointments_hint'] = 'atualizar os agentamentos do calendario.'; -$lang['trigger_google_sync_hint'] = 'Disparar o processo de sincronização do Google Calendar.'; +$lang['trigger_sync_hint'] = 'Disparar o processo de sincronização do Google Calendar.'; $lang['appointment_updated'] = 'Atualizado com sucesso.'; $lang['undo'] = 'Desfazer'; $lang['appointment_details_changed'] = 'Detalhes do agendamento foram alterados.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tempo'; $lang['hour'] = 'Hora'; $lang['minute'] = 'Minuto'; -$lang['google_sync_completed'] = 'Sincronização com a Google efetuada com sucesso.'; -$lang['google_sync_failed'] = 'Falha na sincronização com o Google: não foi possível conectar ao servidor.'; -$lang['select_google_calendar'] = 'Selecione o seu Calendário Google'; -$lang['select_google_calendar_prompt'] = 'Selecione o calendário para sincronizar os seus compromissos. Será selecionado o calendario padrão, caso não queira especificar um.'; -$lang['google_calendar_selected'] = 'Calendario do google foi selecionado com sucesso.'; +$lang['calendar_sync_completed'] = 'Sincronização com a Google efetuada com sucesso.'; +$lang['calendar_sync_failed'] = 'Falha na sincronização com o Google: não foi possível conectar ao servidor.'; +$lang['select_sync_calendar'] = 'Selecione o seu Calendário Google'; +$lang['select_sync_calendar_prompt'] = 'Selecione o calendário para sincronizar os seus compromissos. Será selecionado o calendario padrão, caso não queira especificar um.'; +$lang['sync_calendar_selected'] = 'Calendario do google foi selecionado com sucesso.'; $lang['oops_something_went_wrong'] = 'Ops! Algo deu errado.'; -$lang['could_not_add_to_google_calendar'] = 'Não foi possível adicionar à sua conta do Google Calendar.'; $lang['ea_update_success'] = 'Easy!Appointments foi atualizado com sucesso.'; $lang['require_captcha'] = 'Requer CAPTCHA'; $lang['require_captcha_hint'] = 'Quando habilitado, os clientes terão que digitar um código CAPTCHA gerado randomicamente antes de cadastrar/atualizar um agendamento.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/portuguese/translations_lang.php b/application/language/portuguese/translations_lang.php index c86b612d06..335e9b986e 100755 --- a/application/language/portuguese/translations_lang.php +++ b/application/language/portuguese/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nome'; $lang['appointment_link_title'] = 'Link de apontamentos'; $lang['success'] = 'Sucesso.'; -$lang['appointment_added_to_google_calendar'] = 'O seu evento foi adicionado a sua conta "Google Calendar".'; -$lang['view_appointment_in_google_calendar'] = 'Clique aqui para ver os seus compromissos no "Google Calendar".'; $lang['appointment_added_to_your_plan'] = 'Um novo evento foi adicionado ao seu plano.'; $lang['appointment_link_description'] = 'Pode fazer alterações clicando no link.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Durante os periodos indisponíveis o fornecedor não aceitar novos evento.'; $lang['new_appointment_hint'] = 'Criar um novo evento e guarda-lo na base de dados.'; $lang['reload_appointments_hint'] = 'Carregar eventos do calendario.'; -$lang['trigger_google_sync_hint'] = 'Desencadear o processo de sincronização do Google Calendar.'; +$lang['trigger_sync_hint'] = 'Desencadear o processo de sincronização do Google Calendar.'; $lang['appointment_updated'] = 'Evento actualizado com sucesso.'; $lang['undo'] = 'Desfazer'; $lang['appointment_details_changed'] = 'Detalhes do evento foram alterados.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tempo'; $lang['hour'] = 'Hora'; $lang['minute'] = 'Minuto'; -$lang['google_sync_completed'] = 'Sincronização com a Google efectuada com sucesso.'; -$lang['google_sync_failed'] = 'Falha na sincronização com o Google: não foi possivel ligar ao servidor.'; -$lang['select_google_calendar'] = 'Selecione o seu Calendario Google'; -$lang['select_google_calendar_prompt'] = 'Selecione o calendario para sincronizar os seus compromissos. Caso não tenha será selecionado um pre-definido.'; -$lang['google_calendar_selected'] = 'Calendario da google foi selecionado com sucesso.'; +$lang['calendar_sync_completed'] = 'Sincronização com a Google efectuada com sucesso.'; +$lang['calendar_sync_failed'] = 'Falha na sincronização com o Google: não foi possivel ligar ao servidor.'; +$lang['select_sync_calendar'] = 'Selecione o seu Calendario Google'; +$lang['select_sync_calendar_prompt'] = 'Selecione o calendario para sincronizar os seus compromissos. Caso não tenha será selecionado um pre-definido.'; +$lang['sync_calendar_selected'] = 'Calendario da google foi selecionado com sucesso.'; $lang['oops_something_went_wrong'] = 'Ops! Algo deu errado.'; -$lang['could_not_add_to_google_calendar'] = 'Sua nomeação não pode ser adicionado à sua conta do Google Calendar.'; $lang['ea_update_success'] = 'Nomeações fáceis! Foi atualizado com sucesso.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/romanian/translations_lang.php b/application/language/romanian/translations_lang.php index a4143b3cf0..6f787ad381 100755 --- a/application/language/romanian/translations_lang.php +++ b/application/language/romanian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nume'; $lang['appointment_link_title'] = 'Linkul întâlnirii'; $lang['success'] = 'Succes.'; -$lang['appointment_added_to_google_calendar'] = 'Întâlnirea a fost adaugata în Calendarul Google.'; -$lang['view_appointment_in_google_calendar'] = 'Apasati aici ca sa vizualizati întâlnirea în Calendarul Google.'; $lang['appointment_added_to_your_plan'] = 'O noua întâlnire a fost adaugata în planul dumneavoastra.'; $lang['appointment_link_description'] = 'Puteti face modificari apasând pe linkul întâlnirii de dedesubt.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'În timpul perioadei de indisponibilitate, furnizorul nu va accepta întâlniri noi.'; $lang['new_appointment_hint'] = 'Creeaza întâlnire noua si înregistreaza în baza de date.'; $lang['reload_appointments_hint'] = 'Reîncarca întâlnirile din calendar.'; -$lang['trigger_google_sync_hint'] = 'Porneste procesul de sincronizare cu Calendarul Google.'; +$lang['trigger_sync_hint'] = 'Porneste procesul de sincronizare cu Calendarul Google.'; $lang['appointment_updated'] = 'Întâlnire actualizata cu succes.'; $lang['undo'] = 'Înapoi'; $lang['appointment_details_changed'] = 'Detaliile întâlnirii au fost modificate.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Ora'; $lang['hour'] = 'Ora'; $lang['minute'] = 'Minut'; -$lang['google_sync_completed'] = 'Sincronizarea cu Google a reusit.'; -$lang['google_sync_failed'] = 'Sincronizarea cu Google a esuat: nu s-a putut stabili conexiunea cu serverul.'; -$lang['select_google_calendar'] = 'Selecteaza Calendarul Google'; -$lang['select_google_calendar_prompt'] = 'Selecteaza calendarul în care doriti sa sincronizati întâlnirile. Daca nu doriti sa selectati un anume calendar va fi folosit cel implicit.'; -$lang['google_calendar_selected'] = 'Calendarul Google a fost selectat.'; +$lang['calendar_sync_completed'] = 'Sincronizarea cu Google a reusit.'; +$lang['calendar_sync_failed'] = 'Sincronizarea cu Google a esuat: nu s-a putut stabili conexiunea cu serverul.'; +$lang['select_sync_calendar'] = 'Selecteaza Calendarul Google'; +$lang['select_sync_calendar_prompt'] = 'Selecteaza calendarul în care doriti sa sincronizati întâlnirile. Daca nu doriti sa selectati un anume calendar va fi folosit cel implicit.'; +$lang['sync_calendar_selected'] = 'Calendarul Google a fost selectat.'; $lang['oops_something_went_wrong'] = 'Oops! Ceva nu a funtionat corect.'; -$lang['could_not_add_to_google_calendar'] = 'Întâlnirea nu a putut fi adaugata în Calendarul Google.'; $lang['ea_update_success'] = 'Easy!Appointments a fost actualizat.'; $lang['require_captcha'] = 'Require CAPTCHA'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/russian/translations_lang.php b/application/language/russian/translations_lang.php index a66bc54c0a..0c238fadeb 100644 --- a/application/language/russian/translations_lang.php +++ b/application/language/russian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Имя'; $lang['appointment_link_title'] = 'Ссылка на назначение'; $lang['success'] = 'Готово.'; -$lang['appointment_added_to_google_calendar'] = 'Ваше назначение было внесено в Google-календарь вашего аккаунта.'; -$lang['view_appointment_in_google_calendar'] = 'Нажмите сюда для просмотра вашего назначения в Google-календаре.'; $lang['appointment_added_to_your_plan'] = 'Новое назначение было добавлено в ваш план.'; $lang['appointment_link_description'] = 'Вы можете внести изменения кликнув на ссылку назначения ниже.'; $lang['appointment_locked'] = 'Модификация невозможна.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'На протяжении недоступного периода исполнитель не будет принимать новые назначения.'; $lang['new_appointment_hint'] = 'Создать новое назначение и сохранить его в базе данных.'; $lang['reload_appointments_hint'] = 'Перезагрузить календарь назначений.'; -$lang['trigger_google_sync_hint'] = 'Инициировать процесс синхронизации Google-календаря.'; +$lang['trigger_sync_hint'] = 'Инициировать процесс синхронизации Google-календаря.'; $lang['appointment_updated'] = 'Назначение успешно обновлено.'; $lang['undo'] = 'Вернуть'; $lang['appointment_details_changed'] = 'Детали назначения изменены.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Время'; $lang['hour'] = 'Часов'; $lang['minute'] = 'Минут'; -$lang['google_sync_completed'] = 'Google синхронизация выполнена успешно.'; -$lang['google_sync_failed'] = 'Google синхронизация не удалась: сервер не доступен.'; -$lang['select_google_calendar'] = 'Выберите Google-календарь'; -$lang['select_google_calendar_prompt'] = 'Выберите календарь который вы хотите синхронизировать с вашими назначениями. Если вы не выберите будет использован ваш Google-календарь по умолчанию.'; -$lang['google_calendar_selected'] = 'Google-календарь был успешно выбран.'; +$lang['calendar_sync_completed'] = 'Google синхронизация выполнена успешно.'; +$lang['calendar_sync_failed'] = 'Google синхронизация не удалась: сервер не доступен.'; +$lang['select_sync_calendar'] = 'Выберите Google-календарь'; +$lang['select_sync_calendar_prompt'] = 'Выберите календарь который вы хотите синхронизировать с вашими назначениями. Если вы не выберите будет использован ваш Google-календарь по умолчанию.'; +$lang['sync_calendar_selected'] = 'Google-календарь был успешно выбран.'; $lang['oops_something_went_wrong'] = 'Сорри! Возникла неопределённая ошибка.'; -$lang['could_not_add_to_google_calendar'] = 'Ваше событие не было добавлено в указанный Google-календарь.'; $lang['ea_update_success'] = 'Готово! Успешно обновлено.'; $lang['require_captcha'] = 'Требуется CAPTCHA'; $lang['require_captcha_hint'] = 'Если эта функция включена - клиенты должны будут ввести случайно сгенерированную строку CAPTCHA перед бронированием/обновлением записи на прием.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/serbian/translations_lang.php b/application/language/serbian/translations_lang.php index 2448f7064a..9815a85125 100644 --- a/application/language/serbian/translations_lang.php +++ b/application/language/serbian/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Ime'; $lang['appointment_link_title'] = 'Link za posetu'; $lang['success'] = 'Obavljeno!'; -$lang['appointment_added_to_google_calendar'] = 'Vaše vreme posete dodato je u Vaš Google kalendar.'; -$lang['view_appointment_in_google_calendar'] = 'Pogledajte ovde da biste videli zakazano vreme posete u Google Calendar nalogu.'; $lang['appointment_added_to_your_plan'] = 'Novo vreme posete je dodato.'; $lang['appointment_link_description'] = 'Unesite izmene klikom na link ispod.'; $lang['appointment_locked'] = 'Promena nije moguća.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Izvan radnog vremena izvršilac neće prihvatati nove termine.'; $lang['new_appointment_hint'] = 'Izaberite novi termin i sačuvajte ga u bazi podataka.'; $lang['reload_appointments_hint'] = 'Ponovo učitaj kalendar poseta.'; -$lang['trigger_google_sync_hint'] = 'Pokreni sinhronizaciju Google kalendara.'; +$lang['trigger_sync_hint'] = 'Pokreni sinhronizaciju Google kalendara.'; $lang['appointment_updated'] = 'Vreme posete je ažurirano!'; $lang['undo'] = 'Poništi'; $lang['appointment_details_changed'] = 'Vreme posete je izmenjeno.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Vreme'; $lang['hour'] = 'Sat'; $lang['minute'] = 'Minut'; -$lang['google_sync_completed'] = 'Google usaglašavanje uspešno je završeno!'; -$lang['google_sync_failed'] = 'Google usaglašavanje nije uspelo: Veza sa serverom ne može da se uspostavi.'; -$lang['select_google_calendar'] = 'Izaberite Google kalendar'; -$lang['select_google_calendar_prompt'] = 'Izaberite kalendar sa kojim želite usaglasiti Vaš termin. Ako ne želite izabrati poseban kalendar, koristiće se uobičajeni.'; -$lang['google_calendar_selected'] = 'Google kalendar je uspešno odabran!'; +$lang['calendar_sync_completed'] = 'Google usaglašavanje uspešno je završeno!'; +$lang['calendar_sync_failed'] = 'Google usaglašavanje nije uspelo: Veza sa serverom ne može da se uspostavi.'; +$lang['select_sync_calendar'] = 'Izaberite Google kalendar'; +$lang['select_sync_calendar_prompt'] = 'Izaberite kalendar sa kojim želite usaglasiti Vaš termin. Ako ne želite izabrati poseban kalendar, koristiće se uobičajeni.'; +$lang['sync_calendar_selected'] = 'Google kalendar je uspešno odabran!'; $lang['oops_something_went_wrong'] = 'Oops! Nešto nije u redu!'; -$lang['could_not_add_to_google_calendar'] = 'Vaš termin se ne može dodati u Vaš Google kalendar nalog.'; $lang['ea_update_success'] = 'Easy!Appointments je uspešno ažuriran!'; $lang['require_captcha'] = 'Zahtevajte CAPTCHA-u'; $lang['require_captcha_hint'] = 'Ako je moguće, korisnik treba da unese slučajno generisan CAPTCHA niz znakova pre zakazivanja ili menjanja termina.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/slovak/translations_lang.php b/application/language/slovak/translations_lang.php index bcc7e700ff..a268ab8318 100755 --- a/application/language/slovak/translations_lang.php +++ b/application/language/slovak/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Meno'; $lang['appointment_link_title'] = 'Link na rezerváciu'; $lang['success'] = 'Úspech.'; -$lang['appointment_added_to_google_calendar'] = 'Vaša rezervácia bola pridaná do vášho konta služby Kalendár Google.'; -$lang['view_appointment_in_google_calendar'] = 'Ak chcete zobraziť vašu rezerváciu v Kalendári Google Kliknite tu.'; $lang['appointment_added_to_your_plan'] = 'Nová rezervácia bola pridaná do vášho kalendára.'; $lang['appointment_link_description'] = 'Môžete vykonať zmeny v rezervácií kliknutím na odkaz nižšie.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Počas nedostupnosti (otváracia doba) nebudú akceptované nové rezervácie.'; $lang['new_appointment_hint'] = 'Vytvorte novú rezerváciu a uložte ju do databázy.'; $lang['reload_appointments_hint'] = 'Obnoviť rezervácie v kalendári.'; -$lang['trigger_google_sync_hint'] = 'Trigger proces synchronizácie kalendára Google.'; +$lang['trigger_sync_hint'] = 'Trigger proces synchronizácie kalendára Google.'; $lang['appointment_updated'] = 'Rezervácia úspešne aktualizovaná.'; $lang['undo'] = 'Odvolať akciu'; $lang['appointment_details_changed'] = 'Podrobnosti rezervácie boli zmenené'; @@ -265,13 +263,12 @@ $lang['time'] = 'Čas'; $lang['hour'] = 'Hodina'; $lang['minute'] = 'Minúta'; -$lang['google_sync_completed'] = 'Synchronizácia s Google úspešne dokončená.'; -$lang['google_sync_failed'] = 'Synchronizácia Google zlyhala: Nemožno vytvoriť pripojenie k serveru.'; -$lang['select_google_calendar'] = 'Vybrať Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Vyberte kalendár, s ktorým chcete synchronizovať svoje stretnutia. Ak si nechcete vybrať konkrétny kalendár bude použitý predvolený.'; -$lang['google_calendar_selected'] = 'Kalendár Google bol úspešne zvolený.'; +$lang['calendar_sync_completed'] = 'Synchronizácia s Google úspešne dokončená.'; +$lang['calendar_sync_failed'] = 'Synchronizácia Google zlyhala: Nemožno vytvoriť pripojenie k serveru.'; +$lang['select_sync_calendar'] = 'Vybrať Google Calendar'; +$lang['select_sync_calendar_prompt'] = 'Vyberte kalendár, s ktorým chcete synchronizovať svoje stretnutia. Ak si nechcete vybrať konkrétny kalendár bude použitý predvolený.'; +$lang['sync_calendar_selected'] = 'Kalendár Google bol úspešne zvolený.'; $lang['oops_something_went_wrong'] = 'Úups! Niečo sa pokazilo.'; -$lang['could_not_add_to_google_calendar'] = 'Vaše rezervácie nemoholi byť pridané do vášho účtu služby Google Kalendár.'; $lang['ea_update_success'] = 'Easy!Appointments bolo úspešne aktualizované.'; $lang['require_captcha'] = 'Vyžadovať CAPTCHA'; $lang['require_captcha_hint'] = 'Po zapnutí budú zákazníci musieť pred rezerváciou / aktualizáciou schôdzky napísať náhodne vygenerovaný reťazec CAPTCHA.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/spanish/translations_lang.php b/application/language/spanish/translations_lang.php index fd893f61ad..fc819e6f4f 100755 --- a/application/language/spanish/translations_lang.php +++ b/application/language/spanish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Nombre'; $lang['appointment_link_title'] = 'Enlace a la cita'; $lang['success'] = '¡Cita completada.'; -$lang['appointment_added_to_google_calendar'] = 'Su cita ha sido agregada a su cuenta de Google Calendar.'; -$lang['view_appointment_in_google_calendar'] = 'Haga clic aquí para ver su cita en Google Calendar.'; $lang['appointment_added_to_your_plan'] = 'Se ha agendado una nueva cita en su calendario.'; $lang['appointment_link_description'] = 'Haga clic en la cita para realizar cambios.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'El proveedor no podrá aceptar nuevas citas cuando se encuentre como No disponible.'; $lang['new_appointment_hint'] = 'Crear una nueva cita y guardarla en la base de datos.'; $lang['reload_appointments_hint'] = 'Cargar nuevamente citas del calendario.'; -$lang['trigger_google_sync_hint'] = 'Iniciar el proceso de sinconización de Google Calendar.'; +$lang['trigger_sync_hint'] = 'Iniciar el proceso de sinconización de Google Calendar.'; $lang['appointment_updated'] = 'Cita actualizada exitosamente'; $lang['undo'] = 'Deshacer'; $lang['appointment_details_changed'] = 'Se han modificado los detalles de la cita.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Hora'; $lang['hour'] = 'Hora'; $lang['minute'] = 'Minuto'; -$lang['google_sync_completed'] = 'Se completó la sincronización con Google exitosamente'; -$lang['google_sync_failed'] = 'La sincronización con Google falló: No se pudo establecer una conexión con el servidor.'; -$lang['select_google_calendar'] = 'Seleccionar un calendario de Google Calendar'; -$lang['select_google_calendar_prompt'] = 'Seleccione el calendario con el que desea sincronizar sus citas. Si no desea seleccionar un calendario en particular, se utilizará el calendario por defecto.'; -$lang['google_calendar_selected'] = 'Se ha seleccionado el calendario de Google Calendar exitosamente'; +$lang['calendar_sync_completed'] = 'Se completó la sincronización con Google exitosamente'; +$lang['calendar_sync_failed'] = 'La sincronización con Google falló: No se pudo establecer una conexión con el servidor.'; +$lang['select_sync_calendar'] = 'Seleccionar un calendario de Google Calendar'; +$lang['select_sync_calendar_prompt'] = 'Seleccione el calendario con el que desea sincronizar sus citas. Si no desea seleccionar un calendario en particular, se utilizará el calendario por defecto.'; +$lang['sync_calendar_selected'] = 'Se ha seleccionado el calendario de Google Calendar exitosamente'; $lang['oops_something_went_wrong'] = '¡Ups! ¡Algo ha salido mal.'; -$lang['could_not_add_to_google_calendar'] = 'No se ha podido agregar la cita a su cuenta de Google Calendar.'; $lang['ea_update_success'] = 'Easy!Appointments ha sido actualizado exitosamente'; $lang['require_captcha'] = 'Requiere CAPTCHA'; $lang['require_captcha_hint'] = 'Cuando se habilita, el cliente tendrá que escribir el código CAPTCHA antes de reservar/actualizar una cita.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/swedish/translations_lang.php b/application/language/swedish/translations_lang.php index 0272eda315..e772dc1107 100644 --- a/application/language/swedish/translations_lang.php +++ b/application/language/swedish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Namn'; $lang['appointment_link_title'] = 'Länk till bokning..'; $lang['success'] = 'Lyckades.'; -$lang['appointment_added_to_google_calendar'] = 'Din bokning är skickad till din Google-kalender.'; -$lang['view_appointment_in_google_calendar'] = 'Klicka här för att se bokningen i Google-kalendern.'; $lang['appointment_added_to_your_plan'] = 'En ny bokning har lagst till i ditt schema.'; $lang['appointment_link_description'] = 'Du kan göra ändringar genom att klicka på länken nedan.'; $lang['appointment_locked'] = 'Modifiering kan inte göras.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Under låsta perioder går det inte att boka leverantören.'; $lang['new_appointment_hint'] = 'Skapa en ny bokning och spara den i databasen.'; $lang['reload_appointments_hint'] = 'Uppdatera kalendern.'; -$lang['trigger_google_sync_hint'] = 'Starta synkroniseringen med Google-kalendrar.'; +$lang['trigger_sync_hint'] = 'Starta synkroniseringen med Google-kalendrar.'; $lang['appointment_updated'] = 'Bokningen är uppdaterad.'; $lang['undo'] = 'Ångra'; $lang['appointment_details_changed'] = 'Bokningen har ändrats.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Tid'; $lang['hour'] = 'Timme'; $lang['minute'] = 'Minuter'; -$lang['google_sync_completed'] = 'Google synkroniseringen klar.'; -$lang['google_sync_failed'] = 'Google synkroniseringen misslyckades, kunde inte ansluta till servern..'; -$lang['select_google_calendar'] = 'Välj Google kalender'; -$lang['select_google_calendar_prompt'] = 'Välj den kalender du vill ha bokningen i. Om du inte väljer hamnar den i din standardkalender.'; -$lang['google_calendar_selected'] = 'Googlekalendern är vald.'; +$lang['calendar_sync_completed'] = 'Google synkroniseringen klar.'; +$lang['calendar_sync_failed'] = 'Google synkroniseringen misslyckades, kunde inte ansluta till servern..'; +$lang['select_sync_calendar'] = 'Välj Google kalender'; +$lang['select_sync_calendar_prompt'] = 'Välj den kalender du vill ha bokningen i. Om du inte väljer hamnar den i din standardkalender.'; +$lang['sync_calendar_selected'] = 'Googlekalendern är vald.'; $lang['oops_something_went_wrong'] = 'Oops! Något gick fel.'; -$lang['could_not_add_to_google_calendar'] = 'Din bokning gick inte att lägga in i din Google-kalender.'; $lang['ea_update_success'] = 'Easy!Appointments är uppdaterad.'; $lang['require_captcha'] = 'Kräv CAPTCHA'; $lang['require_captcha_hint'] = 'När denna är aktiv måste kunderna skriva lite slumpmässig text innann de kan göra/ändra en bokning.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/language/turkish/translations_lang.php b/application/language/turkish/translations_lang.php index 6702a6f543..484c971c9c 100755 --- a/application/language/turkish/translations_lang.php +++ b/application/language/turkish/translations_lang.php @@ -49,8 +49,6 @@ $lang['name'] = 'Ad'; $lang['appointment_link_title'] = 'Randevunun Bağlantısı'; $lang['success'] = 'Başarılı.'; -$lang['appointment_added_to_google_calendar'] = 'Randevunuz Google Takvim hesabınıza eklendi.'; -$lang['view_appointment_in_google_calendar'] = 'Google Takvimde randevunuzu görmek için buraya tıklayın.'; $lang['appointment_added_to_your_plan'] = 'Planınıza yeni bir randevu eklendi.'; $lang['appointment_link_description'] = 'Değişiklik yapmak için aşağıdaki randevu linkine tıklayabilirsiniz.'; $lang['appointment_locked'] = 'Modification impossible.'; @@ -89,7 +87,7 @@ $lang['unavailability_periods_hint'] = 'Uygun olmayan zaman aralıklarında hizmet sağlayıcı yeni randevu kabul etmeyecektir.'; $lang['new_appointment_hint'] = 'Yeni bir randevu yaratarak veri tabanına kaydet.'; $lang['reload_appointments_hint'] = 'Takvim randevularını tekrar yükle.'; -$lang['trigger_google_sync_hint'] = 'Google Takvim eşitlemeyi başlat.'; +$lang['trigger_sync_hint'] = 'Google Takvim eşitlemeyi başlat.'; $lang['appointment_updated'] = 'Randevu başarıyla güncellendi.'; $lang['undo'] = 'Geri al'; $lang['appointment_details_changed'] = 'Randevu detayları değiştirildi.'; @@ -265,13 +263,12 @@ $lang['time'] = 'Zaman'; $lang['hour'] = 'Saat'; $lang['minute'] = 'Dakika'; -$lang['google_sync_completed'] = 'Google eşitlemesi başarıyla tamamlandı.'; -$lang['google_sync_failed'] = 'Google eşitlemesi başarısız: Sunucu ile bağlantı kurulamadı.'; -$lang['select_google_calendar'] = 'Google Takvimini seçin.'; -$lang['select_google_calendar_prompt'] = 'Randevularınızı eşitlemek istediğiniz takvimi seçin. Eğer spesifik bir takvim seçmezseniz varsayılan takvim kullanılacaktır.'; -$lang['google_calendar_selected'] = 'Google Takvimi başarıyla seçildi.'; +$lang['calendar_sync_completed'] = 'Google eşitlemesi başarıyla tamamlandı.'; +$lang['calendar_sync_failed'] = 'Google eşitlemesi başarısız: Sunucu ile bağlantı kurulamadı.'; +$lang['select_sync_calendar'] = 'Google Takvimini seçin.'; +$lang['select_sync_calendar_prompt'] = 'Randevularınızı eşitlemek istediğiniz takvimi seçin. Eğer spesifik bir takvim seçmezseniz varsayılan takvim kullanılacaktır.'; +$lang['sync_calendar_selected'] = 'Google Takvimi başarıyla seçildi.'; $lang['oops_something_went_wrong'] = 'Oops! Bir Sorun Oluştu.'; -$lang['could_not_add_to_google_calendar'] = 'Randevunuz Google Takvim hesabınıza eklenemedi.'; $lang['ea_update_success'] = 'Easy!Appointments başarı ile güncellendi.'; $lang['require_captcha'] = 'CAPTCHA gereklidir'; $lang['require_captcha_hint'] = 'When enabled, the customers will have to type a random generated CAPTCHA string before booking/updating an appointment.'; @@ -460,4 +457,8 @@ $lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.'; $lang['default_language'] = 'Default Language'; $lang['default_language_hint'] = 'Set the default language value that will be used for new records.'; +$lang['sync_method_prompt'] = 'Which sync method would you like to use?'; +$lang['caldav_server'] = 'CalDAV Server'; +$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.'; +$lang['connect'] = 'Connect'; // End diff --git a/application/libraries/Caldav_sync.php b/application/libraries/Caldav_sync.php new file mode 100644 index 0000000000..a8e6ff671b --- /dev/null +++ b/application/libraries/Caldav_sync.php @@ -0,0 +1,478 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +use GuzzleHttp\Client; +use GuzzleHttp\Exception\GuzzleException; +use GuzzleHttp\Exception\RequestException; +use Sabre\VObject\Component\VEvent; +use Sabre\VObject\Reader; + +/** + * Caldav sync library. + * + * Handles CalDAV related operations using Guzzle. + * + * @package Libraries + */ +class Caldav_sync +{ + /** + * @var EA_Controller|CI_Controller + */ + protected EA_Controller|CI_Controller $CI; + + /** + * Caldav_sync constructor. + * + * This method initializes the Caldav client class and the Calendar service class so that they can be used by the + * other methods. + */ + public function __construct() + { + $this->CI = &get_instance(); + + $this->CI->load->model('appointments_model'); + $this->CI->load->model('customers_model'); + $this->CI->load->model('providers_model'); + $this->CI->load->model('services_model'); + + $this->CI->load->library('ics_file'); + } + + /** + * Add an appointment record to the connected CalDAV calendar. + * + * @param array $appointment Appointment record. + * @param array $service Service record. + * @param array $provider Provider record. + * @param array $customer Customer record. + * + * @return string|null Returns the event ID + * + * @throws \Jsvrcek\ICS\Exception\CalendarEventException + */ + public function save_appointment(array $appointment, array $service, array $provider, array $customer): ?string + { + try { + $ics_file = $this->get_appointment_ics_file($appointment, $service, $provider, $customer); + + $client = $this->get_http_client_by_provider_id($provider['id']); + + $caldav_calendar = $provider['settings']['caldav_calendar']; + + $caldav_event_id = + $appointment['id_caldav_calendar'] ?: $this->CI->ics_file->generate_uid($appointment['id']); + + $uri = $this->get_caldav_event_uri($caldav_calendar, $caldav_event_id); + + $client->request('PUT', $uri, [ + 'headers' => [ + 'Content-Type' => 'text/calendar', + ], + 'body' => $ics_file, + ]); + + return $caldav_event_id; + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to save CalDAV event'); + return null; + } + } + + /** + * Add an unavailability record to the connected CalDAV calendar. + * + * @param array $unavailability Appointment record. + * @param array $provider Provider record. + * + * @return string|null Returns the event ID + * + * @throws \Jsvrcek\ICS\Exception\CalendarEventException + */ + public function save_unavailability(array $unavailability, array $provider): ?string + { + try { + $ics_file = $this->get_unavailability_ics_file($unavailability, $provider); + + $client = $this->get_http_client_by_provider_id($provider['id']); + + $caldav_calendar = $provider['settings']['caldav_calendar']; + + $caldav_event_id = + $unavailability['id_caldav_calendar'] ?: $this->CI->ics_file->generate_uid($unavailability['id']); + + $uri = $this->get_caldav_event_uri($caldav_calendar, $caldav_event_id); + + $client->request('PUT', $uri, [ + 'headers' => [ + 'Content-Type' => 'text/calendar', + ], + 'body' => $ics_file, + ]); + + return $caldav_event_id; + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to save CalDAV event'); + return null; + } + } + + /** + * Delete an existing appointment from Caldav Calendar. + * + * @param array $provider Provider data. + * @param string $caldav_event_id The Caldav Calendar event ID to be removed. + */ + public function delete_event(array $provider, string $caldav_event_id): void + { + try { + $client = $this->get_http_client_by_provider_id($provider['id']); + + $caldav_calendar = $provider['settings']['caldav_calendar']; + + $uri = $this->get_caldav_event_uri($caldav_calendar, $caldav_event_id); + + $client->request('DELETE', $uri); + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to save CalDAV event'); + } + } + + /** + * Get a Caldav Calendar event. + * + * @param array $provider Provider Data. + * @param string $caldav_event_id CalDAV calendar event ID. + * + * @return array|null + * @throws Exception + */ + public function get_event(array $provider, string $caldav_event_id): ?array + { + try { + $client = $this->get_http_client_by_provider_id($provider['id']); + + $caldav_calendar = $provider['settings']['caldav_calendar']; + + $uri = $this->get_caldav_event_uri($caldav_calendar, $caldav_event_id); + + $response = $client->request('GET', $uri); + + $ics_file = $response->getBody()->getContents(); + + $vcalendar = Reader::read($ics_file); + + return $this->convert_caldav_event_to_array_event($vcalendar->VEVENT); + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to save CalDAV event'); + return null; + } + } + + /** + * Get all the events between the sync period. + * + * @param array $provider Provider data. + * @param string $start_date_time The start date of sync period. + * @param string $end_date_time The end date of sync period. + * + * @return array + * @throws Exception + */ + public function get_sync_events(array $provider, string $start_date_time, string $end_date_time): array + { + try { + $client = $this->get_http_client_by_provider_id($provider['id']); + + $caldav_calendar = $provider['settings']['caldav_calendar']; + + $uri = $this->get_caldav_event_uri($caldav_calendar); + + $start_date_time_object = new DateTime($start_date_time); + $formatted_start_date_time = $start_date_time_object->format('Ymd\THis\Z'); + $end_date_time_object = new DateTime($end_date_time); + $formatted_end_date_time = $end_date_time_object->format('Ymd\THis\Z'); + + $response = $client->request('REPORT', $uri, [ + 'headers' => [ + 'Content-Type' => 'application/xml', + 'Depth' => '1', + ], + 'body' => + ' + + + + + + + + + + + + + + ', + ]); + + $xml = new SimpleXMLElement($response->getBody(), 0, false, 'd', true); + + $events = []; + + foreach ($xml->children('d', true) as $response) { + $ics_file = (string) $response->propstat->prop->children('cal', true); + + $vcalendar = Reader::read($ics_file); + + $events[] = $this->convert_caldav_event_to_array_event($vcalendar->VEVENT); + } + + return $events; + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to save CalDAV event'); + return []; + } + } + + /** + * Return available Caldav Calendars for specific user. + * + * The given user's token must already exist in db in order to get access to his + * Caldav Calendar account. + * + * @return array Returns an array with the available calendars. + * + * @throws Exception + */ + public function get_caldav_calendars(int $provider_id): array + { + try { + $provider = $this->CI->providers_model->find($provider_id); + + if (!$provider['settings']['caldav_sync']) { + throw new RuntimeException( + 'The selected provider does not have the CalDAV sync enabled: ' . $provider_id, + ); + } + + $caldav_url = $provider['settings']['caldav_url']; + $caldav_username = $provider['settings']['caldav_username']; + $caldav_password = $provider['settings']['caldav_password']; + + $client = $this->get_http_client($caldav_url, $caldav_username, $caldav_password); + + $caldav_calendars = []; + + $response = $client->request('PROPFIND', 'calendars/' . $caldav_username); + + $xml = new SimpleXMLElement($response->getBody(), 0, false, 'd', true); + + foreach ($xml->children('d', true) as $response) { + $resource_type = $response->propstat->prop->resourcetype->children('cal', true)->getName(); + + if ($resource_type !== 'calendar') { + continue; + } + + $caldav_calendars[] = [ + 'id' => $this->sanitize_href($caldav_url, $response->href), + 'summary' => (string) $response->propstat->prop->displayname, + ]; + } + + return $caldav_calendars; + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to get the CalDAV calendars'); + return []; + } + } + + /** + * Connect to the remote CalDAV server and get the default calendar URL. + * + * @param string $caldav_url + * @param string $caldav_username + * @param string $caldav_password + * + * @return string|null + * + * @throws Exception + */ + public function get_default_calendar(string $caldav_url, string $caldav_username, string $caldav_password): ?string + { + try { + $client = $this->get_http_client($caldav_url, $caldav_username, $caldav_password); + + $response = $client->request('PROPFIND', 'calendars/' . $caldav_username); + + $xml = new SimpleXMLElement($response->getBody(), 0, false, 'd', true); + + foreach ($xml->children('d', true) as $response) { + $resource_type = $response->propstat->prop->resourcetype->children('cal', true)->getName(); + + if ($resource_type === 'calendar') { + return $this->sanitize_href($caldav_url, $response->href); // Use this response as the default calendar + } + } + + return null; + } catch (GuzzleException $e) { + $this->handle_guzzle_exception($e, 'Failed to check CalDAV credentials'); + return null; + } + } + + /** + * Common error handling for the CalDAV requests. + * + * @param GuzzleException $e + * @param string $message + * + * @return void + */ + private function handle_guzzle_exception(GuzzleException $e, string $message): void + { + // Guzzle throws a RequestException for HTTP errors + + if ($e instanceof RequestException && $e->hasResponse()) { + // Handle HTTP error response + + $response = $e->getResponse(); + + $status_code = $response->getStatusCode(); + + $guzzle_info = '(Status Code: ' . $status_code . '): ' . $response->getBody()->getContents() . PHP_EOL; + } else { + // Handle other request errors + + $guzzle_info = $e->getMessage(); + } + + log_message('error', $message . ' ' . $guzzle_info); + } + + private function get_http_client(string $caldav_url, string $caldav_username, string $caldav_password): Client + { + if (!filter_var($caldav_url, FILTER_VALIDATE_URL)) { + throw new InvalidArgumentException('Invalid CalDAV URL provided: ' . $caldav_url); + } + + if (!$caldav_username) { + throw new InvalidArgumentException('Invalid CalDAV username provided: ' . $caldav_username); + } + + if (!$caldav_password) { + throw new InvalidArgumentException('Invalid CalDAV password provided: ' . $caldav_password); + } + + return new Client([ + 'base_uri' => rtrim($caldav_url, '/') . '/', + 'connect_timeout' => 15, + 'headers' => [ + 'Content-Type' => 'text/xml', + ], + 'auth' => [$caldav_username, $caldav_password], + ]); + } + + private function sanitize_href(string $caldav_url, string $href): string + { + $parts = parse_url($caldav_url); + + return str_replace($parts['path'], '', $href); + } + + private function get_http_client_by_provider_id(int $provider_id): Client + { + $provider = $this->CI->providers_model->find($provider_id); + + if (!$provider['settings']['caldav_sync']) { + throw new RuntimeException('The selected provider does not have the CalDAV sync enabled: ' . $provider_id); + } + + $caldav_url = $provider['settings']['caldav_url']; + $caldav_username = $provider['settings']['caldav_username']; + $caldav_password = $provider['settings']['caldav_password']; + + return $this->get_http_client($caldav_url, $caldav_username, $caldav_password); + } + + /** + * Generate the event URI, used in various requests. + * + * @param string $caldav_calendar + * @param string|null $caldav_event_id + * + * @return string + */ + private function get_caldav_event_uri(string $caldav_calendar, ?string $caldav_event_id = null): string + { + return trim($caldav_calendar, '/') . ($caldav_event_id ? '/' . $caldav_event_id . '.ics' : ''); + } + + /** + * @throws \Jsvrcek\ICS\Exception\CalendarEventException + */ + private function get_appointment_ics_file( + array $appointment, + array $service, + array $provider, + array $customer, + ): string { + $ics_file = $this->CI->ics_file->get_stream($appointment, $service, $provider, $customer); + + return str_replace('METHOD:PUBLISH', '', $ics_file); + } + + /** + * @throws \Jsvrcek\ICS\Exception\CalendarEventException + */ + private function get_unavailability_ics_file(array $unavailability, array $provider): string + { + $ics_file = $this->CI->ics_file->get_unavailability_stream($unavailability, $provider); + + return str_replace('METHOD:PUBLISH', '', $ics_file); + } + + /** + * Convert the VEvent object to an associative array + * + * @link https://sabre.io/vobject/icalendar + * + * @param VEvent $vevent Holds the VEVENT information + * + * @return array + * + * @throws Exception + */ + private function convert_caldav_event_to_array_event(VEvent $vevent): array + { + $start_date_time_object = new DateTime((string) $vevent->DTSTART); + $end_date_time_object = new DateTime((string) $vevent->DTEND); + + return [ + 'id' => (string) $vevent->UID, + 'summary' => (string) $vevent->SUMMARY, + 'start_datetime' => $start_date_time_object->format('Y-m-d H:i:s'), + 'end_datetime' => $end_date_time_object->format('Y-m-d H:i:s'), + 'description' => (string) $vevent->DESCRIPTION, + 'status' => (string) $vevent->STATUS, + 'location' => (string) $vevent->LOCATION, + ]; + } +} diff --git a/application/libraries/Ics_file.php b/application/libraries/Ics_file.php index a17261f945..4466936acf 100644 --- a/application/libraries/Ics_file.php +++ b/application/libraries/Ics_file.php @@ -78,7 +78,7 @@ public function get_stream(array $appointment, array $service, array $provider, ->setEnd($appointment_end) ->setStatus('CONFIRMED') ->setSummary($service['name']) - ->setUid($appointment['id']); + ->setUid($appointment['id_caldav_calendar'] ?: $this->generate_uid($appointment['id'])); if (!empty($service['location'])) { $location = new Location(); @@ -181,4 +181,51 @@ public function get_stream(array $appointment, array $service, array $provider, return $calendarExport->getStream(); } + + public function get_unavailability_stream(array $unavailability, array $provider): string + { + $unavailability_timezone = new DateTimeZone($provider['timezone']); + + $unavailability_start = new DateTime($unavailability['start_datetime'], $unavailability_timezone); + + $unavailability_end = new DateTime($unavailability['end_datetime'], $unavailability_timezone); + + // Set up the event. + $event = new CalendarEvent(); + + $event + ->setStart($unavailability_start) + ->setEnd($unavailability_end) + ->setStatus('CONFIRMED') + ->setSummary('Unavailability') + ->setUid($unavailability['id_caldav_calendar'] ?: $this->generate_uid($unavailability['id'])); + + $event->setDescription(str_replace("\n", "\\n", (string) $unavailability['notes'])); + + // Set the organizer. + $organizer = new Organizer(new Formatter()); + + $organizer->setValue($provider['email'])->setName($provider['first_name'] . ' ' . $provider['last_name']); + + $event->setOrganizer($organizer); + + // Setup calendar. + $calendar = new Ics_calendar(); + + $calendar + ->setProdId('-//EasyAppointments//Open Source Web Scheduler//EN') + ->setTimezone(new DateTimeZone($provider['timezone'])) + ->addEvent($event); + + // Setup exporter. + $calendarExport = new CalendarExport(new CalendarStream(), new Formatter()); + $calendarExport->addCalendar($calendar); + + return $calendarExport->getStream(); + } + + public function generate_uid(int $db_record_id): string + { + return 'ea-' . md5($db_record_id); + } } diff --git a/application/libraries/Synchronization.php b/application/libraries/Synchronization.php index d029730cf4..aed977c57c 100644 --- a/application/libraries/Synchronization.php +++ b/application/libraries/Synchronization.php @@ -36,6 +36,7 @@ public function __construct() $this->CI->load->model('appointments_model'); $this->CI->load->library('google_sync'); + $this->CI->load->library('caldav_sync'); } /** @@ -55,32 +56,45 @@ public function sync_appointment_saved( array $settings, ): void { try { - if (!$provider['settings']['google_sync']) { - return; - } + // Google - if (empty($provider['settings']['google_token'])) { - throw new RuntimeException('No google token available for the provider: ' . $provider['id']); - } + if ($provider['settings']['google_sync']) { + if (empty($provider['settings']['google_token'])) { + throw new RuntimeException('No google token available for the provider: ' . $provider['id']); + } + + $google_token = json_decode($provider['settings']['google_token'], true); - $google_token = json_decode($provider['settings']['google_token'], true); + $this->CI->google_sync->refresh_token($google_token['refresh_token']); - $this->CI->google_sync->refresh_token($google_token['refresh_token']); + if (empty($appointment['id_google_calendar'])) { + $google_event = $this->CI->google_sync->add_appointment( + $appointment, + $provider, + $service, + $customer, + $settings, + ); + + $appointment['id_google_calendar'] = $google_event->getId(); + + $this->CI->appointments_model->save($appointment); + } else { + $this->CI->google_sync->update_appointment($appointment, $provider, $service, $customer, $settings); + } + } - if (empty($appointment['id_google_calendar'])) { - $google_event = $this->CI->google_sync->add_appointment( + // CalDAV + + if ($provider['settings']['caldav_sync']) { + $appointment['id_caldav_calendar'] = $this->CI->caldav_sync->save_appointment( $appointment, - $provider, $service, + $provider, $customer, - $settings, ); - $appointment['id_google_calendar'] = $google_event->getId(); - $this->CI->appointments_model->save($appointment); - } else { - $this->CI->google_sync->update_appointment($appointment, $provider, $service, $customer, $settings); } } catch (Throwable $e) { log_message( @@ -90,6 +104,47 @@ public function sync_appointment_saved( ') : ' . $e->getMessage(), ); + + log_message('error', $e->getTraceAsString()); + } + } + + /** + * Synchronize removal of an appointment with external calendars. + * + * @param array $appointment Appointment record. + * @param array $provider Provider record. + */ + public function sync_appointment_deleted(array $appointment, array $provider): void + { + try { + // Google + + if ($provider['settings']['google_sync'] && !empty($appointment['id_google_calendar'])) { + if (empty($provider['settings']['google_token'])) { + throw new RuntimeException('No google token available for the provider: ' . $provider['id']); + } + + $google_token = json_decode($provider['settings']['google_token'], true); + + $this->CI->google_sync->refresh_token($google_token['refresh_token']); + + $this->CI->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); + } + + // CalDAV + + if ($provider['settings']['caldav_sync'] && !empty($appointment['id_caldav_calendar'])) { + $this->CI->caldav_sync->delete_event($provider, $appointment['id_caldav_calendar']); + } + } catch (Throwable $e) { + log_message( + 'error', + 'Synchronization - Could not sync cancellation details of appointment (' . + ($appointment['id'] ?? '-') . + ') : ' . + $e->getMessage(), + ); log_message('error', $e->getTraceAsString()); } } @@ -103,26 +158,37 @@ public function sync_appointment_saved( public function sync_unavailability_saved(array $unavailability, array $provider): void { try { - if (!$provider['settings']['google_sync']) { - return; - } + // Google - if (empty($provider['settings']['google_token'])) { - throw new RuntimeException('No google token available for the provider: ' . $provider['id']); - } + if ($provider['settings']['google_sync']) { + if (empty($provider['settings']['google_token'])) { + throw new RuntimeException('No google token available for the provider: ' . $provider['id']); + } + + $google_token = json_decode($provider['settings']['google_token'], true); + + $this->CI->google_sync->refresh_token($google_token['refresh_token']); - $google_token = json_decode($provider['settings']['google_token'], true); + if (empty($unavailability['id_google_calendar'])) { + $google_event = $this->CI->google_sync->add_unavailability($provider, $unavailability); - $this->CI->google_sync->refresh_token($google_token['refresh_token']); + $unavailability['id_google_calendar'] = $google_event->getId(); + + $this->CI->unavailabilities_model->save($unavailability); + } else { + $this->CI->google_sync->update_unavailability($provider, $unavailability); + } + } - if (empty($unavailability['id_google_calendar'])) { - $google_event = $this->CI->google_sync->add_unavailability($provider, $unavailability); + // CalDAV - $unavailability['id_google_calendar'] = $google_event->getId(); + if ($provider['settings']['caldav_sync']) { + $unavailability['id_caldav_calendar'] = $this->CI->caldav_sync->save_unavailability( + $unavailability, + $provider, + ); $this->CI->unavailabilities_model->save($unavailability); - } else { - $this->CI->google_sync->update_unavailability($provider, $unavailability); } } catch (Throwable $e) { log_message( @@ -145,19 +211,25 @@ public function sync_unavailability_saved(array $unavailability, array $provider public function sync_unavailability_deleted(array $unavailability, array $provider): void { try { - if (!$provider['settings']['google_sync'] || empty($unavailability['id_google_calendar'])) { - return; - } + // Google - if (empty($provider['settings']['google_token'])) { - throw new RuntimeException('No google token available for the provider: ' . $provider['id']); - } + if ($provider['settings']['google_sync'] && !empty($unavailability['id_google_calendar'])) { + if (empty($provider['settings']['google_token'])) { + throw new RuntimeException('No google token available for the provider: ' . $provider['id']); + } + + $google_token = json_decode($provider['settings']['google_token'], true); - $google_token = json_decode($provider['settings']['google_token'], true); + $this->CI->google_sync->refresh_token($google_token['refresh_token']); - $this->CI->google_sync->refresh_token($google_token['refresh_token']); + $this->CI->google_sync->delete_unavailability($provider, $unavailability['id_google_calendar']); + } + + // CalDAV - $this->CI->google_sync->delete_unavailability($provider, $unavailability['id_google_calendar']); + if ($provider['settings']['caldav_sync'] && !empty($unavailability['id_caldav_calendar'])) { + $this->CI->caldav_sync->delete_event($provider, $unavailability['id_caldav_calendar']); + } } catch (Throwable $e) { log_message( 'error', @@ -171,7 +243,7 @@ public function sync_unavailability_deleted(array $unavailability, array $provid } /** - * Make sure a synced appointment is removed from Google Calendar, if its provider is changed. + * Make sure a synced appointment is removed from Google/CalDAV Calendar, if its provider is changed. * * @throws Exception */ @@ -180,52 +252,19 @@ public function remove_appointment_on_provider_change($appointment_id): void $existing_appointment = $this->CI->appointments_model->find($appointment_id); $existing_google_id = $existing_appointment['id_google_calendar']; + $existing_caldav_id = $existing_appointment['id_caldav_calendar']; $existing_provider_id = $existing_appointment['id_users_provider']; if ( - !empty($existing_google_id) && + (!empty($existing_google_id) || !empty($existing_caldav_id)) && (int) $existing_provider_id !== (int) $existing_appointment['id_users_provider'] ) { $existing_provider = $this->CI->providers_model->find($existing_provider_id); - if ($existing_provider['settings']['google_sync']) { + if ($existing_provider['settings']['google_sync'] || $existing_provider['settings']['caldav_sync']) { $this->sync_appointment_deleted($existing_appointment, $existing_provider); } } } - - /** - * Synchronize removal of an appointment with external calendars. - * - * @param array $appointment Appointment record. - * @param array $provider Provider record. - */ - public function sync_appointment_deleted(array $appointment, array $provider): void - { - try { - if (!$provider['settings']['google_sync'] || empty($appointment['id_google_calendar'])) { - return; - } - - if (empty($provider['settings']['google_token'])) { - throw new RuntimeException('No google token available for the provider: ' . $provider['id']); - } - - $google_token = json_decode($provider['settings']['google_token'], true); - - $this->CI->google_sync->refresh_token($google_token['refresh_token']); - - $this->CI->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); - } catch (Throwable $e) { - log_message( - 'error', - 'Synchronization - Could not sync cancellation details of appointment (' . - ($appointment['id'] ?? '-') . - ') : ' . - $e->getMessage(), - ); - log_message('error', $e->getTraceAsString()); - } - } } diff --git a/application/migrations/055_add_caldav_columns_to_user_settings_table.php b/application/migrations/055_add_caldav_columns_to_user_settings_table.php new file mode 100644 index 0000000000..71a262ec4e --- /dev/null +++ b/application/migrations/055_add_caldav_columns_to_user_settings_table.php @@ -0,0 +1,112 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +class Migration_Add_caldav_columns_to_user_settings_table extends EA_Migration +{ + /** + * Upgrade method. + */ + public function up() + { + if (!$this->db->field_exists('caldav_sync', 'user_settings')) { + $fields = [ + 'caldav_sync' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'default' => false, + 'after' => 'google_calendar', + ], + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + + if (!$this->db->field_exists('caldav_url', 'user_settings')) { + $fields = [ + 'caldav_url' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => true, + 'after' => 'caldav_sync', + ], + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + + if (!$this->db->field_exists('caldav_username', 'user_settings')) { + $fields = [ + 'caldav_username' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => true, + 'after' => 'caldav_url', + ], + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + + if (!$this->db->field_exists('caldav_password', 'user_settings')) { + $fields = [ + 'caldav_password' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => true, + 'after' => 'caldav_username', + ], + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + + if (!$this->db->field_exists('caldav_calendar', 'user_settings')) { + $fields = [ + 'caldav_calendar' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => true, + 'after' => 'caldav_password', + ], + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('caldav_sync', 'user_settings')) { + $this->dbforge->drop_column('user_settings', 'caldav_sync'); + } + + if ($this->db->field_exists('caldav_url', 'user_settings')) { + $this->dbforge->drop_column('user_settings', 'caldav_url'); + } + + if ($this->db->field_exists('caldav_username', 'user_settings')) { + $this->dbforge->drop_column('user_settings', 'caldav_username'); + } + + if ($this->db->field_exists('caldav_password', 'user_settings')) { + $this->dbforge->drop_column('user_settings', 'caldav_password'); + } + + if ($this->db->field_exists('caldav_calendar', 'user_settings')) { + $this->dbforge->drop_column('user_settings', 'caldav_calendar'); + } + } +} diff --git a/application/migrations/056_add_id_caldav_calendar_column_to_appointments_table.php b/application/migrations/056_add_id_caldav_calendar_column_to_appointments_table.php new file mode 100644 index 0000000000..3eccea923e --- /dev/null +++ b/application/migrations/056_add_id_caldav_calendar_column_to_appointments_table.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +class Migration_Add_id_caldav_calendar_column_to_appointments_table extends EA_Migration +{ + /** + * Upgrade method. + */ + public function up() + { + if (!$this->db->field_exists('id_caldav_calendar', 'appointments')) { + $fields = [ + 'id_caldav_calendar' => [ + 'type' => 'TEXT', + 'default' => '', + 'after' => 'id_google_calendar', + ], + ]; + + $this->dbforge->add_column('appointments', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('id_caldav_calendar', 'appointments')) { + $this->dbforge->drop_column('appointments', 'id_caldav_calendar'); + } + } +} diff --git a/application/models/Appointments_model.php b/application/models/Appointments_model.php index 314ea21921..6c4644c14e 100644 --- a/application/models/Appointments_model.php +++ b/application/models/Appointments_model.php @@ -46,6 +46,7 @@ class Appointments_model extends EA_Model 'providerId' => 'id_users_provider', 'customerId' => 'id_users_customer', 'googleCalendarId' => 'id_google_calendar', + 'caldavCalendarId' => 'id_caldav_calendar', ]; /** @@ -328,6 +329,16 @@ public function clear_google_sync_ids(int $provider_id): void $this->db->update('appointments', ['id_google_calendar' => null], ['id_users_provider' => $provider_id]); } + /** + * Remove all the Google Calendar event IDs from appointment records. + * + * @param int $provider_id Matching provider ID. + */ + public function clear_caldav_sync_ids(int $provider_id): void + { + $this->db->update('appointments', ['id_caldav_calendar' => null], ['id_users_provider' => $provider_id]); + } + /** * Get the attendants number for the requested period. * @@ -544,6 +555,8 @@ public function api_encode(array &$appointment): void 'serviceId' => $appointment['id_services'] !== null ? (int) $appointment['id_services'] : null, 'googleCalendarId' => $appointment['id_google_calendar'] !== null ? $appointment['id_google_calendar'] : null, + 'caldavCalendarId' => + $appointment['id_caldav_calendar'] !== null ? $appointment['id_caldav_calendar'] : null, ]; $appointment = $encoded_resource; @@ -607,6 +620,10 @@ public function api_decode(array &$appointment, array $base = null): void $decoded_request['id_google_calendar'] = $appointment['googleCalendarId']; } + if (array_key_exists('caldavCalendarId', $appointment)) { + $decoded_request['id_caldav_calendar'] = $appointment['caldavCalendarId']; + } + $decoded_request['is_unavailability'] = false; $appointment = $decoded_request; diff --git a/application/models/Providers_model.php b/application/models/Providers_model.php index a3db5df657..e10f646558 100755 --- a/application/models/Providers_model.php +++ b/application/models/Providers_model.php @@ -763,11 +763,26 @@ public function api_encode(array &$provider): void 'googleSync' => array_key_exists('google_sync', $provider['settings']) ? filter_var($provider['settings']['google_sync'], FILTER_VALIDATE_BOOLEAN) : null, + 'googleToken' => array_key_exists('google_token', $provider['settings']) + ? $provider['settings']['google_token'] + : null, 'googleCalendar' => array_key_exists('google_calendar', $provider['settings']) ? $provider['settings']['google_calendar'] : null, - 'googleToken' => array_key_exists('google_token', $provider['settings']) - ? $provider['settings']['google_token'] + 'caldavSync' => array_key_exists('caldav_sync', $provider['settings']) + ? filter_var($provider['settings']['caldav_sync'], FILTER_VALIDATE_BOOLEAN) + : null, + 'caldavUrl' => array_key_exists('caldav_url', $provider['settings']) + ? $provider['settings']['caldav_url'] + : null, + 'caldavUsername' => array_key_exists('caldav_username', $provider['settings']) + ? $provider['settings']['caldav_username'] + : null, + 'caldavPassword' => array_key_exists('caldav_password', $provider['settings']) + ? $provider['settings']['caldav_password'] + : null, + 'caldavCalendar' => array_key_exists('caldav_calendar', $provider['settings']) + ? $provider['settings']['caldav_calendar'] : null, 'syncFutureDays' => array_key_exists('sync_future_days', $provider['settings']) ? (int) $provider['settings']['sync_future_days'] diff --git a/application/views/components/select_google_calendar_modal.php b/application/views/components/select_google_calendar_modal.php deleted file mode 100644 index 82654c319e..0000000000 --- a/application/views/components/select_google_calendar_modal.php +++ /dev/null @@ -1,27 +0,0 @@ - diff --git a/application/views/pages/calendar.php b/application/views/pages/calendar.php index 6645a26284..1b9d8bbf77 100755 --- a/application/views/pages/calendar.php +++ b/application/views/pages/calendar.php @@ -4,30 +4,49 @@
-
+
- +
-
- - - + @@ -63,14 +82,14 @@ - + - + @@ -107,8 +126,6 @@ 'timezone' => vars('timezone'), ]); ?> - - @@ -125,11 +142,14 @@ - - + + + + + diff --git a/assets/js/http/caldav_http_client.js b/assets/js/http/caldav_http_client.js new file mode 100644 index 0000000000..b9e84dcf9f --- /dev/null +++ b/assets/js/http/caldav_http_client.js @@ -0,0 +1,108 @@ +/* ---------------------------------------------------------------------------- + * Easy!Appointments - Online Appointment Scheduler + * + * @package EasyAppointments + * @author A.Tselegidis + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +/** + * Caldav HTTP client. + * + * This module implements the Caldav Calendar related HTTP requests. + */ +App.Http.Caldav = (function () { + /** + * Select the Caldav Calendar for the synchronization with a provider. + * + * @param {Number} providerId + * @param {String} caldavCalendarId + * + * @return {*|jQuery} + */ + function selectCaldavCalendar(providerId, caldavCalendarId) { + const url = App.Utils.Url.siteUrl('caldav/select_caldav_calendar'); + + const data = { + csrf_token: vars('csrf_token'), + provider_id: providerId, + calendar_id: caldavCalendarId, + }; + + return $.post(url, data); + } + + /** + * Disable the Caldav Calendar syncing of a provider. + * + * @param {Number} providerId + * + * @return {*|jQuery} + */ + function disableProviderSync(providerId) { + const url = App.Utils.Url.siteUrl('caldav/disable_provider_sync'); + + const data = { + csrf_token: vars('csrf_token'), + provider_id: providerId, + }; + + return $.post(url, data); + } + + /** + * Get the available Caldav Calendars of the connected provider's account. + * + * @param {Number} providerId + * + * @return {*|jQuery} + */ + function getCaldavCalendars(providerId) { + const url = App.Utils.Url.siteUrl('caldav/get_caldav_calendars'); + + const data = { + csrf_token: vars('csrf_token'), + provider_id: providerId, + }; + + return $.post(url, data); + } + + /** + * Trigger the sync process between Easy!Appointments and Caldav Calendar. + * + * @param {Number} providerId + * + * @return {*|jQuery} + */ + function syncWithCaldav(providerId) { + const url = App.Utils.Url.siteUrl('caldav/sync/' + providerId); + + return $.get(url); + } + + function connectToServer(providerId, caldavUrl, caldavUsername, caldavPassword) { + const url = App.Utils.Url.siteUrl('caldav/connect_to_server'); + + const data = { + csrf_token: vars('csrf_token'), + provider_id: providerId, + caldav_url: caldavUrl, + caldav_username: caldavUsername, + caldav_password: caldavPassword, + }; + + return $.post(url, data); + } + + return { + getCaldavCalendars, + selectCaldavCalendar, + disableProviderSync, + syncWithCaldav, + connectToServer, + }; +})(); diff --git a/assets/js/pages/admins.js b/assets/js/pages/admins.js index 3ae8c35c88..27bf1049de 100644 --- a/assets/js/pages/admins.js +++ b/assets/js/pages/admins.js @@ -154,14 +154,14 @@ App.Pages.Admins = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.Admins.remove(adminId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/blocked_periods.js b/assets/js/pages/blocked_periods.js index 3356f98df5..8d60bc99fe 100644 --- a/assets/js/pages/blocked_periods.js +++ b/assets/js/pages/blocked_periods.js @@ -108,14 +108,14 @@ App.Pages.BlockedPeriods = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.BlockedPeriods.remove(blockedPeriodId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/booking.js b/assets/js/pages/booking.js index 56a9306218..88309713fa 100644 --- a/assets/js/pages/booking.js +++ b/assets/js/pages/booking.js @@ -424,12 +424,6 @@ App.Pages.Booking = (function () { $('#step-' + nextTabIndex).addClass('active-step'); $('#wizard-frame-' + nextTabIndex).fadeIn(); }); - - // Scroll to the top of the page. On a small screen, especially on a mobile device, this is very useful. - const scrollingElement = (document.scrollingElement || document.body); - if (window.innerHeight < scrollingElement.scrollHeight) { - scrollingElement.scrollTop = 0; - } }); /** @@ -481,7 +475,7 @@ App.Pages.Booking = (function () { { text: lang('close'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { @@ -520,7 +514,7 @@ App.Pages.Booking = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { @@ -677,14 +671,14 @@ App.Pages.Booking = (function () {
${serviceOptionText} -
+
${providerOptionText}
${formattedSelectedDate} -
+
${service.duration} ${lang('minutes')} @@ -692,12 +686,12 @@ App.Pages.Booking = (function () {
${timezoneOptionText} -
+
${Number(service.price).toFixed(2)} ${service.currency}
-
+
`); // Render the customer information diff --git a/assets/js/pages/business_settings.js b/assets/js/pages/business_settings.js index f68b3d1e43..4f2f54523d 100644 --- a/assets/js/pages/business_settings.js +++ b/assets/js/pages/business_settings.js @@ -117,7 +117,7 @@ App.Pages.BusinessSettings = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { @@ -130,7 +130,7 @@ App.Pages.BusinessSettings = (function () { App.Layouts.Backend.displayNotification(lang('working_plans_got_updated')); }) .always(() => { - messageModal.dispose(); + messageModal.hide(); }); }, }, diff --git a/assets/js/pages/customers.js b/assets/js/pages/customers.js index 04b3ee64b1..139c7914a2 100644 --- a/assets/js/pages/customers.js +++ b/assets/js/pages/customers.js @@ -160,14 +160,14 @@ App.Pages.Customers = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.Customers.remove(customerId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/providers.js b/assets/js/pages/providers.js index 210cee02b2..450e5e9d23 100755 --- a/assets/js/pages/providers.js +++ b/assets/js/pages/providers.js @@ -135,14 +135,14 @@ App.Pages.Providers = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.Providers.remove(providerId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/secretaries.js b/assets/js/pages/secretaries.js index bb4034d745..97b232d9a8 100644 --- a/assets/js/pages/secretaries.js +++ b/assets/js/pages/secretaries.js @@ -158,14 +158,14 @@ App.Pages.Secretaries = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { remove(secretaryId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/service_categories.js b/assets/js/pages/service_categories.js index 8d96993197..72074f24bd 100644 --- a/assets/js/pages/service_categories.js +++ b/assets/js/pages/service_categories.js @@ -100,14 +100,14 @@ App.Pages.ServiceCategories = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { remove(serviceCategoryId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/services.js b/assets/js/pages/services.js index d1b191a65d..4e67ce86f9 100644 --- a/assets/js/pages/services.js +++ b/assets/js/pages/services.js @@ -178,14 +178,14 @@ App.Pages.Services = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.Services.remove(serviceId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/pages/webhooks.js b/assets/js/pages/webhooks.js index f898e3b263..db3facfaf1 100644 --- a/assets/js/pages/webhooks.js +++ b/assets/js/pages/webhooks.js @@ -148,14 +148,14 @@ App.Pages.Webhooks = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { text: lang('delete'), click: (event, messageModal) => { App.Pages.Webhooks.remove(webhookId); - messageModal.dispose(); + messageModal.hide(); }, }, ]; diff --git a/assets/js/utils/calendar_default_view.js b/assets/js/utils/calendar_default_view.js index 2758af9645..93fe270c87 100755 --- a/assets/js/utils/calendar_default_view.js +++ b/assets/js/utils/calendar_default_view.js @@ -248,7 +248,7 @@ App.Utils.CalendarDefaultView = (function () { { text: lang('cancel'), click: (event, messageModal) => { - messageModal.dispose(); + messageModal.hide(); }, }, { @@ -259,7 +259,7 @@ App.Utils.CalendarDefaultView = (function () { const cancellationReason = $('#cancellation-reason').val(); App.Http.Calendar.deleteAppointment(appointmentId, cancellationReason).done(() => { - messageModal.dispose(); + messageModal.hide(); // Refresh calendar event items. $reloadAppointments.trigger('click'); @@ -297,41 +297,18 @@ App.Utils.CalendarDefaultView = (function () { * Load the appointments that correspond to the select filter item and display them on the calendar. */ $selectFilterItem.on('change', () => { - // If current value is service, then the sync buttons must be disabled. - if ( - $selectFilterItem.find('option:selected').attr('type') === FILTER_TYPE_SERVICE || - $selectFilterItem.val() === 'all' - ) { - $('#google-sync, #enable-sync, #insert-appointment, #insert-dropdown').prop('disabled', true); - } else { - $('#google-sync, #enable-sync, #insert-appointment, #insert-dropdown').prop('disabled', false); - - const providerId = $selectFilterItem.val(); - - const provider = vars('available_providers').find( - (availableProvider) => Number(availableProvider.id) === Number(providerId), - ); + const providerId = $selectFilterItem.val(); - if (provider && provider.timezone) { - $('.provider-timezone').text(vars('timezones')[provider.timezone]); - } - - // If the user has already the sync enabled then apply the proper style changes. - if ($selectFilterItem.find('option:selected').attr('google-sync') === 'true') { - $('#enable-sync').removeClass('btn-light').addClass('btn-secondary enabled'); - $('#enable-sync span').text(lang('disable_sync')); - $('#google-sync').prop('disabled', false); - } else { - $('#enable-sync').removeClass('btn-secondary enabled').addClass('btn-light'); - $('#enable-sync span').text(lang('enable_sync')); - $('#google-sync').prop('disabled', true); - } + const provider = vars('available_providers').find( + (availableProvider) => Number(availableProvider.id) === Number(providerId), + ); - $('#insert-working-plan-exception').toggle( - providerId !== App.Utils.CalendarDefaultView.FILTER_TYPE_ALL, - ); + if (provider && provider.timezone) { + $('.provider-timezone').text(vars('timezones')[provider.timezone]); } + $('#insert-working-plan-exception').toggle(providerId !== App.Utils.CalendarDefaultView.FILTER_TYPE_ALL); + $reloadAppointments.trigger('click'); window.localStorage.setItem('EasyAppointments.SelectFilterItem', $selectFilterItem.val()); @@ -1063,7 +1040,7 @@ App.Utils.CalendarDefaultView = (function () { App.Utils.UI.setDateTimePickerValue($('#unavailability-end'), info.end); - messageModal.dispose(); + messageModal.hide(); }, }, { @@ -1121,7 +1098,7 @@ App.Utils.CalendarDefaultView = (function () { App.Pages.Calendar.getSelectionEndDate(info), ); - messageModal.dispose(); + messageModal.hide(); }, }, ]; @@ -1530,12 +1507,13 @@ App.Utils.CalendarDefaultView = (function () { 'label': lang('providers'), 'type': 'providers-group', 'html': vars('available_providers').map((availableProvider) => { - const hasGoogleSync = availableProvider.settings.google_sync === '1' ? 'true' : 'false'; + const {settings} = availableProvider; return $('