wordpress插件加载顺序有时需要进行干预,因为有的函数会比较霸道,做了很多add_action会改变系统本身的一些变量,导致返回不正确,例如qTranslate会导致插件中获取语言包失败。分析wp-include/plugin.php的最后几行:
[php]
$ii=0;
do {
foreach( (array) current($wp_filter[$tag]) as $the_ )
if ( !is_null($the_['function']) ){
$args[1] = $value;
$value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
if ($tag=='locale') {echo $the_['function'].'>'.$the_['accepted_args'].'>';print_r($args);echo $value.'##'.($ii++).'##';}
}
} while ( next($wp_filter[$tag]) !== false );[/php]
发现在qTranslate加载前加载的插件也会被执行qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage这个函数导致$value返回空从而导致插件中调用语言包失败,例如:
[php]load_plugin_textdomain('wp-sirendingzhi', false, dirname( plugin_basename( __FILE__ )).'/languages/');[/php]
顺着上述代码,跟踪到wp-include/l10n.php的 function load_plugin_textdomain 中,在函数中的这一行:
[php]$locale = apply_filters( 'plugin_locale', $locale, $domain );[/php]
执行之后$locale本应返回zh_CN,却意外的返回了空值。调用的语言包名也变成了 wp-sirendingzhi-.mo,并非我们期望的wp-sirendingzhi-zh_CN.mo
解决方法,虽然我们能够修改wordpress代码,判断返回空的情况下给$locale赋值与WPLANG的值相同,但每次升级Wordpress之后还需要重写此函数,所以有效的解决办法是,在插件中控制插件加载顺序,让他比qTranslate晚加载,甚至在所有插件加载之后再加载,那么看看如下最后加载的实现方法,在加载语言包处改写如下:
[php]include dirname( __FILE__ ) . '/delayload.php';
function _wpsirendingzhi_init() {
load_plugin_textdomain('wp-sirendingzhi', false, dirname( plugin_basename( __FILE__ )).'/languages/');
}
delayload_init( '_wpsirendingzhi_init' );[/php]
以下为delayload.php内容
[php]< ?php
$GLOBALS['_delayload_data'] = array( 56, __FILE__, array( '', ) );
if ( !class_exists( 'delayload' ) ) :
class delayload {
private static $candidates = array();
private static $classes;
private static $callbacks = array();
private static $loaded;
static function init( $callback = '' ) {
list( $rev, $file, $classes ) = $GLOBALS['_delayload_data'];
self::$candidates[$file] = $rev;
self::$classes[$file] = $classes;
if ( !empty( $callback ) ) {
self::$callbacks[$file] = $callback;
add_action( 'activate_plugin', array( __CLASS__, 'delayed_activation' ) );
}
if ( did_action( 'plugins_loaded' ) )
self::load();
else
add_action( 'plugins_loaded', array( __CLASS__, 'load' ), 9, 0 );
}
static function delayed_activation( $plugin ) {
$plugin_dir = dirname( $plugin );
if ( '.' == $plugin_dir )
return;
foreach ( self::$callbacks as $file => $callback ) {
if ( dirname( dirname( plugin_basename( $file ) ) ) == $plugin_dir ) {
self::load( false );
call_user_func( $callback );
do_action( 'delayload_activation_' . $plugin );
break;
}
}
}
static function load( $do_callbacks = true ) {
arsort( self::$candidates );
$file = key( self::$candidates );
$path = dirname( $file ) . '/';
foreach ( self::$classes[$file] as $class_name ) {
if ( class_exists( $class_name ) )
continue;
$fpath = $path . substr( $class_name, 3 ) . '.php';
if ( file_exists( $fpath ) ) {
include $fpath;
self::$loaded[] = $fpath;
}
}
if ( $do_callbacks )
foreach ( self::$callbacks as $callback )
call_user_func( $callback );
}
}
endif;
if ( !function_exists( 'delayload_init' ) ) :
function delayload_init( $callback = '' ) {
delayload::init( $callback );
}
endif;[/php]
以上是通过代码解决问题,当然我们也可以特意做个取不到语言的语言包文件,例如本例中,特意复制1个语言包文件,改名为 wp-sirendingzhi-.mo 。这是最快的解决办法,只能解决有木有的问题,对developer来说,用代码才是解决问题的王道。