Docs · v1.0.1

Introduction

ShapeTranslate turns one WordPress site into a multilingual site. Each post, page or term gets a language, its translations are linked together, and visitors switch languages with one click.


Video tutorial

Watch the full walkthrough first, then use the pages in this guide as a reference.

What you can do

Three ideas to know first

  • Default language. The language your existing content is written in. Content without a language uses it.
  • Translation group. An original and its translations are linked as one group. The switcher uses this group to find the same page in another language.
  • A translation is its own post. It has its own title, slug and content, so you can edit it freely.

How to read this guide

Screens in this guide carry numbered red circles 1. The list under each screen explains every number, so you can follow along in your own dashboard.

System Requirements

Check these before you install ShapeTranslate.


Server & WordPress

  • WordPress6.4 or later. Tested up to 7.1.
  • PHP7.4 or later. Tested up to PHP 8.4.
  • PermalinksAny pretty permalink structure for directory URLs. Plain permalinks work with the query argument format.
  • BrowserAny current Chrome, Firefox, Safari or Edge for the admin screens.

For subdomains or separate domains

  • Every language host must point to the same WordPress installation.
  • Every host needs its own SSL certificate.

Installation

Install and activate ShapeTranslate in under a minute.


ShapeTranslate is free in the WordPress Plugin Directory, so you can install it without downloading anything.

  1. Open Add PluginGo to Plugins → Add Plugin. Older WordPress versions call the menu Add New Plugin.
  2. SearchType ShapeTranslate in the Search Plugins box and keep the filter on Keyword. The results load as you type.
  3. InstallClick Install Now on the ShapeTranslate card by ShapeKode.
  4. ActivateThe button turns into Activate. Click it. ShapeTranslate opens the Setup Wizard on the next page load.
Animation: Plugins, Add Plugin, search ShapeTranslate, Install Now, then Activate
Walkthrough: install from WordPress.org

Or upload the zip file

Use this when you have shapetranslate.zip, for example on a site that can't reach WordPress.org.

  1. Open the uploaderGo to Plugins → Add Plugin → Upload Plugin. Older WordPress versions call the menu Add New Plugin.
  2. Choose the fileSelect shapetranslate.zip as it is, without unzipping it, and click Install Now.
  3. ActivateClick Activate Plugin. ShapeTranslate opens the Setup Wizard on the next page load.
Animation: Plugins, Add Plugin, Upload Plugin, choose shapetranslate.zip, Install Now
Walkthrough: upload the zip

Upload by FTP

  1. UnzipUnzip shapetranslate.zip on your computer.
  2. Upload the folderUpload the shapetranslate folder to wp-content/plugins/.
  3. ActivateGo to Plugins and click Activate under ShapeTranslate.

After activation

A new ShapeTranslate menu appears in the admin sidebar with these screens:

MenuUse it to
ShapeTranslateAdd and manage languages.
String TranslationTranslate site title, tagline, widgets and theme strings.
TranslationsSee what is translated and what is missing.
Setup WizardRun the first-time setup again.
SettingsURLs, content types, sync, switcher, SEO and import/export.

Setup Wizard

Five short steps that make your site multilingual. Find it at ShapeTranslate → Setup Wizard.


The wizard screen

The progress strip at the top shows the five steps; the highlighted one is where you are. Continue saves the step and moves on. Back returns without losing anything.

Animation: the five Setup Wizard steps, from Site Language to Finish Setup
Walkthrough: all five steps

The five steps

  1. Site LanguageChoose the language your existing content is written in. It becomes the default.
  2. LanguagesAdd every language you want to offer: type to search, pick one, click Add language. Remove takes one out; content already assigned to it keeps its language.
  3. Language URLsChoose how URLs show the language (see URL Formats) and whether the default language shows its prefix.
  4. Language SwitcherChoose the label, the layout and, optionally, a menu to add the switcher to.
  5. Ready to TranslateCopy the [shapetranslate_switcher] shortcode if you need it. Click Finish Setup.
Pick the URL format carefullyChanging it later changes every public link. If you change it, clear your page and CDN caches.

Languages Screen

Add, edit, enable, reorder and delete languages at ShapeTranslate → ShapeTranslate.


The language list

Languages screen with the language list
What you see
  1. 1Add Language. Opens the form below to add a new language.
  2. 2Language. Name, native name and the row actions Edit and Delete. The default language can't be deleted.
  3. 3Locale, code, URL slug. The slug is what appears in the URL, like /bn/.
  4. 4Status. Enabled or Disabled. Use Make default to change the default language, and Disable to hide a language for now.
  5. 5Order. The arrows move a language up or down. The switcher follows this order.

