Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(readme_generator/i18n): make README.md.j2 translatable #2149

Merged
merged 14 commits into from
Mar 22, 2024
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
21 changes: 21 additions & 0 deletions tools/readme_generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,24 @@ Add the webhook.service to systemd config, then start it:
```bash
systemctl start the_webhook_service
```

## Translation

It's based on Babel integrated into jinja2 : <https://babel.pocoo.org/en/latest/>

```bash
source venv/bin/activate

# Extract the english sentences from the code, needed if you modified it
pybabel extract --ignore-dirs venv -F babel.cfg -o messages.pot .

# If working on a new locale: initialize it (in this example: fr)
pybabel init -i messages.pot -d translations -l fr
# Otherwise, update the existing .po:
pybabel update -i messages.pot -d translations

# ... translate stuff in translations/<lang>/LC_MESSAGES/messages.po
# re-run the 'update' command to let Babel properly format the text
# then compile:
pybabel compile -d translations
```
1 change: 1 addition & 0 deletions tools/readme_generator/babel.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[jinja2: ./templates/*.j2]
88 changes: 68 additions & 20 deletions tools/readme_generator/make_readme.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#! /usr/bin/env python3

import os
import argparse
import json
from pathlib import Path
Expand All @@ -9,6 +10,9 @@

import toml
from jinja2 import Environment, FileSystemLoader
from babel.support import Translations
from babel.messages.pofile import PoFileParser
from langcodes import Language

README_GEN_DIR = Path(__file__).resolve().parent
APPS_REPO_ROOT = README_GEN_DIR.parent.parent
Expand Down Expand Up @@ -49,7 +53,46 @@ def generate_READMEs(app_path: Path):
)
return

env = Environment(loader=FileSystemLoader(README_GEN_DIR / "templates"))
poparser = PoFileParser({})
poparser.parse(open("messages.pot"))

# we only want to translate a README if all strings are translatables so we
# do this loop to detect which language provides a full translation
fully_translated_langs: List[str] = []
for available_translations in os.listdir("translations"):
translations = Translations.load("translations", available_translations)

is_fully_translated = True
for sentence in poparser.catalog:
# ignore empty strings
if not sentence.strip():
continue

if sentence not in translations._catalog:
is_fully_translated = False
break

if not translations._catalog[sentence]:
is_fully_translated = False
break

if is_fully_translated:
fully_translated_langs.append(available_translations)
else:
print(
"WARNING: skip generating translated README for "
f"{Language(available_translations).language_name()} ({available_translations}) "
"because it is not fully translated yet."
)

fully_translated_langs.sort()

env = Environment(
loader=FileSystemLoader(README_GEN_DIR / "templates"),
extensions=["jinja2.ext.i18n"],
)
translations = Translations.load("translations", ["fr", "en"])
env.install_gettext_translations(translations)

screenshots: List[str] = []

Expand All @@ -64,25 +107,8 @@ def generate_READMEs(app_path: Path):
continue
screenshots.append(str(entry.relative_to(app_path)))

# parse available README template and generate a list in the form of:
# > [("en", ""), ("fr", "_fr"), ...]
available_langs: List[Tuple[str, str]] = [("en", "")]
for README_template in (Path(__file__).parent / "templates").iterdir():
# we only want README_{lang}.md.j2 files
if README_template.name == "README.md.j2":
continue

if not README_template.name.endswith(
".j2"
) or not README_template.name.startswith("README_"):
continue

language_code = README_template.name.split("_")[1].split(".")[0]

available_langs.append((language_code, "_" + language_code))

for lang, lang_suffix in available_langs:
template = env.get_template(f"README{lang_suffix}.md.j2")
def generate_single_README(lang_suffix: str, lang: str):
template = env.get_template("README.md.j2")

if (app_path / "doc" / f"DESCRIPTION{lang_suffix}.md").exists():
description = (
Expand Down Expand Up @@ -130,6 +156,28 @@ def generate_READMEs(app_path: Path):
)
(app_path / f"README{lang_suffix}.md").write_text(out)

generate_single_README("", "en")

for lang in fully_translated_langs:
generate_single_README("_" + lang, lang)

links_to_other_READMEs = []
for language in fully_translated_langs:
translations = Translations.load("translations", [language])
language_name_in_itself = Language.get(language).autonym()
links_to_other_READMEs.append(
(
f"README_{language}.md",
translations.gettext("Read the README in %(language)s")
% {"language": language_name_in_itself},
)
)

out: str = env.get_template("ALL_README.md.j2").render(
links_to_other_READMEs=links_to_other_READMEs
)
(app_path / "ALL_README.md").write_text(out)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
Expand Down
183 changes: 183 additions & 0 deletions tools/readme_generator/messages.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Translations template for PROJECT.
# Copyright (C) 2024 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-22 06:28+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"

#: templates/ALL_README.md.j2:12
#, python-format
msgid "Read the README in %(language)s"
msgstr ""

#: templates/README.md.j2:2
msgid "Packaging an app, starting from this example"
msgstr ""

#: templates/README.md.j2:4
msgid ""
"Copy this app before working on it, using the ['Use this "
"template'](https://github.com/YunoHost/example_ynh/generate) button on "
"the Github repo."
msgstr ""

#: templates/README.md.j2:5
msgid "Edit the `manifest.json` with app specific info."
msgstr ""

#: templates/README.md.j2:6
msgid ""
"Edit the `install`, `upgrade`, `remove`, `backup`, and `restore` scripts,"
" and any relevant conf files in `conf/`."
msgstr ""

#: templates/README.md.j2:7
msgid ""
"Using the [script helpers "
"documentation.](https://yunohost.org/packaging_apps_helpers)"
msgstr ""

#: templates/README.md.j2:8
msgid "Add a `LICENSE` file for the package."
msgstr ""

#: templates/README.md.j2:9
msgid "Edit `doc/DISCLAIMER*.md`"
msgstr ""

#: templates/README.md.j2:10
msgid ""
"The `README.md` files are to be automatically generated by "
"https://github.com/YunoHost/apps/tree/master/tools/readme_generator"
msgstr ""

#: templates/README.md.j2:16
msgid ""
"N.B.: This README was automatically generated by "
"https://github.com/YunoHost/apps/tree/master/tools/readme_generator\n"
"It shall NOT be edited by hand."
msgstr ""

#: templates/README.md.j2:20
#, python-format
msgid "%(application_name)s for YunoHost"
msgstr ""

#: templates/README.md.j2:22
msgid "Integration level"
msgstr ""

#: templates/README.md.j2:22
msgid "Working status"
msgstr ""

#: templates/README.md.j2:22
msgid "Maintenance status"
msgstr ""

#: templates/README.md.j2:24
#, python-format
msgid "Install %(application_name)s with YunoHost"
msgstr ""

#: templates/README.md.j2:26
msgid "Read this README is other languages."
msgstr ""

#: templates/README.md.j2:28
#, python-format
msgid ""
"This package allows you to install %(application_name)s quickly and "
"simply on a YunoHost server.\n"
"If you don't have YunoHost, please consult [the "
"guide](https://yunohost.org/#/install) to learn how to install it."
msgstr ""

#: templates/README.md.j2:31
msgid "Overview"
msgstr ""

#: templates/README.md.j2:34
msgid "**Shipped version:**"
msgstr ""

#: templates/README.md.j2:38
msgid "**Demo:**"
msgstr ""

#: templates/README.md.j2:42
msgid "Screenshots"
msgstr ""

#: templates/README.md.j2:45
#, python-format
msgid "Screenshot of %(application_name)s"
msgstr ""

#: templates/README.md.j2:50
msgid "Disclaimers / important information"
msgstr ""

#: templates/README.md.j2:56
msgid "Antifeatures"
msgstr ""

#: templates/README.md.j2:63
msgid "Documentation and resources"
msgstr ""

#: templates/README.md.j2:65
msgid "Official app website:"
msgstr ""

#: templates/README.md.j2:67
msgid "Official user documentation:"
msgstr ""

#: templates/README.md.j2:69
msgid "Official admin documentation:"
msgstr ""

#: templates/README.md.j2:71
msgid "Upstream app code repository:"
msgstr ""

#: templates/README.md.j2:73
msgid "YunoHost Store:"
msgstr ""

#: templates/README.md.j2:74
msgid "Report a bug:"
msgstr ""

#: templates/README.md.j2:76
msgid "Developer info"
msgstr ""

#: templates/README.md.j2:78
#, python-format
msgid ""
"Please send your pull request to the [testing "
"branch](%(testing_branch_url)s)"
msgstr ""

#: templates/README.md.j2:81
msgid "To try the testing branch, please proceed like that."
msgstr ""

#: templates/README.md.j2:89
msgid "More info regarding app packaging:"
msgstr ""

3 changes: 3 additions & 0 deletions tools/readme_generator/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ sanic==21.12.2
pyyaml
toml
websockets==10.0
babel
langcodes
language_data
13 changes: 13 additions & 0 deletions tools/readme_generator/templates/ALL_README.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# All available README files by language

[Read the README in English](README.md)

{% for filename, translated_sentence in links_to_other_READMEs %}
* [{{ translated_sentence }}]({{ filename }})
{% endfor %}

{% if False %}
Yes this is a hack to add the translatable string to messages.pot

{{ _("Read the README in %(language)s") }}
{% endif %}
Loading
Loading