Commit Graph
6321 Commits
Author SHA1 Message Date
Captain 8527170d82 New translations en.yml (Bengali)
[ci skip]
[ci skip]
2026-06-02 11:17:22 -07:00
Captain 044282730f New translations en.yml (Tamil)
[ci skip]
[ci skip]
2026-06-02 11:17:20 -07:00
Captain d5bf7f81cb New translations en.yml (Persian)
[ci skip]
[ci skip]
2026-06-02 11:17:18 -07:00
Captain 8b125efac2 New translations en.yml (Indonesian)
[ci skip]
[ci skip]
2026-06-02 11:17:16 -07:00
Captain 69ea2dc58d New translations en.yml (Portuguese, Brazilian)
[ci skip]
[ci skip]
2026-06-02 11:17:14 -07:00
Captain 5cc2004a71 New translations en.yml (Icelandic)
[ci skip]
[ci skip]
2026-06-02 11:17:12 -07:00
Captain 92ac1c3825 New translations en.yml (Vietnamese)
[ci skip]
[ci skip]
2026-06-02 11:17:10 -07:00
Captain bc8f528f90 New translations en.yml (Urdu (Pakistan))
[ci skip]
[ci skip]
2026-06-02 11:16:32 -07:00
Captain bef1a6047a New translations en.yml (Chinese Traditional)
[ci skip]
[ci skip]
2026-06-02 11:16:26 -07:00
Captain ab4eb0e7d7 New translations en.yml (Chinese Simplified)
[ci skip]
[ci skip]
2026-06-02 11:16:24 -07:00
Captain e5b64287ac New translations en.yml (Ukrainian)
[ci skip]
[ci skip]
2026-06-02 11:16:22 -07:00
Captain 34a480e799 New translations en.yml (Turkish)
[ci skip]
[ci skip]
2026-06-02 11:16:20 -07:00
Captain 58b067c08f New translations en.yml (Swedish)
[ci skip]
[ci skip]
2026-06-02 11:16:18 -07:00
Captain 78faf125bd New translations en.yml (Albanian)
[ci skip]
[ci skip]
2026-06-02 11:16:15 -07:00
Captain 0d9662477d New translations en.yml (Slovenian)
[ci skip]
[ci skip]
2026-06-02 11:16:13 -07:00
Captain 3e31f63f09 New translations en.yml (Slovak)
[ci skip]
[ci skip]
2026-06-02 11:16:12 -07:00
Captain b84d98b90b New translations en.yml (Russian)
[ci skip]
[ci skip]
2026-06-02 11:16:09 -07:00
Captain 3a75ec02f0 New translations en.yml (Portuguese)
[ci skip]
[ci skip]
2026-06-02 11:16:07 -07:00
Captain 9cbe749994 New translations en.yml (Polish)
[ci skip]
[ci skip]
2026-06-02 11:16:05 -07:00
Captain e9ea5cbe45 New translations en.yml (Norwegian)
[ci skip]
[ci skip]
2026-06-02 11:16:03 -07:00
Captain 665549d52d New translations en.yml (Dutch)
[ci skip]
[ci skip]
2026-06-02 11:16:01 -07:00
Captain 17db86c2fe New translations en.yml (Lithuanian)
[ci skip]
[ci skip]
2026-06-02 11:15:59 -07:00
Captain 0ace7f38a6 New translations en.yml (Korean)
[ci skip]
[ci skip]
2026-06-02 11:15:57 -07:00
Captain 4a2250065c New translations en.yml (Georgian)
[ci skip]
[ci skip]
2026-06-02 11:15:55 -07:00
Captain 31ba25b12b New translations en.yml (Japanese)
[ci skip]
[ci skip]
2026-06-02 11:15:53 -07:00
Captain bc5bd51003 New translations en.yml (Italian)
[ci skip]
[ci skip]
2026-06-02 11:15:51 -07:00
Captain 6d933112e7 New translations en.yml (Armenian)
[ci skip]
[ci skip]
2026-06-02 11:15:49 -07:00
Captain 45d7e570b7 New translations en.yml (Hungarian)
[ci skip]
[ci skip]
2026-06-02 11:15:47 -07:00
Captain bb3ad70f0e New translations en.yml (Hebrew)
[ci skip]
[ci skip]
2026-06-02 11:15:45 -07:00
Captain c983c87537 New translations en.yml (Finnish)
[ci skip]
[ci skip]
2026-06-02 11:15:42 -07:00
Captain c5def0522f New translations en.yml (Greek)
[ci skip]
[ci skip]
2026-06-02 11:15:40 -07:00
Captain b95e59ee0d New translations en.yml (German)
[ci skip]
[ci skip]
2026-06-02 11:15:38 -07:00
Captain f49d825e8b New translations en.yml (Danish)
[ci skip]
[ci skip]
2026-06-02 11:15:36 -07:00
Captain 75a82d9ab7 New translations en.yml (Czech)
[ci skip]
[ci skip]
2026-06-02 11:15:34 -07:00
Captain 0eb121df75 New translations en.yml (Catalan)
[ci skip]
[ci skip]
2026-06-02 11:15:32 -07:00
Captain 18e45a0da6 New translations en.yml (Bulgarian)
[ci skip]
[ci skip]
2026-06-02 11:15:30 -07:00
Captain df14e97ff6 New translations en.yml (Arabic)
[ci skip]
[ci skip]
2026-06-02 11:15:28 -07:00
Captain 63c9cf3ad1 New translations en.yml (Spanish)
[ci skip]
[ci skip]
2026-06-02 11:15:26 -07:00
Captain ec36442f57 New translations en.yml (French)
[ci skip]
[ci skip]
2026-06-02 11:15:24 -07:00
Captain b81c43a5a2 New translations en.yml (Romanian)
[ci skip]
[ci skip]
2026-06-02 11:15:22 -07:00
Captain 23cad33d96 New translations conversation.json (Portuguese, Brazilian)
[ci skip]
[ci skip]
2026-06-02 11:13:36 -07:00
36a05097fa fix(webhooks): strip trailing newlines from webhook message content (#14272)
The TipTap/ProseMirror editor stores agent messages with trailing
paragraph nodes that produce trailing newlines (e.g. \`\n\n\n\`) in the
\`content\` field. While Chatwoot's native channel delivery already
handles this, webhook payloads and API responses were returning raw
content with trailing whitespace — causing visible blank space below
messages in every external integration that consumes Chatwoot webhooks
(WhatsApp via Evolution API, Telegram bots, custom webhook consumers).

Closes #13459

## Root cause

\`Messages::WebhookContentNormalizer\` already strips CommonMark hard
line breaks (\`\\\` + newline) for webhook consumers, but it did not
strip trailing whitespace. All webhook and API responses flow through
this normaliser, so it is the single correct place to apply the fix
without touching stored data.

## What changed

Added \`.rstrip\` to \`Messages::WebhookContentNormalizer.normalize\`:

\`\`\`ruby
# before
text.gsub(/\\\r?\n/, "\n")

# after
text.gsub(/\\\r?\n/, "\n").rstrip
\`\`\`

## Trade-offs considered

| Option | Decision |
|---|---|
| \`before_save\` on \`Message\` model | Would clean stored data but is
a broader change affecting all message creation paths and would require
a data migration for existing records. Out of scope for this bug. |
| Trim in each channel's send path | DRY violation — many channels, each
would need the same patch. |
| Fix at normaliser level (chosen) | Single location, only affects
webhook/API output, zero risk to stored data or native channel delivery.
|

**Known limitation:** existing messages in the database still have
trailing newlines in storage. They will be delivered correctly through
webhooks after this fix, but a follow-up migration could clean stored
content if needed.

## How to reproduce

1. Send an agent reply from the Chatwoot UI
2. Inspect the \`content\` field of the outgoing \`message_created\`
webhook payload
3. Observe trailing \`\n\n\n\` after the message text

After this fix, the \`content\` field is trimmed before delivery.

---------

Co-authored-by: Ramalau Debeila <rdebeila@datacentrix.co.za>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2026-06-02 23:28:13 +05:30
0a181b0cea chore: Update translations (#14498)
Updates dashboard, widget, and backend locale files with the latest
translation sync from Crowdin.

## Closes

N/A

## What changed

- Refreshes translated dashboard JSON locale files across supported
languages.
- Adds the latest backend Help Center/public portal locale strings.
- Keeps the branch current with `develop` and resolves the `ar`, `fr`,
and `pt_BR` locale conflicts.

## Validation

- Parsed all changed JSON and YAML locale files successfully.
- Checked for leftover merge conflict markers.
- Ran `git diff --check`.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-06-02 21:21:50 +05:30
Sony MathewandGitHub 87df43bdd0 revert: restore conversation unread count feature flag (#14623)
This reverts #14610 so conversation unread counts are again controlled
by the `conversation_unread_counts` feature flag across the API,
ActionCable broadcasts, notifier/listener paths, and dashboard sidebar
fetching.

## Closes
- None

## What changed
- Restores feature-flag checks for conversation unread count reads and
broadcasts.
- Restores the dashboard feature flag constant and sidebar/store
behavior for disabled unread counts.
- Restores the specs that cover disabled-feature behavior.

## How to test
- In an account with `conversation_unread_counts` enabled, verify
sidebar unread counts are fetched and updated in real time.
- Disable `conversation_unread_counts` for the account and verify unread
count requests/broadcasts are skipped.
2026-06-02 21:11:48 +05:30
28f87d2fca fix(widget): translate zh_CN availability keys (#14288)
Translate missing Simplified Chinese live-chat widget availability and
reply-time strings so visitors using `zh_CN` no longer see English
fallbacks in offline and pre-chat states.

## Closes

N/A

## How to test

- Open the widget with `Widget Locale = 中文 (zh_CN)` and set the team
offline. The availability card should stay in Chinese.
- Configure working hours so the widget shows minute, hour, tomorrow,
and day-specific return states. The `{time}`, `{n}`, and `{day}`
placeholders should render correctly.

## What changed

- Translated missing `THUMBNAIL.AUTHOR.NOT_AVAILABLE`,
`TEAM_AVAILABILITY.BACK_AS_SOON_AS_POSSIBLE`, and `REPLY_TIME.*` strings
in `app/javascript/widget/i18n/locale/zh_CN.json`.
- Kept the scope limited to Simplified Chinese.

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-06-02 21:10:44 +05:30
37eed5de1e feat(whatsapp): Add support for voice messages (#14606)
> Reopened from #13613, now from a personal fork
(`gabrieljablonski/chatwoot`) so maintainers can push edits —
organization-owned forks don't support "Allow edits from maintainers".
The previous PR is closed in favor of this one; same commits, same diff.

## Description

This PR adds support for sending voice messages (voice notes) through
the WhatsApp Cloud API. When agents record audio in Chatwoot, it is now
transcoded in the browser from WebM/Opus to OGG/Opus and sent with the
`voice: true` flag, so it appears as a native voice note bubble on
WhatsApp — not as a file/document attachment.

Closes #13283

**Key Changes:**
- Added `webmOpusToOgg.js` — a pure JS EBML parser + OGG page builder
that remuxes browser-recorded WebM/Opus audio into OGG/Opus entirely
client-side, with no server-side dependencies.
- Updated `AudioRecorder.vue` to use an explicit `mimeType` hint, proper
resource cleanup, and an `AUDIO_EXTENSION_MAP` for correct file
extensions.
- Renamed `mp3ConversionUtils.js` → `audioConversionUtils.js` and added
OGG conversion support via the new remuxer.
- Updated `ReplyBox.vue` to request OGG format for WhatsApp channels,
pass `isVoiceMessage` per-attachment, and handle recording errors with a
user-facing alert.
- Updated `MessageBuilder` to read the `is_voice_message` param and
persist it in attachment metadata.
- Updated `WhatsappCloudService` to:
- Normalize `audio/opus` → `audio/ogg` content type on ActiveStorage
blobs (works around Marcel gem re-detection).
- Send the `voice: true` flag when the attachment is a voice message
with `audio/ogg` content type.
  - Use WhatsApp Cloud API `v24.0` for the attachment endpoint.
- Added `AUDIO_CONVERSION_FAILED` i18n key.

**How it works:**
1. The browser records audio as WebM/Opus (Chrome/Firefox default).
2. `audioConversionUtils.js` remuxes it to OGG/Opus using the pure-JS
`webmOpusToOgg` remuxer — no server transcoding needed.
3. The OGG file is uploaded with `is_voice_message: true` in the form
payload.
4. `MessageBuilder` persists `is_voice_message` in the attachment's
`meta` hash.
5. `WhatsappCloudService` normalizes the blob content type if needed,
then sends the attachment with `voice: true` so WhatsApp renders it as a
voice note.

## Type of change

- [X] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

1. Record a voice message in a WhatsApp Cloud conversation.
2. Verify the audio is transcoded to OGG (check file extension in the
attachment preview).
3. Verify the message arrives on WhatsApp as a voice note bubble (not a
document/file).
4. Send an image or document attachment and verify it still works as
before (no `voice` flag).
5. Send a regular (non-voice) audio file and verify it arrives without
the voice flag.

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 15:33:32 +04:00
170b64d1f1 chore: upgrade to vite 6 (#14363)
Upgrades the frontend toolchain to Vite 6 and tidies up the build config
along the way. Behavior is unchanged for end users; this is dev/build
infra.

## What changed
- `vite` 5.4 → 6.4, `@vitejs/plugin-vue` → 5.2, `vite-plugin-ruby` → 5.2
(with matching `vite_rails`/`vite_ruby` gem bumps).
- Dropped the `vite-node` 2.0.1 pnpm override — no longer needed now
that vitest 3 runs on Vite 6 directly.
- Split the single `vite.config.ts` into:
- `vite.config.ts` (app), `vite.lib.config.ts` (SDK), `vite.shared.ts`
(aliases / Vue options), `vitest.config.ts` (tests).
- `pnpm build:sdk` now selects the SDK config explicitly instead of
branching on `BUILD_MODE=library`. SDK output path is unchanged
(`public/packs/js/sdk.js`).

No changes needed to Docker images, deployment scripts, or CI — Node 24
and pnpm 10 are already past Vite 6's floor, and the rake
`assets:precompile` hook still drives the SDK build via `pnpm`.

## How to test
- `pnpm dev` and verify the dashboard, widget, and survey routes load
and HMR works.
- Load a Chatwoot site widget on a test page and confirm `sdk.js` is
served and the widget mounts.
- `RAILS_ENV=production bundle exec rake assets:precompile` and confirm
`public/packs/js/sdk.js` plus the rest of the manifest are produced.
- `pnpm test` for the JS suite.

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com>
2026-06-02 17:01:37 +05:30
95cb3a7ad8 feat(onboarding): honor return_to hint in Instagram OAuth callback (#14568)
When connecting an Instagram inbox during onboarding, the OAuth flow
used to drop users in inbox settings, breaking onboarding. The OAuth
start endpoint now accepts an optional `return_to=onboarding` hint,
carried tamper-proof inside the signed state (a claim on the Instagram
JWT), and the callback uses it to return the user to the onboarding
inbox-setup screen. Without the hint, behavior is unchanged.

This is the backend half only; the frontend that sends
`return_to=onboarding` ships separately.

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-06-02 15:28:08 +05:30
ecd9c26c8c feat: Implemented search results page functionality (#11086)
# Pull Request Template

## Description
Implemented search results page functionality. Now you can press "Enter"
to search by term and display results in a results page. Also now you
can link to /hc/{account}/en/search?query=XXXXXX to view search results
for XXXXXX query.

fixes: https://github.com/chatwoot/chatwoot/issues/10945

## Screenshots

Classic layout search results:
<img width="3840" height="2160" alt="classic-results"
src="https://github.com/user-attachments/assets/3bbb3272-33ca-4eb4-b80a-76ed77442088"
/>

Classic layout pagination:
<img width="3840" height="2160" alt="classic-page-two"
src="https://github.com/user-attachments/assets/062b09d3-7c58-4d3b-8611-b94375e7db51"
/>

Classic layout empty search:
<img width="3840" height="2160" alt="no-results"
src="https://github.com/user-attachments/assets/c5e3f47a-cd9a-4e14-ae92-ccba00c89e98"
/>

Documentation layout search results:
<img width="3840" height="2160" alt="documentation-results"
src="https://github.com/user-attachments/assets/9e45d8d9-c975-4589-b6c6-3bc7bb3c588e"
/>

Documentation layout dark theme:
<img width="3840" height="2160" alt="documentation-dark"
src="https://github.com/user-attachments/assets/cdb6ed63-4241-4b32-9f79-7d92ed479fc8"
/>

Plain embedded dark layout:
<img width="3840" height="2160" alt="plain-embedded-dark"
src="https://github.com/user-attachments/assets/7deb02b9-9f24-48fb-8979-a2ecd7002c05"
/>

---------

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
2026-06-02 15:19:23 +05:30
Sony MathewandGitHub 88e2661ca6 feat(conversations): remove unread count feature flag (CW-7237) (#14610)
## Description

Make conversation unread counts always available at runtime by removing
account feature checks from the API endpoint, unread-count listener,
notifier, and ActionCable broadcast path.

Update the dashboard to fetch sidebar unread counts for the active
account without checking FEATURE_FLAGS.CONVERSATION_UNREAD_COUNTS, and
remove the now-unused store clear action that only supported the
disabled state.

Keep the feature entry in config/features.yml to preserve flag bit
order, but mark it enabled and deprecated so fresh installs default to
the always-on behavior while feature-management UI hides it.

Leave existing installation default rows untouched; no migration is
included, so upgraded installs may still store the old flag value but
runtime behavior no longer depends on it.

Update specs around the new always-on contract and remove obsolete
disabled-feature assertions.

Fixes # CW-7237

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Update specs around the new always-on contract and remove obsolete
disabled-feature assertions. Ran specs locally for the changes.


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2026-06-02 14:35:37 +05:30