Wisper is a lightweight I18n translation framework that is easy to use, performs well, and is easy to extend.

Let’s see how to get started with Whisper!

Suppose you have a Spring-based project and the project’s dataSource is already configured.

Sample Whisper code can be linked below

Whisper Demo

The preparatory work

Create I18n translation table

Create an I18N table in the database on which your service is based to store translation relationships.

If you happen to use Mysql, you can create this table directly using the following script:

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;

Copy the code

The implementation of the rest of the database will be covered soon, and contributions from other libraries are welcome.

Adding Maven dependencies

Add Whisper’s Maven dependencies to the project.

<dependency> <groupId>io.github.benhouse1987</groupId> <artifactId>whisper</artifactId> < version > 1.0.0 - the SNAPSHOT < / version > < / dependency > >Copy the code

Initialize the translation Service

Here we use a very basic initialization method.

The initialized Service fixes everything into Chinese.

In fact, you can copy this class directly into your project.

@Configuration
@EnableResourceServer
public class I18nTranslateConfig {

    @Autowired
    ApplicationContext applicationContext;

    @Bean
    public I18nTranslateService init() {
        //this basic translator service always translate your data in  Chinese language
        returnnew I18nTranslateService(applicationContext); }}Copy the code

Now Whisper is ready!

Try it!

Demo 1

Translate the department name into Chinese

First we write a Department class like this:


@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;
    
    
}

Copy the code

If we want to translate the department name into Chinese, we only need to add two I18nMapping annotations to specify the ID of the entity to be translated and the field to be translated.

In the i18n_item table, we initialize an item.

insert into `i18n_item`  values ( '1'.'zh_cn'.'name'.'Chinese Department'.'1'.'0'.'the 2018-08-23 21:41:24');
insert into `i18n_item`  values ( '1'.'en'.'name'.'english department name'.'1'.'0'.'the 2018-08-23 21:41:24');
Copy the code

Now let’s see the effect!

In Controller, add a sample API where we return a department named 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"); }}Copy the code

After the project runs, call the API and you’ll see that Whisper has translated the departmentName field into Chinese!

{
    "departmentId": 1,
    "departmentName": "Chinese Department"."description": "english description"."level": 0}Copy the code

Demo 2

Translation in the specified language (such as the user’s current language)

In Demo 1, we always translate everything into Chinese.

What if we want to return the translation of the API’s caller’s language?

Very simple!

Create a language translation utility class that will help us decide which language to translate in.

This class needs to implement the TranslateToolService interface.

Here’s a simple hint:

public class MyTranslateToolService implements TranslateToolService {


    public String getCurrentLanguage() {

        //some exist logic to get current user language
        //for example from token or some other table
        returnsomeClass.getCurrentUserLanguage(); }}Copy the code

We need to initialize I18nTranslateService using the new constructor in I18nTranslateConfig.

This initialization specifies the language utility class as the MyTranslateToolService we just created.

@Configuration
@EnableResourceServer
public class I18nTranslateConfig {

    @Autowired
    ApplicationContext applicationContext;

    @Bean
    public I18nTranslateService init() {        
        returnnew I18nTranslateService(applicationContext,MyTranslateToolService); }}Copy the code

Now, will Whisper in MyTranslateToolService. GetCurrentLanguage () method returns the language for translation!

Demo 3

An example of an internationalization exception

Perhaps you want to translate the returned error message to the current user’s language as well.

Using the Whisper framework to do this is easy!

Create an error message DTO

Suppose we use the errorCode attribute as the translation ID for i18N.

We want to translate the Message attribute into different languages.

Just add two I18nMapping annotations, it’s pretty easy.

   @Builder
   public class ExceptionDetail {
       @I18nMapping(i18nCode = "message")
       private String message;
   
       @I18nMapping(i18nCode = "id")
       private String errorCode;
   }
Copy the code

Create a ControllerAdvice to handle exceptions


@ControllerAdvice
public class ResourceAdvice {
    @ExceptionHandler(RuntimeException.class)
    @I18nTranslate
    public ResponseEntity<ExceptionDetail> handleValidationException(RuntimeException e) {

        ExceptionDetail detail = ExceptionDetail.builder().errorCode("e001").message("cccc").build();

        returnnew ResponseEntity(detail, HttpStatus.BAD_REQUEST); }}Copy the code

In the i18N_item table, initialize two translation items.

insert into `i18n_item`  values ( 'e001'.'zh_cn'.'message'.'Error in Chinese'.'1'.'0'.'the 2018-08-23 21:41:24');
insert into `i18n_item`  values ( 'e001'.'en'.'message'.'english error message'.'1'.'0'.'the 2018-08-23 21:41:24');
Copy the code

Now, all errors you throw with code E001 will be translated into the specified language, modify DemoController and try it yourself!


@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"); }}Copy the code

How do I create i18N translation entries

We provide a simple API to help you maintain i18N translation items, which allows you to easily integrate your project with Whisper.

Here is a sample code:

        @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);
	}
Copy the code

Pay attention to

We use i18nKey i18nCode, language, as a unique index. Therefore, ensure that all attribute values specified as i18N ID are globally unique (@i18NMapping (i18nCode = “ID “)). The best practice is to use the UUID as the I18N ID. You may need to add a column of i18N_ID for the table to be translated and populate it with a random UUID.