=== WakaLang ===
Contributors: noricku, wakalab
Tags: multilingual, translation, hreflang, language-switcher, i18n
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 0.6.21
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Keep visitors in their language. Lightweight URL-prefix language routing, hreflang, and a language switcher for WordPress.

== Description ==

WakaLang is a lightweight multilingual plugin for WordPress sites that publish manually translated content. It keeps the current language stable through clean URL prefixes such as `/en/about/` and `/ja/about/`, then helps you connect translated posts, terms, menus, navigation blocks, SEO metadata, and `hreflang` output.

The free plugin is complete for manual multilingual publishing and makes no external network calls.

**Free features**

* Register the languages your site offers (code, locale, names, URL prefix, default).
* URL-prefix routing: every page is reachable under each language prefix (`/en/…`, `/ja/…`), with the prefix as the single source of truth for the active language.
* A language switcher with automatic header/footer placement, an editor block, the `[wakalang_switcher]` shortcode, and the `wakalang_language_switcher()` template function — with optional flags rendered as Unicode emoji (no external requests).
* `hreflang` alternate links (and an optional `x-default`) for translated content. If `x_default_url` is left empty, WakaLang derives it from the current page's default-language URL.
* Internal links, menu links, the site/home link, and block-theme (FSE) navigation all keep the current language's URL prefix.
* Link posts, pages, and taxonomy terms into translation groups from a post or term editor, and create draft translations.
* Archive, search, RSS/Atom feeds, and the core `wp-sitemap.xml` are scoped to the current language.
* Translate taxonomy terms (category, tag, custom taxonomy) with per-language name and slug.
* Manage a per-translation SEO title and meta description, handed to WordPress core and to Yoast / Rank Math (their own meta is never touched).
* Translate the site title, tagline, date/time display format, week start day, logo, and site icon per language.
* Every page's `<html lang>` and, for a right-to-left language, `dir="rtl"` are guaranteed directly from the language registry — independent of whether a language pack is installed.
* Review translation coverage, maintenance checks, FAQ, troubleshooting, support routes, and system information inside wp-admin.

**Privacy**

WakaLang does not call any external service, does not track visitors, and stores no personal data. It runs entirely on your own site.

**Third Party Services**

WakaLang Free does not connect to any third-party service, CDN, telemetry endpoint, license server, or translation API. It serves its assets from your WordPress site and performs language routing locally.

**Optional add-on**

A separate paid add-on is planned for AI-assisted, Markdown-safe translation using an administrator-provided API key, glossary, translation memory, and differential translation. The free plugin contains none of that add-on code and works fully without it.

**Try it first**

Use the Live Preview button on this plugin page to try a bilingual (Japanese/English) demo of WakaLang in WordPress Playground — no install required.

**Getting started**

After activation, open **WakaLang → Languages**, add your languages, set the default language, open **WakaLang → Settings** to choose switcher placement, then use the WakaLang editor panel to assign languages and link translated versions. The full user manual is inside **WakaLang → Guide**.

== Installation ==

1. In WordPress, go to **Plugins → Add New**, search for **WakaLang**, install it, and activate it.
2. To install from a ZIP, go to **Plugins → Add New → Upload Plugin**, upload the WakaLang ZIP, install it, and activate it.
3. Go to **WakaLang → Languages** to register your languages and set a default.
4. Go to **WakaLang → Settings** and choose a header or footer language switcher position, or add the block/shortcode where you want it manually.
5. Open **WakaLang → Guide** for setup steps, usage notes, FAQ, troubleshooting, support routes, and system information.

== Frequently Asked Questions ==

= After installing, what should I do first? =

Add your languages under **WakaLang → Languages**, set the default language, choose switcher placement under **WakaLang → Settings**, then assign languages and translation groups in the post or page editor.

= What should I do if settings are not reflected? =

Flush rewrite rules from **WakaLang → Tools**, clear page/object/CDN caches, and confirm you are viewing a URL with the expected language prefix.

= My translations lost their language after moving the site. What happened? =

Language assignments and translation groups are stored in a WakaLang database table, so a WordPress export (WXR) does not carry them. Move the content first, then use **WakaLang → Tools → Import and export translation relationships** on the old site to download the relationships and on the new site to import them. Objects are matched by post type and slug (never by ID), a preview reports what would happen before anything is written, and rows that cannot be matched are listed with a reason.

= Why is my theme or plugin interface text still in English? =

WakaLang translates your content, URLs, and the site's core "face" fields (site title, tagline, date/time display, logo, and site icon). It does not scan or translate the gettext strings built into themes and plugins (button labels, widget titles, form messages). Install a WordPress language pack for each language under **Settings → General** to translate those automatically. For strings without an official translation, hand-edit them with a dedicated string-translation plugin such as Loco Translate — a complementary tool that WakaLang never installs or changes for you. WakaLang and Loco Translate share the work rather than duplicating it.

