Changeset 3453094
- Timestamp:
- 02/03/2026 05:12:45 PM (3 weeks ago)
- Location:
- ai-translate/trunk
- Files:
-
- 25 edited
-
README.md (modified) (1 diff)
-
includes/admin-page.php (modified) (16 diffs)
-
includes/class-ai-cache.php (modified) (1 diff)
-
includes/class-ai-ob.php (modified) (16 diffs)
-
includes/class-ai-slugs.php (modified) (1 diff)
-
languages/ai-translate-ar.mo (modified) (previous)
-
languages/ai-translate-ar.po (modified) (1 diff)
-
languages/ai-translate-de_DE.mo (modified) (previous)
-
languages/ai-translate-de_DE.po (modified) (1 diff)
-
languages/ai-translate-en_US.po (modified) (1 diff)
-
languages/ai-translate-fr_FR.mo (modified) (previous)
-
languages/ai-translate-fr_FR.po (modified) (1 diff)
-
languages/ai-translate-hi_IN.mo (modified) (previous)
-
languages/ai-translate-hi_IN.po (modified) (1 diff)
-
languages/ai-translate-it_IT.mo (modified) (previous)
-
languages/ai-translate-it_IT.po (modified) (1 diff)
-
languages/ai-translate-ja.mo (modified) (previous)
-
languages/ai-translate-ja.po (modified) (1 diff)
-
languages/ai-translate-nl_NL.mo (modified) (previous)
-
languages/ai-translate-nl_NL.po (modified) (1 diff)
-
languages/ai-translate-pt_PT.mo (modified) (previous)
-
languages/ai-translate-pt_PT.po (modified) (1 diff)
-
languages/ai-translate-zh_CN.mo (modified) (previous)
-
languages/ai-translate-zh_CN.po (modified) (1 diff)
-
languages/ai-translate.pot (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ai-translate/trunk/README.md
r3451583 r3453094 32 32 - **🌍 35+ Languages** - Support for all major world languages and much more. 33 33 - **⚡ 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 . 35 35 - **🍪 Remembers Preferences** - Saves each visitor's language preference (via cookies). 36 36 - **🎨 Easy to Use** - Simple language switcher in the left corner of your website. 37 37 - **🔧 Flexible** - Choose your own AI model (OpenAI, Deepseek, or other APIs). 38 38 - **🔗 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. 39 40 40 41 ## Installation -
ai-translate/trunk/includes/admin-page.php
r3452204 r3453094 308 308 309 309 /** 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 */ 315 function 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 /** 310 330 * Return route_id used for cache key when warming cache. Must match class-ai-ob current_route_id() for the same URL. 311 331 * … … 362 382 foreach ($lang_codes as $lang_code) { 363 383 try { 384 warm_cache_log("WARM_CACHE_BATCH: Generating URL", ['post_id' => $post_id, 'lang_code' => $lang_code]); 364 385 $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 365 388 if ($translated_url === '') { 366 389 $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]); 367 391 continue; 368 392 } 369 393 394 warm_cache_log("WARM_CACHE_BATCH: Starting curl request", ['post_id' => $post_id, 'lang_code' => $lang_code, 'url' => $translated_url]); 370 395 $ch = curl_init($translated_url); 371 396 curl_setopt_array($ch, array( … … 429 454 // Accept 200 as success (unless it's an error page) 430 455 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 431 459 // Wait a moment for async cache writes to complete 432 460 usleep(500000); // 0.5 second … … 436 464 $cache_file = \AITranslate\AI_Cache::get_file_path($cache_key); 437 465 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 438 468 if ($cache_file && file_exists($cache_file)) { 439 469 // Ensure metadata is inserted/updated in database … … 441 471 AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash); 442 472 473 warm_cache_log("WARM_CACHE_BATCH: Cache file found immediately", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]); 443 474 $results[$lang_code] = array('success' => true, 'error' => ''); 444 475 } else { … … 451 482 $cache_hash = md5($cache_key); 452 483 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]); 453 485 $results[$lang_code] = array('success' => true, 'error' => ''); 454 486 $found = true; … … 460 492 // Provide more detailed error message 461 493 $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 462 496 if ($cache_file) { 463 497 // Check parent directories existence … … 467 501 if (!is_dir($parent_dir)) { 468 502 $error_detail .= ' (' . __('lang directory missing', 'ai-translate') . ')'; 503 $debug_info['parent_dir_exists'] = false; 469 504 } elseif (!is_dir($cache_dir)) { 470 505 // Hash subdirectory missing is normal - it gets created during write 471 506 // This means the write never happened 472 507 $error_detail .= ' (' . __('no write occurred', 'ai-translate') . ')'; 508 $debug_info['cache_dir_exists'] = false; 473 509 } elseif (!is_writable($cache_dir)) { 474 510 $error_detail .= ' (' . __('not writable', 'ai-translate') . ')'; 511 $debug_info['cache_dir_writable'] = false; 475 512 } else { 476 513 $error_detail .= ' (' . __('check logs', 'ai-translate') . ')'; 514 $debug_info['cache_dir_exists'] = true; 515 $debug_info['cache_dir_writable'] = is_writable($cache_dir); 477 516 } 478 517 } 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); 479 532 $results[$lang_code] = array('success' => false, 'error' => $error_detail); 480 533 } … … 522 575 $translated_url = \AITranslate\AI_SEO::get_translated_url($post_id, $lang_code); 523 576 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]); 524 578 return array('success' => false, 'error' => __('Could not generate post URL.', 'ai-translate')); 525 579 } 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]); 526 582 527 583 // Parse URL to get host and path … … 568 624 // Accept 200 as success (redirects might indicate issues, but we'll check cache anyway) 569 625 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 570 628 // Verify cache was generated by checking if cache file exists 571 629 // Wait a moment for async cache writes to complete … … 576 634 $cache_file = \AITranslate\AI_Cache::get_file_path($cache_key); 577 635 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 578 638 if ($cache_file && file_exists($cache_file)) { 579 639 // Ensure metadata is inserted/updated in database … … 582 642 AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash); 583 643 644 warm_cache_log("WARM_CACHE_INTERNAL: Cache file found immediately", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]); 584 645 return array('success' => true, 'error' => ''); 585 646 } else { … … 591 652 AI_Cache_Meta::insert($post_id, $lang_code, $cache_file, $cache_hash); 592 653 654 warm_cache_log("WARM_CACHE_INTERNAL: Cache file found after delay", ['post_id' => $post_id, 'lang_code' => $lang_code, 'cache_file' => $cache_file]); 593 655 return array('success' => true, 'error' => ''); 594 656 } 595 657 // 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)]); 596 659 return array('success' => false, 'error' => __('Cache file not generated after successful request', 'ai-translate')); 597 660 } … … 1135 1198 } 1136 1199 } 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 1140 1201 if (isset($sanitized['cache_expiration']) && $sanitized['cache_expiration'] > 50000) { 1141 1202 $sanitized['cache_expiration'] = 14 * 24; … … 1164 1225 // Initialiseer als nog niet gezet 1165 1226 $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; 1166 1238 } 1167 1239 … … 2179 2251 echo '</p></div>'; 2180 2252 } 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>'; 2189 2256 } 2190 2257 } -
ai-translate/trunk/includes/class-ai-cache.php
r3433090 r3453094 114 114 wp_mkdir_p($dir); 115 115 } 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 } 117 141 118 142 // Track cache metadata for admin table -
ai-translate/trunk/includes/class-ai-ob.php
r3451123 r3453094 132 132 public function callback($html) 133 133 { 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 134 152 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 } 136 167 return $html; 137 168 } 138 169 $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 } 139 176 140 177 // PHASE 1: Basic environment checks 141 178 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 } 142 184 $processing = false; 143 185 return $html; … … 146 188 // PHASE 2: Content type validation 147 189 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 } 148 195 $processing = false; 149 196 return $html; … … 152 199 // PHASE 3: Page structure validation 153 200 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 } 154 206 $processing = false; 155 207 return $html; … … 158 210 // PHASE 4: File type checks 159 211 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 } 160 217 $processing = false; 161 218 return $html; … … 164 221 // PHASE 5: Language and user validation 165 222 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 } 166 228 $processing = false; 167 229 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); 168 236 } 169 237 … … 210 278 $shouldTranslate = $this->route_should_be_translated($route); 211 279 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 } 212 285 $processing = false; 213 286 return $html; // Return untranslated HTML without processing … … 290 363 // Another request is still generating this page; avoid duplicate API calls 291 364 // 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 } 292 370 $processing = false; 293 371 return $html; … … 298 376 $cached = AI_Cache::get($key); 299 377 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 } 300 383 $processing = false; 301 384 return $cached; … … 306 389 set_transient($lockKey, time(), 120); // Lock expires after 2 minutes as failsafe 307 390 $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 } 308 397 } 309 398 … … 312 401 $remaining = $timeLimit > 0 ? ($timeLimit - $elapsed) : 120; 313 402 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 } 314 408 if ($lockAcquired) { 315 409 delete_transient($lockKey); … … 392 486 if (!$cache_exists || !$cache_is_expired) { 393 487 // 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 } 394 494 if ($lockAcquired) { 395 495 delete_transient($lockKey); … … 456 556 $html3HasBody = (stripos($html3, '<body') !== false); 457 557 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 458 574 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 } 459 580 if ($lockAcquired) { 460 581 delete_transient($lockKey); … … 469 590 // Additional check: only cache if route corresponds to cacheable content (not search pages, etc.) 470 591 $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 471 599 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 472 618 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 } 473 648 } 474 649 … … 599 774 } 600 775 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 601 790 // For singular posts/pages: use post ID (consistent, prevents duplicates) 602 791 // Only use post ID if it's actually a singular post/page (not archive/search/attachment) … … 667 856 $path = preg_replace('#/+#', '/', $path); 668 857 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 669 864 // Remove leading language code to get clean path 670 865 $clean_path = preg_replace('#^/([a-z]{2})(?:/|$)#i', '/', $path); … … 679 874 if (!empty($path_parts) && !in_array($clean_path, array('/category/', '/tag/', '/author/', '/date/'))) { 680 875 $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 } 694 899 } 695 900 } -
ai-translate/trunk/includes/class-ai-slugs.php
r3451123 r3453094 498 498 499 499 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 500 516 return $translated_slug; 501 517 } -
ai-translate/trunk/languages/ai-translate-ar.po
r3451123 r3453094 1070 1070 #: includes/admin-page.php:1977 1071 1071 1072 msgid "No cache records added. Possible causes:"1073 msgstr " لم يتم إضافة سجلات ذاكرة مؤقتة. الأسباب المحتملة:"1072 msgid "No cache records added. There are currently no cache files available." 1073 msgstr "No cache records added. There are currently no cache files available." 1074 1074 1075 1075 #: includes/admin-page.php:1979 -
ai-translate/trunk/languages/ai-translate-de_DE.po
r3451123 r3453094 265 265 266 266 #: includes/admin-page.php:1977 267 msgid "No cache records added. Possible causes:"268 msgstr "Keine Cache-Einträge hinzugefügt. Mögliche Ursachen:"267 msgid "No cache records added. There are currently no cache files available." 268 msgstr "Keine Cache-Einträge hinzugefügt. Derzeit sind keine Cache-Dateien vorhanden." 269 269 270 270 #: includes/admin-page.php:1973 -
ai-translate/trunk/languages/ai-translate-en_US.po
r3451123 r3453094 895 895 896 896 #: 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" 897 msgid "No cache records added. There are currently no cache files available." 910 898 msgstr "" 911 899 -
ai-translate/trunk/languages/ai-translate-fr_FR.po
r3451123 r3453094 265 265 266 266 #: includes/admin-page.php:1977 267 msgid "No cache records added. Possible causes:"268 msgstr "Aucun enregistrement de cache ajouté. Causes possibles :"267 msgid "No cache records added. There are currently no cache files available." 268 msgstr "Aucun enregistrement de cache ajouté. Aucun fichier cache n'est disponible actuellement." 269 269 270 270 #: includes/admin-page.php:1973 -
ai-translate/trunk/languages/ai-translate-hi_IN.po
r3451123 r3453094 1063 1063 #: includes/admin-page.php:1977 1064 1064 1065 msgid "No cache records added. Possible causes:"1066 msgstr " कोई कैश रिकॉर्ड नहीं जोड़ा गया। संभावित कारण:"1065 msgid "No cache records added. There are currently no cache files available." 1066 msgstr "No cache records added. There are currently no cache files available." 1067 1067 1068 1068 #: includes/admin-page.php:1979 -
ai-translate/trunk/languages/ai-translate-it_IT.po
r3451123 r3453094 1090 1090 #: includes/admin-page.php:1977 1091 1091 1092 msgid "No cache records added. Possible causes:"1093 msgstr "N essun record cache aggiunto. Possibili cause:"1092 msgid "No cache records added. There are currently no cache files available." 1093 msgstr "No cache records added. There are currently no cache files available." 1094 1094 1095 1095 #: includes/admin-page.php:1979 -
ai-translate/trunk/languages/ai-translate-ja.po
r3451123 r3453094 1077 1077 #: includes/admin-page.php:1977 1078 1078 1079 msgid "No cache records added. Possible causes:"1080 msgstr " キャッシュレコードが追加されませんでした。考えられる原因:"1079 msgid "No cache records added. There are currently no cache files available." 1080 msgstr "No cache records added. There are currently no cache files available." 1081 1081 1082 1082 #: includes/admin-page.php:1979 -
ai-translate/trunk/languages/ai-translate-nl_NL.po
r3451123 r3453094 1090 1090 #: includes/admin-page.php:1977 1091 1091 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" 1092 msgid "No cache records added. There are currently no cache files available." 1093 msgstr "Geen cache records toegevoegd; er zijn momenteel geen cachebestanden beschikbaar." 1109 1094 1110 1095 #: includes/admin-page.php:1994 -
ai-translate/trunk/languages/ai-translate-pt_PT.po
r3451123 r3453094 265 265 266 266 #: includes/admin-page.php:1977 267 msgid "No cache records added. Possible causes:"268 msgstr "N enhum registro de cache adicionado. Possíveis causas:"267 msgid "No cache records added. There are currently no cache files available." 268 msgstr "No cache records added. There are currently no cache files available." 269 269 270 270 #: includes/admin-page.php:1973 -
ai-translate/trunk/languages/ai-translate-zh_CN.po
r3451123 r3453094 1065 1065 #: includes/admin-page.php:1977 1066 1066 1067 msgid "No cache records added. Possible causes:"1068 msgstr " 未添加缓存记录。可能的原因:"1067 msgid "No cache records added. There are currently no cache files available." 1068 msgstr "No cache records added. There are currently no cache files available." 1069 1069 1070 1070 #: includes/admin-page.php:1979 -
ai-translate/trunk/languages/ai-translate.pot
r3451123 r3453094 790 790 791 791 #: 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" 792 msgid "No cache records added. There are currently no cache files available." 805 793 msgstr "" 806 794
Note: See TracChangeset
for help on using the changeset viewer.