Browse Source

feat: support vscode i18n-ally plugin

vben 4 years ago
parent
commit
962f90de44
39 changed files with 263 additions and 259 deletions
  1. 1 1
      .vscode/extensions.json
  2. 32 48
      .vscode/settings.json
  3. 1 0
      CHANGELOG.zh_CN.md
  4. 6 2
      src/components/Drawer/src/BasicDrawer.tsx
  5. 3 3
      src/components/Drawer/src/props.ts
  6. 4 4
      src/components/Excel/src/ExportExcelModel.vue
  7. 4 4
      src/components/Form/src/FormAction.tsx
  8. 2 2
      src/components/Form/src/FormItem.tsx
  9. 4 4
      src/components/Form/src/helper.ts
  10. 2 2
      src/components/Menu/src/SearchInput.vue
  11. 3 3
      src/components/Modal/src/props.ts
  12. 6 6
      src/components/Table/src/components/TableSetting.vue
  13. 2 2
      src/components/Table/src/hooks/useColumns.ts
  14. 2 2
      src/components/Table/src/hooks/usePagination.tsx
  15. 3 3
      src/components/Upload/src/BasicUpload.vue
  16. 14 14
      src/components/Upload/src/UploadModal.vue
  17. 2 2
      src/components/Upload/src/UploadPreviewModal.vue
  18. 17 17
      src/components/Upload/src/data.tsx
  19. 4 4
      src/components/Upload/src/useUpload.ts
  20. 4 2
      src/components/Verify/src/ImgRotate.tsx
  21. 3 3
      src/components/Verify/src/props.ts
  22. 3 3
      src/layouts/default/footer/index.tsx
  23. 1 1
      src/layouts/default/header/LayoutHeader.tsx
  24. 9 3
      src/layouts/default/header/UserDropdown.tsx
  25. 5 5
      src/layouts/default/lock/LockAction.tsx
  26. 2 2
      src/layouts/default/multitabs/TabContent.tsx
  27. 7 7
      src/layouts/default/multitabs/data.ts
  28. 50 45
      src/layouts/default/setting/SettingDrawer.tsx
  29. 12 12
      src/layouts/default/setting/enum.ts
  30. 2 2
      src/store/modules/permission.ts
  31. 3 3
      src/store/modules/user.ts
  32. 12 12
      src/utils/http/axios/checkStatus.ts
  33. 9 9
      src/utils/http/axios/index.ts
  34. 2 2
      src/views/sys/error-log/DetailModal.vue
  35. 6 6
      src/views/sys/error-log/data.tsx
  36. 2 2
      src/views/sys/error-log/index.vue
  37. 10 10
      src/views/sys/exception/Exception.tsx
  38. 2 2
      src/views/sys/lock/index.vue
  39. 7 5
      src/views/sys/login/Login.vue

+ 1 - 1
.vscode/extensions.json

@@ -5,8 +5,8 @@
     "stylelint.vscode-stylelint",
     "DavidAnson.vscode-markdownlint",
     "esbenp.prettier-vscode",
-    "mrmlnc.vscode-scss",
     "mrmlnc.vscode-less",
+    "antfu.i18n-ally",
     "cpylua.language-postcss",
     "Orta.vscode-jest",
     "antfu.iconify",

+ 32 - 48
.vscode/settings.json

@@ -10,14 +10,13 @@
   "editor.smoothScrolling": true,
   "editor.cursorBlinking": "phase",
   "editor.cursorSmoothCaretAnimation": true,
-  "editor.detectIndentation": false, // vscode默认启用了根据文件类型自动设置tabsize的选项
+  "editor.detectIndentation": false,
   "diffEditor.ignoreTrimWhitespace": false,
-  "editor.formatOnPaste": true, //自动格式化粘贴的内容
-  "editor.formatOnSave": true, //保存自动格式化
+  "editor.formatOnPaste": true,
+  "editor.formatOnSave": true,
   "editor.suggestSelection": "first",
   "editor.trimAutoWhitespace": true,
   "editor.quickSuggestions": {
-    //   快速提示
     "other": true,
     "comments": true,
     "strings": true
@@ -25,41 +24,33 @@
   //===========================================
   //============= Other =======================
   //===========================================
-  "breadcrumbs.enabled": true, // 启用/禁用导航路径
-  "open-in-browser.default": "chrome", // 默认浏览器
+  "breadcrumbs.enabled": true,
+  "open-in-browser.default": "chrome",
   //===========================================
   //============= emmet =======================
   //===========================================
-  "emmet.triggerExpansionOnTab": true, // 配置emmet是否启用tab展开缩写
+  "emmet.triggerExpansionOnTab": true,
   "emmet.showAbbreviationSuggestions": true,
   "emmet.showExpandedAbbreviation": "always",
   "emmet.syntaxProfiles": {
-    // 配置emmet对文件类型的支持,比如vue后缀文件按照html文件来进行emmet扩写
     "vue-html": "html",
     "vue": "html",
     "javascript": "javascriptreact",
-    // xml类型文件默认都是单引号,开启对非单引号的emmet识别
     "xml": {
       "attr_quotes": "single"
     }
   },
   "emmet.includeLanguages": {
-    // 在react的jsx中添加对emmet的支持
     "jsx-sublime-babel-tags": "javascriptreact"
   },
   //===========================================
   //============= files =======================
   //===========================================
-  // "files.autoSave": "onWindowChange", // 窗口失去焦点自动保存
-  // "files.autoSaveDelay": 1000, // 自动保存时间
-  "files.trimTrailingWhitespace": true, // 启用后,将在保存文件时剪裁尾随空格。
-  // 文件末尾插入新行
+  "files.trimTrailingWhitespace": true,
   "files.insertFinalNewline": true,
-  // 删除文件末尾多余的新行
   "files.trimFinalNewlines": true,
   "files.eol": "\n",
   "search.exclude": {
-    // 搜索排除这些区域
     "**/node_modules": true,
     "**/*.log": true,
     "**/*.log*": true,
@@ -76,8 +67,6 @@
     "**/tmp": true
   },
   "files.exclude": {
-    // 排除文件搜索区域,比如node_modules(默认设置已经屏蔽了)
-    // "**/node_modules": true,
     "**/bower_components": true,
     "**/.idea": true,
     "**/yarn.lock": true,
@@ -100,7 +89,6 @@
     "**/yarn.lock": true
   },
   "files.associations": {
-    // 配置文件关联,以便启用对应的智能提示,比如wxss使用css
     "*.vue": "vue",
     "*.wxss": "css"
   },
@@ -109,13 +97,11 @@
   "css.validate": true,
   "less.validate": true,
   "scss.validate": true,
-  // ↓↓↓↓↓↓↓↓↓↓↓↓↓ 以下为插件设置 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
-  // ↓↓↓↓↓↓↓↓↓↓↓↓↓ 需要安装对应的插件 ↓↓↓↓↓↓↓↓↓↓↓↓
   // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
   // ===========================================
   // ================ Eslint ===================
   // ===========================================
-  "eslint.enable": true, // 是否开启eslint
+  "eslint.enable": true,
   "eslint.options": {
     // 配置
     "plugins": [
@@ -126,53 +112,41 @@
       "typescript"
     ]
   },
-  "eslint.autoFixOnSave": true, // 保存自动格式化
+  "eslint.autoFixOnSave": true,
   // ===========================================
   // ================ Vetur ====================
   // ===========================================
   "vetur.experimental.templateInterpolationService": true,
   "vetur.format.options.tabSize": 2,
-  "vetur.format.defaultFormatter.html": "js-beautify-html", // 使用js-beautify-html格式化
-  "vetur.format.defaultFormatter.scss": "prettier", // 使用js-beautify-html格式化
-  "vetur.format.defaultFormatter.css": "prettier", // 使用js-beautify-html格式化
-  //   "vetur.format.defaultFormatter.html": "prettyhtml",
+  "vetur.format.defaultFormatter.html": "js-beautify-html",
+  "vetur.format.defaultFormatter.scss": "prettier",
+  "vetur.format.defaultFormatter.css": "prettier",
   "vetur.format.defaultFormatter.ts": "prettier-tslint",
   "vetur.format.defaultFormatter.js": "prettier",
-    "vetur.languageFeatures.codeActions": false,
-  // "vetur.useWorkspaceDependencies": true,
+  "vetur.languageFeatures.codeActions": false,
   "vetur.format.defaultFormatterOptions": {
     "js-beautify-html": {
-      //   "wrap_attributes": "force-aligned", // 单行
-      "wrap_attributes": "force-expand-multiline" // 属性强制折行对齐 多行
+      "wrap_attributes": "force-expand-multiline"
     },
     "prettier": {
-      "eslintIntegration": true, // 让perttier使用eslint的格式进行检查
-      "arrowParens": "always", // 箭头函数参数括号 默认avoid 可选 avoid | always
-      "semi": false, // 使用分号, 默认true
-      "singleQuote": true // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
+      "eslintIntegration": true,
+      "arrowParens": "always",
+      "semi": false,
+      "singleQuote": true
     }
   },
-  // 函数注释
-  //===========================================
-  //============= Code Runner =================
-  //===========================================
   "javascript.updateImportsOnFileMove.enabled": "never",
   "liveServer.settings.donotShowInfoMsg": true,
-  "[javascript]": {
-    "editor.defaultFormatter": "esbenp.prettier-vscode"
-  },
-  "terminal.integrated.rendererType": "dom", //关闭liveserver提示
+  "terminal.integrated.rendererType": "dom",
   "telemetry.enableCrashReporter": false,
   "telemetry.enableTelemetry": false,
   "workbench.settings.enableNaturalLanguageSearch": false,
-  // 引用路径设置
   "path-intellisense.mappings": {
     "/@/": "${workspaceRoot}/src"
   },
   "prettier.requireConfig": true,
   "typescript.updateImportsOnFileMove.enabled": "always",
   "workbench.sideBar.location": "left",
-
   "[javascriptreact]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"
   },