Change the default language

  1. Enable the languageOnly an enabled language can be the default.
  2. Click "Make default"Under the language's status. You'll see "Default language updated."
Deleting a languageA language still assigned to content or to a menu can't be deleted. Move or delete that content first. Deleting a language never deletes posts.

Add or Edit a Language

Click Add Language on the Languages screen, or Edit under a language.


The language form

Add Language form filled from the German preset
What you see
  1. 1Choose a language. Pick from the list. Every field below fills itself.
  2. 2Name & native name. "German" is shown in the admin, "Deutsch" to visitors.
  3. 3Locale & code. The WordPress locale (de_DE) and ISO code (de). Leave the preset values as they are.
  4. 4URL slug. Must be unique. Example: yoursite.com/de/.
  5. 5Domain. Only for the separate-domain format, like example.fr. Leave empty otherwise.
  6. 6RTL. Tick for Arabic, Hebrew, Urdu, Persian and other right-to-left languages.
  7. 7Enabled. Untick to prepare a language without showing it to visitors yet.
  8. 8Add Language. Saves it. You'll see "Language added."

Tips

  • Always start from Choose a language. The preset fills the locale and code correctly.
  • Keep URL slugs short: bn reads better than bangla.
  • Add a language as disabled to prepare translations before visitors see it.

URL Formats

Decide how the language appears in your web addresses. Set it at ShapeTranslate → Settings → URL.


URL settings

Settings, URL tab
What you see
  1. 1URL behavior. How the language appears in the address. See the table below.
  2. 2Default prefix. Hide it to keep your current URLs (/about/), and give only other languages a prefix (/bn/about/).
  3. 3Visitor language. Sends a first-time visitor on the home page to their browser's language. A shared link always wins.

Compare the formats

FormatExampleGood for
Directory (default)yoursite.com/bn/about/Most sites. Needs pretty permalinks.
Subdomainbn.yoursite.com/about/Each subdomain points to this WordPress, with its own SSL certificate.
Separate domainyoursite.com.bd/about/Country domains. Set each language's Domain on the Languages screen.
Query argumentyoursite.com/about/?lang=bnSites without pretty permalinks.
After changing the formatPublic links and canonical URLs change. Check your menus and clear page or CDN caches.

Translate Posts & Pages

Works the same for posts, pages and every public post type you enable under Settings → Content.


The Language box

The Language box sits in the editor sidebar. Language is the language of this post; new posts start in the default language. Under Translations, ✓ marks this post, ✎ edits an existing translation and + creates a missing one.

Create a translation by hand

  1. Save the original firstThe original needs a language before it can be translated. Click Save or Publish once.
  2. Click + next to the languageShapeTranslate creates a draft holding the title, content, excerpt, featured image, categories, tags and custom fields. You'll see "Translated draft created and linked."
  3. Translate the textReplace the text with the translation. Change the slug for a translated URL.
  4. PublishThe switcher now links both pages to each other.
Animation: the Language box, clicking + next to FR, translating the French draft and publishing it
Walkthrough: translate a post into French

Posts List & Language Filter

Every translatable list (Posts, Pages and custom post types) gets two columns and an admin-bar language filter.


The list screen

  • Language column: the language of each row.
  • Translations column: click + to create a translation, ✎ to edit one.
  • Language filter in the admin bar: shows only content in one language, or "Show all languages". New posts start in the chosen language.
Animation: the Language and Translations columns, then filtering the Posts list to Français from the admin bar
Walkthrough: columns and the language filter

What the icons mean

IconMeaning
✓This row's own language.
✎A translation exists. Click to edit it.
+Missing. Click to create the translation.

Translations Dashboard

One table at ShapeTranslate → Translations that shows what is translated and what is missing across the site.


The dashboard

  • One column per language. Read across a row to see that item in every language.
  • Cells. ✓ done, ✎ draft, + click to create the translation.
  • Filters. Content type, language and status: missing, completed or draft translations.
  • Search. Find content by title.
Animation: the language columns and cell icons, then filtering to missing French translations, then draft translations, then searching for coffee
Walkthrough: columns, filters and search

Good ways to use it

  • Filter by Missing translations and one language to get a to-do list.
  • Filter by Draft translations to find work that is not published yet.

Categories & Tags

Translate categories, tags and any taxonomy you enable under Settings → Content.


Translate a term

  1. Open Posts → CategoriesEach term has a Language field, and the list has Language and Translations columns.
  2. Edit a term and click +ShapeTranslate creates a linked term named like News (Français) with the slug news-fr.
  3. Rename itSet the translated name and slug, then click Update.
Posts, Categories screen with Language and Translations columns
The Categories screen
  1. 1Language. Choose the language when you add a new category.
  2. 2Language column. The language of each term, like EN or FR.
  3. 3Translations column. One flag per language. ✓ is the term itself, ✎ edits an existing translation, + creates a missing one.
