國際化的實現i18n--錯誤碼國際化以及在springboot項目中使用


國際化 ,英文叫 internationalization 單詞太長 ,又被簡稱為 i18n(取頭取尾中間有18個字母);

主要涉及3個類: Locale用來設置定制的語言和國家代碼 

       ResourceBundle 用來加載國際化資源文件

       MessageFormat 用來格式化占位符

//先看結構:

 

在創建國際化資源文件時,如我在resources文件下建了一個i18n文件夾,下放了3個資源文件,idea自動會生成一個Resource Bundle 'messages'文件夾,這個文件夾不是真實存在的,打開項目所在文件夾后,找不到它的;如圖:

資源文件的命名格式:前綴+"_"+"語言代碼"+地區代碼+".properites";(

Locale[] locales = Locale.getAvailableLocales();//獲取世界可用的語言地區表示

)

如上圖所示,我定義了3個資源文件夾,其中一個沒有語言代碼和地區代碼的那個是默認資源,也就是要找的資源文件都不存在時,就會去那里找;

查找順序,如果你指定Locale locale=new Locale("en_US"),那它就會找到messages_en_US.properties,如果你寫錯了一個單詞Locale locale=new Locale("en_USAA");找不到的話,它就會找本地的語言(

Locale locale2 = Locale.getDefault(); //獲取默認語言地區

),如我們在中國就會找本地的中國語言包messages_zh_CN.properties,如果沒有本地的語言包messages_zh_CN.properties,就會去messages.properties這里找

資源文件的內容格式為:key=value,其中value值可以含有占位符,格式{數字},例如" 你的訂單號{0}的訂單,金額{1}元";

key和value值在properties文件中都不用加雙引號

注意:

資源文件中的所有字符都必須是 ascll 碼 ,不能保存為中文的 ,Java 中提供 了 native2ascll 工具用於將中文轉化為 ascll 碼 。所以在編寫 properties 文件的時候寫的是中文 ,一回車就自動被編碼了 。

在idea工具中,可以設置顯示為中文:

后端做國際化用得比較多的情況是錯誤碼國際化:具體代碼如下:

 

 @Test
    public void test2(){
        Locale locale1 = new Locale("en_US");
        Locale locale2 = Locale.getDefault(); //獲取默認語言地區
        System.out.println(locale2.getCountry()); //CN
        System.out.println(locale2.getDisplayCountry()); //中國
        System.out.println(locale2.getDisplayLanguage()); //中文
        System.out.println(locale2.getDisplayName()); //中文(中國)
        System.out.println(locale2.getDisplayLanguage(locale1)); //以某種語言顯示語言,這里是Chinese
        System.out.println(locale2.getLanguage()); //zh 語言代表符
        System.out.println(locale2.toLanguageTag()); //語言標簽 格式語言-國家 這里是zh-CN
        //Locale自定義了很多語言跟國家常量 如中國 和中文,德國和德文
        Locale china = Locale.CHINA; // zh-Cn
        Locale chinese = Locale.CHINESE; //ZH
        System.out.println(china.toLanguageTag()); //ZH-CN
        System.out.println(chinese.toLanguageTag()); //ZH
        Locale german = Locale.GERMAN; //de
        Locale germany = Locale.GERMANY; //de-DE
        System.out.println(german.toLanguageTag());//de
        System.out.println(germany.toLanguageTag());//de-DE
        Locale[] locales = Locale.getAvailableLocales();//獲取世界可用的地區
        for (Locale locale : locales) {
            System.out.println(locale.toLanguageTag());
        }
        ResourceBundle resourceBundle = ResourceBundle.getBundle("i18n/messages",locale2); //這里的baseName也可以表示成i18n.messages形式,messages是虛擬的包名

        String s = resourceBundle.getString("103014"); //我在資源文件存了:103014=訂單號為{0}的訂單已經支付
        MessageFormat messageFormat = new MessageFormat(s);
        String format = messageFormat.format(new String[]{"100002222"});
        System.out.println(format);//輸出值(訂單號為{100002222}的訂單已經支付)


    }

//稍微封裝:
 private String getErrorMessage(String language,String errorCode,String ...params){
        Locale locale=null;
        if(StringUtils.isEmpty(language)){
            locale=new Locale("zh_CN");
        }

        locale=new Locale(language);
        ResourceBundle bundle = ResourceBundle.getBundle("i18n/messages",locale);
        String msg = bundle.getString(errorCode);
        if(StringUtils.isEmpty(msg)){
            return null;
        }
        MessageFormat messageFormat = new MessageFormat(msg);
        String format = messageFormat.format(params);
        return format;

    }
  @Test
    public void testI18n() throws IOException {
   
      //key=value 103032=Order No.{0} and No.{1} has not been linked
        System.out.println(getErrorMessage("en_US", "103032", "dddd", "vvvvvv"));

    }//輸出為Order No.dddd and No.vvvvvv has not been linked



補充:注意下面的區別:下划線和橫線用在不同方法,建議使用

Locale locale = new Locale("en_US");

Locale locale2 =Locale.forLanguageTag("en-US"); //推薦使用這種方式
 

 //springboot項目中使用國際化,非常簡單:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JestTest {
    @Autowired
    private MessageSource messageSource;

    @Test
    public void testI18n() throws IOException {

        Locale locale2 = Locale.forLanguageTag("en-US");

        Object[] arr = {"dddd", "vvvvvv"};
        //key=value    103032=Order No.{0} and No.{1} has not been linked
        System.out.println(messageSource.getMessage("103032", arr, locale2));
        //輸出結果:Order No.dddd and No.vvvvvv has not been linked

    }

}
需要在application.yml中配置:
messages:
always-use-message-format: false # Whether to always apply the MessageFormat rules, parsing even messages without arguments.
basename: i18n/messages # Comma-separated list of basenames (essentially a fully-qualified classpath location), each following the ResourceBundle convention with relaxed support for slash based locations.
cache-duration: # Loaded resource bundle files cache duration. When not set, bundles are cached forever. If a duration suffix is not specified, seconds will be used.
encoding: UTF-8 # Message bundles encoding.
fallback-to-system-locale: true # Whether to fall back to the system Locale if no files for a specific Locale have been found.
use-code-as-default-message: false # Whether to use the message code as the default message instead of throwing a "NoSuchMessageException". Recommended during development only.
如果報這個:org.springframework.context.NoSuchMessageException: No message found under code '103032' for locale 'en_us'
非常有可能是上面的messages在application.yml的位置沒配置對,messages要配置在spring的下一級,如圖所示:

 

 

 錯誤配置如下:

 

                          

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM