{"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-20T09:44:03","modified_gmt":"2026-06-20T09:44:03","slug":"wakalang","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/wakalang\/","author":23328473,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.1.0","stable_tag":"0.1.0","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-20 09:44:03","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":25,"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"}},"upgrade_notice":[],"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"],"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":"Languages screen for registering each language, locale, native name, URL prefix, and default language.","2":"Settings screen for URL-prefix behavior, browser-language detection, and x-default hreflang output.","3":"Front-end language switcher showing the active language and alternate language links on a prefixed page.","4":"Language Switcher block available in the block editor and 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":"Languages screen for registering each language, locale, native name, URL prefix, and default language."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-2.png?rev=3579668","caption":"Settings screen for URL-prefix behavior, browser-language detection, and x-default hreflang output."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-3.png?rev=3579668","caption":"Front-end language switcher showing the active language and alternate language links on a prefixed page."},{"src":"https:\/\/ps.w.org\/wakalang\/assets\/screenshot-4.png?rev=3579668","caption":"Language Switcher block available in the block editor and rendered by the same front-end switcher."}],"raw_content":"<!--section=description-->\n<p>WakaLang is a lightweight multilingual plugin for WordPress. It keeps the visitor's chosen language stable across the whole site using clean, URL-prefixed addresses (for example <code>\/en\/about\/<\/code> and <code>\/ja\/about\/<\/code>), and is designed to be simple for manual translation workflows on technical blogs and documentation sites.<\/p>\n\n<p>The free plugin is fully usable on its own 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>The admin locale follows the URL language so editing screens match the language you are working in.<\/li>\n<li>Filter the post list by language and review an untranslated-coverage report on the Tools screen.<\/li>\n<li>Works alongside Markdown Renderer for GitHub: WakaLang owns the site-wide language spine without duplicating its switcher.<\/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<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>Upload the <code>wakalang<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install it from the Plugins screen.<\/li>\n<li>Activate the plugin.<\/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<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20wakalang%20send%20my%20content%20anywhere%3F\"><h3>Does WakaLang 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<dt id=\"how%20does%20wakalang%20decide%20the%20current%20language%3F\"><h3>How does WakaLang decide the current language?<\/h3><\/dt>\n<dd><p>From the URL prefix (for example <code>\/en\/<\/code>). The prefix is authoritative; visitors are never silently redirected away from the language they are viewing.<\/p><\/dd>\n<dt id=\"can%20i%20use%20wakalang%20without%20an%20add-on%3F\"><h3>Can I use WakaLang without an add-on?<\/h3><\/dt>\n<dd><p>Yes. The free plugin is complete for manual multilingual sites: register languages, use URL prefixes, link translated posts, output a switcher, and publish hreflang alternates.<\/p><\/dd>\n<dt id=\"how%20do%20i%20show%20a%20language%20switcher%3F\"><h3>How do I show a language switcher?<\/h3><\/dt>\n<dd><p>Choose \"Page header\" or \"Page footer\" under <strong>WakaLang \u2192 Settings \u2192 Language switcher position<\/strong> to show the switcher in the site layout instead of inside post content. You can also add the Language Switcher block, place the <code>[wakalang_switcher]<\/code> shortcode in content, or call <code>wakalang_language_switcher()<\/code> from a theme template. You can show country flags (rendered as Unicode emoji, no external requests) with the <code>flags<\/code> option set to <code>flag<\/code> or <code>flag_and_name<\/code>. To turn the switcher off everywhere without removing it from your content, toggle \"Show language switcher\" off on the Settings screen.<\/p><\/dd>\n<dt id=\"how%20do%20i%20link%20a%20post%20to%20its%20translation%20in%20another%20language%3F\"><h3>How do I link a post to its translation in another language?<\/h3><\/dt>\n<dd><p>Open the post or page editor and use the WakaLang meta box to set the post's language and link it into a translation group. From there you can see the other-language versions and create a draft translation to fill in. Taxonomy terms are linked the same way from the term editor. WakaLang stores these relationships in its own table and removes them automatically when a post is deleted.<\/p><\/dd>\n<dt id=\"do%20menus%20and%20internal%20links%20follow%20the%20current%20language%3F\"><h3>Do menus and internal links follow the current language?<\/h3><\/dt>\n<dd><p>Yes. While a visitor is on <code>\/en\/<\/code>, menu links, internal permalinks, the site logo\/home link, and block-theme navigation keep the <code>\/en\/<\/code> prefix. WakaLang maintains the prefix only \u2014 it does not silently redirect to a different translation \u2014 and it leaves external links, anchors, <code>\/wp-admin\/<\/code>, REST, and feeds untouched.<\/p><\/dd>\n<dt id=\"can%20i%20migrate%20from%20polylang%20or%20wpml%3F\"><h3>Can I migrate from Polylang or WPML?<\/h3><\/dt>\n<dd><p>WakaLang does not include an automatic importer. You register your languages, then set each post's language and link translations into a group manually. Because WakaLang relies on WordPress's standard slugs and a small custom table, content stays in plain WordPress posts and terms.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\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:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/328416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=328416"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/noricku"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=328416"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=328416"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=328416"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=328416"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=328416"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=328416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}