目录
3.4 连接本地`scratch-gui`和本地`scratch-blocks`
准备环节
建议先阅读本专栏中的前序文章,有些步骤在本文中不会讲的很详细。
在之前的文章中已经详细介绍过了,比如打开终端。
1、使用IDE打开源码所在文件夹

2、在本地服务器中运行ScratchGUI
使用终端在`scratch-gui-develop`文件夹下执行`npm start`命令。
npm start



成功启动:

在浏览器中访问服务器地址:

3、安装并编译`scratch-blocks`
我们之前把`scratch-blocks`源码解压到本地后并没有对他进行任何操作,此时的`scratch-gui`使用的是从Scratch官网下载的`scratch-blocks`,并没有使用我们本地的源码。
3.1 安装本地`scratch-blocks`的依赖项
打开终端管理员:

移到`scratch-blocks`模块本地源码的文件夹:

Tips:可以在IDE中文件夹右键复制(绝对)路径。
执行`npm install`或`npm ci`:
npm ci
不出意外的话,你要出意外了~
由于官方源码的开发环境是在Linux下的,所以很多源码的工具Windows系统不适用。
我们在【Scratch二次开发#2——自定义菜单栏】中编译`scratch-l10n`时也有遇到类似问题。
主要报错信息:



我们一个一个解决。
问题分析
1. 主要错误 :"命令行太长" - Windows操作系统有命令行长度限制(通常约8191个字符),当文件数量或路径过长时会超出这个限制
2. 部分构建成功 :尽管有错误,部分文件如 blockly_uncompressed_vertical.js 仍然成功生成
3. JSDoc警告 :存在一个非关键警告,关于 blocks_vertical/vertical_extensions.js 中的函数注释位置,但这不影响构建结果
“命令行太长”问题:
在`scratch-blocks-develop\build.py`文件中查找`do_compile_local`,找到函数定义。

修改为以下内容:
def do_compile_local(self, params, target_filename):
filter_keys = ["use_closure_library"]
# 分离JS文件参数和其他参数
js_files = []
other_params = []
for (arg, value) in params:
if arg == "js_file":
js_files.append(value)
elif arg not in filter_keys:
other_params.extend(["--" + arg, value])
# 使用@file参数方式解决Windows命令行长度限制
# 创建临时参数文件
temp_file_name = "closure_params_%s.txt" % target_filename.replace('.js', '')
with open(temp_file_name, 'w') as temp_file:
# 写入所有JS文件路径,每个一行
for js_file in js_files:
temp_file.write(js_file + '\n')
# 构建命令行参数,使用@文件引用
args = [CLOSURE_COMPILER_NPM]
args.extend(other_params)
# 添加@参数文件引用
args.append("@" + temp_file_name)
proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
# 尝试删除临时文件(忽略错误)
try:
os.remove(temp_file_name)
except:
pass
# 如果有错误输出,打印出来
if stderr:
print("COMPILER STDERR:", stderr.decode('utf-8', errors='ignore'))
# Build the JSON response.
filesizes = [os.path.getsize(value) for (arg, value) in params if arg == "js_file"]
return dict(
compiledCode=stdout,
statistics=dict(
originalSize=functools.reduce(lambda v, size: v + size, filesizes, 0),
compressedSize=len(stdout),
)
)
可以直接选中整个函数然后粘贴:
Tips:Ctrl加上正负号可以放大缩小IDE界面。


修改说明
1. 使用文件列表文件 :创建临时文件存储所有JS文件路径,然后通过 @filename 参数传递给编译器,避免直接在命令行中列出大量文件
2. 增强错误输出 :捕获并显示编译器的标准错误输出,方便调试
3. 清理临时文件 :编译完成后自动删除临时文件
重新执行`npm install`或`npm ci`:
Tips:在终端中按“↑”、“↓”键可以查看历史命令。


“命令行太长”的错误已经没了,并且这次的输出信息非常多。
剩下的错误JSDoc警告 是一个非关键警告,关于 blocks_vertical/vertical_extensions.js 中的函数注释位置,但这不影响构建结果
3.2 编译本地`scratch-blocks`
`npm ci`或`npm install`执行后`scratch-blocks`的文件都完整了,接下来需要编译。
执行`npm run build`
不出意外的话,_ _ _ _ _ _ _~

