🌏 TransX
English | 简体中文
🚀 A lightweight, zero-dependency Python internationalization library that supports Python 2.7 through 3.12.
The API is designed to be DCC-friendly, for example, works with Maya, 3DsMax, Houdini, etc.
✨ Features
TransX provides a comprehensive set of features for internationalization:
- 🚀 Zero Dependencies: No external dependencies required
- 🐍 Python Support: Full support for Python 2.7-3.12
- 🌍 Context-based: Accurate translations with context support
- 📦 Standard Format: Compatible with gettext .po/.mo files
- 🎯 Simple API: Clean and intuitive interface
- 🔄 Auto Management: Automatic translation file handling
- 🔍 String Extraction: Built-in source code string extraction
- 🌐 Unicode: Complete Unicode support
- 🔠 Parameters: Named, positional and ${var} style parameters
- 💫 Variable Support: Environment variable expansion support
- ⚡ Performance: High-speed and thread-safe operations
- 🛡️ Error Handling: Comprehensive error management with fallbacks
- 🧪 Testing: 100% test coverage with extensive cases
- 🌐 Auto Translation: Built-in Google Translate API support
- 🎥 DCC Support: Tested with Maya, 3DsMax, Houdini, etc.
- 🔌 Extensible: Pluggable custom text interpreters
- 🎨 Flexible Formatting: Multiple string formatting styles
- 🔄 Runtime Switching: Dynamic locale switching at runtime
- 🔧 Qt Integration: Built-in support for Qt translations
- 📝 Message Extraction: Advanced source code message extraction with context
- 🌐 Multi-App Support: Multiple translation instances for different apps
GNU gettext Compatibility
TransX is fully compatible with the GNU gettext standard, providing seamless integration with existing translation workflows:
- Standard Formats: Full support for
.po
and .mo
file formats according to GNU gettext specifications
- File Structure: Follows the standard locale directory structure (
LC_MESSAGES/domain.{po,mo}
)
- Header Support: Complete support for gettext headers and metadata
- Plural Forms: Compatible with gettext plural form expressions and handling
- Context Support: Full support for msgctxt (message context) using gettext standard separators
- Encoding: Proper handling of character encodings as specified in PO/MO headers
- Tools Integration: Works with standard gettext tools (msgfmt, msginit, msgmerge, etc.)
- Binary Format: Implements the official MO file format specification with both little and big endian support
This means you can:
- Use existing PO editors like Poedit, Lokalize, or GTranslator
- Integrate with established translation workflows
- Migrate existing gettext-based translations seamlessly
- Use standard gettext tools alongside TransX
- Maintain compatibility with other gettext-based systems
🚀 Quick Start
📥 Installation
pip install transx
📝 Basic Usage
from transx import TransX
tx = TransX(locales_root="./locales")
print(tx.tr("Hello"))
print(tx.tr("Hello {name}!", name="张三"))
print(tx.tr("Open", context="button"))
print(tx.tr("Open", context="menu"))
tx.switch_locale("ja_JP")
print(tx.tr("Hello"))
🔄 Translation API
TransX provides two main methods for translation with different levels of functionality:
tr() - High-Level Translation API
The tr()
method is the recommended high-level API that provides all translation features:
tx.tr("Hello")
tx.tr("Hello {name}!", name="张三")
tx.tr("Open", context="button")
tx.tr("Open", context="menu")
tx.tr("Home: $HOME")
tx.tr("Price: $$99.99")
tx.tr("Welcome to ${city}, {country}!", city="北京", country="中国")
translate() - Low-Level Translation API
The translate()
method is a lower-level API that provides basic translation and parameter substitution:
tx.translate("Hello")
tx.translate("Open", context="button")
tx.translate("Hello {name}!", name="张三")
The main differences between tr()
and translate()
:
Basic Translation | ✅ | ✅ |
Context Support | ✅ | ✅ |
Parameter Substitution | ✅ | ✅ |
Environment Variables | ✅ | ❌ |
${var} Style Variables | ✅ | ❌ |
$$ Escaping | ✅ | ❌ |
Interpreter Chain | ✅ | ❌ |
Choose tr()
for full functionality or translate()
for simpler use cases where you only need basic translation and parameter substitution.
🔄 Advanced Parameter Substitution
tx.tr("Welcome to {city}, {country}!", city="北京", country="中国")
tx.tr("File {0} of {1}", 1, 10)
tx.tr("Current user: ${USER}")
tx.tr("Path: $HOME/documents")
tx.tr("Price: $$99.99")
🌐 Available Locales
TransX provides a convenient way to get a list of available locales in your project:
from transx import TransX
tx = TransX(locales_root="./locales")
print(f"Available locales: {tx.available_locales}")
if "zh_CN" in tx.available_locales:
tx.current_locale = "zh_CN"
The available_locales
property returns a sorted list of locale codes that:
- Have a valid locale directory structure (
LC_MESSAGES
folder)
- Contain either
.po
or .mo
translation files
- Are ready to use for translation
This is useful for:
- Building language selection interfaces
- Validating locale switches
- Checking translation file completeness
- Displaying supported languages to users
🛠️ Command Line Interface
TransX provides a command-line interface for common translation tasks. When no arguments are provided for commands, TransX will use the ./locales
directory in your current working directory as the default path.
transx extract
transx extract . --output ./locales/messages.pot
transx update
transx update ./locales
transx compile
transx compile ./locales
The default working directory structure:
./
└── locales/ # Default translation directory
├── messages.pot # Extracted messages template
├── en/ # English translations
│ └── LC_MESSAGES/
│ ├── messages.po
│ └── messages.mo
└── zh_CN/ # Chinese translations
└── LC_MESSAGES/
├── messages.po
└── messages.mo
transx extract app.py -o messages.pot
transx extract ./src -o messages.pot -p "MyProject" -v "1.0"
transx extract ./src -l "en_US,zh_CN,ja_JP"
Update PO Files
transx update messages.pot -l "zh_CN,ja_JP,ko_KR"
transx update messages.pot
transx update messages.pot -o ./locales
Compile MO Files
transx compile path/to/messages.po
transx compile -d ./locales
transx compile file1.po file2.po
List Available Locales
transx list
transx list -d /path/to/locales
Common Options
-d, --directory
: Specify working directory
-o, --output
: Specify output file/directory
-l, --languages
: Comma-separated list of language codes
-p, --project
: Project name (for POT generation)
-v, --version
: Project version (for POT generation)
For detailed help on any command:
transx <command> --help
🚀 Advanced Features
🖥️ Qt Usage
TransX can be used with Qt applications in two ways:
Basic Integration
Use TransX directly in your Qt application:
from PySide2.QtWidgets import QMainWindow
from transx import get_transx_instance
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.tx = get_transx_instance("myapp")
self.setWindowTitle(self.tx.tr("My Application"))
file_menu = self.menuBar().addMenu(self.tx.tr("&File"))
file_menu.addAction(self.tx.tr("&Open"))
file_menu.addAction(self.tx.tr("&Save"))
Qt Translator Integration
For Qt's built-in translation system, you'll need to:
- First convert your .po files to .qm format using Qt's lrelease tool
- Install the .qm files using TransX's Qt extension
from PySide2.QtWidgets import QApplication, QMainWindow
from PySide2.QtCore import QTranslator
from transx.extensions.qt import install_qt_translator
app = QApplication([])
translator = QTranslator()
install_qt_translator(app, translator, "zh_CN", "./translations")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My Application")
Converting .po to .qm files:
lrelease translations/zh_CN/LC_MESSAGES/messages.po -qm translations/qt_zh_CN.qm
Note: The lrelease
tool is part of Qt's Linguist tools:
The Qt integration supports:
- Loading .qm format translation files
- Multiple translator instances
- Note: Qt's built-in tr() function requires .qm files and won't work with .mo files
Extract translatable messages from your source code with powerful context support:
from transx.api.pot import PotExtractor
extractor = PotExtractor(pot_file="messages.pot")
extractor.add_source_file("app.py")
extractor.add_source_file("utils.py")
extractor.add_source_directory("src")
extractor.save_pot(
project="MyApp",
version="1.0.0",
copyright_holder="Your Name",
bugs_address="your.email@example.com"
)
🌐 Multi-App Support
Manage multiple translation instances for different applications or components:
from transx import get_transx_instance
app1 = get_transx_instance("app1", default_locale="en_US")
app2 = get_transx_instance("app2", default_locale="zh_CN")
app1.tr("Hello")
app2.tr("Hello")
app1.switch_locale("ja_JP")
app2.switch_locale("ko_KR")
Multi-app support features:
- Independent translation catalogs
- Separate locale settings per instance
- Thread-safe operation
🔤 Context-Based Translations
print(tx.tr("Open", context="button"))
print(tx.tr("Open", context="menu"))
print(tx.tr("Post", context="verb"))
print(tx.tr("Post", context="noun"))
print(tx.tr("Welcome", context="login"))
print(tx.tr("Welcome", context="home"))
⚠️ Error Handling
TransX provides comprehensive error handling with fallback mechanisms:
from transx import TransX
from transx.exceptions import LocaleNotFoundError, TranslationError
tx = TransX(strict_mode=True)
try:
tx.load_catalog("invalid_locale")
except LocaleNotFoundError as e:
print(f"❌ Locale error: {e.message}")
try:
result = tx.translate("Hello", target_lang="invalid")
except TranslationError as e:
print(f"❌ Translation failed: {e.message}")
📄 Performance
TransX is designed with performance in mind. We continuously monitor and optimize its performance through automated benchmarks.
View our performance benchmarks at: TransX Benchmarks
Our benchmark suite includes:
- Translation lookup performance
- Parameter substitution performance
- Locale switching performance
- Cache efficiency
- Memory usage
- Concurrent operations
- And more...
🛠️ Development
🔧 Environment Setup
git clone https://github.com/loonghao/transx.git
cd transx
- Install development dependencies:
pip install -r requirements-dev.txt
📦 Project Structure
TransX follows a well-organized package structure:
transx/
├── transx/ # Main package directory
│ ├── __init__.py # Package initialization
│ ├── __version__.py # Version information
│ ├── api/ # Public API modules
│ │ ├── __init__.py
│ │ ├── mo.py # MO file operations
│ │ ├── po.py # PO file operations
│ │ └── pot.py # POT file operations
│ ├── app.py # Application management
│ ├── cli.py # Command-line interface
│ ├── constants.py # Constants and configurations
│ ├── context/ # Translation context management
│ │ ├── __init__.py
│ │ └── manager.py # Context manager implementation
│ ├── core.py # Core functionality
│ ├── exceptions.py # Custom exceptions
│ ├── extensions/ # Framework integrations
│ │ ├── __init__.py
│ │ └── qt.py # Qt support
│ └── internal/ # Internal implementation details
│ ├── __init__.py
│ ├── compat.py # Python 2/3 compatibility
│ ├── filesystem.py # File system operations
│ └── logging.py # Logging utilities
├── examples/ # Example code
├── locales/ # Translation files
├── tests/ # Test suite
├── nox_actions/ # Nox automation scripts
├── CHANGELOG.md # Version history
├── LICENSE # MIT License
├── README.md # English documentation
├── README_zh.md # Chinese documentation
├── noxfile.py # Test automation config
├── pyproject.toml # Project configuration
├── requirements.txt # Production dependencies
└── requirements-dev.txt # Development dependencies
🔄 Development Workflow
We use Nox to automate development tasks. Here are the main commands:
nox -s lint
nox -s lint-fix
nox -s pytest
🧪 Running Tests
Tests are written using pytest and can be run using nox:
nox -s pytest
For running specific tests:
nox -s pytest -- tests/test_core.py
nox -s pytest -- -m "not integration"
📊 Code Quality
We maintain high code quality standards using various tools:
- Linting: We use ruff and isort for code linting and formatting
- Type Checking: Static type checking with mypy
- Testing: Comprehensive test suite with pytest
- Coverage: Code coverage tracking with coverage.py
- CI/CD: Automated testing and deployment with GitHub Actions
📝 Documentation
Documentation is written in Markdown and is available in:
- README.md: Main documentation
- examples/: Example code and usage
- API documentation in source code
🤝 Contributing Guidelines
- Fork the repository
- Create a new branch for your feature
- Make your changes
- Run tests and linting
- Submit a pull request
Please ensure your PR:
- Passes all tests
- Includes appropriate documentation
- Follows our code style
- Includes test coverage for new features
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.