Skip to content
Let's talk about your project
tW Translate Plus

tW Translate Plus

CHF 199

Lightweight multilingual translations with engine of choice per site (gpt-oss-20b, OpenAI or Google Cloud Translation v3, each site with its own key): a single WordPress object, language‑prefixed URLs, site glossary and manual overrides.

SKU: tw-translate-plus Category:

Description

tW Translate Plus makes a WordPress site multilingual without duplicating anything: a single page, a single product, a single order. The plugin keeps for each text the original, the automatic translation and any manual correction, and serves each language at its address (/en/, /de/…), indexable by Google.

What it translates

  • Content: titles, texts, excerpts, menus, categories, SEO descriptions, WooCommerce products.
  • Everything the theme outputs: template labels, page builder sections, plugin texts, alt, title attributes, field placeholders.
  • Texts passed to JavaScript (new in 1.20): configurators, forms and components that receive their texts via wp_localize_script are translated without touching IDs, URLs and technical data.

Real coverage, not just a percentage

The language bar counts the texts that the plugin knows. The Real page coverage check (Status tab) opens each page in the main language and in every active language, lets the scripts run and compares what the visitor actually reads. Texts remaining in the original language are listed page by page; brands and proper names can be marked with a click as “same in all languages”.

Engine of choice, costs under control

  • Google Cloud Translation v3 or OpenAI, with the site key: each client pays only for their own translations.
  • Daily character limit, background queue, no engine calls during visits.
  • Translation memory: an identical text translated once is not paid again.
  • Site glossary: brands not to translate and consistently coherent terminology.

Designed for site managers

  • Manual corrections from the Translations tab: they remain even when the engine re‑translates.
  • Languages can be previewed before publishing them in the selector, hreflang and sitemap.
  • Complete multilingual SEO: reciprocal hreflang, x-default, og:locale, language sitemap, translated URLs.
  • Compatible with LiteSpeed Cache, WooCommerce, Elementor, multisite; migration guided by WPML.

Versions

Changelog

