== Changelog ==

= 1.1.0 =
* **[ADDED in Free and Pro]** Block theme support. Navigation, Page List, Site Title and Site Logo links point to the visitor's language; Query Loop blocks and archive pages list only the current language's content; a Language Switcher block is available in the Site Editor; and readable text stored in block settings (button labels, search placeholders, WooCommerce block headings) is translated with the content.
* **[ADDED in Free and Pro]** Site Templates screen: translate block templates, template parts, navigation menus and synced patterns per language. Language versions are used automatically on that language's pages and are marked outdated when the original changes.
* **[ADDED in Free and Pro]** WordPress, the theme and WooCommerce now render in the page's language (for example bg_BG on /bg/ pages), with a safety net that corrects the locale once the request is parsed, a notice when a language pack is missing, and an admin-only diagnostic comment in the page source.
* **[FIXED in Free and Pro]** Translated WooCommerce Shop, Cart, Checkout, My Account and Terms pages are now used as those pages in their language, and /{lang}/shop/ no longer returns 404.
* **[ADDED in Free and Pro]** Variable products: translating a variable product creates its variations with translated attribute values, the same prices and stock, and translated descriptions. Re-translating updates them. Previously the translation became a simple product, and taxonomy attribute names were sent to the translator.
* **[ADDED in Free and Pro]** Price and stock are shared between the language versions of a product and its variations. Sales in any language reduce one shared stock, including two orders placed at the same moment.
* **[FIXED in Free and Pro]** Cart and checkout background requests (the Store API behind the cart and checkout blocks, and classic wc-ajax updates) return messages and labels in the page's language. Payment method titles, descriptions and instructions and shipping labels follow the page language too.
* **[ADDED in Free and Pro]** Image alt text, link titles, aria-label and placeholder text in content are translated.
* **[ADDED in Free and Pro]** hreflang tags on the home page, blog page, shop and other archives, not only on single posts and pages.
* **[FIXED in Free and Pro]** The translation-file editor now produces files WordPress can read. The .mo header had wrong offsets, .l10n.php files were written in the wrong format and blanked the whole text domain, context strings lost their context, and JavaScript translations ignored context and plurals. JavaScript translations are now compiled per script on every Save.
* **[FIXED in Free and Pro]** Saving a .po file no longer corrupts long strings that contain quotes. Sync no longer flags every string fuzzy, and its message reports the same total as the status bar.
* **[FIXED in Free and Pro]** The editor's status bar and string list now read the file the editor saves. With an official language pack installed, they showed the pack's numbers, so saved changes appeared not to apply.
* **[FIXED in Free and Pro]** The editor's counters, filters and compiled files use one rule for what counts as translated: blank, whitespace-only or incomplete plural translations count as untranslated.
* **[FIXED in Pro]** Auto-translate fills every plural form, skips blank answers from the provider, reports the total for the whole run, and names the strings it could not translate.
* **[FIXED in Free and Pro]** The current URL keeps its port, and a site whose home page lists latest posts gets a working /{lang}/ home page.
* **[CHANGED in Free and Pro]** Requires WordPress 5.8 or later (was 5.6), for the block template functions block theme support uses.

= 1.0.4 =
* **[FIXED in Free and Pro]** Previewing an unpublished translation now shows that translation instead of the original. Preview URLs are deliberately unlocalized (?p=NNN&preview=true), so the request carried no language, it resolved to the default language, and the singular-query translation swap replaced the previewed draft with its published source sibling. Preview requests are now detected (including the ?p=NNN&preview=true form), never swapped to a sibling, and the previewed post's own language drives the runtime context so the language switcher, generated URLs and canonical output agree with what is on screen.
* **[FIXED in Free and Pro]** An unpublished translation no longer offers a public View link it cannot resolve: the translation status map leaves the view link empty for draft, pending and scheduled targets, and the sidebar, the modal and the AI Translation page fall back to the Preview link. The preview redirect hook also lost an unreachable redirect branch.

