From d9c907a25a0c4b635a78e4de5bc8aa52bec8db59 Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Thu, 21 May 2026 14:36:47 +0000 Subject: [PATCH] added template --- docs/language-packs/template.md | 239 ++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/docs/language-packs/template.md b/docs/language-packs/template.md index def0bb2..543a0b1 100644 --- a/docs/language-packs/template.md +++ b/docs/language-packs/template.md @@ -1 +1,240 @@ # Add Your Language + +Anyone can publish a `foreignthon-xx` language pack to PyPI — no access to the core repo is needed, and the pack works for anyone who installs it the moment it is on PyPI. + +The recommended path is to start from the official language template. See [Contributing → Language Packs](../contributing/language-packs.md) for the full contribution and review process. This page is a quick reference. + +--- + +## Start from the template + +Fork the official language template on Gitea: + +``` +https://git.keshavanand.net/foreign-thon/language-template.git +``` + +The template gives you the full correct structure — `__init__.py`, JSON pack, the universal `tests/test_pack.py`, and all three CI workflows — pre-wired and ready to rename. + +!!! tip "Why fork instead of starting fresh?" + The template includes the shared test suite (`tests/test_pack.py`) that every official pack uses. Starting from it means your CI is already correct and your pack will pass the same checks as `foreignthon-es` and `foreignthon-ta` from day one. + +Alternatively, if you just want a local pack for your own project without publishing, use: + +```bash +fpy new myproject --lang custom +``` + +This scaffolds a `custom.json` locally — no PyPI account needed. See [Custom Packs](../custom-packs.md) for details. + +--- + +## Package structure + +After renaming the template for your language (e.g. French, code `fr`): + +``` +foreignthon-fr/ +├── .gitea/workflows/ +│ ├── ci.yml # pytest on push / PR +│ ├── publish.yml # PyPI upload on v* tag +│ └── trigger-docs.yml # docs rebuild on README.md change +├── .gitignore +├── LICENSE # GPL v3 +├── README.md +├── pyproject.toml +└── src/ + └── foreignthon_fr/ + ├── __init__.py + └── fr.json +``` + +--- + +## `pyproject.toml` + +```toml +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "foreignthon-fr" +version = "0.1.0" +description = "French language pack for ForeignThon." +license = { text = "GPL v3" } +requires-python = ">=3.9" +authors = [ + { name = "Your Name", email = "you@example.com" } +] +keywords = ["foreignthon", "french", "français"] +dependencies = ["foreignthon>=0.5.3"] + +[project.urls] +Homepage = "https://git.keshavanand.net/foreign-thon/foreignthon-fr" + +[project.entry-points."foreignthon.langs"] +fr = "foreignthon_fr" + +[tool.hatch.build.targets.wheel] +packages = ["src/foreignthon_fr"] +``` + +The `[project.entry-points."foreignthon.langs"]` block is what makes ForeignThon auto-discover your pack — the key is the language code, the value is the Python module name. + +--- + +## `__init__.py` + +```python +from importlib.resources import files +from importlib.metadata import version, metadata, PackageNotFoundError + +try: + package_name = (__package__ or "").replace("_", "-") + __version__ = version(package_name) + + pkg_metadata = metadata(package_name) + raw_authors = pkg_metadata.get_all("Author") or [] + raw_emails = pkg_metadata.get_all("Author-email") or [] + + combined = [] + for item in (raw_authors + raw_emails): + clean_name = item.split("<")[0].strip() + if clean_name and clean_name not in combined: + combined.append(clean_name) + + __authors__ = combined + +except PackageNotFoundError: + __version__ = "0.0.0" + __authors__ = [] + + +def get_pack_path(): + return files(__name__) / "fr.json" +``` + +Change `"fr.json"` to match your actual filename. + +--- + +## The JSON pack + +Keys are your language's words. Values are English Python identifiers — **never change the values**. + +```json +{ + "meta": { + "name": "French", + "native_name": "Français", + "code": "fr" + }, + "keywords": { + "si": "if", + "sinon": "else", + "sinonsi": "elif", + "pour": "for", + "tantque": "while", + "déf": "def", + "classe": "class", + "importer": "import", + "depuis": "from", + "comme": "as", + "retourner": "return", + "arrêter": "break", + "continuer": "continue", + "passer": "pass", + "essayer": "try", + "sauf": "except", + "finalement": "finally", + "lever": "raise", + "avec": "with", + "dans": "in", + "est": "is", + "et": "and", + "ou": "or", + "non": "not", + "supprimer": "del", + "global": "global", + "nonlocal": "nonlocal", + "affirmer": "assert", + "générer": "yield", + "attendre": "await", + "asynchrone": "async", + "lambda": "lambda", + "Vrai": "True", + "Faux": "False", + "Rien": "None" + }, + "builtins": { + "afficher": "print", + "saisir": "input", + "longueur": "len", + "intervalle": "range", + ... + }, + "exceptions": { + "ErreurDeValeur": "ValueError", + ... + }, + "error_messages": { + "ValueError": "Erreur de valeur", + ... + }, + "stdlib": { + "mathématiques": "math", + ... + }, + "postfix_keywords": [] +} +``` + +### `postfix_keywords` + +Set this to a list of English keywords if your language is SOV (subject-object-verb) and benefits from `@@` postfix style on decompile. Example (Tamil): + +```json +"postfix_keywords": ["if", "elif", "while", "class", "with"] +``` + +Set it to `[]` for SVO languages like Spanish or French. + +### Filename rule + +The JSON filename **must** match `meta.code` exactly. `fr.json` for code `"fr"`. + +--- + +## Validate and test + +```bash +pip install -e . +pip install pytest + +fpy pack src/foreignthon_fr/fr.json +# ✓ Pack 'French' is valid. + +pytest tests/ -v +``` + +The shared `tests/test_pack.py` checks that all sections exist, all values are real Python identifiers, the filename matches `meta.code`, and `postfix_keywords` entries each have a translation. + +--- + +## Publish + +Tag and push — the CI handles the rest: + +```bash +git tag v0.1.0 +git push origin v0.1.0 +``` + +The `publish.yml` workflow builds the wheel and uploads it to PyPI using the `PYPI_TOKEN` secret. Add your own `PYPI_TOKEN` to your fork's secrets if you are not yet under the official org. + +--- + +## Getting listed + +Once your pack is working and on PyPI, open a PR or issue on [foreignthon-docs](https://git.keshavanand.net/foreign-thon/foreignthon-docs) to get added to the [Language Packs overview](index.md). See [Contributing → Language Packs](../contributing/language-packs.md) for the full process.