# Changelog

Toutes les modifications notables de ce plugin sont documentées dans ce fichier.

Le format suit [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
et ce projet adhère au [Versioning Sémantique](https://semver.org/lang/fr/).

## [3.13.2] - 2026-10-26

Suite de la réduction du volume d'envois à l'API : neutralisation du « churn »
de hash provoqué par les nombres variables.

### Fixed

- **Compteurs et nombres variables re-traduits à chaque changement.** Les
  masques existants couvraient dates, heures et téléphones, mais pas les
  nombres génériques. « 3 commentaires » et « 5 commentaires » étaient donc
  deux chaînes distinctes : chaque valeur partait en traduction (crédits) et
  s'accumulait en base — churn continu sur tout compteur dynamique (nombre de
  commentaires, « X résultats », panier, temps relatifs « il y a X jours »…).
  `trim_HTML_string()` masque désormais les nombres restants en placeholder
  `{n}` (une seule chaîne à traduire quelle que soit la valeur, le vrai nombre
  étant restauré à l'affichage via `$params`, même contrat que les masques
  date/heure). Les décimaux/séparateurs (`4,5`, `10,000`, `3.12.1`) sont
  groupés en un seul placeholder. Prudence : les nombres collés à des lettres
  (`3D`, `MP3`, `H264`…) et les placeholders déjà posés ne sont pas touchés.
  Ce masque couvre aussi le churn numérique des temps relatifs (« il y a `{n}`
  jours », « `{n}` days ago »). (`includes/tricot_dom.php` — `trim_HTML_string`)

## [3.13.1] - 2026-10-26

Réduction drastique du volume d'envois à l'API — suite au constat « Tricot
traduit en continu une quantité anormale de chaînes, même quand le site ne
change pas ».

### Fixed

- **Balisage de shortcode page-builder capturé comme contenu.** Des bribes de
  `post_content` non traitées par `do_shortcode()` (champ ACF contenant du
  contenu WPBakery/Salient, fragment AJAX brut, contenu mal fermé) comme
  `[/vc_column_text][nectar_cta btn_style= »basic »…]` partaient à DeepL :
  chaînes « orphelines » qui s'accumulent, crédits gaspillés, et traduction
  qui aurait corrompu le shortcode si elle avait été ré-appliquée.
  `string_translate()` saute désormais le balisage de shortcode brut
  (shortcode fermant `[/…]`, identifiant de builder avec underscore,
  `[tag attr=…`, ou attribut encodé `attr= »valeur »`), à l'unique point de
  passage — donc quel que soit le chemin de capture (DOM, AJAX, JSON,
  intégrations). La détection est conservatrice : une phrase contenant
  incidemment `[Note]` ou `[1]` reste traduite.
  (`includes/tricot_translate.php` — `is_shortcode_markup`, `string_translate`)

- **Re-soumission des chaînes déjà traduites à chaque rendu.** La file d'envoi
  (`new_translations`) était alimentée pour **toute** ligne rencontrée, pas
  seulement celles sans traduction. Résultat : à chaque vue d'une page, tout
  son contenu déjà traduit était renvoyé à l'API — d'où l'impression de
  traduction continue alors que rien ne change. Seules les lignes
  `translated IS NULL` sont désormais enfilées. Une source modifiée prend un
  nouveau hash (nouvelle ligne NULL) et reste donc bien reprise ; les flux de
  re-traduction (glossaire, re-soumission manuelle) remettent `translated` à
  NULL avant de ré-enfiler. (`includes/tricot_translate.php` — `string_translate`)

## [3.13.0] - 2026-09-29

### Fixed
- **Traduction anglaise partielle après la détection.** Le rendu déclenché
  par le crawler était traité comme un rendu visiteur : délai de 5 s vers
  l'App, puis disjoncteur de 5 minutes qui bloquait l'envoi de toutes les
  pages suivantes. Le crawler, wp-cron, l'admin et l'AJAX authentifié
  utilisent maintenant le délai long (60 s) et le crawler ignore le
  disjoncteur.
- **Envoi par lots** : les chaînes d'une page partent en lots de 50
  (25 en rendu front, filtre `tricot_api_send_batch_size`), les chaînes
  non traduites en premier. Un lot en échec n'emporte plus toute la page.
  En rendu front, un seul lot est envoyé pour ne pas bloquer l'affichage.
- **La détection signale enfin ses échecs** : erreur réseau ou code HTTP
  différent de 200 sur la page font échouer la source (relance du job en
  arrière-plan, message d'erreur dans le journal de la page Indexation).
  Un délai dépassé est signalé sans relancer la page, qui continue d'être
  traitée côté serveur.
- Délai du rendu de page par le crawler porté de 30 s à 120 s (filtre
  `tricot_indexation_fetch_timeout`) et verrou du job de détection porté
  à 10 minutes pour éviter deux passages en parallèle.
- Le crawl de la page Indexation ne s'arrête plus à la première erreur
  réseau : 3 tentatives avant l'arrêt.
- Les traductions reçues hors rendu de page (crawler, cron, admin)
  purgent le cache des pages concernées (nouvelle action
  `tricot_translations_received`).

### Changed
- **Charge réduite sur l'App** : lors d'une visite (rendu front), seules
  les chaînes sans traduction sont envoyées. Les chaînes déjà traduites
  (environ 97 % du trafic observé) ne partent plus que depuis la
  détection, l'admin et le cron de rattrapage. Le créneau de 2 s
  des visiteurs anonymes n'est consommé que s'il y a quelque chose à
  envoyer.

### Added
- **Rapatriement horaire des modifications faites dans l'App** (portail,
  admin) via `/sync_translations?modified_since=…` : remplace le retour
  des traductions qui passait par les renvois à chaque visite. Seules les
  lignes locales existantes et réellement modifiées sont mises à jour, puis
  le cache des pages concernées est purgé. Nécessite TricotApp 0.13.0 ;
  ignoré proprement avec une App plus ancienne.
- **Rattrapage automatique** des chaînes jamais traduites : cron horaire
  `tricot_retry_untranslated` (200 chaînes par passage, filtre
  `tricot_retry_untranslated_limit`), page par page, pour les langues en
  traduction automatique. Après chaque page détectée, les chaînes restées
  sans traduction sont aussi renvoyées immédiatement.

## [3.6.0] - 2026-04-18

### Added

- **Période d'essai gratuite de 7 jours** avec 3 000 crédits et
  l'ensemble des fonctionnalités Premium (sauf import). Un nouveau
  parcours d'activation dans le wizard permet de choisir entre essai
  gratuit, plan gratuit ou achat direct Pro / Premium.
- **Bandeau et messages contextuels** dans l'admin pendant l'essai :
  compte à rebours, nombre de crédits restants, boutons pour passer
  à Pro ou Premium en un clic.
- **Date d'expiration** affichée à côté du statut *Active* sur la
  page *Activation de la licence* + nouveau bouton **Mettre à niveau
  ma licence** qui redirige vers le portail client.
- **Page *Gestion des crédits* retravaillée** avec affichage dynamique
  des trois blocs de crédits disponibles selon le plan actif.
- **Sélection par plage sur les tableaux admin** : maintenir *Maj*
  tout en cliquant une case à cocher sélectionne toutes les lignes
  entre la dernière cliquée et la courante (comportement standard
  style Gmail / Finder).
- **Compatibilité étendue avec les plugins populaires** :
  - *SEO* — Yoast, Rank Math, All In One SEO, The SEO Framework,
    Slim SEO, SmartCrawl (en plus de SEOPress déjà couvert).
  - *Formulaires* — Gravity Forms, WPForms, Formidable Forms,
    Fluent Forms.
  - *Constructeurs de pages* — Elementor, Divi.
  - *Événements* — The Events Calendar.
  - *Consentement cookies (RGPD)* — Complianz.
  - *Champs personnalisés* — intégration ACF enrichie (repeater,
    flexible content, groupes, liens, Options Pages).
- **Invalidation automatique du cache** à chaque modification de
  traduction pour 9 plugins de cache (WP Rocket, W3 Total Cache,
  LiteSpeed Cache, WP Super Cache, WP Fastest Cache, SG Optimizer,
  Hummingbird, Cache Enabler, Breeze). Les visiteurs voient les
  nouvelles traductions sans attendre l'expiration du cache.

### Changed

- **Libellé** *Gestion du crédit* → *Gestion des crédits* (pluriel).
- **Compte à rebours d'essai** plus précis : l'heure et le jour
  affichés correspondent désormais à ce que l'utilisateur attend
  intuitivement (un essai de 7 jours commence bien à 7 jours, pas 6).

### Fixed

- Spinners natifs de WordPress (sauvegarde inline, médias, mises à
  jour) qui apparaissaient incorrectement à cause d'une collision
  CSS avec Tricot.
- Plusieurs correctifs autour du cycle de vie de la période d'essai
  (conversion en plan payant, déduction correcte des crédits
  consommés, messages d'état cohérents).
- Diverses améliorations mineures d'affichage dans l'admin.

### Security

- Tous les nouveaux endpoints REST sont protégés par validation
  de licence + clé API côté public, et par vérification de capacité
  `manage_options` côté administration.

## [3.5.12] - Antérieur

Version de référence — voir l'historique Git pour les changements
précédents.
