首页 > 其他分享 >在项目中定义 i18n 结构化对象的简单思路

在项目中定义 i18n 结构化对象的简单思路

时间:2022-12-08 23:56:08浏览次数:53  
标签:结构化 moduleName const 定义 js fieldName 模块 i18n

简介

本文介绍一种在项目定义 i18n 文本结构的简单思路,以及定义一些简单的全局函数,用于获取 i18n 文本。

文件结构

src
├── i18n
└── index.js
├── zhCN
├── index.js
├── common.js // 放置项目中通用的文本
├── moduleName.js // 放置各模块独立的文本
├── ...
├── en
├── index.js
├── common.js
├── moduleName.js
├── ...
├── ... // 其他语言

在项目根路径下新建 i18n 文件夹,也就是 /src/i18n (可配置别名 @/i18n),并新建 index.js 文件。这里省略 i18n 的创建过程。

在同级目录下新建各语言的对应文件夹,并统一创建 index.js ,内容都一样:

const allModules = import.meta.globEager('./*');
let modules = {};
Object.keys(allModules).forEach((key) => {
  // 这是将单个模块文件作为一个属性,若模块导出了多个值,这些值位于该属性值的对象中
  //   modules[key.replace(/(\.\/|\.js)/g, '')] = allModules[key].default;
  // 这是将所有模块直接打平,再导出为一个对象
  modules = Object.assign(modules, allModules[key].default);
});

export default modules;

通用模块

common.js

// 全局通用但暂时想不到分类可以先放这里
const common = {
  all: 'All',
  action: 'Action',
  success: 'Success',
  fail: 'Fail',
};
// 操作
const action = {
  submit: 'Submit',
  cancel: 'Cancel',
  confirm: 'Confirm',
  reset: 'Reset',
  view: 'View',
  add: 'Add New',
  edit: 'Edit',
  delete: 'Delete',
  copy: 'Copy',
};
// 这里并不是表示货币符号与语言直接挂钩,而是可能有特殊的格式化,比如中文下的 RMB 格式化为 ¥(元)
const currency = {
  en: '$',
  zhCN: '¥',
};
export default {
  common,
  form,
  currency,
};

各模块

主要包括 info、fieldKey、filter、message、placeholder 等,主要分为两大类。

  • 一类是与视图构建相关的文本,如 fieldKey ,开发输出组件时常使用配置化的方式减少模板的使用,而是通过 v-if、v-for 等指令快速构建;
  • 另外一类是与各类辅助信息、提示消息等相关的文本,包括 info、message、placeholder 等单纯用于不同语言下切换的文本,以及 filter 这类用于过滤后端返回数据的文本。比如 select 组件的 value 为了存储方便,通常会使用纯数字表示,但不便于用户记忆和使用,在 vue2 中可以通过 filters 搭配管道操作符进行替换, vue3 中虽然移除了 filters ,但这种需求场景仍然存在,因此仍然有必要为了该需求设置一个专门的对象用于过滤并输出方便人看的内容。即使未使用 i18n ,该对象也可以作为组件内的私有变量存在。

下面以产品模块为例。

const productManagement = {
  info: {
    moduleName: 'ProductManagement', // 可能用于特殊用途
  },
  fieldKey: {
    productId: 'Product Id',
    productName: 'Product Name',
  },
  filter: {
    warehouseType: {
      [0]: 'Domectic Warehouse',
      [1]: 'Oversea Warehouse',
    },
  },
  message: {
    field: {
      productName: {
        required: 'Product name is required',
        length: 'Please input no more than 20 characters',
      },
    },
    form: {
      add: {
        success: 'Product added',
        fail: 'Fail to add product, please check',
      },
      edit: {
        success: 'Product edited',
        fail: 'Fail to edit product, please check',
      },
      delete: {
        success: 'Product deleted',
        fail: 'Fail to delete product, please check',
      },
    },
  },
  placeholder: {
    productName: 'Please input the product name',
  },
};

export default { productManagement};

全局的 i18n 转换函数

这里仅展示获取上一段有提到的结构化对象中文本的函数。

