Python Tool Translation Guide
This guide covers translating GhostBSD Python applications using the standard workflow implemented in update-station.
Prerequisites
Python development environment
Git access to the repository
Text editor for .po files
gettext tools:
sudo pkg install gettext-tools
Setup.py Implementation
GhostBSD Python tools use these custom setuptools commands (based on update-station):
import os
import glob
from setuptools import setup, Command
from DistUtilsExtra.command.build_extra import build_extra
from DistUtilsExtra.command.build_i18n import build_i18n
from DistUtilsExtra.command.clean_i18n import clean_i18n
class UpdateTranslationsCommand(Command):
"""Custom command to extract messages and update .po files."""
description = 'Extract messages to .pot and update .po'
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
pot_file = 'po/[tool-name].pot'
po_files = glob.glob('po/*.po')
# Extract messages to .pot file
print("Extracting messages to .pot file...")
os.system(f'xgettext --from-code=UTF-8 -L Python -o {pot_file} [tool_directory]/*.py [main-script]')
# Update .po files
print("Updating .po files with new translations...")
for po_file in po_files:
print(f"Updating {po_file}...")
os.system(f'msgmerge -U {po_file} {pot_file}')
print("Translation update complete.")
class CreateTranslationCommand(Command):
"""Custom command to create a new .po file for a specific language."""
description = 'Create a new .po file for the specified language'
user_options = [
('locale=', 'l', 'Locale code for the new translation (e.g., fr_FR, pt_BR)')
]
def initialize_options(self):
self.locale = None
def finalize_options(self):
if self.locale is None:
raise Exception("You must specify the locale code (e.g., --locale=fr_FR)")
def run(self):
pot_file = 'po/[tool-name].pot'
po_dir = 'po'
po_file = os.path.join(po_dir, f'{self.locale}.po')
# Create .pot file if needed
if not os.path.exists(pot_file):
print("Extracting messages to .pot file...")
os.system(f'xgettext --from-code=UTF-8 -L Python -o {pot_file} [tool_directory]/*.py [main-script]')
# Create new .po file
if not os.path.exists(po_file):
print(f"Creating new {po_file} for locale '{self.locale}'...")
os.makedirs(po_dir, exist_ok=True)
os.system(f'msginit --locale={self.locale} --input={pot_file} --output-file={po_file}')
else:
print(f"PO file for locale '{self.locale}' already exists: {po_file}")
setup(
cmdclass={
'create_translation': CreateTranslationCommand,
'update_translations': UpdateTranslationsCommand,
'build': build_extra,
'build_i18n': build_i18n,
'clean': clean_i18n
}
)
Translation Workflow
1. Clone Repository
git clone https://github.com/ghostbsd/[tool-name]
cd [tool-name]
2. Create New Translation
python setup.py create_translation --locale=fr_FR
Creates po/fr_FR.po with proper locale settings.
3. Update Translations
After code changes:
python setup.py update_translations
Updates all .po files with new/changed strings.
4. Edit Translations
Edit the .po file:
#: update_station/main.py:45
msgid "Network Manager"
msgstr "Gestionnaire de R�seau"
5. Build and Test
python setup.py build
LANG=fr_FR.UTF-8 python3 [main-script]
Directory Structure
repository/
po/
[tool-name].pot # Template (generated)
fr_FR.po # French (France)
fr_CA.po # French (Canada)
pt_BR.po # Portuguese (Brazil)
build/
lib/
locale/ # Compiled .mo files
setup.py # Translation commands
Locale Format
Use full locale format language_COUNTRY following install-station standard:
Supported Locales (from install-station)
ar_EG- Arabic (Egypt)bg_BG- Bulgarian (Bulgaria)bn_BD- Bengali (Bangladesh)ca_ES- Catalan (Spain)cs_CZ- Czech (Czech Republic)da_DK- Danish (Denmark)de_DE- German (Germany)el_GR- Greek (Greece)en_GB- English (United Kingdom)en_US- English (United States)es_ES- Spanish (Spain)es_MX- Spanish (Mexico)et_EE- Estonian (Estonia)eu_ES- Basque (Spain)fi_FI- Finnish (Finland)fr_CA- French (Canada)fr_FR- French (France)gl_ES- Galician (Spain)he_IL- Hebrew (Israel)hi_IN- Hindi (India)hr_HR- Croatian (Croatia)hu_HU- Hungarian (Hungary)id_ID- Indonesian (Indonesia)is_IS- Icelandic (Iceland)it_IT- Italian (Italy)ja_JP- Japanese (Japan)ko_KR- Korean (South Korea)lt_LT- Lithuanian (Lithuania)lv_LV- Latvian (Latvia)mk_MK- Macedonian (North Macedonia)nb_NO- Norwegian Bokmål (Norway)nl_NL- Dutch (Netherlands)nn_NO- Norwegian Nynorsk (Norway)pl_PL- Polish (Poland)pt_BR- Portuguese (Brazil)pt_PT- Portuguese (Portugal)ro_RO- Romanian (Romania)ru_RU- Russian (Russia)sk_SK- Slovak (Slovakia)sl_SI- Slovenian (Slovenia)sr_RS- Serbian (Serbia)sv_SE- Swedish (Sweden)th_TH- Thai (Thailand)tr_TR- Turkish (Turkey)uk_UA- Ukrainian (Ukraine)vi_VN- Vietnamese (Vietnam)zh_CN- Chinese (China)zh_TW- Chinese (Taiwan)
Repository Status
Tools Using This Standard
update-station - Reference implementation
install-station - Same implementation
Tools Needing Implementation
networkmgr - Needs migration to standard commands
setup-station - Needs translation commands added
station-tweak - Needs translation commands added
software-station - Needs translation commands added
backup-station - Needs migration from DistUtilsExtra
gbi - Needs translation commands added
Best Practices
Use full
language_COUNTRYlocale formatKeep UI text concise for interface constraints
Test translations in actual application
Use consistent terminology across GhostBSD tools
Commit only .po files (not .pot or .mo files)
Run
update_translationsregularly after code changes
Contributing
Fork repository
Create/update translations:
python setup.py create_translation --locale=fr_FREdit .po files with translations
Build and test:
python setup.py buildCommit only .po files
Submit pull request