Edit Category screen with Language and Translations fields
Edit a term
  1. 1Language. The language this term belongs to.
  2. 2Translations. Click ✎ to open a translation, or + to create one. Then set the translated name and slug and click Update.

When you translate a post, its categories and tags switch to their translations automatically.

Media

Give images a different title, alt text, caption and description in each language.


Turn it on

  1. Open Settings → ContentTick Translate media titles, alternative text, captions, and descriptions.
  2. Edit an imageThe attachment details now have a Language field, and the Media Library gets Language and Translations columns.
  3. Create the translationClick + next to a language. ShapeTranslate creates that language's media record. Type the translated title, alternative text, caption and description, then click Update.
Settings, Content tab with the Media option ticked
Step 1: turn on media translation
  1. 1Content tab. Open ShapeTranslate → Settings → Content.
  2. 2Media. Tick the option and click Save Changes at the bottom of the page.
Edit Media screen with the Language box
Step 2: translate an image
  1. 1Language. The language of this media record.
  2. 2Translations. ✓ is this record. + creates the record for a language that has none yet.
  3. 3Add a translation. Click +, then fill in the title, alternative text, caption and description in that language.
Media Library list with Language and Translations columns
The Media Library
  1. 1Language column. The language of each media record.
  2. 2Translations column. ✓ is the record itself. + creates the translation for that language straight from the list.
No duplicate filesEach language gets its own media record pointing at the same file. Nothing is uploaded twice.

String Translation

For text that isn't a post: site title, tagline, date and time formats, widget text and strings registered by themes and plugins. Find it at ShapeTranslate → String Translation.


The string editor

String Translation screen
What you see
  1. 1Group and language. Narrow the list, for example "Widgets" strings in বাংলা.
  2. 3Translation. Type the translated text. Empty means the original is shown.
  3. 4Save translations. Saves every field on the page.

String groups

WordPressWidgetsYour theme & plugins

WordPress holds the site title, tagline, date format and time format. Widgets holds widget titles and text. Strings registered with shapetranslate_register_string(), and plugins that ship a wpml-config.xml file, add their own groups.

Switcher Placements

The switcher sends a visitor to the same page in another language. A floating switcher is on from day one, so every language is reachable right after setup.


Where you can place it

WhereHow to add it
Floating switcherOn by default. Settings → Switcher → Floating switcher.
Language Switcher blockAdd the block anywhere in the block editor or Site Editor.
Navigation blockInside a Navigation block, add "Language Switcher". It can show as a submenu.
Classic menuAppearance → Menus → ShapeTranslate box → Language switcher → Add to Menu.
Shortcode[shapetranslate_switcher] in any post, page or widget.
Classic widgetAppearance → Widgets → "Language Switcher".
Elementor"Language Switcher" widget in the ShapeTranslate category, with full style controls.
Theme template<?php shapetranslate_language_switcher(); ?>

What it looks like

On the demo site, the switcher sits in the header menu, and the floating switcher is on.

Site header with the language switcher open, and the floating switcher on the right
On the site
  1. 1Menu switcher. Added from Appearance → Menus. Hover or click it to open the list of languages.
  2. 2Floating switcher. Fixed to the edge of the screen. Change its position and layout under Settings → Switcher.

Add it to a classic menu

Appearance, Menus with the ShapeTranslate box open
Appearance → Menus
  1. 1ShapeTranslate box. Open it in the Add menu items column.
  2. 2Language switcher. Tick it.
  3. 3Add to Menu. Adds the switcher to the menu on the right.
  4. 4In the menu. Drag it into place, then click Save Menu.

Add the block

Block inserter showing the Language Switcher block
Block editor or Site Editor
  1. 1Language Switcher block. Click + at the top left, search for "Language Switcher" and click the block. It works in posts, pages, templates and template parts.

Add it with Elementor

Elementor widget panel showing the Language Switcher widget
Step 1: find the widget
  1. 1Language Switcher (globe icon). Search for "Language Switcher" in the Elements panel, or open the ShapeTranslate category. Drag it onto the page. The one with the WordPress icon is the classic widget; use the globe one for full style controls.
Elementor editor with the Language Switcher widget selected
Step 2: set it up
  1. 1Languages. Layout, label, flags, which languages to show, hiding the current language and what to do when a translation is missing.
  2. 2Style. Colors, typography, flag size, dropdown and spacing.
  3. 3The switcher. Shows on the canvas as you change the settings. Click Publish to save.
Turn off the floating switcherOnce your own switcher sits in the menu or header, untick "Show a floating switcher on the site".

