-
Notifications
You must be signed in to change notification settings - Fork 14
Localization
Codex keeps its user-facing strings in language files under plugins/CodexCore/lang/.
This is the thing to understand before editing anything. A Codex language file contains strings served by two independent engines with different placeholder syntax, different fallback rules, and different loaders:
| Keys | Engine | Placeholders | Language-aware? |
|---|---|---|---|
general.* |
MessageUtil |
$<name> |
No — always messages_en.yml
|
everything else (Prefix, Codex.*, Error.*, Time.*, the name tables) |
ILangMsg |
%name% |
Yes, via general.lang
|
They do not interoperate. A %placeholder% in a general.* string is literal text, and a $<...>
in an ILangMsg string is likewise inert.
The key that picks the file is
general.lang, which is not present in the shippedconfig.yml. The documentedcore.langis read into a field with no consumers, so setting it does nothing.Adding
general: {lang: cn}by hand does switch theILangMsghalf. Thegeneral.*half is loaded from a hardcodedmessages_en.ymlpath and can never be localised.
general:
lang: cnCodex ships two files:
| Value | File |
|---|---|
en |
lang/messages_en.yml |
cn |
lang/messages_cn.yml |
The two shipped files are near-disjoint rather than large and small versions of each other.
messages_en.yml(25 lines) holds onlycustom-placeholdersandgeneral:— the$<>set.messages_cn.yml(2028 lines) holds only the%…%set, with nogeneral:section at all. The Chinese file is also partly stale: itsCodexCore:root does not match any current key path, and it is missing theCodex.Editor.*keys.
On first run Codex appends every missing ILangMsg default to the file on disk, including full
entity, material, potion, and enchantment name tables — so the 25-line shipped file becomes very
large once generated. Missing %…% keys fall back to their built-in defaults; missing $<> keys do
not — they render as the literal key path, e.g. general.notAPlayer.
The general.* set uses $<name>:
general:
noPermissions: "&cYou don't have permissions ($<permission>)!"
notAPlayer: "&cCan't find player named: $<name>!"
notANumber: "&c\"$<text>\" it's not a number!"Which placeholders are available depends on the message. Keep the ones present in the default string — removing a placeholder is fine, but inventing a new one will render literally.
Note this is separate from the {player} style used by Join and Interact Commands and from
PlaceholderAPI's %…% placeholders.
Standard & codes work everywhere. Hex colours are supported as &#RRGGBB — but the leading & is
optional in the pattern, so a bare #1a2b3c anywhere in a message is silently treated as a
colour too. Watch for that if your text legitimately contains a # followed by six hex digits.
general:
reload: "�ff88Reloaded settings!"The top of the language file defines reusable values you can reference from other messages:
custom-placeholders:
my-color: '#ff0000'
my-text: 'Sample Text'Reference them wrapped in percent signs — %my-color%, %my-text% — and note they are substituted
only into %…%-style messages, never into general.* $<> strings.
Define your own here to keep a colour or phrase consistent across many messages — change it once and every message using it updates.
YAML block scalars are used for messages spanning several lines:
general:
commands:
help: |2-
You typed: &7$<text>&r
Valid syntax:
&8/&7codex &rreload|2- is an ordinary YAML block scalar — a plain |-, |, or a YAML list works identically. For
%…% messages, lines are split on the literal two-character sequence \n rather than real newlines.
A YAML parse error does not fall back to defaults: the main language config throws and the plugin
is disabled, while a broken general.* load leaves every $<> message rendering as its raw key.
%…% messages — and only those — can carry a {message: …} block controlling how they are
delivered. Each argument is written ~name: value;, and the whole block is stripped from the output:
Codex:
Example: '{message: ~type: TITLES; ~fadeIn: 10; ~stay: -1; ~fadeOut: 10;}&aHello'| Argument | Meaning |
|---|---|
type |
CHAT, ACTION_BAR, TITLES, or NONE (suppresses the message entirely) |
prefix |
Boolean; only has effect in CHAT mode |
fadeIn / stay / fadeOut
|
Title timings, in ticks — a stay below 0 is coerced to 10000 |
⚠️ Here the timing flags are camelCase —~fadeIn:,~fadeOut:. The Actions Engine uses identical-looking~flag: value;syntax but a different parser that requires them lowercase (~fadein:,~fadeout:). Copying a line between the two will silently drop the timings.
World display names are configured in config.yml rather than the language file, since they are
per-server rather than per-language:
locale:
world-names:
world: 'World'
world_nether: 'Nether'See Configuration.
⚠️ /codex reloaddoes not re-read language files. The config objects are built once at startup, and the engine's reload only re-applies what is already in memory. Edit your language file and restart the server. See Configuration.
The command itself requires codexcore.admin — see Permissions.
Source · Issues · Discord · Maven repo
Server Owners
- Installation
- Configuration
- Commands
- Permissions
- Join and Interact Commands
- Localization
- Version Support
Deprecated
-
Chat Module
⚠️ -
Scoreboard Module
⚠️
Developers