Plugin Directory

Changeset 3454590


Ignore:
Timestamp:
02/05/2026 11:59:11 AM (7 weeks ago)
Author:
creavi
Message:
  • Added multilingual support for frontend and admin.
  • Included French (fr_FR) and Danish (da_DK) translations.
Location:
creavi-booking-service
Files:
56 added
6 edited

Legend:

Unmodified
Added
Removed
  • creavi-booking-service/trunk/assets/js/admin.js

    r3431070 r3454590  
    9595});
    9696
    97 /*
    98 document.addEventListener('DOMContentLoaded', function () {
    99     const field = document.querySelector("#creavibc_available_booking_days");
    100 
    101     if (!field || typeof flatpickr === "undefined") {
    102         console.warn('Flatpickr or input not found');
    103         return;
    104     }
    105 
    106     const defaultDates = field.value
    107         ? field.value.split(',').map(s => s.trim())
    108         : [];
    109 
    110     flatpickr(field, {
    111         mode: "multiple",
    112         dateFormat: "Y-m-d",
    113         defaultDate: defaultDates,
    114         closeOnSelect: false,
    115         onChange: function (selectedDates, dateStr, instance) {
    116             const formatted = selectedDates.map(date =>
    117                 instance.formatDate(date, "Y-m-d")
    118             ).join(',');
    119             field.value = formatted;
    120             field.dispatchEvent(new Event('input', { bubbles: true }));
    121         }
    122     });
    123 });*/
    12497
    12598document.addEventListener('DOMContentLoaded', function () {
     
    202175
    203176    if (addBtn && container) {
    204 
    205        
     177 
    206178
    207179        addBtn.addEventListener('click', () => {
     
    577549    }
    578550
    579 
    580 
    581 
    582 
    583 
    584551});
    585552
  • creavi-booking-service/trunk/assets/js/booking.js

    r3448790 r3454590  
    11jQuery(function ($) {
     2
     3    const i18n = (window.wp && wp.i18n) ? wp.i18n : null;
     4    const __ = i18n ? i18n.__ : (s) => s;
     5    const sprintf = i18n ? i18n.sprintf : (fmt, ...args) => [fmt, ...args].join(' ');
     6    const CBS_DOMAIN = 'creavi-booking-service';
     7
     8    function creavibcApplyFlatpickrLocale() {
     9        if (!window.flatpickr || !window.creavibc_ajax) return;
     10
     11        const wpLocale = String(creavibc_ajax.locale || '').toLowerCase();
     12
     13        if (wpLocale.startsWith('fr') && flatpickr.l10ns.fr) flatpickr.localize(flatpickr.l10ns.fr);
     14        if (wpLocale.startsWith('da') && flatpickr.l10ns.da) flatpickr.localize(flatpickr.l10ns.da);
     15    }
     16
     17    creavibcApplyFlatpickrLocale();
     18
     19
     20
    221    function isValidEmail(email) {
    322        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
     
    2443            if (val === '') {
    2544                $input.addClass('creavibc-field-error');
    26                 $input.after('<span class="creavibc-error-msg">This field is required.</span>');
     45                //$input.after('<span class="creavibc-error-msg">This field is required.</span>');
     46                $input.after('<span class="creavibc-error-msg">' + __( 'This field is required.', CBS_DOMAIN ) + '</span>');
     47
    2748                return false;
    2849            }
    2950            if (isEmail && !isValidEmail(val)) {
    3051                $input.addClass('creavibc-field-error');
    31                 $input.after('<span class="creavibc-error-msg">Please enter a valid email address.</span>');
     52                //$input.after('<span class="creavibc-error-msg">Please enter a valid email address.</span>');
     53                $input.after('<span class="creavibc-error-msg">' + __( 'Please enter a valid email address.', CBS_DOMAIN ) + '</span>');
     54
    3255                return false;
    3356            }
     
    6588        const backBtn = popup.querySelector('.creavibc-back');
    6689
    67         if (step === 1) {
    68             nextBtn.textContent = 'Next';
     90        if (step === 1) {           
     91            nextBtn.textContent = __( 'Next', CBS_DOMAIN );
    6992            nextBtn.classList.remove('creavibc-submit-final');
    7093            backBtn.disabled = true;
    7194        } else {
    72             nextBtn.textContent = 'Book a Meeting';
     95           
     96            nextBtn.textContent = __( 'Book a Meeting', CBS_DOMAIN );           
    7397            nextBtn.classList.add('creavibc-submit-final');
    7498            backBtn.disabled = false;
     
    214238
    215239            const instance = window.CREAVIBC_INSTANCES?.[serviceId];
    216             const thankyouText = instance?.THANKYOU_TEXT || "Thank you for booking\nSee you soon!";
     240            //const thankyouText = instance?.THANKYOU_TEXT || "Thank you for booking\nSee you soon!";
     241            const thankyouText = instance?.THANKYOU_TEXT || __( "Thank you for booking\nSee you soon!", CBS_DOMAIN );
     242
    217243            console.log(instance.THANKYOU_TEXT);
    218244
     
    235261                .removeClass('creavibc-submit-final')
    236262                .addClass('creavibc-close-final')
    237                 .text('Close');
     263                .text( __( 'Close', CBS_DOMAIN ) );
     264
    238265        });
    239266    });
     
    427454
    428455        const form = CREAVIBC_INSTANCES[serviceId].FORM_FIELDS;
    429         let html = '<p class="creavibc-form-heading"><strong>Enter your details:</strong></p>';
     456        //let html = '<p class="creavibc-form-heading"><strong>Enter your details:</strong></p>';
     457        let html = '<p class="creavibc-form-heading"><strong>' + __( 'Enter your details:', CBS_DOMAIN ) + '</strong></p>';
     458
    430459
    431460        if (form.name) {
    432461            const isRequired = form.required?.name ? 'required' : '';
    433462            const asterisk = isRequired ? ' <span class="creavibc-required">*</span>' : '';
    434             html += `<label>Name${asterisk}<br><input type="text" id="creavibc-name-${serviceId}" ${isRequired}></label>`;
     463            //html += `<label>Name${asterisk}<br><input type="text" id="creavibc-name-${serviceId}" ${isRequired}></label>`;
     464            html += `<label>${ __( 'Name', CBS_DOMAIN ) }${asterisk}<br><input type="text" id="creavibc-name-${serviceId}" ${isRequired}></label>`;
     465
    435466        }
    436467
     
    438469            const isRequired = form.required?.email ? 'required' : '';
    439470            const asterisk = isRequired ? ' <span class="creavibc-required">*</span>' : '';
    440             html += `<label>Email${asterisk}<br><input type="email" id="creavibc-email-${serviceId}" ${isRequired}></label>`;
     471            //html += `<label>Email${asterisk}<br><input type="email" id="creavibc-email-${serviceId}" ${isRequired}></label>`;
     472            html += `<label>${ __( 'Email', CBS_DOMAIN ) }${asterisk}<br><input type="email" id="creavibc-email-${serviceId}" ${isRequired}></label>`;
     473
    441474        }
    442475
    443476        if (Array.isArray(form.custom)) {
    444477            form.custom.forEach((field, i) => {
    445                 const label = field.label || `Field ${i + 1}`;
     478                //const label = field.label || `Field ${i + 1}`;
     479                const label = field.label || sprintf( __( 'Field %d', CBS_DOMAIN ), i + 1 );
     480
    446481                const type = field.type || 'text';
    447482                const required = field.required ? 'required' : '';
     
    630665
    631666            if (!slots.length) {
    632                 container.innerHTML = '<p>No slots available for this date.</p>';
     667               
     668                container.innerHTML = '<p>' + __( 'No slots available for this date.', CBS_DOMAIN ) + '</p>';
     669
    633670                return;
    634671            }
     
    745782            let message = '';
    746783            if (tzMode === 'locked' && adminTimezone !== userTimezone) {
    747                 message = `Time slots shown in provider’s timezone: ${adminTimezone}`;
     784                //message = `Time slots shown in provider’s timezone: ${adminTimezone}`;
     785                message = sprintf(
     786                __( 'Time slots shown in provider’s timezone: %s', CBS_DOMAIN ),
     787                adminTimezone
     788                );
     789
    748790            } else {
    749                 message = `Time slots are shown in your local timezone: ${userTimezone}`;
     791                //message = `Time slots are shown in your local timezone: ${userTimezone}`;
     792                message = sprintf(
     793                __( 'Time slots are shown in your local timezone: %s', CBS_DOMAIN ),
     794                userTimezone
     795                );
     796
    750797            }
    751798            tzNotice.innerHTML = message;
  • creavi-booking-service/trunk/creavi-booking-service.php

    r3448790 r3454590  
    44 * Description: Easy appointment booking system. Create services, manage availability, and accept bookings with a simple booking calendar.
    55 * Text Domain: creavi-booking-service
    6  * Version: 1.1.6
     6 * Domain Path: /languages
     7 * Version: 1.1.7
    78 * Author: Creavi
    89 * License: GPL2
     
    1516define('CREAVIBC_PLUGIN_URL', plugin_dir_url(__FILE__));
    1617define('CREAVIBC_PLUGIN_PATH', plugin_dir_path(__FILE__));
    17 define('CREAVIBC_VERSION', '1.1.6');
     18define('CREAVIBC_VERSION', '1.1.7');
     19
     20
     21add_action( 'plugins_loaded', function () {
     22    $domain = 'creavi-booking-service';
     23    $locale = function_exists( 'determine_locale' ) ? determine_locale() : get_locale();
     24
     25    $global_mo = WP_LANG_DIR . '/plugins/' . $domain . '-' . $locale . '.mo';
     26    $plugin_mo = plugin_dir_path( __FILE__ ) . 'languages/' . $domain . '-' . $locale . '.mo';
     27
     28    // Prefer global packs if present
     29    if ( file_exists( $global_mo ) ) {
     30        load_textdomain( $domain, $global_mo );
     31        return;
     32    }
     33
     34    // Otherwise load bundled MO
     35    if ( file_exists( $plugin_mo ) ) {
     36        load_textdomain( $domain, $plugin_mo );
     37    }
     38}, 1 );
     39
    1840
    1941require_once CREAVIBC_PLUGIN_DIR . 'includes/deactivation-feedback.php';
     
    3557
    3658
    37 add_action('wp_enqueue_scripts', function () {
    38        
     59add_action( 'wp_enqueue_scripts', function () {
     60
    3961    // Vendor scripts
    4062    wp_enqueue_script(
     
    6082        true
    6183    );
     84   
     85    // Flatpickr locale loading (conditional)
     86     
     87    $locale = function_exists( 'determine_locale' )
     88        ? determine_locale()
     89        : get_locale();
    6290
     91    // Normalize (fr_FR → fr, da_DK → da)
     92    $flatpickr_locale = strtolower( substr( $locale, 0, 2 ) );
    6393
    64     wp_enqueue_style('creavibc-style', CREAVIBC_PLUGIN_URL . 'assets/css/style.css', [], CREAVIBC_VERSION);
    65     $all_styles = get_option('creavibc_dynamic_button_styles', []);
    66     if (!empty($all_styles)) {
    67         wp_add_inline_style('creavibc-style', implode("\n", $all_styles));
     94    $supported_locales = [ 'fr', 'da' ];
     95
     96    if ( in_array( $flatpickr_locale, $supported_locales, true ) ) {
     97        wp_enqueue_script(
     98            'flatpickr-l10n-' . $flatpickr_locale,
     99            CREAVIBC_PLUGIN_URL . 'assets/vendor/flatpickr/l10n/' . $flatpickr_locale . '.js',
     100            [ 'flatpickr' ],
     101            '4.6.13',
     102            true
     103        );
    68104    }
    69105
    70     wp_enqueue_style('dashicons');
    71    
     106    wp_enqueue_style(
     107        'creavibc-style',
     108        CREAVIBC_PLUGIN_URL . 'assets/css/style.css',
     109        [],
     110        CREAVIBC_VERSION
     111    );
     112
     113    $all_styles = get_option( 'creavibc_dynamic_button_styles', [] );
     114    if ( ! empty( $all_styles ) ) {
     115        wp_add_inline_style( 'creavibc-style', implode( "\n", $all_styles ) );
     116    }
     117
     118    wp_enqueue_style( 'dashicons' );
     119
    72120});
    73 
    74121
    75122
     
    77124
    78125function creavibc_booking_admin_menu() {
     126
    79127    // Main menu
    80128    add_menu_page(
    81         'Creavi Booking',
    82         'Creavi Booking',
     129        __( 'Creavi Booking', 'creavi-booking-service' ),
     130        __( 'Creavi Booking', 'creavi-booking-service' ),
    83131        'manage_options',
    84132        'edit.php?post_type=creavibc_service',
     
    91139    add_submenu_page(
    92140        'edit.php?post_type=creavibc_service',
    93         'Services',
    94         'Services',
     141        __( 'Services', 'creavi-booking-service' ),
     142        __( 'Services', 'creavi-booking-service' ),
    95143        'manage_options',
    96144        'edit.php?post_type=creavibc_service'
     
    100148    add_submenu_page(
    101149        'edit.php?post_type=creavibc_service',
    102         'All Bookings',
    103         'All Bookings',
     150        __( 'All Bookings', 'creavi-booking-service' ),
     151        __( 'All Bookings', 'creavi-booking-service' ),
    104152        'manage_options',
    105153        'edit.php?post_type=creavibc_booking'
    106154    );
    107155}
     156
    108157
    109158register_deactivation_hook(__FILE__, function () {
  • creavi-booking-service/trunk/includes/functions.php

    r3448790 r3454590  
    2222    if (!in_array($service_id, $creavibc_services_on_page)) {
    2323        $creavibc_services_on_page[] = $service_id;
    24     }
    25        
    26     $btn_text = get_post_meta($service_id, '_creavibc_button_text', true) ?: 'Book Now';
     24    }       
     25   
     26    $btn_text = get_post_meta( $service_id, '_creavibc_button_text', true );
     27    if ( '' === (string) $btn_text ) {
     28        $btn_text = __( 'Book Now', 'creavi-booking-service' );
     29    }
     30
     31   
    2732    return '<button class="creavibc-book-now-btn" data-service-id="' . esc_attr($service_id) . '">' . esc_html($btn_text) . '</button>';
    2833
     
    195200
    196201add_action('wp_enqueue_scripts', function() {
    197   wp_register_script(
    198     'creavibc-script',
    199     CREAVIBC_PLUGIN_URL . 'assets/js/booking.js',
    200     ['jquery', 'flatpickr', 'luxon'],
    201     CREAVIBC_VERSION,
    202     true
    203   );
    204 
    205   wp_enqueue_script('creavibc-script');
    206 
    207   wp_localize_script('creavibc-script', 'creavibc_ajax', [
     202    wp_register_script(
     203        'creavibc-script',
     204        CREAVIBC_PLUGIN_URL . 'assets/js/booking.js',
     205        ['jquery', 'flatpickr', 'luxon', 'wp-i18n'],
     206        CREAVIBC_VERSION,
     207        true
     208    );   
     209
     210    wp_localize_script('creavibc-script', 'creavibc_ajax', [
    208211        'ajax_url'       => admin_url('admin-ajax.php'),
    209212        'nonce'          => wp_create_nonce('creavibc_booking_nonce'),
    210213        'week_starts_on' => (int) get_option('start_of_week', 0), //  WP setting
     214        'locale'         => function_exists('determine_locale') ? determine_locale() : get_locale(),
     215       
    211216    ]);
    212217
     218    wp_set_script_translations(
     219        'creavibc-script',
     220        'creavi-booking-service',
     221        CREAVIBC_PLUGIN_DIR . 'languages'
     222    );
     223
     224    wp_enqueue_script('creavibc-script');
     225
    213226});
     227
    214228
    215229
  • creavi-booking-service/trunk/includes/meta-boxes.php

    r3448790 r3454590  
    66    add_meta_box(
    77        'creavibc_output_type',
    8         'Booking Display Type',
     8        __( 'Booking Display Type', 'creavi-booking-service' ),
    99        'creavibc_render_output_type_box',
    1010        'creavibc_service',
     
    1212        'default'
    1313    );
    14     add_meta_box('creavibc_available_days', 'Available Booking Days', 'creavibc_render_available_days_box', 'creavibc_service', 'normal', 'high');   
    15     add_meta_box('creavibc_booking_form_fields', 'Booking Form Fields', 'creavibc_render_form_fields_box', 'creavibc_service', 'normal', 'default');
    16     add_meta_box('creavibc_booking_details', 'Booking Details', 'creavibc_render_booking_meta', 'creavibc_booking', 'normal', 'default');
     14    add_meta_box('creavibc_available_days', __( 'Available Booking Days', 'creavi-booking-service' ), 'creavibc_render_available_days_box', 'creavibc_service', 'normal', 'high');
     15
     16    add_meta_box('creavibc_booking_form_fields', __( 'Booking Form Fields', 'creavi-booking-service' ), 'creavibc_render_form_fields_box', 'creavibc_service', 'normal', 'default');
     17    add_meta_box('creavibc_booking_details', __( 'Booking Details', 'creavi-booking-service' ), 'creavibc_render_booking_meta', 'creavibc_booking', 'normal', 'default');
    1718    add_meta_box(
    1819        'creavibc_time_slot_grid',
    19         'Visual Time Slot Selector',
     20        __( 'Visual Time Slot Selector', 'creavi-booking-service' ),
    2021        'creavibc_render_weekday_slots_grid_box',
    2122        'creavibc_service',
     
    2627    add_meta_box(
    2728        'creavibc_service_options',
    28         'Booking Appearance & Notifications',
     29        __( 'Booking Appearance & Notifications', 'creavi-booking-service' ),
    2930        'creavibc_render_service_options_box',
    3031        'creavibc_service',
     
    3536    add_meta_box(
    3637        'creavibc_google_calendar',
    37         'Google Calendar',
     38        __( 'Google Calendar', 'creavi-booking-service' ),
    3839        'creavibc_render_google_calendar_box',
    3940        'creavibc_service',
     
    4748add_action('init', function () {
    4849    register_taxonomy('creavibc_service_category', 'creavibc_booking', [       
    49         'label'        => 'Service Category',
     50        'labels' => [
     51            'name'          => __( 'Service Categories', 'creavi-booking-service' ),
     52            'singular_name' => __( 'Service Category', 'creavi-booking-service' ),
     53            'menu_name'     => __( 'Service Categories', 'creavi-booking-service' ),
     54        ],
     55
    5056        'hierarchical' => false,
    5157        'public'       => false,
     
    5763});
    5864
    59 /*
    60 function creavibc_render_output_type_box($post) {
    61     $stored_value = get_post_meta($post->ID, '_creavibc_output_type', true);
    62     $value = in_array($stored_value, ['popup', 'inline']) ? $stored_value : 'popup'; // stricter
    63 
    64     ?>
    65     <p><strong>How should the calendar appear?</strong></p>
    66     <label>
    67         <input type="radio" name="creavibc_output_type" value="popup" <?php checked($value, 'popup'); ?> />
    68         Popup (opens calendar in a modal on button click))
    69     </label><br>
    70     <label>
    71         <input type="radio" name="creavibc_output_type" value="inline" <?php checked($value, 'inline'); ?> />
    72         Inline (displays booking form directly on the page)
    73     </label>
    74     <?php
    75     wp_nonce_field('creavibc_save_output_type', 'creavibc_output_type_nonce');
    76 }*/
    7765
    7866function creavibc_render_output_type_box($post) {
     
    9078                <rect x="7" y="8" width="10" height="6" rx="1" fill="#007cba"/>
    9179            </svg>
    92             <strong>Popup</strong><br>
    93             Opens in a modal after clicking a button
     80            <strong><?php esc_html_e( 'Popup', 'creavi-booking-service' ); ?></strong><br>
     81            <?php esc_html_e( 'Opens in a modal after clicking a button', 'creavi-booking-service' ); ?>
     82
    9483        </label>
    9584
     
    9988                <path d="M3 4h18v2H3zm0 4h18v2H3zm0 4h18v2H3zm0 4h18v2H3zm0 4h18v2H3z"/>
    10089            </svg>
    101             <strong>Inline</strong><br>
    102             Embedded directly into the page
     90            <strong><?php esc_html_e( 'Inline', 'creavi-booking-service' ); ?></strong><br>
     91            <?php esc_html_e( 'Embedded directly into the page', 'creavi-booking-service' ); ?>
     92
    10393        </label>
    10494    </div>
     
    223213                        <select name="creavibc_dynamic_months_ahead" id="creavibc_dynamic_months_ahead" class="creavibc-select">
    224214                            <?php for ($i = 1; $i <= 12; $i++): ?>
    225                                 <option value="<?php echo esc_attr($i); ?>" <?php selected($months_ahead, $i); ?>>
    226                                     <?php echo esc_html($i . ' ' . __('month', 'creavi-booking-service') . ($i > 1 ? 's' : '')); ?>
     215
     216                                <option value="<?php echo esc_attr( $i ); ?>" <?php selected( $months_ahead, $i ); ?>>
     217                                    <?php
     218                                    echo esc_html(
     219                                        sprintf(
     220                                            _n( '%d month', '%d months', $i, 'creavi-booking-service' ),
     221                                            $i
     222                                        )
     223                                    );
     224                                    ?>
    227225                                </option>
     226
     227
    228228                            <?php endfor; ?>
    229229                        </select>
     
    266266                            <?php for ($i = 1; $i <= 12; $i++): ?>
    267267                                <option value="<?php echo esc_attr($i); ?>">
    268                                     <?php echo esc_html($i . ' Month' . ($i > 1 ? 's' : '') . ' Ahead'); ?>
     268                                    <?php
     269                                    echo esc_html( sprintf(
     270                                        _n( '%d month ahead', '%d months ahead', $i, 'creavi-booking-service' ),
     271                                        $i
     272                                    ) ); ?>
     273
    269274                                </option>
    270275                            <?php endfor; ?>
     
    307312
    308313    wp_nonce_field('creavibc_save_form_fields', 'creavibc_form_fields_nonce');
    309     echo '<p><strong>Enable Default Fields:</strong></p>';
     314
     315    echo '<p><strong>' . esc_html__( 'Enable Default Fields:', 'creavi-booking-service' ) . '</strong></p>';
    310316
    311317    $name_required  = !empty($settings['required']['name']);
     
    314320    echo '<div class="creavibc-default-field-row">';
    315321    echo '<label class="creavibc-checkbox-label">';
    316     echo '<input type="checkbox" name="creavibc_form_defaults[name]" value="1" ' . checked($defaults['name'], true, false) . '> Name';
     322    echo '<input type="checkbox" name="creavibc_form_defaults[name]" value="1" ' . checked($defaults['name'], true, false) . '> ' . esc_html__( 'Name', 'creavi-booking-service' );
    317323    echo '</label>';
    318324    echo '<label class="creavibc-checkbox-label">';
    319     echo '<input type="checkbox" name="creavibc_form_required[name]" value="1" ' . checked($name_required, true, false) . '> Required';
     325    echo '<input type="checkbox" name="creavibc_form_required[name]" value="1" ' . checked($name_required, true, false) . '> ' . esc_html__( 'Required', 'creavi-booking-service' );
    320326    echo '</label>';
    321327    echo '</div>';
     
    323329    echo '<div class="creavibc-default-field-row">';
    324330    echo '<label class="creavibc-checkbox-label">';
    325     echo '<input type="checkbox" name="creavibc_form_defaults[email]" value="1" ' . checked($defaults['email'], true, false) . '> Email';
     331    echo '<input type="checkbox" name="creavibc_form_defaults[email]" value="1" ' . checked($defaults['email'], true, false) . '> ' . esc_html__( 'Email', 'creavi-booking-service' );
    326332    echo '</label>';
    327333    echo '<label class="creavibc-checkbox-label">';
    328     echo '<input type="checkbox" name="creavibc_form_required[email]" value="1" ' . checked($email_required, true, false) . '> Required';
     334    echo '<input type="checkbox" name="creavibc_form_required[email]" value="1" ' . checked($email_required, true, false) . '> ' . esc_html__( 'Required', 'creavi-booking-service' );
    329335    echo '</label>';
    330336    echo '</div>';
    331337
    332338
    333     echo '<hr><p><strong>Custom Fields:</strong></p>';
     339    echo '<hr><p><strong>' . esc_html__( 'Custom Fields:', 'creavi-booking-service' ) . '</strong></p>';
    334340    echo '<div id="creavibc-custom-fields-container">';
    335341
     
    340346
    341347        echo '<div class="creavibc-custom-row">';
    342         echo '<input type="text" name="creavibc_custom_fields[label][]" value="' . esc_attr($label) . '" placeholder="Field label (e.g. Phone)" style="width: 45%;" />';
     348        echo '<input type="text" name="creavibc_custom_fields[label][]" value="' . esc_attr($label) . '" placeholder="' . esc_attr__( 'Field label (e.g. Phone)', 'creavi-booking-service' ) . '" style="width: 45%;" />';
    343349        echo '<select name="creavibc_custom_fields[type][]" style="width: 20%;">';
    344         echo '<option value="text"' . ($type === 'text' ? ' selected' : '') . '>Text</option>';
    345         echo '<option value="textarea"' . ($type === 'textarea' ? ' selected' : '') . '>Textarea</option>';
     350        echo '<option value="text"' . ($type === 'text' ? ' selected' : '') . '>' . esc_html__( 'Text', 'creavi-booking-service' ) . '</option>';
     351        echo '<option value="textarea"' . ($type === 'textarea' ? ' selected' : '') . '>' . esc_html__( 'Textarea', 'creavi-booking-service' ) . '</option>';
    346352        echo '</select>';
    347         echo '<label style="margin-left:10px;"><input type="checkbox" name="creavibc_custom_fields[required][' . esc_attr($i) . ']" value="1"' . ($required ? 'checked' : '') . '> Required</label>';
     353        echo '<label style="margin-left:10px;"><input type="checkbox" name="creavibc_custom_fields[required][' . esc_attr( $i ) . ']" value="1"' . ( $required ? ' checked' : '' ) . '> ' . esc_html__( 'Required', 'creavi-booking-service' ) . '</label>';
    348354        echo '<button type="button" class="button creavibc-remove-field">–</button>';
    349355        echo '</div>';
     
    351357
    352358
    353         echo '</div><button type="button" class="button" id="creavibc-add-field">+ Add Custom Field</button>';
     359        echo '</div><button type="button" class="button" id="creavibc-add-field">+ ' . esc_html__( 'Add Custom Field', 'creavi-booking-service' ) . '</button>';
    354360    }
    355361
     
    362368    $custom  = get_post_meta($post->ID, '_creavibc_booking_custom', true) ?: [];
    363369
    364     echo "<p><strong>Date:</strong> " . esc_html($date) . "</p>";
    365     echo "<p><strong>Time:</strong> " . esc_html($time) . "</p>";
    366     echo "<p><strong>Name:</strong> " . esc_html($name) . "</p>";
    367     echo "<p><strong>Email:</strong> " . esc_html($email) . "</p>";
    368     echo "<p><strong>Comment:</strong><br>" . nl2br(esc_html($comment)) . "</p>";
    369 
    370     if (!empty($custom)) {
    371         echo "<hr><p><strong>Custom Fields:</strong></p>";
     370    echo '<p><strong>' . esc_html__( 'Date:', 'creavi-booking-service' ) . '</strong> ' . esc_html( $date ) . '</p>';
     371    echo '<p><strong>' . esc_html__( 'Time:', 'creavi-booking-service' ) . '</strong> ' . esc_html( $time ) . '</p>';
     372    echo '<p><strong>' . esc_html__( 'Name:', 'creavi-booking-service' ) . '</strong> ' . esc_html( $name ) . '</p>';
     373    echo '<p><strong>' . esc_html__( 'Email:', 'creavi-booking-service' ) . '</strong> ' . esc_html( $email ) . '</p>';
     374    echo '<p><strong>' . esc_html__( 'Comment:', 'creavi-booking-service' ) . '</strong><br>' . nl2br( esc_html( $comment ) ) . '</p>';
     375
     376    if ( ! empty( $custom ) ) {
     377        echo '<hr><p><strong>' . esc_html__( 'Custom Fields:', 'creavi-booking-service' ) . '</strong></p>';
     378
    372379        foreach ($custom as $label => $value) {
    373380            echo "<p><strong>" . esc_html($label) . ":</strong> " . esc_html($value) . "</p>";
     
    380387    $admin_tz = get_post_meta($post->ID, '_creavibc_admin_timezone', true) ?: date_default_timezone_get();
    381388
    382     echo '<p><strong>Appointment timezone:</strong></p>';
    383    
    384     echo '<label><input type="radio" name="creavibc_timezone_mode" value="localized" ' . checked($mode, 'localized', false) . '> Localized</label> ';
    385     echo '<label><input type="radio" name="creavibc_timezone_mode" value="locked" ' . checked($mode, 'locked', false) . '> Locked</label>';
     389    echo '<p><strong>' . esc_html__( 'Appointment timezone:', 'creavi-booking-service' ) . '</strong></p>';
     390    echo '<label><input type="radio" name="creavibc_timezone_mode" value="localized" ' . checked( $mode, 'localized', false ) . '> ' . esc_html__( 'Localized', 'creavi-booking-service' ) . '</label> ';
     391    echo '<label><input type="radio" name="creavibc_timezone_mode" value="locked" ' . checked( $mode, 'locked', false ) . '> ' . esc_html__( 'Locked', 'creavi-booking-service' ) . '</label>';
    386392
    387393    echo '<p class="creavibc-timezone-description">';
    388     if ($mode === 'locked') {
    389         echo 'Your customers will see available appointment times in <strong>' . esc_html($admin_tz) . '</strong>. Recommended for offline meetingss.';
     394    if ( 'locked' === $mode ) {
     395        echo sprintf(
     396            /* translators: %s: timezone string (e.g. Europe/Paris) */
     397            esc_html__( 'Your customers will see available appointment times in %s. Recommended for offline meetings.', 'creavi-booking-service' ),
     398            '<strong>' . esc_html( $admin_tz ) . '</strong>'
     399        );
    390400    } else {
    391         echo 'Your customers will see available appointment times in their own timezone. Recommended for online meetings.';
     401        echo esc_html__( 'Your customers will see available appointment times in their own timezone. Recommended for online meetings.', 'creavi-booking-service' );
    392402    }
    393403    echo '</p>';
     404
    394405}
    395406
     
    402413
    403414    $weekdays = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday'];
     415
     416    $weekday_labels = [
     417        'monday'    => __( 'Monday', 'creavi-booking-service' ),
     418        'tuesday'   => __( 'Tuesday', 'creavi-booking-service' ),
     419        'wednesday' => __( 'Wednesday', 'creavi-booking-service' ),
     420        'thursday'  => __( 'Thursday', 'creavi-booking-service' ),
     421        'friday'    => __( 'Friday', 'creavi-booking-service' ),
     422        'saturday'  => __( 'Saturday', 'creavi-booking-service' ),
     423        'sunday'    => __( 'Sunday', 'creavi-booking-service' ),
     424        ];
     425
     426
     427
    404428    $times = [];
    405429    for ($h = 8; $h <= 16; $h++) {
     
    416440    ?>
    417441
    418     <p><strong>Admin Timezone:</strong></p>
     442    <?php echo '<p><strong>' . esc_html__( 'Admin Timezone:', 'creavi-booking-service' ) . '</strong></p>'; ?>
    419443
    420444    <div id="creavibc-timezone-wrapper">
    421445        <p>
    422             Detected: <span id="creavibc-admin-tz-label"><?php echo esc_html($tz_value ?: '...'); ?></span>
    423             <button type="button" id="creavibc-admin-tz-edit" class="button small">Change</button>
     446            <?php echo esc_html__( 'Detected:', 'creavi-booking-service' ); ?>
     447            <span id="creavibc-admin-tz-label"><?php echo esc_html( $tz_value ?: '...' ); ?></span>
     448            <button type="button" id="creavibc-admin-tz-edit" class="button small">
     449                <?php echo esc_html__( 'Change', 'creavi-booking-service' ); ?>
     450            </button>
    424451        </p>
    425 
    426         <!--
    427         <select id="creavibc-admin-tz-select" name="creavibc_admin_timezone" style="display:none; max-width: 300px;">
    428              Populated via JS
    429         </select> -->
     452       
    430453
    431454        <select id="creavibc-admin-tz-select" name="creavibc_admin_timezone" style="display:none; max-width: 300px;">
     
    442465    <?php creavibc_render_service_timezone_setting($post); ?>
    443466
    444 
    445 
    446467<?php
    447     echo '<p><strong>Slot Duration:</strong></p>';
     468    echo '<p><strong>' . esc_html__( 'Slot Duration:', 'creavi-booking-service' ) . '</strong></p>';
    448469    echo '<div id="creavibc-slot-duration-options">';
    449470    foreach (['20','30','60'] as $min) {
     
    462483        ' . esc_html__( 'The weekday columns follow your WordPress “Week Starts On” setting (Settings → General).', 'creavi-booking-service' ) . '
    463484    </div>';
    464 
    465 
    466     echo '<p><strong>Select appointment start times:</strong></p>';
     485   
     486    echo '<p><strong>' . esc_html__( 'Select appointment start times:', 'creavi-booking-service' ) . '</strong></p>';
     487
    467488    echo '<div id="creavibc-slot-wrapper" style="position:relative;">';
    468489    echo '<div id="creavibc-slot-grid-container">';
     
    471492    echo '<thead><tr><th></th>';
    472493    foreach ($weekdays as $day) {
    473         echo '<th>' . esc_html(ucfirst($day)) . '</th>';
     494        echo '<th>' . esc_html( $weekday_labels[ $day ] ?? ucfirst($day) ) . '</th>';
    474495    }
    475496    echo '</tr></thead><tbody>';
     
    504525   
    505526
    506     echo '<input type="hidden" name="creavibc_grid_slots" id="creavibc_grid_slots" value="' . esc_attr(implode(',', $stored_slots)) . '">';
    507     echo '<p class="description">Click cells to select/deselect time slots.</p>';
     527    echo '<input type="hidden" name="creavibc_grid_slots" id="creavibc_grid_slots" value="' . esc_attr(implode(',', $stored_slots)) . '">';   
     528    echo '<p class="description">' . esc_html__( 'Click cells to select/deselect time slots.', 'creavi-booking-service' ) . '</p>';
     529
    508530}
    509531
     
    531553    $hover_border_color = get_post_meta($post->ID, '_creavibc_hover_border_color', true) ?: $bg_color;
    532554
    533     $button_text = get_post_meta($post->ID, '_creavibc_button_text', true) ?: 'Book Now';
     555    $button_text = get_post_meta( $post->ID, '_creavibc_button_text', true );
     556    if ( empty( $button_text ) ) {
     557        $button_text = __( 'Book Now', 'creavi-booking-service' );
     558    }
    534559
    535560    $color = get_post_meta($post->ID, '_creavibc_primary_color', true) ?: '#569FF7';
    536     $thankyou = get_post_meta($post->ID, '_creavibc_thankyou_text', true) ?: 'Thank you for booking! See you soon!';
    537     $admin_email_tpl = get_post_meta($post->ID, '_creavibc_email_admin_template', true) ?: "New booking:\n\nName: {name}\nEmail: {email}\nDate: {date}\nTime: {time}\nService: {service}";
    538     $user_email_tpl = get_post_meta($post->ID, '_creavibc_email_user_template', true) ?: "Hi {name},\n\nThanks for booking {service} on {date} at {time}.";
     561   
     562    $thankyou = get_post_meta( $post->ID, '_creavibc_thankyou_text', true );
     563    if ( empty( $thankyou ) ) {
     564        $thankyou = __( 'Thank you for booking! See you soon!', 'creavi-booking-service' );
     565    }
     566
     567    $admin_email_tpl = get_post_meta( $post->ID, '_creavibc_email_admin_template', true );
     568    if ( empty( $admin_email_tpl ) ) {
     569        $admin_email_tpl = __( "New booking:\n\nName: {name}\nEmail: {email}\nDate: {date}\nTime: {time}\nService: {service}", 'creavi-booking-service' );
     570    }
     571
     572    $user_email_tpl = get_post_meta( $post->ID, '_creavibc_email_user_template', true );
     573    if ( empty( $user_email_tpl ) ) {
     574        $user_email_tpl = __( "Hi {name},\n\nThanks for booking {service} on {date} at {time}.", 'creavi-booking-service' );
     575    }   
    539576
    540577    wp_nonce_field('creavibc_save_service_options', 'creavibc_service_options_nonce');
    541 
    542     echo '<p><label for="creavibc_primary_color"><strong>Primary Brand Color:</strong></label><br>';
     578   
     579    echo '<p><label for="creavibc_primary_color"><strong>' . esc_html__( 'Primary Brand Color:', 'creavi-booking-service' ) . '</strong></label><br>';
     580
    543581    echo '<input type="color" id="creavibc_primary_color" name="creavibc_primary_color" value="' . esc_attr($color) . '" style="width: 100px;"></p>';
    544582
    545     echo '<p><label for="creavibc_button_text"><strong>Booking Button Text:</strong></label><br>';
     583    echo '<p><label for="creavibc_button_text"><strong>' . esc_html__( 'Booking Button Text:', 'creavi-booking-service' ) . '</strong></label><br>';
     584
    546585    echo '<input type="text" id="creavibc_button_text" name="creavibc_button_text" value="' . esc_attr($button_text) . '" style="width: 100%;"></p>';
    547586
    548     echo '<hr><h4 style="margin-top: 30px;">Booking Button Style</h4>';
    549     echo '<hr><h4 class="creavibc-subsection">Booking Button Style</h4>';
     587    echo '<hr><h4 style="margin-top: 30px;">' . esc_html__( 'Booking Button Style', 'creavi-booking-service' ) . '</h4>';
     588   
    550589
    551590    $allowed = [
     
    562601
    563602    echo '<div class="creavibc-style-grid">';
    564     echo wp_kses( creavibc_style_field('Text Color:', 'creavibc_button_text_color', $text_color, 'color'), $allowed );
    565     echo wp_kses( creavibc_style_field('Background:', 'creavibc_button_bg_color', $bg_color, 'color'), $allowed );
    566     echo wp_kses( creavibc_style_field('Border Color:', 'creavibc_button_border_color', $border_color, 'color'), $allowed );
     603        echo wp_kses( creavibc_style_field( __( 'Text Color:', 'creavi-booking-service' ), 'creavibc_button_text_color', $text_color, 'color' ), $allowed );
     604        echo wp_kses( creavibc_style_field( __( 'Background:', 'creavi-booking-service' ), 'creavibc_button_bg_color', $bg_color, 'color' ), $allowed );
     605        echo wp_kses( creavibc_style_field( __( 'Border Color:', 'creavi-booking-service' ), 'creavibc_button_border_color', $border_color, 'color' ), $allowed );   
    567606    echo '</div>';
    568607
    569608    echo '<div class="creavibc-style-grid">';
    570     echo wp_kses( creavibc_style_field('Border Radius (px):', 'creavibc_button_radius', $radius, 'number'), $allowed );
    571     echo wp_kses( creavibc_style_field('Font Size (px):', 'creavibc_button_font_size', $font_size, 'number'), $allowed );
     609        echo wp_kses( creavibc_style_field( __( 'Border Radius (px):', 'creavi-booking-service' ), 'creavibc_button_radius', $radius, 'number' ), $allowed );         
     610        echo wp_kses( creavibc_style_field( __( 'Font Size (px):', 'creavi-booking-service' ), 'creavibc_button_font_size', $font_size, 'number' ), $allowed );
    572611    echo '</div>';
    573612
    574613    echo '<div class="creavibc-style-grid">';
    575     echo wp_kses( creavibc_style_field('Padding Vertical (px):', 'creavibc_button_padding_vertical', $padding_vertical, 'number'), $allowed );
    576     echo wp_kses( creavibc_style_field('Padding Horizontal (px):', 'creavibc_button_padding_horizontal', $padding_horizontal, 'number'), $allowed );
    577     echo '</div>';
    578 
    579     echo '<h4 class="creavibc-subsection">Hover Styles</h4>';
     614        echo wp_kses( creavibc_style_field( __( 'Padding Vertical (px):', 'creavi-booking-service' ), 'creavibc_button_padding_vertical', $padding_vertical, 'number' ), $allowed );
     615        echo wp_kses( creavibc_style_field( __( 'Padding Horizontal (px):', 'creavi-booking-service' ), 'creavibc_button_padding_horizontal', $padding_horizontal, 'number' ), $allowed );       
     616    echo '</div>';
     617
     618    echo '<h4 class="creavibc-subsection">' . esc_html__( 'Hover Styles', 'creavi-booking-service' ) . '</h4>';
    580619    echo '<div class="creavibc-style-grid">';
    581     echo wp_kses( creavibc_style_field('Text Color:', 'creavibc_hover_text_color', $hover_text_color, 'color'), $allowed );
    582     echo wp_kses( creavibc_style_field('Background:', 'creavibc_hover_bg_color', $hover_bg_color, 'color'), $allowed );
    583     echo wp_kses( creavibc_style_field('Border Color:', 'creavibc_hover_border_color', $hover_border_color, 'color'), $allowed );
    584     echo '</div>';
    585 
    586     echo '<hr><h4 class="creavibc-subsection">Notifications</h4>';
    587 
    588     echo '<p><label for="creavibc_thankyou_text"><strong>Thank You Text:</strong></label><br>';
     620        echo wp_kses( creavibc_style_field( __( 'Text Color:', 'creavi-booking-service' ), 'creavibc_hover_text_color', $hover_text_color, 'color' ), $allowed );
     621        echo wp_kses( creavibc_style_field( __( 'Background:', 'creavi-booking-service' ), 'creavibc_hover_bg_color', $hover_bg_color, 'color' ), $allowed );
     622        echo wp_kses( creavibc_style_field( __( 'Border Color:', 'creavi-booking-service' ), 'creavibc_hover_border_color', $hover_border_color, 'color' ), $allowed );
     623    echo '</div>';
     624
     625    echo '<hr><h4 class="creavibc-subsection">' . esc_html__( 'Notifications', 'creavi-booking-service' ) . '</h4>';
     626
     627    echo '<p><label for="creavibc_thankyou_text"><strong>' . esc_html__( 'Thank You Text:', 'creavi-booking-service' ) . '</strong></label><br>';
    589628    echo '<input type="text" id="creavibc_thankyou_text" name="creavibc_thankyou_text" value="' . esc_attr($thankyou) . '" style="width: 100%;"></p>';
    590629
    591     echo '<p><label for="creavibc_email_admin_template"><strong>Admin Email Template:</strong></label><br>';   
     630    echo '<p><label for="creavibc_email_admin_template"><strong>' . esc_html__( 'Admin Email Template:', 'creavi-booking-service' ) . '</strong></label><br>';
    592631    echo '<textarea name="creavibc_email_admin_template" id="creavibc_email_admin_template" rows="4" style="width: 100%;">' . esc_textarea($admin_email_tpl) . '</textarea></p>';
    593632
     
    598637    }
    599638
    600     echo '<p><label for="creavibc_gcal_admin_email"><strong>Admin Notification Email:</strong></label><br>';
     639    echo '<p><label for="creavibc_gcal_admin_email"><strong>' . esc_html__( 'Admin Notification Email:', 'creavi-booking-service' ) . '</strong></label><br>';
    601640    echo '<input type="email" id="creavibc_gcal_admin_email" name="creavibc_gcal_admin_email" value="' . esc_attr($gcal_admin_email) . '" class="regular-text">';
    602     echo '<br><span class="description">Defaults to the site admin email (' . esc_html(get_option('admin_email')) . ') if not set. Used for notifications and calendar invites.</span></p>';
    603 
    604 
    605     echo '<p><label for="creavibc_email_user_template"><strong>User Email Template:</strong></label><br>';
     641       
     642    echo '<br><span class="description">';
     643    echo sprintf(
     644        /* translators: %s: admin email */
     645        esc_html__( 'Defaults to the site admin email (%s) if not set. Used for notifications and calendar invites.', 'creavi-booking-service' ),
     646        esc_html( get_option( 'admin_email' ) )
     647    );
     648    echo '</span></p>';
     649   
     650    echo '<p><label for="creavibc_email_user_template"><strong>' . esc_html__( 'User Email Template:', 'creavi-booking-service' ) . '</strong></label><br>';
    606651    echo '<textarea name="creavibc_email_user_template" id="creavibc_email_user_template" rows="4" style="width: 100%;">' . esc_textarea($user_email_tpl) . '</textarea></p>';
    607 
    608     echo '<p class="description">Available tags: {name}, {email}, {date}, {time}, {service}</p>';   
     652   
     653    echo '<p class="description">' . esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' {name}, {email}, {date}, {time}, {service}</p>';
    609654
    610655    // ---------------------------
     
    619664    }
    620665
    621     $reminder_subject = get_post_meta( $post->ID, '_creavibc_email_reminder_subject', true );
     666    $reminder_subject = get_post_meta( $post->ID, '_creavibc_email_reminder_subject', true );
     667
     668
    622669    if ( empty( $reminder_subject ) ) {
    623         $reminder_subject = 'Reminder: {service} on {date} at {time}';
    624     }
    625 
     670        $reminder_subject = __( 'Reminder: {service} on {date} at {time}', 'creavi-booking-service' );
     671    }
    626672    $reminder_tpl = get_post_meta( $post->ID, '_creavibc_email_reminder_template', true );
    627673    if ( empty( $reminder_tpl ) ) {
    628         $reminder_tpl = "Hi {name},\n\nJust a friendly reminder about your upcoming appointment:\n\nService: {service}\nDate: {date}\nTime: {time}\n\nSee you soon!";
    629     }
     674        $reminder_tpl = __( "Hi {name},\n\nJust a friendly reminder about your upcoming appointment:\n\nService: {service}\nDate: {date}\nTime: {time}\n\nSee you soon!", 'creavi-booking-service' );
     675    }   
     676   
    630677
    631678    $reminder_options = array(
     
    688735}
    689736
    690 add_filter('manage_creavibc_service_posts_columns', function($columns) {
    691     $columns['creavibc_shortcode'] = 'Shortcode';
     737add_filter('manage_creavibc_service_posts_columns', function($columns) {   
     738    $columns['creavibc_shortcode'] = __( 'Shortcode', 'creavi-booking-service' );
     739
    692740    return $columns;
    693741});
  • creavi-booking-service/trunk/readme.txt

    r3448790 r3454590  
    55Tested up to: 6.7
    66Requires PHP: 7.4 
    7 Stable tag: 1.1.6
     7Stable tag: 1.1.7
    88License: GPLv2 or later 
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    4949* Bookings stored as custom post types for easy management
    5050* Custom taxonomy to categorize and filter services
     51* Multilingual & Translation Ready
    5152
    5253== Installation ==
     
    8586
    8687== Changelog ==
     88
     89= 1.1.7 =
     90* Added multilingual support for frontend and admin.
     91* Included French (fr_FR) and Danish (da_DK) translations.
    8792
    8893= 1.1.6 =
Note: See TracChangeset for help on using the changeset viewer.