Hoppa till innehållet
Sonenta

SDK · Utvärdering av slutanvändare

Förhandsversion

@sonenta/feedback

Låt dina egna slutanvändare betygsätta (5★) och föreslå översättningar direkt inifrån appen du har publicerat. React och React Native kopplas in i den @sonenta/*-i18n-provider du redan kör (ingen andra kontext, ingen omrendering av värden); allt annat går via /core, den frysta klienten som varje bindning omsluter. Samma protokoll, samma serverskapade session, samma moderationsbackoffice. Tillgängligt som betalt tillägg från Pro.

Paketet @sonenta/feedback levereras med tillägget för slutanvändarutvärdering av översättningar vid Sonenta V1-lanseringen. Wire-kontraktet är fryst (v3); framework-bindningarna stabiliseras fortfarande och kan ä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
controllerRefRef<Controller>,
onReady(c) => void,
keysstring[]auto-discovered
flushDebounceMsnumber1500
maxBatchnumber20
defaultButtonbooleanfalse

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. 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.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. 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"] });

6. 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).

7. 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.

8. Samtycke och säkerhet

Ett versionerat slutanvändaravtal från Sonenta ligger före den första skrivningen. I React- och React Native-panelerna visas samtyckessteget före varje autentiserat anrop, och det är slutanvändarens egen tryckning som anropar acceptTos(): hämtningen av strängarna är kopplad till samtycke redan i konstruktionen. Om du i stället använder /core, skapa klienten med autoAcceptTos: false och anropa acceptTos() först när din användare har samtyckt, annars samtycker det första autentiserade anropet i deras ställe. Klienten håller sedan en kortlivad JWT som är begränsad enbart till feedback:write, kryptografiskt skild från din egen kundautentisering, och roterar den transparent. Slutanvändare är anonyma (ogenomskinligt id, inga personuppgifter). I @sonenta/feedback 1.2.x och tidigare är detta STANDARDBETEENDET: klienten samtycker vid det första autentiserade anropet om du inte skickar autoAcceptTos: false. Version 1.3.0 vänder på standardvärdet och misslyckas säkert, genom att kasta FeedbackError("not consented") i stället för att samtycka åt din användare.

Vad du får utan ansträngning

Härnäst