Merge pull request #7814 from QKflame/feat-complete-i18n-example-code

完善国际化调试代码
This commit is contained in:
wutong 2023-08-15 11:21:13 +08:00 committed by GitHub
commit c2e9063bcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 395 additions and 3 deletions

View File

@ -9,9 +9,9 @@ import LayoutList from './layout/index';
import themeConfig from 'amis-theme-editor-helper/lib/systemTheme/cxd';
// 测试组织属性配置面板的国际化,可以放开如下注释
// import '../renderer/InputTextI18n';
// import '../renderer/TextareaI18n';
// import '../utils/overwriteSchemaTpl';
// import './renderer/InputTextI18n';
// import './renderer/TextareaI18n';
// import './utils/overwriteSchemaTpl';
// const i18nEnabled = true;
const i18nEnabled = false;
setThemeConfig(themeConfig);

View File

@ -0,0 +1,167 @@
/**
* @file client/renderer/InputTextI18n.tsx
* @description input-text
*/
import {
FormControlProps,
FormItem,
makeTranslator,
autobind
} from '../../../amis-core/src/index';
import React from 'react';
import {Icon, InputBox} from '../../../amis-ui/src/index';
import {InputBoxProps} from '../../../amis-ui/src/components/InputBox';
import cx from 'classnames';
import {getEnv} from 'mobx-state-tree';
import {pick} from 'lodash';
/** 语料 key 正则表达式 */
export const corpusKeyReg =
/^i18n:[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/;
interface InputTextI18nProps extends InputBoxProps {
classPrefix: string;
i18nEnabled?: boolean;
disabled?: boolean;
locale?: string;
maxLength?: number;
minLength?: number;
translate?: (value: any) => any;
onI18nChange?: (value: string) => void;
}
export class InputTextI18n extends React.Component<InputTextI18nProps> {
constructor(props: InputTextI18nProps) {
super(props);
}
render() {
let {
value,
classPrefix,
i18nEnabled,
className,
disabled,
translate = makeTranslator(this.props.locale),
placeholder,
onI18nChange,
...rest
} = this.props;
const restProps = rest
? pick(rest, [
'onBlur',
'placeholder',
'disabled',
'readOnly',
'onClear',
'hasError',
'prefix',
'children',
'borderMode'
])
: {};
const isMatch = corpusKeyReg.test(value!);
const _value = i18nEnabled ? translate(value) : value;
return (
<div
className={cx(className, `${classPrefix}InputI18n-container`, {
[`${classPrefix}InputI18n-multi-container`]: i18nEnabled
})}
>
<div className={cx(`${classPrefix}InputI18n-inner-container`)}>
<InputBox
{...restProps}
value={_value}
clearable={false}
onChange={this.onInputChange}
placeholder={placeholder}
disabled={disabled}
></InputBox>
{i18nEnabled && !disabled ? (
<div
className={cx(`${classPrefix}InputI18n-addon-container`, {
[`${classPrefix}InputI18n-addon-active`]: isMatch
})}
onClick={this.onClickI18nBtn}
>
<Icon
icon="corpus-i18n"
className="icon cursor-pointer CorpusI18n-input-icon"
/>
</div>
) : null}
{isMatch && i18nEnabled ? (
<div
className={cx(`${classPrefix}InputI18n-overlay`)}
onClick={this.onClickI18nBtn}
></div>
) : null}
</div>
</div>
);
}
@autobind
onClickI18nBtn() {
const {value} = this.props;
if (corpusKeyReg.test(value!)) {
this.props?.onChange?.('');
this.props.onI18nChange?.('');
return;
}
let _uuid = 'i18n:1189fb5d-ac5b-4558-b363-068ce5decc99';
this.props?.onChange?.(_uuid);
this.props.onI18nChange?.(_uuid);
}
@autobind
onInputChange(value: string) {
this.props.onChange?.(value);
}
}
interface InputTextI18nControlProps extends FormControlProps {}
class InputTextI18nControl extends React.Component<InputTextI18nControlProps> {
constructor(props: InputTextI18nControlProps) {
super(props);
}
render() {
const {
onChange,
value,
classPrefix,
className,
classnames,
placeholder,
disabled,
...rest
} = this.props;
const {i18nEnabled} = getEnv((window as any).editorStore);
return (
<InputTextI18n
{...rest}
i18nEnabled={i18nEnabled}
onChange={onChange}
classPrefix={classPrefix}
classnames={classnames}
value={value}
placeholder={placeholder}
className={className}
disabled={disabled}
></InputTextI18n>
);
}
}
@FormItem({
type: 'input-text-i18n'
})
export class InputTextI18nRenderer extends InputTextI18nControl {}

View File

@ -0,0 +1,83 @@
/**
* @file client/renderer/TextAreaI18n.tsx
* @description textarea
*/
import React from 'react';
import {
autobind,
FormControlProps,
FormItem
} from '../../../amis-core/src/index';
import {Icon, Textarea} from '../../../amis-ui/src/index';
import cx from 'classnames';
/** 语料 key 正则表达式 */
export const corpusKeyReg =
/^i18n:[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/;
export interface TextareaI18nProps extends FormControlProps {}
class TextareaI18n extends React.Component<TextareaI18nProps> {
@autobind
onClickI18nBtn() {
const {value} = this.props;
if (corpusKeyReg.test(value!)) {
this.props?.onChange?.('');
return;
}
let _uuid = 'i18n:1189fb5d-ac5b-4558-b363-068ce5decc99';
this.props?.onChange?.(_uuid);
}
render() {
const {value, onChange, className} = this.props;
const isMatch = corpusKeyReg.test(value!);
return (
<>
<div
className={cx(
'TextareaI18n',
className,
'TextareaI18n-multi-container'
)}
>
<Textarea
value={value}
clearable={false}
onChange={onChange}
></Textarea>
{
<ul className={cx('TextareaI18n-footer')}>
<li
className={cx('TextareaI18n-footer-corpusIcon', {
'TextareaI18n-footer-highlight-corpusIcon': isMatch
})}
onClick={this.onClickI18nBtn}
>
<a data-tooltip="多语言" data-position="top">
<Icon icon="corpus-i18n" className="icon" />
</a>
</li>
</ul>
}
{isMatch ? (
<div
className={cx('TextareaI18n-overlay')}
onClick={this.onClickI18nBtn}
></div>
) : null}
</div>
</>
);
}
}
@FormItem({
type: 'textarea-i18n'
})
export class TextAreaI18nRenderer extends TextareaI18n {}

View File

@ -0,0 +1,142 @@
import {remarkTpl} from '../../src/index';
import {getSchemaTpl, setSchemaTpl} from '../../../amis-editor-core/src/index';
/** 国际化组件类型 */
enum I18nComptType {
InputText = 'input-text',
Textarea = 'textarea',
TextareaFormula = 'textarea-formula',
RichText = 'rich-text',
ButtonLabel = 'button-label'
}
/** 缓存已经重写过的 tpl 名称 */
const overwriteNames: {[propName: string]: boolean} = {};
/** 重写 schema tpl */
const overwriteSchemaTpl = (
name: string,
i18nType = I18nComptType.InputText,
options?: {[key: string]: any}
) => {
if (overwriteNames[name]) {
throw new Error(name + 'has been rewritten');
}
overwriteNames[name] = true;
const getType = () => {
if (i18nType === I18nComptType.InputText) {
return 'input-text-i18n';
}
if (i18nType === I18nComptType.Textarea) {
return 'textarea-i18n';
}
return 'input-text-i18n';
};
setSchemaTpl(
name,
getSchemaTpl(
name,
options
? options
: {
type: getType()
}
)
);
};
overwriteSchemaTpl('label');
overwriteSchemaTpl('btnLabel');
overwriteSchemaTpl('placeholder');
overwriteSchemaTpl('startPlaceholder');
overwriteSchemaTpl('endPlaceholder');
overwriteSchemaTpl('option');
overwriteSchemaTpl('description', I18nComptType.Textarea);
overwriteSchemaTpl('pageTitle');
overwriteSchemaTpl('pageSubTitle', I18nComptType.Textarea);
overwriteSchemaTpl('tpl:rich-text', I18nComptType.RichText);
overwriteSchemaTpl('prefix');
overwriteSchemaTpl('suffix');
overwriteSchemaTpl('unit');
overwriteSchemaTpl('optionsTip');
overwriteSchemaTpl('tableCellRemark');
overwriteSchemaTpl('title');
overwriteSchemaTpl('caption');
overwriteSchemaTpl('imageCaption');
overwriteSchemaTpl('inputBody');
overwriteSchemaTpl('stepSubTitle');
overwriteSchemaTpl('stepDescription');
overwriteSchemaTpl('taskNameLabel');
overwriteSchemaTpl('operationLabel');
overwriteSchemaTpl('statusLabel');
overwriteSchemaTpl('remarkLabel');
overwriteSchemaTpl('inputArrayItem');
overwriteSchemaTpl('actionPrevLabel');
overwriteSchemaTpl('actionNextLabel');
overwriteSchemaTpl('actionNextSaveLabel');
overwriteSchemaTpl('actionFinishLabel');
overwriteSchemaTpl('imgCaption', I18nComptType.Textarea);
overwriteSchemaTpl('taskRemark', I18nComptType.Textarea);
overwriteSchemaTpl('tooltip', I18nComptType.Textarea);
overwriteSchemaTpl('anchorTitle');
overwriteSchemaTpl('avatarText');
overwriteSchemaTpl('cardTitle');
overwriteSchemaTpl('cardSubTitle');
overwriteSchemaTpl('cardsPlaceholder');
overwriteSchemaTpl('cardDesc', I18nComptType.Textarea);
overwriteSchemaTpl('imageTitle');
overwriteSchemaTpl('imageDesc', I18nComptType.Textarea);
overwriteSchemaTpl('fetchSuccess');
overwriteSchemaTpl('fetchFailed');
overwriteSchemaTpl('saveOrderSuccess');
overwriteSchemaTpl('saveOrderFailed');
overwriteSchemaTpl('quickSaveSuccess');
overwriteSchemaTpl('quickSaveFailed');
overwriteSchemaTpl('saveSuccess');
overwriteSchemaTpl('saveFailed');
overwriteSchemaTpl('validateFailed');
overwriteSchemaTpl('tablePlaceholder');
overwriteSchemaTpl('collapseOpenHeader');
overwriteSchemaTpl('matrixColumnLabel');
overwriteSchemaTpl('matrixRowLabel');
overwriteSchemaTpl('matrixRowTitle');
overwriteSchemaTpl('submitText');
overwriteSchemaTpl('tpl:btnLabel', I18nComptType.ButtonLabel);
overwriteSchemaTpl('switchOption');
overwriteSchemaTpl('createBtnLabel');
overwriteSchemaTpl('tableCellPlaceholder');
overwriteSchemaTpl('addOnLabel');
overwriteSchemaTpl('onText');
overwriteSchemaTpl('offText');
overwriteSchemaTpl('propertyTitle');
overwriteSchemaTpl('propertyLabel');
overwriteSchemaTpl('propertyContent');
overwriteSchemaTpl('draggableTip');
overwriteSchemaTpl('deleteConfirmText');
overwriteSchemaTpl('optionsLabel');
overwriteSchemaTpl('checkAllLabel');
overwriteSchemaTpl('name');
overwriteSchemaTpl('anchorNavTitle');
setSchemaTpl(
'remark',
remarkTpl({
name: 'remark',
label: '控件提示',
labelRemark:
'在输入控件旁展示提示,注意控件宽度需设置,否则提示触发图标将自动换行',
i18nEnabled: true
})
);
setSchemaTpl(
'labelRemark',
remarkTpl({
name: 'labelRemark',
label: '标题提示',
labelRemark: '在标题旁展示提示',
i18nEnabled: true
})
);