解析 WordPress `wp_get_installed_languages()` 函数的源码:如何获取所有已安装的语言。

各位同学,晚上好!欢迎来到今天的“WordPress源码解剖”小课堂。今天我们要一起扒一扒WordPress里面一个看似简单,实则暗藏玄机的函数:wp_get_installed_languages()。这个函数的作用,顾名思义,就是获取所有已经安装的语言。

但是,它到底是怎么找到这些语言的?里面有什么坑需要注意?今天我们就来一探究竟。

1. 先来热个身:wp-config.php 中的 WPLANG

在深入源码之前,我们先来复习一下WordPress的语言设置。最基础的,就是在wp-config.php文件中定义WPLANG常量。

define( 'WPLANG', 'zh_CN' ); // 设置语言为简体中文

这个常量告诉WordPress,网站要使用哪个语言包。如果WPLANG为空,WordPress会默认使用英语(en_US)。

2. wp_get_installed_languages() 函数登场:源码解析

好了,现在我们正式进入主题。wp_get_installed_languages()函数定义在wp-includes/l10n.php文件中。让我们一起来看看它的源码:

/**
 * Retrieves a list of available languages.
 *
 * @since 4.0.0
 *
 * @return string[] Array of language codes.
 */
function wp_get_installed_languages() {
    $languages = get_available_languages();

    /**
     * Filters the array of installed languages.
     *
     * @since 4.0.0
     *
     * @param string[] $languages Array of language codes.
     */
    return apply_filters( 'wp_get_installed_languages', $languages );
}

是不是感觉有点短?别急,好戏还在后头。wp_get_installed_languages()函数其实就是一个“包装工”,它把获取语言列表的任务委托给了get_available_languages()函数,然后通过apply_filters()提供了一个钩子,允许我们修改最终的语言列表。

3. get_available_languages() 函数:幕后英雄

接下来,我们来看get_available_languages()函数,这才是真正干活的家伙。

/**
 * Retrieves a list of available languages.
 *
 * Searches the wp-content directory for available translations.
 *
 * @since 3.0.0
 *
 * @global WP_Locale $wp_locale
 *
 * @return string[] Array of language codes.
 */
function get_available_languages() {
    global $wp_locale;

    $languages = array();

    $lang_files = glob( WP_LANG_DIR . '/*.mo' );
    if ( ! empty( $lang_files ) ) {
        foreach ( $lang_files as $lang_file ) {
            if ( preg_match( '//([a-z]{2,3}(?:_[A-Z]{2})?)(?:-[^\/]+)?.mo$/', $lang_file, $match ) ) {
                if ( ! in_array( $match[1], $languages, true ) ) {
                    $languages[] = $match[1];
                }
            }
        }
    }

    if ( isset( $wp_locale->installed ) ) {
        return $wp_locale->installed;
    }

    return $languages;
}

让我们一行一行地解读:

  • global $wp_locale;: 声明全局变量$wp_locale。这个变量存储了当前站点的语言环境信息。
  • $languages = array();: 初始化一个空数组,用于存储找到的语言代码。
  • *`$lang_files = glob( WP_LANG_DIR . ‘/.mo’ );**: 使用glob()函数查找WP_LANG_DIR目录下的所有.mo文件。WP_LANG_DIR通常指向wp-content/languages目录。.mo`文件是经过编译的语言包。

    • glob()函数科普: glob()函数是一个强大的文件路径匹配工具。它接受一个模式字符串作为参数,并返回所有匹配的文件路径组成的数组。例如,glob("/path/to/directory/*.txt")会返回/path/to/directory目录下所有.txt文件的路径。
  • if ( ! empty( $lang_files ) ) { ... }: 判断是否找到了.mo文件。如果找到了,就进入循环。
  • foreach ( $lang_files as $lang_file ) { ... }: 遍历所有找到的.mo文件。
  • if ( preg_match( '//([a-z]{2,3}(?:_[A-Z]{2})?)(?:-[^\/]+)?.mo$/', $lang_file, $match ) ) { ... }: 使用正则表达式从.mo文件名中提取语言代码。

    • 正则表达式解析: 这个正则表达式有点复杂,我们来拆解一下:
      • /: 匹配斜杠,用于分隔目录。
      • ([a-z]{2,3}(?:_[A-Z]{2})?): 这是我们要提取的关键部分,用括号括起来表示一个捕获组。它匹配语言代码,语言代码的格式通常是xxxx_YY,其中xx是小写的语言代码(2-3个字符),YY是大写的国家代码(2个字符)。(?: ... )表示一个非捕获组,也就是说,它匹配的内容不会被保存到$match数组中。
      • (?:-[^\/]+)?: 匹配可选的后缀,例如-formal-informal[^\/]+表示匹配除了斜杠之外的任意字符,至少一个。
      • .mo$: 匹配.mo文件扩展名,$表示字符串结尾。
    • $match数组: 如果正则表达式匹配成功,$match数组会包含以下内容:
      • $match[0]: 完整的匹配字符串(例如:/zh_CN.mo)。
      • $match[1]: 第一个捕获组的内容,也就是我们需要的语言代码(例如:zh_CN)。
  • if ( ! in_array( $match[1], $languages, true ) ) { ... }: 检查提取的语言代码是否已经存在于$languages数组中。如果不存在,就将其添加到数组中。true参数表示使用严格比较(类型和值都要相等)。
  • if ( isset( $wp_locale->installed ) ) { ... }: 检查$wp_locale->installed是否设置。如果设置了,就返回$wp_locale->installed

    • $wp_locale->installed的来源: $wp_locale->installed通常是由插件或主题设置的,用于覆盖默认的语言列表。这提供了一种灵活的方式来管理已安装的语言。
  • return $languages;: 如果$wp_locale->installed没有设置,就返回从.mo文件中提取的语言列表。

