> For the complete documentation index, see [llms.txt](https://edseries-plugins.gitbook.io/p/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://edseries-plugins.gitbook.io/p/edlang/reference/developer-api.md).

# Developer API

Most plugins need no code at all: a placeholder in any text a player sees is translated by the packet translator. The API is for texts a plugin wants in one language itself (a log line, a book written for one player, a database row), to build placeholders, and to react to language changes.

## Setup

```xml
<dependency>
    <groupId>es.edwardbelt</groupId>
    <artifactId>edlang</artifactId>
    <version>2.0.0</version>
    <scope>provided</scope>
</dependency>
```

`plugin.yml`: `softdepend: [EdLang]`. Keep every call behind `Bukkit.getPluginManager().isPluginEnabled("EdLang")` (or `EdLangAPI.isEnabled()`), and reach EdLang classes through a small nested class so they are only loaded when EdLang is there. Everything is in `es.edwardbelt.edlang.api`; every method is safe from any thread unless noted.

## EdLangAPI

```java
// texts
String  translate(String text, Player viewer)          // placeholders in the viewer's language (null = default)
String  translate(String text, String code)
List<String> translate(List<String> lines, Player viewer)
Component translate(Component component, Player viewer)
Component translate(Component component, String code)
boolean hasPlaceholder(String text)
String  placeholder(String key, String... args)        // "{lang:key|a|b}" with escaping, or "%lang_key%"
String  get(String key, Player viewer)                 // a key's raw value, or null
String  format(String key, Player viewer, String... args)      // filled in, § colours
Component component(String key, Player viewer, String... args)
ItemStack translateItem(ItemStack item, String code)   // a copy with name and lore translated

// languages and players
String  language(Player player)                        // code
String  language(UUID uuid)
String  defaultLanguage()
boolean isDefault(Player player)
boolean isAutomatic(UUID uuid)
Set<String> languages()
List<LanguageInfo> languageInfos()                     // code, name, isDefault
LanguageInfo languageInfo(String code)
LanguageInfo languageInfo(Player player)
boolean setLanguage(Player player, String code)        // null = automatic; main thread
boolean chatTranslation(UUID uuid)
void    setChatTranslation(UUID uuid, boolean on)
void    refresh(Player player)                         // re-send holograms, items, boss bars, sidebar, tab; main thread
Map<String, List<Player>> group(Collection<? extends Player> players)   // players by language code
```

`translate` returns the same String when the text has no placeholder and a cached String otherwise, so it is fine on hot paths. Translate the RAW config text first, then fill in your `{tokens}`, PlaceholderAPI and colours.

```java
// a broadcast built once per language
EdLangAPI.group(Bukkit.getOnlinePlayers()).forEach((code, players) -> {
    String line = EdLangAPI.format("myplugin.event.start", players.get(0), eventName);
    players.forEach(p -> p.sendMessage(line));
});
```

## Events

| Event                       |                                                                                                                                                                                                                                           |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PlayerLanguageChangeEvent` | An online player's language changed (`/lang`, client language, reload). `getPrevious()`, `getLanguage()`. Refresh texts you cache per player. Not fired for the language set on join (that happens before other plugins' join listeners). |
| `LanguagesReloadEvent`      | `/edlang reload` finished: drop texts you cache per language.                                                                                                                                                                             |
| `ChatTranslateEvent`        | A chat message is about to be translated (async, cancellable). `getMessage()`, `getTargets()` (mutable set of language codes).                                                                                                            |

## Upgrading from the 1.x API

Every 1.x method keeps its signature and behaviour. `translate` now also handles `{lang:...}`, and `translateItem` replaces placeholders first. Plugins built against 1.0.0 work unchanged.
