# 多語言文件

多語言文件，指一個訊息集合下可有多種不同的語言，可用作 [i18n](https://openhome.cc/Gossip/Rails/i18n.html)。

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

{% code title="Langs/en-us.yml" %}

```yaml
prefix: "[ELD] "
first: "This is the first message"
second: "This is the second message"
third: "This is the third message"
```

{% endcode %}

{% code title="Langs/zh-tw\.yml" %}

```yaml
prefix: "[ELD] "
first: "這是第一則信息"
second: "這是第二則訊息"
third: "這是第三則信息"
```

{% endcode %}

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

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

```

註冊如下:

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

## 使用

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

```java
@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"));
    }
}
```

{% hint style="success" %}
在上述的指令中, 輸入 /test lang en-us 將出現 en-us.yml 文件內的訊息，輸入 /test lang zh-tw 則出現 zh-tw\.yml 文件內的訊息。若查無文件，則發送 `unknown language 。`
{% endhint %}

在使用上，你會發現跟 [文件池配置](/eldependenci/advanced-tutorial/config-operation/configuration-pool.md) 其實很相同。但兩者的分別在於，`GroupLang<T>` 只提供了唯讀性質的操作。其源碼如下：

```java
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();


}
```

{% hint style="warning" %}
跟 `GroupConfig<T>`同樣，`GroupLang<T>` 本身的操作也不是異步的，你需要自行實作異步。但它本身亦有快取功能，能大程度上加快二次獲取。

有時候你可能需要手動去獲取特定類型的 `GroupLang<T>`，這時候你應該使用[文件池服務](/eldependenci/references/internal-api-services/config-pool-service.md)。
{% endhint %}

## 使用為 i18n&#x20;

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

{% code title="I18nService.java" %}

```java
public interface I18nService {
    
    void sendMessage(Player player, String path);
    
    void switchLanguage(Player player, String lang);
    
}
```

{% endcode %}

{% code title="I18nServiceImpl.java" %}

```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);
    }
}
```

{% endcode %}

{% hint style="info" %}
記得別忘了註冊！
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://eric2788.gitbook.io/eldependenci/advanced-tutorial/config-operation/i18n.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
