define_constants();
$this->load_dependencies();
$this->init_hooks();
}
/**
* System path definition maps.
*/
private function define_constants()
{
if (! defined('AF_TRANSLATE_FILE')) {
define('AF_TRANSLATE_FILE', __FILE__);
}
if (! defined('AF_TRANSLATE_BASE')) {
define('AF_TRANSLATE_BASE', plugin_basename(AF_TRANSLATE_FILE));
}
if (! defined('AF_TRANSLATE_DIR')) {
define('AF_TRANSLATE_DIR', dirname(AF_TRANSLATE_FILE));
}
if (! defined('AF_TRANSLATE_PATH')) {
define('AF_TRANSLATE_PATH', plugin_dir_path(__FILE__));
}
if (! defined('AF_TRANSLATE_URL')) {
define('AF_TRANSLATE_URL', plugin_dir_url(__FILE__));
}
// Add an optional indicator lookup helper
if (! defined('AF_TRANSLATE_IS_PRO')) {
define('AF_TRANSLATE_IS_PRO', class_exists('AF_Translate_Pro') || defined('AF_TRANSLATE_PRO_FILE'));
}
}
/**
* High-performance memory-optimized asset loading schema.
*/
private function load_dependencies()
{
// Shared global multi-dimensional localization data configurations
require_once AF_TRANSLATE_PATH . 'includes/class-i18n-data.php';
require_once AF_TRANSLATE_PATH . 'includes/class-af-translate.php';
// Critical Performance Safeguard: Execute heavy analysis suites only on back-end requests
if (is_admin()) {
require_once AF_TRANSLATE_PATH . 'includes/class-bundle-analyzer.php';
require_once AF_TRANSLATE_PATH . 'includes/class-translate-scanner.php';
require_once AF_TRANSLATE_PATH . 'includes/class-project-config.php';
require_once AF_TRANSLATE_PATH . 'includes/class-project-ajax.php';
require_once AF_TRANSLATE_PATH . 'includes/class-editor-view.php';
require_once AF_TRANSLATE_PATH . 'includes/class-file-pot-generator.php';
require_once AF_TRANSLATE_PATH . 'includes/class-file-compiler.php';
require_once AF_TRANSLATE_PATH . 'includes/class-file-stream.php';
require_once AF_TRANSLATE_PATH . 'includes/class-file-ajax.php';
require_once AF_TRANSLATE_PATH . 'includes/class-editor-path-validator.php';
require_once AF_TRANSLATE_PATH . 'includes/class-editor-po-processor.php';
require_once AF_TRANSLATE_PATH . 'includes/class-editor-ajax-handler.php';
require_once AF_TRANSLATE_PATH . 'includes/class-translate-ai-engine.php';
require_once AF_TRANSLATE_PATH . 'includes/class-translate-ai-ajax.php';
//require_once AF_TRANSLATE_PATH . 'includes/class-translate-ai-bridge.php';
}
}
/**
* Standard runtime execution initialization hooks.
*/
private function init_hooks()
{
add_action('plugins_loaded', array($this, 'boot_core_engine'));
/**
* CRITICAL GLOBAL HOOK: Intercepts and redirects MO file loading metrics.
* Must run globally (outside of is_admin) so frontend visitors see custom strings.
*/
add_filter('load_textdomain_mofile', array($this, 'af_translate_load_from_uploads'), 1, 2);
add_filter('plugin_row_meta', [$this, 'plugin_row_meta'], 10, 2);
add_filter('plugin_action_links_' . AF_TRANSLATE_BASE, [$this, 'plugin_action_links']);
}
public function plugin_action_links($links)
{
$settings_link = sprintf('%2$s', admin_url('admin.php?page=af-translate'), esc_html__('Get Started', 'af-translate'));
array_unshift($links, $settings_link);
$links['af-translate-ai-connecter'] = sprintf('%2$s', admin_url('admin.php?page=af-translate-ai-connecter'), esc_html__('AI Settings', 'af-translate'));
return $links;
}
public function plugin_row_meta($plugin_meta, $plugin_file)
{
if (AF_TRANSLATE_BASE === $plugin_file) {
$row_meta = [
'af-translate-plugins' => sprintf('%2$s', admin_url('admin.php?page=af-translate-plugins'), esc_html__('Translate Plugins', 'af-translate')),
'af-translate-themes' => sprintf('%2$s', admin_url('admin.php?page=af-translate-themes'), esc_html__('Translate Themes', 'af-translate')),
];
$plugin_meta = array_merge($plugin_meta, $row_meta);
}
return $plugin_meta;
}
public function af_translate_load_from_uploads($mofile, $domain)
{
// error_log("WATCHDOG: WordPress is attempting to load translations for domain: [$domain] | File: [$mofile]");
// if ($domain === 'shopical-pro') {
// error_log("AF Translate FOUND IT: Domain [$domain] requested file: [$mofile]");
// }
// return $mofile;
// 1. Skip core translation
if ('default' === $domain) {
return $mofile;
}
$filename = basename($mofile);
// 2. Robust Regex: matches either "domain-locale.mo" or "locale.mo"
// This safely extracts the locale even if the domain prefix is missing.
$pattern = '/^(?:' . preg_quote($domain, '/') . '-)?(.+)\.mo$/';
if (!preg_match($pattern, $filename, $matches)) {
return $mofile; // Exit if filename format is unexpected
}
$locale = $matches[1];
$upload_dir = wp_upload_dir();
$base_path = $upload_dir['basedir'] . '/af-translate/';
// 3. Construct the exact filename we are looking for
// This ensures we always look for "domain-locale.mo"
$target_filename = $domain . '-' . $locale . '.mo';
$directories = [
$base_path . 'themes/',
$base_path . 'plugins/',
$base_path . 'core/'
];
foreach ($directories as $dir) {
// ADD THIS LOG:
// error_log("AF Translate DEBUG: Searching for [$target_filename] in [$dir]");
$found = $this->find_file_case_insensitive($dir, $target_filename);
if ($found) {
// DEBUG: See if we are actually swapping the file
// error_log("AF Translate SUCCESS: Swapping $mofile with $found");
return $found;
}
}
return $mofile;
}
/**
* Case-insensitive file search helper
*/
private function find_file_case_insensitive($directory, $filename)
{
if (!is_dir($directory)) return false;
// Scan directory and compare names using case-insensitive comparison
$files = scandir($directory);
foreach ($files as $file) {
if (strcasecmp($file, $filename) === 0) {
return $directory . $file;
}
}
return false;
}
/**
* Instantiates the foundational translation controller framework safely.
*/
public function boot_core_engine()
{
// 1. Boot the core foundational translation framework
if (class_exists('AF_Translate_Core')) {
new AF_Translate_Core();
}
// 2. Ignite the streaming download hooks for admin-post.php
if (class_exists('AF_Translate_File_Streaming')) {
AF_Translate_File_Streaming::init_hooks();
}
// 3. Editor Workbench AJAX Actions
if (class_exists('AF_Translate_Editor_AJAX_Handler')) {
add_action('wp_ajax_af_translate_save_pot', array('AF_Translate_Editor_AJAX_Handler', 'handle_save'));
}
// 4. Extended Utilities AJAX Actions
if (class_exists('AF_Translate_Ajax_Extended')) {
add_action('wp_ajax_af_translate_init_locale', array('AF_Translate_Ajax_Extended', 'ajax_init_po_handler'));
add_action('wp_ajax_af_translate_import_po', array('AF_Translate_Ajax_Extended', 'ajax_import_po_handler'));
}
/**
* POLYMORPHIC ROUTER: Intercepts the shared action hook collision
* and safely directs traffic to the correct engine component.
*/
add_action('wp_ajax_af_translate_sync_po', array($this, 'route_sync_po_requests'));
/**
* Freemius.
*/
if (!class_exists('AF_Translate_Pro')) {
require_once(AF_TRANSLATE_DIR . '/freemius.php');
}
}
/**
* Polymorphic AJAX Router to handle shared action hook collisions safely.
* Evaluates parameters to differentiate between the editor screen and portability screen.
*/
public function route_sync_po_requests()
{
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Operational routing controller check; verification is safely deferred to downstream workbench sync execution context handlers.
if (isset($_POST['po_file_target']) && class_exists('AF_Translate_Editor_AJAX_Handler')) {
AF_Translate_Editor_AJAX_Handler::handle_sync();
exit;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Operational routing controller check; verification is safely deferred to downstream module dashboard sync handlers.
if (isset($_POST['component']) && class_exists('AF_Translate_Ajax_Extended')) {
AF_Translate_Ajax_Extended::ajax_sync_po_handler();
exit;
}
wp_send_json_error(esc_html__('Invalid transaction routing parameter signature.', 'af-translate'));
}
}
/**
* Accessor function shortcut to instantiate the architectural controller context.
*
* @return AF_Translate
*/
function af_translate_engine()
{
return AF_Translate::instance();
}
// Ignite operational plugin setup
af_translate_engine();