WP DEVELOP

EP162. “JavaScript 多语言翻译:wp.i18n 与 wp_set_script_translations”

首页 WordPress 开发课程 新 BLOCK 类型练习 · EP162
约 15 分钟· #EP162#新 BLOCK 类型练习
🔒 登录后可标记已读

之前的课程已经学过怎么让 PHP 输出的文字支持多语言翻译(用 Loco Translate 插件),这一讲学怎么让 JavaScript(编辑器里下拉框的「Select a professor」占位文字)也支持翻译。即使文字是由 JS 渲染出来的,起点依然要从 PHP 开始:先在插件头部声明 Text Domain/Domain Path,用 load_plugin_textdomain() 告诉 WordPress 这个插件支持翻译;JS 那边用 WordPress 全局提供的 wp.i18n.__() 函数包住要翻译的文字;最后还要额外调用一个专属的 wp_set_script_translations(),把「这个已注册的脚本」和「翻译文件所在目录」关联起来——只做前两步、漏掉这一步,Loco Translate 界面能扫描到待翻译文字、也能保存翻译,但编辑器里实际不会生效。这是这门课 JavaScript 章节(插件开发 Chapter 2)的最后一讲。


涉及文件

  • wp-content/plugins/featured-professor/featured-professor.php (修改)
  • wp-content/plugins/featured-professor/src/index.js (修改)
  • wp-content/plugins/featured-professor/languages/ (新建空文件夹,Loco Translate 生成的翻译文件存放处)

代码实现

featured-professor.php:插件头部声明 Text Domain/Domain PathonInit() 里注册翻译

<?php

/*
  Plugin Name: Featured Professor Block Type
  Version: 1.0
  Author: Your Name Here
  Author URI: https://www.udemy.com/user/bradschiff/
  Text Domain: featured-professor
  Domain Path: /languages
*/

// ...

function onInit() {
  load_plugin_textdomain('featured-professor', false, dirname(plugin_basename(__FILE__)) . '/languages');

  register_meta('post', 'featuredprofessor', array(
    'show_in_rest' => true,
    'type' => 'number',
    'single' => false
  ));

  wp_register_script('featuredProfessorScript', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-i18n', 'wp-editor'));
  wp_register_style('featuredProfessorStyle', plugin_dir_url(__FILE__) . 'build/index.css');

  wp_set_script_translations('featuredProfessorScript', 'featured-professor', plugin_dir_path(__FILE__) . '/languages');

  register_block_type('ourplugin/featured-professor', array(
    'render_callback' => [$this, 'renderCallback'],
    'editor_script' => 'featuredProfessorScript',
    'editor_style' => 'featuredProfessorStyle'
  ));
}

src/index.js:从全局 wp.i18n__ 函数,包住要翻译的文字

import "./index.scss"
import {useSelect} from "@wordpress/data"
import {useState, useEffect} from "react"
import apiFetch from "@wordpress/api-fetch"
const __ = wp.i18n.__

// ...registerBlockType / EditComponent 其余部分不变...

<option value="">{__("Select a professor", "featured-professor")}</option>

关键改动点:

  • Text Domain / Domain Path(插件头部注释)Text Domain 是这个插件在翻译系统里的唯一标识名(这里是 featured-professor),Domain Path 指定翻译文件相对插件根目录存放在哪个子文件夹(这里是 /languages,对应新建的空 languages/ 文件夹)
  • load_plugin_textdomain('featured-professor', false, dirname(plugin_basename(__FILE__)) . '/languages'):告诉 WordPress「这个插件支持翻译,语言文件在这个路径」——第二个参数固定传 false(官方文档本身也没有讲清楚这个参数具体含义,作者的做法是就用 false);第三个参数用 dirname(plugin_basename(__FILE__)) 拼出「当前插件所在目录」再接上 /languages
  • JS 端用 wp.i18n.__ 而不是 import 语法const __ = wp.i18n.__——直接从浏览器全局 wp.i18n 对象上取,而不是写 import {__} from '@wordpress/i18n'。作者提到这是因为实测 Loco Translate 插件在扫描/关联翻译时,需要这样直接从全局取值才能正常工作,用 import 语法有兼容性问题
  • __("Select a professor", "featured-professor")__() 是标准的翻译包装函数,第一个参数是原始文字(默认语言下显示的内容),第二个参数是这个插件的 Text Domain——两者搭配,Loco Translate 才能把这段文字正确归类到这个插件底下去管理翻译。这个函数不是只能在 JSX 的 {} 里用,在普通 JS 代码里任何位置都可以调用
  • Loco Translate 后台操作步骤(不是代码,是管理界面操作):
    1. Loco Translate 设置里的「Scan JavaScript files with extensions」这个选项默认是空的,必须手动填入 js,Loco Translate 才会去扫描 .js 文件里的可翻译文字(不只是 PHP)
    2. 进到这个插件的翻译管理页,先点「Create Template」——生成一份「有哪些待翻译文字」的模板,此时能看到扫描到几个文件、最大的文件多大(用文件大小能大致确认扫描到的是不是自己的 JS 文件)
    3. 点「New language」新增一个语言(比如 Spanish (Mexico)),选择把翻译文件存到插件自己的 languages/ 文件夹里
    4. 逐条填写翻译文字、保存
  • wp_set_script_translations($脚本handle, $text_domain, $翻译文件目录) 是容易被漏掉的关键一步——只做好 PHP 头部声明 + load_plugin_textdomain() + JS 里用 __() 包住文字,这时候去 Loco Translate 后台其实已经能正常扫描、保存翻译;但如果就此打住,编辑器实际界面上依然不会显示翻译后的文字。必须额外调用这个函数,把「已经用 wp_register_script() 注册过的这个脚本」正式和「翻译文件所在目录」关联起来,翻译才会真正在浏览器端生效:
    • 第一个参数是脚本的 handle 名(跟 wp_register_script() 用的名字一致,这里是 featuredProfessorScript
    • 第二个参数是 Text Domain
    • 第三个参数是翻译文件所在的目录路径

Hook / Function 速查

名称类型用途
Text Domain / Domain Path(插件头部注释)WP 插件元信息声明插件的翻译标识名和翻译文件存放路径
load_plugin_textdomain($domain, false, $路径)WP 内建 function告知 WordPress 该插件支持翻译及语言文件位置
wp.i18n.__(原文, $text_domain)WordPress 全局 JS 工具JS 端的翻译包装函数,效果等同于 PHP 的 __()
wp_set_script_translations($脚本handle, $text_domain, $路径)WP 内建 function把已注册的脚本跟翻译文件目录关联起来,翻译才会真正在前端生效

常见坑

  • JS 里用 import {__} from '@wordpress/i18n' 而不是从全局 wp.i18n.__ 取——作者提到这样写会跟 Loco Translate 插件配合有问题,翻译扫描/关联不能正常工作
  • 只做了 PHP 头部声明 + load_plugin_textdomain() + JS 里的 __() 包装,漏掉 wp_set_script_translations() 这一步——Loco Translate 后台能扫描、能保存翻译,但编辑器界面实际不会显示翻译后的文字
  • Loco Translate 设置里没有把「Scan JavaScript files with extensions」填成 js——扫描时完全不会去看 .js 文件,Loco Translate 会以为这个插件没有需要翻译的 JS 内容
  • __() 第二个参数(Text Domain)跟插件头部声明的名字对不上——翻译系统没法把这段文字正确关联到对应插件,翻译不生效

[截图:Loco Translate 翻译管理页面,显示已扫描到 JS 文件里的"Select a professor"待翻译字符串]


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 26, EP162