This guide explains how to contribute translations for HyperFactions.
-
Run the scaffolding script to create a new locale:
./scripts/new-translation.sh fr-FR # Linux/Mac scripts\new-translation.bat fr-FR # Windows
-
Edit the
.langfiles insrc/main/resources/Server/Languages/<locale>/ -
Edit the help markdown files in
src/main/resources/Server/Languages/<locale>/help/ -
Build to verify:
./gradlew :HyperFactions:shadowJar -
Submit a pull request
| Code | Language | Status |
|---|---|---|
| en-US | English (US) | Complete |
| es-ES | Spanish (Spain) | Complete |
| de-DE | German | Untranslated |
| fr-FR | French | Untranslated |
| it-IT | Italian | Untranslated |
| nl-NL | Dutch | Untranslated |
| pl-PL | Polish | Untranslated |
| pt-BR | Brazilian Portuguese | Untranslated |
| ru-RU | Russian | Untranslated |
| tl-PH | Filipino (Tagalog) | Untranslated |
Located at src/main/resources/Server/Languages/<locale>/:
| File | Content | Key Count |
|---|---|---|
hyperfactions.lang |
Commands, errors, common strings | ~800 |
hyperfactions_gui.lang |
GUI labels, buttons, nav | ~830 |
hyperfactions_admin.lang |
Admin GUI strings | ~840 |
hyperfactions_help.lang |
Help system content (auto-generated) | varies |
# Section comments start with #
key.name = Translated value here
key.with.placeholder = Hello {0}, you have {1} powerRules:
- Keys are on the left side of
=— never modify keys - Values are on the right side — translate these
{0},{1}, etc. are placeholders — keep them in the translation- Lines starting with
#are comments — translate for context but not required - Blank lines are ignored
- Backslash
\at end of line continues to next line
Located at src/main/resources/Server/Languages/<locale>/help/<category>/<topic>.md.
Each file has YAML frontmatter and markdown content. See docs/help-markdown.md for the full syntax reference.
| Markdown Syntax | Entry Type | Translate? |
|---|---|---|
# Heading |
Topic title | Yes |
## Subheading |
HEADING | Yes |
| Plain text line | TEXT | Yes |
| Blank line | SPACER | Keep as-is |
`command text` |
COMMAND | No — command syntax stays in English |
**bold text** |
BOLD | Yes |
*italic text* |
ITALIC | Yes |
- list item |
LIST | Yes |
1. numbered item |
LIST | Yes (translate text, keep number) |
--- |
SEPARATOR | Keep as-is |
> tip text |
CALLOUT | Yes |
>[!TYPE] text |
CALLOUT | Yes (translate text only) |
[#RRGGBB] text |
TEXT (colored) | Yes (translate text only) |
!warning text |
TEXT (colored) | Yes (translate text only) |
| col | col | header row |
TABLE_HEADER | Yes (translate column labels) |
| val | val | data row |
TABLE_ROW | Yes (translate cell values) |
|---|---| separator |
— (consumed) | Keep as-is |
These are syntax markers or identifiers — keep them exactly as written:
- Frontmatter:
id:andcommands:values - Command syntax:
/f create <name>,/f claim, etc. - Color codes:
[#FF5555],[#55AAFF], etc. - Named color keywords:
!warning,!success,!note,!muted - Callout type tags:
>[!WARNING],>[!TIP],>[!INFO],>[!NOTE],>[!SUCCESS] - Separator syntax:
--- - Table separators:
|---|---|---|(the row between header and data) - Table pipe syntax:
|characters (keep the pipe structure intact)
- Topic titles (
# Getting Started) - Heading text after
## - Plain text lines
- Text content in bold (
**text here**) and italic (*text here*) - List item text (after
-or1.) - Callout text (after
>or>[!TYPE]) - Colored text (after
[#RRGGBB]or!warning) - Table header labels and data cell values (between
|pipes)
Example:
# Getting Started ← Translate: "Primeros Pasos"
## How Claims Work ← Translate: "Como Funcionan los Reclamos"
`/f claim` ← Do NOT translate
- Stand in the chunk ← Translate: "- Parate en el chunk"
>[!WARNING] Don't wander off! ← Translate: ">[!WARNING] No te alejes!"
!note Power regenerates ← Translate: "!note El poder se regenera"
[#FF5555] Important info ← Translate: "[#FF5555] Informacion importante"GUI labels have limited space. Keep translations concise:
| Element Type | Max Length (approx) |
|---|---|
| Nav bar buttons | 12 characters |
| Button labels | 20 characters |
| Section titles | 30 characters |
| Descriptions | 60 characters |
| Chat messages | No limit |
| Help content | No limit |
If a translation is too long, it may overflow or be truncated in the UI.
Use commonly understood gaming terms in your language. Some terms are typically kept in English across all languages:
- PvP (Player vs Player)
- PvE (Player vs Environment)
- NPC (Non-Player Character)
- K/D (Kill/Death ratio)
- UUID
- chunk (a 16x16 block area)
Brand names should not be translated:
- HyperFactions
- HyperPerms
- OrbisGuard
- HyperProtect
Placeholders like {0}, {1} are replaced at runtime with dynamic values. The order matters — {0} is always the first argument, {1} the second, etc.
Common placeholder meanings (by context):
{0}in faction messages: usually faction name or player name{0}in error messages: usually the specific value that failed{0},{1}in range messages: min and max values
Use consistent terminology throughout your translation:
- Pick one word for "faction" and use it everywhere
- Pick one word for "claim/territory" and use it consistently
- Role names should be consistent (Leader, Officer, Member, Recruit)
# Build (generates help .lang from markdown + compiles)
./gradlew :HyperFactions:shadowJar
# Deploy to dev server
./gradlew buildAndDeploy
# In-game: change your client language to test# Compare key counts between locales
./gradlew :HyperFactions:checkTranslationsThis task reports any keys present in en-US but missing in other locales.
- Fork the repository
- Create a branch:
feat/i18n-<locale>(e.g.,feat/i18n-fr-FR) - Run
./scripts/new-translation.sh <locale>if starting fresh - Translate all
.langfiles and help.mdfiles - Build and test locally
- Submit a pull request
- Translations are reviewed by native speakers when possible
- Machine translations are accepted as a starting point but should be refined
- Partial translations are welcome — untranslated keys fall back to English