#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2025 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # See the file COPYING for details. from datetime import datetime from jinja2.filters import pass_environment as environmentfilter import locale from num2words import num2words import re from django.conf import settings def set_locale(): language_code = settings.LANGUAGE_CODE.split("-") language_code = language_code[0] + "_" + language_code[1].upper() for language_suffix in (".utf8", ""): try: locale.setlocale(locale.LC_TIME, language_code + language_suffix) break except locale.Error: pass @environmentfilter def float_format(*args): """ 10350.5 -> 10 350,5 5 -> 5 5.449999 -> 5,45 """ value = args[0] if len(args) == 1 else args[1] # jinja simple filter if value is None or value == "": return "" try: value = float(value) except ValueError: return "" locale.setlocale(locale.LC_ALL, "fr_FR.UTF-8") if int(value) != value: value = float(f"{value:.2f}") return f"{value:n}" @environmentfilter def euro_format(*args): """ 15000 -> 15 000,00 € 5 -> 5,00 € """ value = args[0] if len(args) == 1 else args[1] # jinja simple filter value = float_format(value) if not value: return "" parts = value.split(",") if len(parts) < 2: return value + ",00 €" elif len(parts[1]) == 1: return value + "0 €" return value + " €" @environmentfilter def number_to_words(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter if value is None or value == "": return "" try: value = float(value) except ValueError: return "" return num2words(value, lang=settings.LANGUAGE_CODE.split("-")[0]) @environmentfilter def replace_line_breaks(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter return (value or "").replace("\r\n", "\n") @environmentfilter def capfirst_filter(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter return value[0].upper() + value[1:] if value else value @environmentfilter def lowerfirst_filter(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter return value[0].lower() + value[1:] if value else value RE_CAP = re.compile(r"[^-' ]+") SEP = ("un", "une", "le", "la", "les", "lez", "d", "l", "de", "des", "du", "sur", "sous", "en") @environmentfilter def capitalize_filter(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter if not value: return "" value = value.lower() res = "" for m in RE_CAP.finditer(value): start = m.start() if start: res += value[start - 1] v = m.group() if v not in SEP: v = v[0].upper() + v[1:] res += v return res @environmentfilter def human_date_filter(*args): value = args[0] if len(args) == 1 else args[1] # jinja simple filter try: value = datetime.strptime(value, "%Y-%m-%d") except (ValueError, TypeError) as __: return "" set_locale() return value.strftime(settings.DATE_FORMAT)