← Files VeraARCHIVED FILE

modules/variance-analysis/scripts/report_locales.py

21.8 KB · Oct 2, 2026 · 00:29 UTC

↓ Download file

"""French and German display copy for the native variance report."""

from __future__ import annotations

__all__ = ["REPORT_TEXT", "CONTROL_FIELDS", "CONTROL_STATUS", "OVERVIEW_TEXT"]

OVERVIEW_TEXT = {
    "it": {
        "title": "Confronto degli importi",
        "draft_title": "Confronto degli importi — bozza",
        "heading": "Risultato del confronto",
        "line": "Voce",
        "total": "Totale",
        "intro": "Da {baseline} a {actual} {currency}: lo scostamento è {delta} {currency} ({percent}).",
        "note": "Le voci ricostruiscono il totale. Δ = confronto meno base. La percentuale non è esposta quando la base è nulla o negativa; il segno degli importi va letto secondo la convenzione contabile indicata sotto.",
        "amount_note": "Il file permette il confronto degli importi. Senza quantità non si possono distinguere effetti di prezzo, volume e mix né dedurre le cause commerciali.",
        "variance_type_total": "Scostamento totale",
        "sequence": "Sequenza alternativa dei contributi",
    },
    "en": {
        "title": "Amount comparison",
        "draft_title": "Amount comparison — draft",
        "heading": "Comparison result",
        "line": "Category",
        "total": "Total",
        "intro": "From {baseline} to {actual} {currency}: the difference is {delta} {currency} ({percent}).",
        "note": "The categories reconcile to the total. Δ = comparison less baseline. Percentages are unavailable for zero or negative bases; interpret amount signs using the accounting convention below.",
        "amount_note": "The file supports an amount comparison. Without quantities it cannot separate price, volume and mix effects or establish commercial causes.",
        "variance_type_total": "Total variance",
        "sequence": "Alternative contribution sequence",
    },
    "fr": {
        "title": "Comparaison des montants",
        "draft_title": "Comparaison des montants — brouillon",
        "heading": "Résultat de la comparaison",
        "line": "Rubrique",
        "total": "Total",
        "intro": "De {baseline} à {actual} {currency} : l’écart est de {delta} {currency} ({percent}).",
        "note": "Les rubriques reconstituent le total. Δ = comparaison moins base. Le pourcentage n’est pas présenté lorsque la base est nulle ou négative ; le signe des montants suit la convention comptable ci-dessous.",
        "amount_note": "Le fichier permet de comparer des montants. Sans quantités, il ne permet ni de distinguer les effets de prix, volume et mix, ni d’établir les causes commerciales.",
        "variance_type_total": "Écart total",
        "sequence": "Autre séquence de contributions",
    },
    "de": {
        "title": "Betragsvergleich",
        "draft_title": "Betragsvergleich — Entwurf",
        "heading": "Ergebnis des Vergleichs",
        "line": "Position",
        "total": "Gesamt",
        "intro": "Von {baseline} auf {actual} {currency}: Die Abweichung beträgt {delta} {currency} ({percent}).",
        "note": "Die Positionen ergeben die Gesamtsumme. Δ = Vergleich minus Basis. Bei einer Basis von null oder einem negativen Wert entfällt die Prozentangabe; die Bedeutung der Vorzeichen folgt der unten genannten Konvention.",
        "amount_note": "Die Datei ermöglicht einen Betragsvergleich. Ohne Mengen lassen sich Preis-, Volumen- und Mixeffekte nicht trennen und wirtschaftliche Ursachen nicht belegen.",
        "variance_type_total": "Gesamtabweichung",
        "sequence": "Alternative Beitragsfolge",
    },
    "es": {
        "title": "Comparación de importes",
        "draft_title": "Comparación de importes — borrador",
        "heading": "Resultado de la comparación",
        "line": "Partida",
        "total": "Total",
        "intro": "De {baseline} a {actual} {currency}: la diferencia es de {delta} {currency} ({percent}).",
        "note": "Las partidas concilian con el total. Δ = comparación menos base. No se muestra el porcentaje si la base es nula o negativa; los signos deben leerse según la convención contable indicada abajo.",
        "amount_note": "El archivo permite comparar importes. Sin cantidades no se pueden separar efectos de precio, volumen y mix ni demostrar causas comerciales.",
        "variance_type_total": "Variación total",
        "sequence": "Secuencia alternativa de contribuciones",
    },
}