Switcher Settings

Site-wide defaults for every switcher, at ShapeTranslate → Settings → Switcher.


The Switcher tab

Settings, Switcher tab
What you see
  1. 1Settings tabs. The switcher has its own tab.
  2. 2Label & layout. Show "বাংলা", "Bengali" or "BN", as a list or a dropdown.
  3. 3Missing translation. When a page has no translation: hide the language, show it as unavailable, link to that language's homepage, or keep the current URL.
  4. 4Visibility. Hide the current language, show flags, or show disabled languages.
  5. 5Floating switcher. Fixed to the screen edge. Choose one of six positions and a layout.
  6. 6Ready-made shortcode. Updates as you change the controls above. Click Copy and paste it anywhere.

Override per placement

A single block, menu item or shortcode can use its own settings. The values on this tab are only the defaults.

Site Editor (Block Themes)

Translate templates, template parts and navigation menus in block themes.


Translate a header or footer

  1. Open the partAppearance → Editor, then open a template, template part or navigation menu.
  2. Open the Languages panelFrom the editor's top toolbar.
  3. Create or adopt a version+ creates a version in another language. Use an existing one adopts a part you already have.

A language without its own version uses the default language's version automatically.

Page Builders

Headers, footers, popups and templates are translated per language, and their display rules follow the language.


Supported plugins

Elementor & Elementor ProElementor Header & Footer BuilderEssential AddonsElementsKitHappy AddonsRoyal Elementor AddonsElement PackJeg KitYoast SEORank MathSEOPress

Yoast SEO, Rank Math and SEOPress keep their own title and meta description per translation, and ShapeTranslate adds the language links next to them.

Settings Overview

ShapeTranslate → Settings has seven tabs. Each tab saves on its own with Save Changes.


The tabs

TabWhat you set there
GeneralDefault language and enabled languages.
URLURL format, default-language prefix, browser language detection. See URL Formats.
ContentTranslatable post types and taxonomies, a default category per language, and media translation.
SynchronizationWhat stays the same across languages after the first copy.
SwitcherSwitcher defaults, floating switcher, shortcode builder, menu languages and theme locations.
SEOhreflang links, x-default, one sitemap per language.
AdvancedDelete data on uninstall (off by default), export and import.

Screenshots of the URL, Content and Switcher tabs are on URL Formats, Media and Switcher Settings.

General

Settings, General tab
Settings → General
  1. 1General tab. The first tab under ShapeTranslate → Settings.
  2. 2Default language. Used for content with no language and for URLs without a language prefix.
  3. 3Enabled languages. Untick to hide a language from the site and the switcher. Its translations are kept.

Synchronization

Settings, Synchronization tab
Settings → Synchronization
  1. 1Synchronization tab. A new translation always starts as a full copy. This tab decides what stays linked after that.
  2. 2Keep synchronized. A ticked item changes in every language when you edit it in one.

SEO

Settings, SEO tab
Settings → SEO
  1. 1SEO tab.
  2. 2Alternate language URLs. Adds hreflang links and an x-default link so search engines show the right language.
  3. 3Sitemap. One sitemap per language under a shared index.

Advanced

Settings, Advanced tab with export and import
Settings → Advanced
  1. 1Advanced tab.
  2. 2Uninstall behavior. Off by default, so your translations survive an uninstall. Deactivating never deletes data.
  3. 3Settings Export. Downloads your settings as a JSON file.
  4. 4Settings Import. Upload the JSON file or paste it, then click Import Settings. See Import & Export.

Synchronization items

TaxonomiesCustom fieldsComment statusPing statusSticky statusPublished datePost formatPage parentPage templatePage orderFeatured image
A synced item changes everywhereWith "Featured image" synced, changing the image on the বাংলা post also changes it on the English one.

Import & Export

Move your ShapeTranslate settings to another site from Settings → Advanced.


Copy settings to a new site

  1. ExportClick Download Settings JSON. The file is named like shapetranslate-settings-2026-10-11.json.
  2. Install ShapeTranslate on the new siteAdd the same languages first. The import stops if a language in the file is not on the new site yet.
  3. ImportChoose the file, or paste the JSON, and click Import Settings.
Settings Export with the Download Settings JSON button
Step 1: export (Settings → Advanced)
  1. 1Download Settings JSON. Saves your languages and plugin settings as one file. Menu IDs are left out, because they differ on every site.
Settings Import with a JSON file chosen
Step 3: import on the new site
  1. 1What import does. Replaces the settings and the enabled languages. Every language in the file must already exist on this site.
  2. 2JSON file. Choose the file you downloaded.
  3. 3Or paste JSON. Paste the file's contents here instead.
  4. 4Import Settings. Runs the import. Your posts and translations are not touched.

