# WordPress Hooks & Filters

This document lists all available WordPress hooks and filters in the translate-press-zone plugin for extending functionality.

---

## Actions (Hooks)

### Translation Job Lifecycle

#### `presszone_translate_before_send_job`
Fires before a translation job is sent to the API.

**Parameters:**
- `int $job_id` - WPML job ID
- `array $payload` - API payload to be sent
- `int $local_job_id` - Local database job ID

**Example:**
```php
add_action('presszone_translate_before_send_job', function($job_id, $payload, $local_job_id) {
    // Log job submission
    error_log("Sending translation job {$job_id} to API");
}, 10, 3);
```

---

#### `presszone_translate_after_send_job`
Fires after a translation job is successfully sent to the API.

**Parameters:**
- `int $job_id` - WPML job ID
- `string $api_job_id` - API-assigned job ID
- `int $local_job_id` - Local database job ID
- `array $response_body` - Full API response body

**Example:**
```php
add_action('presszone_translate_after_send_job', function($job_id, $api_job_id, $local_job_id, $body) {
    // Notify admin that job was sent
    wp_mail(get_option('admin_email'), 'Translation Job Sent', "Job {$job_id} sent successfully");
}, 10, 4);
```

---

#### `presszone_translate_before_process_completed`
Fires before processing a completed translation from the webhook.

**Parameters:**
- `object $job` - Local job database record
- `string $translation` - Translated content
- `int $tokens_used` - Tokens consumed
- `float $cost_usd` - Cost in USD

**Example:**
```php
add_action('presszone_translate_before_process_completed', function($job, $translation, $tokens, $cost) {
    // Track costs in custom analytics
    update_option('total_translation_cost', get_option('total_translation_cost', 0) + $cost);
}, 10, 4);
```

---

#### `presszone_translate_after_process_completed`
Fires after a completed translation has been saved to WPML.

**Parameters:**
- `object $job` - Local job database record
- `string $translation` - Translated content
- `int $tokens_used` - Tokens consumed
- `float $cost_usd` - Cost in USD

**Example:**
```php
add_action('presszone_translate_after_process_completed', function($job, $translation, $tokens, $cost) {
    // Send Slack notification
    send_slack_notification("Translation completed for job {$job->wpml_job_id}");
}, 10, 4);
```

---

#### `presszone_translate_job_failed`
Fires when a translation job fails.

**Parameters:**
- `object $job` - Local job database record
- `string $error_message` - Error message from API

**Example:**
```php
add_action('presszone_translate_job_failed', function($job, $error) {
    // Alert admin of failures
    wp_mail(get_option('admin_email'), 'Translation Failed', "Job {$job->wpml_job_id} failed: {$error}");
}, 10, 2);
```

---

#### `presszone_translate_process_custom_fields`
Fires when processing custom fields from translation result.

Use this to handle translation of custom fields that were included in the job.

**Parameters:**
- `object $job` - Local job database record
- `string $translation` - Full translation result (may include custom field data)

**Example:**
```php
add_action('presszone_translate_process_custom_fields', function($job, $translation) {
    // Extract and save custom field translations
    $data = json_decode($translation, true);
    if (isset($data['custom_fields'])) {
        foreach ($data['custom_fields'] as $field => $value) {
            update_post_meta($job->translation_post_id, $field, $value);
        }
    }
}, 10, 2);
```

---

## Filters

### Content Modification

#### `presszone_translate_before_send_content`
Filters content before sending to translation API.

**Parameters:**
- `string $content` - Content to translate
- `int $job_id` - WPML job ID
- `string $source_lang` - Source language code
- `string $target_lang` - Target language code

**Returns:** `string` Modified content

**Example:**
```php
add_filter('presszone_translate_before_send_content', function($content, $job_id, $source, $target) {
    // Add context for better translation
    if ($target === 'ja') {
        $content = "<!-- Japanese translation -->\n" . $content;
    }
    return $content;
}, 10, 4);
```

---

#### `presszone_translate_result`
Filters translated content before saving to WPML.

**Parameters:**
- `string $translation` - Translated content from API
- `int $wpml_job_id` - WPML job ID
- `string $source_lang` - Source language code
- `string $target_lang` - Target language code

**Returns:** `string` Modified translation

**Example:**
```php
add_filter('presszone_translate_result', function($translation, $job_id, $source, $target) {
    // Remove specific HTML comments
    $translation = preg_replace('/<!-- .* -->/U', '', $translation);
    return $translation;
}, 10, 4);
```

---

### Custom Fields Support

#### `presszone_translate_custom_fields`
Filters custom fields to include in translation job.

**Parameters:**
- `array $custom_fields` - Array of custom fields (empty by default)
- `int $job_id` - WPML job ID
- `object $job_data` - Full WPML job data

**Returns:** `array` Custom fields to translate

**Example:**
```php
add_filter('presszone_translate_custom_fields', function($fields, $job_id, $job_data) {
    // Add product description custom field
    $post_id = $job_data->element_id ?? 0;
    if ($post_id) {
        $fields['product_description'] = get_post_meta($post_id, 'product_description', true);
        $fields['seo_title'] = get_post_meta($post_id, '_yoast_wpseo_title', true);
    }
    return $fields;
}, 10, 3);
```