= 1.0.3 =
* **[FIXED in Free and Pro]** The plugin list row no longer links the website twice. WordPress renders “Visit plugin site” from the plugin header (Plugin URI), so the row link that repeated the same URL was removed, and the row now ends with a TheBrandPlace credit linking to thebrandplace.com. The vendor URL is filterable with fluentor_plugin_vendor_url.
* **[FIXED in Pro]** Pro installations that still displayed the doubled product name “Fluentor Fluentor Pro” now show “Fluentor Pro”. Freemius builds the premium name from the plugin name plus the premium suffix, and the suffix now carries only “Pro”, so Pro sites that installed 1.0.2 receive the corrected name with this release.

= 1.0.2 =
* **[FIXED in Free and Pro]** WooCommerce order and account endpoints are no longer redirected. An order-received request such as /checkout/order-received/123/?key=... lost its endpoint path and sent the customer to an empty cart. Every endpoint request, and any request carrying an order or payment parameter, is now left untouched, and endpoint path segments are preserved whenever a localized request is rebuilt.
* **[ADDED in Free and Pro]** New “Language routing” setting. Automatic (the new default) routes languages in URLs only when more than one language is active, so a single-language site never has its URLs rewritten. “Always route languages in URLs” and “Translation tools only” are available for explicit control. Translation Files, language entries and AI translation keep working in every mode.
* **[FIXED in Free and Pro]** Changes saved in the translation-file editor now always apply. WordPress 6.5+ prefers a sibling .l10n.php file over the .mo file and does not compare timestamps, so a previously compiled PHP file could keep overriding the freshly saved .mo file. Sibling formats are now rebuilt on save, the .mo is written and verified, and the override lookup uses the locale WordPress is actually loading.
* **[ADDED in Free and Pro]** Runtime status panel on the editor’s File info tab: the file WordPress really loads, which compiled formats exist (with sizes and timestamps), and a live check that a translated string comes back translated.
* **[ADDED in Free and Pro]** Translations saved to the Custom (Fluentor) folder can be downloaded as a zip containing every compiled format, and the Plugins screen warns before deactivating the plugin while such files exist.
* **[FIXED in Pro]** Fluentor Pro is now named “Fluentor Pro” instead of “Fluentor Fluentor Pro”. Freemius shows the premium name as the plugin name plus the premium suffix, and the suffix was set to the full product name, so the name was repeated.

= 1.0.1 =
* Bug fix: the Duplicate (Translate Later) action now completes on PHP 8 and opens the new draft for review; previously it stopped with an error.
* Bug fix: unexpected PHP errors during a single-post or media translation now show a message instead of a blank screen.
* Maintenance: the free package now matches the current code base, including the latest translation-file editor behavior.

= 1.7.9 =
* Compliance: prepared the plugin for the WordPress.org directory — removed the self-referencing Plugin URI from the main file header, moved textdomain loading to init, converted inline admin script/style blocks to enqueued assets, and added the translation template (languages/fluentor.pot). The readme now documents the AI services, provider terms of use, and the plugin’s privacy behavior, and lists the wp.org contributor.

= 1.7.8 =
* Maintenance: WordPress Plugin Check clean-up — added the missing translators comments for all placeholder strings, replaced mt_rand() with wp_rand(), and documented the intended SQL/meta-query and display-only request reads with phpcs annotations.

= 1.7.7 =
* UX: a collapsed “Separate-domain setup guide” now appears under the URL-mode options in the setup wizard and Multilingual Settings when separate-domain mode is relevant — it explains the DNS and web-server mapping the mode requires, with a concrete international example.

= 1.7.6 =
* Tuned: the default AI provider is now DeepL (a quality-first default).

= 1.7.5 =
* New: 11 additional AI providers — OpenRouter, DeepSeek, Groq, Mistral, Together AI, Fireworks AI, Cerebras, xAI (Grok), NVIDIA NIM, SambaNova, and Anthropic (Claude) — powered by a new OpenAI Chat Completions adapter and a native Anthropic Messages adapter. Every provider is configurable in Multilingual Settings, verifiable with the Test connection button, and usable through the fluentor_translation_providers filter.
* New: provider registry entries now support a base_url, so any OpenAI-compatible endpoint can be pointed at a custom base URL.