它居然说没有这个命令,`scratch-l10n`都能用,为什么这里不能用呢?
答案就在`package.json`这个文件中。
分别打开`scratch-l10n`和scratch-blocks`的`package.json`对比一下:
- `scratch-blocks-develop\package.json`
- `scratch-l10n-master\package.json`
右键其中一个代码标签页,向右拆分方便对比:

找到两个文件中的`scripts`部分:

`scratch-l10n`是有build命令的,而`scratch-blocks`是没有的,唯一相关的命令是`prepublish`。
在 npm 脚本中,"prepublish": "python build.py && webpack" 表示一个预发布钩子脚本,其作用是:
当执行 npm publish 命令发布包时,会自动先执行该 prepublish 定义的命令:
首先运行 python build.py,通过 Python 脚本(build.py)完成一些构建准备工作(如处理资源、生成文件等)
若第一步成功(&& 表示前序命令成功才继续),则执行 webpack 进行前端资源的打包处理
这是 npm 的生命周期钩子机制,用于在发布前自动完成必要的构建流程,确保发布的内容是经过处理的最终版本。
很麻烦。为了结构清晰,和之前操作类似,我们直接自己添加一个`build`命令,并且由于Scratch源码开发的时候使用的是Python2,现在大部分电脑安装的是Python3,在这里顺便添加一下对Python3的支持(AI说要这么干的,但其实这个地方加个python3好像没有卵用)。
选中`prepublish`这一整行,粘贴下面的代码:
"prepublish": "echo 'Running build.py...' && (python3 build.py || python build.py) && echo 'Running webpack...' && webpack",
"build": "echo 'Running build.py...' && (python3 build.py || python build.py) && echo 'Running webpack...' && webpack",


继续在终端执行`npm run build`:

除了下面这个不要紧的warning以外,一片白和绿就是编译成功了。


3.3 链接本地`scratch-blocks`
在终端中执行`npm link`命令。
告诉npm工具,我这也有一份(`scratch-blocks`),可以考虑用我这份哦~
`link`成功:

3.4 连接本地`scratch-gui`和本地`scratch-blocks`
上一步只是告诉npm工具,我电脑里有一份`scratch-blocks`。
但是此时`scratch-gui-develop`文件夹内用的还是原版的`scratch-blocks`。
需要来到`scratch-gui-develop`目录下用我们的`scratch-blocks`替换原版的`scratch-blocks`。
Tips:`scratch-blocks`是模块名,npm工具能看到这个名字,`scratch-blocks-develop`是文件夹名。
文件夹名可以自行修改,每个人可能不一样。
执行命令时要分清输入的是文件夹路径还是模块名。

`link`成功:

回到浏览器看一眼,看一眼就“爆炸”:

细心的同学应该能发现,出问题的并不是`scratch-blocks`而是`scratch-l10n`,这是为什么呢?
因为在`scratch-gui`里link其它模块时,是覆盖而不是添加,如果你只写了link scratch-blocks那么gui就只会链接本地的`scratch-blocks`,本地`scratch-l10n`并没有被带上(即使我们之前link过)。
重新执行命令`npm link scratch-blocks scratch-l10n`:
npm link scratch-blocks scratch-l10n

在浏览器中重新加载,OK啦~

自定义指令积木上文本的字体大小
原理与【Scratch二次开发#3——自定义GUI文本】中修改字体大小的逻辑一样。
`scratch-blocks`的源码中,控制界面字体大小的代码格式是`font-size: {整数}pt`。
比如`font-size: 9pt`、`font-size: 12pt`。
对应的正则表达式是`font-size:\s*(\d+)pt`。
打开IDE查找替换工具并启用正则表达式,输入正则表达式`font-size:\s*(\d+)pt`查找对应代码。

找到`blocklyText`部分的`font-size`:

修改后需要在本地`scratch-blocks`目录下重新编译(我改成了13pt,大家自行修改):
cd ..\scratch-blocks-develop\
npm run build

编译成功:

由于我们之前link过了,可以直接回到浏览器中重新加载GUI(其实它大概率会自己刷新):


其它部分大家可以自行测试,或者问AI是控制哪些区域的字体大小,比如:


自定义指令积木上文本的内容
原理与【Scratch二次开发#3——自定义GUI文本】中修改不同区域文本内容的逻辑一样。
只要找到对应的中文翻译,修改翻译即可。
Tips:修改翻译不需要像修改字体大小一样重新编译,修改后直接在浏览器中重新加载即可。
1、修改“重复执行”为“一直重复执行”
我看这个翻译不爽很久了。
“重复执行”、“重复执行_次”、“重复执行直到”每次用嘴巴讲解三个积木混用的时候,脑子里都在打架。
先看原版英语单词:

forever和repeat怎么能用同一个词呢?
我个人想把它改成“一直重复执行”,大家有更好的翻译也可以在评论区分享。
查找本地`scratch-blocks`中的“重复执行”。


修改为“一直重复执行”后,由于我们之前link过了,可以直接回到浏览器中重新加载GUI:

2、修改“重复执行直到<>”为“重复执行直到<>才停”
低龄的小朋友需要清晰的指令才能更好的理解程序,英文原版的until本身就有直到...停止的意思,中文翻译省略掉了停反而不好理解(大龄的小朋友还比较好理解)。
比如我说“重复执行移动10步直到碰到角色1”,感觉就戛然而止了,后半句要自己脑补。
“重复执行移动10步直到碰到角色1才停”有明确的停,让小朋友知道这个积木是会停的。
以上是我的个人理解,我自己也很犹豫,好像有点多此一举。
我反悔了,原版挺好的,很精简。 ![]()

修改为“重复执行直到 %1才停”,%1是占位符。
在浏览器中重新加载:

3、修改“等待<>”为“一直等待直到<>”

明明是同一个单词,前面还有“重复执行直到”,到“等待”这个积木,连“直到”这层意思都不翻译了。
看看台湾繁体中文的翻译:

我决定改为“一直等待直到”和前面“一直重复执行”保持一致。
我有想过要不要改成“一直等待直到<>才继续”,但是考虑到积木会变的很长,所以折中选这个。
我也有想过要不要改成“等待直到<>”,但是经常有小孩子找积木的时候把“等待()秒”当成“等待<>”。
为了让这两个积木差别大一些,决定还是加上一直。
大家有想法也可以在评论区分享一下,我一个人想的一定是片面的。
查找本地`scratch-blocks`中的“等待 %1”。(就在“重复执行直到”的上一行)

修改为“一直等待直到 %1”,在浏览器中重新加载:

4、修改“停止全部脚本”为“停止程序”
很多小朋友会以为这个是停止当前角色的全部脚本,英文原版是"stop all"。
本身并没有脚本的意思,应该是一切都停止了。

我觉得翻译为“停止程序”会更清晰,可以和其它停止脚本区分开。
Mixly硬件编程中也有“停止程序”这样的积木。
就在上面,不用查找了。

修改为“程序”,在浏览器中重新加载:

5、修改“换成( )##”为“将##设为( )”

英语的语法结构、语境,无论用switch还是set搭配to介词都很清晰。
但是中文翻译就很奇怪:

“给我干哪来了,这还是国内吗?”
为了强化孩子们对“变量赋值”的抽象理解,我决定与下面这些赋值的指令积木统一翻译风格:

在`scratch-blocks-develop\msg\scratch_msgs.js`中查找`换成 %1`。

把`换成 %1 造型`改成`将造型设为 %1`。
把`换成 %1 背景`改成`将背景设为 %1`。
“换成 %1 背景并等待”与“当背景换成 %1”是一对配对积木,这两个我就不改了。
回到浏览器中重新加载:

而且在使用数字变量控制造型切换时念起来也更通顺:

6、修改“将大小##( )”



英语和繁体中文都有百分号,就简体中文没有。
加上百分号方便孩子们理解角色大小和造型大小之间的关系。
在`scratch-blocks-develop\msg\scratch_msgs.js`中查找`将大小设为 %1`。
修改成`将大小设为 %1 %`后回到浏览器中重新加载:

“将大小增加”这个也没有百分号,英文原版和繁体中文的都没有。

但是在英语语境里之所以没有是因为它用了介词by,表示通过by后面的东西修改size,如果加上百分号,那么在英语语境里就是通过百分之十修改大小,对英语来说很奇怪。
但是在中文语境里,将大小增加百分之十,是比较通顺的,所以我还是想加上。
修改成`将大小增加 %1 %`后回到浏览器中重新加载:

`将音量增加`同理,大家自己改改吧:

7、修改“播放声音”
不废话,直接看翻译


start = play = 播放是吧?until的直到怎么又变成等待了?
我决定将它们改成:“播放声音()直到播完”和“开始播放声音()”。
在`scratch-blocks-develop\msg\scratch_msgs.js`中查找这两个翻译并修改即可。
修改后回到浏览器中重新加载:

8、修改“碰到边缘就反弹”
先看翻译:


我 if 呢?
我决定将它改成:“如果碰到边缘就反弹”。
在`scratch-blocks-develop\msg\scratch_msgs.js`中查找这个翻译并修改即可。
修改后回到浏览器中重新加载:

9、修改“询问并等待( )”
很多低龄的小朋友初学编程时不理解`询问并等待( )`与`回答`的配对关系。
需要老师另外解释,很不直观。

我决定改为`询问并等待( )回答`。
在`scratch-blocks-develop\msg\scratch_msgs.js`中查找这个翻译并修改即可。
修改后回到浏览器中重新加载:

10、修改“广播消息( )并等待”
与“询问并等待( )”同理,很多小朋友并不知道它到底在等待什么,需要老师另外解释。
我决定改为“广播消息( )并等待接收”,这样就可以和“当接收到【】”配对。

在`scratch-blocks-develop\msg\scratch_msgs.js`中查找这个翻译并修改即可。
修改后回到浏览器中重新加载:

修改“积木分类区”中的“运算”为“运算符”
在乐高EV3的编程如今中就翻译为“运算符”。(EV3的二次开发做的挺好的,体验感很好)
我个人的看法是如果翻译为运算,那么孩子们只能联想到数学运算本身。
而如果翻译为运算符,我可以很方便的给孩子们拓展:“除了加减乘除以外,在计算机编程中还有其它运算符,比如......,这些对与计算机来说都是一种‘运算’”。
AI的建议:
Scratch 图形化编程软件中,
Operators模块的标准中文翻译是 运算符。翻译依据
语义匹配:
Operators在编程领域的核心含义是 “运算符”,特指实现数学计算、逻辑判断等操作的符号或指令。功能对应:该模块包含加减乘除、比较大小(等于 / 大于 / 小于)、逻辑运算(与 / 或 / 非)、字符串拼接等功能,完全符合 “运算符” 的应用场景。
官方统一:Scratch 中文官方版本(包括网页版、桌面版)均将该模块译为 “运算符”,是行业通用且官方认可的翻译。
补充说明
中文界面显示:在 Scratch 中文模式下,左侧模块栏直接显示 “运算符”,点击后可看到该分类下的所有运算类积木。
避免混淆:不要译为 “操作符”(虽语义相近,但 “运算符” 更贴合编程教育场景的通俗表达,适合青少年理解)。
不建议将
Operators译为 “运算”,准确性和场景适配性会打折扣。核心原因
语义偏差:“运算” 是动词或过程(比如 “执行加法运算”),而
Operators在 Scratch 中是模块名称,指 “实现运算的工具集合”,对应的名词是 “运算符”(比如 “+、-、>、= 都是运算符”)。场景适配性差:Scratch 是编程教育工具,模块名称需要明确指向 “具体工具”。“运算” 太笼统,青少年用户可能无法直观理解该模块的功能(比如会疑惑 “是教运算方法,还是提供运算工具?”)。
不符合官方与行业共识:中文官方版本、编程教育教材均统一用 “运算符”,译为 “运算” 会打破这种共识,可能导致用户查阅资料时产生混淆。
补充说明
如果只是个人使用时的简化称呼,偶尔说 “运算模块” 问题不大,但正式场景(比如教学、分享、自定义界面开发)建议沿用 “运算符”,既准确又符合用户认知习惯。
在`scratch-blocks-develop\msg\scratch_msgs.js`中查找`运算`并修改即可。
修改后回到浏览器中重新加载:

结语
本文的翻译都是我的个人想法,大家觉得哪些值得改,哪些不值得改,欢迎在评论区交流讨论。
1万+

被折叠的 条评论
为什么被折叠?



