loca1h0st's Blog
loca1h0st's Blog

跟着AI学二次开发,绕过99欧的功能限制

跟着AI学二次开发,绕过99欧的功能限制

在之前的文章中我们已经介绍了如何使用polylang对网站启用多语言支持的功能,并描述了使用n8n对文章自动化的进行多语言翻译:

完成后经过一段时间的试用,插件相对完美的达到了我要的需求,但我也发现有一个非常影响使用的点:Polylang插件的免费版本不支持API使用,这严重影响了使用体验,例如以下的几个场景无法自动化的完成:

  • 无法获取文章的语言状态,导致webhook自动化完成翻译后,会对已经是英文的文章再翻译一遍创建新文章,从而进入死循环
  • 无法自动化关联多语言文章之间的关系,这导致站点的中文和英文文章之间没有关联,无法自动切换内页文章语言

考虑到API是我的强需求,且Polylang的Pro版本相对于我的需求而言性价比并不太高(在1个站点的情况下,需要99欧),于是考虑自行添加相关的功能。

了解插件

对于PHP和Wordpress我相对还比较熟悉,但是我不太希望通过阅读一个非常复杂的代码进行定制化开发,于是我想到了利用AI的辅助:我提供思路,由AI帮助我完成这个需求,以下是相关的记录:

数据库交互

我首先想到,插件一定会在数据库中保存相关的信息,这些信息关系到了文章是什么语言类型,之间的映射关系如何:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-27-1024x496.png

基于答案,搜索Polylang插件的相关代码,最终找到pll_save_post函数,贴入相关的代码:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-28-1024x422.png

发现gpt-4o是认识这个插件的,并准确的提示了相关函数的作用,从而我直接问数据保存的结果:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-29-1024x559.png

得到答案后,在服务端进行验证,找到关键词post_translations,序列化后保存了多语言文章之间的相关的映射关系:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-30-1024x244.png

找到关键函数

基于gpt-4o给出的提示:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-31-1024x322.png

在源代码中对相关关键词进行搜索,找到字段名在程序中的变量名:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-32-1024x529.png

了解到变量名后,找对应的调用方法,经过测试,save_translation从名字和功能上比较贴近相关的实用场景:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-33-1024x736.png

找到函数后,寻找看是否有上层函数的传入和调用,最终在api.php文件中找到一个调用,函数名pll_save_post_translations适合我们的需求,且经过验证确实可用:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-34-1024x707.png

调用函数

找到函数并验证后,接下来就是使用这个函数。考虑到polylang插件未来是有可能升级的,我们尽可能不要对原插件进行编辑,于是我将如下的代码添加到了我的主题的funtions.php文件的末尾,从而实现我需要添加的功能。

以下代码中值得一提的关键函数是add_actionadd_filter,这是Wordpress的内置函数,从而使得我们可以对REST的API进行编辑,包括增加端点或对request/response进行数据截获和编辑(编写的时候如果你不会,同样的也可以寻求AI的帮助)。

//基于polylang添加自定义的API
add_action('rest_api_init', 'register_get_language');
function register_get_language() {
    register_rest_route('pl', '/language', array(
        'methods' => 'GET',
        'callback' => 'get_language_by_post_id',
        'args' => array(
            'id' => array(
                'required' => true,
                'validate_callback' => function($param, $request, $key) {
                    return is_numeric($param);
                }
            ),
        ),
        'permission_callback' => '__return_true'
    ));
}
function get_language_by_post_id($request) {
    // 获取请求中的参数 id
    $post_id = $request->get_param('id');

    // 检查 id 是否有效
    if (empty($post_id) || !is_numeric($post_id)) {
        return new WP_REST_Response(array(
            'success' => false,
            'message' => 'Invalid post ID.',
        ), 400); // 返回 400 错误
    }

    // 检查 Polylang 函数是否可用
    if (!function_exists('pll_get_post_translations')) {
        return new WP_REST_Response(array(
            'success' => false,
            'message' => 'Polylang plugin is not active or not installed.',
        ), 500); // 返回 500 错误
    }

    // 获取指定帖子的语言信息
    $languages = pll_get_post_translations($post_id);

    // 如果未找到语言信息
    if (empty($languages)) {
        return new WP_REST_Response(array(
            'success' => false,
            'message' => 'No language information found for the given post ID.',
        ), 404); // 返回 404 错误
    }

    // 返回语言信息
    return new WP_REST_Response(array(
        'success' => true,
        'language'    => $languages,
    ), 200); // 返回 200 成功
}

// 设置语言

add_filter('rest_pre_echo_response', 'save_post_translations', 10, 3);
function save_post_translations($response, $server, $request) {
    // 检查是否为 /wp/v2/posts 的请求
    if ($request->get_route() === '/wp/v2/posts') {
        $from_id = $request->get_param('from_id');
        if ($from_id){
            // 检查 Polylang 函数是否可用
            if (!function_exists('pll_save_post_translations')) {
                return new WP_REST_Response(array(
                    'success' => false,
                    'message' => 'Polylang plugin is not active or not installed.',
                ), 500); // 返回 500 错误
            }
            // 检查提交的post语言格式
            $languages = pll_get_post_language($response['id']);
            pll_save_post_translations(array(
                'zh' => $from_id,
                $languages => $response['id']
            ));
        }
    }
    return $response;
}

结果

最终我们在如上的代码中添加了两个API端点,来支持我们的功能,分别是/wp-json/pl/language?id={id}/wp-json/wp/v2/posts?from_id={id}

获取文章语言列表 /wp-json/pl/language?id={id}

当传入文章的ID时,服务端会返回这个ID关联的多语言的文章ID列表,从而可以用来判断是否需要进行翻译:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-35-939x1024.png

当文章的多语言都已经配置好时,不再进行下一步动作:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-38-1024x456.png

创建文章,并关联语言关系 /wp-json/wp/v2/posts?from_id={id}

当使用API创建文章时,带上原文ID,则自动绑定两者之间的语言关系:

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-36-903x1024.png

完整的工作流

https://blog.mrtblogs.net/wp-content/uploads/2024/12/image-37-1024x309.png

发表回复

textsms
account_circle
email

loca1h0st's Blog

跟着AI学二次开发,绕过99欧的功能限制
在之前的文章中我们已经介绍了如何使用polylang对网站启用多语言支持的功能,并描述了使用n8n对文章自动化的进行多语言翻译: https://blog.mrtblogs.net/auto-translate-article-by-…
扫描二维码继续阅读
2024-12-22