= 1.7.4 =
* Bug fix: ACF choice/enum/asset field values (select, checkbox, radio, link, images, ...) are no longer treated as translatable free text — their stored values are always preserved, and every ACF field is excluded from the generic meta translator and tracked in the source signature.
* New: ACF fields attached to taxonomy terms now follow translations — a per-term Translate action on taxonomy list tables creates/links the translated term, translates its name and description, and applies translated ACF field values (including reference fields) onto the sibling.
* New: ACF options pages can now be translated per language from Multilingual Settings; translated values are stored per language and swapped in automatically on the front end (ACF Pro options pages included).

= 1.7.3 =
* New: ACF reference fields now follow the translation — relationship, post object, page link, and taxonomy fields on a translated copy are remapped to the translated posts/terms in the target language (including references nested inside groups, repeaters, and flexible content); references without a translation keep the source value.

= 1.7.2 =
* New: Pods relationship fields now follow the translation — on a translated copy, "pick" fields that reference posts or terms (e.g. parent/child session links on a translated Pods "Program" item) are remapped to the translated siblings in the target language; references without a translation keep the source value.

= 1.7.1 =
* New: translation providers are now pluggable through a provider registry — themes and plugins can register their own AI providers (including OpenAI-compatible services such as DeepSeek or OpenRouter) via the `fluentor_translation_providers` filter, with no core edits. Dispatch, key sanitization, default settings, chunk limits, model selection, and all provider labels now read from the registry.
* New: a "Test connection" button on the Multilingual Settings page checks the saved provider API key on demand and reports the result, so you can confirm your provider (built-in or custom) works before translating.

= 1.7.0 =
* Maintenance: removed the unused legacy Search & Replace Elementor-JSON engine and search-history storage, and the related search-batch-size setting; the genuinely-used helpers it hosted now live in the logging and translation render modules.
* Maintenance: rebranded remaining "ElementorTextReplacer" package docblocks and "ETP" fallback log prefixes to Fluentor.

= 1.6.9 =
* UX: the AI Translation page's Content type filter now shows Elementor templates under a clear "Elementor Templates" label instead of the raw "Template"/"elementor_library" name.

= 1.6.8 =
* New: Elementor Loop Grid / Loop Carousel support — translating a page now points its loop widgets at the translated Loop Item template (when one exists), and loop queries on the frontend are scoped to the current language so a translated page lists translated custom post type entries.

= 1.6.7 =
* New: the source language of a post/page can now be changed directly from the edit screen — the Translations meta box includes an inline language selector that saves immediately.
* Bug fix: languages whose display name was stored as a bare code (e.g. "bg" instead of "Bulgarian") now show their full name in list tables and language selectors, and the stored name is repaired automatically on upgrade.

= 1.6.6 =
* New: a Language filter dropdown in the list-table toolbar of every enabled post type (next to All dates / Filter) lets you view posts by language — posts without an explicit language resolve to the site default and show under it.
* New: an inline Language selector on every row of enabled post-type and taxonomy list tables lets you set or change an item's language (or restore the default) in one click.
* New: "Translate" is now a reliable WordPress bulk action on enabled post-type list tables — it works for posts that only resolve to the default language, not just posts with an explicitly assigned language.

= 1.6.5 =
* Bug fix: the "select all" checkbox on the AI Translation page now actually selects every candidate — previously it only toggled itself and never checked the rows (and it stays in sync with individual selections, including a partial-selection state).

= 1.6.4 =
* Bug fix: batch translation from the AI Translation page is fixed — the AJAX handler was registered under a legacy action name the page's JavaScript no longer uses, so every batch request silently failed with a generic error and nothing was logged. The handler is now registered under the current action name (plus a legacy alias).

= 1.6.3 =
* Bug fix: DeepL requests now retry once with backoff on transient rate-limit (429) and server (5xx) errors, which previously caused batch translations from the AI Translation page to fail while single-post translations succeeded.
* Bug fix: bare ampersands in content (e.g. "Tom & Jerry") are now protected through translation, so DeepL's HTML tag handling no longer rejects them as invalid XML.
* UX: enabling a new content type in Multilingual Settings now auto-assigns the default language to its existing posts, so they immediately appear as translatable candidates (covers custom post types created via Pods).

