Changelog — JPKCom Simple Lang
Versionsverlauf des WordPress-Plugins JPKCom Simple Lang.
Versionsverlauf von jpkcom-simple-lang. Die Einträge stammen unverändert aus der README des Projekts. Eine ausführliche Anleitung mit Tipps findest du im Projekt-Guide.
1.2.9
- Fixed: WordPress variant locales could not be saved. The check was a regex,
/^[a-z]{2,3}(_[A-Z]{2})?$/, which silently rejectedde_DE_formal,nl_NL_formal,de_CH_informal,pt_PT_ao90andart_xemoji— the meta box offered them,save_postdropped them, and nothing said so. This plugin even ships its ownde_DE_formaltranslation. Validation now runs againstget_available_languages()plusen_US, which is both stricter (no invented locales) and complete - Fixed: hreflang lost the region.
de_DEandde_ATboth came out ashreflang="de", so a two-language set advertised the same value for two different URLs and the annotation became ambiguous — regional variants are exactly what hreflang is for. Tags are now proper BCP 47 (de-DE,de-AT,pt-BR), WordPress variant suffixes are dropped (de_DE_formal→de-DE), and two versions resolving to the same tag contribute one entry instead of a contradictory pair - Added: an
x-defaultlink pointing at the version in the site's default language, matched on the BCP 47 tag so ade_DE_formalpage still counts as the German version on ade_DEsite. Omitted when no version carries the default language - Fixed: the
langattribute on<html>now carries the region too (lang="de-DE"instead oflang="de") - Fixed: a failed locale switch is no longer treated as a success.
switch_to_locale()returns false when the language pack is missing; that return value was ignored, so a page set to an uninstalled language advertisedlang="fr"andhreflang="fr"while serving the site language, andwp_footerrestored a switch that had never happened - Added: the editor now warns when a post's language pack is not installed, and the stored language stays selectable in the meta box. Previously it vanished from the dropdown, so simply pressing Update silently cleared the post's language without anyone touching the field
- Removed: the plugin's own
localefilter.switch_to_locale()installs WordPress' own filter, so it was redundant when the switch succeeded — and when it failed it was the thing that made the request claim a language WordPress had not loaded. It also ran ahead of the core locale switcher, so a laterswitch_to_locale()by other code could be overridden - Fixed: the settings sanitiser raised a
TypeErroron a non-array value. It was typed?array, which rejected the value before theis_array()guard inside could run, so a hand-edited options form produced a fatal instead of the intended fallback - Added:
tests/test-language.php— 36 cases covering locale validation, BCP 47 conversion, the hreflang and x-default output and the settings sanitiser; 13 of them fail against 1.2.8. CI runs it on every pull request and push tomain - i18n: new strings translated for
de_DEandde_DE_formal,.pot,.moand.l10n.phpregenerated. Atranslators:comment that sat too far from its_n()call to reach the POT was moved next to it - i18n: the shipped translation files were carrying about 110 foreign strings — entries extracted from WordPress core's
theme.json, WooCommerce's email editor and the Twenty Twenty-Five theme, from a POT that had once been generated in the wrong working directory. Regenerating from the plugin directory alone brings the catalogue down to the 47 strings this plugin actually has. The.poheaders, includingPlural-Forms, are unchanged
1.2.8
- Changed: the update manifest generator now defaults a missing
Network:header to false instead of true, matching WordPress' own default. No change for this plugin, which declaresNetwork: trueexplicitly - CI: the lint and guard workflow now also runs on pushes to
main. It only covered pull requests, so a direct push with bypass rights skipped every check - Changed: comments, workflow step names and CI output across the repository are now English throughout, and the developer notes in
CLAUDE.mdwere translated and trimmed. No effect on the shipped plugin
1.2.7
- Changed:
Tested up toraised to WordPress 7.1 - Changed: the bundled updater's runtime floor now matches the plugin's own minimum. It bailed out below WordPress 6.8 while the plugin header has required 6.9 for several releases, so the check could never fire on a supported installation
- Docs: the remaining "WordPress 6.8" requirement statements now say 6.9, matching the plugin header
- CI: the release manifest's fallback values for
requiresandtestednow say 6.9 and 7.1. They only apply when the README metadata cannot be read, but a stale fallback would have published a minimum the plugin no longer supports
1.2.6
- Changed: the plugin banners (
assets/banner-1544x500.avif,assets/banner-772x250.avif) are now a plain#3c4955surface with no lettering
1.2.5
- CI: the release step no longer copies the staging directory into itself, so the ZIP has no empty
jpkcom-simple-lang/jpkcom-simple-lang/folder - CI: bumped the pinned GitHub Actions (checkout v7.0.1, setup-python v7.0.0, action-gh-release v3.0.2, fetch-metadata v3.1.0), still pinned to full commit SHAs
- CI: the release ZIP now excludes the development-only
tests/andtools/directories - CI: security and regression tests now run on every pull request, where a plugin has them
1.2.4
- Security: update packages are now verified before installation — the verified file is handed to WordPress instead of being downloaded a second time, so the bytes that were checked are the bytes that get installed
- Security: a missing or unfetchable SHA-256 checksum now aborts the update instead of installing unverified code (previously it silently skipped verification)
- Security: pinned every GitHub Action to a full commit SHA and added Dependabot with a 7-day cooldown, so a moved tag can no longer change the release build
- Security: tightened which download the updater claims, so sibling plugins cannot match each other's package
- Fixed:
sprintf()calls in the updater bound named arguments to a variadic parameter, which raisesArgumentCountErroron PHP 8.3 - Fixed: the "View Details" modal could fail with a
TypeErrorwhen the manifest omittedrequires_plugins - Performance: a failed manifest fetch is now cached for an hour instead of being retried on every admin request
- Added: CI workflow on every pull request (PHP lint, named-argument check, YAML validation, action-pinning guard)
- Housekeeping: removed stray editor backups from the release package
1.2.3 - 2026-06-16
- Raised the minimum WordPress version to 6.9 and "Tested up to" to WordPress 7.0
- Switched license metadata to the SPDX identifier
GPL-2.0-or-laterwith the HTTPS license URI
1.2.2 - 2026-06-16
- Security: updater prefers an exact match against the manifest
download_urlover the slug heuristic, so a tampered manifest can no longer bypass the checksum gate - Security: timing-safe checksum comparison (
hash_equals()) with anis_string()guard againsthash_file()failures - Security: manifest fetch via
wp_safe_remote_get()(SSRF defense-in-depth) - Fixed PHP warning and missing contributor names in the plugin detail popup (
display_namenow provided) - Fixed PHP warning/deprecation on
wp plugin listby completing theno_updatetransient entry (new_version,package,tested,requires_php)
1.2.1 - 2026-03-13
Bug Fixes
- Fixed manual ZIP upload failing with "No valid URL" error caused by checksum verification running on local file paths instead of remote URLs
- Fixed release ZIP missing top-level plugin directory, preventing WordPress from recognizing it as an update to the existing installation
1.2.0 - 2026-03-13
Bug Fixes
- Fixed language selection not saving for locales without country code (e.g.
arfor Arabic) - Updated locale validation regex to accept both short (
xx) and full (xx_XX) locale formats
1.1.1 - 2025-12-17
Bug Fixes
- Fixed duplicate "Settings saved" message on admin settings page
- Fixed Oxygen Builder conditions not displaying dropdown options
- Fixed Oxygen Builder condition callback signatures to match API requirements
Improvements
- Updated Oxygen Builder conditions to use correct API structure with 'options' array
- Added proper operator support (==, !=) for "Post Language Is" condition
- Added Yes/No dropdown options for boolean Oxygen conditions
- Added German translations for Oxygen condition options (Ja/Nein)
- All Oxygen conditions now appear under "Simple Lang" category
Technical Changes
- Renamed callback functions to match Oxygen API conventions:
jpkcom_simplelang_oxygen_post_language_is()with ($value, $operator) parametersjpkcom_simplelang_oxygen_has_custom_language()with ($value, $operator) parametersjpkcom_simplelang_oxygen_uses_default_language()with ($value, $operator) parameters
- Removed redundant
settings_errors()call in admin settings page
1.1.0 - 2025-12-17
New Features
- Translation Links: New meta box for linking posts in different languages
- Hreflang Tags: Automatic generation of SEO-friendly
<link rel="alternate" hreflang="">tags - Bidirectional Linking: Posts automatically link to each other when translation links are created
- Complete Translation Sets: All posts in a translation group are automatically linked together
- Smart Validation: Prevents duplicate languages in translation sets
Bug Fixes
- Fixed locale detection for default site language in translation grouping
- Fixed type casting issue in translation link display
- Improved meta data consistency across all translation sync operations
Improvements
- New helper function:
jpkcom_simplelang_get_site_default_locale() - Enhanced hreflang output with deterministic sorting
- Performance optimization: Single query for all translation posts (prevents N+1 queries)
- Updated German translations (de_DE and de_DE_formal)
Developer Notes
- New module:
includes/hreflang-translations.php - New meta key:
_jpkcom_simplelang_translations(multiple entries per post) - All translation sync operations use loop prevention for data integrity
1.0.0 - 2025-12-16
Initial Release
- Language selection dropdown in post editor sidebar
- Support for all WordPress core languages
- Post type activation settings page
- Frontend locale override (HTML lang attribute and SEO plugin compatibility)
- Oxygen Builder conditional logic integration
- Helper functions for developers
- Template override system
- Automatic GitHub-based updates
- German translations included
- Full documentation and API docs