# Translations Hooks

Weglot plugin will detect all the words in your HTML. To do this, it will parse the DOM in PHP and detect the inner text of HTML nodes but also some attributes we have defined, like the "placeholder" attribute in a `<input>` node or the "alt" attribute of an `img` node.

This usually ensure all the text in your page is detected and get translated. However, in some case, your text can be located in other location in your HTML. Like it could be in a JavaScript variable like this

```javascript
<script>
var myAwesomeVar = 'This is a text I would like to translate';
</script>
```

In that case, your text will not be detected and not be translated.

This is where you will use filters to extend the definitions of the Weglot Parser and instruct it to detect other text

### weglot\_get\_dom\_checkers

This filter extend the list of HTML nodes and attribute that are being translated.

| Argument       | Type   | Description                                                                       |
| -------------- | ------ | --------------------------------------------------------------------------------- |
| $dom\_checkers | String | Names of used **DomChecker** (extends Weglot\Parser\Check\Dom\AbstractDomChecker) |

#### Use case

It can happen in your HTML that you use data-attributes that are not translated by default. Example with **data-slide-title**

```markup
<div data-slide-title="Title slide">
    New project !
</div>
```

With this the `weglot_get_dom_checkers` filter, you will extend the list of "Dom checkers" by adding a class in the list like on the following example. Y

```php
<?php

add_filter( 'weglot_get_dom_checkers', 'custom_weglot_dom_check' );
function custom_weglot_dom_check( $dom_checkers  ) { //$dom_checkers contains the list of all the class we are checking by default
	if (!class_exists('Div_Slide_Title')) {
		class Div_Slide_Title extends Weglot\Parser\Check\Dom\AbstractDomChecker {
			const DOM       = 'div'; //Type of tag you want to detect // CSS Selector
			const PROPERTY  = 'data-slide-title'; //Name of the attribute in that tag uou want to detect
			const WORD_TYPE = Weglot\Client\Api\Enum\WordType::TEXT; //Do not change unless it's not text but a media URL like a .pdf file for example.
		}
		$dom_checkers[] = '\Div_Slide_Title'; //You add your class to the list because you want the parser to also detect it
	}
	return $dom_checkers ;
}

```

### weglot\_get\_regex\_checkers

This filter is a bit more tricky to understand but also very powerful. It allows you to give a Regex to the parser in order for it to detect the text you want in your DOM.

| Argument         | Type  | Description           |
| ---------------- | ----- | --------------------- |
| $regex\_checkers | array | Used **RegexChecker** |

**$regex\_checkers** is an array that contains the **RegexChecker** objects, which determine what elements to treat as well as the type of data it is (TEXT, HTML or JSON).

```php
\Weglot\Parser\Check\Regex\RegexChecker( $regex = '' , $type = '' , $var_number = 0 , $keys = array() );
```

The **RegexChecker** constructor settings are as follows:

* **$regex**: Regex that target the element you want to be parsed
* **$type**: String variable that determines the type of the targeted element ('TEXT', 'HTML' or 'JSON')
* **$var\_number**: Denotes the number of variable targeted by the regex that you want to parse
* **$key**: If the element being treated is a ‘JSON’ element, this variable allows you to specify keys to translate
* **$decode\_function**: Function callback applied to intercepted content
* **$encode\_function**: Function callback applied to returned content

  <br>

#### Use case

Below are several examples of content that will not be translated by default by Weglot, but that you can translate using this filter

```markup
<script type="text/javascript">
    jQuery(document).ready(function ($) {

        // Untranslate text
        alert("My untranslate text");
        console.log("My untranslate text", "My untranslate text");

        // Untranslate HTML
        $("body").append("<p>My <strong>untranslate</strong> text</p>");

        // Untranslate JSON values
        var myJson = {
            "MyKey1": {
                "MyKey1-1": "My untranslate text",
                "MyKey1-2": "My untranslate text"
            },
            "MyKey2": "My untranslate text",
            "some_array" : [ "Hello" , "Translate this"]
        };

    });
</script>
<script type="text/template">"\r\n\t\t\t<div class=\"sticky-sidebar\">\r\n\t\t\t\t\ ....  \t\t<\/div>\r\n\r\n\t\t\t"</script>
<div data-escapedjson="{&quot;schema&quot;:{&quot;content&quot;:{&quot;desktop&quot;:&quot;&lt;h1&gt;Translate it&lt;\/h1&gt;&quot;}}}"><h1>This, no problem</h1></div>
```

In order for the content in this example to be interpreted, and then translated, we will use the **weglot\_get\_regex\_checkers** filter as followed.