Uninstall behavior

Deactivating never deletes data. Data is removed only when you tick Delete all ShapeTranslate data when the plugin is uninstalled and then delete the plugin.

Developer Quick Start

Everything public is a global function prefixed shapetranslate_ or a hook named shapetranslate_*.


Ground rules

  • Use the API after shapetranslate_loaded (or on init).
  • All functions are safe when ShapeTranslate is inactive: they return an empty value or a WP_Error.
  • A language reference can be a URL slug (bn), code, locale (bn_BD), language ID or record. Empty means the current language.
  • shapetranslate_translate_string() returns unescaped text. Escape it, or use shapetranslate_esc_html__().

Examples

Current language and a translated post
add_action( 'shapetranslate_loaded', function () {
    $slug  = shapetranslate_current_language();  // 'bn', 'en', …
    $bn_id = shapetranslate_get_post( 42, 'bn' ); // 0 when none
    $home  = shapetranslate_home_url( 'fr' );
} );
Make a theme string translatable
add_action( 'init', function () {
    shapetranslate_register_string( 'my-theme', 'footer_note', 'Made with care in Dhaka' );
} );

// In the template:
shapetranslate_esc_html_e( 'my-theme', 'footer_note', 'Made with care in Dhaka' );
Print a switcher in a theme template
<?php
shapetranslate_language_switcher( array(
    'display'              => 'native_name', // name | language_code
    'layout'               => 'dropdown',    // horizontal | vertical
    'show_flags'           => true,
    'unavailable_behavior' => 'home',        // hide | disabled | current
) );
?>

PHP Functions

From includes/api.php and includes/functions.php.


Languages

FunctionReturnsWhat it does
shapetranslate_is_active()boolShapeTranslate is booted and has at least one language.
shapetranslate_current_language( $field = 'slug' )mixedLanguage of the current request.
shapetranslate_default_language( $field = 'slug' )mixedThe default language.
shapetranslate_languages_list( $args = array() )arrayLanguages in order. Args: fields (slug or all), hide_disabled (true).
shapetranslate_get_language( $language = '' )array|nullThe full record for any language reference.
shapetranslate_get_language_field( $language, $field = 'slug' )mixedOne field of a language.
shapetranslate_is_rtl( $language = '' )boolWhether a language is right-to-left.
shapetranslate_home_url( $language = '' )stringHome URL in a language.

Posts and terms

FunctionReturnsWhat it does
shapetranslate_get_post( $post_id, $language = '' )intID of the translation, 0 when none.
shapetranslate_get_post_language( $post_id, $field = 'slug' )mixedLanguage of a post.
shapetranslate_get_post_translations( $post_id )arrayThe whole group, e.g. ['en'=>12,'bn'=>34].
shapetranslate_set_post_language( $post_id, $language )array|WP_ErrorAssign a language to a post.
shapetranslate_save_post_translations( $translations, $source_post_id = 0 )array|WP_ErrorLink existing posts as translations.
shapetranslate_get_term( $term_id, $language = '', $taxonomy = '' )intID of the translated term.
shapetranslate_get_term_language( $term_id, $field = 'slug', $taxonomy = '' )mixedLanguage of a term.
shapetranslate_get_term_translations( $term_id, $taxonomy = '' )arrayThe term's group.
shapetranslate_set_term_language( $term_id, $language, $taxonomy = '' )array|WP_ErrorAssign a language to a term.
shapetranslate_save_term_translations( $translations, $taxonomy = '', $source_term_id = 0 )array|WP_ErrorLink existing terms.
shapetranslate_is_translated_post_type( $post_type )boolThe post type is translatable.
shapetranslate_is_translated_taxonomy( $taxonomy )boolThe taxonomy is translatable.
shapetranslate_object_id( $id, $type = 'post', $return_original_if_missing = true, $language = '' )int|nullSame idea as WPML's icl_object_id().

Strings and switcher

FunctionReturnsWhat it does
shapetranslate_register_string( $group, $key, $original )string|WP_ErrorRegister a string. Call on init or later.
shapetranslate_translate_string( $group, $key, $fallback = '', $language_id = '' )stringTranslated string, unescaped.
shapetranslate__( $group, $key, $fallback = '', $language = '' )stringSame, by any language reference.
shapetranslate_e(), shapetranslate_esc_html__(), shapetranslate_esc_html_e(), shapetranslate_esc_attr__(), shapetranslate_esc_attr_e()string|voidEscaped and echo variants, same arguments.
shapetranslate_get_language_switcher( $args = array() )stringSwitcher HTML.
shapetranslate_language_switcher( $args = array() )voidEchoes the switcher.
shapetranslate_the_languages( $args = array() )stringEchoes the switcher; pass 'echo' => false to return it.

