Self-hosted CMS

Translate a WordPress site

One snippet, hooked to the front end of your theme. Your posts, pages, menus and WooCommerce products read in every language you turn on, and the WordPress admin is left out of it on purpose.

What you need

Where the snippet goes

  1. Copy your snippet

    Open your site in the Verbafy dashboard and copy the embed snippet. It carries your own site id and public key.

    Your page, before </body>
    <script
      src="https://cdn.verbafy.app/widget.js"
      data-site-id="site_abc123"
      data-api-key="pk_live_your_key"
    ></script>
  2. Add it to the front end, and only the front end

    Put this in your child theme's functions.php, or in a code snippets plugin set to run on the front end. Paste your own snippet in place of the one below.

    functions.php
    add_action( 'wp_footer', function () {
        if ( is_admin() ) {
            return;
        }
        ?>
        <script
          src="https://cdn.verbafy.app/widget.js"
          data-site-id="site_abc123"
          data-api-key="pk_live_your_key"
        ></script>
        <?php
    } );
  3. Save, and load your site

    Nothing to build and no cache to prime. If you run a page cache, clear it once so the new footer is served.

Keep it off your admin

Why the snippet is scoped, and not just pasted in the footer

wp_footer is the front-end hook: WordPress' own reference describes it as printing scripts “before the closing body tag on the front end”. It is not quite exclusive, though. Since WordPress 5.8 it also fires on the block-based Widgets screen, which is an admin page. The is_admin() guard closes that gap. Without it, every editor opening that screen would translate your back office and spend your monthly word allowance on pages no customer ever sees.

Check it is working

Worth knowing on WordPress

WooCommerce needs nothing extra

Shop, category, product, cart and checkout are front-end pages rendered by your theme, so the same hook covers them. Prices, variation names and anything WooCommerce swaps in with JavaScript after the page loads are picked up as they appear.

Page caches are fine

The snippet is the same HTML for every visitor, so it caches like the rest of your footer. The translation itself happens in the visitor's browser, after the cached page arrives.

Block themes work the same way

A block theme has no footer.php, but it still calls wp_footer(). The hook is the contract, not the template file.

Steps taken from WordPress's own documentation

Read on 11 October 2026. Platforms move their menus; if a step no longer matches, their page is the one to trust.

Somewhere else?

All platforms

WordPress, in every language

Free tier available. No credit card required.

Get started free