PluginProbe
Gutenberg / 23.1.1
Gutenberg v23.1.1
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.1.1, at lib/compat/wordpress-7.0/script-modules.php

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