PluginProbe
Polylang / 3.0.2
Polylang v3.0.2
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / include / olt-manager.php

olt-manager.php in Polylang 3.0.2, at include/olt-manager.php

262 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * It is best practice that plugins do nothing before plugins_loaded is fired
8 * so it is what Polylang intends to do
9 * but some plugins load their text domain as soon as loaded, thus before plugins_loaded is fired
10 * this class differs text domain loading until the language is defined
11 * either in a plugins_loaded action or in a wp action ( when the language is set from content on frontend )
12 *
13 * @since 1.2
14 */
15 class PLL_OLT_Manager {
16 /**
17 * Singleton instance
18 *
19 * @var PLL_OLT_Manager
20 */
21 protected static $instance;
22
23 /**
24 * Stores the default site locale before it is modified.
25 *
26 * @var string
27 */
28 protected $default_locale;
29
30 /**
31 * Stores all loaded text domains and mo files.
32 *
33 * @var string[][]
34 */
35 protected $list_textdomains = array();
36
37 /**
38 * Stores post types an taxonomies labels to translate.
39 *
40 * @var string[][]
41 */
42 public $labels = array();
43
44 /**
45 * Constructor: setups relevant filters
46 *
47 * @since 1.2
48 */
49 public function __construct() {
50 // Allows Polylang to be the first plugin loaded ;-)
51 add_filter( 'pre_update_option_active_plugins', array( $this, 'make_polylang_first' ) );
52 add_filter( 'pre_update_option_active_sitewide_plugins', array( $this, 'make_polylang_first' ) );
53
54 // Overriding load text domain only on front since WP 4.7.
55 if ( is_admin() && ! Polylang::is_ajax_on_front() ) {
56 return;
57 }
58
59 // Saves the default locale before we start any language manipulation
60 $this->default_locale = get_locale();
61
62 // Filters for text domain management
63 add_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
64 add_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
65 add_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
66
67 // Loads text domains
68 add_action( 'pll_language_defined', array( $this, 'load_textdomains' ), 2 ); // After PLL_Frontend::pll_language_defined
69 add_action( 'pll_no_language_defined', array( $this, 'load_textdomains' ) );
70 }
71
72 /**
73 * Access to the single instance of the class
74 *
75 * @since 1.7
76 *
77 * @return object
78 */
79 public static function instance() {
80 if ( empty( self::$instance ) ) {
81 self::$instance = new self();
82 }
83
84 return self::$instance;
85 }
86
87 /**
88 * Loads text domains
89 *
90 * @since 0.1
91 *
92 * @return void
93 */
94 public function load_textdomains() {
95 // Our load_textdomain_mofile filter has done its job. let's remove it before calling load_textdomain
96 remove_filter( 'load_textdomain_mofile', array( $this, 'load_textdomain_mofile' ), 10, 2 );
97 remove_filter( 'gettext', array( $this, 'gettext' ), 10, 3 );
98 remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ), 10, 4 );
99 $new_locale = get_locale();
100
101 // Don't try to save time for en_US as some users have theme written in another language
102 // Now we can load all overridden text domains with the right language
103 if ( ! empty( $this->list_textdomains ) ) {
104 /*
105 * FIXME: Backward compatibility with WP < 5.6
106 * From WP 4.7 to 5.5, we need to reset the internal cache of _get_path_to_translation when switching from any locale to en_US.
107 * See WP_Locale_Switcher::change_locale()
108 */
109 if ( ! class_exists( 'WP_Textdomain_Registry' ) && function_exists( '_get_path_to_translation' ) ) {
110 _get_path_to_translation( '', true );
111 }
112
113 foreach ( $this->list_textdomains as $textdomain ) {
114 // Since WP 4.6, plugins translations are first loaded from wp-content/languages
115 if ( ! load_textdomain( $textdomain['domain'], str_replace( "{$this->default_locale}.mo", "$new_locale.mo", $textdomain['mo'] ) ) ) {
116 // Since WP 3.5 themes may store languages files in /wp-content/languages/themes
117 if ( ! load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/themes/{$textdomain['domain']}-$new_locale.mo" ) ) {
118 // Since WP 3.7 plugins may store languages files in /wp-content/languages/plugins
119 load_textdomain( $textdomain['domain'], WP_LANG_DIR . "/plugins/{$textdomain['domain']}-$new_locale.mo" );
120 }
121 }
122 }
123 }
124
125 // First remove taxonomies and post_types labels that we don't need to translate
126 $taxonomies = get_taxonomies( array( '_pll' => true ) );
127 $post_types = get_post_types( array( '_pll' => true ) );
128
129 // We don't need to translate core taxonomies and post types labels when setting the language from the url
130 // As they will be translated when registered the second time
131 if ( ! did_action( 'setup_theme' ) ) {
132 $taxonomies = array_merge( get_taxonomies( array( '_builtin' => true ) ), $taxonomies );
133 $post_types = array_merge( get_post_types( array( '_builtin' => true ) ), $post_types );
134 }
135
136 // Translate labels of post types and taxonomies
137 foreach ( array_diff_key( $GLOBALS['wp_taxonomies'], array_flip( $taxonomies ) ) as $tax ) {
138 $this->translate_labels( $tax );
139 }
140 foreach ( array_diff_key( $GLOBALS['wp_post_types'], array_flip( $post_types ) ) as $pt ) {
141 $this->translate_labels( $pt );
142 }
143
144 // Act only if the language has not been set early ( before default textdomain loading and $wp_locale creation )
145 if ( did_action( 'after_setup_theme' ) ) {
146 // Reinitializes wp_locale for weekdays and months
147 unset( $GLOBALS['wp_locale'] );
148 $GLOBALS['wp_locale'] = new WP_Locale();
149 }
150
151 /**
152 * Fires after the post types and taxonomies labels have been translated
153 * This allows plugins to translate text the same way we do for post types and taxonomies labels
154 *
155 * @since 1.2
156 *
157 * @param array $labels list of strings to trnaslate
158 */
159 do_action_ref_array( 'pll_translate_labels', array( &$this->labels ) );
160
161 // Free memory
162 unset( $this->default_locale, $this->list_textdomains, $this->labels );
163 }
164
165 /**
166 * Saves all text domains in a table for later usage.
167 * It replaces the 'override_load_textdomain' filter previously used.
168 *
169 * @since 2.0.4
170 *
171 * @param string $mofile The translation file name.
172 * @param string $domain The text domain name.
173 * @return string
174 */
175 public function load_textdomain_mofile( $mofile, $domain ) {
176 // On multisite, 2 files are sharing the same domain so we need to distinguish them.
177 if ( 'default' === $domain && false !== strpos( $mofile, '/ms-' ) ) {
178 $this->list_textdomains['ms-default'] = array( 'mo' => $mofile, 'domain' => $domain );
179 } else {
180 $this->list_textdomains[ $domain ] = array( 'mo' => $mofile, 'domain' => $domain );
181 }
182 return ''; // Hack to prevent WP loading text domains as we will load them all later.
183 }
184
185 /**
186 * Saves post types and taxonomies labels for a later usage
187 *
188 * @since 0.9
189 *
190 * @param string $translation not used
191 * @param string $text string to translate
192 * @param string $domain text domain
193 * @return string unmodified $translation
194 */
195 public function gettext( $translation, $text, $domain ) {
196 if ( is_string( $text ) ) { // Avoid a warning with some buggy plugins which pass an array
197 $this->labels[ $text ] = array( 'domain' => $domain );
198 }
199 return $translation;
200 }
201
202 /**
203 * Saves post types and taxonomies labels for a later usage
204 *
205 * @since 0.9
206 *
207 * @param string $translation not used
208 * @param string $text string to translate
209 * @param string $context some comment to describe the context of string to translate
210 * @param string $domain text domain
211 * @return string unmodified $translation
212 */
213 public function gettext_with_context( $translation, $text, $context, $domain ) {
214 $this->labels[ $text ] = array( 'domain' => $domain, 'context' => $context );
215 return $translation;
216 }
217
218 /**
219 * Translates post types and taxonomies labels once the language is known.
220 *
221 * @since 0.9
222 *
223 * @param WP_Post_Type|WP_Taxonomy $type Either a post type or a taxonomy.
224 * @return void
225 */
226 public function translate_labels( $type ) {
227 // Use static array to avoid translating several times the same ( default ) labels
228 static $translated = array();
229
230 foreach ( $type->labels as $key => $label ) {
231 if ( is_string( $label ) && isset( $this->labels[ $label ] ) ) {
232 if ( empty( $translated[ $label ] ) ) {
233 // PHPCS:disable WordPress.WP.I18n
234 $type->labels->$key = $translated[ $label ] = isset( $this->labels[ $label ]['context'] ) ?
235 _x( $label, $this->labels[ $label ]['context'], $this->labels[ $label ]['domain'] ) :
236 __( $label, $this->labels[ $label ]['domain'] );
237 // PHPCS:enable
238 }
239 else {
240 $type->labels->$key = $translated[ $label ];
241 }
242 }
243 }
244 }
245
246 /**
247 * Allows Polylang to be the first plugin loaded ;-).
248 *
249 * @since 1.2
250 *
251 * @param string[] $plugins List of active plugins.
252 * @return string[] List of active plugins.
253 */
254 public function make_polylang_first( $plugins ) {
255 if ( $key = array_search( POLYLANG_BASENAME, $plugins ) ) {
256 unset( $plugins[ $key ] );
257 array_unshift( $plugins, POLYLANG_BASENAME );
258 }
259 return $plugins;
260 }
261 }
262