Perpetual license: you pay once only, no annual fee.

  • WordPress 6.2 or later
  • PHP 7.4 or newer
  1. 1.20.3Latest version
    • News · Slovak, correct WPML import for terms, non‑Latin slugs and redirect, v1.20.3
    • Fix · WPML import strings step crashed on undefined $copies, v1.20.2
    • Fix · coverage check button; rich update details v1.20.1
    • News · translate script data and check real page coverage v1.20.0
    • Fix · do not requeue rendered translations; hide WPML tab after migration v1.19.5
    • Fix · short description whitespace, WPML variation descriptions v1.19.4
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
  2. 1.20.2
    • Fix · WPML import strings step crashed on undefined $copies, v1.20.2
    • Fix · coverage check button; rich update details v1.20.1
    • News · translate script data and check real page coverage v1.20.0
    • Fix · do not requeue rendered translations; hide WPML tab after migration v1.19.5
    • Fix · short description whitespace, WPML variation descriptions v1.19.4
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
  3. 1.20.1
    • Fix · coverage check button; rich update details v1.20.1
    • News · translate script data and check real page coverage v1.20.0
    • Fix · do not requeue rendered translations; hide WPML tab after migration v1.19.5
    • Fix · short description whitespace, WPML variation descriptions v1.19.4
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
  4. 1.20.0
    • News · translate script data and check real page coverage v1.20.0
    • Fix · do not requeue rendered translations; hide WPML tab after migration v1.19.5
    • Fix · short description whitespace, WPML variation descriptions v1.19.4
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
  5. 1.19.5
    • Fix · do not requeue rendered translations; hide WPML tab after migration v1.19.5
    • Fix · short description whitespace, WPML variation descriptions v1.19.4
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
  6. 1.19.3
    • Fix · never redirect LiteSpeed ESI sub-requests v1.19.3
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
  7. 1.19.2
    • News · WPML import of visible custom field values v1.19.2
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
  8. 1.19.1
    • Fix · detect JetEngine lazy listing requests v1.19.1
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
  9. 1.19.0
    • News · translate HTML fragments in front-end AJAX responses (JetEngine, Woo) v1.19.0
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
  10. 1.18.3
    • Fix · original slug for trashed WPML copies v1.18.3
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
  11. 1.18.2
    • Fix · never queue search/feed/404 page texts v1.18.2
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
  12. 1.18.1
    • Fix · entity-insensitive page text lookup v1.18.1
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
    • Fix · progress bar shows only the share of translated texts v1.12.1
  13. 1.18.0
    • News · translate WooCommerce fee names; texturized page texts in WPML import; --include-trashed v1.18.0
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
    • Fix · progress bar shows only the share of translated texts v1.12.1
    • News · editor translation box + Translate now, hard run deadline v1.12.0
  14. 1.17.3
    • News · switcher labels attribute v1.17.3
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
    • Fix · progress bar shows only the share of translated texts v1.12.1
    • News · editor translation box + Translate now, hard run deadline v1.12.0
    • News · translation memory, self-healing errors, simpler API page v1.11.0
  15. 1.17.2
    • Fix · texturized lookup also for single_post_title v1.17.2
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
    • Fix · progress bar shows only the share of translated texts v1.12.1
    • News · editor translation box + Translate now, hard run deadline v1.12.0
    • News · translation memory, self-healing errors, simpler API page v1.11.0
    • News · self-driven background worker, gpt-oss-20b default engine v1.10.0
  16. 1.17.1
    • Fix · WPML import uses whole texts, texturized titles, clean queue; names switcher + order v1.17.1
    • News · WPML importer, translated URLs + 301, Elementor links, AJAX language v1.17.0
    • Fix · admin hint when no language is published, no page cache while translations are pending v1.16.3
    • Fix · translate product titles, protect site name, normalized echo repair, worker liveness v1.16.2
    • Fix · worker restart on stale hint, accept confirmed-unchanged texts, session page fetch, rounded switcher styles v1.16.1
    • News · page-level HTML translation of everything visible, per-variant switcher previews v1.16.0
    • News · [tw_language_switcher] shortcode with bundled SVG flags v1.15.0
    • Fix · reject echoed translations, gpt-oss-120b, security/SEO/perf review fixes v1.14.0
    • Performance · parallel engine requests, fastest OpenRouter provider v1.13.0
    • Fix · browser autofill no longer overwrites API keys v1.12.2
    • Fix · progress bar shows only the share of translated texts v1.12.1
    • News · editor translation box + Translate now, hard run deadline v1.12.0
    • News · translation memory, self-healing errors, simpler API page v1.11.0
    • News · self-driven background worker, gpt-oss-20b default engine v1.10.0
    • News · automatic indexing, 45s queue runs, OpenAI-compatible engine v1.9.1
  17. 1.17.0
    • feat(migrazione): import from WPML (tab «WPML Migration» and wp twtr wpml-import: contents, products and variants, Elementor templates, menu items, categories and attributes, media, strings; no translation re‑done by the engine (origin=wpml, locked). Report with notes to check, repeatable and cancelable import.
    • feat(url): translated addresses per language (Twtr_Slugs, segment map: pages also nested, products, product base, categories) without rewrite rule; 301 from original slug to translated one; 301 redirect for old addresses without page (only on 404).
    • feat(elementor): internal page links (Elementor, editor) point to the current language (language selectors excluded); the raw content of pages built with Elementor is no longer queued (the page level translates it: no unnecessary costs).
    • feat(ajax): AJAX requests (forms, cart, plugin responses) originating from a translated page use that page's language (same‑site Referrer).
    • feat(wpml): as long as WPML is active tW Translate remains on hold on the public site (admin notice with link to migration).
  18. 1.16.3
    • ux(selettore): with fewer than two published languages the shortcode shows administrators a notice («no language published: check Published in tW Translate → Languages») instead of disappearing without explanation; visitors continue to see nothing.
    • perf(pagina): a page translated with newly discovered texts (still being translated) is not cached by LiteSpeed, so subsequent visitors receive the freshly translated texts instead of the partially Italian version until the next cache purge.
  19. 1.16.2
    • fix(qualità): product titles remained in Italian: the model instructions said not to translate “product names”, and gpt-oss left “Caviale di lenticchie all'aglio nero bio 90g”. Now the instructions ask to translate titles and names made of common words (leaving only brands), remind that every text is shown to visitors of the version in that language, and protect the site name (get_bloginfo('name'))
    • fix(qualità): after the update (DB version 5) translations that remained in Italian and differ from the original only by entities or typography are also re‑queued (all’aglio / all’aglio)
    • fix(worker): after a cycle ended the worker appeared “active” for 3 minutes, so the newly discovered texts (e.g., the 410 theme texts found by opening a page) waited. Now there is an explicit in‑progress cycle indicator: the new job starts immediately.
  20. 1.16.1
    • fix(coda): after the update the worker stayed idle with texts in the queue: rows re‑queued by the migration didn’t notify it and it trusted a zero counter. Now, if the counter says zero, it really checks the queue (an indexed query, at most once a minute) and restarts on its own.
    • fix(qualità): names, addresses and brands that correctly stay the same (“Choco Duo”, “Alla Monda 12, 6515 Gudo”) were flagged as “returned without translation” errors. Now a text that returned unchanged in a group is requested again individually (in parallel if there are multiple): if the model confirms it unchanged it is accepted. After the update such errors re‑enter the queue.
    • fix(editor): “Translate now” opens the translated pages with the user’s session, so it also works with the shop in “coming soon” or maintenance mode, where an anonymous visitor sees only the waiting page.
    • perf(pagina): the finished page translation is skipped for pages over 4 MB or with the PHP process near the memory limit (the page is output untranslated instead of a critical error).
    • ux(selettore): faithful shortcode previews (the style wasn’t loaded in the admin) and new style: flags with rounded corners and subtle shadow, current language with a ring, pill‑shaped abbreviations, tab‑style dropdown menu; inherits the theme’s colors and fonts.
  21. 1.16.0
    • feat(pagina): page translation finished, like a browser translator (class-twtr-html.php). In additional languages the generated HTML is read in full and every visible text is translated, together with <title>, meta description/Open Graph, alt, title, placeholder, aria-label and button texts: also those that the theme or page builder outputs on its own and that no WordPress filter sees (sections built by reading the content, labels in templates, Elementor widgets, markup of other plugins). On oasidellespezie.ch the Italian “Caratteristiche & Proprietà”, “Note del Maestro Speziere” and the product sheet values remained. New texts are queued only once per language (context html, shared by all pages: a repeated label on 900 products is a single line) and the translations already done are reused in any context. Excluding scripts, style, code, pre, textarea, svg, the admin bar, class="notranslate", translate="no", texts without letters, URLs and e‑mail and the translations already produced by the filters. A single indexed query per generated page; LiteSpeed caches the result. Deactivatable with the filter twtr_translate_html.
    • feat(editor): “Translate now” opens the translated pages of the content once (bypassing the cache), so it immediately also translates the theme texts of that page, and the “Translations” panel counts them.
    • ux(languages): preview of each shortcode variant next to the code to copy.
  22. 1.15.0
    • feat(selector): shortcode [tw_language_switcher] to place flags on any theme or page builder (Elementor: “Shortcode” widget, also in the Elementor Pro header; Gutenberg: “Shortcode” block), and PHP function twtr_language_switcher(). Variants: style="flags" (default), flags-names, names, codes, dropdown (dropdown menu without JavaScript); current="hide"; size="24"; flags="en:us" to change the flag of a language; class="...". Every link leads to the same page in the other language, with hreflang, lang e aria-current. Shows only published languages and nothing if there is only one.
    • feat(flags): 24 SVG flags included in the plugin (assets/flags/, also USA and Switzerland), displayed as images: identical on every system (the flag emojis on Windows do not exist and become “DE”, “FR”) and without conflicts with the theme’s CSS. Filter twtr_flag_code to change a flag across the whole site.
    • feat(admin): in the tab Languages the “Site Flags” panel with preview, ready shortcodes and the “Copy” button, and options for developers.
  23. 1.14.0
    • fix(qualità): texts returned untranslated. gpt-oss-20b sometimes returned the Italian sentence unchanged, which was saved as “translated” (on oasidellespezie.ch ~7% of the gpt-20b texts: title and product sheet in Italian under /de/). Now any 4‑word+ sentence that comes back identical is requested again on its own and, if it remains the same, counts as an error (re‑tried automatically), never as a translation; the memory no longer copies these cases; upon update (DB version 4) the rows already hit on all sites return to the queue.
    • feat(engine): default model gpt-oss-120b ( measured: correct translation in ~1 s, against errors like «aglio nero» → «noci nere» of the 20b; ~4× the cost, always fractions of a cent per product). Sites left on the old default automatically move to 120b; a manually selected model is not touched.
    • fix(worker): the background chain stopped after each cycle: the loopback with a 10 ms timeout (as spawn_cron) often didn’t even start on HTTPS. Now 1 s, with the page already detached from the visitor. At most 3 sites on the network translate together (twtr_worker_max_sites), to avoid taking PHP processes away from visitors.
    • security: the engine settings (key, service address, model, limits) can be changed only by a site administrator; editors and shop managers see the page read‑only. Previously an editor could point the address to their own server and receive the key and all texts. Changing service deletes the saved key. The engine output is filtered before being saved (wp_kses with only the original text tags: nothing <script>/onerror injected). No redirects in requests to engines (SSRF), token_uri Google accepted only if it is Google’s, worker signature window 120 s, language packs downloaded only by those who can install them, the capability is no longer reassigned on each request (an administrator can remove it).
    • fix(seo): links mailto:, tel:, #ancora and related ones are no longer turned into broken URLs in translated pages; URLs of other network sites no longer receive the language prefix; hreflang with language‑only codes (de, fr, it, filter twtr_hreflang_code) instead of de-DE; when a translation is ready all page languages are flushed from the cache, so the other languages also update the hreflang.
    • perf: full LiteSpeed cache purge for theme texts occurs at most every 10 minutes (previously each cycle, i.e., every minute, even for Italian); queue writes in a single transaction per block and purges per context instead of per row; memory with a single twin per text; index claim; site settings stored per site also inside switch_to_blog().
  24. 1.13.0
    • perf(coda): parallel requests. With language models the queue sends up to 6 blocks at a time (Twtr_Openai::translate_many(), curl multi via WpOrgRequests, filter twtr_concurrency) and fetches 150 texts per run; blocks that fail in parallel due to a hiccup (misaligned response, network, 400, 429, 5xx) are automatically retried one by one, wrong key/credit/model are not. Tested with a mock server: text order always correct, no text left stuck.
    • perf(gpt-oss): on OpenRouter requests ask the fastest provider (provider.sort = throughput, filter twtr_openrouter_provider): measured on oasidellespezie.ch, 4,000 characters in a constant 2.2 s (Groq) instead of 3–12 s depending on the provider that appears. Combined with parallelism, a site like oasidellespezie.ch translates in minutes instead of days; «Traduci adesso» translates all product languages in a single round‑trip.
    • fix(scoperta): a previously translated text reused by the theme elsewhere (e.g. the SEO description built from the translated summary) is no longer queued as if it were original Italian.
    • docs: for a self‑hosted server (Ollama, vLLM) WordPress only allows ports 80, 443 and 8080 (filters http_allowed_safe_ports e http_request_host_is_external for others).
  25. 1.12.2
    • fix(api): when saving the “API translation” page the browser could fill the key field (empty) with a stored password, which was saved instead of the key: on oasidellespezie.ch the OpenRouter key was replaced by a 10‑character password (“Missing Authentication header”). Now the key fields tell password managers not to fill them (",", attributes for LastPass, 1Password, Bitwarden) and the plugin accepts only values that look like a real key (OpenRouter",", OpenAI",", other services at least 20 characters without spaces): otherwise the previously saved key remains and a notice explains why.autocomplete="new-password": the progress bar now shows only the percentage of texts translated (e.g. 1,343 out of 11,761 → 11%), no longer the minimum between texts and fully translated pages, which stayed at 1–2 % until almost every page was finished. 100 % only when nothing is pending or in error. Two heavy language queries have also been removed from the Languages tab. sk-or-…: panel sk-…«Translations»
  26. 1.12.1
    • ux(languages)in the editor of products, pages, posts and any type of public content: language status (green dot “Translated”, yellow “Translating: X of Y texts ready”, red with the number of errors, gray “Not yet queued”), “View” link to the translated page, link to edit manually and button
  27. 1.12.0
    • feat(editor)«Translate now» , which rereads the saved content, re‑queues its errors and translates its texts immediately (memory, then engine) ahead of everything else, within 40 seconds; the remaining work completes in the background. In listings a column with a dot per language, read with a single query per page. : background cycles were being terminated by LiteSpeed after ~120 s (“request already in process for 121 seconds, fail with 503”): the 45 s budget was checked only between blocks, and a request to gpt‑oss with the default reasoning exceeded 110 s. Now each cycle has a strict deadline: no request starts with less than 12 s, the timeout of each call is reduced to the remaining time, unprocessed texts return to the queue immediately (not after 10 minutes) and are not counted as errors.: “low” reasoning for gpt‑oss on OpenRouter (",") and Groq (","): measured on oasidellespezie.ch, 40 texts in 8.5 s for ~0.00008 $ instead of over 110 s; blocks of 3,000 characters for open models. , which rereads the saved content, re‑queues its errors and translates its texts immediately (memory, then engine) ahead of everything else, within 40 seconds; the remaining work completes in the background. In listings a column feat(memory)
    • fix(worker)translation memory.
    • perf(gpt-oss)Before calling the engine, the queue fills pending (or error) texts that have an identical twin already translated on the same site and in the same language (",", indexreasoning.effortreasoning_effort
  28. 1.11.0
    • : Twtr_Storage::fill_from_memory() memory_lookup, DB version 3): free, without engine and without consuming the daily limit. Copy only ready automatic translations, never manual overrides nor texts from other sites; texts re‑queued due to a glossary change are not «ready», so a copy always respects the current glossary. Within each block identical texts are sent only once. The Status tab shows reused texts and saved characters. On oasidellespezie.ch about 19,900 texts in queue were only ~5,300 different texts.
    • feat(errors): errors no longer stay idle: when you save or successfully test the engine configuration they immediately go back to the queue, and the worker retries them on its own once a day (credit reloaded, service back up). No button to press.
    • ux(API translation): simplified page: top box green/red «Works / Does not work» with the reason in plain words; for gpt-oss only the OpenRouter key with the 3 steps to obtain it; address and model in «Advanced Settings», like the spending limit; the «Save and test» button saves and translates a test word immediately. The status also updates automatically each queue cycle.
    • fix(gpt-oss): error messages of the compatible engine that name the used service instead of «OpenAI»; recognized OpenRouter management keys (cannot translate: «User not found») with the indication to create a normal API key; credit exhausted (402), non‑existent model and explained limits.
  29. 1.10.0
    • feat(worker): self‑sufficient background translation, without configuring anything on the server. New class-twtr-worker.php: the plugin automatically starts its own worker with a non‑blocking loopback request to its own admin-ajax.php (like spawn_cron() of the core), signed HMAC with a site‑specific secret; each cycle works up to 45 s (indexing, then queue) and, if work remains, launches the next cycle itself, so visits are not needed. A check at the end of the request (at most once a minute, no extra query: status in an'autoload option) restarts a broken chain. If the server blocks loopback, the queue advances after the page has already been sent to the visitor (fastcgi_finish_request / litespeed_finish_request) and the Status tab reports it. Automatic pause until midnight UTC at the daily limit and for 10 minutes if the engine errors; new texts in queue cancel it. One worker per site (lock). WP‑Cron remains registered and runs from the same lock: where it works, it helps. Previously, in a multisite with DISABLE_WP_CRON and system cron only on the main site (as on ticinoweb01), the subsites translated only by chance.
    • feat(engine): gpt-oss-20b is the default engine for sites not yet configured: engine «gpt-oss-20b and other open models», pre‑filled with OpenRouter (https://openrouter.ai/api/v1, openai/gpt-oss-20b); just paste the OpenRouter key. Sites already configured keep their own engine. For public services (OpenRouter, Groq, Together…) the key is mandatory, so a site without a key does not attempt requests destined to fail.
  30. 1.9.1
    • feat(indexing): automatic. The whole site is reread in the background (cron twtr_index_site, 30 s per pass, resumes where it left off) when it has never been indexed, when a new language is activated and then every 7 days (daily check twtr_daily_maintenance), so content published before activation, imported or edited without passing through save_postis also queued. During these passes the LiteSpeed cache is cleared only for content that actually has new text. The «Index whole site» button remains for those who want to reread everything immediately; the Status tab shows progress and the date of the last full read.
    • perf(coda): each cron run works up to 45 seconds (Twtr_Queue::process_for()) instead of a single block of 25 texts, and stops early if a block does not advance (daily limit, engine error, empty queue). On oasidellespezie.ch the queue translated 25–100 texts per hour.
    • feat(engine): new engine Compatible OpenAI for open models like gpt-oss or others, via any service with the same API (OpenRouter, Groq, Together, Ollama, vLLM): API address, key (optional) and model name per site. Same client, glossary in the prompt and reduced OpenAI blocks; if the server does not support JSON format the request is retried without it, and JSON is extracted even if the model wraps it in text. Requests use wp_safe_remote_request (no internal addresses, except filter http_request_host_is_external).
    • feat(update): plugin icon (assets/icon.svg + PNG 128/256, ticinoWEB colours) shown in Dashboard → Updates instead of the gray plug. The loader tw-release-updater.php moves to 1.1.0 and reads icons from the assets/ folder of any managed plugin; the mu‑plugin updates itself. The icon appears from updates after this version, because the already‑installed code reports it to WordPress.
  31. 1.9.0
    • fix(glossary): the glossary is site‑specific. Initially the terms were common to the whole network: «Casa dei Ponti», added on casadeiponti.ch, also appeared (and was applied) in the glossary of oasidellespezie.ch. Now the table has the column blog_id (DB version 2, unique key blog_id + termine) and each site sees, saves, deletes and applies only its own terms; changing a term re‑queues only that site’s translations. Glossary version, pairs to sync, CSV file and Google resources are also site‑specific.
    • feat(migrazione): on update every existing term is sent to the sites whose content actually contains it, i.e. the only sites where it had effect; a term that does not appear in any site is sent to all translating sites, so no term is lost. Google sites rebuild their resources on the next cycle.
    • feat(permessi): Glossary and translation API are no longer reserved for Super Admins: they are visible to administrators, shop managers and site editors, like the rest of the tW Translate menu (capability twtr_manage_translations, also assigned to already installed sites and to the shop manager role created by WooCommerce later). The network option «Data on uninstall» remains for Super Admins. The Glossary page in Network Admin has been removed, as it no longer makes sense.
    • fix(openai): «OpenAI response misaligned» no longer crashes the whole batch of 25 texts: when the model drops or merges segments the queue splits the batch in half and retries, isolating the problematic text. On oasidellespezie.ch this error had parked 64 texts.
  32. 1.8.0
    • feat(update): updates via the native header Update URI and the generic loader includes/tw-release-updater.php (TW_Release_Updater), shareable by all ticinoWEB plugins without ever modifying it; automatic updates enabled (can be disabled with TW_RELEASE_AUTO_UPDATE). The plugin installs and updates the loader itself as a mu‑plugin wp-content/mu-plugins/tw-release-updater.php, so updates also work in network admin and in the cron of the main site of a multisite, and on any server where the plugin is activated. Removed includes/class-twtr-updater.php (1.7.0), replaced by this.
  33. 1.7.0
    • feat(multisite): each site translates only with its own key. Engine, OpenAI key / Google credentials, model, bucket, daily limit and character counter move from network settings to site settings (twtr_engine, twtr_usage, not autoload). A site without its own key does not translate: no fallback to a network key, constants TWTR_OPENAI_API_KEY / TWTR_GOOGLE_* / TWTR_PROVIDER or environment variables, which would translate every site at the expense of a single client. Previously one engine and one key served all sites: on 2026‑09‑23 Synergy (Google) translated with Casa Dei Ponti’s OpenAI key, and the single limit of 500 000 characters exhausted by one site stopped the others as well.
    • feat(queue): without credentials the queue does not start (no cron) and wp twtr queue / «Process now» explains why; saving the credentials restarts the queue. Limit and counter are those of the site.
    • feat(glossario): terms still common to the network, but Google sync status per site (each site has resources in its own Google project); changing terms causes each Google site to resynchronize on the next cycle. Google OAuth token and service account key stored per site (also inside a switch_to_blog()).
    • feat(admin): the «Translation API» page configures the current site and warns if the key is missing; Network Admin shows only the Glossary. The Queue tab and wp twtr status show engine, last digits of the key, used characters and site limit.
    • feat(cli): wp twtr legacy-keys [--assign=openai|google] [--purge] to assign the correct site the network credentials from previous versions and delete them from the network.
    • feat(update): updates from the release repo gfrino/ticinoweb-wp-themes-and-plugin-releases (§13), with support for the automatic updates toggle.
ticinoWEB Assistant Online