at path:ROOT / wp-includes / l10n.php
run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄l10n.php
1<?php
2/**
3 * Core Translation API
4 *
5 * @package WordPress
6 * @subpackage i18n
7 * @since 1.2.0
8 */
9
10/**
11 * Retrieves the current locale.
12 *
13 * If the locale is set, then it will filter the locale in the {@see 'locale'}
14 * filter hook and return the value.
15 *
16 * If the locale is not set already, then the WPLANG constant is used if it is
17 * defined. Then it is filtered through the {@see 'locale'} filter hook and
18 * the value for the locale global set and the locale is returned.
19 *
20 * The process to get the locale should only be done once, but the locale will
21 * always be filtered using the {@see 'locale'} hook.
22 *
23 * @since 1.5.0
24 *
25 * @global string $locale The current locale.
26 * @global string $wp_local_package Locale code of the package.
27 *
28 * @return string The locale of the blog or from the {@see 'locale'} hook.
29 */
30function get_locale() {
31 global $locale, $wp_local_package;
32
33 if ( isset( $locale ) ) {
34 /** This filter is documented in wp-includes/l10n.php */
35 return apply_filters( 'locale', $locale );
36 }
37
38 if ( isset( $wp_local_package ) ) {
39 $locale = $wp_local_package;
40 }
41
42 // WPLANG was defined in wp-config.
43 if ( defined( 'WPLANG' ) ) {
44 $locale = WPLANG;
45 }
46
47 // If multisite, check options.
48 if ( is_multisite() ) {
49 // Don't check blog option when installing.
50 if ( wp_installing() ) {
51 $ms_locale = get_site_option( 'WPLANG' );
52 } else {
53 $ms_locale = get_option( 'WPLANG' );
54 if ( false === $ms_locale ) {
55 $ms_locale = get_site_option( 'WPLANG' );
56 }
57 }
58
59 if ( false !== $ms_locale ) {
60 $locale = $ms_locale;
61 }
62 } else {
63 $db_locale = get_option( 'WPLANG' );
64 if ( false !== $db_locale ) {
65 $locale = $db_locale;
66 }
67 }
68
69 if ( empty( $locale ) ) {
70 $locale = 'en_US';
71 }
72
73 /**
74 * Filters the locale ID of the WordPress installation.
75 *
76 * @since 1.5.0
77 *
78 * @param string $locale The locale ID.
79 */
80 return apply_filters( 'locale', $locale );
81}
82
83/**
84 * Retrieves the locale of a user.
85 *
86 * If the user has a locale set to a non-empty string then it will be
87 * returned. Otherwise it returns the locale of get_locale().
88 *
89 * @since 4.7.0
90 *
91 * @param int|WP_User $user User's ID or a WP_User object. Defaults to current user.
92 * @return string The locale of the user.
93 */
94function get_user_locale( $user = 0 ) {
95 $user_object = false;
96
97 if ( 0 === $user && function_exists( 'wp_get_current_user' ) ) {
98 $user_object = wp_get_current_user();
99 } elseif ( $user instanceof WP_User ) {
100 $user_object = $user;
101 } elseif ( $user && is_numeric( $user ) ) {
102 $user_object = get_user_by( 'id', $user );
103 }
104
105 if ( ! $user_object ) {
106 return get_locale();
107 }
108
109 $locale = $user_object->locale;
110
111 return $locale ? $locale : get_locale();
112}
113
114/**
115 * Determines the current locale desired for the request.
116 *
117 * @since 5.0.0
118 *
119 * @global string $pagenow The filename of the current screen.
120 * @global string $wp_local_package Locale code of the package.
121 *
122 * @return string The determined locale.
123 */
124function determine_locale() {
125 /**
126 * Filters the locale for the current request prior to the default determination process.
127 *
128 * Using this filter allows to override the default logic, effectively short-circuiting the function.
129 *
130 * @since 5.0.0
131 *
132 * @param string|null $locale The locale to return and short-circuit. Default null.
133 */
134 $determined_locale = apply_filters( 'pre_determine_locale', null );
135
136 if ( $determined_locale && is_string( $determined_locale ) ) {
137 return $determined_locale;
138 }
139
140 if (
141 isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] &&
142 ( ! empty( $_GET['wp_lang'] ) || ! empty( $_COOKIE['wp_lang'] ) )
143 ) {
144 if ( ! empty( $_GET['wp_lang'] ) ) {
145 $determined_locale = sanitize_locale_name( $_GET['wp_lang'] );
146 } else {
147 $determined_locale = sanitize_locale_name( $_COOKIE['wp_lang'] );
148 }
149 } elseif (
150 is_admin() ||
151 ( isset( $_GET['_locale'] ) && 'user' === $_GET['_locale'] && wp_is_json_request() )
152 ) {
153 $determined_locale = get_user_locale();
154 } elseif (
155 ( ! empty( $_REQUEST['language'] ) || isset( $GLOBALS['wp_local_package'] ) )
156 && wp_installing()
157 ) {
158 if ( ! empty( $_REQUEST['language'] ) ) {
159 $determined_locale = sanitize_locale_name( $_REQUEST['language'] );
160 } else {
161 $determined_locale = $GLOBALS['wp_local_package'];
162 }
163 }
164
165 if ( ! $determined_locale ) {
166 $determined_locale = get_locale();
167 }
168
169 /**
170 * Filters the locale for the current request.
171 *
172 * @since 5.0.0
173 *
174 * @param string $determined_locale The locale.
175 */
176 return apply_filters( 'determine_locale', $determined_locale );
177}
178
179/**
180 * Retrieves the translation of $text.
181 *
182 * If there is no translation, or the text domain isn't loaded, the original text is returned.
183 *
184 * *Note:* Don't use translate() directly, use __() or related functions.
185 *
186 * @since 2.2.0
187 * @since 5.5.0 Introduced `gettext-{$domain}` filter.
188 *
189 * @param string $text Text to translate.
190 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
191 * Default 'default'.
192 * @return string Translated text.
193 */
194function translate( $text, $domain = 'default' ) {
195 $translations = get_translations_for_domain( $domain );
196 $translation = $translations->translate( $text );
197
198 /**
199 * Filters text with its translation.
200 *
201 * @since 2.0.11
202 *
203 * @param string $translation Translated text.
204 * @param string $text Text to translate.
205 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
206 */
207 $translation = apply_filters( 'gettext', $translation, $text, $domain );
208
209 /**
210 * Filters text with its translation for a domain.
211 *
212 * The dynamic portion of the hook name, `$domain`, refers to the text domain.
213 *
214 * @since 5.5.0
215 *
216 * @param string $translation Translated text.
217 * @param string $text Text to translate.
218 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
219 */
220 $translation = apply_filters( "gettext_{$domain}", $translation, $text, $domain );
221
222 return $translation;
223}
224
225/**
226 * Removes last item on a pipe-delimited string.
227 *
228 * Meant for removing the last item in a string, such as 'Role name|User role'. The original
229 * string will be returned if no pipe '|' characters are found in the string.
230 *
231 * @since 2.8.0
232 *
233 * @param string $text A pipe-delimited string.
234 * @return string Either $text or everything before the last pipe.
235 */
236function before_last_bar( $text ) {
237 $last_bar = strrpos( $text, '|' );
238 if ( false === $last_bar ) {
239 return $text;
240 } else {
241 return substr( $text, 0, $last_bar );
242 }
243}
244
245/**
246 * Retrieves the translation of $text in the context defined in $context.
247 *
248 * If there is no translation, or the text domain isn't loaded, the original text is returned.
249 *
250 * *Note:* Don't use translate_with_gettext_context() directly, use _x() or related functions.
251 *
252 * @since 2.8.0
253 * @since 5.5.0 Introduced `gettext_with_context-{$domain}` filter.
254 *
255 * @param string $text Text to translate.
256 * @param string $context Context information for the translators.
257 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
258 * Default 'default'.
259 * @return string Translated text on success, original text on failure.
260 */
261function translate_with_gettext_context( $text, $context, $domain = 'default' ) {
262 $translations = get_translations_for_domain( $domain );
263 $translation = $translations->translate( $text, $context );
264
265 /**
266 * Filters text with its translation based on context information.
267 *
268 * @since 2.8.0
269 *
270 * @param string $translation Translated text.
271 * @param string $text Text to translate.
272 * @param string $context Context information for the translators.
273 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
274 */
275 $translation = apply_filters( 'gettext_with_context', $translation, $text, $context, $domain );
276
277 /**
278 * Filters text with its translation based on context information for a domain.
279 *
280 * The dynamic portion of the hook name, `$domain`, refers to the text domain.
281 *
282 * @since 5.5.0
283 *
284 * @param string $translation Translated text.
285 * @param string $text Text to translate.
286 * @param string $context Context information for the translators.
287 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
288 */
289 $translation = apply_filters( "gettext_with_context_{$domain}", $translation, $text, $context, $domain );
290
291 return $translation;
292}
293
294/**
295 * Retrieves the translation of $text.
296 *
297 * If there is no translation, or the text domain isn't loaded, the original text is returned.
298 *
299 * @since 2.1.0
300 *
301 * @param string $text Text to translate.
302 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
303 * Default 'default'.
304 * @return string Translated text.
305 */
306function __( $text, $domain = 'default' ) {
307 return translate( $text, $domain );
308}
309
310/**
311 * Retrieves the translation of $text and escapes it for safe use in an attribute.
312 *
313 * If there is no translation, or the text domain isn't loaded, the original text is returned.
314 *
315 * @since 2.8.0
316 *
317 * @param string $text Text to translate.
318 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
319 * Default 'default'.
320 * @return string Translated text on success, original text on failure.
321 */
322function esc_attr__( $text, $domain = 'default' ) {
323 return esc_attr( translate( $text, $domain ) );
324}
325
326/**
327 * Retrieves the translation of $text and escapes it for safe use in HTML output.
328 *
329 * If there is no translation, or the text domain isn't loaded, the original text
330 * is escaped and returned.
331 *
332 * @since 2.8.0
333 *
334 * @param string $text Text to translate.
335 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
336 * Default 'default'.
337 * @return string Translated text.
338 */
339function esc_html__( $text, $domain = 'default' ) {
340 return esc_html( translate( $text, $domain ) );
341}
342
343/**
344 * Displays translated text.
345 *
346 * @since 1.2.0
347 *
348 * @param string $text Text to translate.
349 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
350 * Default 'default'.
351 */
352function _e( $text, $domain = 'default' ) {
353 echo translate( $text, $domain );
354}
355
356/**
357 * Displays translated text that has been escaped for safe use in an attribute.
358 *
359 * Encodes `< > & " '` (less than, greater than, ampersand, double quote, single quote).
360 * Will never double encode entities.
361 *
362 * If you need the value for use in PHP, use esc_attr__().
363 *
364 * @since 2.8.0
365 *
366 * @param string $text Text to translate.
367 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
368 * Default 'default'.
369 */
370function esc_attr_e( $text, $domain = 'default' ) {
371 echo esc_attr( translate( $text, $domain ) );
372}
373
374/**
375 * Displays translated text that has been escaped for safe use in HTML output.
376 *
377 * If there is no translation, or the text domain isn't loaded, the original text
378 * is escaped and displayed.
379 *
380 * If you need the value for use in PHP, use esc_html__().
381 *
382 * @since 2.8.0
383 *
384 * @param string $text Text to translate.
385 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
386 * Default 'default'.
387 */
388function esc_html_e( $text, $domain = 'default' ) {
389 echo esc_html( translate( $text, $domain ) );
390}
391
392/**
393 * Retrieves translated string with gettext context.
394 *
395 * Quite a few times, there will be collisions with similar translatable text
396 * found in more than two places, but with different translated context.
397 *
398 * By including the context in the pot file, translators can translate the two
399 * strings differently.
400 *
401 * @since 2.8.0
402 *
403 * @param string $text Text to translate.
404 * @param string $context Context information for the translators.
405 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
406 * Default 'default'.
407 * @return string Translated context string without pipe.
408 */
409function _x( $text, $context, $domain = 'default' ) {
410 return translate_with_gettext_context( $text, $context, $domain );
411}
412
413/**
414 * Displays translated string with gettext context.
415 *
416 * @since 3.0.0
417 *
418 * @param string $text Text to translate.
419 * @param string $context Context information for the translators.
420 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
421 * Default 'default'.
422 */
423function _ex( $text, $context, $domain = 'default' ) {
424 echo _x( $text, $context, $domain );
425}
426
427/**
428 * Translates string with gettext context, and escapes it for safe use in an attribute.
429 *
430 * If there is no translation, or the text domain isn't loaded, the original text
431 * is escaped and returned.
432 *
433 * @since 2.8.0
434 *
435 * @param string $text Text to translate.
436 * @param string $context Context information for the translators.
437 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
438 * Default 'default'.
439 * @return string Translated text.
440 */
441function esc_attr_x( $text, $context, $domain = 'default' ) {
442 return esc_attr( translate_with_gettext_context( $text, $context, $domain ) );
443}
444
445/**
446 * Translates string with gettext context, and escapes it for safe use in HTML output.
447 *
448 * If there is no translation, or the text domain isn't loaded, the original text
449 * is escaped and returned.
450 *
451 * @since 2.9.0
452 *
453 * @param string $text Text to translate.
454 * @param string $context Context information for the translators.
455 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
456 * Default 'default'.
457 * @return string Translated text.
458 */
459function esc_html_x( $text, $context, $domain = 'default' ) {
460 return esc_html( translate_with_gettext_context( $text, $context, $domain ) );
461}
462
463/**
464 * Translates and retrieves the singular or plural form based on the supplied number.
465 *
466 * Used when you want to use the appropriate form of a string based on whether a
467 * number is singular or plural.
468 *
469 * Example:
470 *
471 * printf( _n( '%s person', '%s people', $count, 'text-domain' ), number_format_i18n( $count ) );
472 *
473 * @since 2.8.0
474 * @since 5.5.0 Introduced `ngettext-{$domain}` filter.
475 *
476 * @param string $single The text to be used if the number is singular.
477 * @param string $plural The text to be used if the number is plural.
478 * @param int $number The number to compare against to use either the singular or plural form.
479 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
480 * Default 'default'.
481 * @return string The translated singular or plural form.
482 */
483function _n( $single, $plural, $number, $domain = 'default' ) {
484 $translations = get_translations_for_domain( $domain );
485 $translation = $translations->translate_plural( $single, $plural, $number );
486
487 /**
488 * Filters the singular or plural form of a string.
489 *
490 * @since 2.2.0
491 *
492 * @param string $translation Translated text.
493 * @param string $single The text to be used if the number is singular.
494 * @param string $plural The text to be used if the number is plural.
495 * @param int $number The number to compare against to use either the singular or plural form.
496 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
497 */
498 $translation = apply_filters( 'ngettext', $translation, $single, $plural, $number, $domain );
499
500 /**
501 * Filters the singular or plural form of a string for a domain.
502 *
503 * The dynamic portion of the hook name, `$domain`, refers to the text domain.
504 *
505 * @since 5.5.0
506 *
507 * @param string $translation Translated text.
508 * @param string $single The text to be used if the number is singular.
509 * @param string $plural The text to be used if the number is plural.
510 * @param int $number The number to compare against to use either the singular or plural form.
511 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
512 */
513 $translation = apply_filters( "ngettext_{$domain}", $translation, $single, $plural, $number, $domain );
514
515 return $translation;
516}
517
518/**
519 * Translates and retrieves the singular or plural form based on the supplied number, with gettext context.
520 *
521 * This is a hybrid of _n() and _x(). It supports context and plurals.
522 *
523 * Used when you want to use the appropriate form of a string with context based on whether a
524 * number is singular or plural.
525 *
526 * Example of a generic phrase which is disambiguated via the context parameter:
527 *
528 * printf( _nx( '%s group', '%s groups', $people, 'group of people', 'text-domain' ), number_format_i18n( $people ) );
529 * printf( _nx( '%s group', '%s groups', $animals, 'group of animals', 'text-domain' ), number_format_i18n( $animals ) );
530 *
531 * @since 2.8.0
532 * @since 5.5.0 Introduced `ngettext_with_context-{$domain}` filter.
533 *
534 * @param string $single The text to be used if the number is singular.
535 * @param string $plural The text to be used if the number is plural.
536 * @param int $number The number to compare against to use either the singular or plural form.
537 * @param string $context Context information for the translators.
538 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
539 * Default 'default'.
540 * @return string The translated singular or plural form.
541 */
542function _nx( $single, $plural, $number, $context, $domain = 'default' ) {
543 $translations = get_translations_for_domain( $domain );
544 $translation = $translations->translate_plural( $single, $plural, $number, $context );
545
546 /**
547 * Filters the singular or plural form of a string with gettext context.
548 *
549 * @since 2.8.0
550 *
551 * @param string $translation Translated text.
552 * @param string $single The text to be used if the number is singular.
553 * @param string $plural The text to be used if the number is plural.
554 * @param int $number The number to compare against to use either the singular or plural form.
555 * @param string $context Context information for the translators.
556 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
557 */
558 $translation = apply_filters( 'ngettext_with_context', $translation, $single, $plural, $number, $context, $domain );
559
560 /**
561 * Filters the singular or plural form of a string with gettext context for a domain.
562 *
563 * The dynamic portion of the hook name, `$domain`, refers to the text domain.
564 *
565 * @since 5.5.0
566 *
567 * @param string $translation Translated text.
568 * @param string $single The text to be used if the number is singular.
569 * @param string $plural The text to be used if the number is plural.
570 * @param int $number The number to compare against to use either the singular or plural form.
571 * @param string $context Context information for the translators.
572 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
573 */
574 $translation = apply_filters( "ngettext_with_context_{$domain}", $translation, $single, $plural, $number, $context, $domain );
575
576 return $translation;
577}
578
579/**
580 * Registers plural strings in POT file, but does not translate them.
581 *
582 * Used when you want to keep structures with translatable plural
583 * strings and use them later when the number is known.
584 *
585 * Example:
586 *
587 * $message = _n_noop( '%s post', '%s posts', 'text-domain' );
588 * ...
589 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) );
590 *
591 * @since 2.5.0
592 *
593 * @param string $singular Singular form to be localized.
594 * @param string $plural Plural form to be localized.
595 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
596 * Default null.
597 * @return array {
598 * Array of translation information for the strings.
599 *
600 * @type string $0 Singular form to be localized. No longer used.
601 * @type string $1 Plural form to be localized. No longer used.
602 * @type string $singular Singular form to be localized.
603 * @type string $plural Plural form to be localized.
604 * @type null $context Context information for the translators.
605 * @type string|null $domain Text domain.
606 * }
607 */
608function _n_noop( $singular, $plural, $domain = null ) {
609 return array(
610 0 => $singular,
611 1 => $plural,
612 'singular' => $singular,
613 'plural' => $plural,
614 'context' => null,
615 'domain' => $domain,
616 );
617}
618
619/**
620 * Registers plural strings with gettext context in POT file, but does not translate them.
621 *
622 * Used when you want to keep structures with translatable plural
623 * strings and use them later when the number is known.
624 *
625 * Example of a generic phrase which is disambiguated via the context parameter:
626 *
627 * $messages = array(
628 * 'people' => _nx_noop( '%s group', '%s groups', 'people', 'text-domain' ),
629 * 'animals' => _nx_noop( '%s group', '%s groups', 'animals', 'text-domain' ),
630 * );
631 * ...
632 * $message = $messages[ $type ];
633 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) );
634 *
635 * @since 2.8.0
636 *
637 * @param string $singular Singular form to be localized.
638 * @param string $plural Plural form to be localized.
639 * @param string $context Context information for the translators.
640 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
641 * Default null.
642 * @return array {
643 * Array of translation information for the strings.
644 *
645 * @type string $0 Singular form to be localized. No longer used.
646 * @type string $1 Plural form to be localized. No longer used.
647 * @type string $2 Context information for the translators. No longer used.
648 * @type string $singular Singular form to be localized.
649 * @type string $plural Plural form to be localized.
650 * @type string $context Context information for the translators.
651 * @type string|null $domain Text domain.
652 * }
653 */
654function _nx_noop( $singular, $plural, $context, $domain = null ) {
655 return array(
656 0 => $singular,
657 1 => $plural,
658 2 => $context,
659 'singular' => $singular,
660 'plural' => $plural,
661 'context' => $context,
662 'domain' => $domain,
663 );
664}
665
666/**
667 * Translates and returns the singular or plural form of a string that's been registered
668 * with _n_noop() or _nx_noop().
669 *
670 * Used when you want to use a translatable plural string once the number is known.
671 *
672 * Example:
673 *
674 * $message = _n_noop( '%s post', '%s posts', 'text-domain' );
675 * ...
676 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) );
677 *
678 * @since 3.1.0
679 *
680 * @param array $nooped_plural {
681 * Array that is usually a return value from _n_noop() or _nx_noop().
682 *
683 * @type string $singular Singular form to be localized.
684 * @type string $plural Plural form to be localized.
685 * @type string|null $context Context information for the translators.
686 * @type string|null $domain Text domain.
687 * }
688 * @param int $count Number of objects.
689 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. If $nooped_plural contains
690 * a text domain passed to _n_noop() or _nx_noop(), it will override this value. Default 'default'.
691 * @return string Either $singular or $plural translated text.
692 */
693function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) {
694 if ( $nooped_plural['domain'] ) {
695 $domain = $nooped_plural['domain'];
696 }
697
698 if ( $nooped_plural['context'] ) {
699 return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain );
700 } else {
701 return _n( $nooped_plural['singular'], $nooped_plural['plural'], $count, $domain );
702 }
703}
704
705/**
706 * Loads a .mo file into the text domain $domain.
707 *
708 * If the text domain already exists, the translations will be merged. If both
709 * sets have the same string, the translation from the original value will be taken.
710 *
711 * On success, the .mo file will be placed in the $l10n global by $domain
712 * and will be a MO object.
713 *
714 * @since 1.5.0
715 * @since 6.1.0 Added the `$locale` parameter.
716 *
717 * @global MO[] $l10n An array of all currently loaded text domains.
718 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again.
719 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
720 *
721 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
722 * @param string $mofile Path to the .mo file.
723 * @param string $locale Optional. Locale. Default is the current locale.
724 * @return bool True on success, false on failure.
725 */
726function load_textdomain( $domain, $mofile, $locale = null ) {
727 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
728 global $l10n, $l10n_unloaded, $wp_textdomain_registry;
729
730 $l10n_unloaded = (array) $l10n_unloaded;
731
732 if ( ! is_string( $domain ) ) {
733 return false;
734 }
735
736 /**
737 * Filters whether to short-circuit loading .mo file.
738 *
739 * Returning a non-null value from the filter will effectively short-circuit
740 * the loading, returning the passed value instead.
741 *
742 * @since 6.3.0
743 *
744 * @param bool|null $loaded The result of loading a .mo file. Default null.
745 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
746 * @param string $mofile Path to the MO file.
747 * @param string|null $locale Locale.
748 */
749 $loaded = apply_filters( 'pre_load_textdomain', null, $domain, $mofile, $locale );
750 if ( null !== $loaded ) {
751 if ( true === $loaded ) {
752 unset( $l10n_unloaded[ $domain ] );
753 }
754
755 return $loaded;
756 }
757
758 /**
759 * Filters whether to override the .mo file loading.
760 *
761 * @since 2.9.0
762 * @since 6.2.0 Added the `$locale` parameter.
763 *
764 * @param bool $override Whether to override the .mo file loading. Default false.
765 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
766 * @param string $mofile Path to the MO file.
767 * @param string|null $locale Locale.
768 */
769 $plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile, $locale );
770
771 if ( true === (bool) $plugin_override ) {
772 unset( $l10n_unloaded[ $domain ] );
773
774 return true;
775 }
776
777 /**
778 * Fires before the MO translation file is loaded.
779 *
780 * @since 2.9.0
781 *
782 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
783 * @param string $mofile Path to the .mo file.
784 */
785 do_action( 'load_textdomain', $domain, $mofile );
786
787 /**
788 * Filters MO file path for loading translations for a specific text domain.
789 *
790 * @since 2.9.0
791 *
792 * @param string $mofile Path to the MO file.
793 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
794 */
795 $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
796
797 if ( ! $locale ) {
798 $locale = determine_locale();
799 }
800
801 $i18n_controller = WP_Translation_Controller::get_instance();
802
803 // Ensures the correct locale is set as the current one, in case it was filtered.
804 $i18n_controller->set_locale( $locale );
805
806 /**
807 * Filters the preferred file format for translation files.
808 *
809 * Can be used to disable the use of PHP files for translations.
810 *
811 * @since 6.5.0
812 *
813 * @param string $preferred_format Preferred file format. Possible values: 'php', 'mo'. Default: 'php'.
814 * @param string $domain The text domain.
815 */
816 $preferred_format = apply_filters( 'translation_file_format', 'php', $domain );
817 if ( ! in_array( $preferred_format, array( 'php', 'mo' ), true ) ) {
818 $preferred_format = 'php';
819 }
820
821 $translation_files = array();
822
823 if ( 'mo' !== $preferred_format ) {
824 $translation_files[] = substr_replace( $mofile, ".l10n.$preferred_format", - strlen( '.mo' ) );
825 }
826
827 $translation_files[] = $mofile;
828
829 foreach ( $translation_files as $file ) {
830 /**
831 * Filters the file path for loading translations for the given text domain.
832 *
833 * Similar to the {@see 'load_textdomain_mofile'} filter with the difference that
834 * the file path could be for an MO or PHP file.
835 *
836 * @since 6.5.0
837 * @since 6.6.0 Added the `$locale` parameter.
838 *
839 * @param string $file Path to the translation file to load.
840 * @param string $domain The text domain.
841 * @param string $locale The locale.
842 */
843 $file = (string) apply_filters( 'load_translation_file', $file, $domain, $locale );
844
845 $success = $i18n_controller->load_file( $file, $domain, $locale );
846
847 if ( $success ) {
848 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof MO ) {
849 $i18n_controller->load_file( $l10n[ $domain ]->get_filename(), $domain, $locale );
850 }
851
852 // Unset NOOP_Translations reference in get_translations_for_domain().
853 unset( $l10n[ $domain ] );
854
855 $l10n[ $domain ] = new WP_Translations( $i18n_controller, $domain );
856
857 $wp_textdomain_registry->set( $domain, $locale, dirname( $file ) );
858
859 return true;
860 }
861 }
862
863 return false;
864}
865
866/**
867 * Unloads translations for a text domain.
868 *
869 * @since 3.0.0
870 * @since 6.1.0 Added the `$reloadable` parameter.
871 *
872 * @global MO[] $l10n An array of all currently loaded text domains.
873 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again.
874 *
875 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
876 * @param bool $reloadable Whether the text domain can be loaded just-in-time again.
877 * @return bool Whether textdomain was unloaded.
878 */
879function unload_textdomain( $domain, $reloadable = false ) {
880 global $l10n, $l10n_unloaded;
881
882 $l10n_unloaded = (array) $l10n_unloaded;
883
884 /**
885 * Filters whether to override the text domain unloading.
886 *
887 * @since 3.0.0
888 * @since 6.1.0 Added the `$reloadable` parameter.
889 *
890 * @param bool $override Whether to override the text domain unloading. Default false.
891 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
892 * @param bool $reloadable Whether the text domain can be loaded just-in-time again.
893 */
894 $plugin_override = apply_filters( 'override_unload_textdomain', false, $domain, $reloadable );
895
896 if ( $plugin_override ) {
897 if ( ! $reloadable ) {
898 $l10n_unloaded[ $domain ] = true;
899 }
900
901 return true;
902 }
903
904 /**
905 * Fires before the text domain is unloaded.
906 *
907 * @since 3.0.0
908 * @since 6.1.0 Added the `$reloadable` parameter.
909 *
910 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
911 * @param bool $reloadable Whether the text domain can be loaded just-in-time again.
912 */
913 do_action( 'unload_textdomain', $domain, $reloadable );
914
915 // Since multiple locales are supported, reloadable text domains don't actually need to be unloaded.
916 if ( ! $reloadable ) {
917 WP_Translation_Controller::get_instance()->unload_textdomain( $domain );
918 }
919
920 if ( isset( $l10n[ $domain ] ) ) {
921 if ( $l10n[ $domain ] instanceof NOOP_Translations ) {
922 unset( $l10n[ $domain ] );
923
924 return false;
925 }
926
927 unset( $l10n[ $domain ] );
928
929 if ( ! $reloadable ) {
930 $l10n_unloaded[ $domain ] = true;
931 }
932
933 return true;
934 }
935
936 return false;
937}
938
939/**
940 * Loads default translated strings based on locale.
941 *
942 * Loads the .mo file in WP_LANG_DIR constant path from WordPress root.
943 * The translated (.mo) file is named based on the locale.
944 *
945 * @see load_textdomain()
946 *
947 * @since 1.5.0
948 *
949 * @param string $locale Optional. Locale to load. Default is the value of get_locale().
950 * @return bool Whether the textdomain was loaded.
951 */
952function load_default_textdomain( $locale = null ) {
953 if ( null === $locale ) {
954 $locale = determine_locale();
955 }
956
957 // Unload previously loaded strings so we can switch translations.
958 unload_textdomain( 'default', true );
959
960 $return = load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo", $locale );
961
962 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) {
963 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo", $locale );
964 return $return;
965 }
966
967 if ( is_admin() || wp_installing() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) || doing_action( 'wp_maybe_auto_update' ) ) {
968 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo", $locale );
969 }
970
971 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) {
972 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo", $locale );
973 }
974
975 return $return;
976}
977
978/**
979 * Loads a plugin's translated strings.
980 *
981 * If the path is not given then it will be the root of the plugin directory.
982 *
983 * The .mo file should be named based on the text domain with a dash, and then the locale exactly.
984 *
985 * @since 1.5.0
986 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
987 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
988 *
989 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
990 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains.
991 *
992 * @param string $domain Unique identifier for retrieving translated strings
993 * @param string|false $deprecated Optional. Deprecated. Use the $plugin_rel_path parameter instead.
994 * Default false.
995 * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides.
996 * Default false.
997 * @return bool True when textdomain is successfully loaded, false otherwise.
998 */
999function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) {
1000 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
1001 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */
1002 global $wp_textdomain_registry, $l10n;
1003
1004 if ( ! is_string( $domain ) ) {
1005 return false;
1006 }
1007
1008 if ( false !== $plugin_rel_path ) {
1009 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' );
1010 } elseif ( false !== $deprecated ) {
1011 _deprecated_argument( __FUNCTION__, '2.7.0' );
1012 $path = ABSPATH . trim( $deprecated, '/' );
1013 } else {
1014 $path = WP_PLUGIN_DIR;
1015 }
1016
1017 $wp_textdomain_registry->set_custom_path( $domain, $path );
1018
1019 // If just-in-time loading was triggered before, reset the entry so it can be tried again.
1020 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) {
1021 unset( $l10n[ $domain ] );
1022 }
1023
1024 return true;
1025}
1026
1027/**
1028 * Loads the translated strings for a plugin residing in the mu-plugins directory.
1029 *
1030 * @since 3.0.0
1031 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
1032 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
1033 *
1034 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1035 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains.
1036 *
1037 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1038 * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo
1039 * file resides. Default empty string.
1040 * @return bool True when textdomain is successfully loaded, false otherwise.
1041 */
1042function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
1043 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
1044 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */
1045 global $wp_textdomain_registry, $l10n;
1046
1047 if ( ! is_string( $domain ) ) {
1048 return false;
1049 }
1050
1051 $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' );
1052
1053 $wp_textdomain_registry->set_custom_path( $domain, $path );
1054
1055 // If just-in-time loading was triggered before, reset the entry so it can be tried again.
1056 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) {
1057 unset( $l10n[ $domain ] );
1058 }
1059
1060 return true;
1061}
1062
1063/**
1064 * Loads the theme's translated strings.
1065 *
1066 * If the current locale exists as a .mo file in the theme's root directory, it
1067 * will be included in the translated strings by the $domain.
1068 *
1069 * The .mo files must be named based on the locale exactly.
1070 *
1071 * @since 1.5.0
1072 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first.
1073 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism.
1074 *
1075 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1076 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains.
1077 *
1078 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1079 * @param string|false $path Optional. Path to the directory containing the .mo file.
1080 * Default false.
1081 * @return bool True when textdomain is successfully loaded, false otherwise.
1082 */
1083function load_theme_textdomain( $domain, $path = false ) {
1084 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
1085 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */
1086 global $wp_textdomain_registry, $l10n;
1087
1088 if ( ! is_string( $domain ) ) {
1089 return false;
1090 }
1091
1092 if ( ! $path ) {
1093 $path = get_template_directory();
1094 }
1095
1096 $wp_textdomain_registry->set_custom_path( $domain, $path );
1097
1098 // If just-in-time loading was triggered before, reset the entry so it can be tried again.
1099 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) {
1100 unset( $l10n[ $domain ] );
1101 }
1102
1103 return true;
1104}
1105
1106/**
1107 * Loads the child theme's translated strings.
1108 *
1109 * If the current locale exists as a .mo file in the child theme's
1110 * root directory, it will be included in the translated strings by the $domain.
1111 *
1112 * The .mo files must be named based on the locale exactly.
1113 *
1114 * @since 2.9.0
1115 *
1116 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1117 * @param string|false $path Optional. Path to the directory containing the .mo file.
1118 * Default false.
1119 * @return bool True when the theme textdomain is successfully loaded, false otherwise.
1120 */
1121function load_child_theme_textdomain( $domain, $path = false ) {
1122 if ( ! $path ) {
1123 $path = get_stylesheet_directory();
1124 }
1125 return load_theme_textdomain( $domain, $path );
1126}
1127
1128/**
1129 * Loads the script translated strings.
1130 *
1131 * @since 5.0.0
1132 * @since 5.0.2 Uses load_script_translations() to load translation data.
1133 * @since 5.1.0 The `$domain` parameter was made optional.
1134 *
1135 * @see WP_Scripts::set_translations()
1136 *
1137 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1138 *
1139 * @param string $handle Name of the script to register a translation domain to.
1140 * @param string $domain Optional. Text domain. Default 'default'.
1141 * @param string $path Optional. The full file path to the directory containing translation files.
1142 * @return string|false The translated strings in JSON encoding on success,
1143 * false if the script textdomain could not be loaded.
1144 */
1145function load_script_textdomain( $handle, $domain = 'default', $path = '' ) {
1146 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
1147 global $wp_textdomain_registry;
1148
1149 $wp_scripts = wp_scripts();
1150
1151 if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
1152 return false;
1153 }
1154
1155 $locale = determine_locale();
1156
1157 if ( ! $path ) {
1158 $path = $wp_textdomain_registry->get( $domain, $locale );
1159 }
1160
1161 $path = untrailingslashit( $path );
1162
1163 // If a path was given and the handle file exists simply return it.
1164 $file_base = 'default' === $domain ? $locale : $domain . '-' . $locale;
1165 $handle_filename = $file_base . '-' . $handle . '.json';
1166
1167 if ( $path ) {
1168 $translations = load_script_translations( $path . '/' . $handle_filename, $handle, $domain );
1169
1170 if ( $translations ) {
1171 return $translations;
1172 }
1173 }
1174
1175 $src = $wp_scripts->registered[ $handle ]->src;
1176
1177 if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $wp_scripts->content_url && str_starts_with( $src, $wp_scripts->content_url ) ) ) {
1178 $src = $wp_scripts->base_url . $src;
1179 }
1180
1181 $relative = false;
1182 $languages_path = WP_LANG_DIR;
1183
1184 $src_url = wp_parse_url( $src );
1185 $content_url = wp_parse_url( content_url() );
1186 $plugins_url = wp_parse_url( plugins_url() );
1187 $site_url = wp_parse_url( site_url() );
1188 $theme_root = get_theme_root();
1189
1190 // If the host is the same or it's a relative URL.
1191 if (
1192 ( ! isset( $content_url['path'] ) || str_starts_with( $src_url['path'], $content_url['path'] ) ) &&
1193 ( ! isset( $src_url['host'] ) || ! isset( $content_url['host'] ) || $src_url['host'] === $content_url['host'] )
1194 ) {
1195 // Make the src relative the specific plugin or theme.
1196 if ( isset( $content_url['path'] ) ) {
1197 $relative = substr( $src_url['path'], strlen( $content_url['path'] ) );
1198 } else {
1199 $relative = $src_url['path'];
1200 }
1201 $relative = trim( $relative, '/' );
1202 $relative = explode( '/', $relative );
1203
1204 /*
1205 * Ensure correct languages path when using a custom `WP_PLUGIN_DIR` / `WP_PLUGIN_URL` configuration,
1206 * a custom theme root, and/or using Multisite with subdirectories.
1207 * See https://core.trac.wordpress.org/ticket/60891 and https://core.trac.wordpress.org/ticket/62016.
1208 */
1209
1210 $theme_dir = array_slice( explode( '/', $theme_root ), -1 );
1211 $dirname = $theme_dir[0] === $relative[0] ? 'themes' : 'plugins';
1212
1213 $languages_path = WP_LANG_DIR . '/' . $dirname;
1214
1215 $relative = array_slice( $relative, 2 ); // Remove plugins/<plugin name> or themes/<theme name>.
1216 $relative = implode( '/', $relative );
1217 } elseif (
1218 ( ! isset( $plugins_url['path'] ) || str_starts_with( $src_url['path'], $plugins_url['path'] ) ) &&
1219 ( ! isset( $src_url['host'] ) || ! isset( $plugins_url['host'] ) || $src_url['host'] === $plugins_url['host'] )
1220 ) {
1221 // Make the src relative the specific plugin.
1222 if ( isset( $plugins_url['path'] ) ) {
1223 $relative = substr( $src_url['path'], strlen( $plugins_url['path'] ) );
1224 } else {
1225 $relative = $src_url['path'];
1226 }
1227 $relative = trim( $relative, '/' );
1228 $relative = explode( '/', $relative );
1229
1230 $languages_path = WP_LANG_DIR . '/plugins';
1231
1232 $relative = array_slice( $relative, 1 ); // Remove <plugin name>.
1233 $relative = implode( '/', $relative );
1234 } elseif ( ! isset( $src_url['host'] ) || ! isset( $site_url['host'] ) || $src_url['host'] === $site_url['host'] ) {
1235 if ( ! isset( $site_url['path'] ) ) {
1236 $relative = trim( $src_url['path'], '/' );
1237 } elseif ( str_starts_with( $src_url['path'], trailingslashit( $site_url['path'] ) ) ) {
1238 // Make the src relative to the WP root.
1239 $relative = substr( $src_url['path'], strlen( $site_url['path'] ) );
1240 $relative = trim( $relative, '/' );
1241 }
1242 }
1243
1244 /**
1245 * Filters the relative path of scripts used for finding translation files.
1246 *
1247 * @since 5.0.2
1248 *
1249 * @param string|false $relative The relative path of the script. False if it could not be determined.
1250 * @param string $src The full source URL of the script.
1251 */
1252 $relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $src );
1253
1254 // If the source is not from WP.
1255 if ( false === $relative ) {
1256 return load_script_translations( false, $handle, $domain );
1257 }
1258
1259 // Translations are always based on the unminified filename.
1260 if ( str_ends_with( $relative, '.min.js' ) ) {
1261 $relative = substr( $relative, 0, -7 ) . '.js';
1262 }
1263
1264 $md5_filename = $file_base . '-' . md5( $relative ) . '.json';
1265
1266 if ( $path ) {
1267 $translations = load_script_translations( $path . '/' . $md5_filename, $handle, $domain );
1268
1269 if ( $translations ) {
1270 return $translations;
1271 }
1272 }
1273
1274 $translations = load_script_translations( $languages_path . '/' . $md5_filename, $handle, $domain );
1275
1276 if ( $translations ) {
1277 return $translations;
1278 }
1279
1280 return load_script_translations( false, $handle, $domain );
1281}
1282
1283/**
1284 * Loads the translation data for the given script handle and text domain.
1285 *
1286 * @since 5.0.2
1287 *
1288 * @param string|false $file Path to the translation file to load. False if there isn't one.
1289 * @param string $handle Name of the script to register a translation domain to.
1290 * @param string $domain The text domain.
1291 * @return string|false The JSON-encoded translated strings for the given script handle and text domain.
1292 * False if there are none.
1293 */
1294function load_script_translations( $file, $handle, $domain ) {
1295 /**
1296 * Pre-filters script translations for the given file, script handle and text domain.
1297 *
1298 * Returning a non-null value allows to override the default logic, effectively short-circuiting the function.
1299 *
1300 * @since 5.0.2
1301 *
1302 * @param string|false|null $translations JSON-encoded translation data. Default null.
1303 * @param string|false $file Path to the translation file to load. False if there isn't one.
1304 * @param string $handle Name of the script to register a translation domain to.
1305 * @param string $domain The text domain.
1306 */
1307 $translations = apply_filters( 'pre_load_script_translations', null, $file, $handle, $domain );
1308
1309 if ( null !== $translations ) {
1310 return $translations;
1311 }
1312
1313 /**
1314 * Filters the file path for loading script translations for the given script handle and text domain.
1315 *
1316 * @since 5.0.2
1317 *
1318 * @param string|false $file Path to the translation file to load. False if there isn't one.
1319 * @param string $handle Name of the script to register a translation domain to.
1320 * @param string $domain The text domain.
1321 */
1322 $file = apply_filters( 'load_script_translation_file', $file, $handle, $domain );
1323
1324 if ( ! $file || ! is_readable( $file ) ) {
1325 return false;
1326 }
1327
1328 $translations = file_get_contents( $file );
1329
1330 /**
1331 * Filters script translations for the given file, script handle and text domain.
1332 *
1333 * @since 5.0.2
1334 *
1335 * @param string $translations JSON-encoded translation data.
1336 * @param string $file Path to the translation file that was loaded.
1337 * @param string $handle Name of the script to register a translation domain to.
1338 * @param string $domain The text domain.
1339 */
1340 return apply_filters( 'load_script_translations', $translations, $file, $handle, $domain );
1341}
1342
1343/**
1344 * Loads plugin and theme text domains just-in-time.
1345 *
1346 * When a textdomain is encountered for the first time, we try to load
1347 * the translation file from `wp-content/languages`, removing the need
1348 * to call load_plugin_textdomain() or load_theme_textdomain().
1349 *
1350 * @since 4.6.0
1351 * @access private
1352 *
1353 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again.
1354 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1355 *
1356 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1357 * @return bool True when the textdomain is successfully loaded, false otherwise.
1358 */
1359function _load_textdomain_just_in_time( $domain ) {
1360 /** @var WP_Textdomain_Registry $wp_textdomain_registry */
1361 global $l10n_unloaded, $wp_textdomain_registry;
1362
1363 $l10n_unloaded = (array) $l10n_unloaded;
1364
1365 // Short-circuit if domain is 'default' which is reserved for core.
1366 if ( 'default' === $domain || isset( $l10n_unloaded[ $domain ] ) ) {
1367 return false;
1368 }
1369
1370 if ( ! $wp_textdomain_registry->has( $domain ) ) {
1371 return false;
1372 }
1373
1374 $locale = determine_locale();
1375 $path = $wp_textdomain_registry->get( $domain, $locale );
1376 if ( ! $path ) {
1377 return false;
1378 }
1379
1380 if ( ! doing_action( 'after_setup_theme' ) && ! did_action( 'after_setup_theme' ) ) {
1381 _doing_it_wrong(
1382 __FUNCTION__,
1383 sprintf(
1384 /* translators: 1: The text domain. 2: 'init'. */
1385 __( 'Translation loading for the %1$s domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the %2$s action or later.' ),
1386 '<code>' . $domain . '</code>',
1387 '<code>init</code>'
1388 ),
1389 '6.7.0'
1390 );
1391 }
1392
1393 // Themes with their language directory outside of WP_LANG_DIR have a different file name.
1394 $template_directory = trailingslashit( get_template_directory() );
1395 $stylesheet_directory = trailingslashit( get_stylesheet_directory() );
1396 if ( str_starts_with( $path, $template_directory ) || str_starts_with( $path, $stylesheet_directory ) ) {
1397 $mofile = "{$path}{$locale}.mo";
1398 } else {
1399 $mofile = "{$path}{$domain}-{$locale}.mo";
1400 }
1401
1402 return load_textdomain( $domain, $mofile, $locale );
1403}
1404
1405/**
1406 * Returns the Translations instance for a text domain.
1407 *
1408 * If there isn't one, returns empty Translations instance.
1409 *
1410 * @since 2.8.0
1411 *
1412 * @global MO[] $l10n An array of all currently loaded text domains.
1413 *
1414 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1415 * @return Translations|NOOP_Translations A Translations instance.
1416 */
1417function get_translations_for_domain( $domain ) {
1418 global $l10n;
1419 if ( isset( $l10n[ $domain ] ) || ( _load_textdomain_just_in_time( $domain ) && isset( $l10n[ $domain ] ) ) ) {
1420 return $l10n[ $domain ];
1421 }
1422
1423 static $noop_translations = null;
1424 if ( null === $noop_translations ) {
1425 $noop_translations = new NOOP_Translations();
1426 }
1427
1428 $l10n[ $domain ] = &$noop_translations;
1429
1430 return $noop_translations;
1431}
1432
1433/**
1434 * Determines whether there are translations for the text domain.
1435 *
1436 * @since 3.0.0
1437 *
1438 * @global MO[] $l10n An array of all currently loaded text domains.
1439 *
1440 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
1441 * @return bool Whether there are translations.
1442 */
1443function is_textdomain_loaded( $domain ) {
1444 global $l10n;
1445 return isset( $l10n[ $domain ] ) && ! $l10n[ $domain ] instanceof NOOP_Translations;
1446}
1447
1448/**
1449 * Translates role name.
1450 *
1451 * Since the role names are in the database and not in the source there
1452 * are dummy gettext calls to get them into the POT file and this function
1453 * properly translates them back.
1454 *
1455 * The before_last_bar() call is needed, because older installations keep the roles
1456 * using the old context format: 'Role name|User role' and just skipping the
1457 * content after the last bar is easier than fixing them in the DB. New installations
1458 * won't suffer from that problem.
1459 *
1460 * @since 2.8.0
1461 * @since 5.2.0 Added the `$domain` parameter.
1462 *
1463 * @param string $name The role name.
1464 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
1465 * Default 'default'.
1466 * @return string Translated role name on success, original name on failure.
1467 */
1468function translate_user_role( $name, $domain = 'default' ) {
1469 return translate_with_gettext_context( before_last_bar( $name ), 'User role', $domain );
1470}
1471
1472/**
1473 * Gets all available languages based on the presence of *.mo and *.l10n.php files in a given directory.
1474 *
1475 * The default directory is WP_LANG_DIR.
1476 *
1477 * @since 3.0.0
1478 * @since 4.7.0 The results are now filterable with the {@see 'get_available_languages'} filter.
1479 * @since 6.5.0 The initial file list is now cached and also takes into account *.l10n.php files.
1480 *
1481 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1482 *
1483 * @param string $dir A directory to search for language files.
1484 * Default WP_LANG_DIR.
1485 * @return string[] An array of language codes or an empty array if no languages are present.
1486 * Language codes are formed by stripping the file extension from the language file names.
1487 */
1488function get_available_languages( $dir = null ) {
1489 global $wp_textdomain_registry;
1490
1491 $languages = array();
1492
1493 $path = is_null( $dir ) ? WP_LANG_DIR : $dir;
1494 $lang_files = $wp_textdomain_registry->get_language_files_from_path( $path );
1495
1496 if ( $lang_files ) {
1497 foreach ( $lang_files as $lang_file ) {
1498 $lang_file = basename( $lang_file, '.mo' );
1499 $lang_file = basename( $lang_file, '.l10n.php' );
1500
1501 if ( ! str_starts_with( $lang_file, 'continents-cities' ) && ! str_starts_with( $lang_file, 'ms-' ) &&
1502 ! str_starts_with( $lang_file, 'admin-' ) ) {
1503 $languages[] = $lang_file;
1504 }
1505 }
1506 }
1507
1508 /**
1509 * Filters the list of available language codes.
1510 *
1511 * @since 4.7.0
1512 *
1513 * @param string[] $languages An array of available language codes.
1514 * @param string $dir The directory where the language files were found.
1515 */
1516 return apply_filters( 'get_available_languages', array_unique( $languages ), $dir );
1517}
1518
1519/**
1520 * Gets installed translations.
1521 *
1522 * Looks in the wp-content/languages directory for translations of
1523 * plugins or themes.
1524 *
1525 * @since 3.7.0
1526 *
1527 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry.
1528 *
1529 * @param string $type What to search for. Accepts 'plugins', 'themes', 'core'.
1530 * @return array Array of language data.
1531 */
1532function wp_get_installed_translations( $type ) {
1533 global $wp_textdomain_registry;
1534
1535 if ( 'themes' !== $type && 'plugins' !== $type && 'core' !== $type ) {
1536 return array();
1537 }
1538
1539 $dir = 'core' === $type ? WP_LANG_DIR : WP_LANG_DIR . "/$type";
1540
1541 if ( ! is_dir( $dir ) ) {
1542 return array();
1543 }
1544
1545 $files = $wp_textdomain_registry->get_language_files_from_path( $dir );
1546 if ( ! $files ) {
1547 return array();
1548 }
1549
1550 $language_data = array();
1551
1552 foreach ( $files as $file ) {
1553 if ( ! preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?)\.(?:mo|l10n\.php)/', basename( $file ), $match ) ) {
1554 continue;
1555 }
1556
1557 list( , $textdomain, $language ) = $match;
1558 if ( '' === $textdomain ) {
1559 $textdomain = 'default';
1560 }
1561
1562 if ( str_ends_with( $file, '.mo' ) ) {
1563 $pofile = substr_replace( $file, '.po', - strlen( '.mo' ) );
1564
1565 if ( ! file_exists( $pofile ) ) {
1566 continue;
1567 }
1568
1569 $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( $pofile );
1570 } else {
1571 $pofile = substr_replace( $file, '.po', - strlen( '.l10n.php' ) );
1572
1573 // If both a PO and a PHP file exist, prefer the PO file.
1574 if ( file_exists( $pofile ) ) {
1575 continue;
1576 }
1577
1578 $language_data[ $textdomain ][ $language ] = wp_get_l10n_php_file_data( $file );
1579 }
1580 }
1581 return $language_data;
1582}
1583
1584/**
1585 * Extracts headers from a PO file.
1586 *
1587 * @since 3.7.0
1588 *
1589 * @param string $po_file Path to PO file.
1590 * @return string[] Array of PO file header values keyed by header name.
1591 */
1592function wp_get_pomo_file_data( $po_file ) {
1593 $headers = get_file_data(
1594 $po_file,
1595 array(
1596 'POT-Creation-Date' => '"POT-Creation-Date',
1597 'PO-Revision-Date' => '"PO-Revision-Date',
1598 'Project-Id-Version' => '"Project-Id-Version',
1599 'X-Generator' => '"X-Generator',
1600 )
1601 );
1602 foreach ( $headers as $header => $value ) {
1603 // Remove possible contextual '\n' and closing double quote.
1604 $headers[ $header ] = preg_replace( '~(\\\n)?"$~', '', $value );
1605 }
1606 return $headers;
1607}
1608
1609/**
1610 * Extracts headers from a PHP translation file.
1611 *
1612 * @since 6.6.0
1613 *
1614 * @param string $php_file Path to a `.l10n.php` file.
1615 * @return string[] Array of file header values keyed by header name.
1616 */
1617function wp_get_l10n_php_file_data( $php_file ) {
1618 $data = (array) include $php_file;
1619
1620 unset( $data['messages'] );
1621 $headers = array(
1622 'POT-Creation-Date' => 'pot-creation-date',
1623 'PO-Revision-Date' => 'po-revision-date',
1624 'Project-Id-Version' => 'project-id-version',
1625 'X-Generator' => 'x-generator',
1626 );
1627
1628 $result = array(
1629 'POT-Creation-Date' => '',
1630 'PO-Revision-Date' => '',
1631 'Project-Id-Version' => '',
1632 'X-Generator' => '',
1633 );
1634
1635 foreach ( $headers as $po_header => $php_header ) {
1636 if ( isset( $data[ $php_header ] ) ) {
1637 $result[ $po_header ] = $data[ $php_header ];
1638 }
1639 }
1640
1641 return $result;
1642}
1643
1644/**
1645 * Displays or returns a Language selector.
1646 *
1647 * @since 4.0.0
1648 * @since 4.3.0 Introduced the `echo` argument.
1649 * @since 4.7.0 Introduced the `show_option_site_default` argument.
1650 * @since 5.1.0 Introduced the `show_option_en_us` argument.
1651 * @since 5.9.0 Introduced the `explicit_option_en_us` argument.
1652 *
1653 * @see get_available_languages()
1654 * @see wp_get_available_translations()
1655 *
1656 * @param string|array $args {
1657 * Optional. Array or string of arguments for outputting the language selector.
1658 *
1659 * @type string $id ID attribute of the select element. Default 'locale'.
1660 * @type string $name Name attribute of the select element. Default 'locale'.
1661 * @type string[] $languages List of installed languages, contain only the locales.
1662 * Default empty array.
1663 * @type array $translations List of available translations. Default result of
1664 * wp_get_available_translations().
1665 * @type string $selected Language which should be selected. Default empty.
1666 * @type bool|int $echo Whether to echo the generated markup. Accepts 0, 1, or their
1667 * boolean equivalents. Default 1.
1668 * @type bool $show_available_translations Whether to show available translations. Default true.
1669 * @type bool $show_option_site_default Whether to show an option to fall back to the site's locale. Default false.
1670 * @type bool $show_option_en_us Whether to show an option for English (United States). Default true.
1671 * @type bool $explicit_option_en_us Whether the English (United States) option uses an explicit value of en_US
1672 * instead of an empty value. Default false.
1673 * }
1674 * @return string HTML dropdown list of languages.
1675 */
1676function wp_dropdown_languages( $args = array() ) {
1677
1678 $parsed_args = wp_parse_args(
1679 $args,
1680 array(
1681 'id' => 'locale',
1682 'name' => 'locale',
1683 'languages' => array(),
1684 'translations' => array(),
1685 'selected' => '',
1686 'echo' => 1,
1687 'show_available_translations' => true,
1688 'show_option_site_default' => false,
1689 'show_option_en_us' => true,
1690 'explicit_option_en_us' => false,
1691 )
1692 );
1693
1694 // Bail if no ID or no name.
1695 if ( ! $parsed_args['id'] || ! $parsed_args['name'] ) {
1696 return;
1697 }
1698
1699 // English (United States) uses an empty string for the value attribute.
1700 if ( 'en_US' === $parsed_args['selected'] && ! $parsed_args['explicit_option_en_us'] ) {
1701 $parsed_args['selected'] = '';
1702 }
1703
1704 $translations = $parsed_args['translations'];
1705 if ( empty( $translations ) ) {
1706 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
1707 $translations = wp_get_available_translations();
1708 }
1709
1710 /*
1711 * $parsed_args['languages'] should only contain the locales. Find the locale in
1712 * $translations to get the native name. Fall back to locale.
1713 */
1714 $languages = array();
1715 foreach ( $parsed_args['languages'] as $locale ) {
1716 if ( isset( $translations[ $locale ] ) ) {
1717 $translation = $translations[ $locale ];
1718 $languages[] = array(
1719 'language' => $translation['language'],
1720 'native_name' => $translation['native_name'],
1721 'lang' => current( $translation['iso'] ),
1722 );
1723
1724 // Remove installed language from available translations.
1725 unset( $translations[ $locale ] );
1726 } else {
1727 $languages[] = array(
1728 'language' => $locale,
1729 'native_name' => $locale,
1730 'lang' => '',
1731 );
1732 }
1733 }
1734
1735 $translations_available = ( ! empty( $translations ) && $parsed_args['show_available_translations'] );
1736
1737 // Holds the HTML markup.
1738 $structure = array();
1739
1740 // List installed languages.
1741 if ( $translations_available ) {
1742 $structure[] = '<optgroup label="' . esc_attr_x( 'Installed', 'translations' ) . '">';
1743 }
1744
1745 // Site default.
1746 if ( $parsed_args['show_option_site_default'] ) {
1747 $structure[] = sprintf(
1748 '<option value="site-default" data-installed="1"%s>%s</option>',
1749 selected( 'site-default', $parsed_args['selected'], false ),
1750 _x( 'Site Default', 'default site language' )
1751 );
1752 }
1753
1754 if ( $parsed_args['show_option_en_us'] ) {
1755 $value = ( $parsed_args['explicit_option_en_us'] ) ? 'en_US' : '';
1756 $structure[] = sprintf(
1757 '<option value="%s" lang="en" data-installed="1"%s>English (United States)</option>',
1758 esc_attr( $value ),
1759 selected( '', $parsed_args['selected'], false )
1760 );
1761 }
1762
1763 // List installed languages.
1764 foreach ( $languages as $language ) {
1765 $structure[] = sprintf(
1766 '<option value="%s" lang="%s"%s data-installed="1">%s</option>',
1767 esc_attr( $language['language'] ),
1768 esc_attr( $language['lang'] ),
1769 selected( $language['language'], $parsed_args['selected'], false ),
1770 esc_html( $language['native_name'] )
1771 );
1772 }
1773 if ( $translations_available ) {
1774 $structure[] = '</optgroup>';
1775 }
1776
1777 // List available translations.
1778 if ( $translations_available ) {
1779 $structure[] = '<optgroup label="' . esc_attr_x( 'Available', 'translations' ) . '">';
1780 foreach ( $translations as $translation ) {
1781 $structure[] = sprintf(
1782 '<option value="%s" lang="%s"%s>%s</option>',
1783 esc_attr( $translation['language'] ),
1784 esc_attr( current( $translation['iso'] ) ),
1785 selected( $translation['language'], $parsed_args['selected'], false ),
1786 esc_html( $translation['native_name'] )
1787 );
1788 }
1789 $structure[] = '</optgroup>';
1790 }
1791
1792 // Combine the output string.
1793 $output = sprintf( '<select name="%s" id="%s">', esc_attr( $parsed_args['name'] ), esc_attr( $parsed_args['id'] ) );
1794 $output .= implode( "\n", $structure );
1795 $output .= '</select>';
1796
1797 if ( $parsed_args['echo'] ) {
1798 echo $output;
1799 }
1800
1801 return $output;
1802}
1803
1804/**
1805 * Determines whether the current locale is right-to-left (RTL).
1806 *
1807 * For more information on this and similar theme functions, check out
1808 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1809 * Conditional Tags} article in the Theme Developer Handbook.
1810 *
1811 * @since 3.0.0
1812 *
1813 * @global WP_Locale $wp_locale WordPress date and time locale object.
1814 *
1815 * @return bool Whether locale is RTL.
1816 */
1817function is_rtl() {
1818 global $wp_locale;
1819 if ( ! ( $wp_locale instanceof WP_Locale ) ) {
1820 return false;
1821 }
1822 return $wp_locale->is_rtl();
1823}
1824
1825/**
1826 * Switches the translations according to the given locale.
1827 *
1828 * @since 4.7.0
1829 *
1830 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object.
1831 *
1832 * @param string $locale The locale.
1833 * @return bool True on success, false on failure.
1834 */
1835function switch_to_locale( $locale ) {
1836 /* @var WP_Locale_Switcher $wp_locale_switcher */
1837 global $wp_locale_switcher;
1838
1839 if ( ! $wp_locale_switcher ) {
1840 return false;
1841 }
1842
1843 return $wp_locale_switcher->switch_to_locale( $locale );
1844}
1845
1846/**
1847 * Switches the translations according to the given user's locale.
1848 *
1849 * @since 6.2.0
1850 *
1851 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object.
1852 *
1853 * @param int $user_id User ID.
1854 * @return bool True on success, false on failure.
1855 */
1856function switch_to_user_locale( $user_id ) {
1857 /* @var WP_Locale_Switcher $wp_locale_switcher */
1858 global $wp_locale_switcher;
1859
1860 if ( ! $wp_locale_switcher ) {
1861 return false;
1862 }
1863
1864 return $wp_locale_switcher->switch_to_user_locale( $user_id );
1865}
1866
1867/**
1868 * Restores the translations according to the previous locale.
1869 *
1870 * @since 4.7.0
1871 *
1872 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object.
1873 *
1874 * @return string|false Locale on success, false on error.
1875 */
1876function restore_previous_locale() {
1877 /* @var WP_Locale_Switcher $wp_locale_switcher */
1878 global $wp_locale_switcher;
1879
1880 if ( ! $wp_locale_switcher ) {
1881 return false;
1882 }
1883
1884 return $wp_locale_switcher->restore_previous_locale();
1885}
1886
1887/**
1888 * Restores the translations according to the original locale.
1889 *
1890 * @since 4.7.0
1891 *
1892 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object.
1893 *
1894 * @return string|false Locale on success, false on error.
1895 */
1896function restore_current_locale() {
1897 /* @var WP_Locale_Switcher $wp_locale_switcher */
1898 global $wp_locale_switcher;
1899
1900 if ( ! $wp_locale_switcher ) {
1901 return false;
1902 }
1903
1904 return $wp_locale_switcher->restore_current_locale();
1905}
1906
1907/**
1908 * Determines whether switch_to_locale() is in effect.
1909 *
1910 * @since 4.7.0
1911 *
1912 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object.
1913 *
1914 * @return bool True if the locale has been switched, false otherwise.
1915 */
1916function is_locale_switched() {
1917 /* @var WP_Locale_Switcher $wp_locale_switcher */
1918 global $wp_locale_switcher;
1919
1920 return $wp_locale_switcher->is_switched();
1921}
1922
1923/**
1924 * Translates the provided settings value using its i18n schema.
1925 *
1926 * @since 5.9.0
1927 * @access private
1928 *
1929 * @param string|string[]|array[]|object $i18n_schema I18n schema for the setting.
1930 * @param string|string[]|array[] $settings Value for the settings.
1931 * @param string $textdomain Textdomain to use with translations.
1932 *
1933 * @return string|string[]|array[] Translated settings.
1934 */
1935function translate_settings_using_i18n_schema( $i18n_schema, $settings, $textdomain ) {
1936 if ( empty( $i18n_schema ) || empty( $settings ) || empty( $textdomain ) ) {
1937 return $settings;
1938 }
1939
1940 if ( is_string( $i18n_schema ) && is_string( $settings ) ) {
1941 return translate_with_gettext_context( $settings, $i18n_schema, $textdomain );
1942 }
1943 if ( is_array( $i18n_schema ) && is_array( $settings ) ) {
1944 $translated_settings = array();
1945 foreach ( $settings as $value ) {
1946 $translated_settings[] = translate_settings_using_i18n_schema( $i18n_schema[0], $value, $textdomain );
1947 }
1948 return $translated_settings;
1949 }
1950 if ( is_object( $i18n_schema ) && is_array( $settings ) ) {
1951 $group_key = '*';
1952 $translated_settings = array();
1953 foreach ( $settings as $key => $value ) {
1954 if ( isset( $i18n_schema->$key ) ) {
1955 $translated_settings[ $key ] = translate_settings_using_i18n_schema( $i18n_schema->$key, $value, $textdomain );
1956 } elseif ( isset( $i18n_schema->$group_key ) ) {
1957 $translated_settings[ $key ] = translate_settings_using_i18n_schema( $i18n_schema->$group_key, $value, $textdomain );
1958 } else {
1959 $translated_settings[ $key ] = $value;
1960 }
1961 }
1962 return $translated_settings;
1963 }
1964 return $settings;
1965}
1966
1967/**
1968 * Retrieves the list item separator based on the locale.
1969 *
1970 * @since 6.0.0
1971 *
1972 * @global WP_Locale $wp_locale WordPress date and time locale object.
1973 *
1974 * @return string Locale-specific list item separator.
1975 */
1976function wp_get_list_item_separator() {
1977 global $wp_locale;
1978
1979 if ( ! ( $wp_locale instanceof WP_Locale ) ) {
1980 // Default value of WP_Locale::get_list_item_separator().
1981 /* translators: Used between list items, there is a space after the comma. */
1982 return __( ', ' );
1983 }
1984
1985 return $wp_locale->get_list_item_separator();
1986}
1987
1988/**
1989 * Retrieves the word count type based on the locale.
1990 *
1991 * @since 6.2.0
1992 *
1993 * @global WP_Locale $wp_locale WordPress date and time locale object.
1994 *
1995 * @return string Locale-specific word count type. Possible values are `characters_excluding_spaces`,
1996 * `characters_including_spaces`, or `words`. Defaults to `words`.
1997 */
1998function wp_get_word_count_type() {
1999 global $wp_locale;
2000
2001 if ( ! ( $wp_locale instanceof WP_Locale ) ) {
2002 // Default value of WP_Locale::get_word_count_type().
2003 return 'words';
2004 }
2005
2006 return $wp_locale->get_word_count_type();
2007}
2008
2009/**
2010 * Returns a boolean to indicate whether a translation exists for a given string with optional text domain and locale.
2011 *
2012 * @since 6.7.0
2013 *
2014 * @param string $singular Singular translation to check.
2015 * @param string $textdomain Optional. Text domain. Default 'default'.
2016 * @param ?string $locale Optional. Locale. Default current locale.
2017 * @return bool True if the translation exists, false otherwise.
2018 */
2019function has_translation( string $singular, string $textdomain = 'default', ?string $locale = null ): bool {
2020 return WP_Translation_Controller::get_instance()->has_translation( $singular, $textdomain, $locale );
2021}
2022
Ui Ux Design – Teachers Night Out

Get in Touch

© 2024 Teachers Night Out. All Rights Reserved.