= 1.6.2 =
* UX: the setup wizard's first step now starts with the site's own WordPress language (Settings → General → Site Language) instead of hard-coded English — applied to fresh installs and to existing installs that still have the untouched English default.

= 1.6.1 =
* Bug fix: legacy etp_* options are now deleted the moment their values are migrated (and purged again on upgrade), so a leftover row can never resurrect your saved provider keys or languages after a fresh install.
* UX: the setup wizard's AI Translation step now offers a "Remove saved key" control, so a stored provider key can be cleared directly from the wizard without opening Multilingual Settings.

= 1.6.0 =
* Bug fix: uninstall now also removes the legacy (pre-rename) options, tables, and meta so a fresh install can never resurrect previous languages or saved provider keys.
* Bug fix: provider API keys that were accidentally stored double-encrypted are auto-repaired — previously such keys decrypted to another encrypted marker, which was sent to providers verbatim and rejected (e.g. DeepL). The stored key is re-encrypted once so translation works again without re-entering the key.
* Bug fix: the settings sanitizer now refuses to re-encrypt an already-encrypted key, preventing future double-encryption.

= 1.5.9 =
* New: Fluentor Dashboard — a plugin home page showing your multilingual status at a glance (languages, translatable/translated posts, translation provider), an ordered “what’s next” guide, and quick cards linking to AI Translation, Translation Files, and Multilingual Settings. The setup wizard now finishes on the Dashboard.

= 1.5.8 =
* UX: removed the duplicate top-level "Fluentor" menu item — the plugin’s main page is now the single "AI Translation" item.
* UX: the wizard now states clearly that it only sets up the multilingual foundation and that you translate your content yourself afterwards; finishing leads to the AI Translation page, and the completion notice also points to the Translation Files editor.
* UX: clearer plain-language explanation on the wizard’s Existing Content step.
* UX: Multilingual Settings sections (except Languages) are now collapsed by default for a less overwhelming page.

= 1.5.7 =
* UX: setup wizard — merged Slug Settings into the URL Modifications step (the wizard is now 6 steps) and removed the redundant "Practical effect" note from the Post Types & Taxonomies step.

= 1.5.6 =
* Bug fix: uninstall now truly removes all Fluentor data — languages, settings, encrypted provider keys, Polylang bridge state, meta, tables, and transients — so a clean reinstall starts empty.

= 1.5.5 =
* UX: Polylang bridge — Actions moved into the main page area as the primary action instead of the sidebar.
* UX: Polylang bridge — the one-way migration reports its status inline (progress, success with stats, or error) through an AJAX notification instead of a WordPress admin notice.
* UX: Polylang bridge — a guided Next Steps flow appears after migration (review posts, verify Elementor templates, deactivate Polylang) plus a one-click switch to the native runtime.
* UX: setup wizard AI provider step — restructured into a clear provider card with compact, full-width dropdowns, per-provider descriptions, and a cleaner test-connection row.

= 1.5.4 =
* UX: resume incomplete translation jobs after a tab close or reload; retry failed jobs from the Recent Jobs list with error details.
* UX: staged progress feedback for single-post AI translation.
* UX: AI provider step in the setup wizard with a live connection test.
* Accessibility: aria-current on the active switcher language and reduced-motion support.
* Maintainability: split the Translation Files editor page into per-section render files and moved its inline JavaScript to a dedicated asset.

= 1.5.3 =
* Performance: per-request settings cache; cached translation-group lookups with invalidation; conditional rewrite-rule flushing; filterable AI retry limit and backoff; pre-filtered PO sync fuzzy matching; output buffering and switcher assets loaded only when used; daily cron plus opportunistic pruning of the translation-jobs table.
* Security: provider API keys encrypted at rest and masked in settings; Gemini key sent via request header instead of a URL parameter; per-user daily AI usage limit; translation backup path containment checks; path-traversal rejection in locale normalization.

= 1.5.2 =
* Multilingual structure, AI translation, language switcher, and translation-file editor releases.

