使用Whisper框架快速為專案新增國際化支援

大白長老發表於2018-08-27

Wisper是一個輕量級I18n翻譯框架,簡單易用,效能出色,並且擴充套件簡單。

讓我們看看如何開始使用Whisper!

假設你有一個基於Spring的專案,並且專案的dataSource已經配置好。

可以在下面連結得到Whisper的樣例程式碼

Whisper Demo

準備工作

建立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填充。

相關文章