Metadata-Version: 2.4
Name: polyglot-ui
Version: 0.1.0
Summary: Smart translation workflow utilities for Django/Lino - extracts only the strings your app actually uses
Project-URL: Homepage, https://github.com/8lurry/polyglot-ui
Project-URL: Documentation, https://github.com/8lurry/polyglot-ui#readme
Project-URL: Repository, https://github.com/8lurry/polyglot-ui
Project-URL: Bug Tracker, https://github.com/8lurry/polyglot-ui/issues
Author-email: 8lurry <sharifmehedi24@outlook.com>
License: GPL-2.0
License-File: LICENSE
Keywords: django,gemini,gettext,i18n,l10n,lino,po,translation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Internationalization
Classifier: Topic :: Software Development :: Localization
Requires-Python: >=3.8
Requires-Dist: google-genai>=0.2.0
Requires-Dist: polib>=1.1.0
Provides-Extra: dev
Requires-Dist: black>=22.0.0; extra == 'dev'
Requires-Dist: flake8>=4.0.0; extra == 'dev'
Requires-Dist: hatch>=1.9.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: twine>=4.0.0; extra == 'dev'
Description-Content-Type: text/x-rst

===========
Polyglot UI
===========

Smart translation workflow for Django/Lino applications.

**Polyglot UI** filters untranslated strings from .po files (generated by ``inv mm``) by checking which Python objects and modules are actually imported by your app, then translates them using Google Gemini API.

.. contents:: Table of Contents
   :local:
   :depth: 2

Features
========

- Filter untranslated help texts by checking if their Python object path is accessible
- Filter untranslated strings from .po files by checking occurrence comments against ``sys.modules``
- Extract all untranslated strings from HTML template sources
- Translate using Google Gemini API with batch processing and resume capability
- Update and compile .po files automatically
- Support for plural forms and format specifier preservation

Installation
============

From PyPI::

    pip install polyglot-ui

For development::

    pip install -e .

**Requirements:**

- Python 3.8+
- ``GEMINI_API_KEY`` environment variable for translation::

    export GEMINI_API_KEY="your-key-here"

Get your API key from https://ai.google.dev/

Quick Start
===========

::

    # 1. Generate .po files (if not done)
    inv mm
    
    # 2. Extract untranslated strings (requires Django context)
    python manage.py run $(which polyglot-ui) helptexts \
        -p lino -l lino -L bn -o translateables.json
    
    # 3. Translate
    polyglot-ui translate -i translateables.json -o translated.json
    
    # 4. Update .po files
    polyglot-ui update -t translated.json -l lino --lang bn

Commands
========

+---------------+--------------------------------------------+----------------+
| Command       | Description                                | Django Context |
+===============+============================================+================+
| ``helptexts`` | Filter help texts by object accessibility  | Required       |
+---------------+--------------------------------------------+----------------+
| ``modules``   | Filter by sys.modules (--all: everything)  | Optional*      |
+---------------+--------------------------------------------+----------------+
| ``html``      | Extract untranslated HTML strings          | No             |
+---------------+--------------------------------------------+----------------+
| ``translate`` | Translate using Gemini API                 | No             |
+---------------+--------------------------------------------+----------------+
| ``update``    | Update .po with translations and compile   | No             |
+---------------+--------------------------------------------+----------------+
| ``compile``   | Compile .po to .mo                         | No             |
+---------------+--------------------------------------------+----------------+

\* Required only when filtering by sys.modules (without --all flag)

Detailed Usage
==============

1. helptexts
------------

Filters untranslated help texts from ``locale_root/help_texts.py`` by checking if the Python object path is accessible.

**How it works:**

1. Reads ``help_texts`` dict from ``locale_root/help_texts.py``
2. For each key (e.g., ``"lino.modlib.users.User.username"``), attempts to resolve it as a Python object using ``getattr`` iteratively
3. Checks if corresponding entry in .po file is untranslated
4. Only includes help texts for objects accessible in current ``sys.modules``

**Requires Django context** (use ``python manage.py run``)::

    python manage.py run $(which polyglot-ui) helptexts \
        -p lino_pronto -l lino_pronto -L bn -o helptexts.json

**Arguments:**

- ``-p, --project_name``: Project name (required)
- ``-l, --locale_root``: Locale root (required, must have help_texts.py)
- ``-L, --lang``: Language code (default: bn)
- ``-o, --output_file``: Output JSON file (default: translateables.json)

2. modules
----------

Filters untranslated strings from .po file (generated by ``inv mm``) by checking if occurrence comments reference imported modules.

**How it works:**

