多語言文件

此為 v0.0.8 後的功能。

多語言文件,指一個訊息集合下可有多種不同的語言,可用作 i18n

假設你的插件 jar 內有兩種語言文件:

Langs/en-us.yml
prefix: "[ELD] "
first: "This is the first message"
second: "This is the second message"
third: "This is the third message"
Langs/zh-tw.yml
prefix: "[ELD] "
first: "這是第一則信息"
second: "這是第二則訊息"
third: "這是第三則信息"

則創建一個繼承 GroupLangConfiguration 的類,並配置如下:

@GroupResource(
        folder = "Langs", // 語言文件的文件夾
        preloads = {"en-us", "zh-tw"} // 複製這兩個文件從 jar 內到 插件資料夾
)
@DefaultLanguage("en-us") // 定義默認語言
@Prefix(path = "prefix") // 定義prefix路徑
public class TesterMultiLang extends GroupLangConfiguration {
}

註冊如下:

    @Override
    public void bindServices(ServiceCollection serviceCollection) {
        serviceCollection.addMultipleLanguages(TesterMultiLang.class); // 註冊多語言文件
    }

使用

註冊完成後,則可注入 GroupLang<T> 服務並標註 @InjectPool 來進行獲取:

@Commander(
        name = "lang",
        description = "test language command"
)
public class TestLanguageCommand implements CommandNode {

    @InjectPool
    private GroupLang<TesterMultiLang> multiLangGroupLang;

    @CommandArg(order = 1)
    private String language;

    @Override
    public void execute(CommandSender commandSender) {
        Optional<TesterMultiLang> multiLangOpt = multiLangGroupLang.getByLocale(language);
        if (multiLangOpt.isEmpty()){
            commandSender.sendMessage("unknown language");
            return;
        }
        var multiLang = multiLangOpt.get();
        commandSender.sendMessage(multiLang.getLang().get("first"));
        commandSender.sendMessage(multiLang.getLang().get("second"));
        commandSender.sendMessage(multiLang.getLang().get("third"));
    }
}

在上述的指令中, 輸入 /test lang en-us 將出現 en-us.yml 文件內的訊息,輸入 /test lang zh-tw 則出現 zh-tw.yml 文件內的訊息。若查無文件,則發送 unknown language 。

在使用上,你會發現跟 文件池配置 其實很相同。但兩者的分別在於,GroupLang<T> 只提供了唯讀性質的操作。其源碼如下:

public interface GroupLang<T extends GroupLangConfiguration> {

    /**
     * 根據 語言 id 獲取語言文件實例
     * @param locale 語言 id
     * @return 語言文件實例
     */
    Optional<T> getByLocale(String locale);

    /**
     * 獲取默認語言文件實例
     * @return 默認語言文件實例
     */
    T getDefault();

    /**
     * 根據 語言 id 清除快取
     * @param locale 語言 id
     */
    void fetchById(String locale);

    /**
     * 清除所有快取
     */
    void fetch();


}

GroupConfig<T>同樣,GroupLang<T> 本身的操作也不是異步的,你需要自行實作異步。但它本身亦有快取功能,能大程度上加快二次獲取。

有時候你可能需要手動去獲取特定類型的 GroupLang<T>,這時候你應該使用文件池服務

使用為 i18n

你可以透過多語言文件實作 i18n 的服務,範例如下:

I18nService.java
public interface I18nService {
    
    void sendMessage(Player player, String path);
    
    void switchLanguage(Player player, String lang);
    
}
I18nServiceImpl.java
public class I18nServiceImpl implements I18nService {

    private final Map<UUID, String> languageMap = new HashMap<>(); // 語言儲存資料庫,你應實作離線儲存

    @InjectPool
    private GroupLang<TesterMultiLang> languagePool;

    // 根據玩家的語言發送訊息
    @Override
    public void sendMessage(Player player, String path) {
        String lang = languageMap.getOrDefault(player.getUniqueId(), "en-us");
        var langConfig = languagePool.getByLocale(lang).orElseGet(() -> {
            player.sendMessage("由於沒有你的語言 (".concat(lang).concat("), 因此使用回默認語言 en-us"));
            return languagePool.getDefault();
        }); // 發送玩家所使用的語言的訊息, 若無則自動返回默認語言文件
        player.sendMessage(langConfig.getLang().get(path));
    }

    // 切換語言
    @Override
    public void switchLanguage(Player player, String lang) {
        languageMap.put(player.getUniqueId(), lang);
    }
}

記得別忘了註冊!

最后更新于