A lightweight, zero-dependency Python library for internationalization and translation management.
Project description
๐ TransX
๐ 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
| Feature | Description |
|---|---|
| ๐ 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. |
| ๐ Project Structure | Well-organized and maintainable codebase |
| ๐ Extensible | Pluggable custom text interpreters system |
| ๐จ Flexible Formatting | Support for various string format styles |
| ๐ Runtime Switching | Dynamic locale switching at runtime |
๐ Project Structure
transx/
โโโ transx/ # Main package directory
โ โโโ api/ # Public API implementations
โ โโโ internal/ # Internal implementation details
โ โโโ core.py # Core functionality
โ โโโ cli.py # Command-line interface
โ โโโ constants.py # Constants and configurations
โ โโโ exceptions.py # Custom exceptions
โโโ examples/ # Example code and usage demos
โโโ tests/ # Test suite
โโโ pyproject.toml # Project configuration
โโโ noxfile.py # Test automation configuration
๐ Quick Start
๐ฅ Installation
pip install transx
๐ Basic Usage
from transx import TransX
# Initialize with locale directory
tx = TransX(locales_root="./locales")
# Basic translation
print(tx.tr("Hello")) # Output: ไฝ ๅฅฝ
# Translation with parameters
print(tx.tr("Hello {name}!", name="ๅผ ไธ")) # Output: ไฝ ๅฅฝ ๅผ ไธ๏ผ
# Context-based translation
print(tx.tr("Open", context="button")) # ๆๅผ
print(tx.tr("Open", context="menu")) # ๆๅผๆไปถ
# Switch language at runtime
tx.current_locale = "ja_JP"
print(tx.tr("Hello")) # Output: ใใใซใกใฏ
๐ Advanced Parameter Substitution
# Named parameters
tx.tr("Welcome to {city}, {country}!", city="ๅไบฌ", country="ไธญๅฝ")
# Positional parameters
tx.tr("File {0} of {1}", 1, 10)
# Dollar sign variables (useful in shell-like contexts)
tx.tr("Current user: ${USER}") # Supports ${var} syntax
tx.tr("Path: $HOME/documents") # Supports $var syntax
# Escaping dollar signs
tx.tr("Price: $$99.99") # Outputs: Price: $99.99
๐ Environment Variable Support
# Environment variables are automatically expanded
tx.tr("User home: ${HOME}")
tx.tr("Current path: ${PATH}")
# Mix with translation parameters
tx.tr("Welcome {name} to ${HOSTNAME}!", name="John")
๐ฏ Context-Aware Translation
# Same string, different contexts
tx.tr("Open", context="button") # Translation for button label
tx.tr("Open", context="menu") # Translation for menu item
tx.tr("Open", context="file_state") # Translation for file status
# Context with parameters
tx.tr("Created {count} items", count=5, context="notification")
๐ ๏ธ Advanced API Usage
๐ Custom Interpreter System
TransX provides a powerful and flexible interpreter system that allows you to customize text processing:
from transx import TextInterpreter, InterpreterExecutor
# Create a custom interpreter
class MyCustomInterpreter(TextInterpreter):
name = "custom"
description = "My custom text processor"
def interpret(self, text, context=None):
# Add your custom text processing logic here
return text.replace("old", "new")
# Use built-in interpreters
tx = TransX(locales_root="./locales")
executor = tx.get_interpreter_executor()
# Add your custom interpreter
executor.add_interpreter(MyCustomInterpreter())
# Built-in interpreters include:
# - TextTypeInterpreter: Ensures correct text encoding
# - DollarVariableInterpreter: Handles ${var} style variables
# - ParameterSubstitutionInterpreter: Handles {name} style parameters
# - EnvironmentVariableInterpreter: Expands environment variables
# - TranslationInterpreter: Handles text translation
# Chain multiple interpreters
executor = InterpreterExecutor([
MyCustomInterpreter(),
tx.get_interpreter("env"), # Environment variables
tx.get_interpreter("dollar"), # ${var} style variables
])
# Execute the interpreter chain
result = executor.execute("Hello ${USER}", {"name": "world"})
# Safe execution with fallback
result = executor.execute_safe(
"Hello ${USER}",
fallback_interpreters=[tx.get_interpreter("parameter")]
)
The interpreter system follows a chain-of-responsibility pattern where each interpreter can:
- Transform text in its own specific way
- Pass context information between interpreters
- Be ordered to control processing sequence
- Fail safely without affecting other interpreters
- Have fallback options for robustness
Message Extraction and PO/MO File Management
from transx.api.pot import PotExtractor
from transx.api.po import POFile
from transx.api.mo import compile_po_file
# Extract messages from source code
extractor = PotExtractor(project="MyProject", version="1.0")
extractor.scan_file("app.py")
extractor.save("messages.pot")
# Create/Update PO file
po = POFile("zh_CN/LC_MESSAGES/messages.po")
po.add_translation("Hello", "ไฝ ๅฅฝ")
po.add_translation("Welcome", "ๆฌข่ฟ", context="greeting")
po.save()
# Compile PO to MO
compile_po_file("zh_CN/LC_MESSAGES/messages.po", "zh_CN/LC_MESSAGES/messages.mo")
Automatic Translation with Google Translate
from transx.api.translate import GoogleTranslator, translate_po_files
# Initialize Google Translator
translator = GoogleTranslator()
# Create and auto-translate PO files for multiple languages
translate_po_files(
pot_file_path="messages.pot",
languages=["zh_CN", "ja_JP", "ko_KR"],
output_dir="locales",
translator=translator
)
Implementing Custom Translation API
You can implement your own translation API by inheriting from the Translator base class:
from transx.api.translate import Translator
from transx.api.translate import translate_po_files
class MyCustomTranslator(Translator):
def translate(self, text, source_lang="auto", target_lang="en"):
"""Implement your custom translation logic.
Args:
text (str): Text to translate
source_lang (str): Source language code (default: auto)
target_lang (str): Target language code (default: en)
Returns:
str: Translated text
"""
# Add your translation logic here
# For example, calling your own translation service:
return my_translation_service.translate(
text=text,
from_lang=source_lang,
to_lang=target_lang
)
# Use your custom translator
translator = MyCustomTranslator()
translate_po_files(
pot_file_path="messages.pot",
languages=["zh_CN", "ja_JP"],
translator=translator
)
๐ Implementing Custom Translation API
TransX provides a flexible way to implement your own translation service. You can either:
- ๐ง Implement your own translation logic
- ๐ Integrate with third-party translation libraries
- ๐ Use direct HTTP requests to translation services
Basic Implementation
The simplest way is to inherit from the Translator base class:
from transx.api.translate import Translator
from transx.api.translate import translate_po_files
class MyCustomTranslator(Translator):
def translate(self, text, source_lang="auto", target_lang="en"):
"""Implement your custom translation logic.
Args:
text (str): Text to translate
source_lang (str): Source language code (default: auto)
target_lang (str): Target language code (default: en)
Returns:
str: Translated text
"""
# Add your translation logic here
return my_translation_service.translate(
text=text,
from_lang=source_lang,
to_lang=target_lang
)
# Use your custom translator
translator = MyCustomTranslator()
translate_po_files(
pot_file_path="messages.pot",
languages=["zh_CN", "ja_JP"],
translator=translator
)
๐ Using Third-Party Libraries
For faster implementation, you can integrate with existing translation libraries:
๐ deep-translator (Python 3.x only)
from deep_translator import GoogleTranslator as DeepGoogleTranslator
from transx.api.translate import Translator
class DeepTranslator(Translator):
"""A powerful translator using deep-translator library.
Supported Services:
โจ Google Translate
โจ DeepL
โจ Microsoft Translator
โจ PONS
โจ Linguee
โจ MyMemory
And more...
"""
def translate(self, text, source_lang="auto", target_lang="en"):
try:
# Convert language codes (e.g., zh_CN -> zh-cn)
source = source_lang.lower().replace('_', '-')
target = target_lang.lower().replace('_', '-')
translator = DeepGoogleTranslator(
source=source if source != "auto" else "auto",
target=target
)
return translator.translate(text)
except Exception as e:
raise TranslationError(f"Translation failed: {str(e)}")
๐ฆ translate (Python 2.7 compatible)
from translate import Translator as PyTranslator
from transx.api.translate import Translator
class SimpleTranslator(Translator):
"""A lightweight translator using the 'translate' library.
Supported Services:
โจ Google Translate
โจ MyMemory
โจ Microsoft Translator
"""
def translate(self, text, source_lang="auto", target_lang="en"):
try:
translator = PyTranslator(from_lang=source_lang, to_lang=target_lang)
return translator.translate(text)
except Exception as e:
raise TranslationError(f"Translation failed: {str(e)}")
โ ๏ธ Python 2.7 Compatibility Note
While TransX supports Python 2.7 through 3.12, many modern translation libraries have dropped Python 2.7 support. Here are your options:
- ๐ฆ Use older versions of translation libraries that still support Python 2.7
- ๐ Implement a simple HTTP client to directly call translation APIs
- โจ Use TransX's built-in
GoogleTranslatorwhich maintains Python 2.7 compatibility
๐ง HTTP Client Example (Python 2.7 compatible)
import requests
from transx.api.translate import Translator
from transx.compat import urlencode
class SimpleGoogleTranslator(Translator):
"""A basic Google Translate implementation using requests."""
def translate(self, text, source_lang="auto", target_lang="en"):
try:
# Convert language codes
source = source_lang.lower().replace('_', '-')
target = target_lang.lower().replace('_', '-')
# Build URL
params = {
'sl': source,
'tl': target,
'q': text
}
url = 'https://translate.googleapis.com/translate_a/single?' + urlencode({
'client': 'gtx',
'dt': 't',
**params
})
# Make request
response = requests.get(url)
data = response.json()
# Extract translation
return ''.join(part[0] for part in data[0])
except Exception as e:
raise TranslationError(f"Translation failed: {str(e)}")
๐ Language Code Support
TransX provides flexible language code handling with automatic normalization:
๐ Example Usage
from transx import TransX
tx = TransX()
# Different language code formats are supported:
tx.current_locale = "zh-CN" # Hyphen format
tx.current_locale = "zh_CN" # Underscore format
tx.current_locale = "zh" # Language only (will use default country code)
tx.current_locale = "Chinese" # Language name
Supported Language Codes
| Language | Standard Code | Alternative Formats |
|---|---|---|
| Chinese (Simplified) | zh_CN |
zh-CN, zh_Hans, Chinese, Chinese Simplified |
| Japanese | ja_JP |
ja, Japanese |
| Korean | ko_KR |
ko, Korean |
| English | en_US |
en, English |
| French | fr_FR |
fr, French |
| Spanish | es_ES |
es, Spanish |
| German | de_DE |
de, German |
| Italian | it_IT |
it, Italian |
| Russian | ru_RU |
ru, Russian |
๐ Default Behavior
TransX handles language codes in the following way:
- ๐ Attempts to detect the system language automatically
- ๐ Normalizes language codes to standard format (e.g.,
zh-CNโzh_CN) - โก Falls back to
en_USif the system language is not supported or cannot be detected
๐ ๏ธ Command Line Interface
TransX provides a powerful CLI for translation management:
Extract Messages
# Extract from a single file
transx extract app.py -o messages.pot
# Extract from a directory
transx extract ./src -o messages.pot -p "MyProject" -v "1.0"
Update PO Files
# Update or create PO files for specific languages
transx update messages.pot -l zh_CN ja_JP ko_KR
# Auto-translate during update
transx update messages.pot -l zh_CN ja_JP ko_KR --translate
Compile MO Files
# Compile a single PO file
transx compile locales/zh_CN/LC_MESSAGES/messages.po
# Compile all PO files in a directory
transx compile locales
๐ Supported Languages
The Google Translator supports a wide range of languages. Here are some commonly used language codes:
- Chinese (Simplified):
zh_CN - Japanese:
ja_JP - Korean:
ko_KR - French:
fr_FR - Spanish:
es_ES
For a complete list of supported languages, refer to the language code documentation.
๐ฏ Advanced Features
Context-Based Translations
# UI Context
print(tx.tr("Open", context="button")) # ๆๅผ
print(tx.tr("Open", context="menu")) # ๆๅผๆไปถ
# Part of Speech
print(tx.tr("Post", context="verb")) # ๅๅธ
print(tx.tr("Post", context="noun")) # ๆ็ซ
# Scene Context
print(tx.tr("Welcome", context="login")) # ๆฌข่ฟ็ปๅฝ
print(tx.tr("Welcome", context="home")) # ๆฌข่ฟๅๆฅ
Error Handling
TransX provides comprehensive error handling for various scenarios:
from transx import TransX
from transx.exceptions import LocaleNotFoundError, CatalogNotFoundError, TranslationError
# 1. Locale and Catalog Errors
tx = TransX(strict_mode=True) # Enable strict mode to raise exceptions
try:
tx.load_catalog("invalid_locale")
except LocaleNotFoundError as e:
print(f"โ Locale error: {e.message}")
print(f" Missing locale: {e.locale}")
try:
tx.load_catalog(None)
except ValueError as e:
print("โ Invalid locale: Locale cannot be None")
# 2. Translation Errors
from transx.api.translate import GoogleTranslator
translator = GoogleTranslator()
try:
result = translator.translate("Hello", source_lang="invalid", target_lang="zh_CN")
except TranslationError as e:
print(f"โ Translation failed: {e.message}")
print(f" Source text: {e.source_text}")
print(f" From: {e.source_lang} To: {e.target_lang}")
# 3. File Parsing Errors
from transx.exceptions import ParserError, ValidationError
from transx.api.po import POFile
try:
po = POFile("invalid.po")
po.parse()
except ParserError as e:
print(f"โ Parse error in {e.file_path}")
if e.line_number:
print(f" At line: {e.line_number}")
if e.reason:
print(f" Reason: {e.reason}")
# 4. Non-Strict Mode Behavior
tx = TransX(strict_mode=False) # Default behavior
# These operations will log warnings instead of raising exceptions
tx.load_catalog("missing_locale") # Returns False, logs warning
tx.tr("missing_key") # Returns the key itself, logs warning
Key error handling features:
- ๐ Strict mode for development/testing
- ๐ Detailed error messages and context
- ๐ชต Fallback behavior in non-strict mode
- ๐ Comprehensive logging
๐ง Error Handling
from transx.exceptions import TranslationError, LocaleError
try:
tx.tr("Hello")
except TranslationError as e:
print(f"Translation failed: {e}")
except LocaleError as e:
print(f"Locale error: {e}")
Multiple Catalogs
tx = TransX()
tx.load_catalog("path/to/main.mo") # Main catalog
tx.load_catalog("path/to/extra.mo") # Extra translations
โก Performance Features
- ๐ Uses compiled MO files for optimal speed
- ๐พ Automatic translation caching
- ๐ Thread-safe for concurrent access
- ๐ Minimal memory footprint
- ๐ Automatic PO to MO compilation
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
๐จโ๐ป Developer Guide
๐ง Development Setup
- Clone the repository:
git clone https://github.com/loonghao/transx.git
cd transx
- Install development dependencies:
pip install -r requirements-dev.txt
๐ Project Structure
transx/
โโโ transx/ # Main package directory
โ โโโ api/ # Public API modules
โ โ โโโ locale.py # Locale handling
โ โ โโโ mo.py # MO file operations
โ โ โโโ po.py # PO file operations
โ โ โโโ translate.py # Translation services
โ โโโ core.py # Core functionality
โ โโโ constants.py # Constants and configurations
โโโ tests/ # Test directory
โโโ examples/ # Example code and usage
โโโ nox_actions/ # Nox automation scripts
โ โโโ codetest.py # Test execution configuration
โ โโโ lint.py # Code linting and formatting
โ โโโ utils.py # Shared utilities and constants
โโโ docs/ # Documentation
๐ Development Workflow
We use Nox to automate development tasks. Here are the main commands:
# Run linting
nox -s lint
# Fix linting issues automatically
nox -s lint-fix
# Run tests
nox -s pytest
๐งช Running Tests
Tests are written using pytest and can be run using nox:
nox -s pytest
For running specific tests:
# Run a specific test file
nox -s pytest -- tests/test_core.py
# Run tests with specific markers
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
- 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file transx-0.2.0.tar.gz.
File metadata
- Download URL: transx-0.2.0.tar.gz
- Upload date:
- Size: 48.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f9d2a1e90c7623f84b655d9094451f5d1d183fb74d2ee79ce1897d072d6421b
|
|
| MD5 |
b04e101f9b592831d43078a4f54508f7
|
|
| BLAKE2b-256 |
96e7981fe3bea5262d0f678eb8b03b077b55fe0048839028bcd72a82868a7ad5
|
Provenance
The following attestation bundles were made for transx-0.2.0.tar.gz:
Publisher:
python-publish.yml on loonghao/transx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
transx-0.2.0.tar.gz -
Subject digest:
2f9d2a1e90c7623f84b655d9094451f5d1d183fb74d2ee79ce1897d072d6421b - Sigstore transparency entry: 153316158
- Sigstore integration time:
-
Permalink:
loonghao/transx@21a1ece6c94d6533c3d03878bdd53ff915da99fe -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/loonghao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@21a1ece6c94d6533c3d03878bdd53ff915da99fe -
Trigger Event:
push
-
Statement type:
File details
Details for the file transx-0.2.0-py2.py3-none-any.whl.
File metadata
- Download URL: transx-0.2.0-py2.py3-none-any.whl
- Upload date:
- Size: 50.5 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32adc71dbcfb5a8744f42718944026361e1f782c3e5a480a98567b2c53aa5ff5
|
|
| MD5 |
69a1c4bd539897269af38621d64bf14e
|
|
| BLAKE2b-256 |
a269dbee9350c04144141498ca238e14c0dde571b2d3876ef7ae02cc5dca4286
|
Provenance
The following attestation bundles were made for transx-0.2.0-py2.py3-none-any.whl:
Publisher:
python-publish.yml on loonghao/transx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
transx-0.2.0-py2.py3-none-any.whl -
Subject digest:
32adc71dbcfb5a8744f42718944026361e1f782c3e5a480a98567b2c53aa5ff5 - Sigstore transparency entry: 153316159
- Sigstore integration time:
-
Permalink:
loonghao/transx@21a1ece6c94d6533c3d03878bdd53ff915da99fe -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/loonghao
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@21a1ece6c94d6533c3d03878bdd53ff915da99fe -
Trigger Event:
push
-
Statement type: