chore: replace all cn comments of fe to en version by volc api (#320)

This commit is contained in:
tecvan
2025-07-31 10:32:15 +08:00
committed by GitHub
parent 716ec0cba8
commit 71f6245a01
2960 changed files with 15545 additions and 15545 deletions

View File

@@ -26,7 +26,7 @@ export const ActionBarContext = createContext<{
controller: {
// eslint-disable-next-line @typescript-eslint/no-empty-function
hideActionBar: () => {},
// 重新定位
// reposition
// eslint-disable-next-line @typescript-eslint/no-empty-function
rePosition: () => {},
},

View File

@@ -135,7 +135,7 @@ export const ActionBar: React.FC<PropsWithChildren<ActionBarProps>> = props => {
// }
editor.$on('mousedown', handleMousedown);
// 不使用 editor.$on 监听 mouseup 事件,因为鼠标可能不在编辑器内
// Do not use editor. $on to listen for mouseup events because the mouse may not be in the editor
document.addEventListener('mouseup', handleMouseup);
editor.$on('selectionChange', handleSelectionChange);
// editor.$on('blur', handleBlur);

View File

@@ -26,7 +26,7 @@ import {
} from '../constant';
export namespace ExpressionEditorParserBuiltin {
/** 计算开始和结束标识的序号 */
/** Calculate the serial number of the start and end tags */
export const tokenOffset = (line: {
lineContent: string;
lineOffset: number;
@@ -49,7 +49,7 @@ export namespace ExpressionEditorParserBuiltin {
firstEndTokenOffset + 2,
);
if (endChars !== ExpressionEditorToken.FullEnd) {
// 结束符号 "}}" 不完整
// End symbol "}}" is incomplete
return;
}
const lastStartTokenOffset = content.lastIndexOf(
@@ -61,7 +61,7 @@ export namespace ExpressionEditorParserBuiltin {
lastStartTokenOffset + 1,
);
if (startChars !== ExpressionEditorToken.FullStart) {
// 开始符号 "{{" 不完整
// The opening symbol "{{" is incomplete
return;
}
return {
@@ -70,7 +70,7 @@ export namespace ExpressionEditorParserBuiltin {
};
};
/** 从行内容提取内容 */
/** Extract content from line content */
export const extractContent = (params: {
lineContent: string;
lineOffset: number;
@@ -99,7 +99,7 @@ export namespace ExpressionEditorParserBuiltin {
};
};
/** 根据 offset 将文本内容切分为可用与不可用 */
/** Split text content into available and unavailable by offset */
export const sliceReachable = (params: {
content: string;
offset: number;
@@ -116,29 +116,29 @@ export namespace ExpressionEditorParserBuiltin {
};
};
/** 切分文本 */
/** Split text */
export const splitText = (pathString: string): string[] => {
// 得到的分割数组,初始为原字符串以"."分割的结果
// The obtained split array, initially the result of splitting the original string with "."
const segments = pathString.split(ExpressionEditorToken.Separator);
// 定义结果数组,并处理连续的"."导致的空字符串
// Define the result array and handle empty strings resulting from consecutive "."
const result: string[] = [];
segments.forEach(segment => {
if (!segment.match(/\[\d+\]/)) {
// 如果不是数组索引,直接加入结果数组,即使是空字符串也加入以保持正确的分割
// If it is not an array index, add the result array directly, even if it is an empty string, to maintain the correct segmentation
result.push(segment);
return;
}
// 如果当前段是数组索引,将前面的字符串和当前数组索引分别加入结果数组
// If the current segment is an array index, add the previous string and the current array index to the result array, respectively
const lastSegmentIndex = segment.lastIndexOf(
ExpressionEditorToken.ArrayStart,
);
const key = segment.substring(0, lastSegmentIndex);
const index = segment.substring(lastSegmentIndex);
// {{array[0]}} 中的 array
// Array in {{array [0]}}
result.push(key);
// {{array[0]}} 中的 [0]
// [0] in {{array [0]}}
result.push(index);
return;
});
@@ -146,14 +146,14 @@ export namespace ExpressionEditorParserBuiltin {
return result;
};
/** 字符串解析为路径 */
/** String parsed as path */
export const toSegments = (
text: string,
): ExpressionEditorSegment[] | undefined => {
const textSegments = ExpressionEditorParserBuiltin.splitText(text);
const segments: ExpressionEditorSegment[] = [];
const validate = textSegments.every((textSegment, index) => {
// 数组下标
// array subscript
if (
textSegment.startsWith(ExpressionEditorToken.ArrayStart) &&
textSegment.endsWith(ExpressionEditorToken.ArrayEnd)
@@ -161,7 +161,7 @@ export namespace ExpressionEditorParserBuiltin {
const arrayIndexString = textSegment.slice(1, -1);
const arrayIndex = Number(arrayIndexString);
if (arrayIndexString === '' || Number.isNaN(arrayIndex)) {
// index 必须是数字
// Index must be a number
return false;
}
const lastSegment = segments[segments.length - 1];
@@ -169,7 +169,7 @@ export namespace ExpressionEditorParserBuiltin {
!lastSegment ||
lastSegment.type !== ExpressionEditorSegmentType.ObjectKey
) {
// 数组索引必须在 key 之后
// The array index must be after the key
return false;
}
segments.push({
@@ -178,7 +178,7 @@ export namespace ExpressionEditorParserBuiltin {
arrayIndex,
});
}
// 最后一行空文本
// The last empty line of text
else if (index === textSegments.length - 1 && textSegment === '') {
segments.push({
type: ExpressionEditorSegmentType.EndEmpty,

View File

@@ -43,7 +43,7 @@ export namespace ExpressionEditorTreeHelper {
const lastSegment = segments[segments.length - 1];
const segmentsRemovedLast =
lastSegment.type === ExpressionEditorSegmentType.ArrayIndex
? segments.slice(0, segments.length - 2) // 数组索引属于上一层级,需要去除两层
? segments.slice(0, segments.length - 2) // The array index belongs to the previous level, and two layers need to be removed.
: segments.slice(0, segments.length - 1);
let treeLayer = tree;
segmentsRemovedLast.forEach(segment => {
@@ -53,7 +53,7 @@ export namespace ExpressionEditorTreeHelper {
const treeChildren = treeLayer.filter(
node => node.label === segment.objectKey,
);
// 兼容变量名重复,但子字段不同的场景
// Compatible variable names are duplicated, but the subfields are different
if (treeChildren?.length) {
treeLayer = treeChildren.reduce(
(pre: ExpressionEditorTreeNode[], cur: ExpressionEditorTreeNode) => {
@@ -80,7 +80,7 @@ export namespace ExpressionEditorTreeHelper {
const pathList: { objectKey: string; arrayIndex?: number }[] = [];
while (current) {
if (current.variable?.type === ViewVariableType.ArrayObject) {
// 默认第0个
// Default 0th
pathList.unshift({
objectKey: current.label,
arrayIndex: 0,
@@ -100,7 +100,7 @@ export namespace ExpressionEditorTreeHelper {
const pathItem = pathList[pathIndex];
pathIndex++;
if (pathItem.objectKey !== segment.objectKey) {
// 退出循环
// exit the loop
return true;
}
const nextSegment = segments[index + 1];
@@ -140,7 +140,7 @@ export namespace ExpressionEditorTreeHelper {
return false;
};
const beforeTreeNode = treeBranch[treeBranch.length - 1];
// 确认非法情况:是否对非数组类型使用数组索引
// Verify Illegal Case: Whether to Use Array Indexing for Non-Array Types
if (
segment.type === ExpressionEditorSegmentType.ArrayIndex &&
beforeTreeNode &&
@@ -148,7 +148,7 @@ export namespace ExpressionEditorTreeHelper {
) {
return itemInvalid();
}
// 确认非法情况:数组只能跟随数组下标
// Confirm illegal condition: Array can only follow array subscript
if (
beforeTreeNode?.variable?.type &&
isArrayType(beforeTreeNode.variable.type) &&
@@ -156,12 +156,12 @@ export namespace ExpressionEditorTreeHelper {
) {
return itemInvalid();
}
// 忽略
// ignore
if (segment.type !== ExpressionEditorSegmentType.ObjectKey) {
return itemValid();
}
const treeNode = treeLayer.find(node => node.label === segment.objectKey);
// 确认非法情况:每一个 object key 必须对应一个 variable node
// Verify illegal condition: each object key must correspond to a variable node
if (!treeNode) {
return itemInvalid();
}

View File

@@ -43,7 +43,7 @@ export interface Variable {
type: VariableType;
name: string;
children?: Variable[];
// 用户自定义节点名展示
// user-defined node name display
label?: string;
}

View File

@@ -57,7 +57,7 @@ function useSelection(editor: ExpressionEditorAPI | undefined) {
const view = editor.$view;
function updateSelection(update?: ViewUpdate) {
// 忽略 replaceTextByRange 导致的 selection change(效果:不触发 selection 变更,进而不显示推荐面板)
// Ignore the selection change caused by replaceTextByRange (effect: no selection change is triggered, and the recommendation panel is not displayed)
if (update?.transactions.some(tr => isSkipSelectionChangeUserEvent(tr))) {
setSelection(undefined);
return;

View File

@@ -22,7 +22,7 @@ import { generateUniqueId, getSearchValue, useLatest } from '../../shared';
import { type ExpressionEditorTreeNode } from '../../core';
import { type CompletionContext } from './types';
// 在数据更新后,强制 Tree 组件重新渲染
// Force the Tree component to re-render after the data update
function useTreeRefresh(filteredVariableTree: ExpressionEditorTreeNode[]) {
const [treeRefreshKey, setTreeRefreshKey] = useState('');
@@ -33,7 +33,7 @@ function useTreeRefresh(filteredVariableTree: ExpressionEditorTreeNode[]) {
return treeRefreshKey;
}
// Tree 组件重新渲染后进行搜索
// Search after the Tree component is re-rendered
// eslint-disable-next-line max-params
function useTreeSearch(
treeRefreshKey: string,

View File

@@ -140,10 +140,10 @@ function Popover({
const { elements } = optionsInfo;
selectNodeByIndex(elements, 0);
});
// selected 仅用于 Tree 组件对应项展示蓝色选中效果,无其他用途
// Selected is only used to display the blue selection effect for the corresponding item of the Tree component, and has no other purpose.
const selected = useSelectedValue(completionContext?.text, variableTree);
// 基于用户选中项,替换所在 {{}} 中的内容
// Replace content in {{}} based on user selection
const handleSelect = useCallback(
// eslint-disable-next-line @typescript-eslint/naming-convention
(_: string, __: boolean, node: TreeNodeData) => {
@@ -166,7 +166,7 @@ function Popover({
Boolean(emptyContent));
const [allowVisible, setAllowVisible] = useState(false);
// 选区变化时,清除锁定效果
// Clear the lock effect when the selection changes
useEffect(() => {
setAllowVisible(true);
}, [selection]);
@@ -180,14 +180,14 @@ function Popover({
treeRef,
);
// 上下键切换推荐项,回车填入
// Press the up and down keys to switch the recommended items, and press Enter to fill in.
useKeyboard(visible, {
ArrowUp: prev,
ArrowDown: next,
Enter: apply,
});
// ESC 关闭
// ESC Close
useKeyboard(visible, {
// eslint-disable-next-line @typescript-eslint/naming-convention
Escape() {
@@ -195,7 +195,7 @@ function Popover({
},
});
// 推荐面板出现时,禁用 ArrowUp/ArrowDown/Enter 的默认行为(行为改为上下键切换推荐项 & 回车插入)
// When the recommendation panel appears, disable the default behavior of ArrowUp/ArrowDown/Enter (the behavior is changed to up and down keys to switch recommendations & enter to insert)
useEffect(() => {
if (visible === true) {
editorRef.current?.disableKeybindings(['ArrowUp', 'ArrowDown', 'Enter']);

View File

@@ -62,7 +62,7 @@ const getOptionInfoFromDOM = (
return;
}
// 获取所有的选项元素
// Get all option elements
const foundNodes = root.querySelectorAll(
'.semi-tree-option-list .semi-tree-option',
);
@@ -73,7 +73,7 @@ const getOptionInfoFromDOM = (
const optionElements = [...foundNodes];
// 找到当前高亮的选项
// Find the currently highlighted option
const selectedIndex = optionElements.findIndex(element =>
element.classList.contains(getSelectedClassName()),
);

View File

@@ -33,10 +33,10 @@ function useLatest<T>(value: T): MutableRefObject<T> {
return ref;
}
// 解除 parent 导致的循环依赖(否则无法深比较)
// Remove circular dependencies caused by parents (otherwise no deep comparison is possible)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function cloneWithout(target: any, keys: string[]) {
// target undefined 时会抛错
// An error is thrown when target is undefined
try {
return JSON.parse(
JSON.stringify(target, function (key, value) {
@@ -85,7 +85,7 @@ function getSearchValue(textBefore: string) {
const lastSegment =
segments[segments.length - 1].type ===
ExpressionEditorSegmentType.ArrayIndex
? segments[segments.length - 2] // 数组索引属于上一层级,需要去除防止影响到搜索值
? segments[segments.length - 2] // The array index belongs to the previous level and needs to be removed to prevent it from affecting the search value
: segments[segments.length - 1];
if (
!lastSegment ||

View File

@@ -70,9 +70,9 @@ function Validation({ variableTree }: Props) {
if (
cursor.name === 'JinjaExpression' &&
// 由于 parser 存在容错能力
// 可能出现缺少右花括号也被正常解析为 Interpolation 的情况
// 如:{{variable
// Due to the fault tolerance of the parser
// It is possible that the missing right curly brace is also parsed normally as Interpolation
// Such as: {{variable
cursor.node.firstChild?.name === 'JinjaExpressionStart' &&
cursor.node.lastChild?.name === 'JinjaExpressionEnd'
) {

View File

@@ -18,7 +18,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
/**
* 前端变量类型
* Front-end variable type
*/
export enum ViewVariableType {
String = 1,
@@ -39,7 +39,7 @@ export enum ViewVariableType {
Svg,
Voice,
Time,
// 上面是 api 中定义的 InputType。下面是整合后的。从 99 开始,避免和后端定义撞车
// The above is the InputType defined in the api. The following is the integrated one. Start from 99 to avoid collisions with the backend definition.
ArrayString = 99,
ArrayInteger,
ArrayBoolean,

View File

@@ -57,7 +57,7 @@ export const useSelectionInJinjaRaw = () => {
editor.$on('viewUpdate', checkInJinjaRaw);
// 初始检查
// Initial inspection
checkInJinjaRaw();
return () => {

View File

@@ -39,7 +39,7 @@ export const ConfigModeWidgetPopover = (props: {
}
const handleViewUpdate = (e: ViewUpdate) => {
if (e.docChanged) {
// 判断当前光标是否在 slot 节点内
// Determine whether the current cursor is in the slot node
const { state } = e;
const range = templateParser.getCursorInMarkNodeRange(state);
if (!range) {

View File

@@ -91,7 +91,7 @@ export class LibraryBlockWidgetType extends WidgetType {
}
if (!this.mounted) {
// 同步渲染,避免抖动
// Synchronized rendering to avoid jitter
this.renderLibraryBlock(this.options);
this.renderTooltip(this.options);
this.mounted = true;
@@ -271,7 +271,7 @@ export const LibraryBlockWidgetReactCom = (props: {
</span>
);
// 只在tooltipConfig存在时渲染Tooltip
// Render Tooltip only if tooltipConfig exists
if (!tooltipConfig) {
return baseElement;
}

View File

@@ -59,8 +59,8 @@ export const LibrarySearchPopover = ({
setToPosition(toB);
setVisible(true);
} else {
// 一些场景输入 { 不应该弹出提示面板
// 如:光标在 {{ }} 内,或在 {% %} 内,或在 {# #}
// Some scene input {should not pop up the prompt panel
// For example, the cursor is within {{ }} , or within {% %} , or within {# #}
setVisible(false);
}
} else {
@@ -114,7 +114,7 @@ export const LibrarySearchPopover = ({
}),
},
});
// 去除插入的快捷键, 因为原来自动添加了
// Remove the inserted shortcut, because the original was automatically added
templateParser.insertTemplateByRange(editor, template, {
from: position,
to: toPosition,

View File

@@ -57,7 +57,7 @@ const defaultLibraryBlockInfo: Record<
icon: imageIcon,
},
};
// 根据资源类型获取对应的信息
// Get the corresponding information according to the resource type
export const getLibraryBlockInfoFromTemplate = (props: {
template: string;
templateParser: TemplateParser;

View File

@@ -129,7 +129,7 @@ export const ContentSearchPopover = ({
activeKey={activeTab}
onChange={key => {
setActiveTab(key);
// 保证切换tab后光标仍然定位在编辑器上
// Make sure the cursor is still positioned on the editor after switching tabs
setTimeout(() => {
editorRef.current?.$view.focus();
}, 0);

View File

@@ -43,7 +43,7 @@ const getOptionInfoFromDOM = (
const optionElements = [...foundNodes];
// 找到当前高亮的选项
// Find the currently highlighted option
const selectedIndex = optionElements.findIndex(element =>
element.classList.contains(SELECTED_OPTION_CLASSNAME),
);

View File

@@ -65,7 +65,7 @@ export default function useVariablesTree({
const selected = useSelectedValue(completionContext?.text, variableTree);
// 基于用户选中项,替换所在 {{}} 中的内容
// Replace content in {{}} based on user selection
const handleSelect = useCallback(
(_: string, __: boolean, node: TreeNodeData) => {
if (!editor || !completionContext) {
@@ -101,7 +101,7 @@ export default function useVariablesTree({
treeRef,
);
// 上下键切换推荐项,回车填入
// Press the up and down keys to switch the recommended items, and press Enter to fill in.
useKeyboard(enableKeyboard, {
ArrowUp: prev,
ArrowDown: next,

View File

@@ -30,7 +30,7 @@ export interface MarkRangeInfo {
close: MarkRange;
}
// 解析模板字符串: {#slot name="slot_name" #}xxx{#/slot#}
// Parse template string: {#slot name = "slot_name" #} xxx {#/slot #}
export class TemplateParser {
public mark!: 'LibraryBlock' | 'InputSlot';
private openReg!: RegExp;
@@ -125,28 +125,28 @@ export class TemplateParser {
return close;
}
// 解析模板字符串: {#slot id="slot_id" value="slot_value"#},获取所有属性
// Parse template string: {#slot id = "slot_id" value = "slot_value" #}, get all properties
getData(templateString: string): { [key: string]: string } | null {
// 根据传入的类型构造正则表达式,例如 slot block
// Constructs regular expressions based on the type passed in, such as slots or blocks
const regex = new RegExp(`\\{#${this.mark}\\s+([^#]+)#\\}`, 'g');
const match = regex.exec(templateString);
if (match !== null) {
const attributes = match[1].trim(); // 匹配到的属性部分
const attributes = match[1].trim(); // Matched attribute part
const attrRegex = /(\w+)\s*=\s*"([^"]*)"/g;
const obj: { [key: string]: string } = {}; // 初始对象
const obj: { [key: string]: string } = {}; // initial object
let attrMatch: RegExpExecArray | null;
while (true) {
attrMatch = attrRegex.exec(attributes);
if (attrMatch === null) {
break;
}
obj[attrMatch[1]] = attrMatch[2]; // 将匹配的键值对添加到对象中
obj[attrMatch[1]] = attrMatch[2]; // Adds a matching key-value pair to the object
}
return obj; // 返回解析结果
return obj; // Return the parsing result
}
return null; // 没有匹配时返回 null
return null; // Returns null if there is no match
}
getCursorTemplateData(state: EditorState) {
@@ -218,8 +218,8 @@ export class TemplateParser {
}
/**
* 修改当前光标所在位置的模板数据: {#slot placeholder="default_placeholder"#} 修改为 {#slot placeholder="new_placeholder"#}
* 新增: {#slot placeholder="default_placeholder"#} 新增 {#slot value="new_value" placeholder="new_placeholder"#}
* Modify the template data for the current cursor position: {#slot placeholder = "default_placeholder" #} Modify to {#slot placeholder = "new_placeholder" #}
* Added: {#slot placeholder = "default_placeholder" #} Added {#slot value = "new_value" placeholder = "new_placeholder" #}
*/
updateCursorTemplateData(editor: EditorAPI, data: { [key: string]: string }) {
const { state } = editor.$view;
@@ -347,14 +347,14 @@ export class TemplateParser {
},
});
}
// 提取模板中内容{#InputSlot placeholder="placeholder"#}123{#/InputSlot#}xxx嵌套模板下内部所有的content
// Extract the content in the template {#InputSlot placeholder = "placeholder" #} 123 {#/InputSlot #} xxx, all the internal content under the nested template
extractTemplateContent(template: string) {
// 使用正则表达式匹配 {#InputSlot ... #} 的部分
// Use regular expressions to match parts of {#InputSlot... #}
const regex = new RegExp(
`\\{#${this.mark}\\s+[^#]+#\\}|\\{#\\/${this.mark}#\\}`,
'g',
);
// 使用 replace 方法替换掉匹配的部分
// Use the replace method to replace the matching part
const result = template.replace(regex, '');
console.log('extractTemplateContent', result);
return result;