# Locales Plugins built on Bookshelf-Locales let you change every piece of text they display, and add languages the developer never shipped. You do it by editing JSON files in the plugin's `locales` folder — no plugin rebuild, no developer involved. > [!info] Per-plugin, not server-wide > Locales belong to the plugin that uses them. Each plugin has its own `locales` folder inside its own data folder, e.g. `plugins/MyPlugin/locales/`. Bookshelf itself does not create one. --- ## The Locales Folder When a plugin ships default translations, it writes them into its `locales` folder on first start: ``` plugins/MyPlugin/ └── locales/ ├── en_us.json └── ja_jp.json ``` Each file is one language. The file name is the language code — `en_us.json` is the locale `en_us`. These files are yours to edit. The plugin will **never** overwrite a file that already exists, so your changes survive updates. --- ## Adding a Language Create a new file named after the language code and write the keys you want translated: `plugins/MyPlugin/locales/fr_fr.json` ```json { "locale.display_name": "Français", "locale.sort_order": "2", "myplugin.welcome": "<green>Bienvenue, <player> !" } ``` That locale now exists. You do not need to translate everything — any key you leave out falls back to the plugin's default language, so a half-finished translation is safe to run. | Key | Purpose | |---|---| | `locale.display_name` | The name shown for this language in a language picker. Falls back to the code. | | `locale.sort_order` | Number controlling its position in that list. Lower comes first. | --- ## Changing Wording To reword something without touching anything else, write **only that key** into the file for that language: ```json { "myplugin.welcome": "<gold>Welcome aboard, <player>!" } ``` Your file takes precedence over both the plugin's built-in defaults and any translations the developer hosts online. Every key you did not write still comes from those defaults. > [!tip] Finding the key > If a plugin displays something like `myplugin.welcome` instead of real text, that is the raw key — the translation is missing. Copy that key into your locale file to define it. --- ## Formatting Values use MiniMessage, the same formatting Bookshelf uses everywhere else. | Syntax | Effect | Example | |---|---|---| | `<red>`, `<gradient:red:blue>` | Colors and styling | `<red>Danger` | | `<player>`, `<count>` | Placeholders the plugin fills in | `Welcome, <player>!` | | `<br>` | Line break | `Line one<br>Line two` | | `<uppercase>…</uppercase>` | Force uppercase | `<uppercase>staff</uppercase>` | | `<lowercase>…</lowercase>` | Force lowercase | `<lowercase>ADMIN</lowercase>` | | `<capitalize>…</capitalize>` | Capitalize each word | `<capitalize>john doe</capitalize>` | | `{other.key}` | Insert another translation | `Hello {myplugin.suffix}` | > [!warning] Only use placeholders the plugin provides > `<player>` works only where the plugin passes a player in. A placeholder the plugin does not fill stays on screen as literal text. Multi-line values can be written as a list, which is easiest to read for item descriptions: ```json { "myplugin.lore": [ "<gray>First line", "<gray>Second line" ] } ``` Keys can also be grouped instead of repeated — these two files behave identically: ```json { "menu": { "title": "Shop", "close": "Close" } } ``` ```json { "menu.title": "Shop", "menu.close": "Close" } ``` --- ## Applying Your Changes Locale files are read when the plugin starts. To apply an edit without a restart, use whatever reload command that plugin provides — the library supports reloading from disk without any network access, so it works while offline. If a file has a JSON syntax error, that one language is skipped and a warning is printed to console naming the file. The rest of the plugin keeps working. --- ## Hosted Translations Some plugins fetch translations from a URL the developer hosts, so new languages and typo fixes arrive without a plugin update. This does not take anything away from you: hosted translations rank **below** your own files. Anything you write in `locales/` wins. ``` your locales/ folder > hosted translations > the plugin's built-in defaults ``` If the plugin caches downloads, you may also see a folder such as `locales-cache/`. That folder is managed automatically and exists so the plugin keeps working when the host is unreachable — do not edit it. Put your changes in `locales/` instead. --- ## Troubleshooting | Symptom | Cause | |---|---| | Text shows as `myplugin.some.key` | No translation defined for that key in any language, including the default. Add it to your locale file. | | Your edit did nothing | The plugin was not reloaded, or the key was written into a language nobody is using. | | A whole language disappeared | JSON syntax error in that file — check console for the warning naming it. | | A placeholder shows as literal `<player>` | That placeholder is not provided where you used it. | | Text reverted after an update | Unlikely — existing files are never overwritten. Check whether you edited the cache folder instead of `locales/`. | --- ## Related Pages - [[Bookshelf/Server Owners/Overview]] — Installation and requirements - [[Bookshelf/Server Owners/Features/Chat System]] — Chat formatting and MiniMessage - [[Bookshelf/Developers/Locales]] — Developer guide to the locale library