@@ -203,8 +177,18 @@
   "[markdown]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"
   },
-
   "editor.codeActionsOnSave": {
     "source.fixAll.eslint": true
-  }
-}
+  },
+  "i18n-ally.localesPaths": [
+    "src/locales/lang",
+  ],
+  "i18n-ally.keystyle": "nested",
+  "i18n-ally.sortKeys": true,
+  "i18n-ally.namespace": true,
+  "i18n-ally.pathMatcher":"{locale}/{namespaces}.{ext}",
+  "i18n-ally.enabledParsers": [
+    "ts"
+  ],
+  "i18n-ally.sourceLanguage": "zh"
+}

+ 1 - 0
CHANGELOG.zh_CN.md

@@ -3,6 +3,7 @@
 ### ✨ Features
 
 - 还原 antdv 默认 loading,重构 `Loading` 组件,增加`useLoading`和`v-loading`指令。并增加示例
+- i18n 支持 vscode `i18n-ally`插件
 
 ### 🎫 Chores
 

+ 6 - 2
src/components/Drawer/src/BasicDrawer.tsx

@@ -29,7 +29,7 @@ export default defineComponent({
     const visibleRef = ref(false);
     const propsRef = ref<Partial<Nullable<DrawerProps>>>(null);
 
-    const { t } = useI18n('component.drawer');
+    const { t } = useI18n();
 
     const getMergeProps = computed(
       (): DrawerProps => {
@@ -228,7 +228,11 @@ export default defineComponent({
             default: () => (
               <>
                 <div ref={scrollRef} style={unref(getScrollContentStyle)}>
-                  <Loading absolute tip={t('loadingText')} loading={unref(getLoading)} />
+                  <Loading
+                    absolute
+                    tip={t('component.drawer.loadingText')}
+                    loading={unref(getLoading)}
+                  />
                   {getSlot(slots)}
                 </div>
                 {renderFooter()}

+ 3 - 3
src/components/Drawer/src/props.ts

@@ -2,7 +2,7 @@ import type { PropType } from 'vue';
 
 import { useI18n } from '/@/hooks/web/useI18n';
 import { propTypes } from '/@/utils/propTypes';
-const { t } = useI18n('component.drawer');
+const { t } = useI18n();
 
 export const footerProps = {
   confirmLoading: propTypes.bool,
@@ -11,13 +11,13 @@ export const footerProps = {
    */
   showCancelBtn: propTypes.bool.def(true),
   cancelButtonProps: Object as PropType<any>,
-  cancelText: propTypes.string.def(t('cancelText')),
+  cancelText: propTypes.string.def(t('component.drawer.cancelText')),
   /**
    * @description: Show confirmation button
    */
   showOkBtn: propTypes.bool.def(true),
   okButtonProps: propTypes.any,
-  okText: propTypes.string.def(t('okText')),
+  okText: propTypes.string.def(t('component.drawer.okText')),
   okType: propTypes.string.def('primary'),
   showFooter: propTypes.bool,
   footerHeight: {

+ 4 - 4
src/components/Excel/src/ExportExcelModel.vue

@@ -1,7 +1,7 @@
 <template>
   <BasicModal
     v-bind="$attrs"
-    :title="t('exportModalTitle')"
+    :title="t('component.excel.exportModalTitle')"
     @ok="handleOk"
     @register="registerModal"
   >
@@ -21,19 +21,19 @@
 
   import { useI18n } from '/@/hooks/web/useI18n';
 
-  const { t } = useI18n('component.excel');
+  const { t } = useI18n();
 
   const schemas: FormSchema[] = [
     {
       field: 'filename',
       component: 'Input',
-      label: t('fileName'),
+      label: t('component.excel.fileName'),
       rules: [{ required: true }],
     },
     {
       field: 'bookType',
       component: 'Select',
-      label: t('fileType'),
+      label: t('component.excel.fileType'),
       defaultValue: 'xlsx',
       rules: [{ required: true }],
       componentProps: {

+ 4 - 4
src/components/Form/src/FormAction.tsx

@@ -9,7 +9,7 @@ import { getSlot } from '/@/utils/helper/tsxHelper';
 import { useI18n } from '/@/hooks/web/useI18n';
 import { propTypes } from '/@/utils/propTypes';
 
-const { t } = useI18n('component.form');
+const { t } = useI18n();
 
 export default defineComponent({
   name: 'BasicFormAction',
@@ -38,14 +38,14 @@ export default defineComponent({
   setup(props, { slots, emit }) {
     const getResetBtnOptionsRef = computed(() => {
       return {
-        text: t('resetButton'),
+        text: t('component.form.resetButton'),
         ...props.resetButtonOptions,
       };
     });
 
     const getSubmitBtnOptionsRef = computed(() => {
       return {
-        text: t('submitButton'),
+        text: t('component.form.submitButton'),
         // htmlType: 'submit',
         ...props.submitButtonOptions,
       };
@@ -77,7 +77,7 @@ export default defineComponent({
         <Button type="default" class="mr-2" onClick={toggleAdvanced}>
           {() => (
             <>
-              {isAdvanced ? t('putAway') : t('unfold')}
+              {isAdvanced ? t('component.form.putAway') : t('component.form.unfold')}
               <BasicArrow expand={!isAdvanced} top />
             </>
           )}

+ 2 - 2
src/components/Form/src/FormItem.tsx

@@ -47,7 +47,7 @@ export default defineComponent({
     },
   },
   setup(props, { slots }) {
-    const { t } = useI18n('component.form');
+    const { t } = useI18n();
     // @ts-ignore
     const itemLabelWidthRef = useItemLabelWidth(toRef(props, 'schema'), toRef(props, 'formProps'));
 
@@ -175,7 +175,7 @@ export default defineComponent({
       const characterInx = rules.findIndex((val) => val.max);
       if (characterInx !== -1 && !rules[characterInx].validator) {
         rules[characterInx].message =
-          rules[characterInx].message || t('maxTip', [rules[characterInx].max]);
+          rules[characterInx].message || t('component.form.maxTip', [rules[characterInx].max]);
       }
       return rules;
     }

+ 4 - 4
src/components/Form/src/helper.ts

@@ -1,17 +1,17 @@
 import type { ComponentType } from './types/index';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('component.form');
+const { t } = useI18n();
 
 /**
  * @description: 生成placeholder
  */
 export function createPlaceholderMessage(component: ComponentType) {
   if (component.includes('Input') || component.includes('Complete')) {
-    return t('input');
+    return t('component.form.input');
   }
   if (component.includes('Picker')) {
-    return t('choose');
+    return t('component.form.choose');
   }
   if (
     component.includes('Select') ||
@@ -21,7 +21,7 @@ export function createPlaceholderMessage(component: ComponentType) {
     component.includes('Switch')
   ) {
     // return `请选择${label}`;
-    return t('choose');
+    return t('component.form.choose');
   }
   return '';
 }

+ 2 - 2
src/components/Menu/src/SearchInput.vue

@@ -1,7 +1,7 @@
 <template>
   <section class="menu-search-input" @Click="handleClick" :class="searchClass">
     <a-input-search
-      :placeholder="t('search')"
+      :placeholder="t('component.menu.search')"
       class="menu-search-input__search"
       allowClear
       @change="handleChange"
@@ -29,7 +29,7 @@
       },
     },
     setup(props, { emit }) {
-      const { t } = useI18n('component.menu');
+      const { t } = useI18n();
 
       const [debounceEmitChange] = useDebounce(emitChange, 200);
 

+ 3 - 3
src/components/Modal/src/props.ts

@@ -3,15 +3,15 @@ import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
 
 import { useI18n } from '/@/hooks/web/useI18n';
 import { propTypes } from '/@/utils/propTypes';
-const { t } = useI18n('component.modal');
+const { t } = useI18n();
 
 export const modalProps = {
   visible: propTypes.bool,
   // open drag
   draggable: propTypes.bool.def(true),
   centered: propTypes.bool,
-  cancelText: propTypes.string.def(t('cancelText')),
-  okText: propTypes.string.def(t('okText')),
+  cancelText: propTypes.string.def(t('component.modal.cancelText')),
+  okText: propTypes.string.def(t('component.modal.okText')),
 
   closeFunc: Function as PropType<() => Promise<boolean>>,
 };

+ 6 - 6
src/components/Table/src/components/TableSetting.vue

@@ -4,27 +4,27 @@
 
     <Tooltip placement="top" v-if="getSetting.redo">
       <template #title>
-        <span>{{ t('settingRedo') }}</span>
+        <span>{{ t('component.table.settingRedo') }}</span>
       </template>
       <RedoOutlined @click="redo" />
     </Tooltip>
 
     <Tooltip placement="top" v-if="getSetting.size">
       <template #title>
-        <span>{{ t('settingDens') }}</span>
+        <span>{{ t('component.table.settingDens') }}</span>
       </template>
       <Dropdown placement="bottomCenter" :trigger="['click']">
         <ColumnHeightOutlined />
         <template #overlay>
           <Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
             <MenuItem key="default">
-              <span>{{ t('settingDensDefault') }}</span>
+              <span>{{ t('component.table.settingDensDefault') }}</span>
             </MenuItem>
             <MenuItem key="middle">
-              <span>{{ t('settingDensMiddle') }}</span>
+              <span>{{ t('component.table.settingDensMiddle') }}</span>
             </MenuItem>
             <MenuItem key="small">
-              <span>{{ t('settingDensSmall') }}</span>
+              <span>{{ t('component.table.settingDensSmall') }}</span>
             </MenuItem>
           </Menu>
         </template>
@@ -140,7 +140,7 @@
         defaultCheckList: [],
       });
 
-      const { t } = useI18n('component.table');
+      const { t } = useI18n();
 
       watchEffect(() => {
         const columns = table.getColumns();

+ 2 - 2
src/components/Table/src/hooks/useColumns.ts

@@ -6,7 +6,7 @@ import { PAGE_SIZE } from '../const';
 import { useProps } from './useProps';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('component.table');
+const { t } = useI18n();
 export function useColumns(
   refProps: ComputedRef<BasicTableProps>,
   getPaginationRef: ComputedRef<false | PaginationProps>
@@ -44,7 +44,7 @@ export function useColumns(
       columns.unshift({
         flag: 'INDEX',
         width: 50,
-        title: t('index'),
+        title: t('component.table.index'),
         align: 'center',
         customRender: ({ index }) => {
           const getPagination = unref(getPaginationRef);

+ 2 - 2
src/components/Table/src/hooks/usePagination.tsx

@@ -10,7 +10,7 @@ import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const';
 import { useProps } from './useProps';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('component.table');
+const { t } = useI18n();
 export function usePagination(refProps: ComputedRef<BasicTableProps>) {
   const configRef = ref<PaginationProps>({});
   const { propsRef } = useProps(refProps);
@@ -25,7 +25,7 @@ export function usePagination(refProps: ComputedRef<BasicTableProps>) {
       pageSize: PAGE_SIZE,
       size: 'small',
       defaultPageSize: PAGE_SIZE,
-      showTotal: (total) => t('total', { total }),
+      showTotal: (total) => t('component.table.total', { total }),
       showSizeChanger: true,
       pageSizeOptions: PAGE_SIZE_OPTIONS,
       itemRender: ({ page, type, originalElement }) => {

+ 3 - 3
src/components/Upload/src/BasicUpload.vue

@@ -2,11 +2,11 @@
   <div>
     <a-button-group>
       <a-button type="primary" @click="openUploadModal" preIcon="ant-design:cloud-upload-outlined">
-        {{ t('upload') }}
+        {{ t('component.upload.upload') }}
       </a-button>
       <Tooltip placement="bottom" v-if="showPreview">
         <template #title>
-          {{ t('uploaded') }}
+          {{ t('component.upload.uploaded') }}
           <template v-if="fileListRef.length">{{ fileListRef.length }}</template>
         </template>
         <a-button @click="openPreviewModal">
@@ -46,7 +46,7 @@
     components: { UploadModal, UploadPreviewModal, Icon, Tooltip },
     props: uploadContainerProps,
     setup(props, { emit, attrs }) {
-      const { t } = useI18n('component.upload');
+      const { t } = useI18n();
       // 上传modal
       const [registerUploadModal, { openModal: openUploadModal }] = useModal();
 

+ 14 - 14
src/components/Upload/src/UploadModal.vue

@@ -1,8 +1,8 @@
 <template>
   <BasicModal
     width="800px"
-    :title="t('upload')"
-    :okText="t('save')"
+    :title="t('component.upload.upload')"
+    :okText="t('component.upload.save')"
     v-bind="$attrs"
     @register="register"
     @ok="handleOk"
@@ -31,7 +31,7 @@
         :before-upload="beforeUpload"
         class="upload-modal-toolbar__btn"
       >
-        <a-button type="primary"> {{ t('choose') }} </a-button>
+        <a-button type="primary"> {{ t('component.upload.choose') }} </a-button>
       </Upload>
     </div>
     <FileList :dataSource="fileListRef" :columns="columns" :actionColumn="actionColumn" />
@@ -64,7 +64,7 @@
     props: basicProps,
     setup(props, { emit }) {
       //   是否正在上传
-      const { t } = useI18n('component.upload');
+      const { t } = useI18n();
 
       const isUploadingRef = ref(false);
       const fileListRef = ref<FileItem[]>([]);
@@ -105,10 +105,10 @@
           (item) => item.status === UploadResultStatus.ERROR
         );
         return isUploadingRef.value
-          ? t('uploading')
+          ? t('component.upload.uploading')
           : someError
-          ? t('reUploadFailed')
-          : t('startUpload');
+          ? t('component.upload.reUploadFailed')
+          : t('component.upload.startUpload');
       });
 
       // 上传前校验
@@ -119,13 +119,13 @@
 
         // 设置最大值,则判断
         if (maxSize && file.size / 1024 / 1024 >= maxSize) {
-          createMessage.error(t('maxSizeMultiple', [maxSize]));
+          createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
           return false;
         }
 
         // 设置类型,则判断
         if (accept.length > 0 && !checkFileType(file, accept)) {
-          createMessage.error!(t('acceptUpload', [accept.join(',')]));
+          createMessage.error!(t('acomponent.upload.cceptUpload', [accept.join(',')]));
           return false;
         }
         const commonItem = {
@@ -206,7 +206,7 @@
       async function handleStartUpload() {
         const { maxNumber } = props;
         if (fileListRef.value.length > maxNumber) {
-          return createMessage.warning(t('maxNumber', [maxNumber]));
+          return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
         }
         try {
           isUploadingRef.value = true;
@@ -233,10 +233,10 @@
         const { maxNumber } = props;
 
         if (fileListRef.value.length > maxNumber) {
-          return createMessage.warning(t('maxNumber', [maxNumber]));
+          return createMessage.warning(t('component.upload.maxNumber', [maxNumber]));
         }
         if (isUploadingRef.value) {
-          return createMessage.warning(t('saveWarn'));
+          return createMessage.warning(t('component.upload.saveWarn'));
         }
         const fileList: string[] = [];
 
@@ -248,7 +248,7 @@
         }
         // 存在一个上传成功的即可保存
         if (fileList.length <= 0) {
-          return createMessage.warning(t('saveError'));
+          return createMessage.warning(t('component.upload.saveError'));
         }
         fileListRef.value = [];
         closeModal();
@@ -261,7 +261,7 @@
           fileListRef.value = [];
           return true;
         } else {
-          createMessage.warning(t('uploadWait'));
+          createMessage.warning(t('component.upload.uploadWait'));
           return false;
         }
       }

+ 2 - 2
src/components/Upload/src/UploadPreviewModal.vue

@@ -1,7 +1,7 @@
 <template>
   <BasicModal
     width="800px"
-    :title="t('preview')"
+    :title="t('component.upload.preview')"
     wrapClassName="upload-preview-modal"
     v-bind="$attrs"
     @register="register"
@@ -30,7 +30,7 @@
     props: previewProps,
     setup(props, { emit }) {
       const [register, { closeModal }] = useModalInner();
-      const { t } = useI18n('component.upload');
+      const { t } = useI18n();
 
       const fileListRef = ref<PreviewFileItem[]>([]);
       watch(

+ 17 - 17
src/components/Upload/src/data.tsx

@@ -7,14 +7,14 @@ import { Progress, Tag } from 'ant-design-vue';
 import TableAction from '/@/components/Table/src/components/TableAction';
 
 import { useI18n } from '/@/hooks/web/useI18n';
-const { t } = useI18n('component.upload');
+const { t } = useI18n();
 
 // 文件上传列表
 export function createTableColumns(): BasicColumn[] {
   return [
     {
       dataIndex: 'thumbUrl',
-      title: t('legend'),
+      title: t('component.upload.legend'),
       width: 100,
       customRender: ({ record }) => {
         const { thumbUrl, type } = (record as FileItem) || {};
@@ -23,7 +23,7 @@ export function createTableColumns(): BasicColumn[] {
     },
     {
       dataIndex: 'name',
-      title: t('fileName'),
+      title: t('component.upload.fileName'),
       align: 'left',
       customRender: ({ text, record }) => {
         const { percent, status: uploadStatus } = (record as FileItem) || {};
@@ -47,7 +47,7 @@ export function createTableColumns(): BasicColumn[] {
     },
     {
       dataIndex: 'size',
-      title: t('fileSize'),
+      title: t('component.upload.fileSize'),
       width: 100,
       customRender: ({ text = 0 }) => {
         return text && (text / 1024).toFixed(2) + 'KB';
@@ -60,15 +60,15 @@ export function createTableColumns(): BasicColumn[] {
     // },
     {
       dataIndex: 'status',
-      title: t('fileStatue'),
+      title: t('component.upload.fileStatue'),
       width: 100,
       customRender: ({ text }) => {
         if (text === UploadResultStatus.SUCCESS) {
-          return <Tag color="green">{() => t('uploadSuccess')}</Tag>;
+          return <Tag color="green">{() => t('component.upload.uploadSuccess')}</Tag>;
         } else if (text === UploadResultStatus.ERROR) {
-          return <Tag color="red">{() => t('uploadError')}</Tag>;
+          return <Tag color="red">{() => t('component.upload.uploadError')}</Tag>;
         } else if (text === UploadResultStatus.UPLOADING) {
-          return <Tag color="blue">{() => t('uploading')}</Tag>;
+          return <Tag color="blue">{() => t('component.upload.uploading')}</Tag>;
         }
 
         return text;
@@ -79,20 +79,20 @@ export function createTableColumns(): BasicColumn[] {
 export function createActionColumn(handleRemove: Function, handlePreview: Function): BasicColumn {
   return {
     width: 120,
-    title: t('operating'),
+    title: t('component.upload.operating'),
     dataIndex: 'action',
     fixed: false,
     customRender: ({ record }) => {
       const actions: ActionItem[] = [
         {
-          label: t('del'),
+          label: t('component.upload.del'),
           color: 'error',
           onClick: handleRemove.bind(null, record),
         },
       ];
       if (checkImgType(record)) {
         actions.unshift({
-          label: t('preview'),
+          label: t('component.upload.preview'),
           onClick: handlePreview.bind(null, record),
         });
       }
@@ -105,7 +105,7 @@ export function createPreviewColumns(): BasicColumn[] {
   return [
     {
       dataIndex: 'url',
-      title: t('legend'),
+      title: t('component.upload.legend'),
       width: 100,
       customRender: ({ record }) => {
         const { url, type } = (record as PreviewFileItem) || {};
@@ -116,7 +116,7 @@ export function createPreviewColumns(): BasicColumn[] {
     },
     {
       dataIndex: 'name',
-      title: t('fileName'),
+      title: t('component.upload.fileName'),
       align: 'left',
     },
   ];
@@ -133,7 +133,7 @@ export function createPreviewActionColumn({
 }): BasicColumn {
   return {
     width: 160,
-    title: t('operating'),
+    title: t('component.upload.operating'),
     dataIndex: 'action',
     fixed: false,
     customRender: ({ record }) => {
@@ -141,18 +141,18 @@ export function createPreviewActionColumn({
 
       const actions: ActionItem[] = [
         {
-          label: t('del'),
+          label: t('component.upload.del'),
           color: 'error',
           onClick: handleRemove.bind(null, record),
         },
         {
-          label: t('download'),
+          label: t('component.upload.download'),
           onClick: handleDownload.bind(null, record),
         },
       ];
       if (isImgTypeByName(url)) {
         actions.unshift({
-          label: t('preview'),
+          label: t('component.upload.preview'),
           onClick: handlePreview.bind(null, record),
         });
       }

+ 4 - 4
src/components/Upload/src/useUpload.ts

@@ -1,6 +1,6 @@
 import { Ref, unref, computed } from 'vue';
 import { useI18n } from '/@/hooks/web/useI18n';
-const { t } = useI18n('component.upload');
+const { t } = useI18n();
 export function useUploadType({
   acceptRef,
   //   uploadTypeRef,
@@ -38,17 +38,17 @@ export function useUploadType({
 
     const accept = unref(acceptRef);
     if (accept.length > 0) {
-      helpTexts.push(t('accept', [accept.join(',')]));
+      helpTexts.push(t('component.upload.accept', [accept.join(',')]));
     }
 
     const maxSize = unref(maxSizeRef);
     if (maxSize) {
-      helpTexts.push(t('maxSize', [maxSize]));
+      helpTexts.push(t('component.upload.maxSize', [maxSize]));
     }
 
     const maxNumber = unref(maxNumberRef);
     if (maxNumber && maxNumber !== Infinity) {
-      helpTexts.push(t('maxNumber', [maxNumber]));
+      helpTexts.push(t('component.upload.maxNumber', [maxNumber]));
     }
     return helpTexts.join(',');
   });

+ 4 - 2
src/components/Verify/src/ImgRotate.tsx

@@ -30,7 +30,7 @@ export default defineComponent({
       endTime: 0,
       draged: false,
     });
-    const { t } = useI18n('component.verify');
+    const { t } = useI18n();
 
     watch(
       () => state.isPassing,
@@ -146,7 +146,9 @@ export default defineComponent({
             />
             {state.showTip && (
               <span class={[`ir-dv-img__tip`, state.isPassing ? 'success' : 'error']}>
-                {state.isPassing ? t('time', { time: time.toFixed(1) }) : t('error')}
+                {state.isPassing
+                  ? t('component.verify.time', { time: time.toFixed(1) })
+                  : t('component.verify.error')}
               </span>
             )}
             {!state.showTip && !state.draged && (

+ 3 - 3
src/components/Verify/src/props.ts

@@ -1,7 +1,7 @@
 import type { PropType } from 'vue';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('component.verify');
+const { t } = useI18n();
 export const basicProps = {
   value: {
     type: Boolean as PropType<boolean>,
@@ -15,11 +15,11 @@ export const basicProps = {
 
   text: {
     type: [String] as PropType<string>,
-    default: t('dragText'),
+    default: t('component.verify.dragText'),
   },
   successText: {
     type: [String] as PropType<string>,
-    default: t('successText'),
+    default: t('component.verify.successText'),
   },
   height: {
     type: [Number, String] as PropType<number | string>,

+ 3 - 3
src/layouts/default/footer/index.tsx

@@ -13,16 +13,16 @@ import { useI18n } from '/@/hooks/web/useI18n';
 export default defineComponent({
   name: 'LayoutContent',
   setup() {
-    const { t } = useI18n('layout.footer');
+    const { t } = useI18n();
     return () => {
       return (
         <Layout.Footer class="layout-footer">
           {() => (
             <>
               <div class="layout-footer__links">
-                <a onClick={() => openWindow(SITE_URL)}>{t('onlinePreview')}</a>
+                <a onClick={() => openWindow(SITE_URL)}>{t('layout.footer.onlinePreview')}</a>
                 <GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
-                <a onClick={() => openWindow(DOC_URL)}>{t('onlineDocument')}</a>
+                <a onClick={() => openWindow(DOC_URL)}>{t('layout.footer.onlineDocument')}</a>
               </div>
               <div>Copyright &copy;2020 Vben Admin</div>
             </>

+ 1 - 1
src/layouts/default/header/LayoutHeader.tsx

@@ -66,7 +66,7 @@ export default defineComponent({
     const logoWidthRef = ref(200);
     const logoRef = ref<ComponentRef>(null);
     const { refreshPage } = useTabs();
-    const { t } = useI18n('layout.header');
+    const { t } = useI18n();
 
     const { getShowTopMenu, getShowHeaderTrigger, getSplit, getTopMenuAlign } = useMenuSetting();
 

+ 9 - 3
src/layouts/default/header/UserDropdown.tsx

@@ -44,7 +44,7 @@ const MenuItem: FunctionalComponent<MenuItemProps> = (props) => {
 export default defineComponent({
   name: 'UserDropdown',
   setup() {
-    const { t } = useI18n('layout.header');
+    const { t } = useI18n();
     const { getShowDoc } = useHeaderSetting();
 
     const getUserInfo = computed(() => {
@@ -91,12 +91,18 @@ export default defineComponent({
         <Menu onClick={handleMenuClick}>
           {() => (
             <>
-              {showDoc && <MenuItem key="doc" text={t('dropdownItemDoc')} icon="gg:loadbar-doc" />}
+              {showDoc && (
+                <MenuItem
+                  key="doc"
+                  text={t('layout.header.dropdownItemDoc')}
+                  icon="gg:loadbar-doc"
+                />
+              )}
               {/* @ts-ignore */}
               {showDoc && <Menu.Divider />}
               <MenuItem
                 key="loginOut"
-                text={t('dropdownItemLoginOut')}
+                text={t('layout.header.dropdownItemLoginOut')}
                 icon="ant-design:poweroff-outlined"
               />
             </>

+ 5 - 5
src/layouts/default/lock/LockAction.tsx

@@ -15,7 +15,7 @@ const prefixCls = 'lock-modal';
 export default defineComponent({
   name: 'LockModal',
   setup(_, { attrs }) {
-    const { t } = useI18n('layout.header');
+    const { t } = useI18n();
     const [register, { closeModal }] = useModalInner();
 
     const [registerForm, { validateFields, resetFields }] = useForm({
@@ -23,7 +23,7 @@ export default defineComponent({
       schemas: [
         {
           field: 'password',
-          label: t('lockScreenPassword'),
+          label: t('layout.header.lockScreenPassword'),
           component: 'InputPassword',
           required: true,
         },
@@ -53,7 +53,7 @@ export default defineComponent({
     return () => (
       <BasicModal
         footer={null}
-        title={t('lockScreen')}
+        title={t('layout.header.lockScreen')}
         {...attrs}
         class={prefixCls}
         onRegister={register}
@@ -69,10 +69,10 @@ export default defineComponent({
 
             <div class={`${prefixCls}__footer`}>
               <Button type="primary" block class="mt-2" onClick={lock}>
-                {() => t('lockScreenBtn')}
+                {() => t('layout.header.lockScreenBtn')}
               </Button>
               <Button block class="mt-2" onClick={lock.bind(null, false)}>
-                {() => t('notLockScreenPassword')}
+                {() => t('layout.header.notLockScreenPassword')}
               </Button>
             </div>
           </div>

+ 2 - 2
src/layouts/default/multitabs/TabContent.tsx

@@ -59,7 +59,7 @@ export default defineComponent({
     },
   },
   setup(props) {
-    const { t } = useI18n('layout.multipleTab');
+    const { t } = useI18n();
     const { getShowMenu } = useMenuSetting();
     const { getShowHeader } = useHeaderSetting();
     const { getShowQuick } = useMultipleTabSetting();
@@ -76,7 +76,7 @@ export default defineComponent({
 
     return () => {
       const scaleAction = getScaleAction(
-        unref(getIsScale) ? t('putAway') : t('unfold'),
+        unref(getIsScale) ? t('layout.multipleTab.putAway') : t('layout.multipleTab.unfold'),
         unref(getIsScale)
       );
       const dropMenuList = unref(getDropMenuList) || [];

+ 7 - 7
src/layouts/default/multitabs/data.ts

@@ -4,7 +4,7 @@ import type { TabItem } from '/@/store/modules/tab';
 
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('layout.multipleTab');
+const { t } = useI18n();
 
 export enum TabContentEnum {
   TAB_TYPE,
@@ -41,40 +41,40 @@ export function getActions() {
   const REFRESH_PAGE: DropMenu = {
     icon: 'ant-design:reload-outlined',
     event: MenuEventEnum.REFRESH_PAGE,
-    text: t('redo'),
+    text: t('layout.multipleTab.redo'),
     disabled: false,
   };
   const CLOSE_CURRENT: DropMenu = {
     icon: 'ant-design:close-outlined',
     event: MenuEventEnum.CLOSE_CURRENT,
-    text: t('close'),
+    text: t('layout.multipleTab.close'),
     disabled: false,
     divider: true,
   };
   const CLOSE_LEFT: DropMenu = {
     icon: 'ant-design:pic-left-outlined',
     event: MenuEventEnum.CLOSE_LEFT,
-    text: t('closeLeft'),
+    text: t('layout.multipleTab.closeLeft'),
     disabled: false,
     divider: false,
   };
   const CLOSE_RIGHT: DropMenu = {
     icon: 'ant-design:pic-right-outlined',
     event: MenuEventEnum.CLOSE_RIGHT,
-    text: t('closeRight'),
+    text: t('layout.multipleTab.closeRight'),
     disabled: false,
     divider: true,
   };
   const CLOSE_OTHER: DropMenu = {
     icon: 'ant-design:pic-center-outlined',
     event: MenuEventEnum.CLOSE_OTHER,
-    text: t('closeOther'),
+    text: t('layout.multipleTab.closeOther'),
     disabled: false,
   };
   const CLOSE_ALL: DropMenu = {
     icon: 'ant-design:line-outlined',
     event: MenuEventEnum.CLOSE_ALL,
-    text: t('closeAll'),
+    text: t('layout.multipleTab.closeAll'),
     disabled: false,
   };
   return [REFRESH_PAGE, CLOSE_CURRENT, CLOSE_LEFT, CLOSE_RIGHT, CLOSE_OTHER, CLOSE_ALL];

+ 50 - 45
src/layouts/default/setting/SettingDrawer.tsx

@@ -56,7 +56,7 @@ interface ThemePickerProps {
 }
 
 const { createSuccessModal, createMessage } = useMessage();
-const { t } = useI18n('layout.setting');
+const { t } = useI18n();
 
 /**
  * Menu type Picker comp
@@ -122,8 +122,8 @@ const FooterButton: FunctionalComponent = () => {
     const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
     unref(isSuccessRef) &&
       createSuccessModal({
-        title: t('operatingTitle'),
-        content: t('operatingContent'),
+        title: t('layout.setting.operatingTitle'),
+        content: t('layout.setting.operatingContent'),
       });
   }
   function handleResetSetting() {
@@ -133,7 +133,7 @@ const FooterButton: FunctionalComponent = () => {
       // updateTheme(themeColor);
       updateColorWeak(colorWeak);
       updateGrayMode(grayMode);
-      createMessage.success(t('resetSuccess'));
+      createMessage.success(t('layout.setting.resetSuccess'));
     } catch (error) {
       createMessage.error(error);
     }
@@ -151,7 +151,7 @@ const FooterButton: FunctionalComponent = () => {
         {() => (
           <>
             <CopyOutlined class="mr-2" />
-            {t('copyBtn')}
+            {t('layout.setting.copyBtn')}
           </>
         )}
       </Button>
@@ -159,7 +159,7 @@ const FooterButton: FunctionalComponent = () => {
         {() => (
           <>
             <RedoOutlined class="mr-2" />
-            {t('resetBtn')}
+            {t('layout.setting.resetBtn')}
           </>
         )}
       </Button>
@@ -167,7 +167,7 @@ const FooterButton: FunctionalComponent = () => {
         {() => (
           <>
             <RedoOutlined class="mr-2" />
-            {t('clearBtn')}
+            {t('layout.setting.clearBtn')}
           </>
         )}
       </Button>
@@ -226,7 +226,7 @@ export default defineComponent({
       return (
         <>
           <MenuTypePicker />
-          {renderSwitchItem(t('splitMenu'), {
+          {renderSwitchItem(t('layout.setting.splitMenu'), {
             handler: (e) => {
               baseHandler(HandlerEnum.MENU_SPLIT, e);
             },
@@ -240,7 +240,7 @@ export default defineComponent({
     function renderTheme() {
       return (
         <>
-          <Divider>{() => t('headerTheme')}</Divider>
+          <Divider>{() => t('layout.setting.headerTheme')}</Divider>
           <ThemePicker
             colorList={HEADER_PRESET_BG_COLOR_LIST}
             def={unref(getHeaderBgColor)}
@@ -248,7 +248,7 @@ export default defineComponent({
               baseHandler(HandlerEnum.HEADER_THEME, e);
             }}
           />
-          <Divider>{() => t('sidebarTheme')}</Divider>
+          <Divider>{() => t('layout.setting.sidebarTheme')}</Divider>
           <ThemePicker
             colorList={SIDE_BAR_BG_COLOR_LIST}
             def={unref(getMenuBgColor)}
@@ -265,56 +265,56 @@ export default defineComponent({
      */
     function renderFeatures() {
       return [
-        renderSwitchItem(t('menuDrag'), {
+        renderSwitchItem(t('layout.setting.menuDrag'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
           },
           def: unref(getCanDrag),
           disabled: !unref(getShowMenuRef),
         }),
-        renderSwitchItem(t('menuSearch'), {
+        renderSwitchItem(t('layout.setting.menuSearch'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
           },
           def: unref(getShowSearch),
           disabled: !unref(getShowMenuRef),
         }),
-        renderSwitchItem(t('menuAccordion'), {
+        renderSwitchItem(t('layout.setting.menuAccordion'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_ACCORDION, e);
           },
           def: unref(getAccordion),
           disabled: !unref(getShowMenuRef),
         }),
-        renderSwitchItem(t('menuCollapse'), {
+        renderSwitchItem(t('layout.setting.menuCollapse'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_COLLAPSED, e);
           },
           def: unref(getCollapsed),
           disabled: !unref(getShowMenuRef),
         }),
-        renderSwitchItem(t('collapseMenuDisplayName'), {
+        renderSwitchItem(t('layout.setting.collapseMenuDisplayName'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
           },
           def: unref(getCollapsedShowTitle),
           disabled: !unref(getShowMenuRef) || !unref(getCollapsed),
         }),
-        renderSwitchItem(t('fixedHeader'), {
+        renderSwitchItem(t('layout.setting.fixedHeader'), {
           handler: (e) => {
             baseHandler(HandlerEnum.HEADER_FIXED, e);
           },
           def: unref(getHeaderFixed),
           disabled: !unref(getShowHeader),
         }),
-        renderSwitchItem(t('fixedSideBar'), {
+        renderSwitchItem(t('layout.setting.fixedSideBar'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_FIXED, e);
           },
           def: unref(getMenuFixed),
           disabled: !unref(getShowMenuRef),
         }),
-        renderSelectItem(t('topMenuLayout'), {
+        renderSelectItem(t('layout.setting.topMenuLayout'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
           },
@@ -322,7 +322,7 @@ export default defineComponent({
           options: topMenuAlignOptions,
           disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),
         }),
-        renderSelectItem(t('menuCollapseButton'), {
+        renderSelectItem(t('layout.setting.menuCollapseButton'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_TRIGGER, e);
           },
@@ -331,7 +331,7 @@ export default defineComponent({
           options: menuTriggerOptions,
         }),
 
-        renderSelectItem(t('contentMode'), {
+        renderSelectItem(t('layout.setting.contentMode'), {
           handler: (e) => {
             baseHandler(HandlerEnum.CONTENT_MODE, e);
           },
@@ -339,7 +339,7 @@ export default defineComponent({
           options: contentModeOptions,
         }),
         <div class={`setting-drawer__cell-item`}>
-          <span>{t('autoScreenLock')}</span>
+          <span>{t('layout.setting.autoScreenLock')}</span>
           <InputNumber
             style="width:126px"
             size="small"
@@ -350,14 +350,14 @@ export default defineComponent({
             defaultValue={appStore.getProjectConfig.lockTime}
             formatter={(value: string) => {
               if (parseInt(value) === 0) {
-                return `0(${t('notAutoScreenLock')})`;
+                return `0(${t('layout.setting.notAutoScreenLock')})`;
               }
-              return `${value}${t('minute')}`;
+              return `${value}${t('layout.setting.minute')}`;
             }}
           />
         </div>,
         <div class={`setting-drawer__cell-item`}>
-          <span>{t('expandedMenuWidth')}</span>
+          <span>{t('layout.setting.expandedMenuWidth')}</span>
           <InputNumber
             style="width:126px"
             size="small"
@@ -377,27 +377,27 @@ export default defineComponent({
 
     function renderContent() {
       return [
-        renderSwitchItem(t('breadcrumb'), {
+        renderSwitchItem(t('layout.setting.breadcrumb'), {
           handler: (e) => {
             baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
           },
           def: unref(getShowBreadCrumb),
           disabled: !unref(getShowHeader),
         }),
-        renderSwitchItem(t('breadcrumbIcon'), {
+        renderSwitchItem(t('layout.setting.breadcrumbIcon'), {
           handler: (e) => {
             baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
           },
           def: unref(getShowBreadCrumbIcon),
           disabled: !unref(getShowHeader),
         }),
-        renderSwitchItem(t('tabs'), {
+        renderSwitchItem(t('layout.setting.tabs'), {
           handler: (e) => {
             baseHandler(HandlerEnum.TABS_SHOW, e);
           },
           def: unref(getShowMultipleTab),
         }),
-        renderSwitchItem(t('tabsQuickBtn'), {
+        renderSwitchItem(t('layout.setting.tabsQuickBtn'), {
           handler: (e) => {
             baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
           },
@@ -405,14 +405,14 @@ export default defineComponent({
           disabled: !unref(getShowMultipleTab),
         }),
 
-        renderSwitchItem(t('sidebar'), {
+        renderSwitchItem(t('layout.setting.sidebar'), {
           handler: (e) => {
             baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
           },
           def: unref(getShowMenu),
           disabled: unref(getIsHorizontal),
         }),
-        renderSwitchItem(t('header'), {
+        renderSwitchItem(t('layout.setting.header'), {
           handler: (e) => {
             baseHandler(HandlerEnum.HEADER_SHOW, e);
           },
@@ -424,25 +424,25 @@ export default defineComponent({
           },
           def: unref(getShowLogo),
         }),
-        renderSwitchItem(t('footer'), {
+        renderSwitchItem(t('layout.setting.footer'), {
           handler: (e) => {
             baseHandler(HandlerEnum.SHOW_FOOTER, e);
           },
           def: unref(getShowFooter),
         }),
-        renderSwitchItem(t('fullContent'), {
+        renderSwitchItem(t('layout.setting.fullContent'), {
           handler: (e) => {
             baseHandler(HandlerEnum.FULL_CONTENT, e);
           },
           def: unref(getFullContent),
         }),
-        renderSwitchItem(t('grayMode'), {
+        renderSwitchItem(t('layout.setting.grayMode'), {
           handler: (e) => {
             baseHandler(HandlerEnum.GRAY_MODE, e);
           },
           def: unref(getGrayMode),
         }),
-        renderSwitchItem(t('colorWeak'), {
+        renderSwitchItem(t('layout.setting.colorWeak'), {
           handler: (e) => {
             baseHandler(HandlerEnum.COLOR_WEAK, e);
           },
@@ -454,13 +454,13 @@ export default defineComponent({
     function renderTransition() {
       return (
         <>
-          {renderSwitchItem(t('progress'), {
+          {renderSwitchItem(t('layout.setting.progress'), {
             handler: (e) => {
               baseHandler(HandlerEnum.OPEN_PROGRESS, e);
             },
             def: unref(getOpenNProgress),
           })}
-          {renderSwitchItem(t('switchLoading'), {
+          {renderSwitchItem(t('layout.setting.switchLoading'), {
             handler: (e) => {
               baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
             },
@@ -468,14 +468,14 @@ export default defineComponent({
             disabled: !unref(getEnableTransition),
           })}
 
-          {renderSwitchItem(t('switchAnimation'), {
+          {renderSwitchItem(t('layout.setting.switchAnimation'), {
             handler: (e) => {
               baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
             },
             def: unref(getEnableTransition),
           })}
 
-          {renderSelectItem(t('animationType'), {
+          {renderSelectItem(t('layout.setting.animationType'), {
             handler: (e) => {
               baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
             },
@@ -519,26 +519,31 @@ export default defineComponent({
             onChange={(e: any) => {
               handler && handler(e);
             }}
-            checkedChildren={t('on')}
-            unCheckedChildren={t('off')}
+            checkedChildren={t('layout.setting.on')}
+            unCheckedChildren={t('layout.setting.off')}
           />
         </div>
       );
     }
 
     return () => (
-      <BasicDrawer {...attrs} title={t('drawerTitle')} width={330} wrapClassName="setting-drawer">
+      <BasicDrawer
+        {...attrs}
+        title={t('layout.setting.drawerTitle')}
+        width={330}
+        wrapClassName="setting-drawer"
+      >
         {{
           default: () => (
             <>
-              <Divider>{() => t('navMode')}</Divider>
+              <Divider>{() => t('layout.setting.navMode')}</Divider>
               {renderSidebar()}
               {renderTheme()}
-              <Divider>{() => t('interfaceFunction')}</Divider>
+              <Divider>{() => t('layout.setting.interfaceFunction')}</Divider>
               {renderFeatures()}
-              <Divider>{() => t('interfaceDisplay')}</Divider>
+              <Divider>{() => t('layout.setting.interfaceDisplay')}</Divider>
               {renderContent()}
-              <Divider>{() => t('animation')}</Divider>
+              <Divider>{() => t('layout.setting.animation')}</Divider>
               {renderTransition()}
               <Divider />
               <FooterButton />

+ 12 - 12
src/layouts/default/setting/enum.ts

@@ -6,7 +6,7 @@ import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
 import menuTopImg from '/@/assets/images/layout/menu-top.svg';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('layout.setting');
+const { t } = useI18n();
 
 export enum HandlerEnum {
   CHANGE_LAYOUT,
@@ -51,41 +51,41 @@ export enum HandlerEnum {
 export const contentModeOptions = [
   {
     value: ContentEnum.FULL,
-    label: t('contentModeFull'),
+    label: t('layout.setting.contentModeFull'),
   },
   {
     value: ContentEnum.FIXED,
-    label: t('contentModeFixed'),
+    label: t('layout.setting.contentModeFixed'),
   },
 ];
 
 export const topMenuAlignOptions = [
   {
     value: TopMenuAlignEnum.CENTER,
-    label: t('topMenuAlignRight'),
+    label: t('layout.setting.topMenuAlignRight'),
   },
   {
     value: TopMenuAlignEnum.START,
-    label: t('topMenuAlignLeft'),
+    label: t('layout.setting.topMenuAlignLeft'),
   },
   {
     value: TopMenuAlignEnum.END,
-    label: t('topMenuAlignCenter'),
+    label: t('layout.setting.topMenuAlignCenter'),
   },
 ];
 
 export const menuTriggerOptions = [
   {
     value: TriggerEnum.NONE,
-    label: t('menuTriggerNone'),
+    label: t('layout.setting.menuTriggerNone'),
   },
   {
     value: TriggerEnum.FOOTER,
-    label: t('menuTriggerBottom'),
+    label: t('layout.setting.menuTriggerBottom'),
   },
   {
     value: TriggerEnum.HEADER,
-    label: t('menuTriggerTop'),
+    label: t('layout.setting.menuTriggerTop'),
   },
 ];
 
@@ -104,20 +104,20 @@ export const routerTransitionOptions = [
 
 export const menuTypeList = [
   {
-    title: t('menuTypeSidebar'),
+    title: t('layout.setting.menuTypeSidebar'),
     mode: MenuModeEnum.INLINE,
     type: MenuTypeEnum.SIDEBAR,
     src: sidebarImg,
   },
   {
-    title: t('menuTypeMix'),
+    title: t('layout.setting.menuTypeMix'),
     mode: MenuModeEnum.INLINE,
     type: MenuTypeEnum.MIX,
     src: mixImg,
   },
 
   {
-    title: t('menuTypeTopMenu'),
+    title: t('layout.setting.menuTypeTopMenu'),
     mode: MenuModeEnum.HORIZONTAL,
     type: MenuTypeEnum.TOP_MENU,
     src: menuTopImg,

+ 2 - 2
src/store/modules/permission.ts

@@ -22,7 +22,7 @@ import { useMessage } from '/@/hooks/web/useMessage';
 // import { warn } from '/@/utils/log';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('sys.app');
+const { t } = useI18n();
 
 const { createMessage } = useMessage();
 const NAME = 'permission';
@@ -104,7 +104,7 @@ class Permission extends VuexModule {
     } else if (permissionMode === PermissionModeEnum.BACK) {
       const messageKey = 'loadMenu';
       createMessage.loading({
-        content: t('menuLoading'),
+        content: t('sys.app.menuLoading'),
         key: messageKey,
         duration: 1,
       });

+ 3 - 3
src/store/modules/user.ts

@@ -143,11 +143,11 @@ class User extends VuexModule {
   @Action
   async confirmLoginOut() {
     const { createConfirm } = useMessage();
-    const { t } = useI18n('sys.app');
+    const { t } = useI18n();
     createConfirm({
       iconType: 'warning',
-      title: t('loginOutTip'),
-      content: t('loginOutMessage'),
+      title: t('sys.app.loginOutTip'),
+      content: t('sys.app.loginOutMessage'),
       onOk: async () => {
         await this.loginOut(true);
       },

+ 12 - 12
src/utils/http/axios/checkStatus.ts

@@ -5,7 +5,7 @@ const { createMessage } = useMessage();
 
 const error = createMessage.error!;
 export function checkStatus(status: number, msg: string): void {
-  const { t } = useI18n('sys.api');
+  const { t } = useI18n();
   switch (status) {
     case 400:
       error(`${msg}`);
@@ -14,39 +14,39 @@ export function checkStatus(status: number, msg: string): void {
     // 未登录则跳转登录页面,并携带当前页面的路径
     // 在登录成功后返回当前页面,这一步需要在登录页操作。
     case 401:
-      error(t('errMsg401'));
+      error(t('sys.api.errMsg401'));
       userStore.loginOut(true);
       break;
     case 403:
-      error(t('errMsg403'));
+      error(t('sys.api.errMsg403'));
       break;
     // 404请求不存在
     case 404:
-      error(t('errMsg404'));
+      error(t('sys.api.errMsg404'));
       break;
     case 405:
-      error(t('errMsg405'));
+      error(t('sys.api.errMsg405'));
       break;
     case 408:
-      error(t('errMsg408'));
+      error(t('sys.api.errMsg408'));
       break;
     case 500:
-      error(t('errMsg500'));
+      error(t('sys.api.errMsg500'));
       break;
     case 501:
-      error(t('errMsg501'));
+      error(t('sys.api.errMsg501'));
       break;
     case 502:
-      error(t('errMsg502'));
+      error(t('sys.api.errMsg502'));
       break;
     case 503:
-      error(t('errMsg503'));
+      error(t('sys.api.errMsg503'));
       break;
     case 504:
-      error(t('errMsg504'));
+      error(t('sys.api.errMsg504'));
       break;
     case 505:
-      error(t('errMsg505'));
+      error(t('sys.api.errMsg505'));
       break;
     default:
   }

+ 9 - 9
src/utils/http/axios/index.ts

@@ -34,7 +34,7 @@ const transform: AxiosTransform = {
    * @description: 处理请求数据
    */
   transformRequestData: (res: AxiosResponse<Result>, options: RequestOptions) => {
-    const { t } = useI18n('sys.api');
+    const { t } = useI18n();
     const { isTransformRequestResult } = options;
     // 不进行任何处理,直接返回
     // 用于页面代码可能需要直接获取code,data,message这些信息时开启
@@ -57,7 +57,7 @@ const transform: AxiosTransform = {
       if (message) {
         // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
         if (options.errorMessageMode === 'modal') {
-          createErrorModal({ title: t('errorTip'), content: message });
+          createErrorModal({ title: t('sys.api.errorTip'), content: message });
         } else {
           createMessage.error(message);
         }
@@ -76,7 +76,7 @@ const transform: AxiosTransform = {
         createMessage.error(data.message);
         Promise.reject(new Error(message));
       } else {
-        const msg = t('errorMessage');
+        const msg = t('sys.api.errorMessage');
         createMessage.error(msg);
         Promise.reject(new Error(msg));
       }
@@ -84,9 +84,9 @@ const transform: AxiosTransform = {
     }
     // 登录超时
     if (code === ResultEnum.TIMEOUT) {
-      const timeoutMsg = t('timeoutMessage');
+      const timeoutMsg = t('sys.api.timeoutMessage');
       createErrorModal({
-        title: t('operationFailed'),
+        title: t('sys.api.operationFailed'),
         content: timeoutMsg,
       });
       Promise.reject(new Error(timeoutMsg));
@@ -154,7 +154,7 @@ const transform: AxiosTransform = {
    * @description: 响应错误处理
    */
   responseInterceptorsCatch: (error: any) => {
-    const { t } = useI18n('sys.api');
+    const { t } = useI18n();
     errorStore.setupErrorHandle(error);
     const { response, code, message } = error || {};
     const msg: string =
@@ -162,12 +162,12 @@ const transform: AxiosTransform = {
     const err: string = error.toString();
     try {
       if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
-        createMessage.error(t('apiTimeoutMessage'));
+        createMessage.error(t('sys.api.apiTimeoutMessage'));
       }
       if (err && err.includes('Network Error')) {
         createErrorModal({
-          title: t('networkException'),
-          content: t('networkExceptionMsg'),
+          title: t('sys.api.networkException'),
+          content: t('sys.api.networkExceptionMsg'),
         });
       }
     } catch (error) {

+ 2 - 2
src/views/sys/error-log/DetailModal.vue

@@ -1,5 +1,5 @@
 <template>
-  <BasicModal :width="800" :title="t('tableActionDesc')" v-bind="$attrs">
+  <BasicModal :width="800" :title="t('sys.errorLog.tableActionDesc')" v-bind="$attrs">
     <Description :data="info" @register="register" />
   </BasicModal>
 </template>
@@ -23,7 +23,7 @@
       },
     },
     setup() {
-      const { t } = useI18n('sys.errorLog');
+      const { t } = useI18n();
       const [register] = useDescription({
         column: 2,
         schema: getDescSchema(),

+ 6 - 6
src/views/sys/error-log/data.tsx

@@ -3,13 +3,13 @@ import { BasicColumn } from '/@/components/Table/index';
 import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
 import { useI18n } from '/@/hooks/web/useI18n';
 
-const { t } = useI18n('sys.errorLog');
+const { t } = useI18n();
 
 export function getColumns(): BasicColumn[] {
   return [
     {
       dataIndex: 'type',
-      title: t('tableColumnType'),
+      title: t('sys.errorLog.tableColumnType'),
       width: 80,
       customRender: ({ text }) => {
         const color =
@@ -32,12 +32,12 @@ export function getColumns(): BasicColumn[] {
     },
     {
       dataIndex: 'time',
-      title: t('tableColumnDate'),
+      title: t('sys.errorLog.tableColumnDate'),
       width: 160,
     },
     {
       dataIndex: 'file',
-      title: t('tableColumnFile'),
+      title: t('sys.errorLog.tableColumnFile'),
       width: 200,
     },
     {
@@ -47,12 +47,12 @@ export function getColumns(): BasicColumn[] {
     },
     {
       dataIndex: 'message',
-      title: t('tableColumnMsg'),
+      title: t('sys.errorLog.tableColumnMsg'),
       width: 300,
     },
     {
       dataIndex: 'stack',
-      title: t('tableColumnStackMsg'),
+      title: t('sys.errorLog.tableColumnStackMsg'),
       width: 300,
     },
   ];

+ 2 - 2
src/views/sys/error-log/index.vue

@@ -53,7 +53,7 @@
       const rowInfoRef = ref<ErrorInfo>();
       const imgListRef = ref<string[]>([]);
 
-      const { t } = useI18n('sys.errorLog');
+      const { t } = useI18n();
 
       const [register, { setTableData }] = useTable({
         title: t('sys.errorLog.tableTitle'),
@@ -80,7 +80,7 @@
       );
       const { createMessage } = useMessage();
       if (isDevMode()) {
-        createMessage.info(t('enableMessage'));
+        createMessage.info(t('sys.errorLog.enableMessage'));
       }
       // 查看详情
       function handleDetail(row: ErrorInfo) {

+ 10 - 10
src/views/sys/exception/Exception.tsx

@@ -53,7 +53,7 @@ export default defineComponent({
     const { query } = useRoute();
     const go = useGo();
     const redo = useRedo();
-    const { t } = useI18n('sys.exception');
+    const { t } = useI18n();
 
     const getStatus = computed(() => {
       const { status: routeStatus } = query;
@@ -67,13 +67,13 @@ export default defineComponent({
       }
     );
 
-    const backLoginI18n = t('backLogin');
-    const backHomeI18n = t('backHome');
+    const backLoginI18n = t('sys.exception.backLogin');
+    const backHomeI18n = t('sys.exception.backHome');
 
     unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_ACCESS, {
       title: '403',
       status: `${ExceptionEnum.PAGE_NOT_ACCESS}`,
-      subTitle: t('subTitle403'),
+      subTitle: t('sys.exception.subTitle403'),
       btnText: props.full ? backLoginI18n : backHomeI18n,
       handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
     });
@@ -81,7 +81,7 @@ export default defineComponent({
     unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_FOUND, {
       title: '404',
       status: `${ExceptionEnum.PAGE_NOT_FOUND}`,
-      subTitle: t('subTitle404'),
+      subTitle: t('sys.exception.subTitle404'),
       btnText: props.full ? backLoginI18n : backHomeI18n,
       handler: () => (props.full ? go(PageEnum.BASE_LOGIN) : go()),
     });
@@ -89,22 +89,22 @@ export default defineComponent({
     unref(statusMapRef).set(ExceptionEnum.ERROR, {
       title: '500',
       status: `${ExceptionEnum.ERROR}`,
-      subTitle: t('subTitle500'),
+      subTitle: t('sys.exception.subTitle500'),
       btnText: backHomeI18n,
       handler: () => go(),
     });
 
     unref(statusMapRef).set(ExceptionEnum.PAGE_NOT_DATA, {
-      title: t('noDataTitle'),
+      title: t('sys.exception.noDataTitle'),
       subTitle: '',
-      btnText: t('redo'),
+      btnText: t('sys.exception.redo'),
       handler: () => redo(),
       icon: notDataImg,
     });
 
     unref(statusMapRef).set(ExceptionEnum.NET_WORK_ERROR, {
-      title: t('networkErrorTitle'),
-      subTitle: t('networkErrorSubTitle'),
+      title: t('sys.exception.networkErrorTitle'),
+      subTitle: t('sys.exception.networkErrorSubTitle'),
       btnText: 'Refresh',
       handler: () => redo(),
       icon: netWorkImg,

+ 2 - 2
src/views/sys/lock/index.vue

@@ -36,7 +36,7 @@
       const loadingRef = ref(false);
       const errMsgRef = ref(false);
 
-      const { t } = useI18n('sys.lock');
+      const { t } = useI18n();
       const [register, { validateFields }] = useForm({
         showActionButtonGroup: false,
         schemas: [
@@ -46,7 +46,7 @@
             component: 'InputPassword',
             componentProps: {
               style: { width: '100%' },
-              placeholder: t('placeholder'),
+              placeholder: t('sys.lock.placeholder'),
             },
             rules: [{ required: true }],
           },

+ 7 - 5
src/views/sys/login/Login.vue

@@ -90,7 +90,7 @@
       const globSetting = useGlobSetting();
       const { locale } = useProjectSetting();
       const { notification } = useMessage();
-      const { t } = useI18n('sys.login');
+      const { t } = useI18n();
 
       // const openLoginVerifyRef = computed(() => appStore.getProjectConfig.openLoginVerify);
 
@@ -104,8 +104,10 @@
       });
 
       const formRules = reactive({
-        account: [{ required: true, message: t('accountPlaceholder'), trigger: 'blur' }],
-        password: [{ required: true, message: t('passwordPlaceholder'), trigger: 'blur' }],
+        account: [{ required: true, message: t('sys.login.accountPlaceholder'), trigger: 'blur' }],
+        password: [
+          { required: true, message: t('sys.login.passwordPlaceholder'), trigger: 'blur' },
+        ],
         // verify: unref(openLoginVerifyRef) ? [{ required: true, message: '请通过验证码校验' }] : [],
       });
 
@@ -130,8 +132,8 @@
           );
           if (userInfo) {
             notification.success({
-              message: t('loginSuccessTitle'),
-              description: `${t('loginSuccessDesc')}: ${userInfo.realName}`,
+              message: t('sys.login.loginSuccessTitle'),
+              description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`,
               duration: 3,
             });
           }