SDK · Utvärdering av slutanvändare
Förhandsversion@sonenta/feedback
Låt dina egna slutanvändare betygsätta (5★) och föreslå översättningar inifrån din publicerade app. Ett paket, fem ingångspunkter — /react, /native, /vue, /svelte, /core — samma wire, samma serversidigt skapade session, samma back office för moderering. React & React Native kopplas in i den @sonenta/*-i18n-provider du redan kör (ingen andra kontext, ingen omrendering av värden); Vue & Svelte är idiomatiska fristående adaptrar. Tillgängligt som ett betaltillägg från Pro och uppåt.
Paketet @sonenta/feedback levereras med tillägget ”Slutanvändarutvärdering av översättningar” vid Sonentas V1-lansering. Det finns ännu inte på npm — wire-kontraktet är fryst (v3); ramverksbindningarna stabiliseras och kan fortfarande ändras före lanseringen.
1. Installera (vid lansering)
Ett enda paket. Importera ingångspunkten för ditt ramverk: @sonenta/feedback/react, /native (RN/Expo), /vue, /svelte, eller /core för allt annat. vue / svelte är valfria peer deps — bara den matchande ingångspunkten behöver dem. Publiceras med tillägget vid V1-lanseringen.
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 (webb) — i18n-plugin
Lägg till feedbackPlugin() i plugins-platsen i din befintliga @sonenta/react-i18next (>= 0.7.0)-provider — ingen ny provider, ingen andra kontext. Providern anropar pluginens setup() en gång och återanvänder sina egna apiBase / projectId / defaultLocale. Panelen monteras som ett isolerat syskonblad med en privat öppen/stäng-store, så att öppna den omrenderar aldrig ditt värdträd. Utlös från din egen CTA via kontrollern som levereras genom controllerRef (eller callbacken onReady).
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> Alla alternativ för feedbackPlugin() / createFeedback()
| Alternativ | 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
Identiskt mönster från ingångspunkten /native: lägg till feedbackPlugin() i samma @sonenta/react-i18next-providers plugins-plats i din Expo-app och utlös via kontrollern. Inga extra nativa moduler; token-lagringen använder plattformens secure store.
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. Vue
@sonenta/feedback/vue är en fristående adapter — explicit konfiguration, ingen i18n-provider att ärva från. createFeedback(config) returnerar { client, isOpen, controller, FeedbackPanel }. Montera <FeedbackPanel /> en gång nära din rot (den Teleporterar till body), och anropa controller.open() från din egen CTA. Samma isolerade öppna-tillstånd — det omrenderar aldrig din app.
App.vue 1// main.ts — standalone adapter, explicit config2import { createFeedback } from "@sonenta/feedback/vue"; 4export const { controller, FeedbackPanel } = createFeedback({5 apiBase: "https://api.sonenta.com",6 projectId: "proj_xxx", language: "fr",7}); 9// App.vue — mount once near root (Teleports to body)10<FeedbackPanel />11<button @click="controller.open()">Rate translations</button> 5. Svelte
@sonenta/feedback/svelte är headless och idiomatisk: createFeedback(config) returnerar Svelte-stores — isOpen (Writable), strings (Writable) — plus open(), close(), loadStrings(), rate(), suggest(). Du renderar din egen panel från storesen; SDK:t äger transporten, samtycket och serversessionen.
+page.svelte 1// feedback.ts — headless idiomatic stores2import { createFeedback } from "@sonenta/feedback/svelte"; 4export const fb = createFeedback({5 apiBase: "https://api.sonenta.com",6 projectId: "proj_xxx", language: "fr",7}); 9// component — render your own panel from the stores10{#if $fb.isOpen}{#each $fb.strings as s}…{/each}{/if}11<button on:click={fb.open}>Rate translations</button> 6. Allt annat — /core
@sonenta/feedback/core exponerar den frysta FeedbackClient som alla adaptrar bygger på: acceptTos(), loadStrings(), rate(), suggest(), debouncad batchad transport, roterande JWT. Använd den direkt för vilket ramverk som helst utan en förstapartsadapter.
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.com",6 projectId: "proj_xxx", language: "fr",7});8await client.acceptTos(); // server mints the session9await client.loadStrings(); client.rate(/* … */); client.suggest(/* … */); 7. Avgränsning till renderade nycklar (automatisk)
Panelen avgränsas automatiskt till de nycklar som faktiskt renderas i den aktuella vyn, via det globala nyckelregister som @sonenta/*-i18n-SDK:t producerar — ingen konfiguration. Skicka en explicit keys-array endast som en fallback (t.ex. strängar som inte kommer från @sonenta/*-i18n); skicka aldrig hela din katalog — det skulle exponera varje sträng i appen, inte de som användaren tittar på. Registret är monteringsspårat och referensräknat: beständiga strängar som alltid är på skärmen (en sidhuvud, en eyebrow) förblir registrerade så länge deras komponent är monterad — det finns ingen återställning per vy. (reset() finns endast som en nödutgång för kantfall med icke-React-routing; SDK:t anropar den aldrig automatiskt.)
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"] }); 8. Namespace-filter (valfritt)
En skärm som renderar flera namespaces kan avgränsa panelen till just det som kunden bryr sig om — skicka ett valfritt namespace (string | string[]) på triggern/konfigurationen (feedbackPlugin() för React/Native, createFeedback() för Vue/Svelte, resolveKeys() / filterByNamespace() för /core). Det kombineras efter avgränsningen till renderade nycklar — visat = renderat ∩ namespace. Odefinierat, "" eller [] betyder inget filter (identiskt med tidigare). Det faller aldrig tillbaka till hela projektet.
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). 9. Serversidigt skapad session (alla ramverk)
Session-/grupperingsnyckeln skapas på serversidan vid samtycke. Klienten skickar eller genererar den aldrig själv — det finns ingen groupingKey-konfiguration och inget begäransfält. Vid acceptTos() returnerar backend den (bunden i den scopebegränsade JWT:n); varje adapter exponerar den skrivskyddat som client.sessionId. Ett återkommande endUserId behåller sitt stabila servervärde; en ny slutanvändare får ett färskt 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. 10. Samtycke & säkerhet (automatiskt)
Före den första skrivningen accepterar slutanvändaren Sonentas versionshanterade slutanvändarvillkor. SDK:t skaffar sedan en kortlivad JWT som är begränsad till enbart scopet feedback:write — kryptografiskt åtskild från din kundautentisering — och roterar den transparent. Slutanvändare är anonyma (ogenomskinligt id, ingen PII). Du behöver inte koda något på säkerhetssidan.
Vad du får utan ansträngning
- Noll omrendering av värden. React/Native körs som ett isolerat syskonblad till i18n-providern; Vue/Svelte håller öppna-tillståndet i sin egen store. Att lägga till eller öppna feedback omrenderar aldrig din app.
- Samtycke + serversession hanteras. Acceptans av villkor, serversidigt skapad session, hämtning av JWT, roterande uppdatering och ett enda transparent återförsök vid 401 — allt inuti SDK:t. Det kastar aldrig undantag in i din renderingsväg.
- Debouncad, batchad transport. Betyg och förslag köas och skickas på en debounce (standard 1,5 s), vid en max-batch, eller vid stängning. Best-effort: en misslyckad batch köas om en gång och sväljs sedan.
- Moderering före publicering. Inget som en slutanvändare skickar in går live automatiskt. Förslag landar som
pendingi din dashboards modereringskö — du godkänner, avvisar eller tillämpar via den vanliga reviderade redigeringsvägen. Betyg sammanställs i en realtidsdashboard per nyckel / per språk.