| @@ -24,11 +24,11 @@ | ||
| 24 | 24 | public const VERSION = '1.0.0'; |
| 25 | 25 | |
| 26 | 26 | public function ui_metadata(): array { |
| 27 | 27 | return array( |
| 28 | - 'label' => 'CDN', | |
| 28 | + 'label' => __( 'CDN', 'xspeed' ), | |
| 29 | 29 | 'icon' => 'Globe', |
| 30 | - 'description' => 'Serve static assets (images, fonts, CSS, JS) from a pull-zone CDN host like BunnyCDN, KeyCDN, or your own.', | |
| 30 | + 'description' => __( 'Serve static assets (images, fonts, CSS, JS) from a pull-zone CDN host like BunnyCDN, KeyCDN, or your own.', 'xspeed' ), | |
| 31 | 31 | ); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | public function settings_schema(): array { |
| @@ -35,16 +35,16 @@ | ||
| 35 | 35 | return array( |
| 36 | 36 | 'enabled' => array( |
| 37 | 37 | 'type' => 'bool', |
| 38 | 38 | 'default' => false, |
| 39 | - 'label' => 'Enable CDN', | |
| 40 | - 'description' => 'Rewrite static asset URLs to the CDN hostname below. Your CDN must be a pull-zone configured to fetch from this site.', | |
| 39 | + 'label' => __( 'Enable CDN', 'xspeed' ), | |
| 40 | + 'description' => __( 'Rewrite static asset URLs to the CDN hostname below. Your CDN must be a pull-zone configured to fetch from this site.', 'xspeed' ), | |
| 41 | 41 | ), |
| 42 | 42 | 'cdn_url' => array( |
| 43 | 43 | 'type' => 'string', |
| 44 | 44 | 'default' => '', |
| 45 | - 'label' => 'CDN URL', | |
| 46 | - 'description' => 'CDN hostname, e.g. cdn.example.com. https:// and trailing slashes are stripped automatically.', | |
| 45 | + 'label' => __( 'CDN URL', 'xspeed' ), | |
| 46 | + 'description' => __( 'CDN hostname, e.g. cdn.example.com. https:// and trailing slashes are stripped automatically.', 'xspeed' ), | |
| 47 | 47 | 'dependsOn' => array( 'field' => 'enabled' ), |
| 48 | 48 | ), |
| 49 | 49 | 'included_extensions' => array( |
| 50 | 50 | 'type' => 'list', |
| @@ -49,10 +49,10 @@ | ||
| 49 | 49 | 'included_extensions' => array( |
| 50 | 50 | 'type' => 'list', |
| 51 | 51 | 'default' => Cdn_Rewriter::DEFAULT_EXTENSIONS, |
| 52 | 52 | 'item_type' => 'string', |
| 53 | - 'label' => 'Included File Extensions', | |
| 54 | - 'description' => 'Only URLs ending in these extensions are rewritten. Defaults cover images, fonts, CSS, JS, and common media.', | |
| 53 | + 'label' => __( 'Included File Extensions', 'xspeed' ), | |
| 54 | + 'description' => __( 'Only URLs ending in these extensions are rewritten. Defaults cover images, fonts, CSS, JS, and common media.', 'xspeed' ), | |
| 55 | 55 | 'dependsOn' => array( 'field' => 'enabled' ), |
| 56 | 56 | ), |
| 57 | 57 | 'excluded_patterns' => array( |
| 58 | 58 | 'type' => 'list', |
| @@ -57,10 +57,10 @@ | ||
| 57 | 57 | 'excluded_patterns' => array( |
| 58 | 58 | 'type' => 'list', |
| 59 | 59 | 'default' => array(), |
| 60 | 60 | 'item_type' => 'string', |
| 61 | - 'label' => 'Excluded Patterns', | |
| 62 | - 'description' => 'Glob patterns matched against the URL path. Matching URLs stay on the origin. Examples: /wp-admin/*, *.pdf, /private/*', | |
| 61 | + 'label' => __( 'Excluded Patterns', 'xspeed' ), | |
| 62 | + 'description' => __( 'Glob patterns matched against the URL path. Matching URLs stay on the origin. Examples: /wp-admin/*, *.pdf, /private/*', 'xspeed' ), | |
| 63 | 63 | 'dependsOn' => array( 'field' => 'enabled' ), |
| 64 | 64 | ), |
| 65 | 65 | ); |
| 66 | 66 | } |
| @@ -76,8 +76,27 @@ | ||
| 76 | 76 | ); |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | 79 | public function boot(): void { |
| 80 | + /* | |
| 81 | + * Deferred to `init`. This module reads its own settings to decide | |
| 82 | + * what to hook, and reading settings builds settings_schema(), whose | |
| 83 | + * labels are declared through __(). boot() runs on `plugins_loaded`, | |
| 84 | + * before `after_setup_theme` — the point WordPress 6.7+ treats as the | |
| 85 | + * earliest safe moment to translate — so doing that here fires | |
| 86 | + * _load_textdomain_just_in_time on every request AND resolves the | |
| 87 | + * labels against a domain that is not loaded yet. | |
| 88 | + * | |
| 89 | + * Everything below hooks actions that fire after `init`, so running | |
| 90 | + * one hook later is equivalent. | |
| 91 | + */ | |
| 92 | + add_action( 'init', array( $this, 'boot_on_init' ) ); | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * The real boot body — see boot() for why it runs on `init`. | |
| 97 | + */ | |
| 98 | + public function boot_on_init(): void { | |
| 80 | 99 | // Always-on: normalize cdn_url on save (admin context too). |
| 81 | 100 | add_filter( 'pre_update_option_xspeed_module_cdn', array( $this, 'normalize_on_save' ), 10, 1 ); |
| 82 | 101 | |
| 83 | 102 | // CDN URLs are baked into cached HTML, so a settings change that |
| @@ -89,8 +108,14 @@ | ||
| 89 | 108 | |
| 90 | 109 | if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) || ( defined( 'DOING_CRON' ) && DOING_CRON ) || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { |
| 91 | 110 | return; |
| 92 | 111 | } |
| 112 | + | |
| 113 | + // Rewriting asset hosts under a builder editor sends the editor's own | |
| 114 | + // scripts to the CDN, where the copy can be stale or absent. (#281) | |
| 115 | + if ( \XSpeed\Builder_Editor::is_active() ) { | |
| 116 | + return; | |
| 117 | + } | |
| 93 | 118 | $opts = $this->get_settings(); |
| 94 | 119 | if ( empty( $opts['enabled'] ) || empty( $opts['cdn_url'] ) ) { |
| 95 | 120 | return; |
| 96 | 121 | } |
| @@ -389,8 +414,9 @@ | ||
| 389 | 414 | array( |
| 390 | 415 | 'name' => 'xspeed cdn', |
| 391 | 416 | 'callback' => array( $this, 'cli_handler' ), |
| 392 | 417 | 'shortdesc' => 'Show CDN settings + test rewriting a URL.', |
| 418 | + 'ai_hint' => 'Is a CDN configured, and does URL rewriting work? Use to check whether assets are served from the CDN, or to test what a given URL rewrites to before trusting the setting.', | |
| 393 | 419 | 'synopsis' => array( |
| 394 | 420 | array( |
| 395 | 421 | 'type' => 'positional', |
| 396 | 422 | 'name' => 'action', |