```php
<?php

add_filter( 'weglot_get_regex_checkers', 'custom_weglot_add_regex_checkers' );

function custom_weglot_add_regex_checkers( $regex_checkers ) {

    // Text
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#alert\(\"(.*)\"\);#', 'TEXT', 1 );
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#console\.log\(\"(.*?)\",.*?\"(.*?)\"\);#', 'TEXT', 2 );

    // HTML
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#\$\(\"body\"\)\.append\(\"(.*)\"\);#', 'HTML', 1 );

    // JSON
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#var myJson = ((.|\s)+?);#', 'JSON', 1, array('MyKey1-1', 'MyKey1-2', 'MyKey2' , 'some_array') );
    
    //More advanced : HTML after a callback
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( "#<script type=\"text\/template\">(.*)<\/script>#", "HTML", 1, array(),"json_decode" , "json_encode");
    
    //More advanced : JSON after a callback
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#data-escapedjson="((.|\s)+?)"#', 'JSON', 1, array(), "html_entity_decode" , "htmlentities" );
    
    //More advanced : JSON after a callback, version with another regex
    $regex_checkers[] = new \Weglot\Parser\Check\Regex\RegexChecker( '#data-escapedjson="(.*)"#', 'JSON', 1, array(), "html_entity_decode" , "htmlentities" );
    
    return $regex_checkers;
}
```

### weglot\_add\_json\_keys

Weglot also translates JSON response but not all values. Use this filter to target specific values.

| Argument | Type  | Description     |
| -------- | ----- | --------------- |
| $keys    | array | Array of string |

The JSON values translated by default are:

* Value with key: "name"
* Value with key: "description"
* Value in HTML format

#### Use case&#x20;

You may come across values used in your JSON that are not translated by default.Here’s an example using the **message** value:

```javascript
{
    "name":"My name value, already translated", //Will be translated by default because key is "name"
    "description":"My description value, already translated", //Will be translated by default because key is "description"
    "my_custom_key":"<p>HTML content, already translated</p>", //Will be translated by default because we detect this is HTML
    "message":"My message value to translate!" //This will not be translated and you will need to use the filter
}
```

To do this, we use **weglot\_add\_json\_keys** filter.

```php
<?php

add_filter( 'weglot_add_json_keys',  'custom_weglot_add_json_keys' );
function custom_weglot_add_json_keys(  $keys  ){ //$keys already contains "name" and "description"
    $keys[]  =  'message'; //This tells Weglot to also look for key "message" when detecting content to translated
    return $keys;
}
```

Also, note that if a URL is detected in a value of the JSON, it will be replaced by the URL with the language code if and only if it is one of the `redirecturl` , `url` ,  `link` . For example, if you original JSON is

```javascript
{
    "url" : "https://mysite.com/contact",
    "redirectURL" : "https://mysite.com/contact",
    "niceURL" : "https://mysite.com/contact",
    "name" : "This is my name"
}
```

The translated response would be

```javascript
{
    "url" : "https://mysite.com/fr/contact",
    "redirectURL" : "https://mysite.com/fr/contact",
    "niceURL" : "https://mysite.com/contact",
    "name" : "C'est mon nom"
}
```

Adding keys to check when replacing URL will be done **weglot\_ajax\_replace\_urls**

If you want to remove some defaults keys you can use the filter **`list_json_ld_keys`**&#x20;

```php
add_filter( 'list_json_ld_keys',  'custom_weglot_add_json_keys' );
function custom_weglot_add_json_keys(  $keys  ){
    $key = array_search('name', $keys);
    if ($key !== false) {
        unset($keys[$key]);
    }
    $keys[]  =  'message';
    return $keys;
}
```

Through this filter, it is possible to remove existing keys and add new ones. In this example, the `name` key is explicitly removed from the array using `array_search()` and `unset()`. After that, a new key called `message` is added to the list.

This approach allows you to customize the structure of the JSON-LD data by excluding unwanted keys (such as `name`) and including alternative ones depending on your needs.

### weglot\_words\_translate

Use this filter to target a specific word literally in your source code

| Argument | Type  | Description     |
| -------- | ----- | --------------- |
| $words   | array | Array of string |

You can add words that are present in your HTML page but not translated. It's useful when a word is not being translated by Weglot because it's inside a JavaScript for example and you can't really use other filters.

#### Use case

```php
<?php

add_filter( 'weglot_words_translate', 'custom_weglot_words_translate' );
function custom_weglot_words_translate( $words ){        
    $words[] = "Monday";       
    $words[] = "Tuesday";    
    $words[] = "Nice to meet you";           
    return $words;
}
```

This filter will tell Weglot to look literally for words in your source code, then translate it and literally replace these words in your source code. Be very careful to not enter keywords as "head" "body" for example as it could break your page.

### weglot\_html\_treat\_page

Use this filter when there is no other solution : It's a very powerful filter that allows you to make manual edition on the final translated DOM in PHP.

| Argument | Type   | Description                     |
| -------- | ------ | ------------------------------- |
| $html    | string | HTML content of translated page |

