PluginProbe
Gutenberg / 23.7.2
Gutenberg v23.7.2
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / compat / wordpress-7.0 / script-modules.php

script-modules.php in Gutenberg 23.7.2, at lib/compat/wordpress-7.0/script-modules.php

230 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Script Modules API: Polyfill for script module translations.
4 *
5 * Provides translation support for script modules on WordPress versions
6 * that do not yet include this functionality in Core.
7 *
8 * @package gutenberg
9 * @since X.X.X
10 */
11
12 /**
13 * Gets the raw source URL for a registered script module.
14 *
15 * Uses WP_Script_Modules::get_registered() if available (WP 7.0+),
16 * otherwise falls back to reflection to access the private registered array.
17 *
18 * @since X.X.X
19 *
20 * @param string $id The script module identifier.
21 * @return string|null The script module source URL, or null if not registered.
22 */
23 function gutenberg_get_script_module_src( string $id ): ?string {
24 $script_modules = wp_script_modules();
25
26 if ( method_exists( $script_modules, 'get_registered' ) ) {
27 $module = $script_modules->get_registered( $id );
28 return null === $module ? null : ( $module['src'] ?? null );
29 }
30
31 // Fallback for WP versions without get_registered().
32 $reflection = new ReflectionClass( $script_modules );
33 $prop = $reflection->getProperty( 'registered' );
34 if ( PHP_VERSION_ID < 80100 ) {
35 $prop->setAccessible( true );
36 }
37 $registered = $prop->getValue( $script_modules );
38
39 return $registered[ $id ]['src'] ?? null;
40 }
41
42 /**
43 * Prints translations for all enqueued script modules.
44 *
45 * Auto-detects the text domain for each enqueued module from its source URL.
46 *
47 * @since X.X.X
48 */
49 function gutenberg_print_script_module_translations() {
50 $script_modules = wp_script_modules();
51 $queue = $script_modules->get_queue();
52 if ( empty( $queue ) ) {
53 return;
54 }
55
56 // Collect enqueued modules and their static/dynamic dependencies.
57 $module_ids = array();
58 $reflection = new ReflectionClass( $script_modules );
59 if ( $reflection->hasMethod( 'get_sorted_dependencies' ) ) {
60 $method = $reflection->getMethod( 'get_sorted_dependencies' );
61 if ( PHP_VERSION_ID < 80100 ) {
62 $method->setAccessible( true );
63 }
64 $module_ids = $method->invoke( $script_modules, $queue );
65 } else {
66 $module_ids = $queue;
67 }
68
69 $set_locale_data_js_function = <<<'JS'
70 ( domain, translations ) => {
71 const localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
72 localeData[""].domain = domain;
73 wp.i18n.setLocaleData( localeData, domain );
74 }
75 JS;
76
77 foreach ( $module_ids as $id ) {
78 $json_translations = load_script_module_textdomain( $id );
79 if ( ! $json_translations ) {
80 continue;
81 }
82
83 $output = sprintf(
84 '( %s )( %s, %s );',
85 $set_locale_data_js_function,
86 wp_json_encode( 'default' ),
87 $json_translations
88 );
89 $source_url = rawurlencode( "wp-script-module-translation-data-{$id}" );
90 $output .= "\n//# sourceURL={$source_url}";
91
92 // Ensure wp-i18n is printed; the inline script below relies on wp.i18n.setLocaleData().
93 if ( ! wp_script_is( 'wp-i18n', 'done' ) ) {
94 wp_scripts()->do_items( array( 'wp-i18n' ) );
95 }
96
97 wp_print_inline_script_tag( $output, array( 'id' => "wp-script-module-translation-data-{$id}" ) );
98 }
99 }
100
101 // Print translations after classic scripts are loaded (priority 10) but before modules execute.
102 add_action( 'wp_footer', 'gutenberg_print_script_module_translations', 21 );
103 add_action( 'admin_print_footer_scripts', 'gutenberg_print_script_module_translations', 11 );
104
105 if ( ! function_exists( 'load_script_module_textdomain' ) ) {
106 /**
107 * Loads the translation data for a given script module ID and text domain.
108 *
109 * Works like load_script_textdomain() but for script modules registered
110 * via wp_register_script_module().
111 *
112 * @since X.X.X
113 *
114 * @param string $id The script module identifier.
115 * @param string $domain Optional. Text domain. Default 'default'.
116 * @param string $path Optional. The full file path to the directory containing translation files.
117 * @return string|false The JSON-encoded translated strings for the given script module and text domain.
118 * False if there are none.
119 */
120 function load_script_module_textdomain( $id, $domain = 'default', $path = '' ) {
121 global $wp_textdomain_registry;
122
123 $src = gutenberg_get_script_module_src( $id );
124
125 if ( null === $src ) {
126 return false;
127 }
128
129 $locale = determine_locale();
130
131 if ( ! $path ) {
132 $path = $wp_textdomain_registry->get( $domain, $locale );
133 }
134
135 $path = untrailingslashit( $path );
136
137 $file_base = 'default' === $domain ? $locale : $domain . '-' . $locale;
138 $handle_filename = $file_base . '-' . $id . '.json';
139
140 if ( $path ) {
141 $translations = load_script_translations( $path . '/' . $handle_filename, $id, $domain );
142 if ( $translations ) {
143 return $translations;
144 }
145 }
146
147 if ( ! preg_match( '|^(https?:)?//|', $src ) ) {
148 $src = site_url( $src );
149 }
150
151 $relative = false;
152 $languages_path = WP_LANG_DIR;
153
154 $src_url = wp_parse_url( $src );
155 $content_url = wp_parse_url( content_url() );
156 $plugins_url = wp_parse_url( plugins_url() );
157 $site_url = wp_parse_url( site_url() );
158 $theme_root = get_theme_root();
159
160 if (
161 ( ! isset( $content_url['path'] ) || str_starts_with( $src_url['path'], $content_url['path'] ) ) &&
162 ( ! isset( $src_url['host'] ) || ! isset( $content_url['host'] ) || $src_url['host'] === $content_url['host'] )
163 ) {
164 if ( isset( $content_url['path'] ) ) {
165 $relative = substr( $src_url['path'], strlen( $content_url['path'] ) );
166 } else {
167 $relative = $src_url['path'];
168 }
169 $relative = trim( $relative, '/' );
170 $relative = explode( '/', $relative );
171
172 $theme_dir = array_slice( explode( '/', $theme_root ), -1 );
173 $dirname = $theme_dir[0] === $relative[0] ? 'themes' : 'plugins';
174
175 $languages_path = WP_LANG_DIR . '/' . $dirname;
176 $relative = array_slice( $relative, 2 );
177 $relative = implode( '/', $relative );
178 } elseif (
179 ( ! isset( $plugins_url['path'] ) || str_starts_with( $src_url['path'], $plugins_url['path'] ) ) &&
180 ( ! isset( $src_url['host'] ) || ! isset( $plugins_url['host'] ) || $src_url['host'] === $plugins_url['host'] )
181 ) {
182 if ( isset( $plugins_url['path'] ) ) {
183 $relative = substr( $src_url['path'], strlen( $plugins_url['path'] ) );
184 } else {
185 $relative = $src_url['path'];
186 }
187 $relative = trim( $relative, '/' );
188 $relative = explode( '/', $relative );
189
190 $languages_path = WP_LANG_DIR . '/plugins';
191 $relative = array_slice( $relative, 1 );
192 $relative = implode( '/', $relative );
193 } elseif ( ! isset( $src_url['host'] ) || ! isset( $site_url['host'] ) || $src_url['host'] === $site_url['host'] ) {
194 if ( ! isset( $site_url['path'] ) ) {
195 $relative = trim( $src_url['path'], '/' );
196 } elseif ( str_starts_with( $src_url['path'], trailingslashit( $site_url['path'] ) ) ) {
197 $relative = substr( $src_url['path'], strlen( $site_url['path'] ) );
198 $relative = trim( $relative, '/' );
199 }
200 }
201
202 /** This filter is documented in wp-includes/l10n.php */
203 $relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $src, true );
204
205 if ( false === $relative ) {
206 return load_script_translations( false, $id, $domain );
207 }
208
209 if ( str_ends_with( $relative, '.min.js' ) ) {
210 $relative = substr( $relative, 0, -7 ) . '.js';
211 }
212
213 $md5_filename = $file_base . '-' . md5( $relative ) . '.json';
214
215 if ( $path ) {
216 $translations = load_script_translations( $path . '/' . $md5_filename, $id, $domain );
217 if ( $translations ) {
218 return $translations;
219 }
220 }
221
222 $translations = load_script_translations( $languages_path . '/' . $md5_filename, $id, $domain );
223 if ( $translations ) {
224 return $translations;
225 }
226
227 return load_script_translations( false, $id, $domain );
228 }
229 }
230