Shortcode & Blocks

Attributes for [shapetranslate_switcher] and the two switcher blocks.


Shortcode

Shortcode
[shapetranslate_switcher layout="dropdown" show_flags="true" hide_current="true"]
AttributeValuesDefault
displaynative_name, name, language_codenative_name
layouthorizontal, vertical, dropdownhorizontal
unavailable_behaviorhide, disabled, home, currenthide
hide_currenttrue / falsefalse
hide_missingtrue / false. Wins over unavailable_behavior.false
show_flagstrue / falsefalse
show_disabledtrue / falsefalse
aria_labelText for screen readersempty
classExtra CSS classempty

Defaults shown are the plugin's own. The values saved under Settings → Switcher replace them site-wide.

Blocks

  • shapetranslate/language-switcher: attributes display, layout, hideCurrent, hideMissing, unavailableBehavior, showFlags, showDisabled, ariaLabel.
  • shapetranslate/navigation-language-switcher: only inside core/navigation; adds dropdown (show as submenu).

Front-end CSS and JS handles: shapetranslate-switcher, shapetranslate-floating-switcher. The switcher markup has the class shapetranslate-switcher.

Hooks Reference

Every action and filter ShapeTranslate fires. filter changes a value; action runs your code at that moment.


Common recipes

Make a custom post type translatable
add_filter( 'shapetranslate_supported_post_types', function ( $post_types ) {
    $post_types[] = 'portfolio';
    return array_unique( $post_types );
} );
Copy a protected meta key into new translations
add_filter( 'shapetranslate_copy_post_meta_keys', function ( $keys, $sync ) {
    $keys[] = '_my_price_note';
    return $keys;
}, 10, 2 );
Run code when a translation is created
add_action( 'shapetranslate_translation_created', function ( $new_post_id, $source_id, $language ) {
    update_post_meta( $new_post_id, '_needs_proofreading', 1 );
    // $language is the language record: $language['url_slug'], $language['locale'] …
}, 10, 3 );
Keep the language cookie for 30 days instead of a year
add_filter( 'shapetranslate_language_cookie_lifetime', function () {
    return 30 * DAY_IN_SECONDS;
} );
Skip browser detection for bots
add_filter( 'shapetranslate_should_detect_language', function ( $allowed ) {
    $ua = isset( $_SERVER['HTTP_USER_AGENT'] ) ? (string) $_SERVER['HTTP_USER_AGENT'] : '';
    return $allowed && ! preg_match( '/bot|crawl|spider/i', $ua );
} );

All hooks

HookTypeArgumentsWhen / what

Translate Plugin Options

Make text saved in a WordPress option translatable, so get_option() returns the right language on the front end.


How it works

You declare an option, and the keys inside it that hold text. Every text value found there becomes a registered string. Translate it on the Strings screen, in the group named after the plugin or theme. The code that reads the option needs no change.

Declare with wpml-config.xml

Say a plugin saves its settings in the option my_plugin_settings:

What the option holds
my_plugin_settings = array(
    'button_text' => 'Book now',
    'api_key'     => 'abc123',
    'messages'    => array( 'success' => 'Thank you!', 'error' => 'Try again.' ),
);
wpml-config.xml
<wpml-config>
  <admin-texts>
    <key name="my_plugin_settings">
      <key name="button_text" />
      <key name="messages">
        <key name="success" />
        <key name="error" />
      </key>
    </key>
  </admin-texts>
</wpml-config>

api_key is not listed, so it is never registered or translated.

A single-value option

When the option itself is the text, declare its name with no children:

wpml-config.xml
<admin-texts>
  <key name="my_plugin_footer_note" />
</admin-texts>

Wildcards

A * in an option name is matched against the options the site actually has. Use it for options that repeat per item:

wpml-config.xml
<admin-texts>
  <key name="widget_my_plugin_*">
    <key name="title" />
  </key>
</admin-texts>

Translate the strings

  1. Load a page that reads the optionOpen any front-end page that uses it. The strings register the first time the option is read.
  2. Open the Strings screenFind the group named after your plugin or theme (for example plugins/my-plugin).
  3. TranslateType the translations. Visit the site in that language to check.
Settings screens stay safeTranslations are applied on the front end only. In wp-admin, the plugin's own settings form always shows the stored original, so saving it never overwrites the original with a translation.

Alternative: register one string in PHP

For a single value in your own code, skip the XML:

Register, then print
add_action( 'init', function () {
    shapetranslate_register_string( 'my-plugin', 'button_text', get_option( 'my_plugin_button' ) );
} );

