Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ __pycache__
build/
db.sqlite3
.venv
python_gpt_po/version.py
python_gpt_po/_version.py
CLAUDE.md
35 changes: 0 additions & 35 deletions CLAUDE.md

This file was deleted.

8 changes: 4 additions & 4 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -e

# Display help information if no arguments are provided
if [ $# -eq 0 ]; then
VERSION=$(gpt-po-translator --version | cut -d' ' -f2)
VERSION=$(python -m python_gpt_po.main --version)
echo "GPT PO Translator Docker Container v$VERSION"
echo "==========================================="
echo
Expand Down Expand Up @@ -33,15 +33,15 @@ fi

# Check if we need to display version
if [ "$1" = "--version" ]; then
gpt-po-translator --version
python -m python_gpt_po.main --version
exit 0
fi

# Check if we need to display help
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
gpt-po-translator --help
python -m python_gpt_po.main --help
exit 0
fi

# Execute command with args
exec gpt-po-translator "$@"
exec python -m python_gpt_po.main "$@"
11 changes: 7 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
[build-system]
requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]==8.1.0"]
requires = ["setuptools>=61.0", "wheel", "setuptools_scm>=6.2"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
# Use find with namespaces=True to handle nested packages
packages = { find = { exclude = ["*.__pycache__", "*.__pycache__.*"], namespaces = true } }

[tool.setuptools_scm]
fallback_version = "0.1.0"
write_to = "python_gpt_po/_version.py"

[project]
name = "gpt_po_translator"
name = "gpt-po-translator"
dynamic = ["version"]
authors = [
{name = "Bram Mittendorff", email = "[email protected]"},
Expand Down Expand Up @@ -36,7 +40,6 @@ classifiers = [
"Topic :: Software Development :: Localization",
"Topic :: Text Processing :: Linguistic",
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
Expand All @@ -57,4 +60,4 @@ gpt-po-translator = "python_gpt_po.main:main"
max-line-length = 120

[tool.isort]
line_length = 120
line_length = 120
53 changes: 49 additions & 4 deletions python_gpt_po/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,52 @@
with support for multiple AI providers including OpenAI and Anthropic.
"""

try:
from ._version import version as __version__
except ImportError:
__version__ = "0.1.0"
import os
import subprocess
from typing import Optional


def _get_version_from_git() -> Optional[str]:
"""
Try to get version from git.

Returns:
Optional[str]: Git version or None if not available
"""
try:
# Check if we're in a git repo
is_git_repo = subprocess.run(
["git", "rev-parse", "--is-inside-work-tree"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=False
).returncode == 0
if is_git_repo:
# Get version from git describe
return subprocess.check_output(
["git", "describe", "--tags"],
stderr=subprocess.STDOUT,
text=True
).strip()
except (subprocess.SubprocessError, FileNotFoundError):
pass
return None


# Version priority:
# 1. Environment variable PACKAGE_VERSION (for Docker/CI environments)
# 2. _version.py from setuptools_scm (for installed packages)
# 3. Git describe (for development environments)
# 4. Fallback to "0.1.0"
if 'PACKAGE_VERSION' in os.environ:
__version__ = os.environ.get('PACKAGE_VERSION')
else:
try:
from ._version import version as __version__ # noqa
except ImportError:
git_version = _get_version_from_git()
if git_version:
__version__ = git_version
else:
__version__ = "0.1.0"
12 changes: 6 additions & 6 deletions python_gpt_po/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ def setup_logging():
def initialize_provider(args) -> tuple[ProviderClients, ModelProvider, str]:
"""
Initialize the provider client and determine the appropriate model.

Args:
args: Command line arguments from argparse

Returns:
tuple: (provider_clients, provider, model)

Raises:
SystemExit: If no valid provider can be found or initialized
"""
Expand Down Expand Up @@ -87,13 +87,13 @@ def get_appropriate_model(
) -> str:
"""
Get the appropriate model for the provider.

Args:
provider (ModelProvider): The selected provider
provider_clients (ProviderClients): The initialized provider clients
model_manager (ModelManager): The model manager instance
requested_model (Optional[str]): Model requested by the user

Returns:
str: The appropriate model ID
"""
Expand Down Expand Up @@ -125,7 +125,7 @@ def process_translations(config: TranslationConfig, folder: str,
batch_size: int):
"""
Process translations for the given languages and directory.

Args:
config (TranslationConfig): The translation configuration
folder (str): Directory containing .po files
Expand Down
2 changes: 1 addition & 1 deletion python_gpt_po/models/provider_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self):

def initialize_clients(self, api_keys: Dict[str, str]):
"""Initialize API clients for all providers with available keys.

Args:
api_keys (Dict[str, str]): Dictionary of provider names to API keys
"""
Expand Down
14 changes: 7 additions & 7 deletions python_gpt_po/services/model_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ def validate_model(provider_clients: ProviderClients, provider: ModelProvider, m
"""
Validates whether the specified model is available for the given provider.
Uses prefix matching so that a shorthand (e.g. "claude") will match a full model name.

Args:
provider_clients (ProviderClients): The initialized provider clients
provider (ModelProvider): The provider to check against
model (str): The model name/ID to validate

Returns:
bool: True if the model is valid, False otherwise
"""
Expand All @@ -99,10 +99,10 @@ def validate_model(provider_clients: ProviderClients, provider: ModelProvider, m
def get_default_model(provider: ModelProvider) -> str:
"""
Returns the default model for a given provider.

Args:
provider (ModelProvider): The provider to get the default model for

Returns:
str: The default model ID
"""
Expand All @@ -128,7 +128,7 @@ def verify_model_capabilities(
provider (ModelProvider): The provider to check against
model (str): The model to verify
required_capability (str): The capability to check for

Returns:
bool: True if the model has the required capability, False otherwise
"""
Expand All @@ -147,12 +147,12 @@ def suggest_model(provider_clients: ProviderClients, provider: ModelProvider,
task: str = "translation") -> str:
"""
Suggests the best model for a given task and provider.

Args:
provider_clients (ProviderClients): The initialized provider clients
provider (ModelProvider): The provider to use
task (str): The task the model will be used for

Returns:
str: The suggested model ID
"""
Expand Down
28 changes: 14 additions & 14 deletions python_gpt_po/services/po_file_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ def disable_fuzzy_translations(po_file_path):
@staticmethod
def get_file_language(po_file_path, po_file, languages, folder_language):
"""Determines the language for a .po file.

Args:
po_file_path (str): Path to the .po file
po_file (polib.POFile): Loaded PO file object
languages (List[str]): List of valid language codes
folder_language (bool): Whether to infer language from folder structure

Returns:
str or None: The normalized language code or None if not found
"""
Expand All @@ -76,10 +76,10 @@ def get_file_language(po_file_path, po_file, languages, folder_language):
@staticmethod
def normalize_language_code(lang):
"""Convert language name or code to ISO 639-1 code.

Args:
lang (str): Language name or code to normalize

Returns:
str or None: The normalized ISO 639-1 language code or None if not found
"""
Expand Down Expand Up @@ -109,7 +109,7 @@ def normalize_language_code(lang):
@staticmethod
def log_translation_status(po_file_path, original_texts, translations):
"""Logs the status of translations for a .po file.

Args:
po_file_path (str): Path to the .po file
original_texts (List[str]): List of original texts to translate
Expand All @@ -133,7 +133,7 @@ def log_translation_status(po_file_path, original_texts, translations):
@staticmethod
def update_po_entry(po_file, original_text, translated_text):
"""Updates a .po file entry with the translated text.

Args:
po_file (polib.POFile): The PO file object
original_text (str): The original text to find
Expand All @@ -149,10 +149,10 @@ def update_po_entry(po_file, original_text, translated_text):
@staticmethod
def read_po_file(po_file_path):
"""Reads a .po file and returns the PO file object.

Args:
po_file_path (str): Path to the .po file

Returns:
polib.POFile: The loaded PO file object
"""
Expand All @@ -165,11 +165,11 @@ def read_po_file(po_file_path):
@staticmethod
def save_po_file(po_file, po_file_path):
"""Saves changes to a .po file.

Args:
po_file (polib.POFile): The PO file object to save
po_file_path (str): Path where the file should be saved

Returns:
bool: True if successful, False otherwise
"""
Expand All @@ -184,10 +184,10 @@ def save_po_file(po_file, po_file_path):
@staticmethod
def get_untranslated_entries(po_file):
"""Gets all untranslated entries from a PO file.

Args:
po_file (polib.POFile): The PO file object

Returns:
List[polib.POEntry]: List of untranslated entries
"""
Expand All @@ -196,10 +196,10 @@ def get_untranslated_entries(po_file):
@staticmethod
def extract_metadata(po_file):
"""Extracts and returns metadata from a PO file.

Args:
po_file (polib.POFile): The PO file object

Returns:
dict: Dictionary containing metadata
"""
Expand Down
2 changes: 1 addition & 1 deletion python_gpt_po/services/translation_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class TranslationService:

def __init__(self, config: TranslationConfig, batch_size: int = 40):
"""Initialize the translation service.

Args:
config (TranslationConfig): Configuration for the translation service
batch_size (int): Size of batches for bulk translation
Expand Down
Loading