Skip to content

About

Complete Spanish translation for CyberPanel 3.0.3 — 3,303 messages, zero untranslated, zero fuzzy — plus tooling to regenerate it.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

7 Commits

Folders and files

Repository files navigation

CyberPanel · Complete Spanish Translation

Full Spanish locale for CyberPanel 3.0.3 — 3,303 messages, zero untranslated, zero fuzzy — plus the tooling to regenerate it after an upgrade.

English · Español

CI

$ msgfmt --statistics -o /dev/null locale/es/LC_MESSAGES/django.po
3303 translated messages.

No untranslated line, no fuzzy line. That's the whole claim.


What it looks like

Dashboard

Sidebar, breadcrumbs, empty states and quick actions — all from the catalogue.

Create website Email
Every field label, placeholder and helper line on the create-website form. Mail account creation, including the per-domain selector.

Websites

Captured from a CyberPanel 3.0.3 install running this catalogue, signed in as a restricted user with no websites — so no domains appear. The server's IP was replaced with the documentation range 203.0.113.0/24 before publishing. The panel in these shots carries a custom theme; the translation itself is theme-independent.

The problem

Selecting Spanish in CyberPanel leaves most of the interface in English. It looks like missing translations. It isn't — or rather, it's three separate problems that happen to share a symptom:

Cause Entries Obvious?
Empty strings 634 Yes
Marked #, fuzzy 378 No — they were written, then discarded
Absent from the catalogue ~2,000 No — the .po was years behind the templates

msgfmt discards fuzzy entries silently

This is the one that wastes your afternoon. msgfmt skips every entry marked #, fuzzy by default, and says nothing about it. A .po that looks translated when you read it compiles to a .mo that is mostly empty.

msgfmt --statistics -o /dev/null django.po
# 1291 translated messages, 1200 fuzzy translations, 812 untranslated messages.
#                           ^^^^^^^^^^^^^^^^^^^^^^^ these do not ship

The catalogue was behind the templates

CyberPanel 3.0.3's templates contain 3,303 translatable strings. The shipped .po covered roughly a third. Whole screens — Docker, incremental backups, webmail, container management — were added over the years without ever regenerating the locales. Those strings had to be extracted and written from scratch.

Why you can't just clear the fuzzy flags

The tempting one-liner is msgattrib --clear-fuzzy. Don't.

Fuzzy means gettext guessed by string similarity — it isn't a partial translation, it's a translation of a different sentence. Clearing the flags activates confidently wrong text:

English What the fuzzy entry said Actual meaning
List Users Modificar Usuario Modify User
Manage Services Opciones SSL SSL Options
Cancel Cancelar Copia de seguridad Cancel Backup
Save Rewrite Rules Cambios Guardados Changes Saved

141 of these were corrected by hand. The remaining ~1,200 were retranslated from scratch rather than trusted — slower, and the only defensible choice.

makemessages needs -i lib

Without it, Django scans site-packages and pulls ~290 of its own internal strings into your catalogue. That isn't just noise: if any of them end up fuzzy, they override the correct translations Django already ships.

python manage.py makemessages -l es --no-wrap \
    -i node_modules -i venv -i lib -i bin -i lib64 --no-obsolete

You can spot the problem by symptom: if Enter a valid URL or %(model_name)s with this %(field_labels)s already exists show up as untranslated, you're scanning Django itself.

Install

# 1 · Back up the existing catalogue
cp /usr/local/CyberCP/locale/es/LC_MESSAGES/django.po ~/django.po.bak

# 2 · Drop this one in
cp locale/es/LC_MESSAGES/django.po /usr/local/CyberCP/locale/es/LC_MESSAGES/

# 3 · Compile and restart
cd /usr/local/CyberCP/locale/es/LC_MESSAGES
msgfmt --statistics -o django.mo django.po
systemctl restart lscpd

Then hard-refresh the browser. Verify with:

msgfmt --statistics -o /dev/null django.po   # expect: 3303 translated messages.

A CyberPanel upgrade overwrites locale/. Keep this repo around and repeat the three steps, or use the tooling below if the upgrade added new screens.

Regenerating after an upgrade

# Extract what is missing
cd /usr/local/CyberCP/locale/es/LC_MESSAGES
msgattrib --untranslated --no-obsolete --no-wrap django.po > untranslated.po
msgattrib --only-fuzzy    --no-obsolete --no-wrap django.po > fuzzy.po

# Pull the msgids out into a plain list
python3 tools/extract.py            # -> pending.json

# Translate, then write them back (clears fuzzy flags as it goes)
python3 tools/apply.py              # dict.json + django.po -> django.po

# Deduplicate and compile
msguniq --use-first --no-wrap -o django.po django.po
msgfmt --statistics -o django.mo django.po

apply.py escapes quotes and backslashes correctly and verifies that every placeholder count matches between source and translation — a mismatched %s raises at runtime, not at compile time, so it has to be caught here.

Other things worth knowing

  • A duplicate msgid breaks compilation. CyberPanel's original ships "Remote Backups" twice. Fix with msguniq --use-first.
  • Placeholders must match exactly. %s, %(name)s and %% need identical counts on both sides or Django raises while rendering the page.
  • Some {% trans %} tags use single quotes, some have trailing whitespace. {% trans "ModSecurity is not installed " %} — note the space. Any homemade grep-based coverage count will be wrong. msgfmt --statistics is the only measurement that counts what actually ships.

Layout

locale/es/LC_MESSAGES/django.po   the catalogue
tools/extract.py                  pull pending msgids out of msgattrib output
tools/apply.py                    write translations back, clear fuzzy, check placeholders
docs/method.md                    the full procedure

Credits and license

The original Spanish translation is by Francisco Galán, 2018. This repository is a 2026 revision that completes it for CyberPanel 3.0.3.

CyberPanel is licensed GPL-3.0. A translation catalogue derived from its own .po is a derivative work, so this repository carries the same license — see LICENSE.

About

Complete Spanish translation for CyberPanel 3.0.3 — 3,303 messages, zero untranslated, zero fuzzy — plus tooling to regenerate it.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages