Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.6.3
0.6.4
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@respondkit/api",
"version": "0.6.3",
"version": "0.6.4",
"private": true,
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion apps/native-example/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@respondkit/native-example",
"version": "0.6.3",
"version": "0.6.4",
"private": true,
"scripts": {
"start": "react-native start",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@respondkit/web",
"version": "0.6.3",
"version": "0.6.4",
"private": true,
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion apps/widget/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@respondkit/widget-playground",
"version": "0.6.3",
"version": "0.6.4",
"private": true,
"type": "module",
"scripts": {
Expand Down
27 changes: 27 additions & 0 deletions docs/releases/0.6.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# RespondKit 0.6.4

Status: prepared, not published. A merged PR does not publish SDK artifacts.

## Release notes

Every string RespondKit shows comes from the translated catalog. 0.6.3 translated the empty state, the "Ask us anything" subtitle and the attach menu; the email ask, composer, delivery statuses, retry and error states, and accessibility labels stayed English. They now follow the user's language on iOS, Android, web and React Native, with the 0.6.3 fallbacks.

- **Native views.** SwiftUI looks every string up in RespondKitUI's bundle instead of the host's main bundle. Compose reads string resources and formats transcript dates in the activity locale.
- **Store text.** The body of an attachment-only message, the length and closed-conversation errors, and the logout, history-save and unverified-identity errors come from the catalog through the new `RespondKitStrings` on the Swift and Kotlin stores. `RespondKitScreen` sets it, and a store used without a screen keeps English.
- **Ten new keys** in all 51 locales: `respondkit_message_too_long`, `respondkit_message_limit`, `respondkit_closed_start_new`, `respondkit_logout_failed`, `respondkit_history_save_failed`, `respondkit_done`, `respondkit_unread_reply`, `respondkit_reconnecting`, `respondkit_conversation_label`, `respondkit_identity_unverified`.
- **Errors.** Network, HTTP, protocol and storage failures show catalog text ("Support request failed.", "Upload failed", "Support chat could not be started.") instead of the SDK's English diagnostics or server messages. The Swift, Kotlin and React Native stores keep the original text in a new `errorDetail`.
- **Default title.** When the host passes no title, iOS, web and React Native show the translated "Support", as Compose already did.
- **Guard.** `pnpm ready` fails if any file in the SwiftUI or Compose module gains an English literal, including lowercase labels, interpolated labels and transcript helpers. Exception messages are exempt, because they are no longer shown.

## Upgrade and compatibility

Use `0.6.4` for the npm packages, `v0.6.4` for SwiftPM and `0.6.4` for Maven. No protocol change.

- Swift: `RespondKitScreen(title:)` is now `String?` (default `nil`, meaning the catalog's "Support"); existing calls compile unchanged.
- `errorMessage` (native) and `error` (React Native) no longer carry raw diagnostics; read `errorDetail` for logging.
- An attachment-only message is sent with the translated "Attached files" body, so operators see it in the customer's language.

## Operator checklist

1. Publish GitHub release `v0.6.4`, which runs the npm publish workflow. Publish Maven Central per `docs/native/releases.md`.
2. Point ReceiptGenie at 0.6.4.
28 changes: 28 additions & 0 deletions docs/worklog/RK-5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RK-5 — SDK 0.6.4: every SDK string from the catalog

2026-10-16 · developer

The views converted in 0.6.3 read the catalog; the rest of each client still had English literals. On iOS, `Text("Save email")` and similar calls looked the string up in the host app's main bundle, so they fell back to English. All four clients now read every user-visible string and accessibility label from the generated catalog. Ten keys were added to all 51 locales. Release 0.6.4 is prepared, not published.

## Decisions

- The native stores write text themselves (the attachment-only body and some errors). Each core gets a `RespondKitStrings` value that defaults to English, and the screen fills it from the catalog. Core keeps no dependency on UI resources.
- Protocol-integrity errors ("Mismatched support messages.") and server-provided messages stay as they are. They are diagnostics, not copy.
- `EncryptedFilePersistence`'s two storage errors stay English. They are not view code, and they surface only when the device's keystore fails.
- The guard (`scripts/native-strings.test.mjs`) flags capitalized English literals in files that import SwiftUI or Compose. The only allowed literal is `you@example.com`.

## Verification

- `swift test`: 28 passed. `xcodebuild -scheme RespondKitUI` for the iOS simulator: succeeded.
- Example-app XCUITest `testScreenAndAttachMenuFollowTheAppLanguage` on an iPhone 17 simulator with `demo_server.py`: passed in ja and zh-Hans. It checks the email ask, placeholder, send and close labels, and "Sent" after a real send. The demo server now answers `GET /v1/client/contact` so the email ask shows.
- `gradlew :core:test :compose:assembleDebug :example:assembleDebug`: passed, 25 core tests. `:compose:connectedDebugAndroidTest` on emulator-5554 (API 36): 9/9, including ja and zh-Hans.
- Web 89 tests, React Native 24, `vp check`, `localization:check` and `test:native-strings`: passed.

Translations of the new keys were written by the agent. No native-speaker review yet.

## Review RK-6 (changes requested at 71a3e48)

- SDK-authored errors reached the UI in English: Android's "File upload failed (500). Try again." and React Native's "Unable to reach RespondKit". Stores and pickers now show catalog text for any error they did not write in the user's language. Errors the SDK localizes itself are thrown as `PresentedError` / `PresentedException`. The raw message stays in `errorDetail` (Swift, Kotlin and React Native stores).
- The new ja/zh-Hans Android test of a failed request found a first-open race: `openConversation` ran before the screen's `SideEffect` handed the store its strings, so the banner was English. The screen now sets the strings at the start of its `LaunchedEffect`, and `RespondKitLifecycle` sets them on both platforms before any background refresh.
- The guard now scans every file in both UI modules, including the transcript helpers. It flags any literal in a UI-call position (so `Text("retry")` and `Button("OK")` fail), English phrases, and interpolated labels. Fixtures cover each case. Restoring 0.6.3's TranscriptRow on either platform now fails it.
- Verification: `pnpm ready` passed (455 package tests). `swift test`: 29 passed. RespondKitUI iOS build: succeeded. Android core tests: 26 passed. `:compose:connectedDebugAndroidTest` on emulator-5554: 11/11 passed.
2 changes: 1 addition & 1 deletion localization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pnpm localization:check

The generator writes `native/swift/Sources/RespondKitUI/Resources/RespondKit.xcstrings` (the SwiftPM resource of `RespondKitUI`) `generated/android/res/values*/strings.xml` (a resource directory of the Compose module), and one TypeScript module copied to `packages/react/src/widget/messages.ts` and `packages/react-native/src/messages.ts`. Commit the outputs with the JSON changes. `pnpm ready` fails if an output is missing, modified, or left behind after removing a locale. Generated files belong to this pipeline; edits in Xcode or Android Studio must be made in JSON instead. No translation services run during compilation.

Every client reads the empty state, the "Ask us anything" subtitle and the attach menu from the generated output, and Compose also reads its closed-conversation strings from it. Other views still use English literals. The catalog ships ReceiptGenie's 51 app locales plus English. Adding a language means adding it to `settings.json` with a complete `messages/{locale}.json`.
Every user-visible string and accessibility label in the SwiftUI, Compose, web and React Native views comes from the generated output. The native stores write a few strings themselves (the body of an attachment-only message and some errors); the screens hand them `RespondKitStrings` from the catalog, and a store used without a screen keeps English. Errors the SDK did not write in the user's language (network, HTTP, protocol, storage and server messages) are shown as a catalog fallback such as `respondkit_request_failed` or `respondkit_upload_failed`; the stores keep the original text in `errorDetail`. `pnpm test:native-strings` fails when a file in the SwiftUI or Compose module gains an English literal outside an exception message. The catalog ships ReceiptGenie's 51 app locales plus English. Adding a language means adding it to `settings.json` with a complete `messages/{locale}.json`.

Locale selection per client:

Expand Down
10 changes: 10 additions & 0 deletions localization/generated/android/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
<string name="respondkit_close_chat" formatted="false">"إغلاق دردشة الدعم"</string>
<string name="respondkit_closed" formatted="false">"مغلقة"</string>
<string name="respondkit_closed_help" formatted="false">"تم إغلاق هذه المحادثة."</string>
<string name="respondkit_closed_start_new" formatted="false">"هذه المحادثة مغلقة. ابدأ محادثة جديدة."</string>
<string name="respondkit_confirming" formatted="false">"جارٍ التأكيد…"</string>
<string name="respondkit_connecting" formatted="false">"لا يزال الدعم قيد الاتصال."</string>
<string name="respondkit_conversation">"محادثة %1$s"</string>
<string name="respondkit_conversation_label" formatted="false">"المحادثة"</string>
<string name="respondkit_conversations" formatted="false">"المحادثات"</string>
<plurals name="respondkit_conversations_unread">
<item quantity="zero">"المحادثات · %1$d غير مقروءة"</item>
Expand All @@ -22,6 +24,7 @@
<item quantity="many">"المحادثات · %1$d غير مقروءة"</item>
<item quantity="other">"المحادثات · %1$d غير مقروءة"</item>
</plurals>
<string name="respondkit_done" formatted="false">"تم"</string>
<string name="respondkit_email_address" formatted="false">"عنوان البريد الإلكتروني"</string>
<string name="respondkit_email_failed" formatted="false">"تعذّر حفظ بريدك الإلكتروني. يُرجى التحقق منه والمحاولة مرة أخرى."</string>
<string name="respondkit_email_prompt" formatted="false">"على أي بريد إلكتروني نرسل إليك الرد؟"</string>
Expand All @@ -30,13 +33,18 @@
<string name="respondkit_files" formatted="false">"الملفات"</string>
<string name="respondkit_help" formatted="false">"كيف يمكننا مساعدتك؟"</string>
<string name="respondkit_history_failed" formatted="false">"تعذّر تحميل سجل المحادثة. اضغط على «المزيد» للمحاولة مرة أخرى."</string>
<string name="respondkit_history_save_failed" formatted="false">"تعذّر حفظ سجل الدعم."</string>
<string name="respondkit_identity_changed" formatted="false">"تغيّرت هوية الدعم في علامة تبويب أخرى. أعد الاتصال لإعادة تحميل حسابك."</string>
<string name="respondkit_identity_unverified" formatted="false">"تعذّر التحقق من هوية الدعم."</string>
<string name="respondkit_intro" formatted="false">"أرسل رسالة وأبقِ هذه الصفحة مفتوحة لتلقي رد سريع."</string>
<string name="respondkit_intro_short" formatted="false">"أرسل رسالة لبدء محادثة."</string>
<string name="respondkit_latest" formatted="false">"أحدث الرسائل"</string>
<string name="respondkit_loading" formatted="false">"جارٍ التحميل…"</string>
<string name="respondkit_loading_messages" formatted="false">"جارٍ تحميل الرسائل"</string>
<string name="respondkit_logout_failed" formatted="false">"تعذّر إلغاء جلسة الدعم السابقة. ستنتهي صلاحيتها تلقائيًا."</string>
<string name="respondkit_message" formatted="false">"الرسالة"</string>
<string name="respondkit_message_limit" formatted="false">"يمكن أن تحتوي الرسائل على 6000 حرف كحد أقصى."</string>
<string name="respondkit_message_too_long" formatted="false">"أدخل رسالة لا تتجاوز 6000 حرف."</string>
<string name="respondkit_messages_failed" formatted="false">"تعذّر تحميل الرسائل الجديدة."</string>
<string name="respondkit_more" formatted="false">"المزيد"</string>
<string name="respondkit_new_conversation" formatted="false">"محادثة جديدة"</string>
Expand All @@ -55,6 +63,7 @@
<string name="respondkit_ready" formatted="false">"جاهز"</string>
<string name="respondkit_reconnect" formatted="false">"إعادة الاتصال"</string>
<string name="respondkit_reconnect_upload" formatted="false">"أعد الاتصال قبل الرفع."</string>
<string name="respondkit_reconnecting" formatted="false">"جارٍ إعادة الاتصال. لا تزال رسائلك الحالية متاحة."</string>
<string name="respondkit_remove" formatted="false">"إزالة"</string>
<string name="respondkit_remove_file">"إزالة %1$s"</string>
<string name="respondkit_request_failed" formatted="false">"فشل طلب الدعم."</string>
Expand Down Expand Up @@ -84,6 +93,7 @@
<string name="respondkit_try_again" formatted="false">"حاول مرة أخرى"</string>
<string name="respondkit_unknown" formatted="false">"لم يتم التأكيد — يمكنك إعادة المحاولة بأمان"</string>
<string name="respondkit_unread" formatted="false">"رد غير مقروء من الدعم"</string>
<string name="respondkit_unread_reply" formatted="false">"رد غير مقروء"</string>
<string name="respondkit_upload_failed" formatted="false">"فشل الرفع"</string>
<string name="respondkit_write_message" formatted="false">"اكتب رسالة…"</string>
</resources>
10 changes: 10 additions & 0 deletions localization/generated/android/res/values-b+fr+CA/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@
<string name="respondkit_close_chat" formatted="false">"Fermer le clavardage avec le soutien"</string>
<string name="respondkit_closed" formatted="false">"Fermée"</string>
<string name="respondkit_closed_help" formatted="false">"Cette conversation est fermée."</string>
<string name="respondkit_closed_start_new" formatted="false">"Cette conversation est fermée. Commencez une nouvelle conversation."</string>
<string name="respondkit_confirming" formatted="false">"Confirmation en cours…"</string>
<string name="respondkit_connecting" formatted="false">"Connexion au soutien en cours."</string>
<string name="respondkit_conversation">"Conversation du %1$s"</string>
<string name="respondkit_conversation_label" formatted="false">"Conversation"</string>
<string name="respondkit_conversations" formatted="false">"Conversations"</string>
<plurals name="respondkit_conversations_unread">
<item quantity="one">"Conversations · %1$d non lue"</item>
<item quantity="many">"Conversations · %1$d non lues"</item>
<item quantity="other">"Conversations · %1$d non lues"</item>
</plurals>
<string name="respondkit_done" formatted="false">"OK"</string>
<string name="respondkit_email_address" formatted="false">"Adresse courriel"</string>
<string name="respondkit_email_failed" formatted="false">"Impossible d’enregistrer votre adresse courriel. Vérifiez-la et réessayez."</string>
<string name="respondkit_email_prompt" formatted="false">"À quelle adresse courriel pouvons-nous vous répondre?"</string>
Expand All @@ -27,13 +30,18 @@
<string name="respondkit_files" formatted="false">"Fichiers"</string>
<string name="respondkit_help" formatted="false">"Comment pouvons-nous vous aider?"</string>
<string name="respondkit_history_failed" formatted="false">"Impossible de charger l’historique de la conversation. Réessayez avec « Afficher plus »."</string>
<string name="respondkit_history_save_failed" formatted="false">"Impossible d\'enregistrer l\'historique de soutien."</string>
<string name="respondkit_identity_changed" formatted="false">"Le compte de soutien a changé dans un autre onglet. Reconnectez-vous pour recharger votre compte."</string>
<string name="respondkit_identity_unverified" formatted="false">"Impossible de vérifier l\'identité de soutien."</string>
<string name="respondkit_intro" formatted="false">"Envoyez-nous un message et gardez cette page ouverte pour obtenir une réponse rapide."</string>
<string name="respondkit_intro_short" formatted="false">"Envoyez un message pour démarrer une conversation."</string>
<string name="respondkit_latest" formatted="false">"Derniers messages"</string>
<string name="respondkit_loading" formatted="false">"Chargement…"</string>
<string name="respondkit_loading_messages" formatted="false">"Chargement des messages"</string>
<string name="respondkit_logout_failed" formatted="false">"La session de soutien précédente n\'a pas pu être révoquée. Elle expirera automatiquement."</string>
<string name="respondkit_message" formatted="false">"Message"</string>
<string name="respondkit_message_limit" formatted="false">"Les messages peuvent contenir jusqu\'à 6 000 caractères."</string>
<string name="respondkit_message_too_long" formatted="false">"Saisissez un message de 6 000 caractères maximum."</string>
<string name="respondkit_messages_failed" formatted="false">"Impossible de charger les nouveaux messages."</string>
<string name="respondkit_more" formatted="false">"Afficher plus"</string>
<string name="respondkit_new_conversation" formatted="false">"Nouvelle conversation"</string>
Expand All @@ -49,6 +57,7 @@
<string name="respondkit_ready" formatted="false">"Prêt"</string>
<string name="respondkit_reconnect" formatted="false">"Se reconnecter"</string>
<string name="respondkit_reconnect_upload" formatted="false">"Reconnectez-vous avant de téléverser des fichiers."</string>
<string name="respondkit_reconnecting" formatted="false">"Reconnexion en cours. Vos messages existants restent disponibles."</string>
<string name="respondkit_remove" formatted="false">"Retirer"</string>
<string name="respondkit_remove_file">"Retirer %1$s"</string>
<string name="respondkit_request_failed" formatted="false">"La demande de soutien a échoué."</string>
Expand All @@ -75,6 +84,7 @@
<string name="respondkit_try_again" formatted="false">"Réessayer"</string>
<string name="respondkit_unknown" formatted="false">"Non confirmé — vous pouvez réessayer sans risque"</string>
<string name="respondkit_unread" formatted="false">"Réponse non lue du soutien"</string>
<string name="respondkit_unread_reply" formatted="false">"Réponse non lue"</string>
<string name="respondkit_upload_failed" formatted="false">"Échec du téléversement"</string>
<string name="respondkit_write_message" formatted="false">"Écrivez un message…"</string>
</resources>
Loading
Loading