1. Reads .po file and finds untranslated entries
2. Checks occurrence comments (e.g., ``#: lino/modlib/users/models.py:123``)
3. Converts file path to module name (e.g., ``lino.modlib.users.models``)
4. Checks if module is in ``sys.modules`` (unless ``--all`` flag is used)
5. Only includes strings from imported modules (or all strings with ``--all``)

**Requires Django context** (when filtering by sys.modules)::

    python manage.py run $(which polyglot-ui) modules \
        -p lino -l lino -L bn -o modules.json

**Extract all strings** (no Django context needed)::

    polyglot-ui modules -p lino -l lino -L bn -o all_modules.json --all

**Arguments:**

- ``-p, --project_name``: Project name (required)
- ``-l, --locale_root``: Locale root (required)
- ``-L, --lang``: Language code (default: bn)
- ``-o, --output_file``: Output JSON file (default: translateables.json)
- ``--all``: Extract all untranslated strings without filtering by sys.modules

3. html
-------

Extracts ALL untranslated strings from .po file where occurrence comment references an HTML file.

**No filtering** - extracts all HTML strings regardless of usage::

    polyglot-ui html -l lino -L bn -o html.json

**Arguments:**

- ``-l, --locale_root``: Locale root (required)
- ``-L, --lang``: Language code (default: bn)
- ``-o, --output_file``: Output JSON file (default: translateables_html.json)

4. translate
------------

Translates strings using Google Gemini API. Resumable - skips already translated strings::

    export GEMINI_API_KEY="your-key"
    polyglot-ui translate -i translateables.json -o translated.json

**Arguments:**

- ``-i, --input_file``: Input JSON (required)
- ``-o, --output_file``: Output JSON (default: translated.json)
- ``-l, --lang``: Language name (default: "Bengali (bn)")
- ``-n, --batch_size``: Batch size (default: 200)

5. update
---------

Updates .po file with translations and compiles to .mo::

    polyglot-ui update -t translated.json -l lino --lang bn

**Arguments:**

- ``-t, --translations_files``: JSON file(s) with translations (required)
- ``-l, --locale_root``: Locale root (required)
- ``--lang``: Language code (default: bn)

6. compile
----------

Manually compile .po to .mo::

    polyglot-ui compile /path/to/django.po

Workflow Example
================

::

    # Setup
    export GEMINI_API_KEY="your-key"
    cd /path/to/project
    inv mm  # Generate .po files
    
    # Extract (requires Django context)
    python manage.py run $(which polyglot-ui) helptexts \
        -p lino -l lino -L bn -o helptexts.json
    python manage.py run $(which polyglot-ui) modules \
        -p lino -l lino -L bn -o modules.json
    
    # Extract HTML (no Django context)
    polyglot-ui html -l lino -L bn -o html.json
    
    # Translate
    polyglot-ui translate -i helptexts.json -o t_helptexts.json
    polyglot-ui translate -i modules.json -o t_modules.json
    polyglot-ui translate -i html.json -o t_html.json
    
    # Update .po files
    polyglot-ui update -t t_helptexts.json t_modules.json t_html.json \
        -l lino --lang bn

How It Works
============

**Prerequisites**

.po files must exist (generated by ``inv mm`` command).

**Smart Filtering**

Shared packages like ``lino`` and ``lino_xl`` contain thousands of strings. Each app only uses a subset. Polyglot UI filters by:

1. **Help texts** (``helptexts``):
   
   - Reads ``help_texts`` dict from ``locale_root/help_texts.py``
   - Keys are Python object paths: ``"lino.modlib.users.User.username"``
   - Checks if object is accessible by iteratively using ``getattr`` on ``sys.modules``
   - Only includes help texts for accessible objects

2. **Module strings** (``modules``):
   
   - Reads occurrence comments from .po file: ``#: lino/modlib/users/models.py:123``
   - Converts file path to module name: ``lino.modlib.users.models``
   - By default: Checks if module is in ``sys.modules`` (requires Django context)
   - With ``--all`` flag: Extracts all strings without filtering (no Django context needed)
   - Only includes strings from imported modules (or all with ``--all``)

3. **HTML strings** (``html``):
   
   - Checks if occurrence comment ends with ``.html``
   - No filtering - extracts ALL HTML strings

**Django Context**

Commands requiring ``python manage.py run``:

- ``helptexts`` - needs ``sys.modules`` to check object accessibility
- ``modules`` - needs ``sys.modules`` to check module imports (unless ``--all`` flag is used)

Other commands run standalone.

Tips
====

- Run ``inv mm`` first to generate/update .po files
- Organize output: ``helptexts.json``, ``modules.json``, ``html.json``
- Batch size: 200 (default) works well; reduce if API limits hit
- Translation is resumable - rerun if interrupted
- Never commit ``GEMINI_API_KEY`` to version control

Troubleshooting
===============

- **"GEMINI_API_KEY not set"**: Export your API key
- **"Module not found"**: Use ``python manage.py run`` for commands requiring Django context
- **"No module named 'google.genai'"**: Run ``pip install google-genai``
- **Incomplete translations**: Check API limits, network; rerun to resume

License & Support
=================

GPL-2.0

Contributions welcome via Pull Request.

Changelog
=========

0.1.0 (2026-02-08)
------------------

- Initial release
- Filter untranslated strings by checking sys.modules and object accessibility
- Google Gemini API integration
- Plural forms and format specifier preservation