// Where you print it:
shapetranslate_esc_html_e( 'my-plugin', 'button_text', get_option( 'my_plugin_button' ) );

Options whose names start with shapetranslate are never translated.

wpml-config.xml Reference

Configure custom post types, taxonomies, custom fields and strings in one XML file. Plugins that already ship this file work with no extra code.


Where ShapeTranslate looks

LocationUse
Root of each active pluginShipped by the plugin author.
Root of the active theme and its parent themeShipped by the theme author.
wp-content/mu-plugins/ and its sub-foldersMust-use plugins.
wp-content/shapetranslate/wpml-config.xmlYour own rules for a plugin that ships none. Read last, and safe from updates.

The file name is always wpml-config.xml. Changes are picked up automatically when a plugin or theme is activated, deactivated, switched or updated, and when the file's modified time changes.

A complete example

wpml-config.xml
<wpml-config>
  <custom-types>
    <custom-type translate="1">portfolio</custom-type>
    <custom-type translate="0">internal_log</custom-type>
  </custom-types>

  <taxonomies>
    <taxonomy translate="1">project_type</taxonomy>
  </taxonomies>

  <custom-fields>
    <custom-field action="translate">subtitle</custom-field>
    <custom-field action="copy">price</custom-field>
    <custom-field action="copy-once">gallery</custom-field>
    <custom-field action="ignore">_edit_lock</custom-field>
  </custom-fields>

  <admin-texts>
    <key name="my_plugin_settings">
      <key name="button_text" />
    </key>
  </admin-texts>

</wpml-config>

Post types and taxonomies

  • translate="1" makes the type or taxonomy available to translate. It includes non-public types such as page builder headers and templates. It does not tick the box in Settings: the site owner still decides what is translated.
  • translate="0" removes it completely. It cannot be turned on from Settings.

Custom fields

Declare what happens to a post meta key when a translation is created or synchronized.

ActionBehavior
copyCopied into a new translation, then kept in step with the original on every save (when custom field synchronization is on in Settings).
copy-onceCopied into a new translation, then left alone.
translateCopied into a new translation as a starting point, then left alone, so later saves never overwrite an editor's work.
ignoreNever copied. Also removes a key ShapeTranslate would otherwise copy. A missing or unknown action counts as ignore.

A declaration can never switch synchronization on. If a site turned custom field synchronization off, copy only seeds new translations, while ignore always applies.

Strings

<admin-texts> is covered in Translate Plugin Options.

What is read and what is applied

SectionStatus
custom-types, taxonomiesApplied
custom-fieldsApplied
custom-fields-textsRead, not applied
admin-textsApplied
gutenberg-blocksRead, not applied
custom-term-fieldsRead and exposed through shapetranslate_wpml_config_rules, not applied yet

Keys that use a lookup type or a search method other than wildcards are skipped, never guessed.

Control it from code

Add a file, adjust rules, or switch the feature off
// Read an extra file.
add_filter( 'shapetranslate_wpml_config_files', function ( $files ) {
    $files['my-addon'] = WP_CONTENT_DIR . '/my-addon/wpml-config.xml';
    return $files;
} );

// Adjust the parsed rules.
add_filter( 'shapetranslate_wpml_config_rules', function ( $rules ) {
    unset( $rules['post_meta']['price'] );
    return $rules;
} );

// Turn it off in wp-config.php:
define( 'SHAPETRANSLATE_WPML_CONFIG', false );

The key of each file (for example plugins/my-plugin) becomes the string group name.

Translate Emails from Any Plugin

Send an email in the recipient's language, with WordPress's own locale switching. ShapeTranslate follows it.


How it works

  1. Find the recipient's localeFor a user, call get_user_locale( $user_id ). It returns the locale saved in the profile.
  2. Switch to itCall switch_to_locale( $locale ). WordPress unloads the old translations and loads the new ones.
  3. Write and send the emailUse normal translation functions. ShapeTranslate strings and translated options answer in the same language.
  4. RestoreCall restore_previous_locale() so the rest of the request is unchanged.
Send an email in a user's language
$locale = get_user_locale( $user_id );
switch_to_locale( $locale );

wp_mail(
    $to,
    __( 'Welcome', 'my-plugin' ),
    shapetranslate_translate_string( 'my-plugin', 'welcome_body', 'Thanks for joining.' )
);

restore_previous_locale();

What follows the switch

TextFollows the switched locale?
Plugin and theme text (__(), _e())Yes. WordPress reloads the text domains on the switch.
Strings from shapetranslate_translate_string() and shapetranslate_esc_html__()Yes.
Options declared in wpml-config.xml admin-textsYes, also when the email is sent from wp-admin.
Email subject, heading and footer saved in an option you did not declareNo. Declare the option first.
An email template saved as a postNo. Translate the post, then load the translation yourself with shapetranslate_get_post().

