Browse Source

feat: form-materials i18n (#641)

Yiwei Mao 5 months ago
parent
commit
ba1f1b1651

+ 2 - 2
packages/materials/form-materials/src/components/condition-row/constants.ts

@@ -5,7 +5,7 @@
 
 import { IRules, Op, OpConfigs } from './types';
 
-export const rules: IRules = {
+export const defaultRules: IRules = {
   string: {
     [Op.EQ]: 'string',
     [Op.NEQ]: 'string',
@@ -62,7 +62,7 @@ export const rules: IRules = {
   },
 };
 
-export const opConfigs: OpConfigs = {
+export const defaultOpConfigs: OpConfigs = {
   [Op.EQ]: {
     label: 'Equal',
     abbreviation: '=',

+ 13 - 9
packages/materials/form-materials/src/components/condition-row/hooks/useOp.tsx

@@ -5,30 +5,34 @@
 
 import React, { useMemo } from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
 import { Button, Select } from '@douyinfe/semi-ui';
 import { IconChevronDownStroked } from '@douyinfe/semi-icons';
 
-import { IRule, Op } from '../types';
-import { opConfigs } from '../constants';
+import { IRule, OpConfigs } from '../types';
+import { defaultOpConfigs } from '../constants';
 
 interface HookParams {
   rule?: IRule;
-  op?: Op;
-  onChange: (op: Op) => void;
+  op?: string;
+  onChange: (op: string) => void;
   readonly?: boolean;
+  userOps?: OpConfigs;
 }
 
-export function useOp({ rule, op, onChange, readonly }: HookParams) {
+export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
   const options = useMemo(
     () =>
       Object.keys(rule || {}).map((_op) => ({
-        ...(opConfigs[_op as Op] || {}),
+        ...(defaultOpConfigs[_op] || {}),
+        ...(userOps?.[_op] || {}),
         value: _op,
+        label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
       })),
-    [rule]
+    [rule, userOps]
   );
 
-  const opConfig = useMemo(() => opConfigs[op as Op], [op]);
+  const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
 
   const renderOpSelect = () => (
     <Select
@@ -38,7 +42,7 @@ export function useOp({ rule, op, onChange, readonly }: HookParams) {
       value={op}
       optionList={options}
       onChange={(v) => {
-        onChange(v as Op);
+        onChange(v as string);
       }}
       triggerRender={({ value }) => (
         <Button size="small" disabled={!rule}>

+ 6 - 3
packages/materials/form-materials/src/components/condition-row/hooks/useRule.ts

@@ -8,12 +8,15 @@ import { useMemo } from 'react';
 import { JsonSchemaUtils, JsonSchemaBasicType } from '@flowgram.ai/json-schema';
 import { useScopeAvailable } from '@flowgram.ai/editor';
 
-import { rules } from '../constants';
+import { IRules } from '../types';
+import { defaultRules } from '../constants';
 import { IFlowRefValue } from '../../../typings';
 
-export function useRule(left?: IFlowRefValue) {
+export function useRule(left?: IFlowRefValue, userRules?: IRules) {
   const available = useScopeAvailable();
 
+  const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
+
   const variable = useMemo(() => {
     if (!left) return undefined;
     return available.getByKeyPath(left.content);
@@ -25,7 +28,7 @@ export function useRule(left?: IFlowRefValue) {
     const schema = JsonSchemaUtils.astToSchema(variable.type, { drilldown: false });
 
     return rules[schema?.type as JsonSchemaBasicType];
-  }, [variable?.type]);
+  }, [variable?.type, rules]);
 
   return { rule };
 }

+ 22 - 6
packages/materials/form-materials/src/components/condition-row/index.tsx

@@ -5,10 +5,10 @@
 
 import React, { useMemo } from 'react';
 
-import { JsonSchemaBasicType } from '@flowgram.ai/json-schema';
+import { I18n } from '@flowgram.ai/editor';
 import { Input } from '@douyinfe/semi-ui';
 
-import { ConditionRowValueType, Op } from './types';
+import { ConditionRowValueType, IRules, OpConfigs } from './types';
 import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
 import { useRule } from './hooks/useRule';
 import { useOp } from './hooks/useOp';
@@ -20,20 +20,36 @@ interface PropTypes {
   onChange: (value?: ConditionRowValueType) => void;
   style?: React.CSSProperties;
   readonly?: boolean;
+  ruleConfig?: {
+    ops?: OpConfigs;
+    rules?: IRules;
+  };
 }
 
-export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
+const defaultRuleConfig = {
+  ops: {},
+  rules: {},
+};
+
+export function ConditionRow({
+  style,
+  value,
+  onChange,
+  readonly,
+  ruleConfig = defaultRuleConfig,
+}: PropTypes) {
   const { left, operator, right } = value || {};
-  const { rule } = useRule(left);
+  const { rule } = useRule(left, ruleConfig.rules);
   const { renderOpSelect, opConfig } = useOp({
     rule,
     op: operator,
     onChange: (v) => onChange({ ...value, operator: v }),
     readonly,
+    userOps: ruleConfig.ops,
   });
 
   const targetSchema = useMemo(() => {
-    const targetType: JsonSchemaBasicType | null = rule?.[operator as Op] || null;
+    const targetType: string | null = rule?.[operator || ''] || null;
     return targetType ? { type: targetType, extra: { weak: true } } : null;
   }, [rule, opConfig]);
 
@@ -70,7 +86,7 @@ export function ConditionRow({ style, value, onChange, readonly }: PropTypes) {
               size="small"
               disabled
               style={{ pointerEvents: 'none' }}
-              value={opConfig?.rightDisplay || 'Empty'}
+              value={opConfig?.rightDisplay || I18n.t('Empty')}
             />
           )}
         </UIRight>

+ 4 - 6
packages/materials/form-materials/src/components/condition-row/types.ts

@@ -3,8 +3,6 @@
  * SPDX-License-Identifier: MIT
  */
 
-import { JsonSchemaBasicType } from '@flowgram.ai/json-schema';
-
 import { IFlowConstantRefValue, IFlowRefValue } from '../../typings';
 
 export enum Op {
@@ -31,14 +29,14 @@ export interface OpConfig {
   rightDisplay?: string;
 }
 
-export type OpConfigs = Record<Op, OpConfig>;
+export type OpConfigs = Record<string, OpConfig>;
 
-export type IRule = Partial<Record<Op, JsonSchemaBasicType | null>>;
+export type IRule = Partial<Record<string, string | null>>;
 
-export type IRules = Record<JsonSchemaBasicType, IRule>;
+export type IRules = Record<string, IRule>;
 
 export interface ConditionRowValueType {
   left?: IFlowRefValue;
-  operator?: Op;
+  operator?: string;
   right?: IFlowConstantRefValue;
 }

+ 7 - 4
packages/materials/form-materials/src/components/json-schema-editor/index.tsx

@@ -6,6 +6,7 @@
 import React, { useMemo, useState } from 'react';
 
 import { IJsonSchema } from '@flowgram.ai/json-schema';
+import { I18n } from '@flowgram.ai/editor';
 import { Button, Checkbox, IconButton } from '@douyinfe/semi-ui';
 import {
   IconExpand,
@@ -219,25 +220,27 @@ function PropertyEdit(props: {
           </UIRow>
           {expand && (
             <UIExpandDetail>
-              <UILabel>{config?.descTitle ?? 'Description'}</UILabel>
+              <UILabel>{config?.descTitle ?? I18n.t('Description')}</UILabel>
               <BlurInput
                 disabled={readonly}
                 size="small"
                 value={description}
                 onChange={(value) => onChange('description', value)}
-                placeholder={config?.descPlaceholder ?? 'Help LLM to understand the property'}
+                placeholder={
+                  config?.descPlaceholder ?? I18n.t('Help LLM to understand the property')
+                }
               />
               {$level === 0 && type && type !== 'array' && (
                 <>
                   <UILabel style={{ marginTop: 10 }}>
-                    {config?.defaultValueTitle ?? 'Default Value'}
+                    {config?.defaultValueTitle ?? I18n.t('Default Value')}
                   </UILabel>
                   <DefaultValueWrapper>
                     <DefaultValue
                       value={defaultValue}
                       schema={value}
                       type={type}
-                      placeholder={config?.defaultValuePlaceholder}
+                      placeholder={config?.defaultValuePlaceholder ?? I18n.t('Default Value')}
                       jsonFormatText={config?.jsonFormatText}
                       onChange={(value) => onChange('default', value)}
                     />

+ 2 - 4
packages/materials/form-materials/src/components/type-selector/index.tsx

@@ -23,8 +23,6 @@ interface PropTypes {
 
 const labelStyle: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 5 };
 
-const firstUppercase = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
-
 export const getTypeSelectValue = (value?: Partial<IJsonSchema>): string[] | undefined => {
   if (value?.type === 'array' && value?.items) {
     return [value.type, ...(getTypeSelectValue(value.items) || [])];
@@ -61,7 +59,7 @@ export function TypeSelector(props: PropTypes) {
           label: (
             <div style={labelStyle}>
               <Icon size="small" svg={_type.icon} />
-              {firstUppercase(_type.type)}
+              {typeManager.getTypeBySchema(_type)?.label || _type.type}
             </div>
           ),
           value: _type.type,
@@ -76,7 +74,7 @@ export function TypeSelector(props: PropTypes) {
                         items: { type: _type.type },
                       })}
                     />
-                    {firstUppercase(_type.type)}
+                    {typeManager.getTypeBySchema(_type)?.label || _type.type}
                   </div>
                 ),
                 value: _type.type,

+ 2 - 1
packages/materials/form-materials/src/components/variable-selector/index.tsx

@@ -6,6 +6,7 @@
 import React, { useMemo } from 'react';
 
 import { IJsonSchema } from '@flowgram.ai/json-schema';
+import { I18n } from '@flowgram.ai/editor';
 import { TriggerRenderProps } from '@douyinfe/semi-ui/lib/es/treeSelect';
 import { TreeNodeData } from '@douyinfe/semi-ui/lib/es/tree';
 import { Popover } from '@douyinfe/semi-ui';
@@ -130,7 +131,7 @@ export const VariableSelector = ({
         showClear={false}
         arrowIcon={<IconChevronDownStroked size="small" />}
         triggerRender={triggerRender}
-        placeholder={config?.placeholder ?? 'Select Variable'}
+        placeholder={config?.placeholder ?? I18n.t('Select Variable')}
       />
     </>
   );

+ 3 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/array.tsx

@@ -6,6 +6,8 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
+
 import { CodeEditorMini } from '@/components/code-editor-mini';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -17,7 +19,7 @@ export const arrayRegistry: Partial<JsonSchemaTypeRegistry> = {
       value={props.value}
       languageId="json"
       onChange={(v) => props.onChange?.(v)}
-      placeholder="Please Input Array"
+      placeholder={I18n.t('Please Input Array')}
       readonly={props.readonly}
     />
   ),

+ 4 - 3
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/boolean.tsx

@@ -6,6 +6,7 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
 import { Select } from '@douyinfe/semi-ui';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -16,12 +17,12 @@ export const booleanRegistry: Partial<JsonSchemaTypeRegistry> = {
     const { value, onChange, ...rest } = props;
     return (
       <Select
-        placeholder="Please Select Boolean"
+        placeholder={I18n.t('Please Select Boolean')}
         size="small"
         disabled={props.readonly}
         optionList={[
-          { label: 'True', value: 1 },
-          { label: 'False', value: 0 },
+          { label: I18n.t('True'), value: 1 },
+          { label: I18n.t('False'), value: 0 },
         ]}
         value={value ? 1 : 0}
         onChange={(value) => onChange?.(!!value)}

+ 2 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/integer.tsx

@@ -6,6 +6,7 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
 import { InputNumber } from '@douyinfe/semi-ui';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -14,7 +15,7 @@ export const integerRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'integer',
   ConstantRenderer: (props) => (
     <InputNumber
-      placeholder="Please Input Integer"
+      placeholder={I18n.t('Please Input Integer')}
       size="small"
       disabled={props.readonly}
       precision={0}

+ 2 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/number.tsx

@@ -6,6 +6,7 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
 import { InputNumber } from '@douyinfe/semi-ui';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -14,7 +15,7 @@ export const numberRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'number',
   ConstantRenderer: (props) => (
     <InputNumber
-      placeholder="Please Input Number"
+      placeholder={I18n.t('Please Input Number')}
       size="small"
       disabled={props.readonly}
       hideButtons

+ 3 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/object.tsx

@@ -6,6 +6,8 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
+
 import { CodeEditorMini } from '@/components/code-editor-mini';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -17,7 +19,7 @@ export const objectRegistry: Partial<JsonSchemaTypeRegistry> = {
       value={props.value}
       onChange={(v) => props.onChange?.(v)}
       languageId="json"
-      placeholder="Please Input Object"
+      placeholder={I18n.t('Please Input Object')}
       readonly={props.readonly}
     />
   ),

+ 7 - 1
packages/materials/form-materials/src/plugins/json-schema-preset/type-definition/string.tsx

@@ -6,6 +6,7 @@
 /* eslint-disable react/prop-types */
 import React from 'react';
 
+import { I18n } from '@flowgram.ai/editor';
 import { Input } from '@douyinfe/semi-ui';
 
 import { type JsonSchemaTypeRegistry } from '../manager';
@@ -13,6 +14,11 @@ import { type JsonSchemaTypeRegistry } from '../manager';
 export const stringRegistry: Partial<JsonSchemaTypeRegistry> = {
   type: 'string',
   ConstantRenderer: (props) => (
-    <Input placeholder="Please Input String" size="small" disabled={props.readonly} {...props} />
+    <Input
+      placeholder={I18n.t('Please Input String')}
+      size="small"
+      disabled={props.readonly}
+      {...props}
+    />
   ),
 };