wenpai.org/wp-content/plugins/plat-wporg-translate-import/Command/Release.php
2024-11-14 02:29:46 +08:00

236 lines
8.7 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Platform\Translate\WPOrgTranslateImport\Command;
use Exception;
use GP;
use GP_Locales;
use Platform\Chinese_Format\Chinese_Format;
use Platform\Logger\Logger;
use WP_CLI;
use WP_CLI_Command;
use function Platform\Translate\WPOrgTranslateImport\get_web_page_contents;
class Release extends WP_CLI_Command {
public function __construct() {
parent::__construct();
try {
WP_CLI::add_command( 'platform translate_import_release', __NAMESPACE__ . '\Release' );
} catch ( Exception $e ) {
Logger::error( Logger::STORE, '注册 WP-CLI 命令失败', [ 'error' => $e->getMessage() ] );
}
}
public function release( $args, $assoc_args ): void {
if ( ! isset( $assoc_args['version'] ) ) {
WP_CLI::line( '你需要给出要抓取的版本号' );
exit;
}
$version = $assoc_args['version'];
// 对版本号进行一下处理。用户传入的是诸如 5.8.3 需要处理成 5.8.x
if ( $version !== 'dev' ) {
$tmp = explode( '.', $version );
$tmp[ count( $tmp ) - 1 ] = 'x';
$version = join( '.', $tmp );
}
$old_version = $assoc_args['old_version'] ?? '';
$display_version = $assoc_args['display_version'] ?? $version;
// 检查当前版本是否已存在
$sub_projects = array(
// 程序主体
'body' =>
array(
'name' => '主体',
'url' => sprintf( 'https://translate.wordpress.org/projects/wp/%s/zh-cn/default/export-translations/?filters[term]&filters[term_scope]=scope_any&filters[status]=current_or_waiting_or_fuzzy_or_untranslated&filters[user_login]&format=po', $version ),
),
// 大洲与城市
'cc' =>
array(
'name' => '大洲与城市',
'url' => sprintf( 'https://translate.wordpress.org/projects/wp/%s/cc/zh-cn/default/export-translations/?filters[term]&filters[term_scope]=scope_any&filters[status]=current_or_waiting_or_fuzzy_or_untranslated&filters[user_login]&format=po', $version ),
),
// 管理面板
'admin' =>
array(
'name' => '管理',
'url' => sprintf( 'https://translate.wordpress.org/projects/wp/%s/admin/zh-cn/default/export-translations/?filters[term]&filters[term_scope]=scope_any&filters[status]=current_or_waiting_or_fuzzy_or_untranslated&filters[user_login]&format=po', $version ),
),
// 多站点网络管理面板
'network' =>
array(
'name' => '网络管理',
'url' => sprintf( 'https://translate.wordpress.org/projects/wp/%s/admin/network/zh-cn/default/export-translations/?filters[term]&filters[term_scope]=scope_any&filters[status]=current_or_waiting_or_fuzzy_or_untranslated&filters[user_login]&format=po', $version ),
),
);
foreach ( $sub_projects as $slug => $project ) {
$this->worker( $version, $old_version, $slug, $project['name'], $project['url'], $display_version );
sleep( 5 ); // 不加延迟现在会直接触发 429 制裁
}
WP_CLI::line( '恭喜你,执行成功' );
}
/**
* @param string $version 当前版本,如果不存在的话会自动创建
* @param string $old_version 旧版本,用于合并翻译
* @param string $wporg_translate_url 要抓取的的 WordPress.org 上的翻译源(通常是到处翻译的链接)
*/
private function worker( string $version, string $old_version, string $sub_project_slug, string $sub_project_name, string $wporg_translate_url, $display_version ): void {
// 判断给定的父项目是否存在,不存在则新建
$father_project = GP::$project->find_one( array(
'path' => sprintf( 'core/%s', $display_version ),
) );
if ( ! $father_project ) {
$root_project = GP::$project->find_one( array(
'path' => 'core',
) );
$father_project_id = $this->create_project( $display_version, $display_version, sprintf( 'WordPress %s 分支的翻译', $display_version ), $root_project->id );
} else {
$father_project_id = $father_project->id;
}
// 获取到父项目后需要把版本号更新上
gp_update_meta( $father_project_id, 'version', $display_version, 'project' );
// 判断给定的子项目是否存在,不存在则新建
$sub_project = GP::$project->find_one( array(
'path' => sprintf( 'core/%s/%s', $display_version, $sub_project_slug ),
) );
if ( ! $sub_project ) {
$sub_project_id = $this->create_project( $sub_project_name, $sub_project_slug, '', $father_project_id, $display_version );
$sub_project = GP::$project->find_one( array(
'id' => $sub_project_id,
) );
}
// 从 WordPress.org 获取翻译
WP_CLI::line( 'URL: ' . $wporg_translate_url );
$data = get_web_page_contents( $wporg_translate_url );
if ( is_wp_error( $data ) ) {
WP_CLI::line( '翻译文件下载失败,错误:' . $data->get_error_message() . ',子项目:' . $sub_project_name );
exit;
}
$temp_file = tempnam( sys_get_temp_dir(), 'Platform' );
if ( ! file_put_contents( $temp_file, $data ) ) {
unlink( $temp_file );
WP_CLI::line( "翻译文件下载后保存失败,可能是权限问题,子项目:{$sub_project_name},临时文件目录:{$temp_file}" );
exit;
}
// 导入原文
$format = gp_get_import_file_format( 'po', '' );
$originals = $format->read_originals_from_file( $temp_file, $sub_project );
if ( ! $originals ) {
unlink( $temp_file );
WP_CLI::line( "无法从翻译文件加载原文,子项目:{$sub_project_name},翻译文件:{$temp_file}" );
exit;
}
GP::$original->import_for_project( $sub_project, $originals );
// 导入翻译
// 正式导入前看看是否需要先导入旧版项目的翻译
$translation_set = GP::$translation_set->find_one( array( 'project_id' => $sub_project->id ) );
if ( ! empty( $old_version ) ) {
$old_sub_project = GP::$project->find_one( array(
'path' => sprintf( 'core/%s/%s', $old_version, $sub_project_slug ),
) );
if ( ! $old_sub_project ) {
WP_CLI::line( "你所指定的旧版翻译的项目不存在错误项目core/$old_version/$sub_project_slug" );
exit;
}
$old_translation_set = GP::$translation_set->find_one( array( 'project_id' => $old_sub_project->id ) );
$old_po = $format->print_exported_file( $old_sub_project, GP_Locales::by_slug( $old_translation_set->locale ), $old_translation_set, GP::$translation->for_export( $old_sub_project, $old_translation_set, array( 'status' => 'current' ) ) );
$old_po_file = tempnam( sys_get_temp_dir(), 'Platform' );
file_put_contents( $old_po_file, $old_po );
$translations = $format->read_translations_from_file( $old_po_file, $sub_project );
if ( ! $translations ) {
unlink( $temp_file );
unlink( $old_po_file );
WP_CLI::line( "无法从翻译文件加载翻译,该翻译文件从 {core/$old_version/$sub_project_slug} 项目中导出,翻译文件位于: {$old_po_file}" );
exit;
}
wp_set_current_user( BOT_USER_ID );
$translation_set->import( $translations );
unlink( $old_po_file );
}
// 然后导入新的翻译
$translations = $format->read_translations_from_file( $temp_file, $sub_project );
if ( ! $translations ) {
unlink( $temp_file );
WP_CLI::line( "无法从翻译文件加载翻译,翻译文件位于: {$temp_file}" );
exit;
}
// 导入前先循环格式化一下,纠正错误的格式
/*$format = Chinese_Format::get_instance();
foreach ( $translations->entries as $translation ) {
foreach ( $translation->translations as $key => $value ) {
$translation->translations[ $key ] = $format->convert( $value );
}
}*/
wp_set_current_user( BOT_USER_ID );
add_filter( 'gp_translation_set_import_status', function ( $status, $entry, $translated ) {
return 'current';
}, 10, 3 );
$translation_set->import( $translations, 'current' );
unlink( $temp_file );
}
private function create_project( string $name, string $slug, string $description, int $parent_project_id = 0, string $parent_project_slug = '' ): int {
global $wpdb;
$parent_project_slug = empty( $parent_project_slug ) ? '' : $parent_project_slug . '/';
$res = $wpdb->insert( 'wp_' . SITE_ID_TRANSLATE . '_gp_projects', array(
'name' => $name,
'slug' => $slug,
'path' => sprintf( 'core/%s%s', $parent_project_slug, $slug ),
'description' => $description,
'source_url_template' => '',
'parent_project_id' => $parent_project_id,
'active' => 1
) );
$project_id = $wpdb->insert_id;
$root_project = GP::$project->find_one( array(
'path' => 'core',
) );
if ( 0 !== (int) $res && $parent_project_id != $root_project->id ) {
$wpdb->insert( 'wp_' . SITE_ID_TRANSLATE . '_gp_translation_sets', array(
'name' => '简体中文',
'slug' => 'default',
'project_id' => $project_id,
'locale' => 'zh-cn'
) );
}
return $project_id;
}
}