REPORT_TEXT = {
    "fr": {
        "title": "Analyse des écarts",
        "draft_title": "Analyse des écarts — brouillon",
        "draft_notice": "Brouillon de travail : la séquence de référence est choisie mécaniquement ; elle ne constitue pas une conclusion approuvée sur les causes économiques.",
        "accounting_controls": "Périmètre et contrôles comptables",
        "accounting_field": "Contrôle",
        "accounting_value": "Résultat",
        "subtitle": "Réalisé et budget",
        "summary": "Synthèse",
        "source_data": "Principales données justificatives",
        "reading_notes": "Notes de lecture",
        "bridge_summary": "Séquence de référence",
        "product_line_drilldown": "Détail de la première contribution",
        "mixed_deep_dive": "Détail à dimensions multiples",
        "chart_1": "Séquence de référence",
        "chart_2": "Détail de la première ligne",
        "chart_3": "Autre séquence de contributions",
        "chart_small_multiples": "Écarts par {dimension}",
        "chart_pvm_ladder": "Décomposition prix, quantités et mix",
        "drilldown_findings": "Constats issus des détails sélectionnés",
        "source_units": "Les montants conservent l’unité de la source ; aucune devise explicite n’est fournie.",
        "currency_note": "Les montants sont exprimés en {currency}, selon la devise retenue pour cette analyse.",
        "price_only": "Le calcul attribue l’écart au prix : les quantités de {baseline_name} et {comparison_name} sont identiques au niveau de calcul, et les effets de quantité et de mix sont nuls.",
        "component_note": "La principale composante calculée est {dominant_type} ({dominant_amount}) ; détail : {components}.",
        "residual_note": "Dans une séquence de contributions, chaque ligne est calculée après retrait des contributions précédentes. Elle ne représente donc pas le total indépendant de la dimension.",
        "source_caption": "Synthèse des données sélectionnées.",
        "drilldown_caption": "Contributions mesurées dans les détails sélectionnés.",
        "chart_footer": "Les contributions sont présentées dans l’ordre ; le solde restant figure dans Autres.",
        "chart_summary_title": "Séquence de référence : {label}",
        "chart_summary_subtitle": "{comparison}, contribution sélectionnée",
        "chart_drilldown_title": "Détail : {label}",
        "chart_drilldown_subtitle": "{comparison}, détail de la ligne sélectionnée",
        "chart_mixed_title": "Séquence à dimensions multiples",
        "chart_mixed_subtitle": "{comparison}, dimensions successives différentes",
        "summary_intro": "L’écart entre {comparison_name} et {baseline_name} est de {delta}. La séquence retient {driver_count} contributions ({items}) et un solde de {residual}.",
        "draft_summary_intro": "L’écart calculé entre {comparison_name} et {baseline_name} est de {delta}. La séquence de référence comporte {driver_count} lignes ({items}) et un solde de {residual}. Ce choix mécanique ne démontre pas les causes économiques.",
        "drilldown_intro": "Le détail de la première ligne montre les contributions suivantes : {items}. La contribution se concentre principalement sur {top_label}.",
        "draft_drilldown_intro": "Le détail de la première ligne montre les contributions calculées : {items}. Leur pertinence économique reste à examiner.",
        "mixed_intro": "Une autre séquence calculée présente {items}, avec un solde de {residual}. Chaque ligne doit être lue après retrait des lignes précédentes.",
        "draft_mixed_intro": "Une séquence à dimensions multiples est également disponible ({items}), avec un solde de {residual}. Sa pertinence reste à examiner.",
        "bridge_reading": "Vérifie que les contributions et le solde reconstituent l’écart.",
        "drilldown_reading": "Décompose la première ligne sélectionnée.",
        "mixed_reading": "Présente une autre séquence de contributions résiduelles.",
        "data_key": "Données clés",
        "reading": "Lecture",
        "residual": "solde",
        "source_col": "Source",
        "analysis_area": "Détail analysé",
        "useful_reading": "Lecture utile",
        "chart_1_reading": "La séquence ({items}) reconstitue l’écart {comparison}, avec un solde final de {residual}.",
        "chart_2_reading": "Le détail de la première ligne comprend {top_label} et les autres contributions calculées.",
        "chart_3_reading": "L’autre séquence à dimensions multiples comprend {items}.",
        "chart_small_multiples_reading": "Les écarts par {dimension} montrent les principales contributions calculées en valeur absolue : {items}.",
        "chart_pvm_ladder_reading": "Le même écart est décomposé à trois niveaux : total combiné, prix et quantités/mix, puis prix, quantités et mix séparés. Composantes : {items}.",
        "chart_1_caption": "La concordance arithmétique est vérifiée ; le choix de la séquence nécessite une revue professionnelle.",
        "chart_1_caption_approved": "La concordance arithmétique est vérifiée ; le choix de la séquence est consigné dans la revue professionnelle.",
        "chart_2_caption": "Le détail montre les contributions mesurées de la première ligne sélectionnée.",
        "chart_3_caption": "Chaque ligne est nette des contributions précédentes.",
        "chart_small_multiples_caption": "Chaque panneau montre les composantes calculées pour un membre de la dimension.",
        "chart_pvm_ladder_caption": "Les panneaux utilisent les mêmes totaux et la même échelle ; seul le niveau de décomposition change.",
        "pvm_ladder_source": "Décomposition prix, quantités et mix",
        "pvm_ladder_reading": "Compare trois décompositions du même écart.",
        "small_multiples_source": "Comparaison par rubrique",
        "small_multiples_reading": "Présente le même calcul pour chaque membre sélectionné.",
        "drilldown_balance": "Le solde comprend des compensations entre contributions positives et négatives.",
        "drilldown_concentration": "La contribution provient de plusieurs éléments.",
        "drilldown_composition": "Le solde se concentre sur quelques éléments.",
        "top_contributions": "Principales contributions : {items}",
        "variance_type_total": "Écart total",
        "variance_type_price": "Prix",
        "variance_type_units": "Quantités",
        "variance_type_volume": "Volume",
        "variance_type_mix": "Mix",
        "variance_type_other": "Autres",
        "variance_type_balance": "Solde",
        "variance_type_net_sales": "Ventes nettes",
        "variance_type_discount": "Remises",
        "variance_type_cogs": "Coût des ventes",
        "variance_type_gross_margin": "Marge brute",
        "variance_type_units_and_mix": "Quantités et mix",
        "variance_type_price_and_units_and_mix": "Prix, quantités et mix",
        "variance_type_price_and_volume_and_mix": "Prix, volume et mix",
        "dimension_category": "rubrique",
        "dimension_month": "mois",
    },
    "de": {
        "title": "Abweichungsanalyse",
        "draft_title": "Abweichungsanalyse — Entwurf",
        "draft_notice": "Arbeitsentwurf: Die Referenzfolge wird rechnerisch ausgewählt. Sie ist keine freigegebene Aussage über wirtschaftliche Ursachen.",
        "accounting_controls": "Umfang und rechnerische Kontrollen",
        "accounting_field": "Kontrolle",
        "accounting_value": "Ergebnis",
        "subtitle": "Ist und Budget",
        "summary": "Überblick",
        "source_data": "Wesentliche Nachweisdaten",
        "reading_notes": "Lesehinweise",
        "bridge_summary": "Referenzfolge",
        "product_line_drilldown": "Detail zum ersten Beitrag",
        "mixed_deep_dive": "Detail mit mehreren Dimensionen",
        "chart_1": "Referenzfolge",
        "chart_2": "Detail zur ersten Zeile",
        "chart_3": "Alternative Beitragsfolge",
        "chart_small_multiples": "Abweichungen nach {dimension}",
        "chart_pvm_ladder": "Zerlegung in Preis, Menge und Mix",
        "drilldown_findings": "Befunde aus den ausgewählten Details",
        "source_units": "Die Beträge behalten die Einheit der Quelle; eine ausdrückliche Währungsangabe fehlt.",
        "currency_note": "Die Beträge werden in der für diese Analyse festgelegten Währung {currency} dargestellt.",
        "price_only": "Der berechnete Unterschied entfällt auf den Preis: Die Mengen von {baseline_name} und {comparison_name} stimmen auf Berechnungsebene überein; Mengen- und Mixeffekte sind null.",
        "component_note": "Die größte berechnete Komponente ist {dominant_type} ({dominant_amount}); Einzelbeiträge: {components}.",
        "residual_note": "Jede Zeile einer Beitragsfolge wird nach Abzug der vorherigen Beiträge berechnet. Sie ist daher nicht der eigenständige Gesamtbetrag dieser Dimension.",
        "source_caption": "Zusammenfassung der ausgewählten Daten.",
        "drilldown_caption": "Gemessene Beiträge in den ausgewählten Details.",
        "chart_footer": "Die Beiträge folgen der ausgewählten Reihenfolge; der verbleibende Saldo steht unter Sonstige.",
        "chart_summary_title": "Referenzfolge: {label}",
        "chart_summary_subtitle": "{comparison}, ausgewählter Beitrag",
        "chart_drilldown_title": "Detail: {label}",
        "chart_drilldown_subtitle": "{comparison}, Detail zur ausgewählten Zeile",
        "chart_mixed_title": "Folge mit mehreren Dimensionen",
        "chart_mixed_subtitle": "{comparison}, wechselnde Dimensionen",
        "summary_intro": "Die Abweichung zwischen {comparison_name} und {baseline_name} beträgt {delta}. Die Folge enthält {driver_count} Beiträge ({items}) und einen Restbetrag von {residual}.",
        "draft_summary_intro": "Die berechnete Abweichung zwischen {comparison_name} und {baseline_name} beträgt {delta}. Die Referenzfolge enthält {driver_count} Zeilen ({items}) und einen Restbetrag von {residual}. Diese rechnerische Auswahl belegt keine wirtschaftlichen Ursachen.",
        "drilldown_intro": "Das Detail zur ersten Zeile zeigt folgende Beiträge: {items}. Der Beitrag entfällt hauptsächlich auf {top_label}.",
        "draft_drilldown_intro": "Das Detail zur ersten Zeile zeigt berechnete Beiträge: {items}. Ihre wirtschaftliche Bedeutung ist noch zu prüfen.",
        "mixed_intro": "Eine alternative berechnete Folge zeigt {items} mit einem Restbetrag von {residual}. Jede Zeile ist nach Abzug der vorherigen Beiträge zu lesen.",
        "draft_mixed_intro": "Eine Folge mit mehreren Dimensionen ist ebenfalls verfügbar ({items}), mit einem Restbetrag von {residual}. Ihre Eignung ist noch zu prüfen.",
        "bridge_reading": "Prüft, ob Beiträge und Restbetrag die Gesamtabweichung ergeben.",
        "drilldown_reading": "Schlüsselt die erste ausgewählte Zeile auf.",
        "mixed_reading": "Zeigt eine alternative Folge verbleibender Beiträge.",
        "data_key": "Wesentliche Daten",
        "reading": "Einordnung",
        "residual": "Restbetrag",
        "source_col": "Quelle",
        "analysis_area": "Analysiertes Detail",
        "useful_reading": "Einordnung",
        "chart_1_reading": "Die Folge ({items}) ergibt die Abweichung {comparison} mit einem abschließenden Restbetrag von {residual}.",
        "chart_2_reading": "Das Detail zur ersten Zeile enthält {top_label} und weitere berechnete Beiträge.",
        "chart_3_reading": "Die alternative Folge mit mehreren Dimensionen enthält {items}.",
        "chart_small_multiples_reading": "Die Abweichungen nach {dimension} zeigen die betragsmäßig größten berechneten Beiträge: {items}.",
        "chart_pvm_ladder_reading": "Dieselbe Abweichung wird auf drei Ebenen zerlegt: Gesamtbetrag, Preis und Menge/Mix, anschließend Preis, Menge und Mix getrennt. Komponenten: {items}.",
        "chart_1_caption": "Die rechnerische Abstimmung ist erfolgt; die Auswahl der Folge erfordert fachliche Prüfung.",
        "chart_1_caption_approved": "Die rechnerische Abstimmung ist erfolgt; die Auswahl der Folge ist in der fachlichen Prüfung dokumentiert.",
        "chart_2_caption": "Das Detail zeigt die gemessenen Beiträge der ersten ausgewählten Zeile.",
        "chart_3_caption": "Jede Zeile ist um die zuvor ausgewiesenen Beiträge bereinigt.",
        "chart_small_multiples_caption": "Jedes Teilbild zeigt die berechneten Komponenten eines Dimensionsmitglieds.",
        "chart_pvm_ladder_caption": "Alle Teilbilder verwenden dieselben Summen und denselben Maßstab; nur die Tiefe der Zerlegung ändert sich.",
        "pvm_ladder_source": "Zerlegung in Preis, Menge und Mix",
        "pvm_ladder_reading": "Vergleicht drei Zerlegungen derselben Abweichung.",
        "small_multiples_source": "Vergleich nach Position",
        "small_multiples_reading": "Zeigt dieselbe Berechnung für jedes ausgewählte Mitglied.",
        "drilldown_balance": "Der Saldo umfasst Verrechnungen zwischen positiven und negativen Beiträgen.",
        "drilldown_concentration": "Der Beitrag stammt aus mehreren Positionen.",
        "drilldown_composition": "Der Restbetrag konzentriert sich auf wenige Positionen.",
        "top_contributions": "Wesentliche Beiträge: {items}",
        "variance_type_total": "Gesamtabweichung",
        "variance_type_price": "Preis",
        "variance_type_units": "Menge",
        "variance_type_volume": "Volumen",
        "variance_type_mix": "Mix",
        "variance_type_other": "Sonstige",
        "variance_type_balance": "Saldo",
        "variance_type_net_sales": "Nettoumsatz",
        "variance_type_discount": "Rabatte",
        "variance_type_cogs": "Umsatzkosten",
        "variance_type_gross_margin": "Bruttomarge",
        "variance_type_units_and_mix": "Menge und Mix",
        "variance_type_price_and_units_and_mix": "Preis, Menge und Mix",
        "variance_type_price_and_volume_and_mix": "Preis, Volumen und Mix",
        "dimension_category": "Position",
        "dimension_month": "Monat",
    },
}

