# Developer Documentation

Here you can find all resources about our integrations or the API reference.

## Integrations

* WordPress : All hooks & filters in the WordPress plugin.
* Javascript : All functions you call when you are using the JS lib.

## Reference

You can find the [API reference](/api/reference) if you want to make HTTP Request directly.

## Slack

You can join our [**Weglot Community**](https://communityinviter.com/apps/weglot-community/weglot-community) Slack where we would be happy to get direct feedback and provide tips


# Requirements

## Requirements

Before installing Weglot, make sure your environment meets the minimum requirements. They depend on the plugin version you're running.

### Weglot 6.1 and later

| Requirement              | Minimum | Tested up to |
| ------------------------ | ------- | ------------ |
| WordPress                | 5.9     | 7.0          |
| PHP                      | 7.4     | —            |
| WooCommerce *(optional)* | 4.0     | 9.5          |

### Weglot before 6.1

| Requirement              | Minimum | Tested up to |
| ------------------------ | ------- | ------------ |
| WordPress                | 4.5     | 6.9          |
| PHP                      | 7.4     | —            |
| WooCommerce *(optional)* | 4.0     | 9.5          |

{% hint style="info" %}
WooCommerce is only required if you translate a WooCommerce store.
{% endhint %}

{% hint style="success" %}
**Next step:** once your environment is ready, follow the [Getting Started](/wordpress/getting-started) guide to install and configure the plugin.
{% endhint %}


# Getting Started

Starting with the Weglot WordPress plugin

## Getting Started

### Introduction

Weglot has built a powerful WordPress plugin that integrates in your WordPress website and make it multilingual in a few minutes.

What does Weglot plugin do exactly ?

1. It creates URL for each languages, like `/fr/about/` or `/es/about/` for instance (but doesn't create actual pages in WordPress backend)
2. On these URL, it returns the translated content
3. It adds a language button on the page and the `hreflang` tags in the `<head>` section of your page for SEO.

### Getting started

To start, install [Weglot Translate](https://wordpress.org/plugins/weglot/) plugin directly from the directory.

In the settings page, configure the 3 mandatory settings :

* **API Key** : You get an API key in your account. If you don't have one, you can [create your account](https://dashboard.weglot.com/register-wordpress).
* **Original Language** : The original language of your WordPress website.
* **Destination Languages** : The languages you want your website to be translated into.

Save the settings and you are done. You will see the language button appear on your website.

{% hint style="success" %}
**Next step:** head over to [Plugin settings](/wordpress/plugin-settings) to control what gets translated (emails, search, specific URLs or blocks) and customize the language switcher.
{% endhint %}


# Plugin settings

## Plugin settings

Once the plugin is set up, a few built-in options let you fine-tune **what** gets translated and **how** the language switcher looks. You'll find them in the plugin's **Advanced** and **Appearance** tabs.

### Translate emails

When enabled, Weglot translates the emails sent by WordPress (through the `wp_mail` function) — both the **subject** and the **body** — into the language of the visitor who triggered them. Typical examples are a WooCommerce order confirmation or a contact-form notification sent to your customer.

The visitor's language is detected from the current request, or from the page they were on when the email was sent.

{% hint style="info" %}
Emails sent to your **site admin address are not translated** by default — they stay in your original language, which is usually what you want for internal notifications.
{% endhint %}

### Translate search

When enabled, your visitors can search your site in their own language. Weglot translates their search term back into your original language, runs the WordPress search on your original content, and returns the results translated.

This means you don't need to store translated content in your database for search to work.

### Exclude URLs

By default, every page of your site is translated. Use **Exclude URLs** to leave some pages untranslated. Rules are managed from your Weglot dashboard and support several matching modes:

* **Contains** — the path contains a given text (default)
* **Is exactly** — the path matches exactly
* **Starts with** / **Ends with**
* **Matches regex** — for advanced patterns

For example, to translate **only your homepage** (exclude every path except `/`), use a "Matches regex" rule with: `[^/]`

{% hint style="info" %}
Rules are matched against the URL **path** only — the query string (everything after `?`) is ignored.
{% endhint %}

### Exclude blocks

Sometimes you want to keep part of a page untranslated — a customer-review area, a code snippet, a brand name. With **Exclude blocks** you provide a CSS selector, and Weglot adds a `data-wg-notranslate` attribute to the matching element. Everything inside it is left as-is.

For example, excluding `.product-description` produces:

```markup
<h1 class="product-title">Mon super article</h1> <!-- translated -->
<p class="product-description" data-wg-notranslate>My awesome article</p> <!-- not translated -->
```

### Language switcher

Weglot adds a language button to your site. From the **Appearance** tab you can customize how it looks:

* **Dropdown or inline** — show the languages in a dropdown menu or side by side
* **With flags** — show a flag next to each language, and choose its shape: rectangle (mat or shiny), square or circle
* **With name** — show the language name, either its full local name (e.g. *Français*) or its ISO code (e.g. *FR*)
* **Custom CSS** — override the switcher's styling with your own rules

#### Positioning the switcher

You can place the language button wherever you want:

* **Default** — automatically added at the bottom-right of every page
* **In a menu** — add a "Weglot Translate" item from *Appearance → Menus*
* **In a widget area** — from *Appearance → Widgets*
* **Anywhere via shortcode** — drop `[weglot_switcher]` into a page, post or template


# Helpers Functions

All Weglot functions you can call in WordPress to get informations

## Helpers Functions

Weglot plugin is exposing functions that can be called in your code.

To see the source code of all available functions, you can go to the file : **weglot-functions.php.**

{% hint style="warning" %}
Make sure your plugin's version is > 3.0
{% endhint %}

#### weglot\_get\_service

```php
weglot_get_service( string $service )
```

Return a Weglot service.

#### weglot\_get\_options

```php
weglot_get_options()
```

Return all Weglot options.

#### weglot\_get\_option

```php
weglot_get_option( string $key )
```

Return Weglot option by key.

#### weglot\_get\_original\_language

```php
weglot_get_original_language()
```

Return the original language code (2-letter internal code, e.g. `en`).

#### weglot\_get\_current\_language

```php
weglot_get_current_language()
```

Return the current language **internal** code (2-letter code, e.g. `en`). This is the code Weglot uses internally, not the one that may appear in your URLs.

#### weglot\_get\_current\_language\_custom

```php
weglot_get_current_language_custom()
```

Return the current language **external** code — the custom language code configured in your Weglot dashboard (falls back to the standard code when none is set). Use this when you need the code as it appears to your visitors.

{% hint style="info" %}
`weglot_get_current_language_code_from_custom_language()` is an alias that returns the exact same value.
{% endhint %}

#### weglot\_get\_destination\_languages

```php
weglot_get_destination_languages()
```

Return an array of public destination language keys.

#### weglot\_get\_request\_url\_service

```php
weglot_get_request_url_service()
```

Return weglot request URL service.

#### weglot\_get\_languages\_available

```php
weglot_get_languages_available()
```

Return an array of all languages objects available.

#### weglot\_get\_button\_selector\_html

```php
weglot_get_button_selector_html( string $add_class = '' )
```

Return the language's selector button HTML in string format.

#### weglot\_get\_exclude\_urls

```php
weglot_get_exclude_urls()
```

Return an array of all excluded URLs.

#### weglot\_get\_translate\_amp\_translation

```php
weglot_get_translate_amp_translation()
```

Return `true` if amp pages translation is activated.

#### weglot\_get\_current\_full\_url

```php
weglot_get_current_full_url()
```

Return a string of current URL.

#### weglot\_create\_url\_object

```php
weglot_create_url_object( string $url )
```

Return a `Weglot\Util\Url` object for the given URL. Call `->getForLanguage( $language )` on it to get the URL translated into a specific language.

#### weglot\_is\_eligible\_url

```php
weglot_is_eligible_url( string $url )
```

Return `true` if `$url` is an eligible URL.

#### weglot\_get\_api\_key

```php
weglot_get_api_key()
```

Return a string of private API key.

#### weglot\_has\_auto\_redirect

```php
weglot_has_auto_redirect()
```

Return `true` if redirect users based on their browser language option is activated.

#### weglot\_get\_full\_url\_no\_language

```php
weglot_get_full_url_no_language()
```

Return a string of current URL without the language key.

#### weglot\_get\_postid\_from\_url

```php
weglot_get_postid_from_url()
```

Return the WordPress post ID matching the current URL, or `0` if none is found.

#### weglot\_get\_rest\_current\_url\_path

```php
weglot_get_rest_current_url_path()
```

Return a string of rest current URL path.


# Hooks

All filters exposed by Weglot


# Translations Hooks

WordPress Filters relating to detecting & translating words

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.

### Extend what gets detected

#### weglot\_get\_dom\_checkers

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

| Argument       | Type  | Description                                                                       |
| -------------- | ----- | --------------------------------------------------------------------------------- |
| $dom\_checkers | array | 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 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.

```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 you 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(), $callback = null, $revert_callback = null );
```

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
* **$keys**: If the element being treated is a 'JSON' element, this variable allows you to specify keys to translate
* **$callback**: Function callback applied to intercepted content
* **$revert\_callback**: Function callback applied to returned content

**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\_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\_preserve\_words\_enabled / weglot\_preserve\_words\_list

The mirror image of `weglot_words_translate`: use these two filters to keep specific words **untranslated**, wherever they appear on the page (brand names, product references, etc.).

* `weglot_preserve_words_enabled` — return `true` to turn the feature on (default `false`).
* `weglot_preserve_words_list` — return the array of literal words to preserve (default empty). It also receives the page content as a second argument if you need to build the list dynamically.

```php
<?php

add_filter( 'weglot_preserve_words_enabled', '__return_true' );

add_filter( 'weglot_preserve_words_list', 'custom_weglot_preserve_words' );
function custom_weglot_preserve_words( $words ) {
    $words[] = "Weglot";
    $words[] = "iPhone";
    return $words;
}
```

#### weglot\_get\_parser\_ignored\_nodes

Change the list of DOM node types the parser never descends into (so their content is never detected nor translated). The filter receives the default list of tag names provided by the parser and must return the modified list.

```php
<?php

add_filter( 'weglot_get_parser_ignored_nodes', 'custom_weglot_ignored_nodes' );
function custom_weglot_ignored_nodes( $nodes ) {
    $nodes[] = 'my-custom-tag';
    return $nodes;
}
```

### Whitelist & exclude blocks

By default, everything on a page is translated except the blocks you exclude. These two filters give you both sides of that control from your code.

#### weglot\_parser\_whitelist

This filter flips the page into **opt-in mode**. By default Weglot translates the whole page; when the array returned by this filter is **not empty**, Weglot adds a `wg-mode-whitelist` attribute to the `<body>` tag and translates **only** the blocks matching the listed CSS selectors — everything else is left untranslated.

```php
<?php

add_filter( 'weglot_parser_whitelist', 'custom_whitelist' );
function custom_whitelist( $whitelist ) {
    $whitelist[] = '.product-title';
    return $whitelist;
}
```

You can whitelist more than one block:

```php
<?php

add_filter( 'weglot_parser_whitelist', 'custom_whitelist' );
function custom_whitelist( $whitelist ) {
    $whitelist[] = '.product-title';
    $whitelist[] = '.product-description';
    return $whitelist;
}
```

{% hint style="warning" %}
Do not confuse `weglot_parser_whitelist` (server-side PHP parser, described here) with `weglot_whitelist_selectors` (client-side JavaScript engine, in the [Client-side (dynamic) translation](#client-side-dynamic-translation) section). They share the word "whitelist" but operate in different layers.
{% endhint %}

#### weglot\_exclude\_blocks

The opposite of the whitelist: add CSS selectors whose content must **not** be translated. Weglot marks every matching element with a `data-wg-notranslate` attribute.

```php
<?php

add_filter( 'weglot_exclude_blocks', 'custom_weglot_exclude_blocks' );
function custom_weglot_exclude_blocks( $blocks ) {
    $blocks[] = '.customer-reviews';
    return $blocks;
}
```

{% hint style="info" %}
Weglot always appends a set of built-in selectors to this list (for example `#wpadminbar`, `.material-icons`, and WooCommerce/Query Monitor selectors when those plugins are active). Your custom selectors are added on top of them.
{% endhint %}

### JSON responses

#### 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**

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 your 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 is done with **weglot\_ajax\_replace\_urls**.

If you want to remove some defaults keys you can use the filter **`list_json_ld_keys`**

```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.

### Escaping content from translation

These filters "shield" parts of your markup from the parser: their content is tokenized before translation and restored afterwards. Use them when a script, template or attribute must be left exactly as-is.

The following filters take an **array** and return the modified array:

| Filter                          | Default                                                                       | Purpose                                                      |
| ------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `weglot_escape_attributes`      | `[]`                                                                          | HTML attribute names whose values must not be translated     |
| `weglot_escape_script_types`    | `text/template`, `text/html`, `text/x-template`, `text/x-handlebars-template` | `<script type="…">` values whose content is escaped          |
| `weglot_escape_script_ids`      | `tmpl-*`, `nf-*`, `*-js-extra`                                                | `<script>` id patterns to escape (`*` wildcard supported)    |
| `weglot_escape_script_classes`  | `[]`                                                                          | `<script>` class patterns to escape (`*` wildcard supported) |
| `weglot_escape_script_contains` | `[]`                                                                          | Escape scripts whose inner content matches a pattern         |

The following filters are simple **on/off toggles** (return `true` to enable, default `false`):

| Filter                            | Purpose                                              |
| --------------------------------- | ---------------------------------------------------- |
| `weglot_escape_script_templates`  | Escape `<script>` template blocks before translation |
| `weglot_escape_vue_js`            | Escape Vue.js attributes                             |
| `weglot_escape_attribute_in_html` | Escape configured attributes in HTML responses       |
| `weglot_escape_attribute_in_json` | Escape configured attributes in JSON responses       |

```php
<?php

// Never translate the value of a data-config attribute
add_filter( 'weglot_escape_attributes', function( $attributes ) {
    $attributes[] = 'data-config';
    return $attributes;
} );
```

### Modifying the final output

These filters let you edit the fully translated response, right before it is sent to the browser. Use them as a last resort, when no detection filter fits.

#### weglot\_html\_treat\_page

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;
}
```

#### weglot\_json\_treat\_page / weglot\_xml\_treat\_page

Same idea as `weglot_html_treat_page`, but for the other response types. Each one receives the final translated string and must return the modified string:

* `weglot_json_treat_page` — final translated **JSON** response.
* `weglot_xml_treat_page` — final translated **XML** response (for example a sitemap).

```php
<?php

add_filter( 'weglot_xml_treat_page', function( $xml ) {
    // edit the translated sitemap here
    return $xml;
} );
```

#### weglot\_render\_dom

Same as `weglot_html_treat_page`, except the language button HTML is already included and the links are already translated. Handy when you need to act on the exact markup that will be rendered.

### Client-side (dynamic) translation

{% hint style="info" %}
All the filters in this section only take effect when `weglot_translate_dynamics` returns `true`. They configure Weglot's front-end **JavaScript** library — not the server-side PHP parser — and are used to translate content that changes after the initial page load.
{% endhint %}

**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. Proxifying iframes and URLs**

Two more front-end filters let you route content through Weglot when needed:

* `weglot_proxify_iframes` — list iframe selectors (same `['value' => '…']` shape as above) whose content should be handled by the JS library. Default empty.
* `weglot_proxify_urls` — list resource URLs that should be routed through the Weglot proxy on translated pages. Default empty.

**6. 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.

### Advanced parser tuning

Low-level filters you should only need in edge cases (very large pages, PCRE limits, custom parser configuration). Each returns the same type it receives.

| Filter                          | Type   | Default                | Purpose                                                                                               |
| ------------------------------- | ------ | ---------------------- | ----------------------------------------------------------------------------------------------------- |
| `weglot_parser_config_provider` | object | `ServerConfigProvider` | Swap the parser's ConfigProvider (must implement `ConfigProviderInterface`)                           |
| `weglot_regex_tags_limit`       | int    | `200000`               | Max tag length before `data-link` URL rewriting is skipped (only applied if a callback is registered) |
| `weglot_length_replace_a`       | int    | `1500`                 | Max URL length considered for `<a>` link replacement; longer URLs are skipped to avoid PCRE errors    |
| `weglot_length_replace_tags`    | int    | `2000`                 | Max surrounding-tag length for link replacement; longer tags are skipped                              |


# Use cases


# Lang attribute

Modify the lang attribute on html tag

You can modify your own `lang` attribute (or any other element in the DOM) using the `weglot_render_dom` filter.

```php
add_filter( 'weglot_render_dom', 'prefix_weglot_render_dom' );
function prefix_weglot_render_dom( $dom ) {
	$dom = str_replace( 'lang="en-US"', 'lang="en-US-wg"', $dom );
	return $dom;
}
```


# Translate link

Add method to translate specifix link

By default, Weglot translates links based on a set of built-in patterns. In the example below, we want to translate the URL held in a `data-link2` attribute. We use the `weglot_get_replace_modify_link` filter to register a new pattern, then provide the function that rewrites it.

```php
add_filter( 'weglot_get_replace_modify_link', 'custom_weglot_get_replace_modify_link' );
function custom_weglot_get_replace_modify_link( $data ) {
	$data['datalink2'] = '/<([^\>]+?)?data-link2=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/';
	return $data;
}

function replace_datalink2( $translated_page, $current_url, $quote1, $quote2, $sometags = null, $sometags2 = null ) {
	$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );
	$replace_url_Service = weglot_get_service( 'Replace_Link_Service_Weglot' );
	$current_language = $request_url_services->get_current_language();
	$translated_page  = preg_replace( '/<' . preg_quote( $sometags, '/' ) . 'data-link2=' . preg_quote( $quote1 . $current_url . $quote2, '/' ) . '/', '<' . $sometags . 'data-link2=' . $quote1 . $replace_url_Service->replace_url( $current_url, $current_language ) . $quote2, $translated_page );
	return $translated_page;
}
```

{% hint style="info" %}
**How the pattern maps to a function.** Each key you add to the `$data` array (here `datalink2`) is resolved to a global function named `replace_<key>` (here `replace_datalink2`). Weglot calls it for every match with these arguments, in order: `$translated_page`, `$current_url`, `$quote1`, `$quote2`, `$sometags`, `$sometags2`. Your function must return the (possibly modified) page. You can change the resolved function name with the `weglot_modify_link_replace_function` filter.
{% endhint %}


# How Weglot handles link translation and exclusions

Weglot automatically translates both the **URL** of a link and its **text label**, based on the current language. This page explains the default behavior and how to control each part independently.

### Default behavior

Take this link:

```html
<a id="my-link" href="https://weglot.com" title="Weglot website">this is my link label</a>
```

On the French version of your site, Weglot outputs:

```html
<a id="my-link" href="https://weglot.com/fr/" title="Weglot website">ceci est le label de mon lien</a>
```

* The **label** (`this is my link label`) is translated.
* The **URL** is automatically adapted to include the language code (`/fr/`).

### Excluding a link from translation

If you exclude the link (for example with the `#my-link` selector in your exclusion rules), the **label stays untranslated** — but the **URL is still adapted** to include the language code:

```html
<a id="my-link" href="https://weglot.com/fr/" title="Weglot website">this is my link label</a>
```

This is expected: excluding a block prevents its text from being translated, while link URLs are rewritten by a separate mechanism.

### Keep the URL untranslated but still translate the label

Sometimes you want the opposite: keep the link URL exactly as-is (no language code) while still translating the label. Add the `wg-excluded-link` attribute to the tag:

```html
<a id="my-link" href="https://weglot.com" title="Weglot website" wg-excluded-link>this is my link label</a>
```

Result in French:

```html
<a id="my-link" href="https://weglot.com" title="Weglot website">ceci est le label de mon lien</a>
```

* The URL stays `https://weglot.com` (no `/fr/`).
* The label is still translated.

Use this when a specific URL must stay untouched (an external tracking link, a file, a third-party endpoint…) while still giving your visitors a localized link text.


# Implementing Custom Link Translation

By default, Weglot translates links based on built-in patterns. In some cases you may want to build a translated link yourself. Below is an example that returns the URL of a WooCommerce product in the current language. You can adapt it further — for instance to target a specific language instead of the current one.

```php
function weglot_get_current_full_product_by_id( $product_id ) {
	$post = get_post( $product_id );
	if ( ! $post || $post->post_type !== 'product' ) {
		return '';
	}
	$product_url = get_permalink( $product_id );
	return weglot_create_url_object( $product_url )->getForLanguage( weglot_get_request_url_service()->get_current_language() );
}
echo weglot_get_current_full_product_by_id( 17 );
```


# Wp-rocket Lazyload

Modify attr when Lazyloading is activate on wp-rocket plugins

When lazy-loading is enabled (for example by WP Rocket), image URLs are stored in `data-lazy-src` / `data-lazy-srcset` attributes instead of `src` / `srcset`. You can tell the Weglot parser to detect and translate those attributes with the `weglot_get_dom_checkers` filter.

```php
add_filter( 'weglot_get_dom_checkers', 'weglot_dom_check_data_lazy_src' );
function weglot_dom_check_data_lazy_src( $dom_checkers ) {

	if ( ! class_exists( 'Img_Data_Lazy_Src' ) ) {
		class Img_Data_Lazy_Src extends Weglot\Parser\Check\Dom\AbstractDomChecker {
			const DOM       = 'img';
			const PROPERTY  = 'data-lazy-src';
			const WORD_TYPE = Weglot\Client\Api\Enum\WordType::IMG_SRC;
		}
		$dom_checkers[] = '\Img_Data_Lazy_Src';
	}

	if ( ! class_exists( 'Source_Data_Lazy_SrcSet' ) ) {
		class Source_Data_Lazy_SrcSet extends Weglot\Parser\Check\Dom\AbstractDomChecker {
			const DOM       = 'source';
			const PROPERTY  = 'data-lazy-srcset';
			const WORD_TYPE = Weglot\Client\Api\Enum\WordType::IMG_SRC;
		}
		$dom_checkers[] = '\Source_Data_Lazy_SrcSet';
	}

	return $dom_checkers;
}
```


# Deactivate Weglot on Elementor

Deactivate Weglot (translate and add swtcher(s)) when you're on elementor webview

Weglot also runs inside Elementor's editor and preview (translating content and injecting switchers), which is not always desirable. To disable Weglot while Elementor is loaded, hook `elementor/init` and turn translation off:

```php
add_action( 'elementor/init', 'weglot_deactivate_elementor' );
function weglot_deactivate_elementor() {
	add_filter( 'weglot_active_translation', '__return_false' );
}
```


# Weglot translate on Elementor

With this code, we force translation of content generate by elementor using the elementor/frontend/the\_content filter

With the code below, we force the translation of content generated by Elementor, using the `elementor/frontend/the_content` filter.

```php
use Weglot\Parser\Parser;
use Weglot\Parser\ConfigProvider\ServerConfigProvider;

function weglot_content_check( $content ) {

	$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );
	$parser_services      = weglot_get_service( 'Parser_Service_Weglot' );
	$generate_switcher    = weglot_get_service( 'Generate_Switcher_Service_Weglot' );
	$replace_url_services = weglot_get_service( 'Replace_Url_Service_Weglot' );
	$current_language     = $request_url_services->get_current_language()->getExternalCode();
	$original_language    = weglot_get_original_language();

	$content = $generate_switcher->generate_switcher_from_dom( $content );
	if ( $original_language == $current_language ) {
		return $content;
	}

	$config  = new ServerConfigProvider();
	$client  = $parser_services->get_client();
	$parser  = new Parser( $client, $config, [] );
	$content = $parser->translate( $content, $original_language, $current_language );
	$content = $replace_url_services->replace_link_in_dom( $content );

	return $content;
}
add_action( 'elementor/frontend/the_content', 'weglot_content_check' );
```


# Language Selector Styling

Adding your own CSS code or HTML button

#### Override language selector CSS

You can add your own CSS rules to customize the language button. Weglot automatically adds a button to your page, which is either a dropdown or a list and looks like this:

{% tabs %}
{% tab title="Dropdown" %}

```markup
<aside data-wg-notranslate class="country-selector weglot-dropdown weglot-default weglot-invert">
    <input id="weglot_choice" type="checkbox" name="menu">
    <label for="weglot_choice" class="wgcurrent wg-li weglot-flags flag-0 en" data-code-language="en">
        <span>EN</span>
    </label>
    <ul>
        <li class="wg-li weglot-flags flag-0 fr" data-code-language="fr">
            <a data-wg-notranslate href="http://example.com/">FR</a>
        </li>
    </ul>
</aside>
```

{% endtab %}

{% tab title="List" %}

```markup
<aside data-wg-notranslate class="country-selector weglot-inline weglot-default weglot-invert">
    <input id="weglot_choice" type="checkbox" name="menu">
    <label for="weglot_choice" class="wgcurrent wg-li weglot-flags en" data-code-language="en">
        <span>English</span>
    </label>
    <ul>
        <li class="wg-li weglot-flags fr" data-code-language="fr">
            <a data-wg-notranslate href="http://example.com/fr/">Français</a>
        </li>
    </ul>
</aside>
```

{% endtab %}
{% endtabs %}

You can use these classes to add your own rules. For example, add this in "Override CSS" to make the language name uppercase:

```css
.country-selector a {
    text-transform: uppercase;
}
```

#### Override CSS on the WordPress back office

You can add your custom CSS rules directly from your WordPress back office. To do that, log in to your WordPress and go to: **Weglot > Language button design (Optional) > Override CSS**

#### Override CSS using a WordPress hook

This filter lets you add custom CSS by default, without going through the settings.

```php
<?php

add_filter( 'weglot_css_custom_inline', 'custom_weglot_css_custom_inline' );
function custom_weglot_css_custom_inline( $css_custom ){     
    $css_custom .= '.country-selector { background-color: red; }'; 
    return $css_custom;
}
```

#### Don't load the Weglot CSS file

By default, the Weglot plugin loads the stylesheet `/wp-content/plugins/weglot/dist/css/front-css.css`. If you would prefer not to load it, you can dequeue it with the `wp_enqueue_scripts` action:

```php
<?php

add_action( 'wp_enqueue_scripts', 'custom_weglot_dequeue_style' );
function custom_weglot_dequeue_style() {
    wp_dequeue_style( 'weglot-css' );
}
```

#### Override the language selector HTML markup

The Weglot plugin exposes a filter that lets you modify the HTML structure of your language-switch button. See the reference: [weglot\_button\_html](/wordpress/helpers-functions-1/weglot_button_html).

**Hook parameters**

* `$button_html`: string containing the switcher's HTML before it is rendered.
* `$add_class`: string containing the classes (space-separated) related to the switcher's layout context and options.

**Example: add code before/after the button**

The example below adds HTML before and/or after the button (you can also run `preg_replace()` on the selector's HTML).

```php
<?php

add_filter( 'weglot_button_html', 'custom_weglot_button_html', 10, 2 );
function custom_weglot_button_html( $button_html, $add_class ) {

	$button_html = '<div style="border: 1px solid red;"><p>Choose your language:</p>' . $button_html . '</div>';

	return $button_html;
}
```

**Example: rebuild the language selector from scratch**

If you'd like to make major changes to the HTML structure of your language button, you can start from the code below.

{% hint style="info" %}
This example mirrors the plugin's built-in button. It is a starting point — keep an eye on it across plugin updates, as the internal markup can evolve.
{% endhint %}

```php
<?php

add_filter( 'weglot_button_html', 'custom_weglot_button_html' );
function custom_weglot_button_html( $html, $add_class = '' ) {

	$current_this        = weglot_get_service( 'Button_Service_Weglot' );
	$option_service      = weglot_get_service( 'Option_Service_Weglot' );
	$request_url_service = weglot_get_service( 'Request_Url_Service_Weglot' );
	$amp_service         = weglot_get_service( 'Amp_Service_Weglot' );
	$language_service    = weglot_get_service( 'Language_Service_Weglot' );

	if ( ! $request_url_service->is_eligible_url() ) {
		return '';
	}

	$original_language = weglot_get_original_language();

	$weglot_url           = $request_url_service->get_weglot_url();
	$amp_regex            = $amp_service->get_regex( true );
	$destination_language = weglot_get_destination_languages();

	$current_language = $request_url_service->get_current_language();

	if ( weglot_get_translate_amp_translation() && preg_match( '#' . $amp_regex . '#', $weglot_url->getUrl() ) === 1 ) {
		$add_class .= ' weglot-invert';
	}

	$flag_class  = $current_this->get_flag_class();
	$class_aside = $current_this->get_class_dropdown();

	$button_html = sprintf( '<!--Weglot %s-->', WEGLOT_VERSION );
	$button_html .= sprintf( "<aside data-wg-notranslate class='country-selector %s'>", $class_aside . $add_class );
	if ( ! empty( $original_language ) && ! empty( $destination_language ) ) {
		$current_language_entry = $language_service->get_language_from_internal( $current_language->getInternalCode() );
		$name                   = $current_this->get_name_with_language_entry( $current_language_entry );
		$uniq_id                = 'wg' . uniqid( strtotime( 'now' ) ) . rand( 1, 1000 );
		$button_html            .= sprintf( '<input id="%s" class="weglot_choice" type="checkbox" name="menu"/><label for="%s" class="wgcurrent wg-li weglot-lang weglot-language %s" data-code-language="%s"><span>%s</span></label>', esc_attr( $uniq_id ), esc_attr( $uniq_id ), esc_attr( $flag_class . $current_language->getInternalCode() ), esc_attr( $current_language->getInternalCode() ), esc_html( $name ) );

		$button_html .= '<ul>';

		array_unshift( $destination_language, $original_language );

		foreach ( $language_service->get_original_and_destination_languages( $request_url_service->is_allowed_private() ) as $language ) {

			if ( $language->getInternalCode() === $current_language->getInternalCode() ) {
				continue;
			}

			$link_button = $request_url_service->get_weglot_url()->getForLanguage( $language );
			if ( ! $link_button ) {
				continue;
			}

			$button_html .= sprintf( '<li class="wg-li weglot-lang weglot-language %s" data-code-language="%s">', $flag_class . $language->getInternalCode(), $language->getInternalCode() );
			$name        = $current_this->get_name_with_language_entry( $language );

			if ( $language === $language_service->get_original_language() &&
			     strpos( $link_button, 'wg-choose-original' ) === false && // If not exist
			     ( is_home() || is_front_page() )
			     && $option_service->get_option( 'auto_redirect' )
			) { // Only for homepage
				if ( strpos( $link_button, '?' ) !== false ) {
					$link_button = str_replace( '?', '?wg-choose-original=true', $link_button );
				} else {
					$link_button .= '?wg-choose-original=true';
				}
			}

			$button_html .= sprintf(
				'<a data-wg-notranslate href="%s">%s</a>',
				esc_url( $link_button ),
				esc_html( $name )
			);

			$button_html .= '</li>';
		}

		$button_html .= '</ul>';
	}

	$button_html .= '</aside>';

	return $button_html;
}
```

#### Change the language selector title

If you use the language selector in a menu with the "dropdown" option enabled, the title of the selector in the menu is "**Choose your language**" in English. To change this text, edit the plugin's translation files, or use the following hook:

```php
<?php

add_filter( 'weglot_menu_parent_menu_item_title', 'custom_weglot_menu_parent_menu_item_title' );
function custom_weglot_menu_parent_menu_item_title( $title ) {

	switch ( weglot_get_current_language() ) {
		case 'en':
			$title = 'Choose your language please';
			break;
		case 'fr':
			$title = 'Choisissez votre langue s\'il vous plaît';
			break;
	}

	return $title;
}
```

#### Add the current-menu-item class to the selector in a menu

If you use the language selector in a menu and want the **`current-menu-item`** class to be present on the current page's link in the selector, use the **`weglot_active_current_menu_item`** filter:

```php
<?php

add_filter( 'weglot_active_current_menu_item', '__return_true' );
```

{% hint style="info" %}
When the auto-redirect option is enabled, the original-language link carries a `wg-choose-original` query parameter so visitors can reach the original language without being redirected again. If you rebuild the button yourself (see above), keep that parameter on the original-language link.
{% endhint %}


# Change flag size

Changing the Weglot flag size with CSS

Because Weglot has grouped all flags within a single file (CSS sprite) for performance, changing the flag size on your website can be a bit tricky.

{% hint style="info" %}
The `flag-N` number depends on your flag type: **shiny** = `flag-1`, **square** = `flag-2`, **circle** = `flag-3`. The default **rectangle (mat)** type has no `flag-N` class — target `.weglot-flags` directly in that case.
{% endhint %}

**1st step:** With your browser's code inspector, find the CSS properties that set the global flag size. It depends on your flag settings. In this example (setting: circle flags), the properties are:

```css
.weglot-flags.flag-3 a::before, 
.weglot-flags.flag-3 span::before {
    background-image: url("../images/circular_flag.png");
    width: 24px !important;
    height: 24px !important;
    -webkit-background-size: auto 24px !important;
    background-size: auto 24px !important;
}
```

Override the `width`, `height` and `background-size` properties with the wanted size.

**2nd step:** For each flag, find its `background-position` property and override it. In this example, the `background-position` properties are:

```css
/* For English flag */
.weglot-flags.flag-3.en > a::before, 
.weglot-flags.flag-3.en > span::before {
    background-position: -2520px 0 !important;
}

/* For Portuguese flag */
.weglot-flags.flag-3.pt > a::before, 
.weglot-flags.flag-3.pt > span::before {
    background-position: -4344px 0 !important;
}
```

To override it, calculate the new value with a cross product using the original size (24px), the wanted size and the default `background-position`.

*New background-position = ( Wanted size / Default size ) \* current background-position*

**Example 1: Smallest flags**

**Type of flags:** Circle\
**Languages:** English and Portuguese\
**Wanted size:** 16px \* 16px

```css
/* Customize English flag */
.weglot-flags.flag-3.en > a::before,
.weglot-flags.flag-3.en > span::before {
    background-position: -1680px 0 !important;
}

/* Customize Portuguese flag */
.weglot-flags.flag-3.pt > a::before,
.weglot-flags.flag-3.pt > span::before {
    background-position: -2896px 0 !important;
}

.weglot-flags.flag-3 a::before,
.weglot-flags.flag-3 span::before {
    width: 16px !important;
    height: 16px !important;
    -webkit-background-size: auto 16px !important;
    background-size: auto 16px !important;
}
```

Calculation for English flag: (16/24)\*-2520 = -1680\
Calculation for Portuguese flag: (16/24)\*-4344 = -2896

**Example 2: Biggest flags**

**Type of flags:** Circle\
**Languages:** English and Portuguese\
**Wanted size:** 48px \* 48px

```css
/* Customize English flag */
.weglot-flags.flag-3.en > a::before,
.weglot-flags.flag-3.en > span::before {
    background-position: -5040px 0 !important;
}

/* Customize Portuguese flag */
.weglot-flags.flag-3.pt > a::before,
.weglot-flags.flag-3.pt > span::before {
    background-position: -8688px 0 !important;
}

.weglot-flags.flag-3 a::before,
.weglot-flags.flag-3 span::before {
    width: 48px !important;
    height: 48px !important;
    -webkit-background-size: auto 48px !important;
    background-size: auto 48px !important;
}
```

Calculation for English flag: (48/24)\*-2520 = -5040\
Calculation for Portuguese flag: (48/24)\*-4344 = -8688


# Exclude a Custom Post Type

To avoid adding URLs to the Weglot exclusion list, you can disable the translation of a given post type directly with our hooks. In the example below we exclude the built-in `page` type — replace `'page'` with your own Custom Post Type slug.

```php
<?php

add_filter( 'weglot_is_eligible_url', 'not_authorize_translation' );
function not_authorize_translation( $eligible ) {
	if ( get_post_type( weglot_get_postid_from_url() ) === 'page' ) {
		return false;
	}
	return $eligible;
}

add_filter( 'weglot_active_translation_before_process', 'check_page_translation' );
function check_page_translation() {
	if ( get_post_type( weglot_get_postid_from_url() ) === 'page' && weglot_get_current_language() !== weglot_get_original_language() ) {
		wp_redirect( weglot_get_request_url_service()->get_full_url() );
		exit;
	}

	return true;
}
```


# Exclude the search page

If you would like to exclude the search page from being translated, you can use the following code:

```php
<?php

add_action( 'pre_get_posts', 'custom_weglot_translated_search_redirect' );
function custom_weglot_translated_search_redirect() {
	if ( ! function_exists( 'weglot_get_original_language' ) || ! function_exists( 'weglot_get_current_language' ) ) {
		return;
	}
	if ( is_search() && ! is_admin() && weglot_get_original_language() != weglot_get_current_language() ) {
		wp_redirect( weglot_get_full_url_no_language(), 301 );
		exit;
	}
}

add_filter( 'weglot_button_html', 'custom_weglot_translated_search_no_selector' );
function custom_weglot_translated_search_no_selector( $button_html ) {
	if ( is_search() && ! is_admin() ) {
		return '';
	}
	return $button_html;
}
```


# Exclude draft or private status post

If you would like to exclude a page that is in draft or private status, you can add the code below:

```php
<?php

add_action( 'pre_get_posts', 'custom_weglot_exclude_draft_private_redirect' );
function custom_weglot_exclude_draft_private_redirect() {
	global $post;
	if ( $post ) {
		$post_status = get_post_status( $post->ID );
		if ( ! function_exists( 'weglot_get_original_language' ) || ! function_exists( 'weglot_get_current_language' ) ) {
			return;
		}
		if ( ( $post_status == 'draft' || $post_status == 'private' ) && ! is_admin() && weglot_get_original_language() != weglot_get_current_language() ) {
			wp_redirect( weglot_get_full_url_no_language(), 301 );
			exit;
		}
	}
}

add_filter( 'weglot_button_html', 'custom_weglot_exclude_draft_private_no_selector' );
function custom_weglot_exclude_draft_private_no_selector( $button_html ) {
	global $post;
	if ( $post ) {
		$post_status = get_post_status( $post->ID );
		if ( ( $post_status == 'draft' || $post_status == 'private' ) && ! is_admin() ) {
			return '';
		}
	}
	return $button_html;
}
```


# Plugin Woocommerce: Translate all email sent to customers

When a WooCommerce order is placed in a translated language, Weglot records that language in the order's metadata (`weglot_language`). The WooCommerce emails related to that order (order confirmation, invoice, etc.) are then translated into the customer's language.

Two conditions must be met:

* The **Translate emails** option is enabled in the Weglot settings.
* The order is linked to a language — orders placed in your original language are not translated.

This behavior is **enabled by default**. If you need to turn it off, use the `weglot_woocommerce_translate_following_mail` filter:

```php
add_filter( 'weglot_woocommerce_translate_following_mail', '__return_false' );
```


# Plugin WooCommerce: Translate Product URLs

By default, Weglot doesn't allow you to translate product URL, you can do it following this

Weglot lets you translate the URL slug of your WooCommerce products directly from the product edit screen: a **Weglot** metabox appears at the bottom of the product page, where you can set a translated slug for each language.

This metabox is available for every public post type except a few that are excluded by default: `attachment`, `shop_order` and `shop_coupon`. You can change that list with the `weglot_url_translate_metabox_post_type_exclude` filter.

For example, to also hide the translated-slug metabox for products:

```php
add_filter( 'weglot_url_translate_metabox_post_type_exclude', 'custom_weglot_metabox_exclude' );
function custom_weglot_metabox_exclude( $excluded ) {
	$excluded[] = 'product';
	return $excluded;
}
```

Or to re-enable it for a post type that is excluded by default (here `shop_coupon`):

```php
add_filter( 'weglot_url_translate_metabox_post_type_exclude', 'custom_weglot_metabox_include' );
function custom_weglot_metabox_include( $excluded ) {
	$index = array_search( 'shop_coupon', $excluded, true );
	if ( $index !== false ) {
		unset( $excluded[ $index ] );
	}
	return $excluded;
}
```


# Use custom language code (URL, lang and hreflang attribute)

Here we explain how to change the default language code. This is useful when you don't like Weglot's default 2-letter code in the URL and want to replace it with another one.

#### Example: change "tw" to "zh-HK"

Below we change the language code `tw` (Traditional Chinese) into `zh-HK` (Hong Kong Chinese).

```markup
<!-- HTML output by default (Traditional Chinese) -->
<html lang="tw">
    <head>
        <link rel="alternate" hreflang="en" href="https://mysite.com/"/>
        <link rel="alternate" hreflang="tw" href="https://mysite.com/tw/"/>
    </head>
</html>

<!-- HTML output with custom language code (Hong Kong Chinese) -->
<html lang="zh-HK">
    <head>
        <link rel="alternate" hreflang="en" href="https://mysite.com/"/>
        <link rel="alternate" hreflang="zh-HK" href="https://mysite.com/zh-HK/"/>
    </head>
</html>
```

#### Hook to customize the language code

This hook must be loaded **before your theme**, so it cannot live in your `functions.php`. Use one of the two methods below (Code Snippets plugin or an MU-plugin).

```php
// Use zh-HK (Hong Kong Chinese) instead of tw (Traditional Chinese)
add_filter( 'weglot_language_code_replace', 'custom_weglot_language_code_replace' );
function custom_weglot_language_code_replace( $replacements ) {
    $replacements['tw'] = 'zh-HK';
    return $replacements;
}

// Optional: keep tw instead of zh-HK on the hreflang tags
add_filter( 'weglot_href_lang', 'custom_weglot_href_lang' );
function custom_weglot_href_lang( $render ) {
    $render = str_replace( 'hreflang="zh-HK"', 'hreflang="tw"', $render );
    return $render;
}
```

#### With the auto-redirect option

If the auto-redirect option is enabled, also map your custom code in the browser-language list with the `weglot_navigator_language` filter:

```php
add_filter( 'weglot_navigator_language', 'custom_weglot_navigator_language' );
function custom_weglot_navigator_language( $navigator_languages ) {
    $navigator_languages = array();
    if ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) { // phpcs:ignore
        $navigator_languages = explode( ',', trim( sanitize_text_field( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) );
        foreach ( $navigator_languages as &$navigator_language ) {
            if ( strpos( $navigator_language, ';' ) !== false ) {
                $navigator_language = substr( $navigator_language, 0, strpos( $navigator_language, ';' ) );
            }
            $navigator_language = strtolower( $navigator_language );
            $navigator_language = str_replace( 'tw', 'zh-HK', $navigator_language );
        }
    }
    return $navigator_languages;
}
```

#### How to load it

**Method 1 — Code Snippets plugin:** install [Code Snippets](https://wordpress.org/plugins/code-snippets/), go to *Snippets → Add new*, paste the code (without the `<?php` tag, the plugin adds it) and save.

**Method 2 — MU-plugin:** create `/wp-content/mu-plugins/weglot-language-code-replace.php` and paste the code (with the `<?php` tag).


# Theme OceanWP: Use language selector in the main menu

How to fix the language selector in mobile menu of OceanWP theme

To build its mobile menu, the OceanWP theme duplicates the main menu with modified attributes, which breaks the Weglot switcher there. Add the JavaScript below (via *Code Snippets* or your theme's `functions.php`) to fix the switcher classes in the OceanWP mobile menu.

OceanWP theme: <https://oceanwp.org/>

```php
add_action( 'wp_footer', 'weglotsupport_wpocean_menu' );
function weglotsupport_wpocean_menu() {
    ?>
    <script type="text/javascript">
        /* WEGLOT FIX WP OCEAN MENU */
        jQuery(document).ready(function ($) {
            var weglotMenuDone = false;
            jQuery(document).on('click', '.oceanwp-theme .mobile-menu', function () {
                if (weglotMenuDone) {
                    return;
                }
                jQuery(".sidr-class-weglot-flags").each(function () {
                    if (typeof jQuery(this).attr("class") !== 'undefined') {
                        var element_class = jQuery(this).attr("class");
                        jQuery(this).addClass(element_class.replace(/sidr-class-/g, ''));
                    }
                });
                weglotMenuDone = true;
            });
        });
    </script>
    <?php
}
```


# Theme Avada: Use language selector in the main menu

How to fix the language selector in mobile menu of Avada theme

To build its mobile menu, the Avada theme duplicates the main menu with modified attributes, which breaks the Weglot switcher there. Add the JavaScript below (via *Code Snippets* or your theme's `functions.php`) to copy the switcher classes onto the Avada mobile menu.

Avada theme: <https://avada.theme-fusion.com/>

```php
add_action( 'wp_footer', 'weglotsupport_fix_avada_menu' );
function weglotsupport_fix_avada_menu() {
    ?>
    <script type="text/javascript">
        /* WEGLOT FIX AVADA MENU */
        jQuery(document).ready(function ($) {
            var weglotMenuDone = false;
            jQuery(document).on('click', '.fusion-mobile-menu-icons', function () {
                if (weglotMenuDone) {
                    return;
                }
                jQuery(".menu-item-weglot.menu-item-object-custom").each(function () {
                    if (typeof jQuery(this).attr("id") !== 'undefined') {
                        var id = jQuery(this).attr("id");
                        var str = "menu-item-";
                        var dataId = id.substring(str.length, id.length);
                        jQuery('[data-item-id="' + dataId + '"]').addClass(jQuery(this).attr("class"));
                    }
                });
                weglotMenuDone = true;
            });
        });
    </script>
    <?php
}
```


# LinkedIn Share Post: Translate oEmbed WP URL

Use filter to translate oEmbed WP URL

The data LinkedIn uses for its share preview is not read from the page title but from the WordPress oEmbed endpoint. The filter below translates that oEmbed URL so LinkedIn picks up the translated page:

```php
add_filter( 'weglot_html_treat_page', 'rb_weglot_localise_oembed_url' );
function rb_weglot_localise_oembed_url( $html ) {
    $search           = '/wp-json/oembed';
    $current_language = weglot_get_current_language();
    $default_language = weglot_get_original_language();
    if ( $current_language !== $default_language ) {
        $html = str_replace( $search, "/$current_language/wp-json/oembed", $html );
    }
    return $html;
}
```

Once done, check the result with the [LinkedIn Post Inspector](https://www.linkedin.com/post-inspector/).


# Hide button on excluded page

Since the version 3.5 of Weglot plugin, the button is visible even is the page is excluded. Here is how to hide it on excluded page

Since version 3.5, the language button stays visible even on pages you excluded from translation. For example, if you excluded `/fr/contact`, the button still shows on both `/contact` and `/fr/contact`.

To hide the button on excluded pages:

```php
// Add this using the "Code Snippets" plugin or directly in functions.php
add_filter( 'weglot_button_html', 'weglot_button_hide', 10, 3 );
function weglot_button_hide( $html, $classes ) {
    $show_button = weglot_get_service( 'Request_Url_Service_Weglot' )->is_eligible_url( weglot_get_current_full_url() );
    if ( ! $show_button ) {
        return '';
    }
    return $html;
}
```


# Auto switch only for HomePage

Since the version 3.5 of Weglot plugin, the auto redirection feature works on all pages. Here is how to restrict it to the homepage only

Since version 3.5, the auto-redirect (auto-switch) feature works on every page. For example, with a **French** browser:

* `/` is redirected to `/fr/`
* `/contact` is redirected to `/fr/contact`

To restrict the auto-redirect to the homepage only:

```php
// Add this using the "Code Snippets" plugin or directly in functions.php
add_filter( 'weglot_autoredirect_only_home', '__return_true' );
```


# Proxify Url

Since the version 4.2 of Weglot plugin, you have a filter to proxify an url

Since version 4.2, a filter lets you route ("proxify") a resource URL through Weglot. A proxified URL is rewritten to this form:

`proxy.weglot.com/API_KEY/LANGUAGE_FROM/LANGUAGE_TO/my.ressource.io`

To proxify one or more URLs, use the `weglot_proxify_urls` filter:

```php
// Add this using the "Code Snippets" plugin or directly in functions.php
add_filter( 'weglot_proxify_urls', 'proxify_callback' );
function proxify_callback( $urls_to_proxify ) {
    $urls_to_proxify[] = 'https://my.ressource.io/';
    return $urls_to_proxify;
}
```

You can add several URLs to the array.


# Translate pdf for Woocommerce pdf invoice

Since the version 3.7 of Weglot plugin, you can translate pdf generate by WooCommerce PDF Invoices & Packing Slips plugin

Since version 3.7, Weglot can translate the PDFs generated by the *WooCommerce PDF Invoices & Packing Slips* plugin. This is disabled by default.

To enable it:

```php
// Add this using the "Code Snippets" plugin or directly in functions.php
add_filter( 'weglot_translate_pdf', '__return_true' );
```


# Translate pdf with Gravity pdf

Since the version 3.7 of Weglot plugin, you can translate pdf generate by Gravity PDF.

Below is an example of how to translate a PDF generated by Gravity PDF into the current language, based on the `gfpdf_pdf_html_output` filter documented here: <https://docs.gravitypdf.com/v6/developers/filters/gfpdf_pdf_html_output/>

```php
// Add this using the "Code Snippets" plugin.

// Create a new meta entry to store the weglot_language on Gravity Forms entries.
add_filter( 'gform_entry_meta', 'get_entry_meta', 10, 2 );
function get_entry_meta( $entry_meta, $form_id ) {
	$entry_meta['weglot_language'] = array(
		'label'                      => 'Weglot language',
		'is_numeric'                 => false,
		'is_default_column'          => true,
		'update_entry_meta_callback' => 'update_entry_meta',
	);
	return $entry_meta;
}

function update_entry_meta( $key, $lead, $form ) {
	return ''; // Return the value of the entry meta.
}

// Store the Weglot language on submission.
add_action( 'gform_after_submission', 'after_submission' );
function after_submission( $entry ) {
	$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );
	$current_language     = $request_url_services->get_current_language()->getExternalCode();
	gform_update_meta( $entry['id'], 'weglot_language', $current_language );
}

// Translate the PDF using the stored language.
add_filter( 'gfpdf_pdf_html_output', function( $html, $form, $entry, $settings, $Helper_PDF ) {
	$weglot_language = gform_get_meta( $entry['id'], 'weglot_language' );
	if ( $weglot_language === weglot_get_original_language() ) {
		return $html;
	}
	$qp                    = new GFPDF\Helper\Helper_QueryPath();
	$pdf_translate_service = weglot_get_service( 'Pdf_Translate_Service_Weglot' );
	$html                  = $pdf_translate_service->translate_pdf( $html, $weglot_language );
	$wrapper               = $qp->html5( $html['content'] );
	return $wrapper->top( 'html' )->innerHTML5();
}, 10, 5 );
```


# Translate Dublin core meta (or other meta)

Dublin Core is a collection of meta tags to describe your content.These tags are automatically generated. Recognised by states/governments, these are used by directories, Bing, Baidu and Yandex.

Dublin Core is a set of meta tags describing your content (recognised by several search engines and directories). They are not translated by default, but you can register them with the `weglot_get_dom_checkers` filter.

Translate a single meta (e.g. `<meta name="dc.title" content="…" />`):

```php
add_filter( 'weglot_get_dom_checkers', 'dublin_core_weglot_dom_check' );
function dublin_core_weglot_dom_check( $dom_checkers ) {
    if ( ! class_exists( 'Dublin_Core_Meta' ) ) {
        class Dublin_Core_Meta extends Weglot\Parser\Check\Dom\AbstractDomChecker {
            const DOM       = 'meta[name="dc.title"]';
            const PROPERTY  = 'content';
            const WORD_TYPE = Weglot\Client\Api\Enum\WordType::META_CONTENT;
        }
        $dom_checkers[] = '\Dublin_Core_Meta';
    }
    return $dom_checkers;
}
```

To target several meta tags at once, list them in the `DOM` selector (comma-separated):

```php
const DOM = 'meta[name="dc.title"],meta[name="dc.description"]';
```


# How to not translate specific ajax action

Weglot translates the response of admin-ajax actions by default. If a specific AJAX action should not be translated, add it to the list with the `weglot_ajax_no_translate` filter.

#### Example: excluding the `loadmore` ajax action

```php
add_filter( 'weglot_ajax_no_translate', 'custom_ajax_no_translate', 10, 1 );
function custom_ajax_no_translate( $ajax_action ) {
    $ajax_action[] = 'loadmore';
    return $ajax_action;
}
```


# How to get translated url programmatically

Below an example of how to get a translated url programmatically

```php
//get services
$language_services = weglot_get_service( 'Language_Service_Weglot' );
$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );

//the url we want to get on other languages
$url = "http://myurl.local/hello-world/";

//create url object
$wg_url = $request_url_services->create_url_object( $url );

// get a language (in my case fr)
$language = $language_services->get_language_from_internal('fr');

//display url for my language
$wg_url->getForLanguage( $language );
```


# How to set WP locale based on Weglot current language

Below is an example of how to set the WordPress locale based on the current Weglot language, using the WordPress `locale` filter:

```php
add_filter( 'locale', 'weglot_set_locale' );
function weglot_set_locale( $lang ) {
    if ( function_exists( 'weglot_get_current_language' ) ) {
        $current_language = weglot_get_current_language();
        switch ( $current_language ) {
            case 'sv':
                return 'sv_SE';
            case 'en':
                return 'en_US';
            case 'no':
                return 'nb_NO';
            default:
                return $lang;
        }
    }
    return $lang;
}
```


# How to translate mail from Photo Reviews for WooCommerce

Works since version 1.2.7 of Photo Reviews for WooCommerce

The following code translates the reminder emails sent by *Photo Reviews for WooCommerce*, using the order's recorded language (stored by Weglot in the `weglot_language` order meta).

```php
use Weglot\Parser\Parser;
use Weglot\Parser\ConfigProvider\ServerConfigProvider;

function wg_viwcpr_email_reminder_get_content( $content, $order_id ) {
	$parser_services   = weglot_get_service( 'Parser_Service_Weglot' );
	$language_services = weglot_get_service( 'Language_Service_Weglot' );
	$original_language = $language_services->get_original_language()->getInternalCode();

	$woocommerce_order_language = get_post_meta( $order_id, 'weglot_language', true ); // phpcs:ignore

	if ( $woocommerce_order_language == weglot_get_original_language() ) {
		return $content;
	}

	$config  = new ServerConfigProvider();
	$client  = $parser_services->get_client();
	$parser  = new Parser( $client, $config, [] );
	$content = $parser->translate( $content, $original_language, $woocommerce_order_language ); // phpcs:ignore

	return $content;
}

function wg_viwcpr_email_reminder_get_subject( $subject, $order_id ) {
	$parser_services   = weglot_get_service( 'Parser_Service_Weglot' );
	$language_services = weglot_get_service( 'Language_Service_Weglot' );
	$original_language = $language_services->get_original_language()->getInternalCode();

	$woocommerce_order_language = get_post_meta( $order_id, 'weglot_language', true ); // phpcs:ignore

	if ( $woocommerce_order_language == weglot_get_original_language() ) {
		return $subject;
	}

	$config  = new ServerConfigProvider();
	$client  = $parser_services->get_client();
	$parser  = new Parser( $client, $config, [] );
	$subject = $parser->translate( $subject, $original_language, $woocommerce_order_language ); // phpcs:ignore

	return $subject;
}

add_filter( 'viwcpr_email_reminder_get_content', 'wg_viwcpr_email_reminder_get_content', 10, 2 );
add_filter( 'viwcpr_email_reminder_get_subject', 'wg_viwcpr_email_reminder_get_subject', 10, 2 );
```


# How to translate schema from schema.org generate by Yoast plugin

On this example we use a filter to translate some entry from our schema based on this doc : https\://developer.yoast.com/features/schema/api/

```php
add_filter( 'wpseo_schema_graph', 'wg_schema', 10, 2 );

function wg_schema( $data, $context ) {
	
	foreach ( $data as $key => $value ) {
        if ( $value['@type'] === 'WebPage' || $value['@type'] === 'WebSite') {
            $data[$key]['@id'] = weglot_get_current_full_url();
			$data[$key]['url'] = weglot_get_current_full_url();
			$data[$key]['inLanguage'] = weglot_get_current_language();
        }
		
		if ( $value['@type'] === 'ImageObject' || $value['@type'] === 'primaryImageOfPage') {
			$data[$key]['inLanguage'] = weglot_get_current_language();
        }
    }
		
    return $data;
}
```


# How to translate email sending by plugin WP Mail SMTP

On this example we use a filter to translate our email message based on this doc : https\://wpmailsmtp.com/docs/setting-a-custom-reply-to-email/

{% hint style="info" %}
Weglot can translate `wp_mail` emails natively — just enable the **Translate emails** option in the Weglot settings. Use the snippet below only if you need custom handling on top of the built-in option (for example with WP Mail SMTP).
{% endhint %}

This example translates the email message body into the current language:

```php
function wp_mail_smtp_weglot( $args ) {
	$original_lang    = weglot_get_original_language();
	$current_language = weglot_get_current_language();
	if ( $original_lang == $current_language ) {
		return $args;
	}

	if ( ! empty( $args['message'] ) ) {
		$translate_service = weglot_get_service( 'Pdf_Translate_Service_Weglot' );
		$translate_message = $translate_service->translate_pdf( $args['message'], $current_language );
		$args['message']   = $translate_message['content'];
	}
	return $args;
}

add_filter( 'wp_mail', 'wp_mail_smtp_weglot', PHP_INT_MAX );
```


# How to hide the Weglot admin button for non administrator roles

In this example, we hide the Weglot button in the top navigation for users without the role of administrator

```php
if(is_user_logged_in()){
	$user = wp_get_current_user();
	if ( !in_array( 'administrator', (array) $user->roles ) ) {
		add_action( 'admin_head', 'hide_wg_button' );
	}
}

function hide_wg_button() {
 echo "<style>#wp-admin-bar-weglot{display:none;}</style>";
}
```


# Exemple of snippet to translate search from JetSearch plugin

In this example, we use custom code to translate the search result provide by the plugin jetSearch

To translate the results of the JetSearch plugin, reverse-translate the search term back into your original language before the query runs, then declare the JSON keys JetSearch returns so Weglot translates them.

```php
add_action( 'jet-search/ajax-search/search-query', 'modify_weglot_search_query', 10, 2 );
function modify_weglot_search_query( $instance, $args ) {
    $parser_services      = weglot_get_service( 'Parser_Service_Weglot' );
    $parser               = $parser_services->get_parser();
    $language_services    = weglot_get_service( 'Language_Service_Weglot' );
    $original_language    = $language_services->get_original_language()->getInternalCode();
    $destination_languages = weglot_get_destination_languages();
    $current_language     = weglot_get_current_language();

    if ( $original_language === $current_language ) {
        return;
    }

    foreach ( $destination_languages as $destination ) {
        if ( $destination['language_to'] === $current_language && ! empty( $destination['custom_code'] ) ) {
            $current_language = substr( $destination['custom_code'], 0, 2 );
        }
    }

    if ( ! empty( $instance->search_query['s'] ) ) {
        $instance->search_query['s'] = $parser->translate( $instance->search_query['s'], $current_language, $original_language );
    }
}

add_filter( 'weglot_add_json_keys', 'custom_weglot_add_json_keys' );
function custom_weglot_add_json_keys( $keys ) {
    $keys[] = 'title';
    $keys[] = 'link';
    $keys[] = 'before_title';
    $keys[] = 'posts';
    return $keys;
}
```


# Example of snippet to translate your checkout element (override/added by the Funnel Builder plugin)

```php
add_filter('woocommerce_update_order_review_fragments', 'wg_update_checkout', 999, 2);
function wg_update_checkout($arr) {
$pdf_translate_service = weglot_get_service( 'Pdf_Translate_Service_Weglot' );
$original_lang = weglot_get_original_language();
$current_language = weglot_get_current_language();
if ( $original_lang == $current_language ) {
	return $arr;
}
$pot = $pdf_translate_service->translate_pdf( $arr['place_order_text'], $current_language );
$arr['place_order_text'] = $pot['content'];
return $arr;
}
```


# LScache

Compatibility issue with LScache

LScache uses so called “Cache Vary”. That means each URL can be cached with different cache copies depending on user related facts like cookie, device and many others. The problem is that Weglot uses PHP and detects language using PHP, but if a page is cached there is no more PHP interpretor, because a cached URL is pure plain text and plain text can’t execute PHP. To make Weglot work with LScache a cookie must be set with different cookie value depending on the selected language. Then this cookie can be used for cache vary so each language gets its own cached copy.

To make it works you can modifiy your Litespeed Vhost with this code :

```php
<IfModule LiteSpeed>
RewriteEngine onCacheLookup on
## Create a separate cache for each language [create a rule for each language you have on your website except the fallback language. In this example we have: FR (original language) + ES (target language) + EN (target but fallback language)] ##
## FR cache ##
RewriteCond %{HTTP:Accept-Language} ^fr [NC]RewriteRule .* - [E=Cache-Control:vary=%{ENV:LSCACHE_VARY_VALUE}+french]
## ES cache ##
RewriteCond %{HTTP:Accept-Language} ^es [NC]RewriteRule .* - [E=Cache-Control:vary=%{ENV:LSCACHE_VARY_VALUE}+spain]
## Create a separate cache if the browser is different from the website - add it imperatively or it will cause issue if the cache is made with the wrong language ##
RewriteCond %{HTTP_COOKIE} ^.*WG_CHOOSE_ORIGINAL.*$RewriteRule .* - [E=Cache-Control:vary=%{ENV:LSCACHE_VARY_VALUE}+wg_choose_original]
</IfModule>
```

Be careful, in some cases, if the Litespeed server is a “fake”, configured with reverse proxies by the host, this code must be added to the Litespeed Vhost. Unfortunately, some hosts do not allow this...


# How to fix live builder issue with Weglot

Compatibility issue with live theme builder

Weglot is not intended to translate backoffice elements. More and more site builders offer the live builder feature. Some of its live builders will come into conflict with Weglot because Weglot will attempt to translate elements that are not wanted at that time. To avoid this we will ask Weglot not to translate when we are in the live builder.

Let’s take the example of Avada theme builder. When we are in the live builder we have the get fb-edit variable in the url so we can use this snippet:

<pre class="language-php"><code class="lang-php">if(isset($_GET['fb-edit']) || isset($_GET['builder'])){
<strong>    add_filter( 'weglot_active_translation', '__return_false', 99999 );
</strong>}
</code></pre>

Here another exemple with elementor : we use a hook instead of url parameters :&#x20;

```php
function weglot_deactivate_elementor() {
	add_filter( 'weglot_active_translation', '__return_false', 99999 );
}
add_action( 'elementor/init', 'weglot_deactivate_elementor' );
```


# Add translated url to Rankmath sitemap index

First step, add this snippet to be sure to purge the sitemap caching

```php
/**
 * Filter if XML sitemap transient cache is enabled.
 *
 * @param boolean $unsigned Enable cache or not, defaults to true
 */
add_filter( 'rank_math/sitemap/enable_caching', '__return_false');
```

Add this filter. For the moment you need to add the list of url you want to translate into your sitemap

```php
add_filter( 'rank_math/sitemap/index', function( $xml ) {
	// Fetch Weglot services
	$language_services = weglot_get_service( 'Language_Service_Weglot' );
	$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );

	// List of URLs to be translated
	$urls = [
		"http://beta-429.local/post-sitemap.xml",
		"http://beta-429.local/page-sitemap.xml",
		"http://beta-429.local/category-sitemap.xml",
	];

	$destination_languages = weglot_get_destination_languages();
	foreach ( $urls as $url ) {
		$wg_url = $request_url_services->create_url_object( $url );

		// Iterate over each destination language
		foreach ( $destination_languages as $language_code ) {
			$language = $language_services->get_language_from_internal( $language_code['language_to'] );

			$translated_url = $wg_url->getForLanguage( $language );

			$xml .= '
                <sitemap>
                    <loc>' . esc_url( $translated_url ) . '</loc>
                    <lastmod>' . esc_html( date( 'c' ) ) . '</lastmod>
                </sitemap>';
		}
	}

	return $xml;
}, 999 );
```


# Advanced Woo Search X Weglot

Advanced Woo Search (aws) is a plugin to make advance search with WooCommerce. You can find the plugin here : https\://wordpress.org/plugins/advanced-woo-search/

To make Advanced Woo Search return results in translated languages, reverse-translate the search terms into your original language before the search runs. The right hook (see the [Advanced Woo Search hooks reference](https://advanced-woo-search.com/guide/hooks-reference/)) is `aws_search_terms`.

```php
use WeglotWP\Helpers\Helper_API;

add_filter( 'aws_search_terms', 'my_aws_search_terms' );
function my_aws_search_terms( $terms ) {
    $original_language = weglot_get_original_language();
    $current_language  = weglot_get_current_language();
    if ( $original_language === $current_language || ! $terms ) {
        return $terms;
    }

    $option_services = weglot_get_service( 'Option_Service_Weglot' );
    $api_key_private = $option_services->get_api_key_private();

    foreach ( $terms as $key => $term ) {
        $request_body = wp_json_encode( array(
            'l_from'      => $current_language,
            'l_to'        => $original_language,
            'request_url' => home_url( '/' ),
            'words'       => array(
                array( 'w' => $term, 't' => 1 ),
            ),
        ) );

        $url      = sprintf( '%s/translate?api_key=%s', Helper_API::get_api_url(), $api_key_private );
        $response = wp_remote_post( $url, array(
            'body'        => $request_body,
            'headers'     => array( 'Content-Type' => 'application/json' ),
            'method'      => 'POST',
            'data_format' => 'body',
        ) );

        if ( is_wp_error( $response ) ) {
            continue; // Keep the original term if the request fails.
        }

        $response_data = json_decode( wp_remote_retrieve_body( $response ), true );
        if ( isset( $response_data['to_words'][0] ) ) {
            $terms[ $key ] = $response_data['to_words'][0];
        }
    }

    return $terms;
}
```


# Conditionally Disabling Weglot Translation for Specific URLs

When using Weglot on your website, you might occasionally encounter issues where its translation processes interfere with certain functionalities, like generating PDFs or handling custom endpoints. In

Suppose you’re facing an issue where generating PDFs is not working correctly due to Weglot's translation being applied to those URLs. In this case, instead of disabling the entire Weglot plugin, you can selectively disable its translation process for specific URLs.

```php
add_action('init', 'conditionally_apply_weglot_translation');
function conditionally_apply_weglot_translation() {
    $current_url = $_SERVER['REQUEST_URI'];
    // Check if the current URL contains 'front-end'
    if (strpos($current_url, 'front-end') !== false) {
        // Disable Weglot translation for this specific request
        add_filter('weglot_active_translation_before_process', function() {
            return false;
        });
    }
}
```

**Why Use This Approach?**

* **Avoid full deactivation**: Instead of disabling the entire Weglot plugin (which affects your whole site), this solution allows you to keep Weglot active while bypassing translation only for specific scenarios.
* **Resolve conflicts efficiently**: For example, if generating PDFs or handling specific routes fails due to translations, disabling Weglot only for those URLs resolves the issue without affecting the rest of your website.


# Weglot filters

All Weglot filters you can call to modify translations

Weglot plugin is exposing actions and filters that can be called in your code.


# weglot\_translate\_email

This filter allow you to prevent weglot translate email even if the option is checks on your options.

```php
add_filter( 'weglot_translate_email', '__return_false' );
```


# weglot\_cancel\_init

This filter allow you to prevent weglot to be load.

### weglot\_cancel\_init

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


# weglot\_translate\_email\_languages\_forced

Weglot prevent to translate emails that are fro admins. But you can force it by adding this filter.

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


# weglot\_menu\_parent\_menu\_item\_title

When the language switcher is added through the WordPress menu in dropdown mode, its parent item shows a default title ("Choose your language"). Use this filter to change it.

```php
add_filter( 'weglot_menu_parent_menu_item_title', 'custom_weglot_menu_parent_menu_item_title' );
function custom_weglot_menu_parent_menu_item_title( $title ) {
    return 'Choose your language';
}
```


# weglot\_active\_current\_menu\_item

With this filter you can manage if you want to add the current-item-menu class into your switcher element (menu version).

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


# weglot\_ajax\_no\_translate

This filter help you prevent Weglot to translate some ajax action. Here the list of action we don't translate :

```php
add_filter( 'weglot_ajax_no_translate', [] );
```

```
array(
   'add-menu-item', // WP Core.
   'query-attachments', // WP Core.
   'avia_ajax_switch_menu_walker', // Enfold theme.
   'query-themes', // WP Core.
   'wpestate_ajax_check_booking_valability_internal', // WP Estate theme.
   'wpestate_ajax_add_booking', // WP Estate theme.
   'wpestate_ajax_check_booking_valability', // WP Estate theme.
   'mailster_get_template', // Mailster Pro.
   'mmp_map_settings', // MMP Map.
   'elementor_ajax', // Elementor since 2.5.
   'ct_get_svg_icon_sets', // Oxygen.
   'oxy_render_nav_menu', // Oxygen.
   'hotel_booking_ajax_add_to_cart', // Hotel booking plugin.
   'imagify_get_admin_bar_profile', // Imagify Admin Bar.
   'el_check_user_login', // Event list plugin.
   'wcfm_ajax_controller', // wcfm_ajax_controller.
   'jet_ajax_search', // jet_ajax_search.
   'woofc_update_qty', // jet_ajax_search.
)
```

With the filter you can update this array by add or unset array index.


# weglot\_active\_translation\_before\_process

This filter allow you to interrupt translation process before Weglot check redirection needed.

```php
add_filter( 'weglot_active_translation_before_process', '__return_false' );
```


# weglot\_active\_translation\_before\_treat\_page

This filter allow you to interrupt translation process after Weglot have check redirection needed.

```php
add_filter( 'weglot_active_translation_before_treat_page', '__return_false' );
```


# weglot\_debug\_file

In the Weglot plugin you can active a debug mode.

To activate the debug mode the steps are:

* In Weglot.php set **`WEGLOT_DEBUG`** to true
* Create a file **`content.html`** on Weglot plugin dir root&#x20;

```php
add_filter( 'weglot_debug_file', 'path to your file' );
```

With this filter you can access debug mode from another file instead of :

```
WEGLOT_DIR . '/content.html'
```


# weglot\_autoredirect\_only\_home

This filter allow you to restrict autoredirect to the homepage only.

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


# weglot\_autoredirect\_skip

This filter allow you to deactivate the autoswitch feature even if the option is activate.

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


# weglot\_remove\_google\_translate

By default, Weglot prevent google translating page but with this flter you can enable this google feature

```php
add_filter( 'weglot_autoredirect_only_home', '__return_false' );
```


# weglot\_add\_hreflang

This filter allow you to prevent Weglot add hreflangs if you want to add yours

```php
add_filter( 'weglot_add_hreflang', '__return_false' );
```


# weglot\_get\_replace\_modify\_link

This filter allow you to add pattern to define kind of link you want to translate.

here the list of pattern we already treat on Weglot:

```php
array(
   'a'         => '/<a([^\>]+?)?href=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',
   'datalink'  => '/<([^\>]+?)?data-link=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',
   'dataurl'   => '/<([^\>]+?)?data-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',
   'datacart'  => '/<([^\>]+?)?data-cart-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',
   'form'      => '/<form([^\>]+?)?action=(\"|\')([^\s\>]+?)(\"|\')/',
   'canonical' => '/<link rel="canonical"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/',
   'amp'       => '/<link rel="amphtml"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/',
   'meta'      => '/<meta property="og:url"(.*?)?content=(\"|\')([^\s\>]+?)(\"|\')/',
   'next' => '/<link rel="next"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/',
   'prev' => '/<link rel="prev"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/',
);
```

```php
add_filter( 'weglot_get_replace_modify_link', [] );
```

Here 2 exemples of how to use this filter :<br>

```html
<div data-link2="http://debug-wp-woo.local/shop/">http://debug-wp-woo.local/shop/</div>
```

To translate the link into the attribute data-link-2 you cn use this code :&#x20;

```php
add_filter( 'weglot_get_replace_modify_link', 'custom_weglot_get_replace_modify_link' );
function custom_weglot_get_replace_modify_link( $data ) {
	$data['datalink2'] = '/<([^\>]+?)?data-link2=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/';
    return $data;
}

function replace_datalink2( $translated_page, $current_url, $quote1, $quote2, $sometags = null, $sometags2 = null ) {
	$request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );
	$replace_url_Service = weglot_get_service( 'Replace_Link_Service_Weglot' );
	$current_language = $request_url_services->get_current_language();
	$translated_page  = preg_replace( '/<' . preg_quote( $sometags, '/' ) . 'data-link2=' . preg_quote( $quote1 . $current_url . $quote2, '/' ) . '/', '<' . $sometags . 'data-link2=' . $quote1 . $replace_url_Service->replace_url( $current_url, $current_language ) . $quote2, $translated_page );
	return $translated_page;
}
```

Now try with a more complexe case :&#x20;

```html
                <div data-actions="o:click;a:simplelink;target:_self;url:http://debug-wp-woo.local/shop/;">http://debug-wp-woo.local/shop/</div>
```

```php
add_filter( 'weglot_get_replace_modify_link', 'custom_weglot_get_replace_modify_link_2' );
function custom_weglot_get_replace_modify_link_2( $data ) {
	$data['dataactions'] = '/<div[^>]*?data-actions=(["\'].*?url:)([^"\'>]+).*?>(.*?)<\/div>/';
	return $data;
}

function replace_dataactions( $translated_page, $current_url, $quote1, $quote2, $sometags = null, $sometags2 = null ) {
    $request_url_services = weglot_get_service( 'Request_Url_Service_Weglot' );
    $replace_url_Service = weglot_get_service( 'Replace_Link_Service_Weglot' );
    $current_language = $request_url_services->get_current_language();
    $sometags = 'div ';
    $quote1 = '"o:click;a:simplelink;target:_self;url:';
    $quote2 = ';"';
	$translated_page  = preg_replace( '/<' . preg_quote( $sometags, '/' ) . 'data-actions=' . preg_quote( $quote1 . $current_url . $quote2, '/' ) . '/', '<' . $sometags . 'data-actions=' . $quote1 . $replace_url_Service->replace_url( $current_url, $current_language ) . $quote2, $translated_page );
	return $translated_page;
}
```


# get\_replace\_modify\_link\_in\_xml

This filter allow you to add pattern to define kind of link you want to translate in xml.

here the list of pattern we already treat on Weglot:

```php
array('loc' => '/<loc>(.*?)<\/loc>/');
```

```php
add_filter( 'get_replace_modify_link_in_xml', [] );
```


# weglot\_get\_flag\_class

This filter allow to add or remove class use to display flag on switcher

```php
add_filter( 'weglot_get_flag_class', 'list of class' );
```


# weglot\_get\_name\_with\_language\_entry

With this filter you can modifiy the name of language we diplay on switcher for each languages

```php
add_filter( 'weglot_get_name_with_language_entry', $name, $language_entry );
```


# weglot\_get\_class\_dropdown

This filter allow you to modify list of class use to display our switcher dropdown.

```php
add_filter( 'weglot_get_class_dropdown', '' );
```


# weglot\_button\_html

this filter allows you yo get the html generate for our switcher and modify it.

You can find an exemple [here](https://developers.weglot.com/wordpress/use-cases/language-selector-styling#example-adding-code-before-after-the-button).

```php
add_filter( 'weglot_button_html', 'custom_weglot_button_html', 10, 2 );
```


# weglot\_get\_dom\_checkers

This filter allow you to add rule to our dom checker. You can add rule to telle Weglot what kind of node need to be translate.

You've an exemple here: <https://developers.weglot.com/wordpress/filters/translations-filters#weglot_get_dom_checkers>


# weglot\_replace\_div\_id

This filter allow you to get the translated content after we have replace the \<div id="weglot\_here">\</div> with the switcher

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


# weglot\_replace\_weglot\_menu

This filter allow to modify the content before we add the switcher(s)

```php
add_filter( 'weglot_replace_weglot_menu', $dom );
```


# weglot\_render\_default\_button

This filter allows you to modifiy the content after the default switcher is added

```php
add_filter( 'weglot_render_default_button', $dom );
```


# weglot\_render\_switcher\_editor\_button

This filter allow you to modifiy the translated content after the custom switcher is added.

```php
add_filter( 'weglot_render_switcher_editor_button', $dom );
```


# weglot\_href\_lang

With this filter you can modifiy hreflangs generate by Weglot before we add them.

Lets you alter the hreflang block Weglot outputs in the `<head>` (for example to swap a language code).

```php
add_filter( 'weglot_href_lang', 'custom_weglot_href_lang' );
function custom_weglot_href_lang( $render ) {
    $render = str_replace( 'hreflang="zh-HK"', 'hreflang="tw"', $render );
    return $render;
}
```


# weglot\_get\_options\_from\_cdn\_cache

This filter allow you to prevent to load Weglot settings from transient.

```php
add_filter( 'weglot_get_options_from_cdn_cache', '__return_false' );
```


# weglot\_get\_options\_from\_cdn\_cache\_duration

With this filter you can modifiy the duration of cache where we save Weglot settings. By default we fix it to 300 seconds

```php
add_filter( 'weglot_get_options_from_cdn_cache_duration', 300 );
```


# weglot\_get\_slugs\_from\_cache

This filter allow you to get your slug directly from the API instead of getting them from transient. Be carefull using this filter.

```php
add_filter( 'weglot_get_slugs_from_cache', '__return_false' );
```


# weglot\_get\_slugs\_cache\_duration

This filter allow you to change the duration of cache we store the slugs. By default is setting to 0.

Translated URL slugs are cached in a transient. By default the duration is `0` (no explicit expiration set on the transient). Use this filter to set a custom cache duration, in seconds.

```php
add_filter( 'weglot_get_slugs_cache_duration', 'custom_weglot_get_slugs_cache_duration' );
function custom_weglot_get_slugs_cache_duration( $duration ) {
    return HOUR_IN_SECONDS;
}
```


# weglot\_exclude\_blocks

This filter allow you to modifiy the array of exclude blocks.

```php
add_filter( 'weglot_exclude_blocks', [] );
```


# weglot\_exclude\_urls

This filter allow you to modifiy the list of your excluded url.

```php
add_filter( 'weglot_exclude_urls', $exclude_urls );
```


# weglot\_get\_parser\_ignored\_nodes

This filter allow you to modify the list of node ignored by Weglot.

the default list is :&#x20;

```php
$ignoredNodes = [
    'strong', 'b',
    'em', 'i',
    'small', 'big',
    'sub', 'sup',
    'abbr',
    'acronym',
    'bdo',
    'cite',
    'kbd',
    'q',
];
```

```php
add_filter( 'weglot_get_parser_ignored_nodes', $ignored_nodes );
```


# weglot\_navigator\_language

With this filter you can modifiy the browser language(s) detect by Weglot.

Lets you change the list of browser languages Weglot reads from the visitor to decide the redirect language. Useful together with a custom language code.

```php
add_filter( 'weglot_navigator_language', 'custom_weglot_navigator_language' );
function custom_weglot_navigator_language( $navigator_languages ) {
    return $navigator_languages;
}
```


# weglot\_url\_auto\_redirect

This filter can be use to modify the url where use will be redirect if the autoswitch option is activate.

When the browser-language auto-redirect runs, this filter lets you change the destination URL.

```php
add_filter( 'weglot_url_auto_redirect', 'custom_weglot_url_auto_redirect' );
function custom_weglot_url_auto_redirect( $url ) {
    return $url;
}
```


# weglot\_replace\_url

This filter allow you to modifiy the replaced url when it is translated.

```php
add_filter( 'weglot_replace_url', $replaced_url );
```


# weglot\_replace\_link

This filter allow you to modifiy the dom after the link has benne replaced.

This filter lets you modify the DOM while Weglot replaces links. It receives the DOM string being processed and must return it.

```php
add_filter( 'weglot_replace_link', 'custom_weglot_replace_link' );
function custom_weglot_replace_link( $dom ) {
    // Modify $dom here.
    return $dom;
}
```


# weglot\_ajax\_replace\_urls

When Weglot translate json content, we don't translate all entry. With this filter you can modifiy the keys we translate for url.

by default we translate this keys :&#x20;

```php
[ 'redirecturl', 'url', 'link' ]
```

```php
add_filter( 'weglot_ajax_replace_urls', [] );
```


# weglot\_proxify\_urls

This filter allow you to modify the list of url you want to proxify.

```php
add_filter( 'weglot_proxify_urls', [] );
```


# weglot\_add\_json\_keys

With this filter you can add keys Weglot msut translate into a json content.

```php
add_filter( 'weglot_add_json_keys', [] );
```


# weglot\_json\_treat\_page

This filter allow you to modifiy the translated content when this one is a json.

```php
add_filter( 'weglot_json_treat_page', $translated_content );
```


# weglot\_html\_treat\_page

This filter allow you to modifiy the translated content when this one is html.

```php
add_filter( 'weglot_html_treat_page', $translated_content );
```


# Copy of weglot\_xml\_treat\_page

This filter allow you to modifiy the translated content when this one is xml.

```php
add_filter( 'weglot_xml_treat_page', $translated_content );
```


# weglot\_render\_dom

This filter allow to modify the translated content after putting meta and replace link.

```php
add_filter( 'weglot_render_dom', $dom );
```


# weglot\_default\_current\_language\_empty

When we not able to find the current language, we set it to the original language by default. This filter allow you to modifiy.

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


# weglot\_active\_translation

The master switch for Weglot's page translation. Return `false` to disable translation entirely.

```php
add_filter( 'weglot_active_translation', '__return_false' );
```


# weglot\_active\_slugs

Controls whether Weglot loads and applies translated URL slugs. Return `false` to disable them.

```php
add_filter( 'weglot_active_slugs', '__return_false' );
```


# weglot\_is\_eligible\_url

Lets you force whether a URL is translatable. The filter receives the current decision and the URL object.

```php
add_filter( 'weglot_is_eligible_url', 'custom_weglot_is_eligible_url', 10, 2 );
function custom_weglot_is_eligible_url( $eligible, $weglot_url ) {
    // return true or false to force eligibility
    return $eligible;
}
```


# weglot\_autoredirect\_js

Return `true` to perform the auto-redirect via the front-end JS library instead of server-side. Useful behind aggressive caching that interferes with server redirects.

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


# weglot\_add\_trailing\_slash

By default Weglot adds a trailing slash to translated links. Return `false` to keep links without a trailing slash.

```php
add_filter( 'weglot_add_trailing_slash', '__return_false' );
```


# weglot\_no\_replace\_a\_href

Links whose `href` contains this string are left untouched during link replacement. The default is `wp-content/uploads`.

```php
add_filter( 'weglot_no_replace_a_href', 'custom_weglot_no_replace_a_href' );
function custom_weglot_no_replace_a_href( $condition ) {
    return 'my-folder';
}
```


# weglot\_url\_object

Advanced. Lets you replace the `Weglot\Util\Url` object Weglot uses for the current request.

```php
add_filter( 'weglot_url_object', 'custom_weglot_url_object' );
function custom_weglot_url_object( $weglot_url ) {
    return $weglot_url;
}
```


# weglot\_language\_code\_replace

Replace Weglot's default language code with a custom one (e.g. `tw` → `zh-HK`). See the dedicated use case for the full example.

```php
add_filter( 'weglot_language_code_replace', 'custom_weglot_language_code_replace' );
function custom_weglot_language_code_replace( $replacements ) {
    $replacements['tw'] = 'zh-HK';
    return $replacements;
}
```


# weglot\_get\_translation\_engine

Returns the translation engine version used by the project.

```php
add_filter( 'weglot_get_translation_engine', 'custom_weglot_get_translation_engine' );
function custom_weglot_get_translation_engine( $engine ) {
    return $engine;
}
```




---

[Next Page](/llms-full.txt/1)

