Перейти к содержимому
Sonenta

SDK · Оценка конечным пользователем

Превью

@sonenta/feedback

Позвольте вашим конечным пользователям оценивать (5★) и предлагать переводы прямо из вашего приложения. React и React Native подключаются к провайдеру @sonenta/*-i18n, который у вас уже работает (без второго контекста, без ре-рендера хоста); всё остальное идёт через /core, замороженный клиент, который оборачивает каждый биндинг. Тот же протокол, та же сессия, созданная на сервере, тот же бэк-офис модерации. Доступно как платное дополнение начиная с Pro.

Пакет @sonenta/feedback поставляется с дополнением для оценки переводов конечными пользователями на запуске Sonenta V1. Сетевой контракт заморожен (v3); биндинги для фреймворков ещё стабилизируются и могут измениться до запуска.

1. Установка (при запуске)

Один пакет. Импортируйте точку входа вашего фреймворка: @sonenta/feedback/react, /native (RN/Expo), /vue, /svelte или /core для всего остального. vue / svelte, это опциональные peer-зависимости; они нужны только соответствующей точке входа. Публикуется вместе с дополнением при запуске 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), плагин i18n

Добавьте feedbackPlugin() в слот plugins вашего существующего провайдера @sonenta/react-i18next (>= 0.7.0), никакого нового провайдера, никакого второго контекста. Провайдер вызывает setup() плагина один раз и переиспользует свои apiBase / projectId / defaultLocale. Панель монтируется как изолированный соседний лист с приватным хранилищем открытия/закрытия: её открытие никогда не вызывает ре-рендер вашего хост-дерева. Запускайте из своего собственного CTA через контроллер, предоставленный через controllerRef (или коллбэк 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>
Все опции feedbackPlugin() / createFeedback()
Опция Тип По умолчанию
controllerRefRef<Controller>,
onReady(c) => void,
keysstring[]auto-discovered
flushDebounceMsnumber1500
maxBatchnumber20
defaultButtonbooleanfalse

3. React Native / Expo

Та же схема из точки входа /native: добавьте feedbackPlugin() в слот plugins того же провайдера @sonenta/react-i18next в вашем приложении Expo и запускайте через контроллер. Никаких дополнительных нативных модулей; хранение токена использует защищённое хранилище платформы.

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. Всё остальное, /core

@sonenta/feedback/core предоставляет зафиксированный FeedbackClient, на котором построены все адаптеры: acceptTos(), loadStrings(), rate(), suggest(), транспорт с дебаунсом и батчингом, ротируемый JWT. Используйте его напрямую для любого фреймворка без 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. Привязка к отображаемым ключам (автоматически)

Панель автоматически ограничивается ключами, фактически отображёнными в текущем представлении, через глобальный реестр ключей, который формирует SDK @sonenta/*-i18n, без настройки. Передавайте явный массив keys только как запасной вариант (например, строки не из @sonenta/*-i18n); никогда не передавайте весь ваш каталог, это раскрыло бы все строки приложения, а не те, на которые смотрит пользователь. Реестр отслеживается по монтированию и считается по ссылкам: постоянно присутствующие на экране строки (заголовок, eyebrow) остаются зарегистрированными, пока их компонент смонтирован, никакого сброса на каждое представление. (reset() существует только как аварийный выход для краевых случаев маршрутизации вне React; SDK никогда не вызывает его автоматически.)

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 (опционально)

Экран, который рендерит несколько namespace, может ограничить панель именно тем, который интересует клиента, передайте опциональный namespace (string | string[]) в триггер/конфигурацию (feedbackPlugin() для React/Native, createFeedback() для Vue/Svelte, resolveKeys() / filterByNamespace() для /core). Он применяется после привязки к отображаемым ключам, показано = отображённое ∩ namespace. Не задано, "" или [] = без фильтра (как раньше). Он никогда не откатывается на весь проект.

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. Сессия, выпущенная на сервере (все фреймворки)

Ключ сессии / группировки выпускается на стороне сервера при согласии. Клиент никогда не отправляет и не генерирует его сам, нет конфигурации groupingKey и нет поля запроса. При acceptTos() бэкенд возвращает его (привязанным к ограниченному JWT); каждый адаптер предоставляет его только для чтения через client.sessionId. Возвращающийся endUserId сохраняет своё стабильное серверное значение; новый пользователь получает свежий 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. Согласие и безопасность

Версионированные пользовательские условия Sonenta предшествуют первой записи. В панелях React и React Native шаг с условиями отображается до любого аутентифицированного вызова, и именно нажатие самого конечного пользователя вызывает acceptTos(): загрузка строк по построению привязана к согласию. Если вы используете /core, создавайте клиент с autoAcceptTos: false и вызывайте acceptTos() только после согласия вашего пользователя, иначе первый аутентифицированный вызов примет условия за него. Затем клиент удерживает краткоживущий JWT, ограниченный только областью feedback:write, криптографически отделённый от аутентификации ваших клиентов, и прозрачно его обновляет. Конечные пользователи анонимны (непрозрачный id, без персональных данных). В @sonenta/feedback 1.2.x и ранее это поведение ПО УМОЛЧАНИЮ: клиент принимает условия при первом аутентифицированном вызове, если вы не передали autoAcceptTos: false. Версия 1.3.0 меняет умолчание и завершается безопасно, выбрасывая FeedbackError("not consented") вместо принятия за вашего пользователя.

Что вы получаете бесплатно

Далее