If no enabled language uses the switched locale, ShapeTranslate leaves its answer as it was.

WordPress emails

WordPress sends the welcome and password-reset emails in the user's locale. ShapeTranslate saves it for you: a visitor who registers on a translated page gets that page's locale saved in the profile.

  • Accounts created in wp-admin are left alone, because they say nothing about the new user's language.
  • Users who can edit posts are left alone, because the locale is also the language of their dashboard.
  • A locale that is already saved is never replaced.
  • Users who registered before ShapeTranslate was installed have no locale. Set it in their profile.

Plugins that load their own translations

Most plugins need nothing. A plugin that loads its text domain by hand should load it again on each switch:

Reload on every locale change
add_action( 'change_locale', function ( $locale ) {
    load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
} );

Check that it works

  1. Register from a translated pageOpen a page with a language prefix, such as /bn/, and create an account.
  2. Check the profileThe user's locale is the one of that language.
  3. Trigger the emailUse the password reset. The email should arrive in that language, even if you started it from another one.
The plugin has to switchShapeTranslate cannot know who an email is for. A plugin that never calls switch_to_locale() sends in the language of the request. Ask its author to add the switch, or send the email yourself as shown above.

Hooks

HookUse
shapetranslate_current_language_idChange the language ShapeTranslate answers in.
shapetranslate_translate_optionDecide whether a declared option is translated on this request.
shapetranslate_should_switch_localeStop ShapeTranslate from changing the WordPress locale for a request.
shapetranslate_request_localeChange the locale used for a language-prefixed request.

REST API & Constants

Routes under shapetranslate/v1 and wp-config.php constants.


REST API (shapetranslate/v1)

RouteMethodPermission
/navigation-menus/{translation|language|link|candidates}POST, DELETE, GETmanage capability + edit_theme_options
/template-parts/…, /templates/… (block themes only)POST, DELETE, GETmanage capability + edit_theme_options
/site-editor/panel?postType=&slug=GETmanage capability

Core REST collections accept lang and lang_fallback.

Constants

ConstantUse
SHAPETRANSLATE_WPML_CONFIGSet to false to ignore wpml-config.xml files.
SHAPETRANSLATE_VERSION, SHAPETRANSLATE_PATH, SHAPETRANSLATE_URL, SHAPETRANSLATE_FILE, SHAPETRANSLATE_BASENAMERead-only plugin info.
SHAPETRANSLATE_LOCAL_DIRwp-content/shapetranslate. Place your own wpml-config.xml files here.

There are no WP-CLI commands in version 1.0.1.

Data Storage

Where ShapeTranslate keeps languages, translations and settings.


WhatWhere
Post language and groupHidden taxonomies shapetranslate_language and shapetranslate_post_group (not post meta).
Term language and groupHidden taxonomies shapetranslate_term_language and shapetranslate_term_group.
LanguagesOption shapetranslate_language_registry.
SettingsOptions shapetranslate_settings and shapetranslate_workflow_settings.
Registered stringsTables {prefix}shapetranslate_strings and {prefix}shapetranslate_string_translations.
Visitor's languageCookie shapetranslate_language (only the language slug).

FAQ & Troubleshooting

Quick answers to the questions we hear most.


Common questions

Language URLs show a 404 page.

Go to Settings → Permalinks and click Save Changes once. If the site uses plain permalinks, choose a pretty structure or switch ShapeTranslate to the query argument format.

The switcher doesn't show a language.

Check that the language is enabled. By default the switcher hides a language the site has nothing published in yet. Publish something in it, or change Missing translation under Settings → Switcher.

The switcher sends visitors to the home page.

That page has no translation in that language yet, and Missing translation is set to "Link to language homepage". Create the translation from the Translations dashboard.

Visitors see the wrong language on the home page.

With browser detection on, the home page must not be cached by a CDN or server cache. Exclude the home page there, or let it vary on the Accept-Language header.

I can't delete a language.

It's still assigned to content or a menu. Move that content to another language or delete it first. The default language can never be deleted; make another language the default first.

Will deactivating ShapeTranslate delete my translations?

No. Data is removed only if you tick "Delete all ShapeTranslate data when the plugin is uninstalled" under Settings → Advanced and then delete the plugin.

Can I switch from WPML or Polylang?

ShapeTranslate reads wpml-config.xml files from themes and plugins, and offers WPML-style functions such as shapetranslate_object_id(). While Polylang or WPML is active, ShapeTranslate leaves front-end routing to them.

ShapeTranslate 1.0.1 · by ShapeKode · GPLv2 or laterScreens are illustrations of the real admin pages; labels match the plugin.