exists() ) { $protected_metadata[] = $current_theme->get( 'Name' ); $protected_metadata[] = $current_theme->get( 'ThemeURI' ); $protected_metadata[] = $current_theme->get( 'Description' ); $protected_metadata[] = $current_theme->get( 'Author' ); $protected_metadata[] = $current_theme->get( 'AuthorURI' ); $parent_theme = $current_theme->parent(); if ( $parent_theme && $parent_theme->exists() ) { $protected_metadata[] = $parent_theme->get( 'Name' ); $protected_metadata[] = $parent_theme->get( 'ThemeURI' ); $protected_metadata[] = $parent_theme->get( 'Description' ); $protected_metadata[] = $parent_theme->get( 'Author' ); $protected_metadata[] = $parent_theme->get( 'AuthorURI' ); } } } if ( function_exists( 'get_plugins' ) ) { if ( ! function_exists( 'get_plugin_data' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( function_exists( 'get_plugins' ) ) { $all_plugins = get_plugins(); foreach ( $all_plugins as $plugin_file => $plugin_data ) { if ( ! empty( $plugin_data['Name'] ) ) { $protected_metadata[] = $plugin_data['Name']; $protected_metadata[] = $plugin_data['PluginURI']; $protected_metadata[] = $plugin_data['Description']; $protected_metadata[] = $plugin_data['Author']; $protected_metadata[] = $plugin_data['AuthorURI']; } } } } $protected_metadata = array_filter( array_unique( array_map( 'trim', $protected_metadata ) ) ); $translation_map = array(); $fallback_msgid_map = array(); $existing_po_keys = array(); $po_entries = array(); $po_header_node = null; $pot_header_node = null; // Step 1: Parse the existing PO translation workspace if it exists if ( file_exists( $po_path ) ) { $po_entries = AF_Translate_PO_Processor::parse_file( $po_path ); foreach ( $po_entries as $entry ) { $context = isset( $entry['msgctxt'] ) ? trim( (string) $entry['msgctxt'] ) : ''; $msgid = isset( $entry['msgid'] ) ? (string) $entry['msgid'] : ''; // Track and isolate the translation target file header node if ( '' === $msgid && '' === $context ) { $po_header_node = $entry; continue; } $exact_key = $context . '|||' . $msgid; $existing_po_keys[ $exact_key ] = true; if ( ! isset( $translation_map[ $exact_key ] ) || empty( $translation_map[ $exact_key ] ) ) { $translation_map[ $exact_key ] = $entry['msgstr']; } if ( ! empty( $entry['msgstr'] ) ) { $fallback_msgid_map[ $msgid ] = $entry['msgstr']; } } } $unique_compiled_output = array(); $new_strings_count = 0; $matched_pot_keys = array(); // Step 2: Merge template updates down from the template layout blueprint foreach ( $pot_entries as $pot_node ) { $pot_context = isset( $pot_node['msgctxt'] ) ? trim( (string) $pot_node['msgctxt'] ) : ''; $pot_msgid = isset( $pot_node['msgid'] ) ? (string) $pot_node['msgid'] : ''; if ( '' === $pot_msgid && '' === $pot_context ) { $pot_header_node = $pot_node; continue; } $compound_key = $pot_context . '|||' . $pot_msgid; $matched_pot_keys[ $compound_key ] = true; if ( isset( $unique_compiled_output[ $compound_key ] ) ) { continue; } if ( ! isset( $existing_po_keys[ $compound_key ] ) ) { $new_strings_count++; } if ( isset( $translation_map[ $compound_key ] ) ) { $pot_node['msgstr'] = $translation_map[ $compound_key ]; } elseif ( isset( $fallback_msgid_map[ $pot_msgid ] ) ) { $pot_node['msgstr'] = $fallback_msgid_map[ $pot_msgid ]; } $unique_compiled_output[ $compound_key ] = $pot_node; } // --- CORE METADATA RE-INJECTION MATRIX --- // Iterate through existing workspace entries and intercept protected metadata text lines before they drop foreach ( $po_entries as $po_node ) { $po_context = isset( $po_node['msgctxt'] ) ? trim( (string) $po_node['msgctxt'] ) : ''; $po_msgid = isset( $po_node['msgid'] ) ? (string) $po_node['msgid'] : ''; if ( '' === $po_msgid ) { continue; } $compound_key = $po_context . '|||' . $po_msgid; // If the metadata string was missing from the POT file but is recognized as a valid header, force-inject it back if ( ! isset( $unique_compiled_output[ $compound_key ] ) ) { if ( in_array( trim( $po_msgid ), $protected_metadata, true ) ) { $unique_compiled_output[ $compound_key ] = $po_node; $matched_pot_keys[ $compound_key ] = true; // Nullify obsolete status calculation flag } } } $obsolete_strings_count = 0; foreach ( $existing_po_keys as $old_key => $void ) { if ( ! isset( $matched_pot_keys[ $old_key ] ) ) { $obsolete_strings_count++; } } // Step 3: Combine structural headers and active sync structures $final_nodes = array(); if ( ! empty( $po_header_node ) ) { $final_nodes[] = $po_header_node; } elseif ( ! empty( $pot_header_node ) ) { $final_nodes[] = $pot_header_node; } foreach ( $unique_compiled_output as $node ) { $final_nodes[] = $node; } $raw_po_text = AF_Translate_PO_Processor::generate_po_string( $final_nodes ); $sanitized_po_text = self::deduplicate_raw_po_string( $raw_po_text ); if ( false === file_put_contents( $po_path, $sanitized_po_text ) ) { return false; } return array( 'new' => $new_strings_count, 'obsolete' => $obsolete_strings_count, ); } /** * Compiles clean standard plain-text raw .po files into machine-readable .mo formats. */ public static function compile_po_to_mo( $po_path, $mo_path ) { $po_path = self::resolve_canonical_path( $po_path ); $mo_path = self::resolve_canonical_path( $mo_path ); if ( ! file_exists( $po_path ) || ! class_exists( 'AF_Translate_PO_Processor' ) ) { return false; } $entries_parsed = AF_Translate_PO_Processor::parse_file( $po_path ); $entries = array(); foreach ( $entries_parsed as $entry ) { $id = isset( $entry['msgid'] ) ? (string) $entry['msgid'] : ''; // Guardrail protection: Retain the structural header record (empty ID with content string) if ( '' === $id && ( empty( $entry['msgstr'] ) || empty( $entry['msgstr'][0] ) ) ) { continue; } if ( ! empty( $entry['msgid_plural'] ) ) { $id .= "\x00" . $entry['msgid_plural']; } if ( ! empty( $entry['msgctxt'] ) ) { $id = $entry['msgctxt'] . "\x04" . $id; } $str_val = ''; if ( ! empty( $entry['msgstr'] ) ) { $str_val = implode( "\x00", $entry['msgstr'] ); } $entries[ $id ] = $str_val; } // ksort places the empty header key "" securely at index 0 per Gettext requirements ksort( $entries ); $count = count( $entries ); if ( 0 === $count ) { return false; } $ids = ''; $strs = ''; $ids_offsets = array(); $strs_offsets = array(); foreach ( $entries as $id => $str ) { $ids_offsets[] = array( 'len' => strlen( $id ), 'pos' => strlen( $ids ) ); $ids .= $id . "\x00"; $strs_offsets[] = array( 'len' => strlen( $str ), 'pos' => strlen( $strs ) ); $strs .= $str . "\x00"; } $key_start = 28; $val_start = $key_start + ( $count * 8 ); $size_start = $val_start + ( $count * 8 ); $offsets_key = ''; foreach ( $ids_offsets as $offset ) { $offsets_key .= pack( 'VV', $offset['len'], $offset['pos'] + $size_start ); } $offsets_val = ''; foreach ( $strs_offsets as $offset ) { $offsets_val .= pack( 'VV', $offset['len'], $offset['pos'] + $size_start + strlen( $ids ) ); } $mo_header = pack( 'VvvIIIII', 0x950412de, 0, 0, $count, $key_start, $val_start, 0, 0 ); $mo_binary_data = $mo_header . $offsets_key . $offsets_val . $ids . $strs; return ( false !== file_put_contents( $mo_path, $mo_binary_data ) ); } }