---

### API Payload Modification

#### `presszone_translate_api_payload`
Filters the complete API payload before sending.

**Parameters:**
- `array $payload` - Full API payload
- `int $job_id` - WPML job ID
- `object $job_data` - Full WPML job data

**Returns:** `array` Modified payload

**Example:**
```php
add_filter('presszone_translate_api_payload', function($payload, $job_id, $job_data) {
    // Add custom instructions for specific content types
    if ($job_data->post_type === 'product') {
        $payload['tone'] = 'professional';
        $payload['preserve_tags'][] = 'price';
    }
    return $payload;
}, 10, 3);
```

---

## Common Use Cases

### 1. Track All Translation Costs

```php
add_action('presszone_translate_after_process_completed', function($job, $translation, $tokens, $cost) {
    global $wpdb;
    $wpdb->insert($wpdb->prefix . 'translation_costs', [
        'job_id' => $job->id,
        'cost' => $cost,
        'tokens' => $tokens,
        'date' => current_time('mysql'),
    ]);
}, 10, 4);
```

---

### 2. Translate WooCommerce Product Custom Fields

```php
// Add custom fields to translation job
add_filter('presszone_translate_custom_fields', function($fields, $job_id, $job_data) {
    $post_id = $job_data->element_id ?? 0;
    if (get_post_type($post_id) === 'product') {
        $fields['short_description'] = get_post_meta($post_id, '_product_short_description', true);
        $fields['specifications'] = get_post_meta($post_id, '_product_specs', true);
    }
    return $fields;
}, 10, 3);

// Save translated custom fields
add_action('presszone_translate_process_custom_fields', function($job, $translation) {
    $data = json_decode($translation, true);
    if (isset($data['custom_fields']) && $job->translation_post_id) {
        foreach ($data['custom_fields'] as $field => $value) {
            update_post_meta($job->translation_post_id, $field, $value);
        }
    }
}, 10, 2);
```

---

### 3. Clean HTML Before/After Translation

```php
// Remove specific elements before translation
add_filter('presszone_translate_before_send_content', function($content) {
    // Remove shortcodes that shouldn't be translated
    $content = preg_replace('/\[contact_form.*?\]/', '', $content);
    return $content;
}, 10, 1);

// Restore formatting after translation
add_filter('presszone_translate_result', function($translation) {
    // Ensure proper spacing around inline elements
    $translation = preg_replace('/<\/strong> </', '</strong>&nbsp;<', $translation);
    return $translation;
}, 10, 1);
```

---

### 4. Send Notifications on Job Events

```php
// Notify on job failure
add_action('presszone_translate_job_failed', function($job, $error) {
    $admin_email = get_option('admin_email');
    $subject = sprintf('[%s] Translation Failed', get_bloginfo('name'));
    $message = sprintf(
        "Translation job %d failed:\n\nError: %s\n\nLanguages: %s → %s",
        $job->wpml_job_id,
        $error,
        $job->source_lang,
        $job->target_lang
    );
    wp_mail($admin_email, $subject, $message);
}, 10, 2);

// Notify on successful completion
add_action('presszone_translate_after_process_completed', function($job) {
    $editor_email = get_post_meta($job->post_id, '_editor_email', true);
    if ($editor_email) {
        wp_mail($editor_email, 'Translation Complete',
            "Your content has been translated to {$job->target_lang}");
    }
}, 10, 1);
```

---

### 5. Add Translation Memory Integration

```php
add_filter('presszone_translate_before_send_content', function($content, $job_id, $source, $target) {
    // Check translation memory for common phrases
    $tm = get_translation_memory_entries($source, $target);

    foreach ($tm as $source_phrase => $translated_phrase) {
        // Mark pre-translated segments
        $content = str_replace(
            $source_phrase,
            "<!-- TM:{$translated_phrase} -->{$source_phrase}",
            $content
        );
    }

    return $content;
}, 10, 4);

add_filter('presszone_translate_result', function($translation) {
    // Extract TM segments and ensure they weren't modified
    $translation = preg_replace_callback(
        '/<!-- TM:(.*?) -->(.*?)(?=<|$)/s',
        function($matches) {
            return $matches[1]; // Use TM translation
        },
        $translation
    );

    return $translation;
}, 10, 1);
```

---

## Best Practices

1. **Always return values in filters** - Forgetting to return will break the plugin
2. **Use appropriate priority** - Default is 10, use higher numbers (20+) to run after core processing
3. **Sanitize and validate** - Always sanitize data when modifying content
4. **Check for empty values** - Don't assume parameters will always have data
5. **Test error conditions** - Ensure your hooks handle failures gracefully
6. **Document your extensions** - Help other developers understand your customizations

---

## Need Help?

For questions about hooks and filters:
- Check WordPress Plugin API: https://developer.wordpress.org/plugins/hooks/
- Review WPML hooks: https://wpml.org/documentation/support/wpml-coding-api/
- Contact: support@translate.press.zone