= Can I use WakaLang with my theme or cache plugin? =

Yes in normal setups. If root browser-language detection is enabled, exclude the bare site root (`/`) from full-page caching, host cache, and CDN cache, or turn that detection off in **WakaLang → Settings**. Prefixed URLs such as `/en/` and `/ja/` remain safe to cache normally because the URL prefix is the language source of truth. Clear caches after changing URL, menu, or switcher settings.

= What is the difference between Free and Pro? =

WakaLang Free is complete for manual multilingual publishing. WakaLang Pro is a separate add-on for licensed AI-assisted translation workflows and is not bundled in the free WordPress.org plugin.

= Where can I get support? =

Use the WordPress.org support forum for WakaLang Free. Do not post license keys, API keys, account details, payment information, or refund requests in public forum threads; use the Pro support route shown inside the plugin when applicable.

= Does WakaLang Free send my content anywhere? =

No. WakaLang Free makes no external network calls, does not use a CDN, does not include telemetry, and does not perform license checks.

= Does WakaLang support right-to-left (RTL) languages like Arabic and Hebrew? =

Yes. Every page's `<html>` tag gets a `lang` attribute and, for a right-to-left language, `dir="rtl"`, guaranteed directly from your configured language registry rather than from WordPress's own installed language packs — so it is correct even before you install that language's translation files. This covers WCAG success criteria 3.1.1 (Language of Page) and 3.1.2 (Language of Parts) for the language-of-page/switcher parts of your site. The language switcher also marks each right-to-left language's link with `dir="rtl"`.

= What does WakaLang intentionally not do? =

To stay lightweight, WakaLang does not include a visual front-end translation editor, a full theme/plugin string-scanning panel, media/attachment translation, translated or shared slugs, per-language domains or subdomains, WooCommerce or page-builder specific integrations, translation-agency workflows, multisite language networks, or a visitor-facing machine-translation widget. The URL prefix stays the source of truth for the current language, WordPress slugs stay canonical, and no translation credits are sold.

= Is WakaLang actually lightweight? =

The additional database queries, autoload option payload, and TTFB impact WakaLang adds to a front-end page load are measured with a reproducible script and published at https://github.com/my-biz-dev/wakalang/blob/main/docs/benchmarks/frontend-performance.md — run it yourself against the project's local verification stack to confirm the numbers. For hosting recommendations (a persistent object cache, page-cache interaction) see https://github.com/my-biz-dev/wakalang/blob/main/docs/performance.md.

== Screenshots ==

1. Language registry with setup guidance and controls for editing, enabling, and ordering languages.
2. Sectioned language switcher settings for display, style, placement, and the admin-bar menu.
3. Post editor translation panel for assigning a language and linking translated versions.
4. Front-end flag-and-name language switcher output on a prefixed page.
5. Language Switcher block options for labels, flags, style, and current-language visibility.

== Source Code ==

WakaLang ships as readable PHP; the only compiled asset is the block editor script.

* `assets/blocks/language-switcher/build/index.js` is the compiled Language Switcher block editor script. Its human-readable source ships in this plugin under `assets/blocks/language-switcher/src/` (`index.js`, `edit.js`, `block.json`).

To rebuild it, install Node.js, run `npm install`, then `npm run build:blocks` (which runs `@wordpress/scripts`). No other plugin code is minified or generated by a build tool.

== Upgrade Notice ==

= 0.6.0 =
Maintenance and test-coverage release. No action needed: language routing, translation links and your existing settings are unchanged.

= 0.4.0 =
Adds site-to-site export and import of translation relationships, so language assignments and translation groups survive a WordPress (WXR) content move. Nothing changes until you use the new Tools section.

= 0.3.2 =
Adds an opt-in notice on 404 pages linking to an existing translation of the requested path. Off by default; nothing changes until you enable it.

= 0.3.1 =
Adds a per-block language scope for the Query Loop block and a per-language translation permission model. Existing behaviour is unchanged.

= 0.3.0 =
Adds the declarative content schema for translation drafts. hreflang x-default now derives from the current page's default-language URL when x_default_url is left empty; sites that set x_default_url keep the previous behaviour.

= 0.2.5 =
Maintenance update for the plugin details link.

== Changelog ==

= 0.6.21 =
* Backfill source_language_code and record AI-reviewed status.
* Add Gutenberg translation sidebar.
* Address code review findings for flaky test tracking.

= 0.6.20 =
* Guarantee each language's `<html lang>`/`dir` directly from the language registry (not the installed language pack), add a `dir="rtl"` to right-to-left language switcher links, and add a Multilingual Doctor check for language attribute misconfiguration.

