From 0482101db2cd17389707f2e38a6705cd5afbc799 Mon Sep 17 00:00:00 2001 From: Emerson Rocha Date: Fri, 2 Sep 2022 06:17:53 -0300 Subject: [PATCH] i18n (#3): started migration to use liquid template engine over mustache --- .github/requirements.txt | 7 +- .github/workflows/data-lint.yml | 2 +- .github/workflows/main.yml | 2 +- CONTRIBUTING.md | 17 ++++- scripts/readme-from-csv.py | 124 +++++++++++++++++++++++++++++++- 5 files changed, 146 insertions(+), 6 deletions(-) diff --git a/.github/requirements.txt b/.github/requirements.txt index 8aa82ba..5a2f010 100644 --- a/.github/requirements.txt +++ b/.github/requirements.txt @@ -1,2 +1,7 @@ +frictionless chevron -frictionless \ No newline at end of file + +# Template engine +python-liquid +# Used by i18n +python-liquid-extra diff --git a/.github/workflows/data-lint.yml b/.github/workflows/data-lint.yml index b1607d2..67212cd 100644 --- a/.github/workflows/data-lint.yml +++ b/.github/workflows/data-lint.yml @@ -26,7 +26,7 @@ jobs: - run: pip install frictionless - - name: frictionless validate datapackage.json + - run: frictionless validate datapackage.json # - name: Run linters # uses: wearerequired/lint-action@v2 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f3f51c1..e57b741 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -147,7 +147,7 @@ jobs: cache: "pip" # - run: pip install libhxl hxltm-eticaai openpyxl frictionless csvkit # - run: pip install -r .github/requirements.txt - - run: pip install -r ../.github/requirements.txt + - run: pip install -r .github/requirements.txt continue-on-error: true # #### Java Setup __________________________________________________________ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73751ed..ebba8c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,25 @@ # Contribution Guidelines -## Techincal aspects +## Data contribution The primary way to store the content of this project is on the [data/](data/) folder. This means that if you want to propose new or an edit **for content**, very likely the edit will be on that folder. -## Non techincal +## Language localization contribution + +The translations are stored at [i18n/](i18n/). + +## Code internals contribution + +1. Give a look at our code. It mostly python, bash script and GitHub Action. +2. We use Shopify Liquid template engine (same features as GitHub pages with Jekyll) + with common documentation at https://shopify.github.io/liquid/. + 1. The _specific_ implementation is python-liquid maintaned coordinated by @jg-rp. + Check . `python -m pip install python-liquid` + 2. We also use some extra filters `python -m pip install -U python-liquid-extra` + +## Other non techincal aspects ### Code of Conduct Please note that this project is released with a [Contributor Code of Conduct](.github/CODE_OF_CONDUCT.md). diff --git a/scripts/readme-from-csv.py b/scripts/readme-from-csv.py index 253c940..a5bd54b 100755 --- a/scripts/readme-from-csv.py +++ b/scripts/readme-from-csv.py @@ -23,6 +23,7 @@ # REVISION: 2022-09-01 01:27 UTC csv-to-readme.py -> readme-from-csv.py # =============================================================================== + import glob import os import argparse @@ -30,9 +31,17 @@ from genericpath import exists import re import sys -from typing import List +from typing import List, Type from ast import literal_eval +from liquid import Template +from liquid import FileSystemLoader +from liquid import StrictUndefined +from liquid import Mode +from liquid_extra import filters +from liquid import Environment +from liquid_extra.filters import Translate + # import pystache import chevron @@ -424,6 +433,8 @@ class CSVtoReadme: data_lines: List[list] = None # data_dict: List[list] = None + liquid: Type['LiquidRenderer'] = None + def __init__( self, infile, line_formatter, @@ -453,6 +464,8 @@ def __init__( self.input_delimiter = input_delimiter # self.output_format = output_format + self.liquid = LiquidRenderer() + def _get_url(self, line): for item in reversed(line): if item.startswith(('http://', 'https://')): @@ -599,6 +612,11 @@ def print(self): self.line_formatter, line_variables).replace('\\n', "\n")) + # print(self.liquid.render( + # self.line_formatter, + # line_variables + # )) + if self.group_suffix: print(self.group_suffix) @@ -686,6 +704,110 @@ def print(self): print(line) pass +# @see https://shopify.github.io/liquid/ +# @see https://jg-rp.github.io/liquid/ +# @see https://jg-rp.github.io/liquid/extra/filters#t-translate + + +# template = Template("Hello, {{ you }}!") +# print(template.render(you="World")) # Hello, World! +# print(template.render(you="Liquid")) # Hello, Liquid! + + +# env = Environment() +# env.add_filter("json", filters.JSON()) + + +class LiquidRenderer: + """LiquidRenderer + + @see https://shopify.github.io/liquid/ + @see https://jg-rp.github.io/liquid/ + @see https://jg-rp.github.io/liquid/extra/filters#t-translate + """ + + default_template: Type['Template'] = None + env: Environment + + def __init__(self) -> None: + + self.default_template = Template( + "Hello, {{ you }}!", + # tolerance=Mode.STRICT, + # undefined=StrictUndefined, + ) + # pass + # self.env = Environment() + # self.env.add_filter("json", filters.JSON()) + self.env = Environment( + tolerance=Mode.STRICT, + undefined=StrictUndefined, + # loader=FileSystemLoader("./templates/"), + ) + self.env.add_filter("json", filters.JSON()) + + some_locales = { + "default": { + "layout": { + "greeting": r"Hello {{ name }}", + }, + "cart": { + "general": { + "title": "Shopping Basket", + }, + }, + "pagination": { + "next": "Next Page", + }, + }, + "de": { + "layout": { + "greeting": r"Hallo {{ name }}", + }, + "cart": { + "general": { + "title": "Warenkorb", + }, + }, + "pagination": { + "next": "Nächste Seite", + }, + }, + } + self.env.add_filter(Translate.name, Translate(locales=some_locales)) + + def render(self, template: str = None, context: dict = None) -> str: + + # env = Environment() + # env.add_filter("index", filters.index) + # env.add_filter("json", filters.JSON()) + # if template is None: + # compiled_template = self.default_template + # else: + # compiled_template = Template( + # # "Hello, {{ you }}!", + # template, + # # tolerance=Mode.STRICT, + # # undefined=StrictUndefined, + # ) + if template is None or template is False: + extra_context = {'current_context': context} + compiled_template = self.env.from_string( + '{{ current_context | json }}' + ) + else: + compiled_template = self.env.from_string(template) + extra_context = context + + result = compiled_template.render(extra_context) + return result + + +# lrenderer = LiquidRenderer() +# print(lrenderer.render("Hello, {{ you }}!", {'you': 'you value'})) + +# sys.exit(1) + def evaluate(textoperation: str) -> bool: """evaluate evaluate simple text operations like "1==2"