Plugin Directory

Changeset 3453094


Ignore:
Timestamp:
02/03/2026 05:12:45 PM (3 weeks ago)
Author:
gkanters
Message:

Logging added to identify issue with translations not being performed

Location:
ai-translate/trunk
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • ai-translate/trunk/README.md

    r3451583 r3453094  
    3232- **🌍 35+ Languages** - Support for all major world languages and much more.
    3333- **⚡ Fast Caching** - Intelligent cache for better performance and lower costs.
    34 - **🔄 Automatic Updates** - Translations are automatically updated when content changes.
     34- **🔄 Automatic Updates** - Cache expires immediately of content when the original page changes .
    3535- **🍪 Remembers Preferences** - Saves each visitor's language preference (via cookies).
    3636- **🎨 Easy to Use** - Simple language switcher in the left corner of your website.
    3737- **🔧 Flexible** - Choose your own AI model (OpenAI, Deepseek, or other APIs).
    3838- **🔗 SEO-Friendly** - Also translates URLs for better search engine optimization.
     39- **🔥 Cache-Warming** - Have all pages pre-translated so they are immediately available to visitors.
    3940
    4041## Installation
  • ai-translate/trunk/includes/admin-page.php

    r3452204 r3453094  
    308308
    309309/**
     310 * Log warm cache debugging information to a dedicated log file.
     311 *
     312 * @param string $message Log message
     313 * @param array $context Additional context data
     314 */
     315function warm_cache_log($message, $context = [])
     316{
     317    $uploads = wp_upload_dir();
     318    $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     319    if (!is_dir($log_dir)) {
     320        wp_mkdir_p($log_dir);
     321    }
     322    $log_file = $log_dir . 'warm-cache-debug.log';
     323    $timestamp = date('Y-m-d H:i:s');
     324    $context_str = !empty($context) ? ' | Context: ' . json_encode($context, JSON_UNESCAPED_SLASHES) : '';
     325    $log_entry = "[{$timestamp}] {$message}{$context_str}\n";
     326    @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     327}
     328
     329/**
    310330 * Return route_id used for cache key when warming cache. Must match class-ai-ob current_route_id() for the same URL.
    311331 *
     
    362382    foreach ($lang_codes as $lang_code) {
    363383        try {
     384            warm_cache_log("WARM_CACHE_BATCH: Generating URL", ['post_id' => $post_id, 'lang_code' => $lang_code]);
    364385            $translated_url = \AITranslate\AI_SEO::get_translated_url($post_id, $lang_code);
     386            warm_cache_log("WARM_CACHE_BATCH: Generated URL", ['post_id' => $post_id, 'lang_code' => $lang_code, 'url' => $translated_url]);
     387           
    365388            if ($translated_url === '') {
    366389                $results[$lang_code] = array('success' => false, 'error' => __('Could not generate post URL.', 'ai-translate'));
     390                warm_cache_log("WARM_CACHE_BATCH: Could not generate URL", ['post_id' => $post_id, 'lang_code' => $lang_code]);
    367391                continue;
    368392            }
    369393
     394            warm_cache_log("WARM_CACHE_BATCH: Starting curl request", ['post_id' => $post_id, 'lang_code' => $lang_code, 'url' => $translated_url]);
    370395            $ch = curl_init($translated_url);
    371396            curl_setopt_array($ch, array(
     
    429454        // Accept 200 as success (unless it's an error page)
    430455        if ($http_code === 200 && !$is_error_page) {
     456            $effective_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // Get actual URL after redirects
     457            warm_cache_log("WARM_CACHE_BATCH: HTTP 200 received", ['post_id' => $post_id, 'lang_code' => $lang_code, 'requested_url' => $translated_url, 'effective_url' => $effective_url, 'response_size' => strlen($response_body)]);
     458           
    431459            // Wait a moment for async cache writes to complete
    432460            usleep(500000); // 0.5 second
     
    436464            $cache_file = \AITranslate\AI_Cache::get_file_path($cache_key);
    437465           
     466            warm_cache_log("WARM_CACHE_BATCH: Checking cache file", ['post_id' => $post_id, 'lang_code' => $lang_code, 'route_id' => $route_id, 'cache_key' => $cache_key, 'cache_file' => $cache_file]);
     467           
    438468            if ($cache_file && file_exists($cache_file)) {
    439469                // Ensure metadata is inserted/updated in database
     
    441471                AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash);
    442472               
     473                warm_cache_log("WARM_CACHE_BATCH: Cache file found immediately", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]);
    443474                $results[$lang_code] = array('success' => true, 'error' => '');
    444475            } else {
     
    451482                        $cache_hash = md5($cache_key);
    452483                        AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash);
     484                        warm_cache_log("WARM_CACHE_BATCH: Cache file found after delay", ['post_id' => $post_id, 'lang_code' => $lang_code, 'attempt' => $attempt, 'cache_file' => $cache_file]);
    453485                        $results[$lang_code] = array('success' => true, 'error' => '');
    454486                        $found = true;
     
    460492                    // Provide more detailed error message
    461493                    $error_detail = __('Cache file not generated', 'ai-translate');
     494                    $debug_info = ['post_id' => $post_id, 'lang_code' => $lang_code, 'route_id' => $route_id, 'cache_key' => $cache_key, 'cache_file' => $cache_file];
     495                   
    462496                    if ($cache_file) {
    463497                        // Check parent directories existence
     
    467501                        if (!is_dir($parent_dir)) {
    468502                            $error_detail .= ' (' . __('lang directory missing', 'ai-translate') . ')';
     503                            $debug_info['parent_dir_exists'] = false;
    469504                        } elseif (!is_dir($cache_dir)) {
    470505                            // Hash subdirectory missing is normal - it gets created during write
    471506                            // This means the write never happened
    472507                            $error_detail .= ' (' . __('no write occurred', 'ai-translate') . ')';
     508                            $debug_info['cache_dir_exists'] = false;
    473509                        } elseif (!is_writable($cache_dir)) {
    474510                            $error_detail .= ' (' . __('not writable', 'ai-translate') . ')';
     511                            $debug_info['cache_dir_writable'] = false;
    475512                        } else {
    476513                            $error_detail .= ' (' . __('check logs', 'ai-translate') . ')';
     514                            $debug_info['cache_dir_exists'] = true;
     515                            $debug_info['cache_dir_writable'] = is_writable($cache_dir);
    477516                        }
    478517                    }
     518
     519                    // Fallback: take the HTML response we just fetched and write it to cache directly
     520                    if (!empty($response_body)) {
     521                        \AITranslate\AI_Cache::set($cache_key, $response_body);
     522                        if ($cache_file && file_exists($cache_file)) {
     523                            $cache_hash = md5($cache_key);
     524                            AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash);
     525                            warm_cache_log("WARM_CACHE_BATCH: Cache file written from response", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]);
     526                            $results[$lang_code] = array('success' => true, 'error' => '');
     527                            continue;
     528                        }
     529                    }
     530
     531                    warm_cache_log("WARM_CACHE_BATCH: Cache file NOT found after all attempts", $debug_info);
    479532                    $results[$lang_code] = array('success' => false, 'error' => $error_detail);
    480533                }
     
    522575    $translated_url = \AITranslate\AI_SEO::get_translated_url($post_id, $lang_code);
    523576    if ($translated_url === '') {
     577        warm_cache_log("WARM_CACHE_INTERNAL: Could not generate URL", ['post_id' => $post_id, 'lang_code' => $lang_code, 'request_path' => $request_path]);
    524578        return array('success' => false, 'error' => __('Could not generate post URL.', 'ai-translate'));
    525579    }
     580   
     581    warm_cache_log("WARM_CACHE_INTERNAL: Starting request", ['post_id' => $post_id, 'lang_code' => $lang_code, 'request_path' => $request_path, 'url' => $translated_url]);
    526582
    527583    // Parse URL to get host and path
     
    568624    // Accept 200 as success (redirects might indicate issues, but we'll check cache anyway)
    569625    if ($response_code === 200) {
     626        warm_cache_log("WARM_CACHE_INTERNAL: HTTP 200 received", ['post_id' => $post_id, 'lang_code' => $lang_code, 'url' => $translated_url]);
     627       
    570628        // Verify cache was generated by checking if cache file exists
    571629        // Wait a moment for async cache writes to complete
     
    576634        $cache_file = \AITranslate\AI_Cache::get_file_path($cache_key);
    577635       
     636        warm_cache_log("WARM_CACHE_INTERNAL: Checking cache file", ['post_id' => $post_id, 'lang_code' => $lang_code, 'route_id' => $route_id, 'cache_key' => $cache_key, 'cache_file' => $cache_file]);
     637       
    578638        if ($cache_file && file_exists($cache_file)) {
    579639            // Ensure metadata is inserted/updated in database
     
    582642            AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash);
    583643           
     644            warm_cache_log("WARM_CACHE_INTERNAL: Cache file found immediately", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]);
    584645            return array('success' => true, 'error' => '');
    585646        } else {
     
    591652                AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash);
    592653               
     654                warm_cache_log("WARM_CACHE_INTERNAL: Cache file found after delay", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]);
    593655                return array('success' => true, 'error' => '');
    594656            }
    595657            // Request was successful but cache not found - might be bypassed or error in generation
     658            warm_cache_log("WARM_CACHE_INTERNAL: Cache file NOT found", ['post_id' => $post_id, 'lang_code' => $lang_code, 'route_id' => $route_id, 'cache_key' => $cache_key, 'cache_file' => $cache_file, 'cache_dir_exists' => ($cache_file ? is_dir(dirname($cache_file)) : false), 'cache_dir_writable' => ($cache_file ? is_writable(dirname($cache_file)) : false)]);
    596659            return array('success' => false, 'error' => __('Cache file not generated after successful request', 'ai-translate'));
    597660        }
     
    11351198                }
    11361199            }
    1137            
    1138             // Emergency fix: if value is absurdly high due to previous bug, reset it
    1139             // 50000 hours is approx 2000 days or 5.7 years, which is way beyond reasonable
     1200                       
    11401201            if (isset($sanitized['cache_expiration']) && $sanitized['cache_expiration'] > 50000) {
    11411202                 $sanitized['cache_expiration'] = 14 * 24;
     
    11641225                // Initialiseer als nog niet gezet
    11651226                $sanitized['stop_translations_except_cache_invalidation'] = false;
     1227            }
     1228
     1229            // Multi-domain caching (checkbox)
     1230            // Bij formulier-submit: checkbox is aangevinkt als key bestaat, anders uitgevinkt
     1231            // Bij AJAX/partial update: alleen updaten als expliciet in input
     1232            if ($is_form_submit) {
     1233                $sanitized['multi_domain_caching'] = isset($input['multi_domain_caching']);
     1234            } elseif (array_key_exists('multi_domain_caching', $input)) {
     1235                $sanitized['multi_domain_caching'] = (bool) $input['multi_domain_caching'];
     1236            } elseif (!isset($sanitized['multi_domain_caching'])) {
     1237                $sanitized['multi_domain_caching'] = false;
    11661238            }
    11671239
     
    21792251                        echo '</p></div>';
    21802252                    } else {
    2181                         echo '<div class="notice notice-warning is-dismissible"><p>';
    2182                         echo __('No cache records added. Possible causes:', 'ai-translate');
    2183                         echo '<ul style="margin-left: 20px; margin-top: 10px;">';
    2184                         echo '<li>' . __('Cache files do not exist at the expected location', 'ai-translate') . '</li>';
    2185                         echo '<li>' . __('Cache files have a different format than expected', 'ai-translate') . '</li>';
    2186                         echo '<li>' . __('Multi-domain caching configuration does not match', 'ai-translate') . '</li>';
    2187                         echo '</ul>';
    2188                         echo '</p></div>';
     2253                    echo '<div class="notice notice-warning is-dismissible"><p>';
     2254                    echo __('No cache records added. There are currently no cache files available.', 'ai-translate');
     2255                    echo '</p></div>';
    21892256                    }
    21902257                }
  • ai-translate/trunk/includes/class-ai-cache.php

    r3433090 r3453094  
    114114            wp_mkdir_p($dir);
    115115        }
    116         @file_put_contents($file, $html);
     116       
     117        // Log cache write for warm cache debugging
     118        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     119        $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     120       
     121        if ($is_warm_cache_request) {
     122            $uploads = wp_upload_dir();
     123            $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     124            if (!is_dir($log_dir)) {
     125                wp_mkdir_p($log_dir);
     126            }
     127            $log_file = $log_dir . 'warm-cache-debug.log';
     128            $timestamp = date('Y-m-d H:i:s');
     129            $log_entry = "[{$timestamp}] CACHE_SET: Writing cache file | key: {$key} | file: {$file} | dir_exists: " . (is_dir($dir) ? 'yes' : 'no') . " | dir_writable: " . (is_writable($dir) ? 'yes' : 'no') . " | html_size: " . strlen($html) . "\n";
     130            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     131        }
     132       
     133        $result = @file_put_contents($file, $html);
     134       
     135        if ($is_warm_cache_request) {
     136            $timestamp = date('Y-m-d H:i:s');
     137            $file_exists_after = file_exists($file);
     138            $log_entry = "[{$timestamp}] CACHE_SET: Write result | file: {$file} | write_result: " . ($result !== false ? 'success (' . $result . ' bytes)' : 'failed') . " | file_exists_after: " . ($file_exists_after ? 'yes' : 'no') . "\n";
     139            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     140        }
    117141       
    118142        // Track cache metadata for admin table
  • ai-translate/trunk/includes/class-ai-ob.php

    r3451123 r3453094  
    132132    public function callback($html)
    133133    {
     134        // Log callback trigger for warm cache debugging (before static check)
     135        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     136        $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     137        $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
     138       
     139        if ($is_warm_cache_request) {
     140            $uploads = wp_upload_dir();
     141            $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     142            if (!is_dir($log_dir)) {
     143                wp_mkdir_p($log_dir);
     144            }
     145            $log_file = $log_dir . 'warm-cache-debug.log';
     146            $timestamp = date('Y-m-d H:i:s');
     147            $lang = AI_Lang::current();
     148            $log_entry = "[{$timestamp}] OB_CALLBACK: Triggered | request_uri: {$request_uri} | lang: " . ($lang ?? 'null') . " | html_size: " . strlen($html) . "\n";
     149            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     150        }
     151       
    134152        static $processing = false;
    135         if ($processing) {
     153       
     154        if ($is_warm_cache_request && $log_file) {
     155            $timestamp = date('Y-m-d H:i:s');
     156            $log_entry = "[{$timestamp}] OB_CALLBACK: Static check | processing: " . ($processing ? 'true' : 'false') . " | is_warm_cache: " . ($is_warm_cache_request ? 'true' : 'false') . "\n";
     157            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     158        }
     159       
     160        // Allow warm cache requests to bypass static processing check (they need to generate cache)
     161        if ($processing && !$is_warm_cache_request) {
     162            if ($is_warm_cache_request && $log_file) {
     163                $timestamp = date('Y-m-d H:i:s');
     164                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (static processing check)\n";
     165                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     166            }
    136167            return $html;
    137168        }
    138169        $processing = true;
     170
     171        if ($is_warm_cache_request && $log_file) {
     172            $timestamp = date('Y-m-d H:i:s');
     173            $log_entry = "[{$timestamp}] OB_CALLBACK: Past static check, starting PHASE checks\n";
     174            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     175        }
    139176
    140177        // PHASE 1: Basic environment checks
    141178        if ($this->should_skip_basic_checks()) {
     179            if ($is_warm_cache_request) {
     180                $timestamp = date('Y-m-d H:i:s');
     181                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (basic checks)\n";
     182                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     183            }
    142184            $processing = false;
    143185            return $html;
     
    146188        // PHASE 2: Content type validation
    147189        if ($this->should_skip_content_type($html)) {
     190            if ($is_warm_cache_request && $log_file) {
     191                $timestamp = date('Y-m-d H:i:s');
     192                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (PHASE 2: content type)\n";
     193                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     194            }
    148195            $processing = false;
    149196            return $html;
     
    152199        // PHASE 3: Page structure validation
    153200        if ($this->should_skip_page_structure()) {
     201            if ($is_warm_cache_request && $log_file) {
     202                $timestamp = date('Y-m-d H:i:s');
     203                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (PHASE 3: page structure)\n";
     204                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     205            }
    154206            $processing = false;
    155207            return $html;
     
    158210        // PHASE 4: File type checks
    159211        if ($this->should_skip_file_types($html)) {
     212            if ($is_warm_cache_request && $log_file) {
     213                $timestamp = date('Y-m-d H:i:s');
     214                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (PHASE 4: file type)\n";
     215                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     216            }
    160217            $processing = false;
    161218            return $html;
     
    164221        // PHASE 5: Language and user validation
    165222        if ($this->should_skip_language_or_user()) {
     223            if ($is_warm_cache_request && $log_file) {
     224                $timestamp = date('Y-m-d H:i:s');
     225                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (PHASE 5: language/user)\n";
     226                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     227            }
    166228            $processing = false;
    167229            return $html;
     230        }
     231       
     232        if ($is_warm_cache_request && $log_file) {
     233            $timestamp = date('Y-m-d H:i:s');
     234            $log_entry = "[{$timestamp}] OB_CALLBACK: All PHASE checks passed, continuing\n";
     235            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
    168236        }
    169237
     
    210278        $shouldTranslate = $this->route_should_be_translated($route);
    211279        if (!$shouldTranslate) {
     280            if ($is_warm_cache_request) {
     281                $timestamp = date('Y-m-d H:i:s');
     282                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (route should not be translated) | route: {$route}\n";
     283                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     284            }
    212285            $processing = false;
    213286            return $html; // Return untranslated HTML without processing
     
    290363                    // Another request is still generating this page; avoid duplicate API calls
    291364                    // Serve the current HTML without starting a second translation pass
     365                    if ($is_warm_cache_request) {
     366                        $timestamp = date('Y-m-d H:i:s');
     367                        $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (lock timeout) | lockKey: {$lockKey}\n";
     368                        @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     369                    }
    292370                    $processing = false;
    293371                    return $html;
     
    298376                $cached = AI_Cache::get($key);
    299377                if ($cached !== false) {
     378                    if ($is_warm_cache_request) {
     379                        $timestamp = date('Y-m-d H:i:s');
     380                        $log_entry = "[{$timestamp}] OB_CALLBACK: Cache found while waiting for lock | key: {$key}\n";
     381                        @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     382                    }
    300383                    $processing = false;
    301384                    return $cached;
     
    306389            set_transient($lockKey, time(), 120); // Lock expires after 2 minutes as failsafe
    307390            $lockAcquired = true;
     391           
     392            if ($is_warm_cache_request) {
     393                $timestamp = date('Y-m-d H:i:s');
     394                $log_entry = "[{$timestamp}] OB_CALLBACK: Lock acquired | lockKey: {$lockKey}\n";
     395                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     396            }
    308397        }
    309398       
     
    312401        $remaining = $timeLimit > 0 ? ($timeLimit - $elapsed) : 120;
    313402        if ($remaining < 20) {
     403            if ($is_warm_cache_request) {
     404                $timestamp = date('Y-m-d H:i:s');
     405                $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (insufficient time remaining) | remaining: {$remaining}\n";
     406                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     407            }
    314408            if ($lockAcquired) {
    315409                delete_transient($lockKey);
     
    392486            if (!$cache_exists || !$cache_is_expired) {
    393487                // Cache doesn't exist or is not expired, block translation
     488                if ($is_warm_cache_request) {
     489                    $timestamp = date('Y-m-d H:i:s');
     490                    $reason = $cache_exists ? 'cache_not_expired' : 'cache_not_exists';
     491                    $log_entry = "[{$timestamp}] OB_CALLBACK: Skipped (stop_translations enabled) | reason: {$reason} | cache_exists: " . ($cache_exists ? 'yes' : 'no') . " | cache_is_expired: " . ($cache_is_expired ? 'yes' : 'no') . "\n";
     492                    @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     493                }
    394494                if ($lockAcquired) {
    395495                    delete_transient($lockKey);
     
    456556        $html3HasBody = (stripos($html3, '<body') !== false);
    457557       
     558        // Log validation for warm cache debugging
     559        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     560        $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     561       
     562        if ($is_warm_cache_request) {
     563            $uploads = wp_upload_dir();
     564            $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     565            if (!is_dir($log_dir)) {
     566                wp_mkdir_p($log_dir);
     567            }
     568            $log_file = $log_dir . 'warm-cache-debug.log';
     569            $timestamp = date('Y-m-d H:i:s');
     570            $log_entry = "[{$timestamp}] OB_CALLBACK: HTML validation | lang: {$lang} | route: {$route} | html3Len: {$html3Len} | hasHtml: " . ($html3HasHtml ? 'yes' : 'no') . " | hasBody: " . ($html3HasBody ? 'yes' : 'no') . "\n";
     571            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     572        }
     573       
    458574        if ($html3Len < 500 || !$html3HasHtml || !$html3HasBody) {
     575            if ($is_warm_cache_request) {
     576                $timestamp = date('Y-m-d H:i:s');
     577                $log_entry = "[{$timestamp}] OB_CALLBACK: HTML validation FAILED - skipping cache\n";
     578                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     579            }
    459580            if ($lockAcquired) {
    460581                delete_transient($lockKey);
     
    469590        // Additional check: only cache if route corresponds to cacheable content (not search pages, etc.)
    470591        $isCacheable = $this->route_has_valid_content($route);
     592       
     593        if ($is_warm_cache_request) {
     594            $timestamp = date('Y-m-d H:i:s');
     595            $log_entry = "[{$timestamp}] OB_CALLBACK: Cache decision | bypassUserCache: " . ($bypassUserCache ? 'yes' : 'no') . " | hasDynamicQueryParams: " . ($hasDynamicQueryParams ? 'yes' : 'no') . " | isCacheable: " . ($isCacheable ? 'yes' : 'no') . " | route: {$route}\n";
     596            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     597        }
     598       
    471599        if (!$bypassUserCache && !$hasDynamicQueryParams && $isCacheable) {
     600            // Log cache write attempt for warm cache debugging
     601            $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
     602            $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     603            $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     604           
     605            if ($is_warm_cache_request) {
     606                $uploads = wp_upload_dir();
     607                $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     608                if (!is_dir($log_dir)) {
     609                    wp_mkdir_p($log_dir);
     610                }
     611                $log_file = $log_dir . 'warm-cache-debug.log';
     612                $cache_file = AI_Cache::get_file_path($key);
     613                $timestamp = date('Y-m-d H:i:s');
     614                $log_entry = "[{$timestamp}] OB_CALLBACK: Writing cache | lang: {$lang} | route: {$route} | key: {$key} | cache_file: {$cache_file} | request_uri: {$request_uri}\n";
     615                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     616            }
     617           
    472618            AI_Cache::set($key, $html3);
     619           
     620            if ($is_warm_cache_request) {
     621                $cache_file_after = AI_Cache::get_file_path($key);
     622                $file_exists = file_exists($cache_file_after);
     623                $timestamp = date('Y-m-d H:i:s');
     624                $log_entry = "[{$timestamp}] OB_CALLBACK: Cache write completed | cache_file: {$cache_file_after} | exists: " . ($file_exists ? 'yes' : 'no') . "\n";
     625                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     626            }
     627        } else {
     628            // Log why cache was skipped
     629            $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
     630            $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     631            $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     632           
     633            if ($is_warm_cache_request) {
     634                $uploads = wp_upload_dir();
     635                $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     636                if (!is_dir($log_dir)) {
     637                    wp_mkdir_p($log_dir);
     638                }
     639                $log_file = $log_dir . 'warm-cache-debug.log';
     640                $timestamp = date('Y-m-d H:i:s');
     641                $skip_reasons = [];
     642                if ($bypassUserCache) $skip_reasons[] = 'bypassUserCache';
     643                if ($hasDynamicQueryParams) $skip_reasons[] = 'hasDynamicQueryParams';
     644                if (!$isCacheable) $skip_reasons[] = '!isCacheable';
     645                $log_entry = "[{$timestamp}] OB_CALLBACK: Cache SKIPPED | lang: {$lang} | route: {$route} | reasons: " . implode(', ', $skip_reasons) . " | request_uri: {$request_uri}\n";
     646                @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     647            }
    473648        }
    474649       
     
    599774        }
    600775       
     776        // CRITICAL: For warm cache requests and translated URLs, resolve the post ID from the URL FIRST
     777        // This is needed because WordPress query functions (is_singular, get_queried_object_id)
     778        // may not work correctly during warm cache internal requests
     779        $req_uri = isset($_SERVER['REQUEST_URI']) ? (string) $_SERVER['REQUEST_URI'] : '';
     780        if ($req_uri !== '' && preg_match('#^/([a-z]{2})/([^/?]+)/?#i', $req_uri, $url_match)) {
     781            $url_lang = strtolower($url_match[1]);
     782            $url_slug = $url_match[2];
     783            // Try to resolve the translated slug to a post ID
     784            $resolved_id = \AITranslate\AI_Slugs::resolve_path_to_post($url_lang, $url_slug);
     785            if ($resolved_id !== null && $resolved_id > 0) {
     786                return 'post:' . $resolved_id;
     787            }
     788        }
     789       
    601790        // For singular posts/pages: use post ID (consistent, prevents duplicates)
    602791        // Only use post ID if it's actually a singular post/page (not archive/search/attachment)
     
    667856            $path = preg_replace('#/+#', '/', $path);
    668857           
     858            // Extract language code from path
     859            $lang_from_path = null;
     860            if (preg_match('#^/([a-z]{2})(?:/|$)#i', $path, $lang_match)) {
     861                $lang_from_path = strtolower($lang_match[1]);
     862            }
     863           
    669864            // Remove leading language code to get clean path
    670865            $clean_path = preg_replace('#^/([a-z]{2})(?:/|$)#i', '/', $path);
     
    679874            if (!empty($path_parts) && !in_array($clean_path, array('/category/', '/tag/', '/author/', '/date/'))) {
    680875                $slug = end($path_parts);
    681             // Try to find post/page by slug - include all public post types (exclude attachments)
    682             $public_post_types = get_post_types(array('public' => true), 'names');
    683             $public_post_types = array_diff($public_post_types, array('attachment'));
    684             if (empty($public_post_types)) {
    685                 $public_post_types = array('post', 'page');
    686             }
    687             $found_post = get_page_by_path($slug, OBJECT, array_values($public_post_types));
    688             if ($found_post && isset($found_post->ID)) {
    689                 // Skip attachments - they should not be cached
    690                 if (isset($found_post->post_type) && $found_post->post_type !== 'attachment') {
    691                     return 'post:' . $found_post->ID;
    692                 }
    693             }
     876               
     877                // IMPORTANT: First try to resolve translated slug to post ID using AI_Slugs
     878                // This is needed for warm cache requests where the URL uses translated slugs
     879                if ($lang_from_path !== null) {
     880                    $resolved_post_id = \AITranslate\AI_Slugs::resolve_path_to_post($lang_from_path, $slug);
     881                    if ($resolved_post_id !== null && $resolved_post_id > 0) {
     882                        return 'post:' . $resolved_post_id;
     883                    }
     884                }
     885               
     886                // Fallback: Try to find post/page by original slug
     887                $public_post_types = get_post_types(array('public' => true), 'names');
     888                $public_post_types = array_diff($public_post_types, array('attachment'));
     889                if (empty($public_post_types)) {
     890                    $public_post_types = array('post', 'page');
     891                }
     892                $found_post = get_page_by_path($slug, OBJECT, array_values($public_post_types));
     893                if ($found_post && isset($found_post->ID)) {
     894                    // Skip attachments - they should not be cached
     895                    if (isset($found_post->post_type) && $found_post->post_type !== 'attachment') {
     896                        return 'post:' . $found_post->ID;
     897                    }
     898                }
    694899            }
    695900        }
  • ai-translate/trunk/includes/class-ai-slugs.php

    r3451123 r3453094  
    498498
    499499        self::upsert_row($post_id, $lang, $source_slug, $translated_slug, $version);
     500       
     501        // Log for warm cache debugging
     502        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
     503        $is_warm_cache_request = (strpos($user_agent, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') !== false);
     504        if ($is_warm_cache_request) {
     505            $uploads = wp_upload_dir();
     506            $log_dir = trailingslashit($uploads['basedir']) . 'ai-translate/logs/';
     507            if (!is_dir($log_dir)) {
     508                wp_mkdir_p($log_dir);
     509            }
     510            $log_file = $log_dir . 'warm-cache-debug.log';
     511            $timestamp = date('Y-m-d H:i:s');
     512            $log_entry = "[{$timestamp}] SLUGS_GET_OR_GENERATE: Generated new slug | post_id: {$post_id} | lang: {$lang} | translated_slug: {$translated_slug}\n";
     513            @file_put_contents($log_file, $log_entry, FILE_APPEND | LOCK_EX);
     514        }
     515       
    500516        return $translated_slug;
    501517    }
  • ai-translate/trunk/languages/ai-translate-ar.po

    r3451123 r3453094  
    10701070#: includes/admin-page.php:1977
    10711071
    1072 msgid "No cache records added. Possible causes:"
    1073 msgstr "لم يتم إضافة سجلات ذاكرة مؤقتة. الأسباب المحتملة:"
     1072msgid "No cache records added. There are currently no cache files available."
     1073msgstr "No cache records added. There are currently no cache files available."
    10741074
    10751075#: includes/admin-page.php:1979
  • ai-translate/trunk/languages/ai-translate-de_DE.po

    r3451123 r3453094  
    265265
    266266#: includes/admin-page.php:1977
    267 msgid "No cache records added. Possible causes:"
    268 msgstr "Keine Cache-Einträge hinzugefügt. Mögliche Ursachen:"
     267msgid "No cache records added. There are currently no cache files available."
     268msgstr "Keine Cache-Einträge hinzugefügt. Derzeit sind keine Cache-Dateien vorhanden."
    269269
    270270#: includes/admin-page.php:1973
  • ai-translate/trunk/languages/ai-translate-en_US.po

    r3451123 r3453094  
    895895
    896896#: includes/admin-page.php:1977
    897 msgid "No cache records added. Possible causes:"
    898 msgstr ""
    899 
    900 #: includes/admin-page.php:1979
    901 msgid "Cache files do not exist at the expected location"
    902 msgstr ""
    903 
    904 #: includes/admin-page.php:1980
    905 msgid "Cache files have a different format than expected"
    906 msgstr ""
    907 
    908 #: includes/admin-page.php:1981
    909 msgid "Multi-domain caching configuration does not match"
     897msgid "No cache records added. There are currently no cache files available."
    910898msgstr ""
    911899
  • ai-translate/trunk/languages/ai-translate-fr_FR.po

    r3451123 r3453094  
    265265
    266266#: includes/admin-page.php:1977
    267 msgid "No cache records added. Possible causes:"
    268 msgstr "Aucun enregistrement de cache ajouté. Causes possibles :"
     267msgid "No cache records added. There are currently no cache files available."
     268msgstr "Aucun enregistrement de cache ajouté. Aucun fichier cache n'est disponible actuellement."
    269269
    270270#: includes/admin-page.php:1973
  • ai-translate/trunk/languages/ai-translate-hi_IN.po

    r3451123 r3453094  
    10631063#: includes/admin-page.php:1977
    10641064
    1065 msgid "No cache records added. Possible causes:"
    1066 msgstr "कोई कैश रिकॉर्ड नहीं जोड़ा गया। संभावित कारण:"
     1065msgid "No cache records added. There are currently no cache files available."
     1066msgstr "No cache records added. There are currently no cache files available."
    10671067
    10681068#: includes/admin-page.php:1979
  • ai-translate/trunk/languages/ai-translate-it_IT.po

    r3451123 r3453094  
    10901090#: includes/admin-page.php:1977
    10911091
    1092 msgid "No cache records added. Possible causes:"
    1093 msgstr "Nessun record cache aggiunto. Possibili cause:"
     1092msgid "No cache records added. There are currently no cache files available."
     1093msgstr "No cache records added. There are currently no cache files available."
    10941094
    10951095#: includes/admin-page.php:1979
  • ai-translate/trunk/languages/ai-translate-ja.po

    r3451123 r3453094  
    10771077#: includes/admin-page.php:1977
    10781078
    1079 msgid "No cache records added. Possible causes:"
    1080 msgstr "キャッシュレコードが追加されませんでした。考えられる原因:"
     1079msgid "No cache records added. There are currently no cache files available."
     1080msgstr "No cache records added. There are currently no cache files available."
    10811081
    10821082#: includes/admin-page.php:1979
  • ai-translate/trunk/languages/ai-translate-nl_NL.po

    r3451123 r3453094  
    10901090#: includes/admin-page.php:1977
    10911091
    1092 msgid "No cache records added. Possible causes:"
    1093 msgstr "Geen cache records toegevoegd. Mogelijke oorzaken:"
    1094 
    1095 #: includes/admin-page.php:1979
    1096 
    1097 msgid "Cache files do not exist at the expected location"
    1098 msgstr "Cache bestanden bestaan niet op de verwachte locatie"
    1099 
    1100 #: includes/admin-page.php:1980
    1101 
    1102 msgid "Cache files have a different format than expected"
    1103 msgstr "Cache bestanden hebben een ander formaat dan verwacht"
    1104 
    1105 #: includes/admin-page.php:1981
    1106 
    1107 msgid "Multi-domain caching configuration does not match"
    1108 msgstr "Multi-domain caching configuratie komt niet overeen"
     1092msgid "No cache records added. There are currently no cache files available."
     1093msgstr "Geen cache records toegevoegd; er zijn momenteel geen cachebestanden beschikbaar."
    11091094
    11101095#: includes/admin-page.php:1994
  • ai-translate/trunk/languages/ai-translate-pt_PT.po

    r3451123 r3453094  
    265265
    266266#: includes/admin-page.php:1977
    267 msgid "No cache records added. Possible causes:"
    268 msgstr "Nenhum registro de cache adicionado. Possíveis causas:"
     267msgid "No cache records added. There are currently no cache files available."
     268msgstr "No cache records added. There are currently no cache files available."
    269269
    270270#: includes/admin-page.php:1973
  • ai-translate/trunk/languages/ai-translate-zh_CN.po

    r3451123 r3453094  
    10651065#: includes/admin-page.php:1977
    10661066
    1067 msgid "No cache records added. Possible causes:"
    1068 msgstr "未添加缓存记录。可能的原因:"
     1067msgid "No cache records added. There are currently no cache files available."
     1068msgstr "No cache records added. There are currently no cache files available."
    10691069
    10701070#: includes/admin-page.php:1979
  • ai-translate/trunk/languages/ai-translate.pot

    r3451123 r3453094  
    790790
    791791#: includes/admin-page.php:1977
    792 msgid "No cache records added. Possible causes:"
    793 msgstr ""
    794 
    795 #: includes/admin-page.php:1979
    796 msgid "Cache files do not exist at the expected location"
    797 msgstr ""
    798 
    799 #: includes/admin-page.php:1980
    800 msgid "Cache files have a different format than expected"
    801 msgstr ""
    802 
    803 #: includes/admin-page.php:1981
    804 msgid "Multi-domain caching configuration does not match"
     792msgid "No cache records added. There are currently no cache files available."
    805793msgstr ""
    806794
Note: See TracChangeset for help on using the changeset viewer.