= 0.6.19 =
* Add per-language/provider AI usage breakdown with CSV export.
* Refresh plugin screenshots.

= 0.6.18 =
* Add language filter to taxonomy term list tables.
* Memoize UrlResolver::resolve_for_language() per request.
* Batch translation graph priming for REST post collections.
* Stabilize admin site-health and permissions specs.

= 0.6.17 =
* Add translation coverage dashboard widget.
* Scope dashboard widget by allow-list and fix broken empty-state link.
* Keep core sitemap alive alongside an SEO plugin.

= 0.6.16 =
* Translation Exchange (Pro) can now include excerpt, per-translation SEO title/meta description and slugs in an export via opt-in checkboxes, and taxonomy term names as a separate unit type; imports apply the new fields, hold slugs for explicit manual application, and keep title/content-only files working unchanged (Issue #466).

= 0.6.15 =
* Language switcher links now point at the clean translation URLs, matching the hreflang alternates; the preferred-language cookie is written by a small front-end script on click instead of a query-parameter redirect hop (Issue #633). The server-side `?wakalang_switch_language=` flow is kept for backward compatibility.

= 0.6.14 =
* Prevent WP 7.1 handle_404 false positive on sitemap requests.
* Send 200 explicitly and tighten pre_handle_404 test coverage.
* Declare WordPress 7.1 compatibility.

= 0.6.10 =
* Add bulk approve/reject to Translation Review queue.

= 0.6.8 =
* Add translationGroupId field and own i18n catalog.
* Bump minimum Free version to 0.3.1 for TranslationGraphBuilder.
* Suppress nonce-verification false positives in Pro admin pages.
* Guard adapter package against Pro declarations.

= 0.6.7 =
* Move SEO consistency observation off front-end requests.
* Reject a redirected or empty head in the consistency scan.

= 0.6.6 =
* Speed up the Translation Hub and translation coverage report on large sites.

= 0.6.5 =
* Cap default-language assignment to a bounded batch per call.
* Batch translation group lookups in the post list table.
* Restore quality threshold baseline.

= 0.6.4 =
* Memoize merged settings and schema defaults.
* Resolve 404 fallback target via bare permalink.

= 0.6.2 =
* Add bulk language assignment to the post list.
* Add edit, enable/disable, and reorder to the Languages page.
* Add term translation search and draft creation (#442).
* Show source-change diffs and add bulk needs-update resolution.
* Add bulk translation-draft creation to the Translation Hub.
* Add confirm-before-destructive-action and notice dismissal.
* Add versioned DB migrations.
* Resolve menu items via known object id instead of URL reverse lookup.
* Fall back to a display name when no flag emoji resolves.
* Detect and recover from a missing translations table.
* Remove residual WakaLang data.
* Verify critical write results.
* Localize GFMR and CLI notices.

= 0.4.0 =
* Add site-to-site export and import of translation relationships, so language assignments and translation groups survive a WordPress (WXR) content move.

= 0.3.2 =
* Add cross-language 404 fallback resolution.

= 0.3.1 =
* Add per-block language scope override to Query Loop.
* Add the WPGraphQL companion adapter for the translation graph. It is a separate free plugin for sites running WPGraphQL, not part of this plugin — download it from https://github.com/my-biz-dev/wakalang/releases
* Add per-language translation permission model.
* Add WordPress Playground Live Preview blueprint.
* Add frontend performance benchmark harness.
* Pin Free AI translation spike findings for Cloudflare Workers AI.

= 0.3.0 =
* Declarative content schema: extensions can now declare, per post meta key and block attribute, whether a value should be copied, translated manually, or ignored when a translation draft is created — through the `wakalang_content_schema` filter or a theme's `wpml-config.xml`. Unknown or unsafe declarations are ignored and reported, secret/authentication meta is never copied, and with nothing declared the existing draft behavior is unchanged. See docs/HOOKS.md.
* hreflang `x-default` now auto-derives from the current page's default-language URL when `x_default_url` is left empty and `enable_x_default` is on. Sites that explicitly set `x_default_url` keep the previous fixed-URL behavior.

= 0.2.6 =
* Block themes: assign a different navigation per language for each navigation your site uses. Header and footer (or any separate Navigation blocks) can now each be mapped independently — on a non-default-language page the navigation you chose for that language is shown in its place. Configure it under WakaLang → Settings → Navigation menus, where each navigation your site references appears as its own row; the default language keeps the original.
* Optionally scope secondary post listings to the current language. When enabled under WakaLang → Settings, Recent Posts widgets, Latest Posts blocks and other secondary queries on a language page (e.g. /en/) show only that language's posts, matching the main archive. Off by default; a theme can keep a specific query showing every language with the `wakalang_filter_secondary_queries` filter.

