{"id":328416,"date":"2026-06-20T09:44:21","date_gmt":"2026-06-20T09:44:21","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wakalang\/"},"modified":"2026-06-29T01:32:17","modified_gmt":"2026-06-29T01:32:17","slug":"wakalang","status":"publish","type":"plugin","link":"https:\/\/pcd.wordpress.org\/plugins\/wakalang\/","author":23328473,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.2.6","stable_tag":"0.2.6","tested":"7.0","requires":"6.4","requires_php":"7.4","requires_plugins":null,"header_name":"WakaLang","header_author":"Wakalab","header_description":"Keep visitors in their language. URL-prefix language routing, hreflang, and a language switcher for WordPress.","assets_banners_color":"e8f4f5","last_updated":"2026-06-29 01:32:17","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/wakalab.dev","rating":0,"author_block_rating":0,"active_installs":0,"downloads":272,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.0":{"tag":"0.1.0","author":"noricku","date":"2026-06-20 09:44:03"},"0.1.1":{"tag":"0.1.1","author":"noricku","date":"2026-06-22 07:15:45"},"0.2.0":{"tag":"0.2.0","author":"noricku","date":"2026-06-22 23:59:02"},"0.2.1":{"tag":"0.2.1","author":"noricku","date":"2026-06-23 13:51:04"},"0.2.2":{"tag":"0.2.2","author":"noricku","date":"2026-06-24 08:46:11"},"0.2.3":{"tag":"0.2.3","author":"noricku","date":"2026-06-25 02:56:15"},"0.2.4":{"tag":"0.2.4","author":"noricku","date":"2026-06-25 13:19:22"},"0.2.5":{"tag":"0.2.5","author":"noricku","date":"2026-06-26 03:16:44"},"0.2.6":{"tag":"0.2.6","author":"noricku","date":"2026-06-29 01:32:17"}},"upgrade_notice":{"0.2.5":"<p>Maintenance update for the plugin details link.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3579668,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3579668,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3579668,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3579668,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3579668,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":{"wakalang\/language-switcher":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"wakalang\/language-switcher","title":"Language Switcher","category":"widgets","icon":"translation","description":"Display links for switching between enabled languages.","textdomain":"wakalang","attributes":{"show":{"type":"string","default":"native"},"flags":{"type":"string"},"hideCurrent":{"type":"boolean","default":false}},"supports":{"html":false},"editorScript":"file:.\/index.js"}},"tagged_versions":["0.1.0","0.1.1","0.2.0","0.2.1","0.2.2","0.2.3","0.2.4","0.2.5","0.2.6"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3579668,"resolution":"1","location":"assets","locale":"","width":1200,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3579668,"resolution":"2","location":"assets","locale":"","width":1200,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3579668,"resolution":"3","location":"assets","locale":"","width":1200,"height":900},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3579668,"resolution":"4","location":"assets","locale":"","width":1200,"height":900}},"screenshots":{"1":"Initial language setup screen after activating the plugin.","2":"Main settings screen for URL behavior, switcher placement, and navigation options.","3":"Post editor translation panel for assigning a language and linking translated versions.","4":"Front-end language switcher output on a prefixed page.","5":"Language Switcher block options in the block editor, rendered by the same front-end switcher."}},"plugin_section":[],"plugin_tags":[2993,104,22323,99,2333],"plugin_category":[48],"plugin_contributors":[268062],"plugin_business_model":[],"class_list":["post-328416","plugin","type-plugin","status-publish","hentry","plugin_tags-hreflang","plugin_tags-i18n","plugin_tags-language-switcher","plugin_tags-multilingual","plugin_tags-translation","plugin_category-language-tools","plugin_contributors-noricku","plugin_committers-noricku"],"banners":{"banner":"https:\/\/ps.w.org\/wakalang\/assets\/banner-772x250.png?rev=3579668","banner_2x":"https:\/\/ps.w.org\/wakalang\/assets\/banner-1544x500.png?rev=3579668","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/wakalang\/assets\/icon.svg?rev=3579668","icon":"https:\/\/ps.w.org\/wakalang\/assets\/icon.svg?rev=3579668","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-1.png?rev=3579668","caption":"Initial language setup screen after activating the plugin."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-2.png?rev=3579668","caption":"Main settings screen for URL behavior, switcher placement, and navigation options."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-3.png?rev=3579668","caption":"Post editor translation panel for assigning a language and linking translated versions."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-4.png?rev=3579668","caption":"Front-end language switcher output on a prefixed page."}],"raw_content":"<!--section=description-->\n<p>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 <code>\/en\/about\/<\/code> and <code>\/ja\/about\/<\/code>, then helps you connect translated posts, terms, menus, navigation blocks, SEO metadata, and <code>hreflang<\/code> output.<\/p>\n\n<p>The free plugin is complete for manual multilingual publishing and makes no external network calls.<\/p>\n\n<p><strong>Free features<\/strong><\/p>\n\n<ul>\n<li>Register the languages your site offers (code, locale, names, URL prefix, default).<\/li>\n<li>URL-prefix routing: every page is reachable under each language prefix (<code>\/en\/\u2026<\/code>, <code>\/ja\/\u2026<\/code>), with the prefix as the single source of truth for the active language.<\/li>\n<li>A language switcher with automatic header\/footer placement, an editor block, the <code>[wakalang_switcher]<\/code> shortcode, and the <code>wakalang_language_switcher()<\/code> template function \u2014 with optional flags rendered as Unicode emoji (no external requests).<\/li>\n<li><code>hreflang<\/code> alternate links (and an optional <code>x-default<\/code>) for translated content.<\/li>\n<li>Internal links, menu links, the site\/home link, and block-theme (FSE) navigation all keep the current language's URL prefix.<\/li>\n<li>Link posts, pages, and taxonomy terms into translation groups from a post or term editor, and create draft translations.<\/li>\n<li>Archive, search, RSS\/Atom feeds, and the core <code>wp-sitemap.xml<\/code> are scoped to the current language.<\/li>\n<li>Translate taxonomy terms (category, tag, custom taxonomy) with per-language name and slug.<\/li>\n<li>Manage a per-translation SEO title and meta description, handed to WordPress core and to Yoast \/ Rank Math (their own meta is never touched).<\/li>\n<li>Translate the site title and tagline per language.<\/li>\n<li>Review translation coverage, maintenance checks, FAQ, troubleshooting, support routes, and system information inside wp-admin.<\/li>\n<\/ul>\n\n<p><strong>Privacy<\/strong><\/p>\n\n<p>WakaLang does not call any external service, does not track visitors, and stores no personal data. It runs entirely on your own site.<\/p>\n\n<p><strong>Third Party Services<\/strong><\/p>\n\n<p>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.<\/p>\n\n<p><strong>Optional add-on<\/strong><\/p>\n\n<p>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.<\/p>\n\n<p><strong>Getting started<\/strong><\/p>\n\n<p>After activation, open <strong>WakaLang \u2192 Languages<\/strong>, add your languages, set the default language, open <strong>WakaLang \u2192 Settings<\/strong> to choose switcher placement, then use the WakaLang editor panel to assign languages and link translated versions. The full user manual is inside <strong>WakaLang \u2192 Guide<\/strong>.<\/p>\n\n<h3>Source Code<\/h3>\n\n<p>WakaLang ships as readable PHP; the only compiled asset is the block editor script.<\/p>\n\n<ul>\n<li><code>assets\/blocks\/language-switcher\/build\/index.js<\/code> is the compiled Language Switcher block editor script. Its human-readable source ships in this plugin under <code>assets\/blocks\/language-switcher\/src\/<\/code> (<code>index.js<\/code>, <code>edit.js<\/code>, <code>block.json<\/code>).<\/li>\n<\/ul>\n\n<p>To rebuild it, install Node.js, run <code>npm install<\/code>, then <code>npm run build:blocks<\/code> (which runs <code>@wordpress\/scripts<\/code>). No other plugin code is minified or generated by a build tool.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>In WordPress, go to <strong>Plugins \u2192 Add New<\/strong>, search for <strong>WakaLang<\/strong>, install it, and activate it.<\/li>\n<li>To install from a ZIP, go to <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>, upload the WakaLang ZIP, install it, and activate it.<\/li>\n<li>Go to <strong>WakaLang \u2192 Languages<\/strong> to register your languages and set a default.<\/li>\n<li>Go to <strong>WakaLang \u2192 Settings<\/strong> and choose a header or footer language switcher position, or add the block\/shortcode where you want it manually.<\/li>\n<li>Open <strong>WakaLang \u2192 Guide<\/strong> for setup steps, usage notes, FAQ, troubleshooting, support routes, and system information.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"after%20installing%2C%20what%20should%20i%20do%20first%3F\"><h3>After installing, what should I do first?<\/h3><\/dt>\n<dd><p>Add your languages under <strong>WakaLang \u2192 Languages<\/strong>, set the default language, choose switcher placement under <strong>WakaLang \u2192 Settings<\/strong>, then assign languages and translation groups in the post or page editor.<\/p><\/dd>\n<dt id=\"what%20should%20i%20do%20if%20settings%20are%20not%20reflected%3F\"><h3>What should I do if settings are not reflected?<\/h3><\/dt>\n<dd><p>Flush rewrite rules from <strong>WakaLang \u2192 Tools<\/strong>, clear page\/object\/CDN caches, and confirm you are viewing a URL with the expected language prefix.<\/p><\/dd>\n<dt id=\"can%20i%20use%20wakalang%20with%20my%20theme%20or%20cache%20plugin%3F\"><h3>Can I use WakaLang with my theme or cache plugin?<\/h3><\/dt>\n<dd><p>Yes in normal setups. Clear caches after changing URL, menu, or switcher settings. If a problem appears, temporarily disable optimization plugins or switch themes to isolate the conflict.<\/p><\/dd>\n<dt id=\"what%20is%20the%20difference%20between%20free%20and%20pro%3F\"><h3>What is the difference between Free and Pro?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n<dt id=\"where%20can%20i%20get%20support%3F\"><h3>Where can I get support?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n<dt id=\"does%20wakalang%20free%20send%20my%20content%20anywhere%3F\"><h3>Does WakaLang Free send my content anywhere?<\/h3><\/dt>\n<dd><p>No. WakaLang Free makes no external network calls, does not use a CDN, does not include telemetry, and does not perform license checks.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.2.6<\/h4>\n\n<ul>\n<li>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 \u2014 on a non-default-language page the navigation you chose for that language is shown in its place. Configure it under WakaLang \u2192 Settings \u2192 Navigation menus, where each navigation your site references appears as its own row; the default language keeps the original.<\/li>\n<li>Optionally scope secondary post listings to the current language. When enabled under WakaLang \u2192 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 <code>wakalang_filter_secondary_queries<\/code> filter.<\/li>\n<\/ul>\n\n<h4>0.2.5<\/h4>\n\n<ul>\n<li>Avoid duplicating the plugin \"View details\" link.<\/li>\n<\/ul>\n\n<h4>0.2.4<\/h4>\n\n<ul>\n<li>Assign a different navigation menu per language to each theme menu location: on a non-default-language page (e.g. \/en\/) the menu you assigned for that language is shown in place of the theme's default, so labels, items and order can differ per language. Configure it under WakaLang \u2192 Settings \u2192 Navigation menus; the default language keeps the theme's own assignment. Only menus shown through a theme menu location are affected, and the feature can be turned off.<\/li>\n<\/ul>\n\n<h4>0.2.1<\/h4>\n\n<ul>\n<li>Agent-assisted migration from Polylang and WPML: import existing language assignments and translation groups into WakaLang locally (no external requests), via the WakaLang \u2192 Tools screen, the <code>wp wakalang migrate polylang|wpml<\/code> command, or the <code>import-from-polylang<\/code> \/ <code>import-from-wpml<\/code> abilities. Post content and slugs are never moved; imports default to a dry-run preview and are bounded per run.<\/li>\n<li>Expose WakaLang's agent abilities on the core WordPress Abilities REST API (WP 6.9+) via <code>meta.show_in_rest<\/code>. Read-safe abilities (list languages, get settings, diagnose, \u2026) are reachable over REST; writes stay behind authentication and capability checks.<\/li>\n<li>Languages screen: reject adding a language whose URL prefix is already used by another language (previously only a duplicate code was caught, so two languages could share a URL prefix). Code and URL-prefix conflicts now show an error notice, matching the REST\/CLI behavior.<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Exclude pro scope commits from the free changelog.<\/li>\n<li>Replace wporg screenshot placeholders.<\/li>\n<\/ul>\n\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>Settings and \"View details\" action links on the Plugins list row.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Language registry (option-backed) with an admin <strong>Languages<\/strong> screen: each language carries a code, locale, name, native name, URL prefix, default flag and enabled flag.<\/li>\n<li>URL-prefix rewrite routing (<code>\/ja\/\u2026<\/code>, <code>\/en\/\u2026<\/code>) \u2014 the prefix is the source of truth for the current language; rewrite rules flush on activation\/deactivation.<\/li>\n<li>Current-language context service and public template functions (<code>wakalang_get_current_language()<\/code>, <code>wakalang_get_supported_languages()<\/code>, \u2026), with optional root-request browser-language detection and a preferred-language cookie (both off-by-default-friendly and configurable).<\/li>\n<li>Settings screen for URL mode, fallback behaviour, hreflang, x-default, cookie\/browser-detection toggles and uninstall data handling.<\/li>\n<li>Translation linking: a custom <code>wp_wakalang_translations<\/code> table and a post-editor meta box to set a post's language, link it into a translation group, see the other-language versions, and create a draft translation. Rows are removed when a post is permanently deleted; group changes fire the <code>wakalang_translation_group_updated<\/code> action.<\/li>\n<li>Translation repository served through the WordPress object cache (negative lookups cached, writes purge touched entries); <code>merge_groups()<\/code> folds one translation group into another, refused on a same-language collision.<\/li>\n<li>Language switcher via the <code>[wakalang_switcher]<\/code> shortcode, the <code>wakalang_language_switcher()<\/code> \/ <code>wakalang_get_language_switcher()<\/code> template functions, and an editor block. The current language renders as a non-link with <code>aria-current<\/code>; output passes through <code>wp_kses()<\/code>.<\/li>\n<li>Language switcher display options: a <code>flags<\/code> mode (<code>name<\/code> \/ <code>flag<\/code> \/ <code>flag_and_name<\/code>) rendering each language's flag as a Unicode emoji from its locale (no bundled images, no external requests), a global show\/hide toggle, and automatic header (<code>wp_body_open<\/code>) or footer (<code>wp_footer<\/code>) placement.<\/li>\n<li>hreflang <code>&lt;link rel=\"alternate\" hreflang=\"\u2026\"&gt;<\/code> tags in <code>wp_head<\/code> for a page's language variants, plus an optional <code>x-default<\/code>. Filterable via <code>wakalang_hreflang_entries<\/code>.<\/li>\n<li>Language-preserving links: <code>post_link<\/code> \/ <code>page_link<\/code> \/ <code>post_type_link<\/code> \/ <code>term_link<\/code>, nav-menu item URLs, <code>home_url()<\/code> output, and block-theme\/FSE navigation links keep the current language's URL prefix. External links, anchors, <code>mailto:<\/code>\/<code>tel:<\/code>, <code>\/wp-admin\/<\/code>, REST and feeds are left untouched.<\/li>\n<li>Query language scoping: archive, search and feed (RSS\/Atom) queries, plus the core <code>wp-sitemap.xml<\/code> (split per language), are filtered to the current language via shared <code>posts_clauses<\/code> \/ <code>terms_clauses<\/code> SQL with cache invalidation.<\/li>\n<li>Taxonomy translation: categories, tags and public custom taxonomy terms carry per-language name\/slug and link into translation groups, with a term-editor field and a Translations column in term lists.<\/li>\n<li>SEO title and meta description per translation, stored in WakaLang-owned post meta and passed to WordPress core and the Yoast \/ Rank Math public filters (their own meta is never read or written).<\/li>\n<li>Per-language site title and tagline translation (overriding <code>option_blogname<\/code> \/ <code>option_blogdescription<\/code> on the front end without going through gettext).<\/li>\n<li>Admin locale follows the URL language via <code>determine_locale<\/code>.<\/li>\n<li>Admin post-list language filtering and an untranslated-coverage report on the Tools screen, alongside rewrite flush, relationship\/orphan checks and settings export\/import.<\/li>\n<li>Markdown Renderer for GitHub cooperation: WakaLang owns the site-wide language spine and suppresses GFMR's own switcher via its <code>gfmr_language_switcher_enabled<\/code> hook, avoiding a duplicate switcher.<\/li>\n<li>Extension API surface for add-ons (the <code>wakalang_loaded<\/code> action and the add-on registry) plus free-edition licensing stubs and a feature gate.<\/li>\n<li>Plugin bootstrap, activation\/deactivation, uninstall handling, a privacy-policy suggestion, and full internationalization (bundled <code>.pot<\/code> + Japanese <code>.po<\/code>\/<code>.mo<\/code> and block-editor JS translations).<\/li>\n<\/ul>","raw_excerpt":"Keep visitors in their language. Lightweight URL-prefix language routing, hreflang, and a language switcher for WordPress.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/328416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=328416"}],"author":[{"embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/noricku"}],"wp:attachment":[{"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=328416"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=328416"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=328416"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=328416"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=328416"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/pcd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=328416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}