Wisper是一個輕量級I18n翻譯框架,簡單易用,效能出色,並且擴充套件簡單。
讓我們看看如何開始使用Whisper!
假設你有一個基於Spring的專案,並且專案的dataSource已經配置好。
可以在下面連結得到Whisper的樣例程式碼
準備工作
建立I18n翻譯表
在你的服務基於的資料庫中,建立一張i18n表,用來儲存翻譯關係。
如果恰好使用Mysql,你可以直接使用以下指令碼建立這張表:
CREATE TABLE `i18n_item` (
`i18n_key` varchar(36) NOT NULL,
`language` varchar(20) NOT NULL,
`i18n_code` varchar(45) NOT NULL,
`i18n_name` longtext,
`is_enabled` bigint(1) NOT NULL,
`is_deleted` bigint(1) NOT NULL,
`created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `index_key_lang_code` (`i18n_key`,`language`,`i18n_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製程式碼
其餘資料庫的實現我們後續會很快給出,也歡迎大家貢獻其他庫的實現方式。
新增Maven依賴
將Whisper的Maven依賴加入到專案中。
<dependency>
<groupId>io.github.benhouse1987</groupId>
<artifactId>whisper</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>>
複製程式碼
初始化翻譯Service
這裡我們使用一個最基本的初始化方式。
該初始化的Service固定將所有內容翻譯成中文。
事實上,你可以直接將這個類複製到你的專案中。
@Configuration
@EnableResourceServer
public class I18nTranslateConfig {
@Autowired
ApplicationContext applicationContext;
@Bean
public I18nTranslateService init() {
//this basic translator service always translate your data in Chinese language
return new I18nTranslateService(applicationContext);
}
}
複製程式碼
現在,Whisper已經準備完畢!
嘗試一下!
Demo 1
將部門名稱翻譯成中文
首先我們寫一個Department類,像這樣:
@Data
public class Department {
// this is the department id , we will translate the department name by this id
@I18nMapping(i18nCode = "id")
private Long departmentId;
// this is the attribute we need to translate
@I18nMapping(i18nCode = "name")
private String departmentName;
private String description;
private Integer level;
}
複製程式碼
假如我們希望把部門名稱翻譯成中文,只需要加兩個I18nMapping
註解,分別用來指定待翻譯實體的id以及,要翻譯的欄位。
在i18n_item表中,我們初始化一條中文翻譯:
insert into `i18n_item` values ( '1', 'zh_cn', 'name', '中文部門', '1', '0', '2018-08-23 21:41:24');
insert into `i18n_item` values ( '1', 'en', 'name', 'english department name', '1', '0', '2018-08-23 21:41:24');
複製程式碼
現在讓我們看看效果!
在Controller中,新增一個示例的api,這個api中,我們返回一個名稱為english department name
的部門:
@Controller
public class DemoController {
@RequestMapping(value = "/getOneDepartment")
@I18nTranslate
@ResponseBody
public Department getOneDepartment() {
Department department = new Department();
department.setDepartmentId(1L);
department.setDepartmentName("english department name");
department.setDescription("english description");
department.setLevel(0);
throw new RuntimeException("i18n exception test");
}
}
複製程式碼
專案執行後,呼叫該api,你會發現Whisper把departmentName
欄位翻譯成了中文!
{
"departmentId": 1,
"departmentName": "中文部門",
"description": "english description",
"level": 0
}
複製程式碼
Demo 2
按指定的語言翻譯(比如使用者的當前語言)
在Demo 1中,我們總是把任何東西翻譯成中文。
如果我們想按照api的呼叫者語言,返回相應語言的翻譯怎麼辦呢?
非常簡單!
建立一個語言翻譯工具類,這個類將幫助我們決定按何種語言翻譯。
這個類需要實現TranslateToolService 介面。
下面是個簡單的示意:
public class MyTranslateToolService implements TranslateToolService {
public String getCurrentLanguage() {
//some exist logic to get current user language
//for example from token or some other table
return someClass.getCurrentUserLanguage();
}
}
複製程式碼
我們需要在I18nTranslateConfig
中,使用新的建構函式初始化I18nTranslateService。
該初始化指定了語言工具類為我們剛才新建的MyTranslateToolService
。
@Configuration
@EnableResourceServer
public class I18nTranslateConfig {
@Autowired
ApplicationContext applicationContext;
@Bean
public I18nTranslateService init() {
return new I18nTranslateService(applicationContext,MyTranslateToolService);
}
}
複製程式碼
現在,Whisper將按照MyTranslateToolService.getCurrentLanguage()
方法的返回語言進行翻譯!
Demo 3
一個國際化異常的例子
也許你希望將返回的錯誤資訊也按照當前使用者的語言來翻譯。
使用Whisper框架做這件事情非常簡單!
建立一個錯誤資訊DTO
假設我們將errorCode
屬性作為i18n的翻譯ID。
我們希望將message
屬性翻譯成不同語言。
只需要加兩個I18nMapping 的 annotation,非常簡單。
@Builder
public class ExceptionDetail {
@I18nMapping(i18nCode = "message")
private String message;
@I18nMapping(i18nCode = "id")
private String errorCode;
}
複製程式碼
建立一個 ControllerAdvice來處理異常
@ControllerAdvice
public class ResourceAdvice {
@ExceptionHandler(RuntimeException.class)
@I18nTranslate
public ResponseEntity<ExceptionDetail> handleValidationException(RuntimeException e) {
ExceptionDetail detail = ExceptionDetail.builder().errorCode("e001").message("cccc").build();
return new ResponseEntity(detail, HttpStatus.BAD_REQUEST);
}
}
複製程式碼
在 i18n_item 表中,初始化兩條翻譯項。
insert into `i18n_item` values ( 'e001', 'zh_cn', 'message', '中文報錯', '1', '0', '2018-08-23 21:41:24');
insert into `i18n_item` values ( 'e001', 'en', 'message', 'english error message', '1', '0', '2018-08-23 21:41:24');
複製程式碼
現在,你丟擲的所有code為e001的報錯都將被翻譯成指定的語言,修改DemoController自己試一試吧!
@Controller
public class DemoController {
@RequestMapping(value = "/getOneDepartment")
@I18nTranslate
@ResponseBody
public Department getOneDepartment() {
Department department = new Department();
department.setDepartmentId(1L);
department.setDepartmentName("english department name");
department.setDescription("english description");
department.setLevel(0);
throw new RuntimeException("i18n exception test");
}
}
複製程式碼
如何建立i18n翻譯項
我們提供了一個簡單的api,幫助你維護i18n翻譯項,你可以通過這個api輕鬆地將你的專案與Whisper整合起來。
這裡是一段樣例程式碼:
@Inject
I18nTranslateService i18nTranslateService;
public Boolean createI18nItems(){
List<I18nTranslateItemDTO> i18nTranslateItemDTOS = new ArrayList<>();
i18nTranslateItemDTOS.add(I18nTranslateItemDTO.builder().i18nKey("1").code("name").language("en").name("department english name").build());
return i18nTranslateService.createOrUpdateI18nItems(i18nTranslateItemDTOS);
}
複製程式碼
注意
我們使用i18nKey,i18nCode,language,作為聯合唯一索引。所以請保證所有的被指定為i18n id的屬性值全域性唯一(@I18nMapping(i18nCode = "id"))。 最佳實踐是使用UUID作為i18n id,你可能需要為需要翻譯的表新增一列i18n_id,並用隨機的UUID填充。