# RemoteLocaleSource
> Locales fetched over HTTP from a manifest you host, with an on-disk cache served when the host is unreachable.
`gg.lode.bookshelflocales.source.RemoteLocaleSource`
---
## Signature
```java
public final class RemoteLocaleSource implements LocaleSource
```
Hard-code one manifest URL and your plugin can ship no locale files at all — new languages and typo fixes reach servers on the next reload, with no plugin update.
---
## Manifest Format
A flat JSON object of language code to download URL:
```json
{
"en_us": "https://cdn.example.com/locales/en_us.json",
"ja_jp": "https://cdn.example.com/locales/ja_jp.json"
}
```
Relative entries such as `"en_us.json"` resolve against the manifest's own URL. Each linked document is an ordinary locale file.
---
## Methods
| Method | Return Type | Description |
|--------|-------------|-------------|
| `header(String name, String value)` | `RemoteLocaleSource` | Adds a request header sent with the manifest and every locale download. |
| `timeout(Duration timeout)` | `RemoteLocaleSource` | Per-request timeout. Defaults to 10 seconds. |
| `cacheFolder(Path folder)` | `RemoteLocaleSource` | Writes each successful download to disk and serves that copy when the host is unreachable. |
| `manifestUrl()` | `String` | The configured manifest URL. |
| `isRemote()` | `boolean` | Always `true`, grouping this source with `reloadFromCloud()`. |
All setters return the source, so they chain.
---
## Failure Behavior
| Failure | Result |
|---|---|
| Manifest unreachable, cache configured | The cached locales are served and a warning is logged. |
| Manifest unreachable, no cache | Nothing is returned; [[LocaleManager]] keeps the previous copy rather than dropping to raw keys. |
| One locale fails to download | That locale falls back to its cached copy; the others load normally. |
| Malformed manifest | Warning naming the URL; the source returns its cache, if any. |
A CDN outage costs you fresh text, not all text.
---
## Usage
```java
LocaleManager locales = LocaleManager.builder()
.defaultLocale("en_us")
.remote("https://cdn.example.com/locales/manifest.json", source -> source
.header("Authorization", "Bearer " + token)
.timeout(Duration.ofSeconds(5))
.cacheFolder(getDataFolder().toPath().resolve("locales-cache")))
.folder(getDataFolder().toPath().resolve("locales"))
.build();
locales.reloadFromCloudAsync();
```
> [!warning] Never fetch on the main thread
> Loading this source blocks on HTTP. Use `reloadFromCloudAsync()` from command handlers.
Register remote sources **before** `folder(...)`: hosted locales are still defaults, so a server owner's local edit should outrank them.
---
## Related Pages
- [[LocaleSource]]
- [[LocaleManager]]
- [[Bookshelf/Developers/Locales]]