SDK · Bewertung durch Endnutzer
Vorschau@sonenta/feedback
Lassen Sie Ihre eigenen Endnutzer Übersetzungen bewerten (5★) und vorschlagen, direkt aus Ihrer ausgelieferten App. React und React Native docken an den @sonenta/*-i18n-Provider an, den Sie bereits betreiben (kein zweiter Kontext, kein Host-Re-Render); alles Weitere läuft über /core, den eingefrorenen Client, den jedes Binding umschließt. Gleiches Protokoll, gleiche serverseitig erzeugte Sitzung, gleiches Moderations-Backoffice. Verfügbar als kostenpflichtiges Add-on ab Pro.
Das Paket @sonenta/feedback wird zum Sonenta-V1-Launch mit dem Add-on für die Übersetzungsbewertung durch Endnutzer ausgeliefert. Der Wire-Contract ist eingefroren (v3); die Framework-Bindings stabilisieren sich noch und können sich vor dem Launch ändern.
1. Installieren (beim Launch)
Ein einziges Paket. Importieren Sie den Einstiegspunkt Ihres Frameworks: @sonenta/feedback/react, /native (RN/Expo), /vue, /svelte oder /core für alles andere. vue / svelte sind optionale Peer-Dependencies, nur der jeweilige Einstiegspunkt benötigt sie. Veröffentlicht mit dem Add-on beim V1-Launch.
terminal 1// ships with the End-user evaluation add-on at the V1 launch2npm i @sonenta/react-i18next @sonenta/feedback3// feedback peers with @sonenta/react-i18next 2.x4// optional peer deps only for the matching entry: vue · svelte 2. React (Web), i18n-Plugin
Fügen Sie feedbackPlugin() dem plugins-Slot Ihres bestehenden @sonenta/react-i18next-Providers (>= 0.7.0) hinzu, kein neuer Provider, kein zweiter Kontext. Der Provider ruft das setup() des Plugins einmal auf und verwendet dessen eigene apiBase / projectId / defaultLocale wieder. Das Panel wird als isoliertes Geschwister-Blatt mit einem privaten Open/Close-Store gemountet: Das Öffnen re-rendert Ihren Host-Baum niemals. Lösen Sie es über Ihr eigenes CTA mithilfe des über controllerRef bereitgestellten Controllers aus (oder dem onReady-Callback).
main.tsx 1// src/main.tsx, plugin of the i18n provider you already run2import { SonentaProvider } from "@sonenta/react-i18next";3import { feedbackPlugin } from "@sonenta/feedback/react";4import { useRef } from "react"; 6const feedback = useRef(null); 8<SonentaProvider9 projectUuid="proj_xxx"10 token={import.meta.env.VITE_SONENTA_TOKEN}11 plugins={[ feedbackPlugin({ controllerRef: feedback }) ]}12>13 <App />14</SonentaProvider> 16// own CTA, does NOT re-render the host tree17<button onClick={() => feedback.current?.open()}>Rate translations</button> Alle Optionen von feedbackPlugin() / createFeedback()
| Option | Typ | Standard |
|---|---|---|
| controllerRef | Ref<Controller> | , |
| onReady | (c) => void | , |
| keys | string[] | auto-discovered |
| flushDebounceMs | number | 1500 |
| maxBatch | number | 20 |
| defaultButton | boolean | false |
3. React Native / Expo
Gleiches Schema vom Einstiegspunkt /native aus: Fügen Sie feedbackPlugin() dem plugins-Slot desselben @sonenta/react-i18next-Providers in Ihrer Expo-App hinzu und lösen Sie über den Controller aus. Keine zusätzlichen nativen Module; die Token-Speicherung verwendet den Secure Store der Plattform.
App.tsx 1// App.tsx (Expo / React Native), same plugins slot2import { SonentaProvider } from "@sonenta/react-i18next";3import { feedbackPlugin } from "@sonenta/feedback/native"; 5<SonentaProvider6 projectUuid="proj_xxx"7 token={process.env.EXPO_PUBLIC_SONENTA_TOKEN}8 plugins={[ feedbackPlugin({ onReady: (c) => (ctrl = c) }) ]}9>{/* … */}</SonentaProvider> 11// wire ctrl.open() to your own button / FAB 4. Alles andere, /core
@sonenta/feedback/core stellt den eingefrorenen FeedbackClient bereit, auf dem alle Adapter aufbauen: acceptTos(), loadStrings(), rate(), suggest(), debounce-ter, gebündelter Transport, rotierendes JWT. Verwenden Sie ihn direkt für jedes Framework ohne First-Party-Adapter.
feedback.ts 1// any framework, the frozen client all adapters wrap2import { FeedbackClient } from "@sonenta/feedback/core"; 4const client = new FeedbackClient({5 apiBase: "https://api.sonenta.dev",6 projectId: "proj_xxx", language: "fr",7 // REQUIRED. Without it, the first authenticated call8 // accepts the end-user ToS on your user's behalf.9 autoAcceptTos: false,10}); 12// show YOUR ToS step, and only once the user agrees:13await client.acceptTos(); // server mints the session14await client.loadStrings(); client.rate(/* … */); client.suggest(/* … */); 16// with autoAcceptTos:false, an unconsented authed call throws17// FeedbackError("not consented") instead of fabricating a record. 5. Eingrenzung auf angezeigte Schlüssel (automatisch)
Das Panel grenzt sich automatisch auf die Schlüssel ein, die tatsächlich in der aktuellen Ansicht angezeigt werden, über das globale Schlüsselregister, das das @sonenta/*-i18n-SDK erzeugt, keine Konfiguration. Übergeben Sie ein explizites keys-Array nur als Fallback (z. B. für Strings, die nicht aus @sonenta/*-i18n stammen); übergeben Sie niemals Ihren gesamten Katalog, das würde jeden String der App offenlegen, nicht die, die der Nutzer gerade betrachtet. Das Register wird beim Mounten verfolgt und per Referenz gezählt: dauerhaft sichtbare Strings (eine Kopfzeile, ein Eyebrow) bleiben registriert, solange ihre Komponente gemountet ist, es gibt kein Zurücksetzen pro Ansicht. (reset() existiert nur als Notausstieg für Sonderfälle bei Nicht-React-Routing; das SDK ruft es niemals automatisch auf.)
scoping.ts 1// the panel auto-scopes to keys RENDERED on the current2// view, via the global key registry the @sonenta/*-i18n3// SDK produces, no config needed:4feedbackPlugin({ controllerRef: feedback }); // auto-scoped 6// explicit keys = FALLBACK only (e.g. strings not from7// @sonenta/*-i18n). NEVER pass your whole catalogue.8feedbackPlugin({ keys: ["common:checkout.cta"] }); 6. Namespace-Filter (optional)
Ein Bildschirm, der mehrere Namespaces rendert, kann das Panel auf den eingrenzen, der den Kunden interessiert, übergeben Sie einen optionalen namespace (string | string[]) am Trigger/an der Konfiguration (feedbackPlugin() für React/Native, createFeedback() für Vue/Svelte, resolveKeys() / filterByNamespace() für /core). Er wird nach der Eingrenzung auf angezeigte Schlüssel zusammengesetzt, angezeigt = angezeigt ∩ namespace. Nicht gesetzt, "" oder [] = kein Filter (wie zuvor). Er fällt niemals auf das gesamte Projekt zurück.
namespace.ts 1// §0d, OPTIONAL namespace filter (customer feature).2// Composes AFTER rendered-scoping: shown = rendered ∩ namespace.3feedbackPlugin({ controllerRef: feedback, namespace: "quiz" }); 5// Vue / Svelte, same option on createFeedback:6createFeedback({ apiBase, projectId, language, namespace: ["quiz"] }); 8// /core, resolveKeys / filterByNamespace:9resolveKeys(explicit, "quiz"); // or filterByNamespace(keys, "quiz") 11// unset / "" / [] ⇒ no filter (identical to v5). 7. Serverseitig erstellte Sitzung (alle Frameworks)
Der Sitzungs-/Gruppierungsschlüssel wird serverseitig erstellt bei der Einwilligung. Der Client sendet oder generiert ihn niemals, es gibt keine groupingKey-Konfiguration und kein Request-Feld. Bei acceptTos() gibt das Backend ihn zurück (gebunden an das eingeschränkte JWT); jeder Adapter stellt ihn schreibgeschützt über client.sessionId bereit. Ein wiederkehrender endUserId behält seinen stabilen Server-Wert; ein neuer Endnutzer erhält ein frisches sess_….
consent.ts 1// session/grouping key is MINTED SERVER-SIDE at consent2await client.acceptTos(); // POST /v1/feedback/tos3client.sessionId; // read-only, e.g. "sess_018f…" 5// NO groupingKey config, NO request field, 6// the client never sends or self-generates the session. 8. Einwilligung und Sicherheit
Eine versionierte Sonenta-Endnutzer-ToS ist dem ersten Schreibvorgang vorgeschaltet. In den React- und React-Native-Panels wird der ToS-Schritt vor jedem authentifizierten Aufruf gerendert, und der Tap des Endnutzers selbst ruft acceptTos() auf: Das Laden der Strings ist konstruktionsbedingt an die Einwilligung gekoppelt. Wenn Sie stattdessen /core verwenden, erzeugen Sie den Client mit autoAcceptTos: false und rufen acceptTos() erst auf, wenn Ihr Nutzer zugestimmt hat, sonst akzeptiert der erste authentifizierte Aufruf an seiner Stelle. Der Client hält danach ein kurzlebiges JWT, das ausschließlich auf feedback:write begrenzt und kryptografisch von Ihrer Kunden-Auth getrennt ist, und rotiert es transparent. Endnutzer sind anonym (opake ID, keine PII). Bei @sonenta/feedback 1.2.x und früher ist dies das STANDARDVERHALTEN: Der Client akzeptiert beim ersten authentifizierten Aufruf, sofern Sie nicht autoAcceptTos: false übergeben. Version 1.3.0 dreht diesen Standard um und schlägt sicher fehl: Sie wirft FeedbackError("not consented"), statt für Ihren Nutzer zu akzeptieren.
Was Sie kostenlos erhalten
- Null Host-Re-Render. React/Native laufen als isoliertes Geschwister-Blatt des i18n-Providers; Vue/Svelte halten den Open-State in ihrem eigenen Store. Das Hinzufügen oder Öffnen von Feedback re-rendert Ihre App niemals.
- Einwilligung + Server-Sitzung übernommen. AGB-Akzeptanz, serverseitig erstellte Sitzung, JWT-Erwerb, rotierende Erneuerung und ein einmaliger transparenter Retry bei 401, alles innerhalb des SDK. Es wirft niemals eine Exception in Ihren Render-Pfad.
- Debounce-ter, gebündelter Transport. Bewertungen und Vorschläge werden eingereiht und auf einem Debounce (standardmäßig 1,5 s), bei einer maximalen Batch-Größe oder beim Schließen gesendet. Best-Effort: ein fehlgeschlagener Batch wird einmal erneut eingereiht und dann verworfen.
- Moderation vor der Veröffentlichung. Nichts, was ein Endnutzer einreicht, geht automatisch live. Vorschläge landen als
pendingin der Moderationswarteschlange Ihres Dashboards, Sie genehmigen, lehnen ab oder wenden sie über den normalen auditierten Bearbeitungspfad an. Bewertungen werden in einem Echtzeit-Dashboard pro Schlüssel / pro Sprache aggregiert.