# easy-translation
**Repository Path**: cai-zhiyuDaKeLe/easy-translation
## Basic Information
- **Project Name**: easy-translation
- **Description**: 一个配置简单,轻量的java自动填充(翻译)字段框架
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 16
- **Forks**: 1
- **Created**: 2024-04-20
- **Last Updated**: 2025-04-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: translation, Java, 自动填充, SpringBoot, mapping
## README
[English](./README-EN.md) | [中文](./README.md)
## 文档地址:https://kkkele.github.io/easy-translation-docs/#/

# Easy-Translation
一个配置上非常轻量,使用简单且强大而灵活的**字段翻译**插件。可以理解为**字段自动填充框架**,主要作用就是由其他的字段**自动映射**成所需要的字段。

## 作用场景
任何您想得到,需要值填充,而填充的手段希望简单,优雅的场景,都可以使用`Easy-Translation`。
## 开发背景
在web开发的过程中,后端程序员经常面临多表查询,然后组装成一个vo类的情况。于是,`Easy-Translation`应运而生,因为它使用场景灵活,所以不再局限于web开发,任何需要灵活,动态的值填充场景,都可以使用`Easy-Translation`,它帮助你省略大部分重复的代码,极大的提高了开发效率,而且从某一层面起到了解耦的作用,使得代码的职责更加清晰。
## 您能从哪里获得值填充(如何获取翻译器进行翻译)
- **动态方法**
动态方法由对象执行,这就意味着,你可以原原本本的使用代理对象,所有增强方法的手段都会被得到执行,事务(例如:*@Transcational*),缓存(例如:*@Cacheable*),或是幂等(`Easy-Idempotent`提供的**@Idempotent**)注解等等,具有极高的兼容性。
- **静态方法**
静态方法并不需要执行对象,只要您提供的路径,能扫到该包,就可以成功的执行对应的翻译功能。
- **枚举类**
是的,`Easy-Translation`支持您使用枚举当作翻译器,不过需要您在枚举类上额外标注*@TransMapper*注解当作翻译的key,*@TransValue*当作翻译的值,
插件会自动为您生成一个方法(底层用map进行了一个存储),从而执行对应的翻译功能。
## 插件的灵活性
- 支持**多参数**翻译:(支持到*0*到*16*个参数。如果您希望由多于16中参数的方法作为翻译器,作者觉得,您可能需要更换代码的写法)
详情用法请看文档
- 可**自选**翻译器返回结果的任意属性填充:
是的,如果您标记了getUserById 方法为翻译器,当翻译器执行后,你可以选择user对象的任意属性进行填充
- **复用**翻译器翻译结果,减少执行方法的消耗:
如果您需要翻译的字段是同一个翻译器,同一个映射值的执行后的不同属性,那么,插件不会 多次执行,而是会复用结果,以减少时间的消耗。
例如:你需要在一个vo中填充user的age和name,那么您只需要在@Mapping注解的receive属性进行一个区分即可。
- **自定义翻译顺序**
例如,您需要的返回对象某些的属性,有一些关联关系,先有a得到b,再用b得到c,你可以通过@Mapping的sort属性和after属性进行一个翻译器执行顺序的排序。
- **异步**组装翻译结果
不相关的属性当然可以利用异步组装来减少时间消耗。
- 多线程异步组装**自动传递上下文变量**
你可以注册一些上下文变量传递者,来解决异步时上下文变量丢失的问题。
- **自动解包**:如果您的返回对象是list,array,map或是其他您希望进行一个拆除的对象。那么插件会进行一个拆包操作,获取其中的item进行逐个翻译,当然,这个过程仍然可以异步处理
- **可扩展性极强**,具体请看相关文档
可自定义 翻译器的生产过程,翻译器产生时的前置操作和后置操作
可自定义 拆包者,选择拆包的结果,需要拆包的对象
- **开箱即用**
在spring环境下,在启动类或是其他@component等注解上标记`@EnableTranslation`,即可使用
在非spring环境下,需要自行手动创建一些全局对象进行维护
## 快速开始
pom.xml添加依赖
```java
io.github.kkkele
easy-translation-spring-boot-start
1.0.0 //请自行替换为最新版本
```
启动类或其他任意被spring管理的类上,加上@EnableTranslation注解
```java
@SpringBootApplication
@EnableTranslation //可自由选择扫描包的路径
public class EasyTranslationApplication {
public static void main(String[] args) {
SpringApplication.run(EasyTranslationApplication.class, args);
}
}
```
在方法上打上**@Translator**注解,并自定义该注解的名称
```java
@Data
public class SysUser {
private Integer userId;
private String username;
private String nickName;
}
@Service
public class UserServiceImpl implements UserService {
@Override
@Translator("getUser")
public SysUser getById(Integer id) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
SysUser sysUser = new SysUser();
sysUser.setUserId(id);
sysUser.setUsername("username" + id);
sysUser.setNickName("nickName" + id);
return sysUser;
}
}
```
在需要翻译的类的字段上,使用@Mapping注解,指定翻译器,和所接收的属性名
```java
@Data
public class Product {
private Integer productId;
private String productName;
private Integer catId;
private Integer createBy;
}
@Data
public class ProductVo extends Product {
@Mapping(translator = "getUser", mapper = "createBy",receive = "nickName")
private String nickName;
@Mapping(translator = "getUser", mapper = "createBy", receive = "username")
private String username;
}
```
在需要翻译的方法上使用**@TranslationExecute**注解,即可自动对执行结果进行翻译填充,不论是map,还是数组,还是list,或是您有其他需求,都可以进行拆包填充
```java
@Override
@TranslationExecute
public ProductVo getDetailById(Integer id) {
ProductVo productVO = new ProductVo();
Product byId = getById(id);
BeanUtil.copyProperties(byId, productVO);
return productVO;
}
```
```javascript
@Data
public class R {
int code;
T data;
public R(int code, T data) {
this.code = code;
this.data = data;
}
public static R ok(T data) {
return new R<>(200, data);
}
public static R error(T data) {
return new R<>(500, data);
}
public static R error() {
return new R<>(500, null);
}
public static R ok() {
return new R<>(200, null);
}
}
```
```java
@GetMapping("/{id}")
@TranslationExecute(field = "data")
public R getDetailById(@PathVariable Integer id) {
return R.ok(productService.getDetailById(id));
}
@GetMapping("/list")
@TranslationExecute(field = "data")
public R> getList() {
return R.ok(mappingToList(ListUtil.of(1, 2, 3, 4, 4)));
}
@GetMapping("/array")
@TranslationExecute(field = "data")
public R getArray() {
return R.ok(mappingToArray(1, 2, 3, 4, 5));
}
@GetMapping("/map")
@TranslationExecute(field = "data")
public R