#### Use case 1

The following code replaces all of the “<https://codex.wordpress.org/>” links with “<https://codex.wordpress.org/fr:Accueil>” in the translated versions.

```php
<?php

add_filter( 'weglot_html_treat_page', 'custom_weglot_html_treat_page_1' );
function custom_weglot_html_treat_page_1( $html ) {

    $s = 'https://codex.wordpress.org/';
    $r = 'https://codex.wordpress.org/fr:Accueil';

    $html = str_replace( $s, $r, $html );
    return $html;
}
```

#### Use case 2

In this example, the replacement occurs according to the chosen language.

```php
<?php

add_filter( 'weglot_html_treat_page', 'custom_weglot_html_treat_page_2' );
function custom_weglot_html_treat_page_2( $html ) {

    $search = 'https://codex.wordpress.org/';

    switch ( weglot_get_current_language() ) {
        case 'fr':
            $html = str_replace( $search, 'https://codex.wordpress.org/fr:Accueil', $html );
            break;
        case 'pt':
            $html = str_replace( $search, 'https://codex.wordpress.org/pt:Página_Inicial', $html );
            break;
    }

    return $html;
}

```

{% hint style="info" %}
Note, you can use `weglot_render_dom` instead, which is the same except there is the HTML of the button and the links are already translated.
{% endhint %}

### Dynamic Selectors

**1. Enabling Dynamic Content Translation**

To enable the use of dynamic content translation on your website, add the following filter:

```php
add_filter( 'weglot_translate_dynamics', '__return_true' );
```

This filter allows Weglot to handle the translation of dynamic content, which may change after the initial page load (e.g., content updated via JavaScript).

2. **Defining Custom Selectors**

Next, define the selectors that Weglot should use to identify dynamic content. We achieve this by creating a custom function:

```php
function custom_weglot_dynamics_selectors( $default_dynamics ) {
    return [
        ['value' => '.wp-block-woocommerce-cart'],
        ['value' => '.qodef-m-content'],
        ['value' => '.wp-block-woocommerce-checkout'],
    ];
}
```

* The function `custom_weglot_dynamics_selectors()` returns an array of CSS selectors. These selectors specify which parts of your website's content should be treated as dynamic.
* For example, `.wp-block-woocommerce-cart` and `.wp-block-woocommerce-checkout` target WooCommerce cart and checkout blocks.

**3. Applying Custom Selectors to Weglot Filters**

To use the custom selectors defined above, apply them to both the dynamic and whitelist selector filters:

```php
add_filter( 'weglot_dynamics_selectors', 'custom_weglot_dynamics_selectors' );
add_filter( 'weglot_whitelist_selectors', 'custom_weglot_dynamics_selectors' );
```

* `weglot_dynamics_selectors`: This filter allows Weglot to recognize dynamic content based on the selectors you defined.
* `weglot_whitelist_selectors`: This filter specifies elements that Weglot should always translate, ensuring that the specified content is included in translations.

By using the same function for both filters, you can reuse the list of selectors for both dynamic and whitelisted content.

4. **Specifying URLs for Applying Custom Translations**

Lastly, define where your custom dynamic translations should be applied. By default, this is set to an empty value, but you can configure it to apply to all URLs or a specific list:

```php
add_filter( 'weglot_allowed_urls', function( $urls ) {
    return 'all'; // This will make $allowed_urls === 'all'
});
```

* `weglot_allowed_urls`: This filter determines on which URLs the custom translation rules will be applied.
* Setting the value to `'all'` ensures that your custom selectors will work on every page of your website. You can also pass an array of specific URLs if you only want the rules to apply to certain pages.

5. #### External JavaScript Dependency for Custom Code

   When using the dynamic code, it requires an external JavaScript script to be loaded correctly for it to function as expected.

   **Key Considerations:**

   1. **Script Loading**:\
      If the external script fails to load or is not included properly on the page, the custom code will not work. Make sure that the script is loaded before the code is executed.
   2. **`defer` Attribute Issues**:\
      If the external script is loaded with the `defer` attribute, it may cause unexpected behavior or delays, especially if your custom code depends on the script being fully available before execution.
   3. **Solution**:\
      To ensure that your custom code works seamlessly, you may need to **exclude this specific script from being deferred**. This way, the script will load immediately and be available when your code is executed, avoiding potential timing issues.

   **How to Exclude the Script from `defer`**

   * Check how your scripts are being loaded (especially if you’re using a plugin or optimization tool that automatically adds the `defer` attribute).
   * Ensure the script tag for your external JavaScript looks like this:

   ```html
   <script src="https://example.com/your-script.js"></script>
   ```

   \
   By excluding the `defer` attribute, the script will be executed as soon as it is downloaded, ensuring your custom code runs without issues.
