diff --git a/CHANGELOG.md b/CHANGELOG.md index b9c57b2..9226e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. ### Changed - License changed from GPL-2.0-or-later to MIT. +- Translations now load from the central `escalated-dev/locale` Composer package (`vendor/escalated-dev/locale/languages/escalated-{locale}.mo`) with optional site-level overrides from `languages/overrides/escalated-{locale}.mo`. Falls back to the in-tree `languages/` dir when the central package is not installed. ### Fixed - Validate priority against allowed enum values in ticket creation. diff --git a/README.md b/README.md index f1cf6bc..7ada06a 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,30 @@ On activation, Escalated schedules: - `escalated_auto_close` (daily) - `escalated_purge_activities` (weekly) +## Translations + +Escalated for WordPress consumes translations from the central +[`escalated-dev/locale`](https://github.com/escalated-dev/escalated-locale) +Composer package, which is the single source of truth for translations +across every Escalated host plugin. + +At runtime the plugin loads translations in two layers (later layer wins): + +1. **Central** — `vendor/escalated-dev/locale/languages/escalated-{locale}.mo` + (installed automatically via `composer install`). +2. **Local overrides** — `languages/overrides/escalated-{locale}.mo` + (drop your own compiled `.mo` here to override individual entries + without forking the central package). + +If the central package is not yet installed, the plugin falls back to +the legacy in-tree `languages/*.po`/`*.mo` files so existing sites keep +working. + +To submit translation fixes, open a PR against +[`escalated-dev/escalated-locale`](https://github.com/escalated-dev/escalated-locale). +Do **not** edit the in-tree `.po` files — they exist only as a fallback +and will be removed once the central package reaches a stable release. + ## Development Install dependencies: diff --git a/composer.json b/composer.json index 5dd2c00..27800da 100644 --- a/composer.json +++ b/composer.json @@ -3,8 +3,12 @@ "description": "Escalated Helpdesk & Ticketing System for WordPress", "type": "wordpress-plugin", "license": "MIT", + "repositories": [ + {"type": "vcs", "url": "https://github.com/escalated-dev/escalated-locale"} + ], "require": { - "php": ">=8.1" + "php": ">=8.1", + "escalated-dev/locale": "^0.1" }, "require-dev": { "phpunit/phpunit": "^9.6", diff --git a/composer.lock b/composer.lock index 12feeb1..e9cab5c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,50 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ced39379909209d87a2ef7b72cb77788", - "packages": [], + "content-hash": "ef9124c8ff46258852e7cb216be3eb8f", + "packages": [ + { + "name": "escalated-dev/locale", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/escalated-dev/escalated-locale.git", + "reference": "803ddf003005f872fb15a4653cc2be8630b8cc60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/escalated-dev/escalated-locale/zipball/803ddf003005f872fb15a4653cc2be8630b8cc60", + "reference": "803ddf003005f872fb15a4653cc2be8630b8cc60", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "type": "library", + "extra": { + "escalated-locale": { + "json-locales-dir": "packages/composer/locales", + "symfony-translations-dir": "packages/composer/translations", + "wordpress-languages-dir": "packages/composer/languages" + } + }, + "autoload": { + "psr-4": { + "Escalated\\Locale\\": "packages/composer/src/" + } + }, + "license": [ + "MIT" + ], + "description": "Canonical Escalated locale bundle for PHP consumers (Laravel, Symfony, WordPress, Filament).", + "homepage": "https://github.com/escalated-dev/escalated-locale", + "support": { + "issues": "https://github.com/escalated-dev/escalated-locale/issues", + "source": "https://github.com/escalated-dev/escalated-locale" + }, + "time": "2026-05-02T18:59:37+00:00" + } + ], "packages-dev": [ { "name": "doctrine/instantiator", diff --git a/includes/class-escalated.php b/includes/class-escalated.php index 392af48..ea511d3 100644 --- a/includes/class-escalated.php +++ b/includes/class-escalated.php @@ -17,7 +17,7 @@ public static function instance(): self public function boot(): void { - load_plugin_textdomain('escalated', false, dirname(ESCALATED_PLUGIN_BASENAME).'/languages'); + $this->load_translations(); // Register custom cron intervals. add_filter('cron_schedules', [Activator::class, 'add_cron_schedules']); @@ -51,4 +51,43 @@ public static function table(string $name): string return $wpdb->prefix.'escalated_'.$name; } + + /** + * Load plugin translations. + * + * Loads translations in two layers, with WordPress's gettext system + * merging them so the later-loaded layer can override earlier entries: + * + * 1. Central translations from the `escalated-dev/locale` Composer + * package (vendor/escalated-dev/locale/languages/escalated-{locale}.mo). + * Source of truth, shared across all Escalated host plugins. + * 2. Local overrides from this plugin's `languages/overrides/` dir + * (escalated-{locale}.mo), giving site operators a way to tweak + * strings without forking the central package. + * + * If the central package is not installed (e.g. fresh checkout before + * `composer install`), we fall back to the legacy `languages/` dir so + * existing installs continue to work. + */ + private function load_translations(): void + { + $domain = 'escalated'; + $locale = determine_locale(); + $mofile = $domain.'-'.$locale.'.mo'; + + // 1. Central translations shipped by escalated-dev/locale. + $central = ESCALATED_PLUGIN_DIR.'vendor/escalated-dev/locale/languages/'.$mofile; + if (file_exists($central)) { + load_textdomain($domain, $central); + } else { + // Fallback to the legacy in-plugin languages/ dir (pre-central rollout). + load_plugin_textdomain($domain, false, dirname(ESCALATED_PLUGIN_BASENAME).'/languages'); + } + + // 2. Local overrides — entries here win over the central package. + $overrides = ESCALATED_PLUGIN_DIR.'languages/overrides/'.$mofile; + if (file_exists($overrides)) { + load_textdomain($domain, $overrides); + } + } } diff --git a/languages/overrides/.gitkeep b/languages/overrides/.gitkeep new file mode 100644 index 0000000..e69de29