4. 流程总结:wp_get_installed_languages() 的工作方式

用一张表格来总结一下wp_get_installed_languages()的工作流程:

步骤 函数 描述
1 wp_get_installed_languages() 作为入口函数,调用get_available_languages()获取语言列表。
2 get_available_languages() 扫描WP_LANG_DIR目录下的.mo文件,提取语言代码。
3 get_available_languages() 检查$wp_locale->installed是否设置,如果设置了,则返回该值。
4 wp_get_installed_languages() 应用wp_get_installed_languages过滤器,允许修改语言列表。
5 wp_get_installed_languages() 返回最终的语言列表。

5. 潜在的坑:需要注意的地方

  • WP_LANG_DIR 的定义: 确保WP_LANG_DIR常量定义正确,指向正确的语言包目录。如果定义错误,get_available_languages()将无法找到.mo文件。
  • .mo 文件命名规范: .mo文件的命名必须符合规范,才能被正则表达式正确匹配。例如,zh_CN.mofr_FR.mo都是合法的命名,而chinese.mo则不合法。
  • $wp_locale->installed 的优先级: 如果$wp_locale->installed被设置,它会覆盖从.mo文件中提取的语言列表。因此,如果发现wp_get_installed_languages()返回的语言列表不正确,需要检查是否有插件或主题修改了$wp_locale->installed
  • 缓存问题: WordPress有各种缓存机制,有时候语言文件的更改可能不会立即反映在wp_get_installed_languages()的输出中。尝试清除缓存来解决这个问题。

6. 实战演练:如何使用 wp_get_installed_languages()

<?php
$languages = wp_get_installed_languages();

if ( ! empty( $languages ) ) {
    echo '已安装的语言:';
    echo '<ul>';
    foreach ( $languages as $language ) {
        echo '<li>' . esc_html( $language ) . '</li>';
    }
    echo '</ul>';
} else {
    echo '没有找到已安装的语言。';
}
?>

这段代码会输出一个包含所有已安装语言代码的无序列表。esc_html()函数用于转义HTML实体,防止XSS攻击。

7. 高级技巧:使用 wp_get_installed_languages 过滤器

wp_get_installed_languages过滤器允许我们修改wp_get_installed_languages()返回的语言列表。例如,我们可以添加或删除某些语言,或者根据自定义逻辑对语言列表进行排序。

<?php
/**
 * 添加一个自定义语言到已安装的语言列表中。
 *
 * @param string[] $languages 已安装的语言列表。
 * @return string[] 修改后的语言列表。
 */
function my_custom_add_language( $languages ) {
    if ( ! in_array( 'my_custom_language', $languages, true ) ) {
        $languages[] = 'my_custom_language';
    }
    return $languages;
}
add_filter( 'wp_get_installed_languages', 'my_custom_add_language' );
?>

这段代码会向wp_get_installed_languages()返回的语言列表中添加一个名为my_custom_language的自定义语言。

8. 总结:wp_get_installed_languages() 的价值

wp_get_installed_languages()函数虽然简单,但它却是WordPress国际化和本地化(i18n/l10n)的重要组成部分。它为插件和主题开发者提供了一种可靠的方式来获取已安装的语言列表,从而可以根据用户的语言环境来提供个性化的体验。

理解wp_get_installed_languages()的工作原理,可以帮助我们更好地理解WordPress的语言处理机制,并能更有效地开发多语言网站和插件。

好了,今天的“WordPress源码解剖”小课堂就到这里。希望大家通过今天的学习,对wp_get_installed_languages()函数有了更深入的了解。记住,源码的世界充满了乐趣,只要你有好奇心,敢于探索,就能发现更多精彩的内容!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注