PluginProbe
Polylang / 3.4
Polylang v3.4
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.4, at include/olt-manager.php

264 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|null
20 */
21 protected static $instance;
22
23 /**
24 * Stores the default site locale before it is modified.
25 *
26 * @var string|null
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 PLL_OLT_Manager
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' ) );
97 remove_filter( 'gettext', array( $this, 'gettext' ) );
98 remove_filter( 'gettext_with_context', array( $this, 'gettext_with_context' ) );
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 $this->default_locale = null;
163 $this->list_textdomains = array();
164 $this->labels = array();
165 }
166
167 /**
168 * Saves all text domains in a table for later usage.
169 * It replaces the 'override_load_textdomain' filter previously used.
170 *
171 * @since 2.0.4
172 *
173 * @param string $mofile The translation file name.
174 * @param string $domain The text domain name.
175 * @return string
176 */
177 public function load_textdomain_mofile( $mofile, $domain ) {
178 // On multisite, 2 files are sharing the same domain so we need to distinguish them.
179 if ( 'default' === $domain && false !== strpos( $mofile, '/ms-' ) ) {
180 $this->list_textdomains['ms-default'] = array( 'mo' => $mofile, 'domain' => $domain );
181 } else {
182 $this->list_textdomains[ $domain ] = array( 'mo' => $mofile, 'domain' => $domain );
183 }
184 return ''; // Hack to prevent WP loading text domains as we will load them all later.
185 }
186
187 /**
188 * Saves post types and taxonomies labels for a later usage
189 *
190 * @since 0.9
191 *
192 * @param string $translation not used
193 * @param string $text string to translate
194 * @param string $domain text domain
195 * @return string unmodified $translation
196 */
197 public function gettext( $translation, $text, $domain ) {
198 if ( is_string( $text ) ) { // Avoid a warning with some buggy plugins which pass an array
199 $this->labels[ $text ] = array( 'domain' => $domain );
200 }
201 return $translation;
202 }
203
204 /**
205 * Saves post types and taxonomies labels for a later usage
206 *
207 * @since 0.9
208 *
209 * @param string $translation not used
210 * @param string $text string to translate
211 * @param string $context some comment to describe the context of string to translate
212 * @param string $domain text domain
213 * @return string unmodified $translation
214 */
215 public function gettext_with_context( $translation, $text, $context, $domain ) {
216 $this->labels[ $text ] = array( 'domain' => $domain, 'context' => $context );
217 return $translation;
218 }
219
220 /**
221 * Translates post types and taxonomies labels once the language is known.
222 *
223 * @since 0.9
224 *
225 * @param WP_Post_Type|WP_Taxonomy $type Either a post type or a taxonomy.
226 * @return void
227 */
228 public function translate_labels( $type ) {
229 // Use static array to avoid translating several times the same ( default ) labels
230 static $translated = array();
231
232 foreach ( (array) $type->labels as $key => $label ) {
233 if ( is_string( $label ) && isset( $this->labels[ $label ] ) ) {
234 if ( empty( $translated[ $label ] ) ) {
235 // PHPCS:disable WordPress.WP.I18n
236 $type->labels->$key = $translated[ $label ] = isset( $this->labels[ $label ]['context'] ) ?
237 _x( $label, $this->labels[ $label ]['context'], $this->labels[ $label ]['domain'] ) :
238 __( $label, $this->labels[ $label ]['domain'] );
239 // PHPCS:enable
240 }
241 else {
242 $type->labels->$key = $translated[ $label ];
243 }
244 }
245 }
246 }
247
248 /**
249 * Allows Polylang to be the first plugin loaded ;-).
250 *
251 * @since 1.2
252 *
253 * @param string[] $plugins List of active plugins.
254 * @return string[] List of active plugins.
255 */
256 public function make_polylang_first( $plugins ) {
257 if ( $key = array_search( POLYLANG_BASENAME, $plugins ) ) {
258 unset( $plugins[ $key ] );
259 array_unshift( $plugins, POLYLANG_BASENAME );
260 }
261 return $plugins;
262 }
263 }
264