mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
feat: locale tester (#6576)
* feat: locale tester * fix: locale * fix: acl.registerSnippet * feat: package.json * fix: locale
This commit is contained in:
parent
9eaa47863d
commit
6bb754612c
@ -0,0 +1,2 @@
|
|||||||
|
/node_modules
|
||||||
|
/src
|
@ -0,0 +1 @@
|
|||||||
|
# @nocobase/plugin-locale-tester
|
2
packages/plugins/@nocobase/plugin-locale-tester/client.d.ts
vendored
Normal file
2
packages/plugins/@nocobase/plugin-locale-tester/client.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './dist/client';
|
||||||
|
export { default } from './dist/client';
|
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./dist/client/index.js');
|
14
packages/plugins/@nocobase/plugin-locale-tester/package.json
Normal file
14
packages/plugins/@nocobase/plugin-locale-tester/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "@nocobase/plugin-locale-tester",
|
||||||
|
"displayName": "Locale tester",
|
||||||
|
"displayName.zh-CN": "翻译测试工具",
|
||||||
|
"version": "1.6.12",
|
||||||
|
"homepage": "https://github.com/nocobase/locales",
|
||||||
|
"main": "dist/server/index.js",
|
||||||
|
"dependencies": {},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@nocobase/client": "1.x",
|
||||||
|
"@nocobase/server": "1.x",
|
||||||
|
"@nocobase/test": "1.x"
|
||||||
|
}
|
||||||
|
}
|
2
packages/plugins/@nocobase/plugin-locale-tester/server.d.ts
vendored
Normal file
2
packages/plugins/@nocobase/plugin-locale-tester/server.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './dist/server';
|
||||||
|
export { default } from './dist/server';
|
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./dist/server/index.js');
|
249
packages/plugins/@nocobase/plugin-locale-tester/src/client/client.d.ts
vendored
Normal file
249
packages/plugins/@nocobase/plugin-locale-tester/src/client/client.d.ts
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// CSS modules
|
||||||
|
type CSSModuleClasses = { readonly [key: string]: string };
|
||||||
|
|
||||||
|
declare module '*.module.css' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.scss' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.sass' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.less' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.styl' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.stylus' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.pcss' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
declare module '*.module.sss' {
|
||||||
|
const classes: CSSModuleClasses;
|
||||||
|
export default classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS
|
||||||
|
declare module '*.css' { }
|
||||||
|
declare module '*.scss' { }
|
||||||
|
declare module '*.sass' { }
|
||||||
|
declare module '*.less' { }
|
||||||
|
declare module '*.styl' { }
|
||||||
|
declare module '*.stylus' { }
|
||||||
|
declare module '*.pcss' { }
|
||||||
|
declare module '*.sss' { }
|
||||||
|
|
||||||
|
// Built-in asset types
|
||||||
|
// see `src/node/constants.ts`
|
||||||
|
|
||||||
|
// images
|
||||||
|
declare module '*.apng' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.png' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.jpg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.jpeg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.jfif' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.pjpeg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.pjp' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.gif' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.svg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.ico' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.webp' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.avif' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// media
|
||||||
|
declare module '*.mp4' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.webm' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.ogg' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.mp3' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.wav' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.flac' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.aac' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.opus' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.mov' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.m4a' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.vtt' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fonts
|
||||||
|
declare module '*.woff' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.woff2' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.eot' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.ttf' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.otf' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other
|
||||||
|
declare module '*.webmanifest' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.pdf' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
declare module '*.txt' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wasm?init
|
||||||
|
declare module '*.wasm?init' {
|
||||||
|
const initWasm: (options?: WebAssembly.Imports) => Promise<WebAssembly.Instance>;
|
||||||
|
export default initWasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// web worker
|
||||||
|
declare module '*?worker' {
|
||||||
|
const workerConstructor: {
|
||||||
|
new(options?: { name?: string }): Worker;
|
||||||
|
};
|
||||||
|
export default workerConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?worker&inline' {
|
||||||
|
const workerConstructor: {
|
||||||
|
new(options?: { name?: string }): Worker;
|
||||||
|
};
|
||||||
|
export default workerConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?worker&url' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?sharedworker' {
|
||||||
|
const sharedWorkerConstructor: {
|
||||||
|
new(options?: { name?: string }): SharedWorker;
|
||||||
|
};
|
||||||
|
export default sharedWorkerConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?sharedworker&inline' {
|
||||||
|
const sharedWorkerConstructor: {
|
||||||
|
new(options?: { name?: string }): SharedWorker;
|
||||||
|
};
|
||||||
|
export default sharedWorkerConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?sharedworker&url' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?raw' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?url' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*?inline' {
|
||||||
|
const src: string;
|
||||||
|
export default src;
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useForm } from '@formily/react';
|
||||||
|
import { ActionProps, ISchema, Plugin, SchemaComponent, useAPIClient, useApp, useRequest } from '@nocobase/client';
|
||||||
|
import { Alert, App as AntdApp, Card, Spin } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { useT } from './locale';
|
||||||
|
|
||||||
|
function LocaleTester() {
|
||||||
|
const { data, loading } = useRequest<any>({
|
||||||
|
url: 'localeTester:get',
|
||||||
|
});
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'void',
|
||||||
|
name: 'root',
|
||||||
|
properties: {
|
||||||
|
test: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'FormV2',
|
||||||
|
properties: {
|
||||||
|
locale: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input.JSON',
|
||||||
|
'x-component-props': {
|
||||||
|
autoSize: { minRows: 20, maxRows: 30 },
|
||||||
|
},
|
||||||
|
default: data?.data?.locale,
|
||||||
|
title: t('Translations'),
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Action',
|
||||||
|
title: t('Submit'),
|
||||||
|
'x-use-component-props': 'useSubmitActionProps',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const useSubmitActionProps = () => {
|
||||||
|
const form = useForm();
|
||||||
|
const api = useAPIClient();
|
||||||
|
const { message } = AntdApp.useApp();
|
||||||
|
const app = useApp();
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'primary',
|
||||||
|
htmlType: 'submit',
|
||||||
|
async onClick() {
|
||||||
|
await form.submit();
|
||||||
|
const values = form.values;
|
||||||
|
await api.request({
|
||||||
|
url: 'localeTester:updateOrCreate',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
filterKeys: ['id'],
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
id: data?.data?.id,
|
||||||
|
locale: values.locale,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
message.success(app.i18n.t('Saved successfully!'));
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <Spin />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Alert
|
||||||
|
style={{ marginBottom: 12 }}
|
||||||
|
description={
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: t(
|
||||||
|
`Please go to <a target="_blank" href="https://github.com/nocobase/locales">nocobase/locales</a> to get the language file that needs translation, then paste it below and provide the translation.`,
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<SchemaComponent schema={schema} scope={{ useSubmitActionProps }} />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PluginLocaleTesterClient extends Plugin {
|
||||||
|
async afterAdd() {
|
||||||
|
// await this.app.pm.add()
|
||||||
|
}
|
||||||
|
|
||||||
|
async beforeLoad() {}
|
||||||
|
|
||||||
|
// You can get and modify the app instance here
|
||||||
|
async load() {
|
||||||
|
this.app.pluginSettingsManager.add('locale-tester', {
|
||||||
|
title: this.t('Locale tester'),
|
||||||
|
icon: 'TranslationOutlined',
|
||||||
|
Component: LocaleTester,
|
||||||
|
});
|
||||||
|
// this.app.addComponents({})
|
||||||
|
// this.app.addScopes({})
|
||||||
|
// this.app.addProvider()
|
||||||
|
// this.app.addProviders()
|
||||||
|
// this.app.router.add()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginLocaleTesterClient;
|
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
import pkg from './../../package.json';
|
||||||
|
import { useApp } from '@nocobase/client';
|
||||||
|
|
||||||
|
export function useT() {
|
||||||
|
const app = useApp();
|
||||||
|
return (str: string) => app.i18n.t(str, { ns: [pkg.name, 'client'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tStr(key: string) {
|
||||||
|
return `{{t(${JSON.stringify(key)}, { ns: ['${pkg.name}', 'client'], nsMode: 'fallback' })}}`;
|
||||||
|
}
|
11
packages/plugins/@nocobase/plugin-locale-tester/src/index.ts
Normal file
11
packages/plugins/@nocobase/plugin-locale-tester/src/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './server';
|
||||||
|
export { default } from './server';
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"Locale": "Locale",
|
||||||
|
"Locale tester": "Locale tester",
|
||||||
|
"Please go to <a target=\"_blank\" href=\"https://github.com/nocobase/locales\">nocobase/locales</a> to get the language file that needs translation, then paste it below and provide the translation.": "Please go to <a target=\"_blank\" href=\"https://github.com/nocobase/locales\">nocobase/locales</a> to get the language file that needs translation, then paste it below and provide the translation."
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"Translations": "翻译",
|
||||||
|
"Locale tester": "翻译测试工具",
|
||||||
|
"Please go to <a target=\"_blank\" href=\"https://github.com/nocobase/locales\">nocobase/locales</a> to get the language file that needs translation, then paste it below and provide the translation.": "请前往 <a target=\"_blank\" href=\"https://github.com/nocobase/locales\">nocobase/locales</a> 获取需要翻译的语言文件,粘贴到下方并进行翻译。"
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { defineCollection } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default defineCollection({
|
||||||
|
name: 'localeTester',
|
||||||
|
autoGenId: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'json',
|
||||||
|
name: 'locale',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { default } from './plugin';
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Plugin } from '@nocobase/server';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
export class PluginLocaleTesterServer extends Plugin {
|
||||||
|
async afterAdd() {}
|
||||||
|
|
||||||
|
async beforeLoad() {
|
||||||
|
this.app.acl.registerSnippet({
|
||||||
|
name: `pm.${this.name}`,
|
||||||
|
actions: ['localeTester:*'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async load() {
|
||||||
|
this.app.resourceManager.use(async (ctx, next) => {
|
||||||
|
await next();
|
||||||
|
const { resourceName, actionName } = ctx.action;
|
||||||
|
if (resourceName === 'app' && actionName === 'getLang') {
|
||||||
|
const repository = this.db.getRepository('localeTester');
|
||||||
|
const record = await repository.findOne();
|
||||||
|
const locale = record?.locale || {};
|
||||||
|
if (locale['cronstrue']) {
|
||||||
|
_.set(ctx.body, 'cronstrue', locale['cronstrue']);
|
||||||
|
}
|
||||||
|
if (locale['react-js-cron']) {
|
||||||
|
_.set(ctx.body, 'cron', locale['react-js-cron']);
|
||||||
|
}
|
||||||
|
Object.keys(locale).forEach((key) => {
|
||||||
|
if (key === 'cronstrue' || key === 'react-js-cron') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const value = locale[key];
|
||||||
|
_.set(ctx.body, ['resources', key], value);
|
||||||
|
const k = key.replace('@nocobase/', '').replace('@nocobase/plugin-', '');
|
||||||
|
_.set(ctx.body, ['resources', k], value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async install() {}
|
||||||
|
|
||||||
|
async afterEnable() {}
|
||||||
|
|
||||||
|
async afterDisable() {}
|
||||||
|
|
||||||
|
async remove() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PluginLocaleTesterServer;
|
@ -43,6 +43,7 @@
|
|||||||
"@nocobase/plugin-gantt": "1.6.12",
|
"@nocobase/plugin-gantt": "1.6.12",
|
||||||
"@nocobase/plugin-graph-collection-manager": "1.6.12",
|
"@nocobase/plugin-graph-collection-manager": "1.6.12",
|
||||||
"@nocobase/plugin-kanban": "1.6.12",
|
"@nocobase/plugin-kanban": "1.6.12",
|
||||||
|
"@nocobase/plugin-locale-tester": "1.6.12",
|
||||||
"@nocobase/plugin-localization": "1.6.12",
|
"@nocobase/plugin-localization": "1.6.12",
|
||||||
"@nocobase/plugin-logger": "1.6.12",
|
"@nocobase/plugin-logger": "1.6.12",
|
||||||
"@nocobase/plugin-map": "1.6.12",
|
"@nocobase/plugin-map": "1.6.12",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user