Przejdź do treści
Sonenta

SDK · Ocena przez użytkownika końcowego

Wersja zapowiadająca

@sonenta/feedback

Pozwól swoim użytkownikom końcowym oceniać (5★) i proponować tłumaczenia z wnętrza wdrożonej aplikacji. React i React Native podpinają się pod provider @sonenta/*-i18n, którego już używasz (bez drugiego kontekstu, bez re-renderu hosta); cała reszta idzie przez /core, zamrożony klient opakowywany przez każdy binding. Ta sama sieć, ta sama sesja tworzona po stronie serwera, to samo zaplecze moderacji. Dostępne jako płatny dodatek od planu Pro.

Pakiet @sonenta/feedback jest dostarczany wraz z dodatkiem do oceny tłumaczeń przez użytkowników końcowych w chwili startu Sonenta V1. Kontrakt sieciowy jest zamrożony (v3); bindingi frameworków wciąż się stabilizują i mogą się zmienić przed startem.

1. Instalacja (przy starcie)

Jeden pakiet. Zaimportuj punkt wejścia swojego frameworka: @sonenta/feedback/react, /native (RN/Expo), /vue, /svelte lub /core dla wszystkiego innego. vue / svelte to opcjonalne peer deps, potrzebuje ich tylko odpowiedni punkt wejścia. Publikowany wraz z dodatkiem przy starcie V1.

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), plugin i18n

Dodaj feedbackPlugin() do slotu plugins w istniejącym providerze @sonenta/react-i18next (>= 0.7.0), bez nowego providera, bez drugiego kontekstu. Provider wywołuje setup() pluginu raz i wykorzystuje ponownie własne apiBase / projectId / defaultLocale. Panel montuje się jako izolowany liść siostrzany z prywatnym storem otwarcia/zamknięcia, więc jego otwarcie nigdy nie renderuje ponownie Twojego drzewa hosta. Wyzwalaj z własnego CTA za pomocą kontrolera dostarczanego przez controllerRef (lub callbacka 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>
Wszystkie opcje feedbackPlugin() / createFeedback()
Opcja Typ Domyślnie
controllerRefRef<Controller>,
onReady(c) => void,
keysstring[]auto-discovered
flushDebounceMsnumber1500
maxBatchnumber20
defaultButtonbooleanfalse

3. React Native / Expo

Identyczny wzorzec z punktu wejścia /native: dodaj feedbackPlugin() do slotu plugins tego samego providera @sonenta/react-i18next w swojej aplikacji Expo i wyzwalaj przez kontroler. Bez dodatkowych modułów natywnych; przechowywanie tokenu korzysta z secure store platformy.

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. Wszystko inne, /core

@sonenta/feedback/core udostępnia zamrożony FeedbackClient, na którym zbudowane są wszystkie adaptery: acceptTos(), loadStrings(), rate(), suggest(), transport z debouncingiem i batchowaniem, rotujący JWT. Używaj go bezpośrednio dla dowolnego frameworka bez adaptera first-party.

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. Ograniczanie do wyświetlanych kluczy (automatyczne)

Panel automatycznie ogranicza się do kluczy faktycznie wyświetlanych w bieżącym widoku, dzięki globalnemu rejestrowi kluczy tworzonemu przez SDK @sonenta/*-i18n, bez konfiguracji. Jawną tablicę keys przekazuj tylko jako rozwiązanie awaryjne (np. teksty niepochodzące z @sonenta/*-i18n); nigdy nie przekazuj całego katalogu, ujawniłoby to każdy tekst w aplikacji, a nie te, na które patrzy użytkownik. Rejestr jest śledzony przy montowaniu i liczony przez referencje: trwałe teksty stale obecne na ekranie (nagłówek, eyebrow) pozostają zarejestrowane, dopóki ich komponent jest zamontowany, nie ma resetu na widok. (reset() istnieje wyłącznie jako furtka awaryjna dla brzegowych przypadków routingu spoza React; SDK nigdy nie wywołuje go automatycznie.)

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. Filtr namespace (opcjonalny)

Ekran renderujący wiele namespace'ów może ograniczyć panel tylko do tego, na którym zależy klientowi, przekaż opcjonalny namespace (string | string[]) na triggerze/konfiguracji (feedbackPlugin() dla React/Native, createFeedback() dla Vue/Svelte, resolveKeys() / filterByNamespace() dla /core). Składa się po ograniczeniu do wyświetlanych kluczy, pokazane = wyświetlone ∩ namespace. Brak wartości, "" lub [] oznacza brak filtra (identycznie jak wcześniej). Nigdy nie wraca do całego projektu.

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. Sesja generowana po stronie serwera (wszystkie frameworki)

Klucz sesji / grupowania jest generowany po stronie serwera w momencie wyrażenia zgody. Klient nigdy go nie wysyła ani nie generuje samodzielnie, nie ma konfiguracji groupingKey ani pola żądania. Przy acceptTos() backend go zwraca (powiązany z ograniczonym JWT); każdy adapter udostępnia go w trybie tylko do odczytu jako client.sessionId. Powracający endUserId zachowuje swoją stabilną wartość serwerową; nowy użytkownik otrzymuje świeży 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. Zgoda i bezpieczeństwo

Wersjonowany regulamin dla użytkownika końcowego Sonenta poprzedza pierwszy zapis. W panelach React i React Native krok z regulaminem pojawia się przed jakimkolwiek uwierzytelnionym wywołaniem, a to dotknięcie samego użytkownika końcowego wywołuje acceptTos(): pobranie ciągów jest z założenia uzależnione od zgody. Jeśli korzystasz z /core, twórz klienta z autoAcceptTos: false i wywołuj acceptTos() dopiero po zgodzie użytkownika, w przeciwnym razie pierwsze uwierzytelnione wywołanie zaakceptuje regulamin za niego. Klient przechowuje następnie krótkotrwały token JWT ograniczony wyłącznie do zakresu feedback:write, kryptograficznie oddzielony od uwierzytelniania Twoich klientów, i odnawia go w sposób przezroczysty. Użytkownicy końcowi są anonimowi (nieprzejrzyste id, brak danych osobowych). W @sonenta/feedback 1.2.x i wcześniejszych jest to zachowanie DOMYŚLNE: klient akceptuje przy pierwszym uwierzytelnionym wywołaniu, chyba że przekażesz autoAcceptTos: false. Wersja 1.3.0 odwraca to ustawienie i zawodzi bezpiecznie, rzucając FeedbackError("not consented") zamiast akceptować za Twojego użytkownika.

Co dostajesz za darmo

Dalej