@/utils/setupI18n/index.js

import { i18n } from '@/i18n'; // 这里是已经在项目中的 i18n 模块下通过 createI18n 方法创建好了对象,所以直接导入
const { t: $t } = i18n.global; // 在普通 js/ts 模块中使用 $t

// 字段
export const setupFieldKeyI18nGlobal = (moduleName) => (fieldName) =>
  $t(`${moduleName}.fieldKeys.${fieldName}`);
// 过滤
export const setupFilersI18nGlobal = (moduleName) => (fieldName, fieldVal) =>
  $t(`${moduleName}.filters.${fieldName}.${fieldVal}`);
// placeholder
export const setupPlaceholderI18nGlobal = (moduleName) => (fieldName) =>
  $t(`${moduleName}.placeholder.${fieldName}`);
// 提示消息
export const setupFieldMessageI18nGlobal =
  (moduleName) => (componentType, actionType) =>
    $t(`${moduleName}.messages.field.${componentType}.${actionType}`);
export const setupFormMessageI18nGlobal =
  (moduleName) => (componentType, actionType) =>
    $t(`${moduleName}.messages.form.${componentType}.${actionType}`);

组件中的使用示例:

import {setupFieldKeyI18nGlobal } from '@/utils/setupI18n';

const moduleName = ref('ProductManagement'); // 业务组件的模块名

// 返回一个新函数 (fieldName) => $t(`ProductManagement.fieldKeys.${fieldName}`);
const setupFilersI18n = setupFilersI18nGlobal(moduleName.value);

通过这种方式,可以将实际的参数结构统一到一个地方进行管理,避免 i18n 模块中的对象结构变更后,还得修改各个组件。

标签:结构化,moduleName,const,定义,js,fieldName,模块,i18n
From: https://www.cnblogs.com/cjc-0313/p/16967762.html

相关文章

  • 调用自定义的包
    创建被调用的包mkdirtestcdtestgomodinitexample.com/testcattest/test.gopackagetestpackagetestimport"fmt"//func定义函数//Hello函数名//......
  • 第二章-线性表 1.线性表的定义和基本操作
    定义具有相关数据类型的n个数据元素的有限序列叫做线性表.术语:位序,表头元素,表尾元素,直接前驱,直接后继.线性表的基本操作基本记忆思路:创建销毁,增删改查.......
  • 自定义RBAC(3)
    您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~​RBAC类型的权限,本质上是一种对资源访问路径的控制,且具有典型的树型层次结构。而树型结构,天然地就有父结点和子结点的关......
  • 自定义RBAC(3)
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~ RBAC类型的权限,本质上是一种对资源访问路径的控制,且具有典型的树型层次结构。而树型结构,天然地就有父结点和子结点的关......
  • vue实现自定义字体库
      先看效果是不是你所需要的,再看具体如何实现。   效果如下图所示:         有些字体需要下载,用图片就会变得很不清楚,这样我们就需要去下载字......
  • extern、定义和声明
    Extern的问题在于不知道这个关键词出现的时候到底是声明还是定义。谨记:声明可以多次,定义只能一次。    对于变量来说,定义就是声明.   例如: inta; 我们可是说......
  • 字符数组的定义与赋值
    今天写c程序时遇到这样的编译问题charstr[10];str[]="welcome";报语法错误charstr[10];str="welcome";也报语法错误 这是为什么呢?如果是其它的变量,比如:inta=1;可......
  • Android自定义View和Canvas绘图解析
    自定义view的流程分为measure、layout、draw三个主要步骤,今天我们通过源码来分下下measure的过程我们从顶级view开始,顶级view即DecorView,view的事件都是先经过这个DecorVi......
  • 4.python-定义函数
    函数1.pycharm快捷键Ctrl+Q快速查看文档(能快速查看到选择的函数创建者对该函数的注释)2.定义(1)用于封装一个特定的功能,表示一个功能或者行为。(2)函数是可以......
  • 6.python-练习定义函数
    defprint_content(content):print(content)defget_sentence_constituent(sentence,constituent):returninput("请输入%s的%s:"%(sentence,constituent))......