CONTROL_FIELDS = {
    "fr": dict(
        zip(
            (
                "perimeter",
                "tie_out",
                "bridge",
                "convention",
                "materiality",
                "professional",
                "root_cause",
                "unresolved",
                "none",
                "baseline",
                "comparison",
                "calculated",
                "source",
                "max_delta",
                "reviewer",
                "reviewed_at",
                "alternative",
                "rationale",
            ),
            (
                "Périmètre",
                "Rapprochement avec la source",
                "Concordance des contributions",
                "Convention favorable/défavorable",
                "Matérialité",
                "Revue professionnelle",
                "Revue des alternatives",
                "Points en suspens",
                "Aucun",
                "base",
                "comparaison",
                "calculé",
                "source",
                "écart maximal",
                "réviseur",
                "date",
                "alternative",
                "motif",
            ),
            strict=True,
        )
    ),
    "de": dict(
        zip(
            (
                "perimeter",
                "tie_out",
                "bridge",
                "convention",
                "materiality",
                "professional",
                "root_cause",
                "unresolved",
                "none",
                "baseline",
                "comparison",
                "calculated",
                "source",
                "max_delta",
                "reviewer",
                "reviewed_at",
                "alternative",
                "rationale",
            ),
            (
                "Umfang",
                "Abstimmung mit der Quelle",
                "Abstimmung der Beiträge",
                "Konvention günstig/ungünstig",
                "Wesentlichkeit",
                "Fachliche Prüfung",
                "Prüfung der Alternativen",
                "Offene Punkte",
                "Keine",
                "Basis",
                "Vergleich",
                "berechnet",
                "Quelle",
                "größte Abweichung",
                "Prüfer",
                "Datum",
                "Alternative",
                "Begründung",
            ),
            strict=True,
        )
    ),
}

CONTROL_STATUS = {
    "fr": dict(
        zip(
            (
                "pending",
                "established",
                "passed",
                "failed",
                "not_established",
                "applied",
                "not_applied",
                "approved",
            ),
            (
                "en attente",
                "confirmé",
                "conforme",
                "non conforme",
                "non établi",
                "appliqué",
                "non appliqué",
                "approuvé",
            ),
            strict=True,
        )
    ),
    "de": dict(
        zip(
            (
                "pending",
                "established",
                "passed",
                "failed",
                "not_established",
                "applied",
                "not_applied",
                "approved",
            ),
            (
                "ausstehend",
                "bestätigt",
                "bestanden",
                "nicht bestanden",
                "nicht festgestellt",
                "angewandt",
                "nicht angewandt",
                "freigegeben",
            ),
            strict=True,
        )
    ),
}

SHA-256: d2fe7b6bab9ea0c3dcf35ecf7a28bc4c02bc3b51d862f35be63f95eed37fd071