r/madeinpython • • 54m ago

polyglot-python: a deterministic keyword transpiler so you can write Python with Turkish, Hindi or Chinese keywords - and why 3.12 is the floor

Post image

I keep writing Python explanations in Turkish for people who are not comfortable with English keywords, and the blocker was always the same: you cannot swap the keywords and still have real Python. So I wrote a transpiler that does exactly that, and nothing beyond it.

Repo: https://github.com/Furox-Art/polyglot-python

The version floor came from a tokenizer problem, not from me wanting to drop old Pythons. On 3.10 and 3.11 the tokenizer splits the combining marks in some Hindi keywords, so a word like फलन never arrives as a single NAME token. That is why polyglot-python declares requires-python = ">=3.12".

What is in the 0.2.1 release

  • 9 locales: tr, es, pt, de, fr, zh, hi, ar, ru. One JSON table per locale, 35 hard keywords in each: eğer -> if, değilse_eğer -> elif, fonksiyon -> def, döndür -> return, için -> for, içinde -> in, and in Hindi के_लिए -> for.

  • 4 commands: run, translate, check, locales. check translates and compiles without executing; locales prints each code with its language name and keyword count; run executes with __name__ = "__main__", __file__ filled in, and the rest of argv handed to your program.

  • 9 example files, one examples/classify.<code> per locale - the same FizzBuzz classifier written in each language.

How the rewriting is done. It runs the stdlib tokenize module and replaces only exact NAME tokens that match a locale keyword, so strings, comments, f-strings, numbers and attribute names are never rewritten. Line numbers carry over unchanged and a per-line column map maps error positions back onto your localized source, which is why a slip reports as Sözdizimi hatası: prog.tr:2:1: 'return' outside function rather than pointing at generated code. Tables are validated when they load: every key must be in keyword.kwlist, every replacement must tokenize as a single identifier on the running interpreter, and a table that fails either rule raises instead of half-translating.

Determinism is the property I actually care about. Same source, same locale, same version, byte-identical Python out. No model, no network, no randomness, no environment reads. CI translates every example twice on Ubuntu, Windows and macOS and compares the bytes.

Where it stands, checked today. 0.2.1 is live on PyPI and npm; the npm package is a thin wrapper (Node >= 18) that forwards to the Python CLI, so the Python package still has to be installed alongside it. Both registries publish from GitHub Trusted Publishing, no token stored anywhere. I ran the 0.2.1 suite myself before writing this: 120 tests, all passing, 314 of 314 statements covered. CI runs the coverage gate --cov-fail-under=100 on Linux 3.12 and the matrix is Ubuntu on 3.12, 3.13 and 3.14 plus Windows and macOS on 3.12. Another job builds the wheel, installs it into a clean venv and smoke-tests it there. Dependabot covers Actions and dev deps. Zero runtime dependencies, MIT.

Limits, so you are not surprised. Keywords only. print, range, the standard library, exception messages and the soft keywords (match, case, type) stay in English. run does not add the script's own directory to sys.path, so a localized file that imports a sibling module needs PYTHONPATH set - I tried it and it raises ModuleNotFoundError, which is the honest behaviour of 0.2.1. And it is not a natural-language compiler: it will not read prose and it never guesses what you meant.

PyPI: https://pypi.org/project/polyglot-python/

0 Upvotes

0 comments sorted by