Compare commits

..
54 Commits
Author SHA1 Message Date
Sojan Jose 899fce1c92 Merge branch 'release/4.12.1'
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Waiting to run
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Waiting to run
Publish Chatwoot EE docker images / merge (push) Blocked by required conditions
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Waiting to run
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Waiting to run
Publish Chatwoot CE docker images / merge (push) Blocked by required conditions
2026-03-25 16:21:28 -07:00
Sojan Jose 7144d55334 Bump version to 4.12.1 2026-03-25 16:20:58 -07:00
250650dd7a feat(platform): Add email channel migration endpoint for bulk OAuth channel creation (#13902)
Adds a Platform API endpoint that allows migrating existing Google and
Microsoft email channels (with OAuth credentials) into Chatwoot without
requiring end-users to re-authenticate. This enables customers who lack
Rails console access to programmatically migrate email channels from
legacy systems.
    
 ### How to test

1. Create a Platform App and grant it permissible access to a target
account
2. `POST /platform/api/v1/accounts/:account_id/email_channel_migrations`
with a payload like:
  ```json
  {
    "migrations": [
      {
        "email": "support@example.com",
        "provider": "google",
        "provider_config": {
          "access_token": "...",
          "refresh_token": "...",
          "expires_on": "..."
        },
        "inbox_name": "Migrated Support"
      }
    ]
  }
```
  3. Verify channels are created with correct provider, provider_config, and IMAP defaults
  4. Verify partial failures (e.g. duplicate email) don't roll back other migrations in the batch
  5. Verify unauthenticated and non-permissible requests return 401

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-25 15:58:08 -07:00
608be1036b fix: Send raw content in webhook payloads instead of channel-rendered markdown (#13896)
Webhook payloads (`message_created`, `message_updated`) started sending
channel-rendered HTML in the `content` field instead of the original raw
message content after PR #12878. This broke downstream agent bots and
integrations that expected plain text or markdown. 
Closes https://linear.app/chatwoot/issue/PLA-109/webhook-payloads-send-channel-rendered-html-instead-of-raw-content

## How to reproduce

1. Connect an agent bot to a WebWidget inbox
2. Send a message with markdown formatting (e.g. `**bold**`) from the
widget
3. Observe the agent bot webhook payload — `content` field contains
`<p><strong>bold</strong></p>` instead of `**bold**`

## What changed

Split `MessageContentPresenter` into two public methods:
- `outgoing_content` — renders markdown for the target channel (used by
channel delivery services)
- `webhook_content` — returns raw content with CSAT survey URL when
applicable, no markdown rendering (used by `webhook_data`)

Updated `Message#webhook_data` to use `webhook_content` instead of
`outgoing_content`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2026-03-25 16:56:22 +04:00
salmonumbrellaandGitHub 6ff643b045 fix(i18n): add zh_TW snooze parser locale (#13822) 2026-03-25 16:54:18 +05:30
Vishnu NarayananandGitHub 775b73d1f9 fix: raise open file descriptor limit to prevent EMFILE errors (#13895)
## Summary
- Adds `LimitNOFILE=65536` to both web and worker systemd service units
- Fixes recurring `Errno::EMFILE` (Too many open files) errors during
peak traffic after deploys

## Context
Puma workers idle at 720-770 open FDs against the default soft limit of
1024, leaving ~250 FDs of headroom. During deploy-triggered instance
refreshes at peak traffic, concurrent requests exhaust the remaining
FDs, causing EMFILE across all web instances.

3 incidents in March 2026 with escalating event counts. The hard limit
is already 524288, so this just raises the soft limit to a standard
production value.

Self-hosted instances pick this up automatically via `cwctl --upgrade`.

Fixes
https://linear.app/chatwoot/issue/CW-6685/errnoemfile-too-many-open-files-rb-sysopen
2026-03-24 17:37:07 -07:00
14df7b3bc1 fix: ai-assist 404 on CE (#13891)
# Pull Request Template

## Description

Relocate controller from enterprise/ to app/ and add
Api::V1::Accounts::Captain::TasksController.prepend_mod_with for EE
overrides.

Fixes: Ai assist giving 404 on CE

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

before:
<img width="482" height="130" alt="image"
src="https://github.com/user-attachments/assets/f51dc28a-ac54-45c4-9015-6f956fdf5057"
/>

after:
<img width="458" height="182" alt="image"
src="https://github.com/user-attachments/assets/eb86a679-5482-4157-9f4e-f3e9953d8649"
/>


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2026-03-24 16:58:11 +05:30
Sivin VargheseandGitHub 6946859ba4 fix: normalize "in less than a minute" to "now" in chat list timestamp (#13874)
# Pull Request Template

## Description

This PR fixes the conversation list showing raw "**in less than a
minute**" text instead of "**now**" for very recent conversations.

Fixes https://linear.app/chatwoot/issue/CW-6666/issue-with-timestamps

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)


## 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
- [ ] 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-03-24 16:16:35 +05:30
Sivin VargheseandGitHub c129ab00ba fix: normalize "in less than a minute" to "now" in chat list timestamp (#13874) 2026-03-24 15:40:31 +05:30
7edae93ee8 fix(agent-bot): Include payload in webhook retry failure logs (#13879)
Webhook retry failure logs for agent-bot now include the event payload,
making it easier to identify which event failed when debugging transient
upstream errors (429/500).

Previously the log only showed:
`[AgentBots::WebhookJob] attempt 1 failed
RestClient::InternalServerError`

Now it includes the payload:
`[AgentBots::WebhookJob] attempt 1 failed
RestClient::InternalServerError payload={"event":"message_created",...}`

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:52:37 +04:00
4b315bc2ec chore: Update translations (#13884)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-23 20:06:17 -07:00
Sivin VargheseandGitHub 30c0479e9a fix: show agent name in unread bubble for Captain replies (#13876) 2026-03-23 20:03:31 +05:30
Aakash BakhleandGitHub 3c0d55f87a fix: handoff only if conversation pending (#13882)
# Pull Request Template

## Description

- Skip handoff when the conversation is no longer pending. 
- Fetch conversation status with Conversation.uncached to avoid stale
query cache when checking pending state.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

Difficult to reproduce locally, but seen a couple of conversations where
bot hands off an extra time or Captain re-generates usually due to a
retry on FaradayTimeoutError but at perform time, the conversation
status is stale so it appears as if Captain responded in an open
conversation.

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-23 17:09:58 +05:30
Aakash BakhleandGitHub 4af3e830fc fix: conversation completion prompt to auto-resolve gibberish/no-intent messages after inactivity (#13875)
# Pull Request Template

## Description

For our account, the conversation completion evaluator was proving to be
too conservative. This resulted in queue noise.
This PR adds a line to handle gibberish/single worded messages with no
further context.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

<img width="3012" height="978" alt="CleanShot 2026-03-23 at 11 44 55@2x"
src="https://github.com/user-attachments/assets/328195e8-6ea0-4c3a-9049-ee80196eecad"
/>

<img width="2202" height="866" alt="CleanShot 2026-03-23 at 11 47 15@2x"
src="https://github.com/user-attachments/assets/8d51cff4-b18f-4582-9455-8119ec7eff3a"
/>


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-23 12:18:23 +05:30
b974993886 chore: Update translations (#13845)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-21 02:20:27 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Sojan Jose
4b849cdd11 chore(deps): bump bcrypt from 3.1.20 to 3.1.22 (#13852)
Bumps [bcrypt](https://github.com/bcrypt-ruby/bcrypt-ruby) from 3.1.20
to 3.1.22.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/releases">bcrypt's
releases</a>.</em></p>
<blockquote>
<h2>v3.1.22</h2>
<h2>What's Changed</h2>
<ul>
<li>Move compilation after bundle install by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/291">bcrypt-ruby/bcrypt-ruby#291</a></li>
<li>Add TruffleRuby in CI by <a
href="https://github.com/tjschuck"><code>@​tjschuck</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/293">bcrypt-ruby/bcrypt-ruby#293</a></li>
<li>fix env url by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/294">bcrypt-ruby/bcrypt-ruby#294</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.21...v3.1.22">https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.21...v3.1.22</a></p>
<h2>v3.1.21</h2>
<h2>What's Changed</h2>
<ul>
<li>Provide a 'Changelog' link on rubygems.org/gems/bcrypt by <a
href="https://github.com/mark-young-atg"><code>@​mark-young-atg</code></a>
in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/274">bcrypt-ruby/bcrypt-ruby#274</a></li>
<li>Support ruby 3.3 and 3.4.0-preview1 by <a
href="https://github.com/m-nakamura145"><code>@​m-nakamura145</code></a>
in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/276">bcrypt-ruby/bcrypt-ruby#276</a></li>
<li>Mark as ractor-safe by <a
href="https://github.com/mohamedhafez"><code>@​mohamedhafez</code></a>
in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/280">bcrypt-ruby/bcrypt-ruby#280</a></li>
<li>Add == gotcha that can be unintuitive at first by <a
href="https://github.com/federicoaldunate"><code>@​federicoaldunate</code></a>
in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/279">bcrypt-ruby/bcrypt-ruby#279</a></li>
<li>Constant compare by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/282">bcrypt-ruby/bcrypt-ruby#282</a></li>
<li>try to modernize CI by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/287">bcrypt-ruby/bcrypt-ruby#287</a></li>
<li>Try to deal with flaky tests by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/288">bcrypt-ruby/bcrypt-ruby#288</a></li>
<li>Configure trusted publishing by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/289">bcrypt-ruby/bcrypt-ruby#289</a></li>
<li>bump version by <a
href="https://github.com/tenderlove"><code>@​tenderlove</code></a> in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/290">bcrypt-ruby/bcrypt-ruby#290</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/mark-young-atg"><code>@​mark-young-atg</code></a>
made their first contribution in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/274">bcrypt-ruby/bcrypt-ruby#274</a></li>
<li><a
href="https://github.com/m-nakamura145"><code>@​m-nakamura145</code></a>
made their first contribution in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/276">bcrypt-ruby/bcrypt-ruby#276</a></li>
<li><a
href="https://github.com/mohamedhafez"><code>@​mohamedhafez</code></a>
made their first contribution in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/280">bcrypt-ruby/bcrypt-ruby#280</a></li>
<li><a
href="https://github.com/federicoaldunate"><code>@​federicoaldunate</code></a>
made their first contribution in <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/pull/279">bcrypt-ruby/bcrypt-ruby#279</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.20...v3.1.21">https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.20...v3.1.21</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/blob/master/CHANGELOG">bcrypt's
changelog</a>.</em></p>
<blockquote>
<p>3.1.22 Mar 18 2026</p>
<ul>
<li>[CVE-2026-33306] Fix integer overflow in Java extension</li>
</ul>
<p>3.1.21 Dec 31 2025</p>
<ul>
<li>Use constant time comparisons</li>
<li>Mark as Ractor safe</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/831ce64cb0a9502130fa93a28bfd9527a5fa45c4"><code>831ce64</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/32e687ec5f62baad01a62e4634e41d97f8432a61"><code>32e687e</code></a>
bump version update changelog</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/5faa2748331d3edc661c127ef2fbb3afcb6b02a4"><code>5faa274</code></a>
Fix integer overflow in JRuby BCrypt rounds calculation</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/aafc0332ac1aa0d774f2c864439596436f92d18d"><code>aafc033</code></a>
Merge pull request <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/issues/294">#294</a>
from bcrypt-ruby/fix-publishing</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/01f947a66ad8c5e20d8c89d9adbc7e3bd49afb70"><code>01f947a</code></a>
fix env url</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/92ca1d67deeb8e64dbe779396c52b177e307bc43"><code>92ca1d6</code></a>
Merge pull request <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/issues/293">#293</a>
from bcrypt-ruby/truffleruby-ci-alt-implementation</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/4d1d95b8ec624d0cf8ed1099402a7edd2f308da2"><code>4d1d95b</code></a>
Add TruffleRuby in CI</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/36a04a2278fae3b38100912ff489b86cd0984b8a"><code>36a04a2</code></a>
Merge pull request <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/issues/291">#291</a>
from tenderlove/fix-publishing</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/01cc68835f0bcdd7ef16de477471c112adb417da"><code>01cc688</code></a>
Move compilation after bundle install</li>
<li><a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/commit/82e6c4c6cf81912768c68d721372e78330ff2c92"><code>82e6c4c</code></a>
Merge pull request <a
href="https://redirect.github.com/bcrypt-ruby/bcrypt-ruby/issues/290">#290</a>
from tenderlove/bump</li>
<li>Additional commits viewable in <a
href="https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.20...v3.1.22">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=bcrypt&package-manager=bundler&previous-version=3.1.20&new-version=3.1.22)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/chatwoot/chatwoot/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-20 16:30:50 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Sojan Jose
310590cae3 chore(deps): bump json from 2.18.1 to 2.19.2 (#13849)
Bumps [json](https://github.com/ruby/json) from 2.18.1 to 2.19.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/json/releases">json's
releases</a>.</em></p>
<blockquote>
<h2>v2.19.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix a format string injection vulnerability in <code>JSON.parse(doc,
allow_duplicate_key: false)</code>. <code>CVE-2026-33210</code></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ruby/json/compare/v2.19.1...v2.19.2">https://github.com/ruby/json/compare/v2.19.1...v2.19.2</a></p>
<h2>v2.19.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix a compiler dependent GC bug introduced in
<code>2.18.0</code>.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ruby/json/compare/v2.19.0...v2.19.1">https://github.com/ruby/json/compare/v2.19.0...v2.19.1</a></p>
<h2>v2.19.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix <code>allow_blank</code> parsing option to no longer allow
invalid types (e.g. <code>load([], allow_blank: true)</code> now raise a
type error).</li>
<li>Add <code>allow_invalid_escape</code> parsing option to ignore
backslashes that aren't followed by one of the valid escape
characters.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/ruby/json/compare/v2.18.1...v2.19.0">https://github.com/ruby/json/compare/v2.18.1...v2.19.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/json/blob/master/CHANGES.md">json's
changelog</a>.</em></p>
<blockquote>
<h3>2026-03-18 (2.19.2)</h3>
<ul>
<li>Fix a format string injection vulnerability in <code>JSON.parse(doc,
allow_duplicate_key: false)</code>. <code>CVE-2026-33210</code>.</li>
</ul>
<h3>2026-03-08 (2.19.1)</h3>
<ul>
<li>Fix a compiler dependent GC bug introduced in
<code>2.18.0</code>.</li>
</ul>
<h3>2026-03-06 (2.19.0)</h3>
<ul>
<li>Fix <code>allow_blank</code> parsing option to no longer allow
invalid types (e.g. <code>load([], allow_blank: true)</code> now raise a
type error).</li>
<li>Add <code>allow_invalid_escape</code> parsing option to ignore
backslashes that aren't followed by one of the valid escape
characters.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ruby/json/commit/54f8a878aebee090476a53c851c943128894be62"><code>54f8a87</code></a>
Release 2.19.2</li>
<li><a
href="https://github.com/ruby/json/commit/393b41c3e5f87491e1e34fa59fa78ff6fa179a74"><code>393b41c</code></a>
Fix a format string injection vulnerability</li>
<li><a
href="https://github.com/ruby/json/commit/dbf6bb12aac85db939df1180028aea06c8d3b762"><code>dbf6bb1</code></a>
Merge pull request <a
href="https://redirect.github.com/ruby/json/issues/953">#953</a> from
ruby/dependabot/github_actions/actions/create-gi...</li>
<li><a
href="https://github.com/ruby/json/commit/7187315b4571ade59d68a1fad84be2794cda744d"><code>7187315</code></a>
Bump actions/create-github-app-token from 2 to 3</li>
<li><a
href="https://github.com/ruby/json/commit/4a42a04280d96d8dd94558078c16f1c078c38e1b"><code>4a42a04</code></a>
Release 2.19.1</li>
<li><a
href="https://github.com/ruby/json/commit/13689c269970f18316952541f8544830ec2dc5c4"><code>13689c2</code></a>
Add missing GC_GUARD in <code>fbuffer_append_str</code></li>
<li><a
href="https://github.com/ruby/json/commit/a11acc1ff496627e5d72c71d6d1229e8c8ffeaa1"><code>a11acc1</code></a>
Release 2.19.0</li>
<li><a
href="https://github.com/ruby/json/commit/0a4fb79cd97f535701cc2240ac736d76b9af5025"><code>0a4fb79</code></a>
fbuffer.h: Use size_t over unsigned long</li>
<li><a
href="https://github.com/ruby/json/commit/a29fcdcb4a78164daa14f6af05812690dd3ac939"><code>a29fcdc</code></a>
Add depth validation to Jruby and TruffleRuby implementations</li>
<li><a
href="https://github.com/ruby/json/commit/de993aa76639078da891f46351a36f77d51ad3d3"><code>de993aa</code></a>
Reject negative depth; add overflow guards to prevent hang/crash</li>
<li>Additional commits viewable in <a
href="https://github.com/ruby/json/compare/v2.18.1...v2.19.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=json&package-manager=bundler&previous-version=2.18.1&new-version=2.19.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/chatwoot/chatwoot/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-20 16:30:35 -07:00
Sivin VargheseandGitHub 251e9980fd chore: Auto-focus editor when replying to a message (#13857)
# Pull Request Template

## Description

This PR adds support to auto-focus the editor when clicking reply to
this message, the editor now automatically receives focus so users can
start typing immediately.

Fixes
https://linear.app/chatwoot/issue/CW-6661/typing-box-not-focused-after-clicking-reply-to-message

## Type of change


- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

### Screencast


https://github.com/user-attachments/assets/c5e77055-3f68-4ad8-934e-cfc465166e8a




## 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
- [ ] 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-03-20 16:59:27 +05:30
Tanmay Deep SharmaandGitHub 2b50909d9b fix: use last_activity_at for orphan conversation cleanup timeframe (#13859)
## Description

The RemoveOrphanConversationsService filters orphan conversations by a
time window before deleting them. Previously it used created_at, which
could miss old conversations that still had recent activity.
Switching to last_activity_at ensures the cleanup window reflects actual
conversation activity rather than creation time.

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- By running Rake task 
- Run the job from console 

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2026-03-20 16:28:05 +05:30
Aakash BakhleandGitHub 290dd3abf5 feat: allow captain to access contact attributes (#13850)
# Pull Request Template

## Description

Captain v1 does not have access to contact attributes. Added a toggle to
let user choose if they want contact information available to Captain.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

Specs and locally
<img width="1924" height="740" alt="CleanShot 2026-03-19 at 18 48 19@2x"
src="https://github.com/user-attachments/assets/353cfeaa-cd58-40eb-89e7-d660a1dc1185"
/>

![Uploading CleanShot 2026-03-19 at 18.53.26@2x.png…]()


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-20 16:15:06 +05:30
a9123e7d66 chore(i18n): add missing pt_BR locale imports for companies, mfa, snooze, webhooks and more (#13844)
## Description

Add missing JSON imports and spread exports for `companies`,
`contentTemplates`, `mfa`, `snooze`, `webhooks`, and `yearInReview` so
these translations are properly loaded in the pt_BR locale. Without
these imports, those sections of the UI were falling back to English for
Brazilian Portuguese users.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] My changes generate no new warnings

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-19 01:27:37 -07:00
9967101b48 feat(rollup): add models and write path [1/3] (#13796)
## PR#1: Reporting events rollup — model and write path

Reporting queries currently hit the `reporting_events` table directly.
This works, but the table grows linearly with event volume, and
aggregation queries (counts, averages over date ranges) get
progressively slower as accounts age.

This PR introduces a pre-aggregated `reporting_events_rollups` table
that stores daily per-metric, per-dimension (account/agent/inbox)
totals. The write path is intentionally decoupled from the read path —
rollup rows are written inline from the event listener via upsert, and a
backfill service exists to rebuild historical data from raw events.
Nothing reads from this table yet.

The write path activates when an account has a `reporting_timezone` set
(new account setting). The `reporting_events_rollup` feature flag
controls only the future read path, not writes — so rollup data
accumulates silently once timezone is configured. A `MetricRegistry`
maps raw event names to rollup column semantics in one place, keeping
the write and (future) read paths aligned.

### What changed

- Migration for `reporting_events_rollups` with a unique composite index
for upsert
- `ReportingEventsRollup` model
- `reporting_timezone` account setting with IANA timezone validation
- `MetricRegistry` — single source of truth for event-to-metric mappings
- `RollupService` — real-time upsert from event listener
- `BackfillService` — rebuilds rollups for a given account + date from
raw events
- Rake tasks for interactive backfill and timezone setup
- `reporting_events_rollup` feature flag (disabled by default)

### How to test

1. Set a `reporting_timezone` on an account
(`Account.first.update!(reporting_timezone: 'Asia/Kolkata')`)
2. Resolve a conversation or trigger a first response
3. Check `ReportingEventsRollup.where(account_id: ...)` — rows should
appear
4. Run backfill: `bundle exec rake reporting_events_rollup:backfill` and
verify historical data populates

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-19 13:12:36 +05:30
654fcd43f2 docs(swagger): fix public API schema definitions to match jbuilder responses (#13693)
## Description

This PR updates the OpenAPI schema definitions for Public API resources
(`public_conversation`, `public_message`, `public_contact`) so they
match the actual API responses produced by the jbuilder views.

These definitions were introduced in #2417 (2021-06) with a minimal set
of fields. The jbuilder views have since been updated (e.g. `uuid` in
#7255, `agent_last_seen_at` in #4377), but the Swagger definitions were
never updated. As a result, generated API clients get incorrect or
missing types. This change fixes that by aligning the schemas with the
implementation.

**Fixes #13692**

## 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)
- [x] This change requires a documentation update

## How Has This Been Tested?

- Compared each jbuilder view
(`app/views/public/api/v1/models/_conversation.json.jbuilder`,
`_message.json.jbuilder`, `_contact.json.jbuilder`) field-by-field
against the Swagger YAML definitions.
- Cross-referenced Ruby model enums (`Conversation.status`,
`Attachment.file_type`, `Message.message_type`) for enum values.
- Ran the swagger build (via the project’s `rake swagger:build` logic /
`json_refs` resolution) to regenerate `swagger.json` and tag group
files; confirmed the generated schemas contain the correct fields and
types.
- No runtime tests were run; this is a documentation/schema-only change.

## 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 *(N/A: schema definitions)*
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works *(N/A: documentation/schema only)*
- [ ] New and existing unit tests pass locally with my changes *(N/A: no
code under test)*
- [x] Any dependent changes have been merged and published in downstream
modules *(N/A: none)*

---

## Change summary (for reference)

### `public_conversation`
- Added missing fields: `uuid`, `status`, `contact_last_seen_at`,
`agent_last_seen_at`
- Fixed `inbox_id` type from `string` to `integer`
- Fixed `messages` items `$ref` from `message` to `public_message`
- Added property details for embedded `contact` object (`id`, `name`,
`email`, `phone_number`)
- Added `status` enum: `open`, `resolved`, `pending`, `snoozed`

### `public_message`
- Fixed `id`, `message_type`, `created_at`, `conversation_id` types
(string → integer where applicable)
- Fixed `content_attributes` type from `string` to `object`
- Added property details for `attachments` items and `sender` object
- Added `file_type` and `sender.type` enums

### `public_contact`
- Added missing `phone_number` field

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-19 00:03:37 -07:00
Shivam MishraandGitHub 284977687c fix: patch Devise confirmable race condition vulnerability (#13843)
Devise 4.9.x has a race condition in the reconfirmable flow where
concurrent email change requests can desynchronize the confirmation
token from `unconfirmed_email`, letting an attacker confirm an email
they don't own. We use `:confirmable` with `reconfirmable = true`, so
we're directly exposed.

The upstream fix is in Devise 5.0.3, but we can't upgrade —
`devise-two-factor` only supports Devise 5 from v6.4.0, which also
raised its Rails minimum to 7.2+. No released version supports both
Devise 5 and Rails 7.1.

This PR ports the Devise 5.0.3 fix locally by overriding
`postpone_email_change_until_confirmation_and_regenerate_confirmation_token`
on the User model to persist the record before regenerating the token.
This is a stopgap — remove it once the dependency chain allows upgrading
to Devise 5.

### How to test

Sign in as a confirmed user and change your email. The app should send a
confirmation to the new address while keeping the current email
unchanged until confirmed.
2026-03-18 21:30:09 -07:00
Sojan Jose 18dc77aa56 Merge branch 'release/4.12.0' into develop 2026-03-17 16:23:16 -07:00
Sojan Jose b6b856260f Merge branch 'release/4.12.0'
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Waiting to run
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Waiting to run
Publish Chatwoot EE docker images / merge (push) Blocked by required conditions
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Waiting to run
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Waiting to run
Publish Chatwoot CE docker images / merge (push) Blocked by required conditions
2026-03-17 16:23:05 -07:00
Sojan Jose 8aad8ad38e Bump version to 4.12.0 2026-03-17 16:19:39 -07:00
098f7a77b6 chore: Update translations (#13832)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-17 16:02:40 -07:00
msaleh-313andGitHub 9c22d791c4 fix: return correct outgoing_url in Platform agent bot API responses (#13827)
The Platform API was returning the bot's `name` value for the
`outgoing_url` field across all agent bot endpoints (index, show,
create, update). A typo in the `_agent_bot.json.jbuilder` partial used
`resource.name` instead of `resource.outgoing_url`.

Closes #13787

## What changed

- `app/views/platform/api/v1/models/_agent_bot.json.jbuilder`: corrected
`resource.name` → `resource.outgoing_url` on the `outgoing_url` field.

## How to reproduce

1. Create an agent bot via `POST /platform/api/v1/agent_bots` with a
distinct `outgoing_url`.
2. Call `GET /platform/api/v1/agent_bots/:id`.
3. Before this fix the `outgoing_url` in the response equals the bot's
`name`; after the fix it equals the value set at creation.

## Tests

Added `outgoing_url` assertions to the existing GET index and GET show
request specs so the regression is covered.
2026-03-17 13:40:45 -07:00
Tanmay Deep SharmaandGitHub 4d344a47dc chore(tds-1): rake task for assignment v2 migration (#13828) 2026-03-17 20:35:03 +05:30
Aakash BakhleandGitHub 38dbda9378 fix: reverse order of api_key for bg task (#13826)
# Pull Request Template

## Description

we were getting 403, 401 errors on `translate_query` on langfuse and
sentry
This happened because, we use the customer's openai key if they have
BYOK
But translation is something they never opt in so we should not use
their quota for it.
This PR addresses the issue.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

locally

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-17 17:36:40 +05:30
a4c3d3d8c0 feat(widget): Allow widget loading in mobile app WebViews when domain restrictions are set (#13763)
When `allowed_domains` is configured on a web widget inbox, the server
responds with Content-Security-Policy: frame-ancestors <domains>, which
blocks the widget iframe in mobile app WebViews. This happens because
WebViews load content from file:// or null origins, which cannot match
any domain in the frame-ancestors directive.

This adds a per-inbox toggle — "Enable widget in mobile apps" — that
skips the frame-ancestors header when the request has no valid Origin
(i.e., it comes from a mobile WebView). Web browsers with a real origin
still get domain restrictions enforced as usual.

<img width="2330" height="1490" alt="CleanShot 2026-03-11 at 10 13
01@2x"
src="https://github.com/user-attachments/assets/d9326fac-020d-4ce7-9ced-0c185468c8fc"
/>


Fixes
https://linear.app/chatwoot/issue/CW-6560/widget-is-not-loading-from-iosandroid-widgets

How to test

1. Go to Settings → Inboxes → (Web Widget) → Configuration
2. Set allowed_domains to a specific domain (e.g., *.example.com)
3. Try loading the widget in a mobile app WebView — it should be blocked
4. Enable "Enable widget in mobile apps" checkbox
5. Reload the widget in the WebView — it should now load successfully
6. Verify the widget on a website not in the allowed domains list is
still blocked

---------

Co-authored-by: iamsivin <iamsivin@gmail.com>
2026-03-17 14:29:41 +04:00
688218de0a feat: distributed scheduling for version check job (#13042)
This change spreads Chatwoot Hub version checks across the day by
scheduling each installation at a stable minute derived from its
installation identifier, instead of having all instances check at the
same fixed time.

Closes
-
https://linear.app/chatwoot/issue/CW-6107/handle-the-spike-at-12-utc-on-chatwoot-hub

What changed
- Added `Internal::TriggerDailyScheduledItemsJob` to act as the daily
trigger for deferred internal jobs.
- Updated the version check cron entry to run once daily at `00:00 UTC`
and enqueue the actual version check for that installation’s assigned
minute of the day.
- Used a deterministic minute-of-day derived from
`ChatwootHub.installation_identifier` so the check time stays stable
across deploys and restarts.
- Kept the existing cron schedule key while switching it to the new
orchestrator job.

How to test
- Run `bundle exec rspec
spec/jobs/internal/check_new_versions_job_spec.rb
spec/jobs/internal/trigger_daily_scheduled_items_job_spec.rb
spec/configs/schedule_spec.rb`
- In a Rails console, run
`Internal::TriggerDailyScheduledItemsJob.perform_now` and verify
`Internal::CheckNewVersionsJob` is enqueued with a `wait_until` later
the same UTC day.
- In Super Admin settings, use Refresh and verify the version check
still runs immediately.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-17 02:27:49 -07:00
Muhsin KelothandGitHub a8d53a6df4 feat(linear): Support refresh tokens and migrate legacy OAuth tokens (#13721)
Linear is deprecating long-lived OAuth2 access tokens (valid for 10
years) in favor of short-lived access tokens with refresh tokens.
Starting October 1, 2025, all new OAuth2 apps will default to refresh
tokens. Linear will no longer issue long-lived access tokens. Please
read more details
[here](https://linear.app/developers/oauth-2-0-authentication#migrate-to-using-refresh-tokens)
We currently use long-lived tokens in our Linear integration (valid for
up to 10 years). To remain compatible, this PR ensures compatibility by
supporting refresh-token-based auth and migrating existing legacy
tokens.

Fixes
https://linear.app/chatwoot/issue/CW-5541/migrate-linear-oauth2-integration-to-support-refresh-tokens
2026-03-17 13:09:03 +04:00
2a90652f05 feat: Add draft status for help center locales (#13768)
This adds a draft status for Help Center locales so teams can prepare
localized content in the dashboard without exposing those locales in the
public portal switcher until they are ready to publish.

Fixes: https://github.com/chatwoot/chatwoot/issues/10412
Closes: https://github.com/chatwoot/chatwoot/issues/10412

## Why

Teams need a way to work on locale-specific Help Center content ahead of
launch. The public portal should only show ready locales, while the
admin dashboard should continue to expose every allowed locale for
ongoing article and category work.

## What this change does

- Adds `draft_locales` to portal config as a subset of `allowed_locales`
- Hides drafted locales from the public portal language switchers while
keeping direct locale URLs working
- Keeps drafted locales fully visible in the admin dashboard for article
and category management
- Adds locale actions to move an existing locale to draft, publish a
drafted locale, and keep the default locale protected from drafting
- Adds a status dropdown when creating a locale so new locales can be
created as `Published` or `Draft`
- Returns each admin locale with a `draft` flag so the locale UI can
reflect the public visibility state

## Validation

- Seed a portal with multiple locales, draft one locale, and confirm the
public portal switcher hides it while `/hc/:slug/:locale` still loads
directly
- In the admin dashboard, confirm drafted locales still appear in the
locale list and remain selectable for articles and categories
- Create a new locale with `Draft` status and confirm it stays out of
the public switcher until published
- Move an existing locale back and forth between `Published` and `Draft`
and confirm the public switcher updates accordingly


## Demo 



https://github.com/user-attachments/assets/ba22dc26-c2e7-463a-b1f5-adf1fda1f9be

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-17 12:45:54 +04:00
270f3c6a80 fix: slim help center search results (#13761)
Fixes help center public article search so query responses stay compact
and locale-scoped. Whitespace-only queries are now treated as empty in
both the portal UI and the server-side search path, and search
suggestions stay aligned with the trimmed query.

Fixes: https://github.com/chatwoot/chatwoot/issues/10402
Closes: https://github.com/chatwoot/chatwoot/issues/10402

## Why

The public help center search endpoint reused the full article
serializer for query responses, which returned much more data than the
search suggestions UI needed. That made responses heavier than necessary
and also surfaced nested portal and category data that made the results
look cross-locale.

Whitespace-only searches could also still reach the backend search path,
and in Enterprise that meant embedding search could be invoked for a
blank query.

## What changed

- return a compact search-specific payload for article query responses
- keep the existing full article serializer for normal article listing
responses
- preserve current-locale search behavior for the portal search flow
- trim whitespace-only search terms on the client so they do not open
suggestions or trigger a request
- reuse the normalized query on the backend so whitespace-only requests
are treated as empty searches in both OSS and Enterprise paths
- pass the trimmed search term into suggestions so highlighting matches
the actual query being sent
- add request and frontend regression coverage for compact payloads,
locale scoping, and whitespace-only search behavior

## Validation

1. Open `/hc/:portal/:locale` in the public help center.
2. Enter only spaces in the search box and confirm suggestions do not
open.
3. Search for a real term and confirm suggestions appear.
4. Verify the results are limited to the active locale.
5. Click a suggestion and confirm it opens the correct article page.
6. Inspect the query response and confirm it returns the compact search
payload instead of the full article serializer.

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-17 00:46:23 -07:00
ad1539c6cf fix(email): Allow inbox OAuth replies without global SMTP (#13820)
Email inbox replies now work for Google and Microsoft OAuth inboxes even
when the self-hosted instance does not have global SMTP configured. This
keeps agent replies working for email channels that already have valid
inbox-level delivery settings.

fixes: chatwoot/chatwoot#13118
closes: chatwoot/chatwoot#13118

## Why
Self-hosted email inbox replies were blocked by a global SMTP guard in
the `email_reply` path. For OAuth-backed email inboxes, outbound
delivery is configured at the inbox level, so the mailer returned early
and the reply flow failed before sending.

## What this change does
- Allows the `email_reply` path to proceed when the inbox has SMTP
configured
- Allows the `email_reply` path to proceed when the inbox has Google or
Microsoft OAuth delivery configured
- Renames the touched mailer helper predicates to `?` methods for
clarity

## Validation
- Configure a Google email inbox on a self-hosted instance without
global `SMTP_ADDRESS`
- Reply from Chatwoot to an existing email conversation
- Confirm the reply is sent through the inbox OAuth SMTP configuration
- Run `bundle exec rspec
spec/mailers/conversation_reply_mailer_spec.rb:595`

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-17 11:10:42 +04:00
349f55b558 fix: upgrade rollup to 4.59.0 to remediate CVE-2026-27606 (#13781)
https://linear.app/chatwoot/issue/CW-6595/vanta-remediate-high-vulnerabilities-identified-in-packages-are

## Description

- Added "rollup": ">=4.59.0" to pnpm.overrides in package.json
- This bumps rollup from 4.52.5 to 4.59.0 (the transitive dep via vite)

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- Overall Sanity via UI.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-16 23:12:04 -07:00
ef91b8bb42 fix(i18n): improve Ukrainian widget translation (#13819)
## Description

This PR improves the Ukrainian translation for the Chatwoot widget
(`app/javascript/widget/i18n/locale/uk.json`).

Key changes:
- Fixed typo: `Звантажити` → `Завантажити`
- Translated missing English strings
- Improved reply time messages
- Updated day names to match `{day}` usage in `BACK_ON_DAY`
- Improved UX wording in form placeholders
- Fixed typography in `ім’я`
- Improved consistency with other Chatwoot translations

These updates improve readability and correctness of the Ukrainian
widget interface.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Reviewed the updated translations and verified that:

- Ukrainian translations render correctly
- Reply time messages display properly
- `{day}` values work correctly with the `BACK_ON_DAY` message
- Form placeholders appear correctly
- No untranslated English strings remain

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] My changes generate no new warnings

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 22:38:08 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Shivam MishraSojan Jose
de4c837885 chore(deps): bump dompurify from 3.2.4 to 3.3.2 (#13738)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.2.4 to
3.3.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cure53/DOMPurify/releases">dompurify's
releases</a>.</em></p>
<blockquote>
<h2>DOMPurify 3.3.2</h2>
<ul>
<li>Fixed a possible bypass caused by jsdom's faulty raw-text tag
parsing, thanks multiple reporters</li>
<li>Fixed a prototype pollution issue when working with custom elements,
thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Fixed a lenient config parsing in <code>_isValidAttribute</code>,
thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Bumped and removed several dependencies, thanks <a
href="https://github.com/Rotzbua"><code>@​Rotzbua</code></a></li>
<li>Fixed the test suite after bumping dependencies, thanks <a
href="https://github.com/Rotzbua"><code>@​Rotzbua</code></a></li>
</ul>
<h2>DOMPurify 3.3.1</h2>
<ul>
<li>Updated <code>ADD_FORBID_CONTENTS</code> setting to extend default
list, thanks <a
href="https://github.com/MariusRumpf"><code>@​MariusRumpf</code></a></li>
<li>Updated the ESM import syntax to be more correct, thanks <a
href="https://github.com/binhpv"><code>@​binhpv</code></a></li>
</ul>
<h2>DOMPurify 3.3.0</h2>
<ul>
<li>Added the SVG <code>mask-type</code> attribute to default
allow-list, thanks <a
href="https://github.com/prasadrajandran"><code>@​prasadrajandran</code></a></li>
<li>Added support for <code>ADD_ATTR</code> and <code>ADD_TAGS</code> to
accept functions, thanks <a
href="https://github.com/nelstrom"><code>@​nelstrom</code></a></li>
<li>Fixed an issue with the <code>slot</code> element being in both SVG
and HTML allow-list, thanks <a
href="https://github.com/Wim-Valgaeren"><code>@​Wim-Valgaeren</code></a></li>
</ul>
<h2>DOMPurify 3.2.7</h2>
<ul>
<li>Added new attributes and elements to default allow-list, thanks <a
href="https://github.com/elrion018"><code>@​elrion018</code></a></li>
<li>Added <code>tagName</code> parameter to custom element
<code>attributeNameCheck</code>, thanks <a
href="https://github.com/nelstrom"><code>@​nelstrom</code></a></li>
<li>Added better check for animated <code>href</code> attributes, thanks
<a href="https://github.com/llamakko"><code>@​llamakko</code></a></li>
<li>Updated and improved the bundled types, thanks <a
href="https://github.com/ssi02014"><code>@​ssi02014</code></a></li>
<li>Updated several tests to better align with new browser encoding
behaviors</li>
<li>Improved the handling of potentially risky content inside CDATA
elements, thanks <a
href="https://github.com/securityMB"><code>@​securityMB</code></a> &amp;
<a href="https://github.com/terjanq"><code>@​terjanq</code></a></li>
<li>Improved the regular expression for raw-text elements to cover
textareas, thanks <a
href="https://github.com/securityMB"><code>@​securityMB</code></a> &amp;
<a href="https://github.com/terjanq"><code>@​terjanq</code></a></li>
</ul>
<h2>DOMPurify 3.2.6</h2>
<ul>
<li>Fixed several typos and removed clutter from our documentation,
thanks <a
href="https://github.com/Rotzbua"><code>@​Rotzbua</code></a></li>
<li>Added <code>matrix:</code> as an allowed URI scheme, thanks <a
href="https://github.com/kleinesfilmroellchen"><code>@​kleinesfilmroellchen</code></a></li>
<li>Added better config hardening against prototype pollution, thanks <a
href="https://github.com/EffectRenan"><code>@​EffectRenan</code></a></li>
<li>Added better handling of attribute removal, thanks <a
href="https://github.com/michalnieruchalski-tiugo"><code>@​michalnieruchalski-tiugo</code></a></li>
<li>Added better configuration for aggressive mXSS scrubbing behavior,
thanks <a
href="https://github.com/BryanValverdeU"><code>@​BryanValverdeU</code></a></li>
<li>Removed the script that caused the fake entry <a
href="https://security.snyk.io/vuln/SNYK-JS-DOMPURIFY-10176060">CVE-2025-48050</a></li>
</ul>
<h2>DOMPurify 3.2.5</h2>
<ul>
<li>Added a check to the mXSS detection regex to be more strict, thanks
<a
href="https://github.com/masatokinugawa"><code>@​masatokinugawa</code></a></li>
<li>Added ESM type imports in source, removes patch function, thanks <a
href="https://github.com/donmccurdy"><code>@​donmccurdy</code></a></li>
<li>Added script to verify various TypeScript configurations, thanks <a
href="https://github.com/reduckted"><code>@​reduckted</code></a></li>
<li>Added more modern browsers to the Karma launchers list</li>
<li>Added Node 23.x to tested runtimes, removed Node 17.x</li>
<li>Fixed the generation of source maps, thanks <a
href="https://github.com/reduckted"><code>@​reduckted</code></a></li>
<li>Fixed an unexpected behavior with <code>ALLOWED_URI_REGEXP</code>
using the 'g' flag, thanks <a
href="https://github.com/hhk-png"><code>@​hhk-png</code></a></li>
<li>Fixed a few typos in the README file</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cure53/DOMPurify/commit/5e56114cb24079ce52dbc51f76e494b77afa5153"><code>5e56114</code></a>
Getting 3.x branch ready for 3.3.2 release (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1208">#1208</a>)</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/e8c95f4a27aa8b041f92b59ab7685a94f7be6208"><code>e8c95f4</code></a>
fix: Fixed the broken package-lock.json</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/9636037c145b769dad0b52da8313301cbf867f46"><code>9636037</code></a>
Update package-lock.json</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/5cad4cecf2e647ac66eed25bc02a2415f00dbc8b"><code>5cad4ce</code></a>
Getting 3.x branch ready for 3.3.2 releas (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1205">#1205</a>)</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/6fc446a589ab3d1d72ae2a5b71167ba38dbd3096"><code>6fc446a</code></a>
Merge pull request <a
href="https://redirect.github.com/cure53/DOMPurify/issues/1175">#1175</a>
from cure53/main</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/3b3bf917d2b39460de6d130acebdc9243cf3e6ae"><code>3b3bf91</code></a>
Merge branch 'main' of github.com:cure53/DOMPurify</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/9863f4195bae6048de9eb2802219218c6904066c"><code>9863f41</code></a>
chore: Preparing 3.3.1 release</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/b4e02954dc4172c3944a755f3e99fbb76be64f7b"><code>b4e0295</code></a>
chore: Preparing 3.3.0 release</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/077746bb2cfb77836dfb628dca7ffc7ced8a5356"><code>077746b</code></a>
build(deps-dev): bump js-yaml from 4.1.0 to 4.1.1 (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1170">#1170</a>)</li>
<li><a
href="https://github.com/cure53/DOMPurify/commit/4de68bba9aba43dc3bba9348df603b64fc06d591"><code>4de68bb</code></a>
build(deps): bump actions/checkout from 5 to 6 (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1171">#1171</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/cure53/DOMPurify/compare/3.2.4...3.3.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dompurify&package-manager=npm_and_yarn&previous-version=3.2.4&new-version=3.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/chatwoot/chatwoot/network/alerts).

</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 21:54:32 -07:00
a62beffeef fix(i18n): complete zh_TW locale coverage (#13792)
This updates the Traditional Chinese (`zh_TW`) locale coverage across
Chatwoot so the app no longer falls back to English for missing backend,
dashboard, widget, and survey strings.

## How to test

1. Start Chatwoot locally and switch the UI locale to Traditional
Chinese (`zh_TW`).
2. Walk through the main product areas: dashboard, settings, inbox
management, help center, automations, reports, widget, and survey flows.
3. Confirm the UI surfaces translated Traditional Chinese copy instead
of English fallbacks.
4. Spot-check newly added locale surfaces such as secure password
messaging and snooze UI copy.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 18:47:22 -07:00
Denis PetrovandGitHub b8f6fe5bb7 feat: Bulgarian locale updates(#13635)
Bulgarian locale updates
2026-03-16 17:47:25 -07:00
b866886b55 feat(i18n): complete Korean (ko) translations to 100% coverage (#13583)
Translate all English strings to Korean across 41 frontend locale files
and 2 backend locale files. Add structurally missing keys and translate
existing keys that were left in English.

# Pull Request Template

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] 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?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 16:54:26 -07:00
b88236e86e chore(i18n): update Russian translations (#13405)
# Pull Request Template

## Description

Updated few i18n files to:
1. fix typos / grammar / punctuation
2. translate strings that were still in english
3. add missing keys

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

i18n change, the format remained the same.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 16:10:16 -07:00
11ee741716 chore: Update translations (#13227)
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-16 15:44:32 -07:00
Aakash BakhleandGitHub ac93290c9a fix: skip captain auto-open for templates (#13802)
# Pull Request Template

## Description

WhatsApp template messages are treated as outgoing human messages so
conversations are automatically marked Open, preventing Captain from
responding. #13673

This PR fixes the behaviour for template messages, so that captain can
respond to them.

## Type of change


- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-16 18:54:12 +05:30
03719cede0 fix: Correct reversed message status indicators for API channel (#13594)
## Description

Fixes the reversed message delivery status indicators for the API
channel. The API inbox was grouped with the web widget inbox in the
`isDelivered` computed property, causing both to treat a `sent` status
as `delivered`. Since the API channel provides real
`sent`/`delivered`/`read` status values from external systems (unlike
the web widget which has no separate delivery confirmation), the API
inbox needs its own handling.

**Before this fix:**
- Status `sent` (0) → incorrectly showed delivered checkmarks
- Status `delivered` (1) → incorrectly showed "Sending" spinner

**After this fix:**
- Status `sent` → correctly shows sent indicator (single checkmark)
- Status `delivered` → correctly shows delivered indicator (double
checkmarks)
- Status `read` → unchanged (already worked correctly)

The web widget inbox behavior is unchanged — it still treats `sent` as
`delivered` since it lacks a separate delivery confirmation mechanism.

Fixes #13576

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Verified by code review that the computed properties now correctly map
API channel message statuses:
- `isSent` returns `true` when `status === 'sent'` for API inbox
- `isDelivered` returns `true` when `status === 'delivered'` for API
inbox
- `isRead` unchanged — already checks `status === 'read'` for API inbox
- Web widget inbox logic is unchanged

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] My changes generate no new warnings

*This PR was created with the assistance of Claude Opus 4.6 by
Anthropic. Happy to make any adjustments! Reviewed and submitted by a
human.*

Co-authored-by: Your Name <your-email@example.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-16 13:21:18 +04:00
a5c50354fc feat: trigger assignment on resolve (#13780)
## Description

When an agent resolves or snoozes a conversation, their capacity frees
up — but under Assignment V2, no new conversation was assigned until the
next event triggered the assignment job. This meant agents could sit
idle despite having queued conversations waiting. This change triggers
the AssignmentJob immediately on resolve/snooze so freed capacity is
utilized right away.

## Type of change

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

## How Has This Been Tested?

- Enable auto assignment v2 on an inbox
- Create a conversation (gets auto-assigned to an available agent)
- Resolve the conversation
- Verify that another unassigned conversation in the inbox gets assigned
to the freed-up agent

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: tds-1 <tds-1@users.noreply.github.com>
2026-03-16 13:13:37 +05:30
a452ce9e84 feat(whatsapp): add webhook registration and status endpoints (#13551)
## Description

Adds webhook configuration management for WhatsApp Cloud API channels,
allowing administrators to check webhook status and register webhooks
directly from Chatwoot without accessing Meta Business Manager.

## Type of change

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


## Screenshots

<img width="1130" height="676" alt="Screenshot 2026-03-05 at 7 04 18 PM"
src="https://github.com/user-attachments/assets/f5dcd9dd-8827-42c5-a52b-1024012703c2"
/>
<img width="1101" height="651" alt="Screenshot 2026-03-05 at 7 04 29 PM"
src="https://github.com/user-attachments/assets/e0bd59f9-2a90-4f24-87c0-b79f21e721ee"
/>



## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-03-16 12:48:16 +05:30
Tanmay Deep SharmaandGitHub 28bf9fa5f9 fix: upgrade markdown-it to 14.1.1 to remediate CVE-2026-2327 (#13782)
## Linear tickets
-
https://linear.app/chatwoot/issue/CW-6607/vanta-remediate-medium-vulnerabilities-identified-in-packages-are
-
https://linear.app/chatwoot/issue/CW-6612/vanta-remediate-medium-vulnerabilities-identified-in-packages-are

## Description

Upgrades markdown-it from 13.0.2 to 14.1.1 to remediate CVE-2026-2327

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- Sanity testing of golden flows via UI

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] 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
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2026-03-16 11:11:19 +05:30
Shivam MishraandGitHub 73a90f2841 feat: update bunny video support in HC (#13815)
Bunny Video has added a new URL player.mediadelivery.net, this PR adds
support for the new URL
2026-03-16 11:04:27 +05:30
Aakash BakhleandGitHub a90ffe6264 feat: Add force legacy auto-resolve flag (#13804)
# Pull Request Template

## Description

Add account setting and store_accessor for
`captain_force_legacy_auto_resolve`.
Enterprise job now skips LLM evaluation when this flag is true and falls
back to legacy time-based resolution. Add spec to cover the fallback.


## Type of change

We recently rolled out Captain deciding if a conversation is resolved or
not. While it is an improvement for majority of customers, some still
prefer the old way of auto-resolving based on inactivity. This PR adds a
check.

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

legacy_auto_resolve = true

<img width="1282" height="848" alt="CleanShot 2026-03-13 at 19 55 55@2x"
src="https://github.com/user-attachments/assets/dfdcc5d5-6d21-462b-87a6-a5e1b1290a8b"
/>


legacy_auto_resolve = false
<img width="1268" height="864" alt="CleanShot 2026-03-13 at 20 00 50@2x"
src="https://github.com/user-attachments/assets/f4719ec6-922a-4c3b-bc45-7b29eaced565"
/>



## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] 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
- [x] Any dependent changes have been merged and published in downstream
modules
2026-03-13 15:04:58 -07:00
Alexander UdovichenkoandGitHub 412b72db7c fix: Delete double hmac check (#12464)
## Description

When hmac identity check is enabled according to
[this](https://www.chatwoot.com/hc/user-guide/articles/1677587479-how-to-enable-identity-validation-in-chatwoot)
I found out, that it checked twice.

If `should_verify_hmac? -> true` then hmac checked in `before_action`
and we don't need to do it again later.

This perfomance related and PR fixes this.
2026-03-13 02:30:17 -07:00
Shivam Mishra 79b18e7009 Merge branch 'hotfix/4.11.2' 2026-03-09 21:19:50 +05:30
1703 changed files with 81079 additions and 40838 deletions
+1
View File
@@ -1,3 +1,4 @@
---
ignore:
- CVE-2021-41098 # https://github.com/chatwoot/chatwoot/issues/3097 (update once azure blob storage is updated)
- GHSA-57hq-95w6-v4fc # Devise confirmable race condition — patched locally in User model (remove once on Devise 5+)
+2 -2
View File
@@ -166,7 +166,7 @@ GEM
multi_json (~> 1)
statsd-ruby (~> 1.1)
base64 (0.3.0)
bcrypt (3.1.20)
bcrypt (3.1.22)
benchmark (0.4.1)
bigdecimal (3.2.2)
bindex (0.8.1)
@@ -465,7 +465,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.18.1)
json (2.19.2)
json_refs (0.1.8)
hana
json_schemer (0.2.24)
+1 -1
View File
@@ -1 +1 @@
4.11.2
4.12.1
@@ -57,7 +57,7 @@ class Api::V1::Accounts::Captain::TasksController < Api::V1::Accounts::BaseContr
if result.nil?
render json: { message: nil }
elsif result[:error]
render json: { error: result[:error] }, status: :unprocessable_entity
render json: { error: result[:error] }, status: :unprocessable_content
else
response_data = { message: result[:message] }
response_data[:follow_up_context] = result[:follow_up_context] if result[:follow_up_context]
@@ -69,3 +69,5 @@ class Api::V1::Accounts::Captain::TasksController < Api::V1::Accounts::BaseContr
authorize(:'captain/tasks')
end
end
Api::V1::Accounts::Captain::TasksController.prepend_mod_with('Api::V1::Accounts::Captain::TasksController')
@@ -0,0 +1,55 @@
module Api::V1::Accounts::Concerns::WhatsappHealthManagement
extend ActiveSupport::Concern
included do
skip_before_action :check_authorization, only: [:health, :register_webhook]
before_action :check_admin_authorization?, only: [:register_webhook]
before_action :validate_whatsapp_cloud_channel, only: [:health, :register_webhook]
end
def sync_templates
return render status: :unprocessable_entity, json: { error: 'Template sync is only available for WhatsApp channels' } unless whatsapp_channel?
trigger_template_sync
render status: :ok, json: { message: 'Template sync initiated successfully' }
rescue StandardError => e
render status: :internal_server_error, json: { error: e.message }
end
def health
health_data = Whatsapp::HealthService.new(@inbox.channel).fetch_health_status
render json: health_data
rescue StandardError => e
Rails.logger.error "[INBOX HEALTH] Error fetching health data: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
end
def register_webhook
Whatsapp::WebhookSetupService.new(@inbox.channel).register_callback
render json: { message: 'Webhook registered successfully' }, status: :ok
rescue StandardError => e
Rails.logger.error "[INBOX WEBHOOK] Webhook registration failed: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
end
private
def validate_whatsapp_cloud_channel
return if @inbox.channel.is_a?(Channel::Whatsapp) && @inbox.channel.provider == 'whatsapp_cloud'
render json: { error: 'Health data only available for WhatsApp Cloud API channels' }, status: :bad_request
end
def whatsapp_channel?
@inbox.whatsapp? || (@inbox.twilio? && @inbox.channel.whatsapp?)
end
def trigger_template_sync
if @inbox.whatsapp?
Channels::Whatsapp::TemplatesSyncJob.perform_later(@inbox.channel)
elsif @inbox.twilio? && @inbox.channel.whatsapp?
Channels::Twilio::TemplatesSyncJob.perform_later(@inbox.channel)
end
end
end
@@ -4,8 +4,9 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
before_action :fetch_agent_bot, only: [:set_agent_bot]
before_action :validate_limit, only: [:create]
# we are already handling the authorization in fetch inbox
before_action :check_authorization, except: [:show, :health]
before_action :validate_whatsapp_cloud_channel, only: [:health]
before_action :check_authorization, except: [:show]
include Api::V1::Accounts::Concerns::WhatsappHealthManagement
def index
@inboxes = policy_scope(Current.account.inboxes.order_by_name.includes(:channel, { avatar_attachment: [:blob] }))
@@ -70,23 +71,6 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
render status: :ok, json: { message: I18n.t('messages.inbox_deletetion_response') }
end
def sync_templates
return render status: :unprocessable_entity, json: { error: 'Template sync is only available for WhatsApp channels' } unless whatsapp_channel?
trigger_template_sync
render status: :ok, json: { message: 'Template sync initiated successfully' }
rescue StandardError => e
render status: :internal_server_error, json: { error: e.message }
end
def health
health_data = Whatsapp::HealthService.new(@inbox.channel).fetch_health_status
render json: health_data
rescue StandardError => e
Rails.logger.error "[INBOX HEALTH] Error fetching health data: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
end
private
def fetch_inbox
@@ -98,12 +82,6 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
@agent_bot = AgentBot.find(params[:agent_bot]) if params[:agent_bot]
end
def validate_whatsapp_cloud_channel
return if @inbox.channel.is_a?(Channel::Whatsapp) && @inbox.channel.provider == 'whatsapp_cloud'
render json: { error: 'Health data only available for WhatsApp Cloud API channels' }, status: :bad_request
end
def create_channel
return unless allowed_channel_types.include?(permitted_params[:channel][:type])
@@ -200,18 +178,6 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController
def get_channel_attributes(channel_type)
channel_type.constantize.const_defined?(:EDITABLE_ATTRS) ? channel_type.constantize::EDITABLE_ATTRS.presence : []
end
def whatsapp_channel?
@inbox.whatsapp? || (@inbox.twilio? && @inbox.channel.whatsapp?)
end
def trigger_template_sync
if @inbox.whatsapp?
Channels::Whatsapp::TemplatesSyncJob.perform_later(@inbox.channel)
elsif @inbox.twilio? && @inbox.channel.whatsapp?
Channels::Twilio::TemplatesSyncJob.perform_later(@inbox.channel)
end
end
end
Api::V1::Accounts::InboxesController.prepend_mod_with('Api::V1::Accounts::InboxesController')
@@ -126,7 +126,7 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
return unless @hook&.access_token
begin
linear_client = Linear.new(@hook.access_token)
linear_client = Linear.new(@hook.access_token, refresh_token: @hook.settings&.[]('refresh_token'))
linear_client.revoke_token
rescue StandardError => e
Rails.logger.error "Failed to revoke Linear token: #{e.message}"
@@ -79,7 +79,7 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController
def portal_params
params.require(:portal).permit(
:id, :color, :custom_domain, :header_text, :homepage_link,
:name, :page_title, :slug, :archived, { config: [:default_locale, { allowed_locales: [] }] }
:name, :page_title, :slug, :archived, { config: [:default_locale, { allowed_locales: [] }, { draft_locales: [] }] }
)
end
@@ -19,7 +19,7 @@ class Api::V1::Widget::ContactsController < Api::V1::Widget::BaseController
contact = @contact
end
@contact_inbox.update(hmac_verified: true) if should_verify_hmac? && valid_hmac?
@contact_inbox.update(hmac_verified: true) if should_verify_hmac?
identify_contact(contact)
end
+39 -12
View File
@@ -2,6 +2,8 @@ class Linear::CallbacksController < ApplicationController
include Linear::IntegrationHelper
def show
return redirect_to(safe_linear_redirect_uri) if params[:code].blank? || account_id.blank?
@response = oauth_client.auth_code.get_token(
params[:code],
redirect_uri: "#{base_url}/linear/callback"
@@ -10,7 +12,7 @@ class Linear::CallbacksController < ApplicationController
handle_response
rescue StandardError => e
Rails.logger.error("Linear callback error: #{e.message}")
redirect_to linear_redirect_uri
redirect_to safe_linear_redirect_uri
end
private
@@ -31,22 +33,19 @@ class Linear::CallbacksController < ApplicationController
end
def handle_response
hook = account.hooks.new(
raise ArgumentError, 'Missing access token in Linear OAuth response' if parsed_body['access_token'].blank?
hook = account.hooks.find_or_initialize_by(app_id: 'linear')
hook.assign_attributes(
access_token: parsed_body['access_token'],
status: 'enabled',
app_id: 'linear',
settings: {
token_type: parsed_body['token_type'],
expires_in: parsed_body['expires_in'],
scope: parsed_body['scope']
}
settings: merged_integration_settings(hook.settings)
)
# You may wonder why we're not handling the refresh token update, since the token will expire only after 10 years, https://github.com/linear/linear/issues/251
hook.save!
redirect_to linear_redirect_uri
rescue StandardError => e
Rails.logger.error("Linear callback error: #{e.message}")
redirect_to linear_redirect_uri
redirect_to safe_linear_redirect_uri
end
def account
@@ -54,19 +53,47 @@ class Linear::CallbacksController < ApplicationController
end
def account_id
return unless params[:state]
return @account_id if instance_variable_defined?(:@account_id)
verify_linear_token(params[:state])
@account_id = params[:state].present? ? verify_linear_token(params[:state]) : nil
end
def linear_redirect_uri
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{account.id}/settings/integrations/linear"
end
def safe_linear_redirect_uri
return base_url if account_id.blank?
linear_redirect_uri
rescue StandardError
base_url
end
def parsed_body
@parsed_body ||= @response.response.parsed
end
def integration_settings
{
token_type: parsed_body['token_type'],
expires_in: parsed_body['expires_in'],
expires_on: expires_on,
scope: parsed_body['scope'],
refresh_token: parsed_body['refresh_token']
}.compact
end
def merged_integration_settings(existing_settings)
existing_settings.to_h.with_indifferent_access.merge(integration_settings)
end
def expires_on
return if parsed_body['expires_in'].blank?
(Time.current.utc + parsed_body['expires_in'].to_i.seconds).to_s
end
def base_url
ENV.fetch('FRONTEND_URL', 'http://localhost:3000')
end
@@ -0,0 +1,101 @@
class Platform::Api::V1::EmailChannelMigrationsController < PlatformController
before_action :set_account
before_action :validate_account_permissible
before_action :validate_feature_flag
before_action :validate_params
def create
results = migrate_email_channels
render json: { results: results }, status: :ok
end
private
def set_account
@account = Account.find(params[:account_id])
end
def validate_account_permissible
return if @platform_app.platform_app_permissibles.find_by(permissible: @account)
render json: { error: 'Non permissible resource' }, status: :unauthorized
end
def validate_feature_flag
return if ActiveModel::Type::Boolean.new.cast(ENV.fetch('EMAIL_CHANNEL_MIGRATION', false))
render json: { error: 'Email channel migration is not enabled' }, status: :forbidden
end
def validate_params
return render json: { error: 'Missing migrations parameter' }, status: :unprocessable_entity if migration_params.blank?
return unless migration_params.size > MAX_MIGRATIONS
return render json: { error: "Too many migrations (max #{MAX_MIGRATIONS})" },
status: :unprocessable_entity
end
def migrate_email_channels
migration_params.map { |entry| migrate_single(entry) }
end
MAX_MIGRATIONS = 25
SUPPORTED_PROVIDERS = %w[google microsoft].freeze
def migrate_single(entry)
validate_provider!(entry[:provider])
ActiveRecord::Base.transaction do
channel = create_channel(entry)
inbox = create_inbox(channel, entry)
{ email: entry[:email], inbox_id: inbox.id, channel_id: channel.id, status: 'success' }
end
rescue StandardError => e
{ email: entry[:email], status: 'error', message: e.message }
end
def create_channel(entry)
Channel::Email.create!(
account_id: @account.id,
email: entry[:email],
provider: entry[:provider],
provider_config: entry[:provider_config]&.to_h,
imap_enabled: entry.fetch(:imap_enabled, true),
imap_address: entry[:imap_address] || default_imap_address(entry[:provider]),
imap_port: entry[:imap_port] || 993,
imap_login: entry[:imap_login] || entry[:email],
imap_enable_ssl: entry.fetch(:imap_enable_ssl, true)
)
end
def create_inbox(channel, entry)
@account.inboxes.create!(
name: entry[:inbox_name] || "Migrated #{entry[:provider]&.capitalize}: #{entry[:email]}",
channel: channel
)
end
def validate_provider!(provider)
return if SUPPORTED_PROVIDERS.include?(provider)
raise ArgumentError, "Unsupported provider '#{provider}'. Must be one of: #{SUPPORTED_PROVIDERS.join(', ')}"
end
def default_imap_address(provider)
case provider
when 'google' then 'imap.gmail.com'
when 'microsoft' then 'outlook.office365.com'
else ''
end
end
def migration_params
params.permit(migrations: [
:email, :provider, :inbox_name,
:imap_enabled, :imap_address, :imap_port, :imap_login, :imap_enable_ssl,
{ provider_config: {} }
])[:migrations]
end
end
@@ -6,6 +6,7 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B
layout 'portal'
def index
@search_query = list_params[:query]
@articles = @portal.articles.published.includes(:category, :author)
@articles = @articles.where(locale: permitted_params[:locale]) if permitted_params[:locale].present?
@@ -73,7 +74,9 @@ class Public::Api::V1::Portals::ArticlesController < Public::Api::V1::Portals::B
end
def list_params
params.permit(:query, :locale, :sort, :status, :page, :per_page)
@list_params ||= params.permit(:query, :locale, :sort, :status, :page, :per_page).tap do |permitted|
permitted[:query] = permitted[:query].to_s.strip.presence
end
end
def permitted_params
+11 -1
View File
@@ -77,13 +77,23 @@ class WidgetsController < ActionController::Base
end
def allow_iframe_requests
if @web_widget.allowed_domains.blank?
if @web_widget.allowed_domains.blank? || embedded_from_non_web_origin?
response.headers.delete('X-Frame-Options')
else
domains = @web_widget.allowed_domains.split(',').map(&:strip).join(' ')
response.headers['Content-Security-Policy'] = "frame-ancestors #{domains}"
end
end
# Mobile WebViews (iOS/Android) load content from file:// or null origins,
# which cannot match any domain in frame-ancestors. When the per-inbox flag
# is enabled, skip frame-ancestors for these requests.
def embedded_from_non_web_origin?
return false unless @web_widget.allow_mobile_webview?
origin = request.headers['Origin']
origin.blank? || origin == 'null' || origin&.start_with?('file://')
end
end
WidgetsController.prepend_mod_with('WidgetsController')
+6
View File
@@ -1,4 +1,10 @@
module TimezoneHelper
def timezone_name_from_params(timezone, offset)
return timezone if timezone.present? && ActiveSupport::TimeZone[timezone].present?
timezone_name_from_offset(offset)
end
# ActiveSupport TimeZone is not aware of the current time, so ActiveSupport::Timezone[offset]
# would return the timezone without considering day light savings. To get the correct timezone,
# this method uses zone.now.utc_offset for comparison as referenced in the issues below
@@ -9,6 +9,10 @@ class InboxHealthAPI extends ApiClient {
getHealthStatus(inboxId) {
return axios.get(`${this.url}/${inboxId}/health`);
}
registerWebhook(inboxId) {
return axios.post(`${this.url}/${inboxId}/register_webhook`);
}
}
export default new InboxHealthAPI();
@@ -26,6 +26,7 @@ const onPortalCreate = ({ slug: portalSlug, locale }) => {
<EmptyStateLayout
:title="$t('HELP_CENTER.TITLE')"
:subtitle="$t('HELP_CENTER.NEW_PAGE.DESCRIPTION')"
class="bg-n-surface-1"
>
<template #empty-state-item>
<div class="grid grid-cols-2 gap-4 p-px">
@@ -1,8 +1,22 @@
<script setup>
import LocaleCard from './LocaleCard.vue';
const locales = [
{ name: 'English', isDefault: true, articleCount: 29, categoryCount: 5 },
{ name: 'Spanish', isDefault: false, articleCount: 29, categoryCount: 5 },
{
name: 'English',
code: 'en',
isDefault: true,
isDraft: false,
articleCount: 29,
categoryCount: 5,
},
{
name: 'Spanish',
code: 'es',
isDefault: false,
isDraft: true,
articleCount: 29,
categoryCount: 5,
},
];
</script>
@@ -19,6 +33,8 @@ const locales = [
<LocaleCard
:locale="locale.name"
:is-default="locale.isDefault"
:is-draft="locale.isDraft"
:locale-code="locale.code"
:article-count="locale.articleCount"
:category-count="locale.categoryCount"
/>
@@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useToggle } from '@vueuse/core';
import { LOCALE_MENU_ITEMS } from 'dashboard/helper/portalHelper';
import { buildLocaleMenuItems } from 'dashboard/helper/portalHelper';
import CardLayout from 'dashboard/components-next/CardLayout.vue';
import Button from 'dashboard/components-next/button/Button.vue';
@@ -17,6 +17,10 @@ const props = defineProps({
type: Boolean,
required: true,
},
isDraft: {
type: Boolean,
required: true,
},
localeCode: {
type: String,
required: true,
@@ -37,11 +41,28 @@ const { t } = useI18n();
const [showDropdownMenu, toggleDropdown] = useToggle();
const localeLabel = computed(() => `${props.locale} (${props.localeCode})`);
const localeMenuLabels = computed(() => ({
'change-default': t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.MAKE_DEFAULT'
),
'move-to-draft': t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.MOVE_TO_DRAFT'
),
'publish-locale': t(
'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.PUBLISH_LOCALE'
),
delete: t('HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.DELETE'),
}));
const localeMenuItems = computed(() =>
LOCALE_MENU_ITEMS.map(item => ({
buildLocaleMenuItems({
isDefault: props.isDefault,
isDraft: props.isDraft,
}).map(item => ({
...item,
label: t(item.label),
disabled: props.isDefault,
label: localeMenuLabels.value[item.action],
}))
);
@@ -56,7 +77,7 @@ const handleAction = ({ action, value }) => {
<div class="flex justify-between gap-2">
<div class="flex items-center justify-start gap-2">
<span class="text-sm font-medium text-n-slate-12 line-clamp-1">
{{ locale }} ({{ localeCode }})
{{ localeLabel }}
</span>
<span
v-if="isDefault"
@@ -64,6 +85,12 @@ const handleAction = ({ action, value }) => {
>
{{ $t('HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DEFAULT') }}
</span>
<span
v-else-if="isDraft"
class="bg-n-alpha-2 h-6 inline-flex items-center justify-center rounded-md text-xs border-px border-transparent text-n-slate-11 px-2 py-0.5"
>
{{ $t('HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DRAFT') }}
</span>
</div>
<div class="flex items-center justify-end gap-4">
<div class="flex items-center gap-4">
@@ -86,6 +113,7 @@ const handleAction = ({ action, value }) => {
</span>
</div>
<div
v-if="localeMenuItems.length"
v-on-clickaway="() => toggleDropdown(false)"
class="relative group"
>
@@ -1,5 +1,5 @@
<script setup>
import { ref, computed } from 'vue';
import { ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useStore } from 'dashboard/composables/store';
import { useAlert, useTrack } from 'dashboard/composables';
@@ -24,12 +24,20 @@ const dialogRef = ref(null);
const isUpdating = ref(false);
const selectedLocale = ref('');
const localeStatus = ref('published');
const addedLocales = computed(() => {
const { allowed_locales: allowedLocales = [] } = props.portal?.config || {};
return allowedLocales.map(locale => locale.code);
});
const draftedLocales = computed(() => {
const { allowed_locales: allowedLocales = [] } = props.portal?.config || {};
return allowedLocales
.filter(locale => locale.draft)
.map(locale => locale.code);
});
const locales = computed(() => {
return Object.keys(allLocales)
.map(key => {
@@ -41,17 +49,44 @@ const locales = computed(() => {
.filter(locale => !addedLocales.value.includes(locale.value));
});
const statusOptions = computed(() => [
{
value: 'published',
label: t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.STATUS.OPTIONS.LIVE'),
},
{
value: 'draft',
label: t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.STATUS.OPTIONS.DRAFT'),
},
]);
const resetForm = () => {
selectedLocale.value = '';
localeStatus.value = 'published';
};
watch(localeStatus, value => {
if (!value) {
localeStatus.value = 'published';
}
});
const onCreate = async () => {
if (!selectedLocale.value) return;
isUpdating.value = true;
const updatedLocales = [...addedLocales.value, selectedLocale.value];
const updatedDraftLocales =
localeStatus.value === 'draft'
? [...new Set([...draftedLocales.value, selectedLocale.value])]
: draftedLocales.value;
try {
await store.dispatch('portals/update', {
portalSlug: props.portal?.slug,
config: {
allowed_locales: updatedLocales,
draft_locales: updatedDraftLocales,
default_locale: props.portal?.meta?.default_locale,
},
});
@@ -62,7 +97,7 @@ const onCreate = async () => {
from: route.name,
});
selectedLocale.value = '';
resetForm();
dialogRef.value?.close();
useAlert(
t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.API.SUCCESS_MESSAGE')
@@ -87,6 +122,7 @@ defineExpose({ dialogRef });
type="edit"
:title="t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.TITLE')"
:description="t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.DESCRIPTION')"
@close="resetForm"
@confirm="onCreate"
>
<div class="flex flex-col gap-6">
@@ -98,6 +134,16 @@ defineExpose({ dialogRef });
"
class="[&>div>button:not(.focused)]:!outline-n-slate-5 [&>div>button:not(.focused)]:dark:!outline-n-slate-5"
/>
<div class="flex flex-col gap-2">
<span class="text-sm font-medium text-n-slate-12">
{{ t('HELP_CENTER.LOCALES_PAGE.ADD_LOCALE_DIALOG.STATUS.LABEL') }}
</span>
<ComboBox
v-model="localeStatus"
:options="statusOptions"
class="[&>div>button:not(.focused)]:!outline-n-slate-5 [&>div>button:not(.focused)]:dark:!outline-n-slate-5"
/>
</div>
</div>
</Dialog>
</template>
@@ -29,6 +29,7 @@ const isLocaleDefault = code => {
const updatePortalLocales = async ({
newAllowedLocales,
newDraftLocales,
defaultLocale,
messageKey,
}) => {
@@ -39,6 +40,7 @@ const updatePortalLocales = async ({
config: {
default_locale: defaultLocale,
allowed_locales: newAllowedLocales,
draft_locales: newDraftLocales,
},
});
@@ -53,8 +55,12 @@ const updatePortalLocales = async ({
const changeDefaultLocale = ({ localeCode }) => {
const newAllowedLocales = props.locales.map(locale => locale.code);
const newDraftLocales = props.locales
.filter(locale => locale.isDraft)
.map(locale => locale.code);
updatePortalLocales({
newAllowedLocales,
newDraftLocales,
defaultLocale: localeCode,
messageKey: 'CHANGE_DEFAULT_LOCALE',
});
@@ -81,11 +87,15 @@ const deletePortalLocale = async ({ localeCode }) => {
const updatedLocales = props.locales
.filter(locale => locale.code !== localeCode)
.map(locale => locale.code);
const updatedDraftLocales = props.locales
.filter(locale => locale.code !== localeCode && locale.isDraft)
.map(locale => locale.code);
const defaultLocale = props.portal.meta.default_locale;
await updatePortalLocales({
newAllowedLocales: updatedLocales,
newDraftLocales: updatedDraftLocales,
defaultLocale,
messageKey: 'DELETE_LOCALE',
});
@@ -98,9 +108,46 @@ const deletePortalLocale = async ({ localeCode }) => {
});
};
const updateDraftLocales = async ({ localeCode, shouldDraft, messageKey }) => {
const newAllowedLocales = props.locales.map(locale => locale.code);
const currentDraftLocales = props.locales
.filter(locale => locale.isDraft)
.map(locale => locale.code);
const newDraftLocales = shouldDraft
? [...new Set([...currentDraftLocales, localeCode])]
: currentDraftLocales.filter(locale => locale !== localeCode);
await updatePortalLocales({
newAllowedLocales,
newDraftLocales,
defaultLocale: props.portal.meta.default_locale,
messageKey,
});
};
const moveLocaleToDraft = async ({ localeCode }) => {
await updateDraftLocales({
localeCode,
shouldDraft: true,
messageKey: 'DRAFT_LOCALE',
});
};
const publishLocale = async ({ localeCode }) => {
await updateDraftLocales({
localeCode,
shouldDraft: false,
messageKey: 'PUBLISH_LOCALE',
});
};
const handleAction = ({ action }, localeCode) => {
if (action === 'change-default') {
changeDefaultLocale({ localeCode: localeCode });
} else if (action === 'move-to-draft') {
moveLocaleToDraft({ localeCode: localeCode });
} else if (action === 'publish-locale') {
publishLocale({ localeCode: localeCode });
} else if (action === 'delete') {
deletePortalLocale({ localeCode: localeCode });
}
@@ -114,6 +161,7 @@ const handleAction = ({ action }, localeCode) => {
:key="index"
:locale="locale.name"
:is-default="isLocaleDefault(locale.code)"
:is-draft="locale.isDraft"
:locale-code="locale.code"
:article-count="locale.articlesCount || 0"
:category-count="locale.categoriesCount || 0"
@@ -4,37 +4,49 @@ import LocalesPage from './LocalesPage.vue';
const locales = [
{
name: 'English (en-US)',
code: 'en',
isDefault: true,
isDraft: false,
articleCount: 5,
categoryCount: 5,
},
{
name: 'Spanish (es-ES)',
code: 'es',
isDefault: false,
isDraft: true,
articleCount: 20,
categoryCount: 10,
},
{
name: 'English (en-UK)',
code: 'en_GB',
isDefault: false,
isDraft: false,
articleCount: 15,
categoryCount: 7,
},
{
name: 'Malay (ms-MY)',
code: 'ms',
isDefault: false,
isDraft: false,
articleCount: 15,
categoryCount: 7,
},
{
name: 'Malayalam (ml-IN)',
code: 'ml',
isDefault: false,
isDraft: false,
articleCount: 10,
categoryCount: 5,
},
{
name: 'Hindi (hi-IN)',
code: 'hi',
isDefault: false,
isDraft: false,
articleCount: 15,
categoryCount: 7,
},
@@ -14,6 +14,10 @@ defineProps({
type: Boolean,
default: false,
},
hideToggle: {
type: Boolean,
default: false,
},
});
const modelValue = defineModel({ type: Boolean, default: false });
@@ -28,7 +32,8 @@ const modelValue = defineModel({ type: Boolean, default: false });
<span class="text-heading-3 text-n-slate-12">
{{ header }}
</span>
<ToggleSwitch v-model="modelValue" />
<div v-if="hideToggle" class="size-2" />
<ToggleSwitch v-else v-model="modelValue" />
</div>
<span v-if="description" class="text-body-main text-n-slate-11">
{{ description }}
@@ -27,6 +27,7 @@ const initialState = {
conversationFaqs: false,
memories: false,
citations: false,
contactAttributes: false,
},
};
@@ -59,6 +60,7 @@ const updateStateFromAssistant = assistant => {
conversationFaqs: config.feature_faq || false,
memories: config.feature_memory || false,
citations: config.feature_citation || false,
contactAttributes: config.feature_contact_attributes || false,
};
};
@@ -79,6 +81,7 @@ const handleBasicInfoUpdate = async () => {
feature_faq: state.features.conversationFaqs,
feature_memory: state.features.memories,
feature_citation: state.features.citations,
feature_contact_attributes: state.features.contactAttributes,
},
};
@@ -138,6 +141,10 @@ watch(
<input v-model="state.features.citations" type="checkbox" />
{{ t('CAPTAIN.ASSISTANTS.FORM.FEATURES.ALLOW_CITATIONS') }}
</label>
<label class="flex items-center gap-2">
<input v-model="state.features.contactAttributes" type="checkbox" />
{{ t('CAPTAIN.ASSISTANTS.FORM.FEATURES.ALLOW_CONTACT_ATTRIBUTES') }}
</label>
</div>
</div>
@@ -67,6 +67,9 @@ const isSent = computed(() => {
return sourceId.value && status.value === MESSAGE_STATUS.SENT;
}
// API inbox messages use real sent/delivered/read status values from the external system.
if (isAPIInbox.value) return status.value === MESSAGE_STATUS.SENT;
// All messages will be mark as sent for the Line channel, as there is no source ID.
if (isALineChannel.value) return true;
@@ -86,8 +89,10 @@ const isDelivered = computed(() => {
) {
return sourceId.value && status.value === MESSAGE_STATUS.DELIVERED;
}
// All messages marked as delivered for the web widget inbox and API inbox once they are sent.
if (isAWebWidgetInbox.value || isAPIInbox.value) {
// API inbox messages use real delivered status from the external system.
if (isAPIInbox.value) return status.value === MESSAGE_STATUS.DELIVERED;
// All messages marked as delivered for the web widget inbox once they are sent.
if (isAWebWidgetInbox.value) {
return status.value === MESSAGE_STATUS.SENT;
}
if (isALineChannel.value) {
@@ -828,6 +828,8 @@ onMounted(() => {
}
});
defineExpose({ focusEditorInputField });
// BUS Event to insert text or markdown into the editor at the
// current cursor position.
// Components using this
@@ -99,6 +99,7 @@ export default {
} = useUISettings();
const replyEditor = useTemplateRef('replyEditor');
const messageEditor = useTemplateRef('messageEditor');
const copilot = useCopilotReply();
const shortcutKey = useKbd(['$mod', '+', 'enter']);
@@ -109,6 +110,7 @@ export default {
setQuotedReplyFlagForInbox,
fetchQuotedReplyFlagFromUISettings,
replyEditor,
messageEditor,
copilot,
shortcutKey,
};
@@ -507,7 +509,7 @@ export default {
);
this.fetchAndSetReplyTo();
emitter.on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo);
emitter.on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.onReplyToMessage);
// A hacky fix to solve the drag and drop
// Is showing on top of new conversation modal drag and drop
@@ -522,7 +524,7 @@ export default {
unmounted() {
document.removeEventListener('paste', this.onPaste);
document.removeEventListener('keydown', this.handleKeyEvents);
emitter.off(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo);
emitter.off(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.onReplyToMessage);
emitter.off(BUS_EVENTS.INSERT_INTO_NORMAL_EDITOR, this.addIntoEditor);
emitter.off(
BUS_EVENTS.NEW_CONVERSATION_MODAL,
@@ -1191,6 +1193,15 @@ export default {
return false;
});
},
onReplyToMessage() {
this.fetchAndSetReplyTo();
if (this.inReplyTo) {
this.$nextTick(() => {
const pos = this.isSignatureEnabledForInbox ? 'start' : 'end';
this.messageEditor?.focusEditorInputField(pos);
});
}
},
resetReplyToMessage() {
const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO;
LocalStorage.deleteFromJsonStore(replyStorageKey, this.conversationId);
@@ -1313,6 +1324,7 @@ export default {
/>
<WootMessageEditor
v-else-if="!showAudioRecorderEditor"
ref="messageEditor"
v-model="message"
:conversation-id="conversationId"
:editor-id="editorStateId"
@@ -32,6 +32,7 @@ const emit = defineEmits(['dismiss']);
xs
slate
icon="i-lucide-x"
class="flex-shrink-0"
@click.stop="emit('dismiss')"
/>
</div>
@@ -133,20 +133,55 @@ export const ARTICLE_TABS_OPTIONS = [
},
];
export const LOCALE_MENU_ITEMS = [
{
export const LOCALE_MENU_ITEMS = {
makeDefault: {
label: 'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.MAKE_DEFAULT',
action: 'change-default',
value: 'default',
icon: 'i-lucide-star',
},
{
moveToDraft: {
label: 'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.MOVE_TO_DRAFT',
action: 'move-to-draft',
value: 'draft',
icon: 'i-lucide-eye-off',
},
publishLocale: {
label: 'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.PUBLISH_LOCALE',
action: 'publish-locale',
value: 'publish',
icon: 'i-lucide-eye',
},
delete: {
label: 'HELP_CENTER.LOCALES_PAGE.LOCALE_CARD.DROPDOWN_MENU.DELETE',
action: 'delete',
value: 'delete',
icon: 'i-lucide-trash',
},
];
};
const disableLocaleMenuItems = menuItems =>
menuItems.map(item => ({ ...item, disabled: true }));
export const buildLocaleMenuItems = ({ isDefault, isDraft }) => {
if (isDefault) {
return disableLocaleMenuItems([
LOCALE_MENU_ITEMS.makeDefault,
LOCALE_MENU_ITEMS.moveToDraft,
LOCALE_MENU_ITEMS.delete,
]);
}
if (isDraft) {
return [LOCALE_MENU_ITEMS.publishLocale, LOCALE_MENU_ITEMS.delete];
}
return [
LOCALE_MENU_ITEMS.makeDefault,
LOCALE_MENU_ITEMS.moveToDraft,
LOCALE_MENU_ITEMS.delete,
];
};
export const ARTICLE_EDITOR_STATUS_OPTIONS = {
published: ['archive', 'draft'],
@@ -166,6 +166,8 @@ const TOD_TO_MERIDIEM = {
evening: 'pm',
night: 'pm',
};
const CJK_CHAR_RE =
/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
// ─── Translation Cache ──────────────────────────────────────────────────────
@@ -278,8 +280,13 @@ const escapeRegex = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const substituteLocalTokens = (text, pairs) => {
let r = text;
pairs.forEach(([local, en]) => {
const re = new RegExp(`(?<=^|\\s)${escapeRegex(local)}(?=\\s|$)`, 'g');
r = r.replace(re, en);
if (CJK_CHAR_RE.test(local)) {
const re = new RegExp(escapeRegex(local), 'g');
r = r.replace(re, ` ${en} `);
} else {
const re = new RegExp(`(?<=^|\\s)${escapeRegex(local)}(?=\\s|$)`, 'g');
r = r.replace(re, en);
}
});
return r;
};
@@ -82,6 +82,9 @@ const ORDINAL_RE = `(\\d{1,2}(?:st|nd|rd|th)?|${ORDINAL_WORDS})`;
const HALF_UNIT_RE = /^(?:in\s+)?half\s+(?:an?\s+)?(hour|day|week|month|year)$/;
const RELATIVE_DURATION_RE = new RegExp(`^(?:in\\s+)?${NUM_RE}\\s+${UNIT_RE}$`);
const RELATIVE_DURATION_AFTER_RE = new RegExp(
`^(?:in\\s+)?${NUM_RE}\\s+${UNIT_RE}\\s+after$`
);
const DURATION_FROM_NOW_RE = new RegExp(
`^${NUM_RE}\\s+${UNIT_RE}\\s+from\\s+now$`
);
@@ -89,6 +92,9 @@ const RELATIVE_DAY_ONLY_RE = new RegExp(`^(${RELATIVE_DAYS})$`);
const RELATIVE_DAY_TOD_RE = new RegExp(
`^(${RELATIVE_DAYS})\\s+(?:at\\s+)?(${TIME_OF_DAY_NAMES})$`
);
const RELATIVE_DAY_MERIDIEM_RE = new RegExp(
`^(${RELATIVE_DAYS})\\s+(?:at\\s+)?(am|pm)$`
);
const RELATIVE_DAY_TOD_TIME_RE = new RegExp(
`^(${RELATIVE_DAYS})\\s+(?:at\\s+)?(${TIME_OF_DAY_NAMES})\\s+(\\d{1,2}(?::\\d{2})?)$`
);
@@ -245,6 +251,7 @@ const matchDuration = (text, now) => {
return (
parseDuration(text.match(DURATION_FROM_NOW_RE), now) ||
parseDuration(text.match(RELATIVE_DURATION_AFTER_RE), now) ||
parseDuration(text.match(RELATIVE_DURATION_RE), now)
);
};
@@ -303,6 +310,13 @@ const matchRelativeDay = (text, now) => {
);
}
const dayMeridiemMatch = text.match(RELATIVE_DAY_MERIDIEM_RE);
if (dayMeridiemMatch) {
const [, dayKey, meridiem] = dayMeridiemMatch;
const hours = meridiem === 'am' ? 9 : 14;
return applyTimeWithRollover(RELATIVE_DAY_MAP[dayKey], hours, 0, now);
}
const dayAtTimeMatch = text.match(RELATIVE_DAY_AT_TIME_RE);
if (dayAtTimeMatch) {
const [, dayKey, timeRaw] = dayAtTimeMatch;
@@ -1,4 +1,8 @@
import { buildPortalArticleURL, buildPortalURL } from '../portalHelper';
import {
buildLocaleMenuItems,
buildPortalArticleURL,
buildPortalURL,
} from '../portalHelper';
describe('PortalHelper', () => {
describe('buildPortalURL', () => {
@@ -68,4 +72,39 @@ describe('PortalHelper', () => {
).toEqual('https://app.chatwoot.com/hc/handbook/articles/article-slug');
});
});
describe('buildLocaleMenuItems', () => {
it('returns disabled actions for the default locale', () => {
expect(
buildLocaleMenuItems({
isDefault: true,
isDraft: false,
})
).toEqual(
expect.arrayContaining([
expect.objectContaining({ action: 'change-default', disabled: true }),
expect.objectContaining({ action: 'move-to-draft', disabled: true }),
expect.objectContaining({ action: 'delete', disabled: true }),
])
);
});
it('returns publish and delete actions for draft locales', () => {
expect(
buildLocaleMenuItems({
isDefault: false,
isDraft: true,
}).map(({ action }) => action)
).toEqual(['publish-locale', 'delete']);
});
it('returns default, draft, and delete actions for live locales', () => {
expect(
buildLocaleMenuItems({
isDefault: false,
isDraft: false,
}).map(({ action }) => action)
).toEqual(['change-default', 'move-to-draft', 'delete']);
});
});
});
@@ -1626,6 +1626,24 @@ describe('generateDateSuggestions — localized input regressions', () => {
},
};
const zhTWSnoozeTranslations = {
UNITS: {
HOUR: '小時',
HOURS: '小時',
DAY: '天',
DAYS: '天',
},
HALF: '半',
RELATIVE: {
TOMORROW: '明天',
},
MERIDIEM: {
AM: '上午',
PM: '下午',
},
AFTER: '後',
};
describe('P1: short non-English tokens must NOT produce spurious half-duration suggestions', () => {
it('Arabic "غد" does not produce half-duration suggestions', () => {
const results = generateDateSuggestions('غد', now, {
@@ -1721,6 +1739,37 @@ describe('generateDateSuggestions — localized input regressions', () => {
expect(results[0].date.getHours()).toBe(6);
});
});
describe('zh_TW compact CJK inputs', () => {
const options = {
translations: zhTWSnoozeTranslations,
locale: 'zh-TW',
};
it('parses "2小時後" (2 hours from now) without spaces', () => {
const results = generateDateSuggestions('2小時後', now, options);
expect(results.length).toBeGreaterThan(0);
expect(results[0].date.getDate()).toBe(16);
expect(results[0].date.getHours()).toBe(12);
expect(results[0].date.getMinutes()).toBe(0);
});
it('parses "半天" (half day) without spaces', () => {
const results = generateDateSuggestions('半天', now, options);
expect(results.length).toBeGreaterThan(0);
expect(results[0].date.getDate()).toBe(16);
expect(results[0].date.getHours()).toBe(22);
expect(results[0].date.getMinutes()).toBe(0);
});
it('parses "明天 上午" (tomorrow AM) into tomorrow 9am', () => {
const results = generateDateSuggestions('明天 上午', now, options);
expect(results.length).toBeGreaterThan(0);
expect(results[0].date.getDate()).toBe(17);
expect(results[0].date.getHours()).toBe(9);
expect(results[0].date.getMinutes()).toBe(0);
});
});
});
describe('no-space duration suggestions', () => {
@@ -4,6 +4,9 @@
"LOADING_EDITOR": "Loading editor...",
"DESCRIPTION": "Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try. You can manage your bots from this page or create new ones using the 'Add Bot' button.",
"LEARN_MORE": "Learn about agent bots",
"COUNT": "{n} bot | {n} bots",
"SEARCH_PLACEHOLDER": "Search bots...",
"NO_RESULTS": "No bots found matching your search",
"GLOBAL_BOT": "System bot",
"GLOBAL_BOT_BADGE": "System",
"AVATAR": {
@@ -34,7 +37,8 @@
"LOADING": "Fetching bots...",
"TABLE_HEADER": {
"DETAILS": "Bot Details",
"URL": "Webhook URL"
"URL": "Webhook URL",
"ACTIONS": "Actions"
}
},
"DELETE": {
@@ -9,6 +9,7 @@
"ADMINISTRATOR": "Administrator",
"AGENT": "Agent"
},
"COUNT": "{n} agent | {n} agents",
"LIST": {
"404": "There are no agents associated to this account",
"TITLE": "Manage agents in your team",
@@ -96,6 +97,8 @@
"ERROR_MESSAGE": "Could not connect to Woot Server, Please try again later"
}
},
"SEARCH_PLACEHOLDER": "Search agents...",
"NO_RESULTS": "No agents found matching your search",
"SEARCH": {
"NO_RESULTS": "No results found."
},
@@ -5,6 +5,9 @@
"LOADING": "Fetching custom attributes",
"DESCRIPTION": "A custom attribute tracks additional details about your contacts or conversations—such as the subscription plan or the date of their first purchase. You can add different types of custom attributes, such as text, lists, or numbers, to capture the specific information you need.",
"LEARN_MORE": "Learn more about custom attributes",
"COUNT": "{n} attribute | {n} attributes",
"SEARCH_PLACEHOLDER": "Search attributes...",
"NO_RESULTS": "No attributes found matching your search",
"ATTRIBUTE_MODELS": {
"CONVERSATION": "Conversation",
"CONTACT": "Contact"
@@ -63,6 +66,10 @@
},
"ENABLE_REGEX": {
"LABEL": "Enable regex validation"
},
"BADGES": {
"PRE_CHAT": "Pre-chat",
"RESOLUTION": "Resolution"
}
},
"API": {
@@ -3,8 +3,11 @@
"HEADER": "Automation",
"DESCRIPTION": "Automation can replace and streamline existing processes that require manual effort, such as adding labels and assigning conversations to the most suitable agent. This allows the team to focus on their strengths while reducing time spent on routine tasks.",
"LEARN_MORE": "Learn more about automation",
"HEADER_BTN_TXT": "Add Automation Rule",
"COUNT": "{n} automation | {n} automations",
"HEADER_BTN_TXT": "Create Automation",
"LOADING": "Fetching automation rules",
"SEARCH_PLACEHOLDER": "Search automation rules...",
"NO_RESULTS": "No automation rules found matching your search",
"ADD": {
"TITLE": "Add Automation Rule",
"SUBMIT": "Create",
@@ -42,9 +45,9 @@
"LIST": {
"TABLE_HEADER": {
"NAME": "Name",
"DESCRIPTION": "Description",
"ACTIVE": "Active",
"CREATED_ON": "Created on"
"CREATED_ON": "Created on",
"ACTIONS": "Actions"
},
"404": "No automation rules found"
},
@@ -150,7 +153,8 @@
"ADD_PRIVATE_NOTE": "Add a Private Note",
"CHANGE_PRIORITY": "Change Priority",
"ADD_SLA": "Add SLA",
"OPEN_CONVERSATION": "Open conversation"
"OPEN_CONVERSATION": "Open conversation",
"PENDING_CONVERSATION": "Mark conversation as pending"
},
"MESSAGE_TYPES": {
"INCOMING": "Incoming Message",
@@ -22,6 +22,10 @@
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
"UPDATE_FAILED": "Failed to update conversations. Please try again."
},
"RESOLVE": {
"ALL_MISSING_ATTRIBUTES": "Cannot resolve conversations due to missing required attributes",
"PARTIAL_SUCCESS": "Some conversations need required attributes before resolving and were skipped"
},
"LABELS": {
"ASSIGN_LABELS": "Assign labels",
"NO_LABELS_FOUND": "No labels found",
@@ -3,8 +3,11 @@
"HEADER": "Canned Responses",
"LEARN_MORE": "Learn more about canned responses",
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
"COUNT": "{n} canned response | {n} canned responses",
"HEADER_BTN_TXT": "Add canned response",
"LOADING": "Fetching canned responses...",
"SEARCH_PLACEHOLDER": "Search canned responses...",
"NO_RESULTS": "No canned responses found matching your search",
"SEARCH_404": "There are no items matching this query.",
"LIST": {
"404": "There are no canned responses available in this account.",
@@ -76,6 +76,9 @@
},
"waiting_since_desc": {
"TEXT": "Pending Response: Shortest first"
},
"priority_desc_created_at_asc": {
"TEXT": "Priority: Highest first, Created: Oldest first"
}
},
"ATTACHMENTS": {
File diff suppressed because it is too large Load Diff
@@ -61,6 +61,7 @@
"UNSUPPORTED_MESSAGE": "This message is unsupported. You can view this message on the Facebook / Instagram app.",
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
"UNSUPPORTED_MESSAGE_TIKTOK": "This message is unsupported. You can view this message on the TikTok app.",
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
"NO_RESPONSE": "No response",
@@ -173,6 +174,10 @@
"SUCCESFUL": "Assigned label #{labelName} to conversation id {conversationId}",
"FAILED": "Couldn't assign label. Please try again."
},
"LABEL_REMOVAL": {
"SUCCESFUL": "Removed label #{labelName} from conversation id {conversationId}",
"FAILED": "Couldn't remove label. Please try again."
},
"TEAM_ASSIGNMENT": {
"SUCCESFUL": "Assigned team \"{team}\" to conversation id {conversationId}",
"FAILED": "Couldn't assign team. Please try again."
@@ -185,7 +190,11 @@
"DISABLE_SIGN_TOOLTIP": "Disable signature",
"MSG_INPUT": "Shift + enter for new line. Start with '/' to select a Canned Response.",
"PRIVATE_MSG_INPUT": "Shift + enter for new line. This will be visible only to Agents",
"MESSAGING_RESTRICTED": "You cannot reply to this conversation",
"MESSAGING_RESTRICTED_WHATSAPP": "You can only reply using a template message due to 24-hour message window restriction",
"MESSAGING_RESTRICTED_API": "You can only reply using a template message due to message window restriction",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
"COPILOT_MSG_INPUT": "Give copilot additional prompts, or ask anything else... Press enter to send follow-up",
"CLICK_HERE": "Click here to update",
"WHATSAPP_TEMPLATES": "Whatsapp Templates"
},
@@ -205,7 +214,7 @@
"DRAG_DROP": "Drag and drop here to attach",
"START_AUDIO_RECORDING": "Start audio recording",
"STOP_AUDIO_RECORDING": "Stop audio recording",
"": "",
"COPILOT_THINKING": "Copilot is thinking",
"EMAIL_HEAD": {
"TO": "TO",
"ADD_BCC": "Add bcc",
@@ -247,9 +256,12 @@
"SUCCESS_DELETE_CONVERSATION": "ውይይት በተሳካ ሁኔታ ተሰርዟል",
"FAIL_DELETE_CONVERSATION": "ውይይትን መሰረዝ አልተቻለም! እንደገና ይሞክሩ",
"FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB attachment limit",
"FILE_TYPE_NOT_SUPPORTED": "This {fileName} file type is not supported in this conversation",
"MESSAGE_ERROR": "Unable to send this message, please try again later",
"SENT_BY": "Sent by:",
"BOT": "Bot",
"NATIVE_APP": "Native app",
"NATIVE_APP_ADVISORY": "This message was sent from the native app. Reply from Chatwoot to maintain the message window.",
"SEND_FAILED": "Couldn't send message! Try again",
"TRY_AGAIN": "retry",
"ASSIGNMENT": {
@@ -294,6 +306,7 @@
"CANCEL": "Cancel",
"SEND_EMAIL_SUCCESS": "The chat transcript was sent successfully",
"SEND_EMAIL_ERROR": "There was an error, please try again",
"SEND_EMAIL_PAYMENT_REQUIRED": "Email transcript is not available on your current plan. Please upgrade to use this feature.",
"FORM": {
"SEND_TO_CONTACT": "Send the transcript to the customer",
"SEND_TO_AGENT": "Send the transcript to the assigned agent",
@@ -3,8 +3,11 @@
"HEADER": "Custom Roles",
"LEARN_MORE": "Learn more about custom roles",
"DESCRIPTION": "Custom roles are roles that are created by the account owner or admin. These roles can be assigned to agents to define their access and permissions within the account. Custom roles can be created with specific permissions and access levels to suit the requirements of the organization.",
"COUNT": "{n} custom role | {n} custom roles",
"HEADER_BTN_TXT": "Add custom role",
"LOADING": "Fetching custom roles...",
"SEARCH_PLACEHOLDER": "Search custom roles...",
"NO_RESULTS": "No custom roles found matching your search",
"SEARCH_404": "There are no items matching this query.",
"PAYWALL": {
"TITLE": "Upgrade to create custom roles",
@@ -1,5 +1,8 @@
{
"DATE_PICKER": {
"PREVIOUS_PERIOD": "Previous period",
"NEXT_PERIOD": "Next period",
"WEEK_NUMBER": "Week #{weekNumber}",
"APPLY_BUTTON": "Apply",
"CLEAR_BUTTON": "Clear",
"DATE_RANGE_INPUT": {
@@ -13,6 +16,8 @@
"LAST_3_MONTHS": "Last 3 months",
"LAST_6_MONTHS": "Last 6 months",
"LAST_YEAR": "Last year",
"THIS_WEEK": "This week",
"MONTH_TO_DATE": "This month",
"CUSTOM_RANGE": "Custom date range"
}
}
@@ -7,6 +7,13 @@
},
"CLOSE": "Close",
"BETA": "Beta",
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it."
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it.",
"ACCEPT": "Accept",
"DISCARD": "Discard",
"PREFERRED": "Preferred"
},
"CHOICE_TOGGLE": {
"YES": "Yes",
"NO": "No"
}
}
@@ -182,6 +182,7 @@
},
"COMMAND_BAR": {
"SEARCH_PLACEHOLDER": "Search or jump to",
"SNOOZE_PLACEHOLDER": "Type a time e.g. tomorrow, 2 hours, next friday, jan 15...",
"SECTIONS": {
"GENERAL": "General",
"REPORTS": "Reports",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -3,6 +3,9 @@
"FETCHING": "Fetching Integrations",
"NO_HOOK_CONFIGURED": "There are no {integrationId} integrations configured in this account.",
"HEADER": "Applications",
"COUNT": "{n} integration | {n} integrations",
"SEARCH_PLACEHOLDER": "Search...",
"NO_RESULTS": "No results found matching your search",
"STATUS": {
"ENABLED": "Enabled",
"DISABLED": "Disabled"
@@ -31,6 +34,7 @@
"LIST": {
"FETCHING": "Fetching integration hooks",
"INBOX": "Inbox",
"ACTIONS": "Actions",
"DELETE": {
"BUTTON_TEXT": "Delete"
}
File diff suppressed because it is too large Load Diff
@@ -5,6 +5,9 @@
"LOADING": "Fetching labels",
"DESCRIPTION": "Labels help you categorize and prioritize conversations and leads. You can assign a label to a conversation or contact using the side panel.",
"LEARN_MORE": "Learn more about labels",
"COUNT": "{n} label | {n} labels",
"SEARCH_PLACEHOLDER": "Search labels...",
"NO_RESULTS": "No labels found matching your search",
"SEARCH_404": "There are no items matching this query",
"LIST": {
"404": "There are no labels available in this account.",
@@ -13,7 +16,8 @@
"TABLE_HEADER": {
"NAME": "Name",
"DESCRIPTION": "Description",
"COLOR": "Color"
"COLOR": "Color",
"ACTION": "Actions"
}
},
"FORM": {
@@ -3,9 +3,12 @@
"HEADER": "Macros",
"DESCRIPTION": "A macro is a set of saved actions that help customer service agents easily complete tasks. The agents can define a set of actions like tagging a conversation with a label, sending an email transcript, updating a custom attribute, etc., and they can run these actions in a single click.",
"LEARN_MORE": "Learn more about macros",
"COUNT": "{n} macro | {n} macros",
"HEADER_BTN_TXT": "Add a new macro",
"HEADER_BTN_TXT_SAVE": "Save macro",
"LOADING": "Fetching macros",
"SEARCH_PLACEHOLDER": "Search macros...",
"NO_RESULTS": "No macros found matching your search",
"ERROR": "Something went wrong. Please try again",
"ORDER_INFO": "Macros will run in the order you add your actions. You can rearrange them by dragging them by the handle beside each node.",
"ADD": {
@@ -29,7 +32,8 @@
"NAME": "Name",
"CREATED BY": "Created by",
"LAST_UPDATED_BY": "Last updated by",
"VISIBILITY": "Visibility"
"VISIBILITY": "Visibility",
"ACTIONS": "Actions"
},
"404": "No macros found"
},
@@ -1,7 +1,7 @@
{
"MFA_SETTINGS": {
"TITLE": "Two-Factor Authentication",
"SUBTITLE": "Secure your account with TOTP-based authentication",
"SUBTITLE": "Protect your account from unauthorized access with TOTP-based authentication. This adds an extra layer of security to your account.",
"DESCRIPTION": "Add an extra layer of security to your account using a time-based one-time password (TOTP)",
"STATUS_TITLE": "Authentication Status",
"STATUS_DESCRIPTION": "Manage your two-factor authentication settings and backup recovery codes",
@@ -1,39 +1,39 @@
{
"REPORT": {
"HEADER": "Conversations",
"LOADING_CHART": "Loading chart data...",
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
"DOWNLOAD_AGENT_REPORTS": "Download agent reports",
"LOADING_CHART": "ገበታ ውሂብ በማስጫን ላይ...",
"NO_ENOUGH_DATA": "ሪፖርት ለማመንጨት በቂ ውሂብ ነጥቦች አልደረሰንም፣ እባክዎ በኋላ ደግመው ይሞክሩ።",
"DOWNLOAD_CONVERSATION_REPORTS": "Download conversation reports",
"DATA_FETCHING_FAILED": "Failed to fetch data, please try again later.",
"SUMMARY_FETCHING_FAILED": "Failed to fetch summary, please try again later.",
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversations",
"DESC": "( Total )"
"NAME": "ውይይቶች",
"DESC": "( ጠቅላላ )"
},
"INCOMING_MESSAGES": {
"NAME": "Messages received",
"DESC": "( Total )"
"DESC": "( ጠቅላላ )"
},
"OUTGOING_MESSAGES": {
"NAME": "Messages sent",
"DESC": "( Total )"
"DESC": "( ጠቅላላ )"
},
"FIRST_RESPONSE_TIME": {
"NAME": "First Response Time",
"DESC": "( Avg )",
"DESC": "( አማካይ )",
"INFO_TEXT": "Total number of conversations used for computation:",
"TOOLTIP_TEXT": "First Response Time is {metricValue} (based on {conversationCount} conversations)"
},
"RESOLUTION_TIME": {
"NAME": "Resolution Time",
"DESC": "( Avg )",
"NAME": "የመፍትሄ ጊዜ",
"DESC": "( አማካይ )",
"INFO_TEXT": "Total number of conversations used for computation:",
"TOOLTIP_TEXT": "Resolution Time is {metricValue} (based on {conversationCount} conversations)"
},
"RESOLUTION_COUNT": {
"NAME": "Resolution Count",
"DESC": "( Total )"
"NAME": "የመፍትሄ ብዛት",
"DESC": "( ጠቅላላ )"
},
"BOT_RESOLUTION_COUNT": {
"NAME": "Resolution Count",
@@ -61,8 +61,8 @@
"CUSTOM_DATE_RANGE": "Custom date range"
},
"CUSTOM_DATE_RANGE": {
"CONFIRM": "Apply",
"PLACEHOLDER": "Select date range"
"CONFIRM": "አተግባር ላይ አውርድ",
"PLACEHOLDER": "የቀን ክልል ይምረጡ"
},
"GROUP_BY_FILTER_DROPDOWN_LABEL": "Group By",
"DURATION_FILTER_LABEL": "Duration",
@@ -127,28 +127,33 @@
}
},
"AGENT_REPORTS": {
"HEADER": "Agents Overview",
"DESCRIPTION": "Easily track agent performance with key metrics such as conversations, response times, resolution times, and resolved cases. Click an agents name to learn more.",
"LOADING_CHART": "Loading chart data...",
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
"DOWNLOAD_AGENT_REPORTS": "Download agent reports",
"FILTER_DROPDOWN_LABEL": "Select Agent",
"HEADER": "የወኪሎች እይታ",
"DESCRIPTION": "Easily track agent performance with key metrics such as conversations, response times, resolution times, and resolved cases. Click an agent's name to learn more.",
"LOADING_CHART": "የቅርጸ ቁምፊ ውሂብ በመጫን ላይ...",
"NO_ENOUGH_DATA": "ሪፖርት ለማቅረብ በቂ ውሂብ አልደረሰንም፣ እባክዎ በኋላ ደግመው ይሞክሩ።.",
"DOWNLOAD_AGENT_REPORTS": "የAgent ሪፖርቶችን አውርድ",
"FILTER_DROPDOWN_LABEL": "Agent ይምረጡ",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"AGENTS": "Search agents"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversations",
"DESC": "( Total )"
"NAME": "ውይይቶች",
"DESC": "( ጠቅላላ )"
},
"INCOMING_MESSAGES": {
"NAME": "Incoming Messages",
"DESC": "( Total )"
"NAME": "የመጣ መልእክቶች",
"DESC": "( ጠቅላላ )"
},
"OUTGOING_MESSAGES": {
"NAME": "Outgoing Messages",
"DESC": "( Total )"
"NAME": "የሚያልኩ መልእክቶች",
"DESC": "( ጠቅላላ )"
},
"FIRST_RESPONSE_TIME": {
"NAME": "First Response Time",
"DESC": "( Avg )",
"DESC": "( አማካይ )",
"INFO_TEXT": "Total number of conversations used for computation:",
"TOOLTIP_TEXT": "First Response Time is {metricValue} (based on {conversationCount} conversations)"
},
@@ -201,6 +206,11 @@
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
"DOWNLOAD_LABEL_REPORTS": "Download label reports",
"FILTER_DROPDOWN_LABEL": "Select Label",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"LABELS": "Search labels"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversations",
@@ -271,6 +281,11 @@
"FILTER_DROPDOWN_LABEL": "Select Inbox",
"ALL_INBOXES": "All Inboxes",
"SEARCH_INBOX": "Search Inbox",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"INBOXES": "Search inboxes"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversations",
@@ -334,11 +349,19 @@
},
"TEAM_REPORTS": {
"HEADER": "Team Overview",
"DESCRIPTION": "Get a snapshot of your teams performance with essential metrics, including conversations, response times, resolution times, and resolved cases. Click a team name for more details.",
"DESCRIPTION": "Get a snapshot of your team's performance with essential metrics, including conversations, response times, resolution times, and resolved cases. Click a team name for more details.",
"LOADING_CHART": "Loading chart data...",
"NO_ENOUGH_DATA": "We've not received enough data points to generate report, Please try again later.",
"DOWNLOAD_TEAM_REPORTS": "Download team reports",
"FILTER_DROPDOWN_LABEL": "Select Team",
"FILTERS": {
"ADD_FILTER": "Add filter",
"CLEAR_ALL": "Clear all",
"NO_FILTER": "No filters available",
"INPUT_PLACEHOLDER": {
"TEAMS": "Search teams"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "Conversations",
@@ -401,35 +424,80 @@
}
},
"CSAT_REPORTS": {
"HEADER": "CSAT Reports",
"NO_RECORDS": "There are no CSAT survey responses available.",
"HEADER": "CSAT ሪፖርቶች",
"NO_RECORDS": "No responses yet",
"NO_RECORDS_DESCRIPTION": "CSAT survey responses will appear here once customers start providing feedback.",
"DOWNLOAD": "Download CSAT Reports",
"DOWNLOAD_FAILED": "Failed to download CSAT Reports",
"FILTERS": {
"ADD_FILTER": "Add filter",
"CLEAR_ALL": "Clear all",
"NO_FILTER": "No filters available",
"INPUT_PLACEHOLDER": {
"AGENTS": "Search agents",
"INBOXES": "Search inboxes",
"TEAMS": "Search teams",
"RATINGS": "Search ratings"
},
"AGENTS": {
"PLACEHOLDER": "Choose Agents"
"LABEL": "Agent"
},
"INBOXES": {
"LABEL": "Inbox"
},
"TEAMS": {
"LABEL": "Team"
},
"RATINGS": {
"LABEL": "Rating"
}
},
"TABLE": {
"HEADER": {
"CONTACT_NAME": "Contact",
"AGENT_NAME": "Assigned agent",
"RATING": "Rating",
"FEEDBACK_TEXT": "Feedback comment"
}
"CONTACT_NAME": "እውቂያ",
"AGENT_NAME": "Agent",
"RATING": "እምነት ደረጃ",
"FEEDBACK_TEXT": "አስተያየት አስተያየት",
"CONVERSATION": "Conversation",
"CUSTOMER": "Customer",
"RESPONSE": "Response",
"HANDLED_BY": "Handled by"
},
"UNKNOWN_CUSTOMER": "Unknown customer"
},
"NO_AGENT": "No assigned agent",
"NO_FEEDBACK": "No feedback provided",
"METRIC": {
"TOTAL_RESPONSES": {
"LABEL": "Total responses",
"TOOLTIP": "Total number of responses collected"
"LABEL": "ጠቅላላ ምላሾች",
"TOOLTIP": "የተሰበሰበው ምላሾች ጠቅላላ ብዛት"
},
"SATISFACTION_SCORE": {
"LABEL": "Satisfaction score",
"TOOLTIP": "Total number of positive responses / Total number of responses * 100"
"LABEL": "የደስታ ነጥብ",
"TOOLTIP": "አጠቃላይ የአዎንታዊ ምላሾች ብዛት / አጠቃላይ የምላሾች ብዛት * 100"
},
"RESPONSE_RATE": {
"LABEL": "Response rate",
"TOOLTIP": "Total number of responses / Total number of CSAT survey messages sent * 100"
"LABEL": "የምላሽ ተመን",
"TOOLTIP": "አጠቃላይ የምላሾች ብዛት / አጠቃላይ የተላኩ የCSAT እቅድ መልእክቶች ብዛት * 100"
},
"RATING_DISTRIBUTION": "Rating distribution"
},
"REVIEW_NOTES": {
"TITLE": "Review notes",
"PLACEHOLDER": "Add review notes about this rating...",
"SAVE": "Save",
"CANCEL": "Cancel",
"SAVING": "Saving...",
"SAVED": "Notes saved successfully",
"SAVE_ERROR": "Failed to save notes",
"UPDATED_BY": "Updated by {name} {time}",
"UPDATED_BY_LABEL": "Updated by",
"PAYWALL": {
"TITLE": "Upgrade to add review notes",
"AVAILABLE_ON": "The review notes feature is only available in the Business and Enterprise plans.",
"UPGRADE_PROMPT": "Add internal context to every CSAT response with review notes. Capture what really happened, spot patterns faster, and make better decisions from your feedback.",
"UPGRADE_NOW": "Upgrade now",
"CANCEL_ANYTIME": "You can change or cancel your plan anytime"
}
}
},
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,7 @@
{
"REGISTER": {
"TRY_WOOT": "Create an account",
"GET_STARTED": "Get started with Chatwoot",
"TITLE": "Register",
"TESTIMONIAL_HEADER": "All it takes is one step to move forward",
"TESTIMONIAL_CONTENT": "You're one step away from engaging your customers, retaining them and finding new ones.",
@@ -5,7 +5,12 @@
"ADD_ACTION_LONG": "Create a new SLA Policy",
"DESCRIPTION": "Service Level Agreements (SLAs) are contracts that define clear expectations between your team and customers. They establish standards for response and resolution times, creating a framework for accountability and ensures a consistent, high-quality experience.",
"LEARN_MORE": "Learn more about SLA",
"COUNT": "{n} SLA | {n} SLAs",
"LOADING": "Fetching SLAs",
"SEARCH_PLACEHOLDER": "Search SLA...",
"SEARCH": {
"NO_RESULTS": "No SLA found matching your search"
},
"PAYWALL": {
"TITLE": "Upgrade to create SLAs",
"AVAILABLE_ON": "The SLA feature is only available in the Business and Enterprise plans.",
@@ -20,14 +25,18 @@
},
"LIST": {
"404": "There are no SLAs available in this account.",
"TABLE_HEADER": {
"SLA": "SLA",
"BUSINESS_HOURS": "Business hours"
},
"EMPTY": {
"TITLE_1": "Enterprise P0",
"DESC_1": "Issues raised by enterprise customers, that require immediate attention.",
"TITLE_2": "Enterprise P1",
"DESC_2": "Issues raised by enterprise customers, that needs to be acknowledged quickly."
},
"BUSINESS_HOURS_ON": "Business hours on",
"BUSINESS_HOURS_OFF": "Business hours off",
"BUSINESS_HOURS_ON": "Turned on",
"BUSINESS_HOURS_OFF": "Turned off",
"RESPONSE_TYPES": {
"FRT": "First response time threshold",
"NRT": "Next response time threshold",
@@ -0,0 +1,72 @@
{
"SNOOZE_PARSER": {
"UNITS": {
"MINUTE": "minute",
"MINUTES": "minutes",
"HOUR": "hour",
"HOURS": "hours",
"DAY": "day",
"DAYS": "days",
"WEEK": "week",
"WEEKS": "weeks",
"MONTH": "month",
"MONTHS": "months",
"YEAR": "year",
"YEARS": "years"
},
"HALF": "half",
"NEXT": "next",
"THIS": "this",
"AT": "at",
"IN": "in",
"FROM_NOW": "from now",
"NEXT_YEAR": "next year",
"MERIDIEM": {
"AM": "am",
"PM": "pm"
},
"RELATIVE": {
"TOMORROW": "tomorrow",
"DAY_AFTER_TOMORROW": "day after tomorrow",
"NEXT_WEEK": "next week",
"NEXT_MONTH": "next month",
"THIS_WEEKEND": "this weekend",
"NEXT_WEEKEND": "next weekend"
},
"TIME_OF_DAY": {
"MORNING": "morning",
"AFTERNOON": "afternoon",
"EVENING": "evening",
"NIGHT": "night",
"NOON": "noon",
"MIDNIGHT": "midnight"
},
"WORD_NUMBERS": {
"ONE": "one",
"TWO": "two",
"THREE": "three",
"FOUR": "four",
"FIVE": "five",
"SIX": "six",
"SEVEN": "seven",
"EIGHT": "eight",
"NINE": "nine",
"TEN": "ten",
"TWELVE": "twelve",
"FIFTEEN": "fifteen",
"TWENTY": "twenty",
"THIRTY": "thirty"
},
"ORDINALS": {
"FIRST": "first",
"SECOND": "second",
"THIRD": "third",
"FOURTH": "fourth",
"FIFTH": "fifth"
},
"OF": "of",
"AFTER": "after",
"WEEK": "week",
"DAY": "day"
}
}
@@ -5,6 +5,9 @@
"LOADING": "Fetching teams",
"DESCRIPTION": "Teams allow you to organize agents into groups based on their responsibilities. An agent can belong to multiple teams. When working collaboratively, you can assign conversations to specific teams.",
"LEARN_MORE": "Learn more about teams",
"COUNT": "{n} team | {n} teams",
"SEARCH_PLACEHOLDER": "Search teams...",
"NO_RESULTS": "No teams found matching your search",
"LIST": {
"404": "There are no teams created on this account.",
"EDIT_TEAM": "Edit team",
@@ -64,8 +67,8 @@
"ERROR_MESSAGE": "Couldn't save the team details. Try again."
},
"AGENTS": {
"AGENT": "AGENT",
"EMAIL": "EMAIL",
"AGENT": "Agent",
"EMAIL": "Email",
"BUTTON_TEXT": "Add agents",
"ADD_AGENTS": "Adding Agents to your Team...",
"SELECT": "select",
@@ -4,6 +4,9 @@
"LOADING_EDITOR": "جار جلب المحرر...",
"DESCRIPTION": "Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try. You can manage your bots from this page or create new ones using the 'Add Bot' button.",
"LEARN_MORE": "Learn about agent bots",
"COUNT": "{n} bot | {n} bots",
"SEARCH_PLACEHOLDER": "Search bots...",
"NO_RESULTS": "No bots found matching your search",
"GLOBAL_BOT": "System bot",
"GLOBAL_BOT_BADGE": "النظام",
"AVATAR": {
@@ -34,7 +37,8 @@
"LOADING": "جار جلب الروبوتات...",
"TABLE_HEADER": {
"DETAILS": "Bot Details",
"URL": "رابط Webhook"
"URL": "رابط Webhook",
"ACTIONS": "الإجراءات"
}
},
"DELETE": {
@@ -9,6 +9,7 @@
"ADMINISTRATOR": "المدير",
"AGENT": "وكيل الدعم"
},
"COUNT": "{n} وكيل | {n} وكلاء",
"LIST": {
"404": "لا يوجد وكلاء دعم مرتبطين بهذا الحساب",
"TITLE": "إدارة وكلاء الدعم في فريقك",
@@ -96,6 +97,8 @@
"ERROR_MESSAGE": "تعذر الاتصال بالخادم، الرجاء المحاولة مرة أخرى لاحقاً"
}
},
"SEARCH_PLACEHOLDER": "البحث عن وكلاء...",
"NO_RESULTS": "No agents found matching your search",
"SEARCH": {
"NO_RESULTS": "لم يتم العثور على النتائج."
},
@@ -5,6 +5,9 @@
"LOADING": "جلب الصفات المخصصة",
"DESCRIPTION": "سمة مخصصة تتتبع تفاصيل إضافية حول جهات الاتصال أو المحادثات الخاصة بك - مثل خطة الاشتراك أو تاريخ الشراء الأول. يمكنك إضافة أنواع مختلفة من السمات المخصصة، مثل النص أو القوائم أو الأرقام، لالتقاط المعلومات المحددة التي تحتاجها.",
"LEARN_MORE": "تعرف على المزيد حول السمات المخصصة",
"COUNT": "{n} attribute | {n} attributes",
"SEARCH_PLACEHOLDER": "البحث عن صفات...",
"NO_RESULTS": "No attributes found matching your search",
"ATTRIBUTE_MODELS": {
"CONVERSATION": "المحادثات",
"CONTACT": "جهات الاتصال"
@@ -63,6 +66,10 @@
},
"ENABLE_REGEX": {
"LABEL": "تمكين التحقق من صحة regex"
},
"BADGES": {
"PRE_CHAT": "Pre-chat",
"RESOLUTION": "Resolution"
}
},
"API": {
@@ -23,52 +23,52 @@
},
"DEFAULT_USER": "النظام",
"AUTOMATION_RULE": {
"ADD": "{agentName} أنشأ قاعدة أتمتة جديدة (##{id})",
"EDIT": "{agentName} قام بتحديث قاعدة أتمتة (##{id})",
"DELETE": "{agentName} حذف قاعدة أتمتة (##{id})"
"ADD": "{agentName} أنشأ قاعدة أتمتة جديدة (#{id})",
"EDIT": "{agentName} قام بتحديث قاعدة أتمتة (#{id})",
"DELETE": "{agentName} حذف قاعدة أتمتة (#{id})"
},
"ACCOUNT_USER": {
"ADD": "{agentName} دعا {invitee} إلى الحساب كـ {role}",
"EDIT": {
"SELF": "{agentName} غير {attributes} الخاصة به إلى {values}",
"OTHER": "{agentName} غير {attributes} لـ {user} إلى {values}",
"DELETED": "{agentName} غير {attributes} لـ %{user} إلى {values}"
"DELETED": "{agentName} غير {attributes} للمستخدم المحذوف إلى {values}"
}
},
"INBOX": {
"ADD": "{agentName} أنشأ صندوق وارد جديد (##{id})",
"EDIT": "{agentName} قام بتحديث صندوق الوارد (##{id})",
"DELETE": "{agentName} حذف صندوق الوارد (##{id})"
"ADD": "{agentName} أنشأ صندوق وارد جديد (#{id})",
"EDIT": "{agentName} قام بتحديث صندوق الوارد (#{id})",
"DELETE": "{agentName} حذف صندوق الوارد (#{id})"
},
"WEBHOOK": {
"ADD": "{agentName} أنشأ Webhook جديد (##{id})",
"EDIT": "{agentName} قام بتحديث Webhook (##{id})",
"DELETE": "{agentName} حذف Webhook (##{id})"
"ADD": "{agentName} أنشأ Webhook جديد (#{id})",
"EDIT": "{agentName} قام بتحديث Webhook (#{id})",
"DELETE": "{agentName} حذف Webhook (#{id})"
},
"USER_ACTION": {
"SIGN_IN": "{agentName} قام بتسجيل الدخول",
"SIGN_OUT": "{agentName} قام بتسجيل الخروج"
},
"TEAM": {
"ADD": "{agentName} أنشأ فريق جديد (##{id})",
"EDIT": "{agentName} قام بتحديث الفريق (##{id})",
"DELETE": "{agentName} حذف الفريق (##{id})"
"ADD": "{agentName} أنشأ فريق جديد (#{id})",
"EDIT": "{agentName} قام بتحديث الفريق (#{id})",
"DELETE": "{agentName} حذف الفريق (#{id})"
},
"MACRO": {
"ADD": "{agentName} أنشأ ماكرو جديد (##{id})",
"EDIT": "{agentName} قام بتحديث ماكرو (##{id})",
"DELETE": "{agentName} حذف ماكرو (##{id})"
"ADD": "{agentName} أنشأ ماكرو جديد (#{id})",
"EDIT": "{agentName} قام بتحديث ماكرو (#{id})",
"DELETE": "{agentName} حذف ماكرو (#{id})"
},
"INBOX_MEMBER": {
"ADD": "{agentName} أضاف {user} إلى صندوق الوارد (##{inbox_id})",
"REMOVE": "{agentName} أزال {user} من صندوق الوارد (##{inbox_id})"
"ADD": "{agentName} أضاف {user} إلى صندوق الوارد (#{inbox_id})",
"REMOVE": "{agentName} أزال {user} من صندوق الوارد (#{inbox_id})"
},
"TEAM_MEMBER": {
"ADD": "{agentName} أضاف {user} إلى الفريق (##{team_id})",
"REMOVE": "{agentName} أزال {user} من الفريق (##{team_id})"
"ADD": "{agentName} أضاف {user} إلى الفريق (#{team_id})",
"REMOVE": "{agentName} أزال {user} من الفريق (#{team_id})"
},
"ACCOUNT": {
"EDIT": "{agentName} قام بتحديث إعدادات الحساب (##{id})"
"EDIT": "{agentName} قام بتحديث إعدادات الحساب (#{id})"
},
"CONVERSATION": {
"DELETE": "{agentName} deleted conversation #{id}"
@@ -3,8 +3,11 @@
"HEADER": "الأتمتة",
"DESCRIPTION": "ويمكن للأتمتة أن تحل محل وتبسط العمليات القائمة التي تتطلب جهداً يدوياً، مثل إضافة تسميات وتعيين المحادثات إلى أنسب وكيل. ويسمح ذلك للفريق بالتركيز على مواطن قوتهم مع تقليل الوقت الذي يقضيه في المهام الروتينية.",
"LEARN_MORE": "تعلم المزيد عن الأتمتة",
"HEADER_BTN_TXT": "إضافة قاعدة أتمتة",
"COUNT": "{n} automation | {n} automations",
"HEADER_BTN_TXT": "Create Automation",
"LOADING": "جلب قواعد الأتمتة",
"SEARCH_PLACEHOLDER": "Search automation rules...",
"NO_RESULTS": "No automation rules found matching your search",
"ADD": {
"TITLE": "إضافة قاعدة أتمتة",
"SUBMIT": "إنشاء",
@@ -42,9 +45,9 @@
"LIST": {
"TABLE_HEADER": {
"NAME": "الاسم",
"DESCRIPTION": "الوصف",
"ACTIVE": "مفعل",
"CREATED_ON": "تم إنشاؤها في"
"CREATED_ON": "تم إنشاؤها في",
"ACTIONS": "الإجراءات"
},
"404": "لم يتم العثور على قواعد أتمتة"
},
@@ -150,7 +153,8 @@
"ADD_PRIVATE_NOTE": "Add a Private Note",
"CHANGE_PRIORITY": "تغيير الأولوية",
"ADD_SLA": "Add SLA",
"OPEN_CONVERSATION": "فتح المحادثة"
"OPEN_CONVERSATION": "فتح المحادثة",
"PENDING_CONVERSATION": "تحديد المحادثة كمعلقة"
},
"MESSAGE_TYPES": {
"INCOMING": "Incoming Message",
@@ -22,6 +22,10 @@
"UPDATE_SUCCESFUL": "تم تحديث حالة المحادثة بنجاح.",
"UPDATE_FAILED": "فشل تحديث المحادثات، الرجاء المحاولة مرة أخرى."
},
"RESOLVE": {
"ALL_MISSING_ATTRIBUTES": "لا يمكن حل المحادثات بسبب عدم وجود السمات المطلوبة",
"PARTIAL_SUCCESS": "بعض المحادثات تحتاج إلى سمات مطلوبة قبل الحل وتم تخطيها"
},
"LABELS": {
"ASSIGN_LABELS": "إضافة وسم",
"NO_LABELS_FOUND": "لم يتم العثور على تصنيفات",
@@ -3,8 +3,11 @@
"HEADER": "الردود الجاهزة",
"LEARN_MORE": "معرفة المزيد عن الاستجابات المعلبة",
"DESCRIPTION": "الردود المسبقة هي قوالب رد مكتوبة مسبقاً تساعدك على الرد بسرعة على محادثة. يمكن للوكلاء كتابة حرف '/' يتبعه الرمز المختصر لإدراج رد مسبق أثناء محادثة. ",
"COUNT": "{n} canned response | {n} canned responses",
"HEADER_BTN_TXT": "إضافة رد جاهز",
"LOADING": "جاري جلب الردود الجاهزة...",
"SEARCH_PLACEHOLDER": "Search canned responses...",
"NO_RESULTS": "No canned responses found matching your search",
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام.",
"LIST": {
"404": "لا توجد ردود جاهزة متوفرة في هذا الحساب.",
@@ -76,6 +76,9 @@
},
"waiting_since_desc": {
"TEXT": "الرد المعلق: الأقصر أولاً"
},
"priority_desc_created_at_asc": {
"TEXT": "Priority: Highest first, Created: Oldest first"
}
},
"ATTACHMENTS": {
@@ -104,7 +107,7 @@
"CONTENT": "Shared contact"
},
"embed": {
"CONTENT": "Embedded content"
"CONTENT": "المحتوى المضمن"
}
},
"CHAT_SORT_BY_FILTER": {
@@ -1,33 +1,33 @@
{
"COMPANIES": {
"HEADER": "Companies",
"HEADER": "الشركات",
"SORT_BY": {
"LABEL": "ترتيب حسب",
"OPTIONS": {
"NAME": "الاسم",
"DOMAIN": "النطاق",
"CREATED_AT": "تم إنشاؤها في",
"CONTACTS_COUNT": "Contacts count"
"CONTACTS_COUNT": "عدد جهات الاتصال"
}
},
"ORDER": {
"LABEL": "Order",
"LABEL": "ترتيب",
"OPTIONS": {
"ASCENDING": "Ascending",
"ASCENDING": "تصاعدي",
"DESCENDING": "Descending"
}
},
"SEARCH_PLACEHOLDER": "Search companies...",
"LOADING": "Loading companies...",
"UNNAMED": "Unnamed Company",
"CONTACTS_COUNT": "{n} contact | {n} contacts",
"SEARCH_PLACEHOLDER": "البحث في الشركات...",
"LOADING": "جاري تحميل الشركات...",
"UNNAMED": "شركة بلا اسم",
"CONTACTS_COUNT": "جهة اتصال {n} | {n} جهات الاتصال",
"EMPTY_STATE": {
"TITLE": "No companies found"
"TITLE": "لم يتم العثور على شركات"
}
},
"COMPANIES_LAYOUT": {
"PAGINATION_FOOTER": {
"SHOWING": "Showing {startItem} {endItem} of {totalItems} company | Showing {startItem} {endItem} of {totalItems} companies"
"SHOWING": "عرض {startItem} - {endItem} من {totalItems} شركة | عرض {startItem} {endItem} من الشركات {totalItems}"
}
}
}
@@ -18,8 +18,8 @@
"CREATED_AT_LABEL": "تم إنشاؤها",
"NEW_MESSAGE": "رسالة جديدة",
"CALL": "Call",
"CALL_INITIATED": "Calling the contact…",
"CALL_FAILED": "Unable to start the call. Please try again.",
"CALL_INITIATED": "جار الاتصال بجهة الاتصال…",
"CALL_FAILED": "تعذر بدء المكالمة. الرجاء المحاولة مرة أخرى.",
"VOICE_INBOX_PICKER": {
"TITLE": "Choose a voice inbox"
},
@@ -457,8 +457,11 @@
"INSTAGRAM": {
"PLACEHOLDER": "Add Instagram"
},
"TELEGRAM": {
"PLACEHOLDER": "Add Telegram"
},
"TIKTOK": {
"PLACEHOLDER": "Add TikTok"
"PLACEHOLDER": "إضافة TikTok"
},
"LINKEDIN": {
"PLACEHOLDER": "Add LinkedIn"
@@ -573,7 +576,8 @@
"SEARCH_EMPTY_STATE_TITLE": "لا توجد جهات اتصال تطابق بحثك 🔍",
"LIST_EMPTY_STATE_TITLE": "No contacts available in this view 📋",
"ACTIVE_EMPTY_STATE_TITLE": "No contacts are active at the moment 🌙"
}
},
"LOAD_MORE": "تحميل المزيد"
},
"CONTACTS_BULK_ACTIONS": {
"ASSIGN_LABELS": "تعيين التسميات",
@@ -607,7 +611,7 @@
"NO_INBOX_ALERT": "There are no available inboxes to start a conversation with this contact.",
"CONTACT_SELECTOR": {
"LABEL": "إلى:",
"TAG_INPUT_PLACEHOLDER": "Search for a contact with name, email or phone number",
"TAG_INPUT_PLACEHOLDER": "Enter at least 2 characters to search by name, email, or phone number",
"CONTACT_CREATING": "Creating contact..."
},
"INBOX_SELECTOR": {
@@ -618,9 +622,9 @@
"SUBJECT_LABEL": "الموضوع :",
"SUBJECT_PLACEHOLDER": "Enter your email subject here",
"CC_LABEL": "نسخة من البريد:",
"CC_PLACEHOLDER": "Search for a contact with their email address",
"CC_PLACEHOLDER": "Enter at least 2 characters to search by email",
"BCC_LABEL": "نسخة خفية من البريد:",
"BCC_PLACEHOLDER": "Search for a contact with their email address",
"BCC_PLACEHOLDER": "Enter at least 2 characters to search by email",
"BCC_BUTTON": "نسخة خفية من البريد"
},
"MESSAGE_EDITOR": {
@@ -61,6 +61,7 @@
"UNSUPPORTED_MESSAGE": "This message is unsupported. You can view this message on the Facebook / Instagram app.",
"UNSUPPORTED_MESSAGE_FACEBOOK": "هذه الرسالة غير مدعومة، يمكنك مشاهدة هذه الرسالة على تطبيق فيسبوك (Messenger).",
"UNSUPPORTED_MESSAGE_INSTAGRAM": "هذه الرسالة غير مدعومة، يمكنك عرض هذه الرسالة على تطبيق Instagram.",
"UNSUPPORTED_MESSAGE_TIKTOK": "هذه الرسالة غير مدعومة. يمكنك مشاهدة هذه الرسالة على تطبيق TikTok.",
"SUCCESS_DELETE_MESSAGE": "تم حذف الرسالة بنجاح",
"FAIL_DELETE_MESSSAGE": "تعذر حذف الرسالة! حاول مرة أخرى",
"NO_RESPONSE": "لا توجد استجابة",
@@ -170,9 +171,13 @@
"FAILED": "تعذر تعيين الوكيل. الرجاء المحاولة مرة أخرى."
},
"LABEL_ASSIGNMENT": {
"SUCCESFUL": "تعيين تسمية ##{labelName} لمعرف المحادثة {conversationId}",
"SUCCESFUL": "تعيين تسمية #{labelName} لمعرف المحادثة {conversationId}",
"FAILED": "تعذر تعيين التسمية. الرجاء المحاولة مرة أخرى."
},
"LABEL_REMOVAL": {
"SUCCESFUL": "Removed label #{labelName} from conversation id {conversationId}",
"FAILED": "Couldn't remove label. Please try again."
},
"TEAM_ASSIGNMENT": {
"SUCCESFUL": "الفريق المعين \"{team}\" لمعرف المحادثة {conversationId}",
"FAILED": "تعذر تعيين الفريق. الرجاء المحاولة مرة أخرى."
@@ -185,7 +190,11 @@
"DISABLE_SIGN_TOOLTIP": "تعطيل التوقيع",
"MSG_INPUT": "زر Shift + Enter لإضافة سطر جديد. ابدأ بزر / للاختيار من الردود الجاهزة.",
"PRIVATE_MSG_INPUT": "زر Shift + Enter لإضافة سطر جديد. سيكون هذا مرئياً للوكلاء فقط",
"MESSAGING_RESTRICTED": "You cannot reply to this conversation",
"MESSAGING_RESTRICTED_WHATSAPP": "You can only reply using a template message due to 24-hour message window restriction",
"MESSAGING_RESTRICTED_API": "You can only reply using a template message due to message window restriction",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "لم يتم تكوين توقيع الرسالة، الرجاء تكوينه في إعدادات الملف الشخصي.",
"COPILOT_MSG_INPUT": "إعطاء copilot أوامر إضافية، أو السؤال عن أي شيء آخر... اضغط على مفتاح الإدخال لإرسال المتابعة",
"CLICK_HERE": "انقر هنا للتحديث",
"WHATSAPP_TEMPLATES": "قوالب الواتساب"
},
@@ -205,7 +214,7 @@
"DRAG_DROP": "اسحب و أسقط هنا للإرفاق",
"START_AUDIO_RECORDING": "بدء التسجيل الصوتي",
"STOP_AUDIO_RECORDING": "إيقاف التسجيل الصوتي",
"": "",
"COPILOT_THINKING": "Copilot يفكر",
"EMAIL_HEAD": {
"TO": "إلى",
"ADD_BCC": "إضافة bcc",
@@ -247,9 +256,12 @@
"SUCCESS_DELETE_CONVERSATION": "Conversation deleted successfully",
"FAIL_DELETE_CONVERSATION": "Couldn't delete conversation! Try again",
"FILE_SIZE_LIMIT": "حجم الملف يتجاوز حد الاقصى وهو {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE}",
"FILE_TYPE_NOT_SUPPORTED": "هذا النوع من الملفات {fileName} غير مدعوم في هذه المحادثة",
"MESSAGE_ERROR": "غير قادر على إرسال هذه الرسالة، الرجاء المحاولة مرة أخرى لاحقاً",
"SENT_BY": "أرسلت بواسطة:",
"BOT": "رد آلي",
"NATIVE_APP": "تطبيق الجوال",
"NATIVE_APP_ADVISORY": "تم إرسال هذه الرسالة من تطبيق الجوال. رد من Chatwoot للحفاظ على نافذة الرسالة.",
"SEND_FAILED": "تعذر إرسال الرسالة! حاول مرة أخرى",
"TRY_AGAIN": "إعادة المحاولة",
"ASSIGNMENT": {
@@ -277,14 +289,14 @@
"COPILOT": "Copilot"
},
"VOICE_WIDGET": {
"INCOMING_CALL": "Incoming call",
"OUTGOING_CALL": "Outgoing call",
"CALL_IN_PROGRESS": "Call in progress",
"NOT_ANSWERED_YET": "Not answered yet",
"HANDLED_IN_ANOTHER_TAB": "Being handled in another tab",
"REJECT_CALL": "Reject",
"JOIN_CALL": "Join call",
"END_CALL": "End call"
"INCOMING_CALL": "مكالمة واردة",
"OUTGOING_CALL": "مكالمة صادرة",
"CALL_IN_PROGRESS": "مكالمة قيد الاتصال",
"NOT_ANSWERED_YET": "لم يتم الرد بعد",
"HANDLED_IN_ANOTHER_TAB": "يتم التعامل معها في علامة تبويب أخرى",
"REJECT_CALL": "رفض",
"JOIN_CALL": "انضم إلى المكالمة",
"END_CALL": "إنهاء المكالمة"
}
},
"EMAIL_TRANSCRIPT": {
@@ -294,6 +306,7 @@
"CANCEL": "إلغاء",
"SEND_EMAIL_SUCCESS": "تم إرسال نص المحادثة بنجاح",
"SEND_EMAIL_ERROR": "حدث خطأ، الرجاء المحاولة مرة أخرى",
"SEND_EMAIL_PAYMENT_REQUIRED": "Email transcript is not available on your current plan. Please upgrade to use this feature.",
"FORM": {
"SEND_TO_CONTACT": "إرسال نص المحادثة إلى العميل",
"SEND_TO_AGENT": "إرسال نص المحادثة إلى وكيل خدمة العملاء المعين",
@@ -3,8 +3,11 @@
"HEADER": "Custom Roles",
"LEARN_MORE": "Learn more about custom roles",
"DESCRIPTION": "Custom roles are roles that are created by the account owner or admin. These roles can be assigned to agents to define their access and permissions within the account. Custom roles can be created with specific permissions and access levels to suit the requirements of the organization.",
"COUNT": "{n} custom role | {n} custom roles",
"HEADER_BTN_TXT": "Add custom role",
"LOADING": "Fetching custom roles...",
"SEARCH_PLACEHOLDER": "Search custom roles...",
"NO_RESULTS": "No custom roles found matching your search",
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام.",
"PAYWALL": {
"TITLE": "Upgrade to create custom roles",
@@ -1,5 +1,8 @@
{
"DATE_PICKER": {
"PREVIOUS_PERIOD": "Previous period",
"NEXT_PERIOD": "Next period",
"WEEK_NUMBER": "Week #{weekNumber}",
"APPLY_BUTTON": "تطبيق",
"CLEAR_BUTTON": "مسح",
"DATE_RANGE_INPUT": {
@@ -13,6 +16,8 @@
"LAST_3_MONTHS": "آخر 3 أشهر",
"LAST_6_MONTHS": "آخر 6 أشهر",
"LAST_YEAR": "العام الماضي",
"THIS_WEEK": "This week",
"MONTH_TO_DATE": "This month",
"CUSTOM_RANGE": "تحديد نطاق التاريخ"
}
}
@@ -7,6 +7,13 @@
},
"CLOSE": "أغلق",
"BETA": "تجريبي",
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it."
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it.",
"ACCEPT": "قبول",
"DISCARD": "Discard",
"PREFERRED": "المفضلة"
},
"CHOICE_TOGGLE": {
"YES": "نعم",
"NO": "لا"
}
}
@@ -182,6 +182,7 @@
},
"COMMAND_BAR": {
"SEARCH_PLACEHOLDER": "البحث أو القفز إلى",
"SNOOZE_PLACEHOLDER": "Type a time e.g. tomorrow, 2 hours, next friday, jan 15...",
"SECTIONS": {
"GENERAL": "عام",
"REPORTS": "التقارير",
@@ -374,6 +374,16 @@
"ERROR_MESSAGE": "Error while deleting article"
}
},
"REORDER_ARTICLE": {
"API": {
"ERROR_MESSAGE": "Unable to reorder articles. Please try again."
}
},
"REORDER_CATEGORY": {
"API": {
"ERROR_MESSAGE": "Unable to reorder categories. Please try again."
}
},
"CREATE_ARTICLE": {
"ERROR_MESSAGE": "Please add the article heading and content then only you can update the settings"
},
@@ -3,6 +3,9 @@
"HEADER": "قنوات التواصل",
"DESCRIPTION": "القناة هي وضع الاتصال الذي يختاره العميل للتفاعل معك. صندوق الوارد هو المكان الذي تدير فيه التفاعلات لقناة معينة. ويمكن أن تشمل الاتصالات من مصادر مختلفة مثل البريد الإلكتروني، والمحادثة الحية، ووسائط الإعلام الاجتماعية.",
"LEARN_MORE": "تعلم المزيد عن صناديق البريد",
"COUNT": "{n} inbox | {n} inboxes",
"SEARCH_PLACEHOLDER": "Search inboxes...",
"NO_RESULTS": "No inboxes found matching your search",
"RECONNECTION_REQUIRED": "Your inbox is disconnected. You won't receive new messages until you reauthorize it.",
"CLICK_TO_RECONNECT": "Click here to reconnect.",
"WHATSAPP_REGISTRATION_INCOMPLETE": "Your WhatsApp Business registration isnt complete. Please check your display name status in Meta Business Manager before reconnecting.",
@@ -58,11 +61,11 @@
"DUPLICATE_INBOX_BANNER": "This Instagram account was migrated to the new Instagram channel inbox. You wont be able to send/receive Instagram messages from this inbox anymore."
},
"TIKTOK": {
"CONTINUE_WITH_TIKTOK": "Continue with TikTok",
"CONNECT_YOUR_TIKTOK_PROFILE": "Connect your TikTok Profile",
"HELP": "To add your TikTok profile as a channel, you need to authenticate your TikTok Profile by clicking on 'Continue with TikTok' ",
"ERROR_MESSAGE": "There was an error connecting to TikTok, please try again",
"ERROR_AUTH": "There was an error connecting to TikTok, please try again"
"CONTINUE_WITH_TIKTOK": "المتابعة مع تيكتوك",
"CONNECT_YOUR_TIKTOK_PROFILE": "الاتصال بحسابك في تيكتوك",
"HELP": "لإضافة ملفك الشخصي على TikTok كقناة، عليك مصادقة ملفك الشخصي على TikTok بالنقر على \"متابعة مع TikTok\".",
"ERROR_MESSAGE": "حدث خطأ أثناء الاتصال بـ TikTok، يرجى المحاولة مرة أخرى",
"ERROR_AUTH": "حدث خطأ أثناء الاتصال بـ TikTok، يرجى المحاولة مرة أخرى"
},
"TWITTER": {
"HELP": "لإضافة حساب تويتر الخاص بك كقناة تواصل، تحتاج إلى مصادقة حسابك على تويتر بك بالنقر على زر \"تسجيل الدخول باستخدام تويتر\" ",
@@ -389,10 +392,10 @@
"ERROR_MESSAGE": "لم نتمكن من حفظ قناة البريد الإلكتروني"
},
"FINISH_MESSAGE": "بدء إعادة توجيه رسائل البريد الإلكتروني الخاصة بك إلى عنوان البريد الإلكتروني التالي.",
"FINISH_MESSAGE_NO_FORWARDING": "Your email inbox has been created successfully! You need to configure SMTP and IMAP credentials to send and receive emails. Without these settings, no emails will be processed.",
"FORWARDING_ADDRESS_LABEL": "Forward emails to this address:",
"FINISH_MESSAGE_NO_FORWARDING": "تم إنشاء بريدك الإلكتروني بنجاح! تحتاج إلى تكوين بيانات اعتماد SMTP و IMAP لإرسال واستقبال رسائل البريد الإلكتروني. بدون هذه الإعدادات، لن يتم معالجة رسائل البريد الإلكتروني.",
"FORWARDING_ADDRESS_LABEL": "إعادة توجيه رسائل البريد الإلكتروني إلى هذا العنوان",
"CONFIGURE_SMTP_IMAP_LINK": "اضغط هنا",
"CONFIGURE_SMTP_IMAP_TEXT": " to configure IMAP and SMTP settings"
"CONFIGURE_SMTP_IMAP_TEXT": " لتهيئة إعدادات IMAP و SMTP"
},
"LINE_CHANNEL": {
"TITLE": "قناة LINE",
@@ -480,7 +483,7 @@
},
"TIKTOK": {
"TITLE": "TikTok",
"DESCRIPTION": "Connect your TikTok account"
"DESCRIPTION": "ربط حسابك في TikTok"
},
"VOICE": {
"TITLE": "Voice",
@@ -575,7 +578,7 @@
"SUBTITLE": "Use only the configured business name as the sender name in the email header."
},
"BUSINESS_NAME": {
"BUTTON_TEXT": "+ Configure your business name",
"BUTTON_TEXT": "Configure your business name",
"PLACEHOLDER": "Enter your business name",
"SAVE_BUTTON_TEXT": "حفظ"
}
@@ -589,8 +592,10 @@
"DISABLED": "معطّل"
},
"LOCK_TO_SINGLE_CONVERSATION": {
"ENABLED": "مفعل",
"DISABLED": "معطّل"
"ENABLED": "Reopen same conversation",
"DISABLED": "Create new conversations",
"ENABLED_DESCRIPTION": "When a contact messages again, the previous conversation will be reopened.",
"DISABLED_DESCRIPTION": "A new conversation will be created each time after the previous one is resolved."
},
"ENABLE_HMAC": {
"LABEL": "تفعيل"
@@ -625,6 +630,8 @@
"ACCOUNT_HEALTH": "Account Health",
"CSAT": "تقييم رضاء العملاء"
},
"CHANNEL_PREFERENCES": "Channel Preferences",
"WIDGET_FEATURES": "Widget features",
"ACCOUNT_HEALTH": {
"TITLE": "Manage your WhatsApp account",
"DESCRIPTION": "Review your WhatsApp account status, messaging limits, and quality. Update settings or resolve issues if needed",
@@ -678,6 +685,16 @@
"SANDBOX": "Sandbox",
"LIVE": "مباشر"
}
},
"WEBHOOK": {
"TITLE": "Webhook Configuration",
"DESCRIPTION": "Webhook URL is required for your WhatsApp Business Account to receive messages from customers",
"ACTION_REQUIRED": "Webhook not configured",
"REGISTER_BUTTON": "Register Webhook",
"REGISTER_SUCCESS": "Webhook registered successfully",
"REGISTER_ERROR": "Failed to register webhook. Please try again.",
"CONFIGURED_SUCCESS": "Webhook configured successfully",
"URL_MISMATCH": "Webhook URL mismatch"
}
},
"SETTINGS": "الإعدادات",
@@ -693,8 +710,20 @@
"MESSENGER_SUB_HEAD": "ضع هذا الكود داخل وسم الـ body في موقعك",
"ALLOWED_DOMAINS": {
"TITLE": "Allowed Domains",
"SUBTITLE": "Add wildcard or regular domains separated by commas (leave blank to allow all), e.g. *.chatwoot.dev, chatwoot.com.",
"PLACEHOLDER": "Enter domains separated by commas (eg: *.chatwoot.dev, chatwoot.com)"
"DESCRIPTION": "Restrict which websites can embed your chat widget. For security, only add domains you own and trust. Add one or more domains separated by commas. Leave blank to allow all domains (not recommended for production).",
"PLACEHOLDER": "example.com, www.example.com, app.example.com"
},
"ALLOW_MOBILE_WEBVIEW": {
"LABEL": "Enable widget in mobile apps",
"SUBTITLE": "Check this if you embed the widget in iOS or Android apps. Mobile apps don't send domain information, so they would be blocked by domain restrictions unless this is enabled."
},
"IDENTITY_VALIDATION": {
"TITLE": "Identity Validation",
"DESCRIPTION": "Verify user authenticity by generating secure tokens. This prevents unauthorized users from impersonating others in your chat.",
"SECRET_KEY": "Secret Key",
"VIEW_DOCS": "View documentation",
"REQUIRE_LABEL": "Require identity validation for all conversations",
"REQUIRE_DESCRIPTION": "When enabled, users must provide a valid identity token to start conversations. Requests without valid tokens will be rejected."
},
"INBOX_AGENTS": "وكيل الدعم",
"INBOX_AGENTS_SUB_TEXT": "إضافة أو إزالة وكلاء من صندوق الوارد هذا",
@@ -708,8 +737,8 @@
"SENDER_NAME_SECTION_TEXT": "تمكين/تعطيل إظهار اسم الوكيل في البريد الإلكتروني، إذا تم تعطيله فسيظهر اسم المنشأة",
"ENABLE_CONTINUITY_VIA_EMAIL": "تمكين استمرارية المحادثة عبر البريد الإلكتروني",
"ENABLE_CONTINUITY_VIA_EMAIL_SUB_TEXT": "المحادثات ستستمر عبر البريد الإلكتروني إذا كان عنوان البريد الإلكتروني لجهة الاتصال متاحاً.",
"LOCK_TO_SINGLE_CONVERSATION": "قفل إلى محادثة واحدة",
"LOCK_TO_SINGLE_CONVERSATION_SUB_TEXT": "تمكين أو تعطيل محادثات متعددة لنفس جهة الاتصال في هذا البريد الوارد",
"LOCK_TO_SINGLE_CONVERSATION": "Conversation Routing",
"LOCK_TO_SINGLE_CONVERSATION_SUB_TEXT": "Configure conversation creation for existing contacts",
"INBOX_UPDATE_TITLE": "إعدادات قناة التواصل",
"INBOX_UPDATE_SUB_TEXT": "تحديث إعدادات قناة التواصل",
"AUTO_ASSIGNMENT_SUB_TEXT": "تمكين أو تعطيل الإسناد التلقائي للمحادثات الجديدة إلى الموظفين المضافين إلى قناة التواصل هذه.",
@@ -758,6 +787,7 @@
"LABEL": "مركز المساعدة",
"PLACEHOLDER": "Select Help Center",
"SELECT_PLACEHOLDER": "Select Help Center",
"NONE": "لا شيء",
"REMOVE": "Remove Help Center",
"SUB_TEXT": "Attach a Help Center with the inbox"
},
@@ -766,6 +796,53 @@
"MAX_ASSIGNMENT_LIMIT_RANGE_ERROR": "الرجاء إدخال قيمة أكبر من 0",
"MAX_ASSIGNMENT_LIMIT_SUB_TEXT": "تحديد الحد الأقصى لعدد المحادثات من علبة الوارد هذه التي يمكن تعيينها تلقائياً إلى وكيل"
},
"ASSIGNMENT": {
"TITLE": "تعيين المحادثة",
"DESCRIPTION": "تعيين المحادثات الواردة تلقائياً إلى الوكلاء المتاحين استناداً إلى سياسات التعيين",
"ENABLE_AUTO_ASSIGNMENT": "تمكين تعيين المحادثة تلقائياً",
"DEFAULT_RULES_TITLE": "قواعد التعيين الافتراضية",
"DEFAULT_RULES_DESCRIPTION": "استخدام سلوك التعيين الافتراضي لجميع المحادثات",
"DEFAULT_RULE_1": "المحادثات التي تم إنشاؤها أولاً",
"DEFAULT_RULE_2": "توزيع الجدولة الدائرية (Round robin)",
"CUSTOMIZE_WITH_POLICY": "Customize with assignment policy",
"USING_POLICY": "استخدام سياسة التعيين المخصصة لهذه القناة",
"CUSTOMIZE_POLICY": "التخصيص وفقًا لسياسة التعيين",
"DELETE_POLICY": "حذف سياسة",
"POLICY_LABEL": "سياسة التعيين",
"ASSIGNMENT_ORDER_LABEL": "ترتيب التعيين",
"ASSIGNMENT_METHOD_LABEL": "طريقة التعيين",
"POLICY_STATUS": {
"ACTIVE": "مفعل",
"INACTIVE": "غير نشط"
},
"PRIORITY": {
"EARLIEST_CREATED": "تم إنشاؤها في وقت سابق",
"LONGEST_WAITING": "أطول انتظار"
},
"METHOD": {
"ROUND_ROBIN": "Round robin",
"BALANCED": "تعيين متوازن"
},
"UPGRADE_PROMPT": "سياسة التعيين المخصصة متاحى في الخطة (Business) ",
"UPGRADE_TO_BUSINESS": "الترقية إلى (Business)",
"DEFAULT_POLICY_LINKED": "السياسة الافتراضية المرتبطة",
"DEFAULT_POLICY_DESCRIPTION": "ربط سياسة تعيين مخصصة لتخصيص كيفية تعيين المحادثات إلى الوكلاء في هذه القناه",
"LINK_EXISTING_POLICY": "ربط السياسة الحالية",
"CREATE_NEW_POLICY": "إنشاء سياسة جديدة",
"NO_POLICIES": "لم يتم العثور على سياسات التعيين",
"VIEW_ALL_POLICIES": "عرض جميع السياسات",
"CURRENT_BEHAVIOR": "حاليا يستخدم سلوك التعيين الافتراضي:",
"LINK_SUCCESS": "تم ربط سياسة التعيين بنجاح",
"LINK_ERROR": "فشل في ربط سياسة التعيين"
},
"ASSIGNMENT_POLICY": {
"DELETE_CONFIRM_TITLE": "حذف سياسة التعيين؟",
"DELETE_CONFIRM_MESSAGE": "هل أنت متأكد من أنك تريد إزالة سياسة التعيين هذه من صندوق الوارد هذا؟ صندوق الوارد سوف يعود إلى قواعد التعيين الافتراضية.",
"CANCEL": "إلغاء",
"CONFIRM_DELETE": "حذف",
"DELETE_SUCCESS": "تمت إزالة سياسة التعيين بنجاح",
"DELETE_ERROR": "فشل في إزالة سياسة التعيين"
},
"FACEBOOK_REAUTHORIZE": {
"TITLE": "إعادة التصريح",
"SUBTITLE": "انتهت صلاحية اتصال الفيسبوك الخاص بك، يرجى إعادة الاتصال بصفحة الفيسبوك الخاصة بك لمواصلة الخدمات",
@@ -809,34 +886,48 @@
"PLACEHOLDER": "Please enter a message to show users with the form"
},
"BUTTON_TEXT": {
"LABEL": "Button text",
"PLACEHOLDER": "Please rate us"
"LABEL": "نص الزر",
"PLACEHOLDER": "يرجى تقييمنا"
},
"LANGUAGE": {
"LABEL": "اللغة",
"PLACEHOLDER": "Select template language"
"PLACEHOLDER": "اختر لغة القالب"
},
"MESSAGE_PREVIEW": {
"LABEL": "Message preview",
"TOOLTIP": "This may vary slightly when rendered on WhatsApp's platform."
"LABEL": "معاينة الرسالة",
"TOOLTIP": "قد يختلف هذا قليلاً عند تقديمه على منصة WhatsApp."
},
"TEMPLATE_STATUS": {
"APPROVED": "Approved by WhatsApp",
"PENDING": "Pending WhatsApp approval",
"REJECTED": "Meta rejected the template",
"DEFAULT": "Needs WhatsApp approval",
"NOT_FOUND": "The template does not exist in the Meta platform."
"APPROVED": "معتمد بواسطة WhatsApp",
"PENDING": "في انتظار موافقة WhatsApp",
"REJECTED": "Meta رفضت القالب",
"DEFAULT": "يحتاج موافقة WhatsApp",
"NOT_FOUND": "هذا القالب غير موجود في منصة ميتا."
},
"TEMPLATE_CREATION": {
"SUCCESS_MESSAGE": "WhatsApp template created successfully and sent for approval",
"ERROR_MESSAGE": "Failed to create WhatsApp template"
"SUCCESS_MESSAGE": "تم إنشاء قالب WhatsApp بنجاح وإرساله للموافقة عليه",
"ERROR_MESSAGE": "فشل إنشاء قالب WhatsApp"
},
"TEMPLATE_UPDATE_DIALOG": {
"TITLE": "Edit survey details",
"DESCRIPTION": "We will delete the previous template and make a new one which will be sent again for WhatsApp approval",
"CONFIRM": "Create new template",
"TITLE": "تعديل تفاصيل الاستبيان",
"DESCRIPTION": "سوف نقوم بحذف القالب السابق ونقوم بإنشاء قالب جديد حيث سيتم إرساله مرة أخرى للاعتماد من قبل Whatsapp",
"CONFIRM": "إنشاء قالب جديد",
"CANCEL": "العودة للخلف"
},
"UTILITY_ANALYZER": {
"ACTION": "Check utility fit",
"HELPER_NOTE": "Check this message before submission to improve Utility fit. The system creates a dedicated CSAT template with buttons for reporting and submits it as Utility; Meta may still reclassify it as Marketing based on content.",
"RESULT_LABEL": "Meta category prediction",
"GUIDANCE_NOTE": "This is a guidance check, not a guarantee of Meta approval.",
"SUGGESTION_LABEL": "Suggested utility-safe rewrite",
"APPLY": "Use this rewrite",
"ERROR_MESSAGE": "Couldn't analyze the message. Please try again.",
"CLASSIFICATION": {
"LIKELY_UTILITY": "Likely Utility",
"LIKELY_MARKETING": "Likely Marketing",
"UNCLEAR": "Needs clarification"
}
},
"SURVEY_RULE": {
"LABEL": "Survey rule",
"DESCRIPTION_PREFIX": "Send the survey if the conversation",
@@ -848,7 +939,7 @@
"SELECT_PLACEHOLDER": "select labels"
},
"NOTE": "Note: CSAT surveys are sent only once per conversation",
"WHATSAPP_NOTE": "Note: We will create a template and send it for WhatsApp approval. After being approved, surveys will be sent only once per conversation as per the survey rule.",
"WHATSAPP_NOTE": "Note: When you save, the system creates a dedicated CSAT template in WhatsApp (used to capture rating and feedback in reports) and submits it as Utility for approval. Meta may still classify it as Marketing based on content. After approval, surveys are sent only once per conversation as per the survey rule.",
"API": {
"SUCCESS_MESSAGE": "CSAT settings updated successfully",
"ERROR_MESSAGE": "We couldn't update CSAT settings. Please try again later."
@@ -864,9 +955,11 @@
"UNAVAILABLE_MESSAGE_LABEL": "رسالة غير متاح للزائرين",
"TOGGLE_HELP": "تمكين توفر العمل سيظهر الساعات المتاحة على أداة الدردشة المباشرة حتى لو كان جميع الوكلاء غير متصلين بالإنترنت. خارج الساعات المتاحة يمكن تحذير الزوار برسالة ونموذج ما قبل الدردشة.",
"DAY": {
"DAY": "اليوم",
"AVAILABILITY": "التوفر",
"HOURS": "Hours",
"ENABLE": "تمكين التوفر لهذا اليوم",
"UNAVAILABLE": "غير متوفر",
"HOURS": "ساعات",
"VALIDATION_ERROR": "يجب أن يكون وقت البدء قبل وقت الإغلاق.",
"CHOOSE": "اختر"
},
@@ -973,11 +1066,12 @@
"IN_A_DAY": "خلال يوم"
},
"WIDGET_COLOR_LABEL": "لون صندوق الدردشة",
"WIDGET_BUBBLE_POSITION_LABEL": "موقع شعار اللايف شات",
"WIDGET_BUBBLE_TYPE_LABEL": "شكل عرض اللايف شات",
"WIDGET_BUBBLE": "Bubble",
"WIDGET_BUBBLE_POSITION_LABEL": "Position:",
"WIDGET_BUBBLE_TYPE_LABEL": "النوع:",
"WIDGET_BUBBLE_LAUNCHER_TITLE": {
"DEFAULT": "تحدث الينا",
"LABEL": "عنوان ايقونة اللايف شات",
"LABEL": "Launcher Title",
"PLACE_HOLDER": "تحدث الينا"
},
"UPDATE": {
@@ -1002,7 +1096,7 @@
},
"WIDGET_SCREEN": {
"DEFAULT": "افتراضي",
"CHAT": "محادثة"
"CHAT": "Chat mode"
},
"REPLY_TIME": {
"IN_A_FEW_MINUTES": "عادة نقوم بالرد خلال بضع دقائق",
@@ -3,6 +3,9 @@
"FETCHING": "جلب التكاملات",
"NO_HOOK_CONFIGURED": "لا يوجد {integrationId} تكاملات مكونة في هذا الحساب.",
"HEADER": "التطبيقات",
"COUNT": "{n} integration | {n} integrations",
"SEARCH_PLACEHOLDER": "Search...",
"NO_RESULTS": "No results found matching your search",
"STATUS": {
"ENABLED": "مفعل",
"DISABLED": "معطّل"
@@ -31,6 +34,7 @@
"LIST": {
"FETCHING": "جلب روابط التكامل",
"INBOX": "صندوق الوارد",
"ACTIONS": "الإجراءات",
"DELETE": {
"BUTTON_TEXT": "حذف"
}
@@ -1,6 +1,7 @@
{
"INTEGRATION_SETTINGS": {
"SHOPIFY": {
"HEADER": "Shopify",
"DELETE": {
"TITLE": "Delete Shopify Integration",
"MESSAGE": "Are you sure you want to delete the Shopify integration?"
@@ -19,6 +20,8 @@
"DESCRIPTION": "Chatwoot تتكامل مع أدوات وخدمات متعددة لتحسين كفاءة فريقك. استكشف القائمة أدناه لتكوين تطبيقاتك المفضلة.",
"LEARN_MORE": "معرفة المزيد عن التكاملات",
"LOADING": "جاري جلب التكاملات",
"SEARCH_PLACEHOLDER": "Search integrations...",
"NO_RESULTS": "No integrations found matching your search",
"CAPTAIN": {
"DISABLED": "لم يتم تمكين الكابتن على حسابك.",
"CLICK_HERE_TO_CONFIGURE": "انقر هنا للتهيئة",
@@ -28,6 +31,17 @@
"WEBHOOK": {
"SUBSCRIBED_EVENTS": "الأحداث المشتركة",
"LEARN_MORE": "Learn more about webhooks",
"SECRET": {
"LABEL": "Secret",
"COPY": "Copy secret to clipboard",
"COPY_SUCCESS": "Secret copied to clipboard",
"TOGGLE": "Toggle secret visibility",
"CREATED_DESC": "Your webhook has been created. Use the secret below to verify webhook signatures. Please copy it now — you can also find it later in the webhook edit form.",
"DONE": "Done"
},
"COUNT": "{n} webhook | {n} webhooks",
"SEARCH_PLACEHOLDER": "Search webhooks...",
"NO_RESULTS": "No webhooks found matching your search",
"FORM": {
"CANCEL": "إلغاء",
"DESC": "أحداث Webhook توفر لك معلومات في الوقت الحقيقي حول ما يحدث في حساب Chatwoot الخاص بك. الرجاء إدخال عنوان URL صالح لتكوين callback.",
@@ -104,6 +118,7 @@
}
},
"SLACK": {
"HEADER": "Slack",
"DELETE": "حذف",
"DELETE_CONFIRMATION": {
"TITLE": "Delete the integration",
@@ -145,7 +160,29 @@
"EXPAND": "Expand",
"MAKE_FRIENDLY": "Change message tone to friendly",
"MAKE_FORMAL": "Use formal tone",
"SIMPLIFY": "تبسيط"
"SIMPLIFY": "تبسيط",
"CONFIDENT": "استخدام نبرة لطيفة",
"PROFESSIONAL": "استخدام نبرة احترافية",
"CASUAL": "استخدم نبرة عادية",
"STRAIGHTFORWARD": "استخدام نبرة مباشرة"
},
"REPLY_OPTIONS": {
"IMPROVE_REPLY": "تحسين الرد",
"IMPROVE_REPLY_SELECTION": "تحسين عملية الاختيار",
"CHANGE_TONE": {
"TITLE": "تغيير النبرة",
"OPTIONS": {
"PROFESSIONAL": "مهني",
"CASUAL": "عادية",
"STRAIGHTFORWARD": "مباشر",
"CONFIDENT": "لطيفة",
"FRIENDLY": "ودي"
}
},
"GRAMMAR": "أصلاح القواعد النحوية والإملائية",
"SUGGESTION": "اقترح رداً",
"SUMMARIZE": "تلخيص المحادثة",
"ASK_COPILOT": "إسأل المساعد"
},
"ASSISTANCE_MODAL": {
"DRAFT_TITLE": "Draft content",
@@ -201,12 +238,16 @@
"SIDEBAR_TXT": "<p><b>Dashboard Apps</b></p><p>Dashboard Apps allow organizations to embed an application inside the Chatwoot dashboard to provide the context for customer support agents. This feature allows you to create an application independently and embed that inside the dashboard to provide user information, their orders, or their previous payment history.</p><p>When you embed your application using the dashboard in Chatwoot, your application will get the context of the conversation and contact as a window event. Implement a listener for the message event on your page to receive the context.</p><p>To add a new dashboard app, click on the button 'Add a new dashboard app'.</p>",
"DESCRIPTION": "تسمح تطبيقات لوحة التحكم للمنظمات بتضمين تطبيق داخل لوحة التحكم لتوفير السياق لوكلاء دعم العملاء. هذه الميزة تسمح لك بإنشاء تطبيق بشكل مستقل وإدراج لتوفير معلومات المستخدم أو طلباتهم أو سجل الدفع السابق.",
"LEARN_MORE": "معرفة المزيد حول تطبيقات لوحة التحكم",
"COUNT": "{n} dashboard app | {n} dashboard apps",
"SEARCH_PLACEHOLDER": "Search dashboard apps...",
"NO_RESULTS": "No dashboard apps found matching your search",
"LIST": {
"404": "لا توجد تطبيقات لوحة التحكم التي تم تكوينها على هذا الحساب حتى الآن",
"LOADING": "جلب تطبيقات لوحة التحكم...",
"TABLE_HEADER": {
"NAME": "الاسم",
"ENDPOINT": "نقطة الوصول"
"ENDPOINT": "نقطة الوصول",
"ACTIONS": "الإجراءات"
},
"EDIT_TOOLTIP": "تعديل التطبيق",
"DELETE_TOOLTIP": "حذف التطبيق"
@@ -243,6 +284,7 @@
}
},
"LINEAR": {
"HEADER": "Linear",
"ADD_OR_LINK_BUTTON": "Create/Link Linear Issue",
"LOADING": "جلب مشاكل من Linear...",
"LOADING_ERROR": "حدث خطأ أثناء جلب المشكلات من Linear، الرجاء المحاولة مرة أخرى",
@@ -337,6 +379,7 @@
}
},
"NOTION": {
"HEADER": "نوشن",
"DELETE": {
"TITLE": "Are you sure you want to delete the Notion integration?",
"MESSAGE": "Deleting this integration will remove access to your Notion workspace and stop all related functionality.",
@@ -406,6 +449,7 @@
"CANCEL_ANYTIME": "You can change or cancel your plan anytime"
},
"ENTERPRISE_PAYWALL": {
"AVAILABLE_ON": "ولا يتوفر الكابتن AI إلا في خطط المؤسسة.",
"UPGRADE_PROMPT": "Upgrade your plan to get access to our assistants, copilot and more.",
"ASK_ADMIN": "Please reach out to your administrator for the upgrade."
},
@@ -483,7 +527,8 @@
"TITLE": "الخصائص",
"ALLOW_CONVERSATION_FAQS": "Generate FAQs from resolved conversations",
"ALLOW_MEMORIES": "Capture key details as memories from customer interactions.",
"ALLOW_CITATIONS": "Include source citations in responses"
"ALLOW_CITATIONS": "Include source citations in responses",
"ALLOW_CONTACT_ATTRIBUTES": "Allow access to contact information"
}
},
"EDIT": {
@@ -5,6 +5,9 @@
"LOADING": "جار جلب الوسوم",
"DESCRIPTION": "Labels help you categorize and prioritize conversations and leads. You can assign a label to a conversation or contact using the side panel.",
"LEARN_MORE": "معرفة المزيد حول التسميات",
"COUNT": "{n} label | {n} labels",
"SEARCH_PLACEHOLDER": "ابحث عن تصنيفات...",
"NO_RESULTS": "No labels found matching your search",
"SEARCH_404": "لا توجد عناصر مطابقة لهذا الاستعلام",
"LIST": {
"404": "لا توجد وسوم متوفرة في هذا الحساب.",
@@ -13,7 +16,8 @@
"TABLE_HEADER": {
"NAME": "الاسم",
"DESCRIPTION": "الوصف",
"COLOR": "اللون"
"COLOR": "اللون",
"ACTION": "الإجراءات"
}
},
"FORM": {
@@ -3,9 +3,12 @@
"HEADER": "ماكروس",
"DESCRIPTION": "الماكرو هو مجموعة من الإجراءات المحفوظة التي تساعد وكلاء خدمة العملاء على إكمال المهام بسهولة. يمكن للوكلاء تحديد مجموعة من الإجراءات مثل وضع علامة على محادثة مع تسمية، وإرسال نص بريد إلكتروني، وتحديث سمة مخصصة، إلخ. ويمكنهم تنفيذ هذه الإجراءات بنقرة واحدة.",
"LEARN_MORE": "تعلم المزيد حول الماكرو",
"COUNT": "{n} macro | {n} macros",
"HEADER_BTN_TXT": "إضافة ماكرو جديد",
"HEADER_BTN_TXT_SAVE": "حفظ الماكرو",
"LOADING": "جاري جلب الماكروس",
"SEARCH_PLACEHOLDER": "Search macros...",
"NO_RESULTS": "No macros found matching your search",
"ERROR": "حدث خطأ ما. الرجاء المحاولة مرة أخرى",
"ORDER_INFO": "سيتم تشغيل الماكرو بالترتيب الذي تضيفه إجراءاتك. يمكنك إعادة ترتيبهم بسحبهم بواسطة المعالج بجانب كل عقدة.",
"ADD": {
@@ -29,7 +32,8 @@
"NAME": "الاسم",
"CREATED BY": "تم إنشاؤها بواسطة",
"LAST_UPDATED_BY": "آخر تحديث بواسطة",
"VISIBILITY": "الظهور"
"VISIBILITY": "الظهور",
"ACTIONS": "الإجراءات"
},
"404": "لم يتم العثور على الماكروس"
},
@@ -1,7 +1,7 @@
{
"MFA_SETTINGS": {
"TITLE": "Two-Factor Authentication",
"SUBTITLE": "Secure your account with TOTP-based authentication",
"SUBTITLE": "Protect your account from unauthorized access with TOTP-based authentication. This adds an extra layer of security to your account.",
"DESCRIPTION": "Add an extra layer of security to your account using a time-based one-time password (TOTP)",
"STATUS_TITLE": "Authentication Status",
"STATUS_DESCRIPTION": "Manage your two-factor authentication settings and backup recovery codes",
@@ -3,7 +3,7 @@
"HEADER": "المحادثات",
"LOADING_CHART": "تحميل بيانات الرسم البياني...",
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
"DOWNLOAD_AGENT_REPORTS": حميل تقارير وكيل",
"DOWNLOAD_CONVERSATION_REPORTS": نزيل تقارير المحادثات",
"DATA_FETCHING_FAILED": "Failed to fetch data, please try again later.",
"SUMMARY_FETCHING_FAILED": "Failed to fetch summary, please try again later.",
"METRICS": {
@@ -128,11 +128,16 @@
},
"AGENT_REPORTS": {
"HEADER": "نظرة عامة للوكلاء",
"DESCRIPTION": "Easily track agent performance with key metrics such as conversations, response times, resolution times, and resolved cases. Click an agents name to learn more.",
"DESCRIPTION": "Easily track agent performance with key metrics such as conversations, response times, resolution times, and resolved cases. Click an agent's name to learn more.",
"LOADING_CHART": "جاري جلب بيانات الرسم البياني...",
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
"DOWNLOAD_AGENT_REPORTS": "تنزيل تقارير الوكيل",
"FILTER_DROPDOWN_LABEL": "اختر وكيل",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"AGENTS": "البحث عن وكلاء"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "المحادثات",
@@ -201,6 +206,11 @@
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
"DOWNLOAD_LABEL_REPORTS": "تحميل تقارير التسمية",
"FILTER_DROPDOWN_LABEL": "حدد التسمية",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"LABELS": "ابحث عن تصنيفات"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "المحادثات",
@@ -271,6 +281,11 @@
"FILTER_DROPDOWN_LABEL": "اختر صندوق الوارد",
"ALL_INBOXES": "All Inboxes",
"SEARCH_INBOX": "Search Inbox",
"FILTERS": {
"INPUT_PLACEHOLDER": {
"INBOXES": "Search inboxes"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "المحادثات",
@@ -334,11 +349,19 @@
},
"TEAM_REPORTS": {
"HEADER": "نظرة عامة للفريق",
"DESCRIPTION": "Get a snapshot of your teams performance with essential metrics, including conversations, response times, resolution times, and resolved cases. Click a team name for more details.",
"DESCRIPTION": "Get a snapshot of your team's performance with essential metrics, including conversations, response times, resolution times, and resolved cases. Click a team name for more details.",
"LOADING_CHART": "تحميل بيانات الرسم البياني...",
"NO_ENOUGH_DATA": "لم يتم جمع بيانات بقدر كافي لإنشاء التقرير، الرجاء المحاولة مرة أخرى لاحقاً.",
"DOWNLOAD_TEAM_REPORTS": "تحميل تقارير الفريق",
"FILTER_DROPDOWN_LABEL": "اختيار فريق",
"FILTERS": {
"ADD_FILTER": "إضافة تصفية",
"CLEAR_ALL": "مسح الكل",
"NO_FILTER": "لا توجد عوامل تصفية متوفرة",
"INPUT_PLACEHOLDER": {
"TEAMS": "البحث عن فريق"
}
},
"METRICS": {
"CONVERSATIONS": {
"NAME": "المحادثات",
@@ -402,22 +425,48 @@
},
"CSAT_REPORTS": {
"HEADER": "تقارير CSAT",
"NO_RECORDS": "لا توجد ردود متوفرة على الدراسة الاستقصائية CSAT.",
"NO_RECORDS": "No responses yet",
"NO_RECORDS_DESCRIPTION": "CSAT survey responses will appear here once customers start providing feedback.",
"DOWNLOAD": "تحميل تقرير رضاء خدمة العملاء",
"DOWNLOAD_FAILED": "Failed to download CSAT Reports",
"FILTERS": {
"ADD_FILTER": "إضافة تصفية",
"CLEAR_ALL": "مسح الكل",
"NO_FILTER": "لا توجد عوامل تصفية متوفرة",
"INPUT_PLACEHOLDER": {
"AGENTS": "البحث عن وكلاء",
"INBOXES": "Search inboxes",
"TEAMS": "البحث عن فريق",
"RATINGS": "البحث في التقييمات"
},
"AGENTS": {
"PLACEHOLDER": "اختر الوكلاء"
"LABEL": "وكيل الدعم"
},
"INBOXES": {
"LABEL": "صندوق الوارد"
},
"TEAMS": {
"LABEL": "الفريق"
},
"RATINGS": {
"LABEL": "التقييم"
}
},
"TABLE": {
"HEADER": {
"CONTACT_NAME": "جهات الاتصال",
"AGENT_NAME": "الوكيل المكلف",
"AGENT_NAME": "وكيل الدعم",
"RATING": "التقييم",
"FEEDBACK_TEXT": "تعليق الملاحظات"
}
"FEEDBACK_TEXT": "تعليق الملاحظات",
"CONVERSATION": "المحادثات",
"CUSTOMER": "عميل",
"RESPONSE": "الردود",
"HANDLED_BY": "تمت معالجتها بواسطة"
},
"UNKNOWN_CUSTOMER": "عميل غير معروف"
},
"NO_AGENT": "لم يتم تعيين وكيل",
"NO_FEEDBACK": "لا توجد ملاحظات مقدمة",
"METRIC": {
"TOTAL_RESPONSES": {
"LABEL": "إجمالي الردود",
@@ -430,6 +479,25 @@
"RESPONSE_RATE": {
"LABEL": "معدل الاستجابة",
"TOOLTIP": "العدد الإجمالي للردود / العدد الإجمالي لرسائل الاستقصاء التي أرسلتها CSAT * 100"
},
"RATING_DISTRIBUTION": "توزيع التقييم"
},
"REVIEW_NOTES": {
"TITLE": "ملاحظات المراجعة",
"PLACEHOLDER": "إضافة ملاحظات مراجعة حول هذا التقييم...",
"SAVE": "حفظ",
"CANCEL": "إلغاء",
"SAVING": "جاري الحفظ...",
"SAVED": "تم حفظ الملاحظات بنجاح",
"SAVE_ERROR": "فشل في حفظ الملاحظات",
"UPDATED_BY": "تم التحديث بواسطة {name} {time}",
"UPDATED_BY_LABEL": "تم التحديث بواسطة",
"PAYWALL": {
"TITLE": "قم بالترقية لإضافة ملاحظات المراجعة",
"AVAILABLE_ON": "ميزة مراجعة الملاحظات متاحة فقط في الخطط Business و Enterprise.",
"UPGRADE_PROMPT": "Add internal context to every CSAT response with review notes. Capture what really happened, spot patterns faster, and make better decisions from your feedback.",
"UPGRADE_NOW": "الترقية الآن",
"CANCEL_ANYTIME": "You can change or cancel your plan anytime"
}
}
},
@@ -1,7 +1,7 @@
{
"SEARCH": {
"TABS": {
"ALL": "All results",
"ALL": "كل النتائج",
"CONTACTS": "جهات الاتصال",
"CONVERSATIONS": "المحادثات",
"MESSAGES": "الرسائل",
@@ -21,48 +21,48 @@
"EMPTY_STATE_FULL": "لم يتم العثور على نتائج للطلب '{query}'",
"PLACEHOLDER_KEYBINDING": "/للتركيز",
"INPUT_PLACEHOLDER": "أكتب 3 أحرف أو أكثر للبحث",
"RECENT_SEARCHES": "Recent searches",
"RECENT_SEARCHES": "عمليات البحث الأخيرة",
"CLEAR_ALL": "Clear all",
"MOST_RECENT": "Most recent",
"MOST_RECENT": "الأحدث",
"EMPTY_STATE_DEFAULT": "البحث عن طريق معرف المحادثة أو البريد الإلكتروني أو رقم الهاتف أو الرسائل للحصول على نتائج بحث أفضل. ",
"BOT_LABEL": "رد آلي",
"READ_MORE": "اقرأ المزيد",
"READ_LESS": "Read less",
"READ_LESS": "قراءة أقل",
"WROTE": "كتب:",
"FROM": "من",
"EMAIL": "البريد الإلكتروني",
"EMAIL_SUBJECT": "الموضوع",
"PRIVATE": "Private note",
"TRANSCRIPT": "Transcript",
"PRIVATE": "ملاحظة خاصة",
"TRANSCRIPT": "النص",
"CREATED_AT": "created {time}",
"UPDATED_AT": "updated {time}",
"UPDATED_AT": "تم التحديث {time}",
"SORT_BY": {
"RELEVANCE": "Relevance"
"RELEVANCE": "ذات صلة"
},
"DATE_RANGE": {
"LAST_7_DAYS": "آخر 7 أيام",
"LAST_30_DAYS": "آخر 30 يوماً",
"LAST_60_DAYS": "آخر 60 يوماً",
"LAST_90_DAYS": "آخر 90 يوماً",
"CUSTOM_RANGE": "Custom range:",
"CREATED_BETWEEN": "Created between",
"CUSTOM_RANGE": "نطاق مخصص:",
"CREATED_BETWEEN": "تم الإنشاء بين",
"AND": "و",
"APPLY": "تطبيق",
"BEFORE_DATE": "Before {date}",
"AFTER_DATE": "After {date}",
"TIME_RANGE": "Filter by time",
"CLEAR_FILTER": "Clear filter"
"BEFORE_DATE": "قبل {date}",
"AFTER_DATE": "بعد {date}",
"TIME_RANGE": "التصفية حسب الوقت",
"CLEAR_FILTER": "مسح عامل التصفية"
},
"FILTERS": {
"FILTER_MESSAGE": "Filter messages by:",
"FILTER_MESSAGE": "تصفية الرسائل بواسطة:",
"FROM": "المرسل",
"IN": "صندوق الوارد",
"AGENTS": "الوكلاء",
"CONTACTS": "جهات الاتصال",
"INBOXES": "قنوات التواصل",
"NO_AGENTS": "لم يتم العثور على وكلاء",
"NO_CONTACTS": "Start by searching to see results",
"NO_INBOXES": "No inboxes found"
"NO_CONTACTS": "ابدأ بالبحث لمشاهدة النتائج",
"NO_INBOXES": "لم يتم العثور على صناديق الوارد"
}
}
}
@@ -273,7 +273,8 @@
"FILE_BUBBLE": {
"DOWNLOAD": "تنزيل",
"UPLOADING": "جاري الرفع...",
"INSTAGRAM_STORY_UNAVAILABLE": "هذه القصة لم تعد متاحة."
"INSTAGRAM_STORY_UNAVAILABLE": "هذه القصة لم تعد متاحة.",
"INSTAGRAM_STORY_REPLY": "رد على قصتك:"
},
"LOCATION_BUBBLE": {
"SEE_ON_MAP": "مشاهدة على الخريطة"
@@ -307,8 +308,8 @@
"SETTINGS": "الإعدادات",
"CONTACTS": "جهات الاتصال",
"ACTIVE": "مفعل",
"COMPANIES": "Companies",
"ALL_COMPANIES": "All Companies",
"COMPANIES": "الشركات",
"ALL_COMPANIES": "كل الحملات",
"CAPTAIN": "قائد",
"CAPTAIN_ASSISTANTS": "Assistants",
"CAPTAIN_DOCUMENTS": "Documents",
@@ -378,7 +379,57 @@
"INFO_SHORT": "Automatically mark offline when you aren't using the app."
},
"DOCS": "قراءة المستندات",
"SECURITY": "Security"
"SECURITY": "Security",
"CAPTAIN_AI": "قائد",
"CONVERSATION_WORKFLOW": "Conversation Workflow"
},
"CAPTAIN_SETTINGS": {
"TITLE": "Captain Settings",
"DESCRIPTION": "Configure your AI models and features for Captain. Captain follows a credit based billing, you will be charged credits for every action Captain takes based on the model selected.",
"LOADING": "Loading Captain configuration...",
"LINK_TEXT": "Learn more about Captain Credits",
"NOT_ENABLED": "Captain is not enabled for your account. Please upgrade your plan to access Captain features.",
"MODEL_CONFIG": {
"TITLE": "Model Configuration",
"DESCRIPTION": "Select AI models for different features.",
"SELECT_MODEL": "Select model",
"CREDITS_PER_MESSAGE": "{credits} credit/message",
"COMING_SOON": "Coming soon",
"EDITOR": {
"TITLE": "Editor Features",
"DESCRIPTION": "Powers smart compose, grammar corrections, tone adjustments, and content enhancement in your message editor."
},
"ASSISTANT": {
"TITLE": "Assistant",
"DESCRIPTION": "Handles automated responses, conversation summaries, and intelligent reply suggestions for customer interactions."
},
"COPILOT": {
"TITLE": "Co-pilot",
"DESCRIPTION": "Provides real-time contextual suggestions, knowledge base recommendations, and proactive insights during conversations."
}
},
"FEATURES": {
"TITLE": "الخصائص",
"DESCRIPTION": "Enable or disable AI-powered features.",
"AUDIO_TRANSCRIPTION": {
"TITLE": "Audio Transcription",
"DESCRIPTION": "Automatically convert voice messages and call recordings into searchable text transcripts."
},
"HELP_CENTER_SEARCH": {
"TITLE": "Help Center Search Indexing",
"DESCRIPTION": "Use AI for context aware search inside your help center articles."
},
"LABEL_SUGGESTION": {
"TITLE": "Label Suggestion",
"DESCRIPTION": "Automatically suggest relevant labels and tags for conversations based on content analysis and context.",
"MODEL_TITLE": "Label Suggestion Model",
"MODEL_DESCRIPTION": "Select the AI model to use for analyzing conversations and suggesting appropriate labels"
}
},
"API": {
"SUCCESS": "Captain settings updated successfully.",
"ERROR": "Failed to update Captain settings. Please try again."
}
},
"BILLING_SETTINGS": {
"TITLE": "الفواتير",
@@ -506,6 +557,58 @@
}
}
},
"CONVERSATION_WORKFLOW": {
"INDEX": {
"HEADER": {
"TITLE": "Conversation Workflows",
"DESCRIPTION": "Configure rules and required fields for conversation resolution."
}
},
"REQUIRED_ATTRIBUTES": {
"TITLE": "Attributes required on resolution",
"DESCRIPTION": "When resolving a conversation, agents will be prompted to fill these attributes if they haven't yet.",
"NO_ATTRIBUTES": "No attributes added yet",
"ADD": {
"TITLE": "Add Attributes",
"SEARCH_PLACEHOLDER": "البحث عن صفات"
},
"SAVE": {
"SUCCESS": "Required attributes updated",
"ERROR": "Could not update required attributes, please try again"
},
"MODAL": {
"TITLE": "حل المحادثة",
"DESCRIPTION": "Please fill in the following custom attributes before resolving this conversation",
"ACTIONS": {
"RESOLVE": "حل المحادثة",
"CANCEL": "إلغاء"
},
"PLACEHOLDERS": {
"TEXT": "Write a note...",
"NUMBER": "Enter a number",
"LINK": "Add a link",
"DATE": "Pick a date",
"LIST": "Select an option"
},
"CHECKBOX": {
"YES": "نعم",
"NO": "لا"
}
},
"PAYWALL": {
"TITLE": "Upgrade to use required attributes",
"AVAILABLE_ON": "The required conversation attributes feature is available on the Business and Enterprise plans.",
"UPGRADE_PROMPT": "Upgrade your plan to prompt agents to fill required attributes before conversation resolution.",
"UPGRADE_NOW": "Upgrade now",
"CANCEL_ANYTIME": "You can change or cancel your plan anytime"
},
"ENTERPRISE_PAYWALL": {
"AVAILABLE_ON": "The required conversation attributes feature is available on the paid plans.",
"UPGRADE_PROMPT": "Upgrade to a paid plan to enforce required attributes before conversation resolution.",
"ASK_ADMIN": "Please reach out to your administrator for the upgrade."
}
}
},
"CREATE_ACCOUNT": {
"NO_ACCOUNT_WARNING": "أوه! لم نتمكن من العثور على الحساب. الرجاء إنشاء حساب جديد للمتابعة.",
"NEW_ACCOUNT": "حساب جديد",
@@ -591,7 +694,8 @@
"CREATE_BUTTON": "Create policy",
"API": {
"SUCCESS_MESSAGE": "Assignment policy created successfully",
"ERROR_MESSAGE": "Failed to create assignment policy"
"ERROR_MESSAGE": "Failed to create assignment policy",
"INBOX_LINKED": "Inbox has been linked to the policy"
}
},
"EDIT": {
@@ -605,6 +709,12 @@
"CONFIRM_BUTTON_LABEL": "Continue",
"CANCEL_BUTTON_LABEL": "إلغاء"
},
"INBOX_LINK_PROMPT": {
"TITLE": "Link inbox to policy",
"DESCRIPTION": "Would you like to link this inbox to the assignment policy?",
"LINK_BUTTON": "Link inbox",
"CANCEL_BUTTON": "Skip"
},
"API": {
"SUCCESS_MESSAGE": "Assignment policy updated successfully",
"ERROR_MESSAGE": "Failed to update assignment policy"
@@ -643,7 +753,9 @@
},
"BALANCED": {
"LABEL": "Balanced",
"DESCRIPTION": "Assign conversations based on available capacity."
"DESCRIPTION": "Assign conversations based on available capacity.",
"PREMIUM_MESSAGE": "Upgrade to access balanced assignment and agent capacity management.",
"PREMIUM_BADGE": "Premium"
}
},
"ASSIGNMENT_PRIORITY": {
@@ -729,6 +841,20 @@
"SUCCESS_MESSAGE": "Agent removed from policy successfully",
"ERROR_MESSAGE": "Failed to remove agent from policy"
}
},
"INBOX_LIMIT_API": {
"ADD": {
"SUCCESS_MESSAGE": "Inbox limit added successfully",
"ERROR_MESSAGE": "Failed to add inbox limit"
},
"UPDATE": {
"SUCCESS_MESSAGE": "Inbox limit updated successfully",
"ERROR_MESSAGE": "Failed to update inbox limit"
},
"DELETE": {
"SUCCESS_MESSAGE": "Inbox limit deleted successfully",
"ERROR_MESSAGE": "Failed to delete inbox limit"
}
}
},
"FORM": {
@@ -1,6 +1,7 @@
{
"REGISTER": {
"TRY_WOOT": "تسجيل حساب",
"GET_STARTED": "Get started with Chatwoot",
"TITLE": "تسجيل",
"TESTIMONIAL_HEADER": "إن كل ما يلزم هو خطوة واحدة للمضي قدما",
"TESTIMONIAL_CONTENT": "You're one step away from engaging your customers, retaining them and finding new ones.",
@@ -5,7 +5,12 @@
"ADD_ACTION_LONG": "Create a new SLA Policy",
"DESCRIPTION": "Service Level Agreements (SLAs) are contracts that define clear expectations between your team and customers. They establish standards for response and resolution times, creating a framework for accountability and ensures a consistent, high-quality experience.",
"LEARN_MORE": "Learn more about SLA",
"COUNT": "{n} SLA | {n} SLAs",
"LOADING": "Fetching SLAs",
"SEARCH_PLACEHOLDER": "Search SLA...",
"SEARCH": {
"NO_RESULTS": "No SLA found matching your search"
},
"PAYWALL": {
"TITLE": "Upgrade to create SLAs",
"AVAILABLE_ON": "The SLA feature is only available in the Business and Enterprise plans.",
@@ -20,14 +25,18 @@
},
"LIST": {
"404": "There are no SLAs available in this account.",
"TABLE_HEADER": {
"SLA": "SLA",
"BUSINESS_HOURS": "Business hours"
},
"EMPTY": {
"TITLE_1": "Enterprise P0",
"DESC_1": "Issues raised by enterprise customers, that require immediate attention.",
"TITLE_2": "Enterprise P1",
"DESC_2": "Issues raised by enterprise customers, that needs to be acknowledged quickly."
},
"BUSINESS_HOURS_ON": "Business hours on",
"BUSINESS_HOURS_OFF": "Business hours off",
"BUSINESS_HOURS_ON": "Turned on",
"BUSINESS_HOURS_OFF": "Turned off",
"RESPONSE_TYPES": {
"FRT": "First response time threshold",
"NRT": "Next response time threshold",
@@ -0,0 +1,72 @@
{
"SNOOZE_PARSER": {
"UNITS": {
"MINUTE": "minute",
"MINUTES": "minutes",
"HOUR": "hour",
"HOURS": "ساعات",
"DAY": "اليوم",
"DAYS": "days",
"WEEK": "اليوم",
"WEEKS": "weeks",
"MONTH": "الأسبوع",
"MONTHS": "months",
"YEAR": "الشهر",
"YEARS": "years"
},
"HALF": "half",
"NEXT": "التالي",
"THIS": "this",
"AT": "at",
"IN": "in",
"FROM_NOW": "from now",
"NEXT_YEAR": "next year",
"MERIDIEM": {
"AM": "am",
"PM": "pm"
},
"RELATIVE": {
"TOMORROW": "غداً",
"DAY_AFTER_TOMORROW": "day after tomorrow",
"NEXT_WEEK": "الأسبوع القادم",
"NEXT_MONTH": "next month",
"THIS_WEEKEND": "this weekend",
"NEXT_WEEKEND": "next weekend"
},
"TIME_OF_DAY": {
"MORNING": "morning",
"AFTERNOON": "afternoon",
"EVENING": "evening",
"NIGHT": "night",
"NOON": "noon",
"MIDNIGHT": "midnight"
},
"WORD_NUMBERS": {
"ONE": "one",
"TWO": "two",
"THREE": "three",
"FOUR": "four",
"FIVE": "five",
"SIX": "six",
"SEVEN": "seven",
"EIGHT": "eight",
"NINE": "nine",
"TEN": "ten",
"TWELVE": "twelve",
"FIFTEEN": "fifteen",
"TWENTY": "twenty",
"THIRTY": "thirty"
},
"ORDINALS": {
"FIRST": "first",
"SECOND": "second",
"THIRD": "third",
"FOURTH": "fourth",
"FIFTH": "fifth"
},
"OF": "of",
"AFTER": "after",
"WEEK": "اليوم",
"DAY": "اليوم"
}
}
@@ -5,6 +5,9 @@
"LOADING": "Fetching teams",
"DESCRIPTION": "الفرق تتيح لك تنظيم الوكلاء في مجموعات بناءً على مسؤولياتهم. يمكن للوكيل أن يكون عضوًا في أكثر من فريق. لتحقيق التعاون في العمل, يمكنك إسناد المحادثات لفرق محددة.",
"LEARN_MORE": "لمعرفة المزيد حول الفرق",
"COUNT": "{n} team | {n} teams",
"SEARCH_PLACEHOLDER": "البحث عن فريق...",
"NO_RESULTS": "No teams found matching your search",
"LIST": {
"404": "لا يوجد موظفي دعم مرتبطين بهذا الحساب.",
"EDIT_TEAM": "تعديل الفريق",
@@ -64,7 +67,7 @@
"ERROR_MESSAGE": "تعذر حفظ تفاصيل الفريق. حاول مرة أخرى."
},
"AGENTS": {
"AGENT": "وكيل",
"AGENT": "وكيل الدعم",
"EMAIL": "البريد الإلكتروني",
"BUTTON_TEXT": "إضافة وكلاء",
"ADD_AGENTS": "إضافة وكلاء إلى فريقك...",
@@ -4,6 +4,9 @@
"LOADING_EDITOR": "Loading editor...",
"DESCRIPTION": "Agent Bots are like the most fabulous members of your team. They can handle the small stuff, so you can focus on the stuff that matters. Give them a try. You can manage your bots from this page or create new ones using the 'Add Bot' button.",
"LEARN_MORE": "Learn about agent bots",
"COUNT": "{n} bot | {n} bots",
"SEARCH_PLACEHOLDER": "Search bots...",
"NO_RESULTS": "No bots found matching your search",
"GLOBAL_BOT": "System bot",
"GLOBAL_BOT_BADGE": "System",
"AVATAR": {
@@ -34,7 +37,8 @@
"LOADING": "Fetching bots...",
"TABLE_HEADER": {
"DETAILS": "Bot Details",
"URL": "Webhook URL"
"URL": "Webhook URL",
"ACTIONS": "Actions"
}
},
"DELETE": {
@@ -9,6 +9,7 @@
"ADMINISTRATOR": "Administrator",
"AGENT": "Agent"
},
"COUNT": "{n} agent | {n} agents",
"LIST": {
"404": "There are no agents associated to this account",
"TITLE": "Manage agents in your team",
@@ -96,6 +97,8 @@
"ERROR_MESSAGE": "Could not connect to Woot Server, Please try again later"
}
},
"SEARCH_PLACEHOLDER": "Search agents...",
"NO_RESULTS": "No agents found matching your search",
"SEARCH": {
"NO_RESULTS": "No results found."
},
@@ -5,6 +5,9 @@
"LOADING": "Fetching custom attributes",
"DESCRIPTION": "A custom attribute tracks additional details about your contacts or conversations—such as the subscription plan or the date of their first purchase. You can add different types of custom attributes, such as text, lists, or numbers, to capture the specific information you need.",
"LEARN_MORE": "Learn more about custom attributes",
"COUNT": "{n} attribute | {n} attributes",
"SEARCH_PLACEHOLDER": "Search attributes...",
"NO_RESULTS": "No attributes found matching your search",
"ATTRIBUTE_MODELS": {
"CONVERSATION": "Conversation",
"CONTACT": "Contact"
@@ -63,6 +66,10 @@
},
"ENABLE_REGEX": {
"LABEL": "Enable regex validation"
},
"BADGES": {
"PRE_CHAT": "Pre-chat",
"RESOLUTION": "Resolution"
}
},
"API": {
@@ -3,8 +3,11 @@
"HEADER": "Automation",
"DESCRIPTION": "Automation can replace and streamline existing processes that require manual effort, such as adding labels and assigning conversations to the most suitable agent. This allows the team to focus on their strengths while reducing time spent on routine tasks.",
"LEARN_MORE": "Learn more about automation",
"HEADER_BTN_TXT": "Add Automation Rule",
"COUNT": "{n} automation | {n} automations",
"HEADER_BTN_TXT": "Create Automation",
"LOADING": "Fetching automation rules",
"SEARCH_PLACEHOLDER": "Search automation rules...",
"NO_RESULTS": "No automation rules found matching your search",
"ADD": {
"TITLE": "Add Automation Rule",
"SUBMIT": "Create",
@@ -42,9 +45,9 @@
"LIST": {
"TABLE_HEADER": {
"NAME": "Name",
"DESCRIPTION": "Description",
"ACTIVE": "Active",
"CREATED_ON": "Created on"
"CREATED_ON": "Created on",
"ACTIONS": "Actions"
},
"404": "No automation rules found"
},
@@ -150,7 +153,8 @@
"ADD_PRIVATE_NOTE": "Add a Private Note",
"CHANGE_PRIORITY": "Change Priority",
"ADD_SLA": "Add SLA",
"OPEN_CONVERSATION": "Open conversation"
"OPEN_CONVERSATION": "Open conversation",
"PENDING_CONVERSATION": "Mark conversation as pending"
},
"MESSAGE_TYPES": {
"INCOMING": "Incoming Message",
@@ -22,6 +22,10 @@
"UPDATE_SUCCESFUL": "Conversation status updated successfully.",
"UPDATE_FAILED": "Failed to update conversations. Please try again."
},
"RESOLVE": {
"ALL_MISSING_ATTRIBUTES": "Cannot resolve conversations due to missing required attributes",
"PARTIAL_SUCCESS": "Some conversations need required attributes before resolving and were skipped"
},
"LABELS": {
"ASSIGN_LABELS": "Assign labels",
"NO_LABELS_FOUND": "No labels found",
@@ -3,8 +3,11 @@
"HEADER": "Canned Responses",
"LEARN_MORE": "Learn more about canned responses",
"DESCRIPTION": "Canned Responses are pre-written reply templates that help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a canned response during a conversation. ",
"COUNT": "{n} canned response | {n} canned responses",
"HEADER_BTN_TXT": "Add canned response",
"LOADING": "Fetching canned responses...",
"SEARCH_PLACEHOLDER": "Search canned responses...",
"NO_RESULTS": "No canned responses found matching your search",
"SEARCH_404": "There are no items matching this query.",
"LIST": {
"404": "There are no canned responses available in this account.",
@@ -76,6 +76,9 @@
},
"waiting_since_desc": {
"TEXT": "Pending Response: Shortest first"
},
"priority_desc_created_at_asc": {
"TEXT": "Priority: Highest first, Created: Oldest first"
}
},
"ATTACHMENTS": {
@@ -1,31 +1,31 @@
{
"CONTACT_PANEL": {
"NOT_AVAILABLE": "Not Available",
"NOT_AVAILABLE": "Mövcud deyil",
"EMAIL_ADDRESS": "Email Address",
"PHONE_NUMBER": "Phone number",
"PHONE_NUMBER": "Telefon nömrəsi",
"IDENTIFIER": "Identifier",
"COPY_SUCCESSFUL": "Copied to clipboard successfully",
"COMPANY": "Company",
"LOCATION": "Location",
"COMPANY": "Şirkət",
"LOCATION": "Yer",
"BROWSER_LANGUAGE": "Browser Language",
"CONVERSATION_TITLE": "Conversation Details",
"VIEW_PROFILE": "View Profile",
"BROWSER": "Browser",
"OS": "Operating System",
"INITIATED_FROM": "Initiated from",
"INITIATED_AT": "Initiated at",
"IP_ADDRESS": "IP Address",
"CREATED_AT_LABEL": "Created",
"OS": "Əməliyyat Sistemi",
"INITIATED_FROM": "Başlanğıc yeri",
"INITIATED_AT": "Başlanğıc vaxtı",
"IP_ADDRESS": "IP ünvanı",
"CREATED_AT_LABEL": "Yaradılıb",
"NEW_MESSAGE": "New message",
"CALL": "Call",
"CALL": "Zəng et",
"CALL_INITIATED": "Calling the contact…",
"CALL_FAILED": "Unable to start the call. Please try again.",
"VOICE_INBOX_PICKER": {
"TITLE": "Choose a voice inbox"
},
"CONVERSATIONS": {
"NO_RECORDS_FOUND": "There are no previous conversations associated to this contact.",
"TITLE": "Previous Conversations"
"NO_RECORDS_FOUND": "Bu əlaqə ilə bağlı əvvəlki söhbətlər yoxdur.",
"TITLE": "Əvvəlki Söhbətlər"
},
"LABELS": {
"CONTACT": {
@@ -44,23 +44,23 @@
}
},
"MERGE_CONTACT": "Merge contact",
"CONTACT_ACTIONS": "Contact actions",
"CONTACT_ACTIONS": "Əlaqə əməliyyatları",
"MUTE_CONTACT": "Block Contact",
"UNMUTE_CONTACT": "Unblock Contact",
"MUTED_SUCCESS": "This contact is blocked successfully. You will not be notified of any future conversations.",
"UNMUTED_SUCCESS": "This contact is unblocked successfully.",
"SEND_TRANSCRIPT": "Send Transcript",
"EDIT_LABEL": "Edit",
"UNMUTED_SUCCESS": "Bu əlaqənin bloku uğurla açıldı.",
"SEND_TRANSCRIPT": "Mətni Göndər",
"EDIT_LABEL": "Redaktə et",
"SIDEBAR_SECTIONS": {
"CUSTOM_ATTRIBUTES": "Custom Attributes",
"CONTACT_LABELS": "Contact Labels",
"PREVIOUS_CONVERSATIONS": "Previous Conversations",
"PREVIOUS_CONVERSATIONS": "Əvvəlki Söhbətlər",
"NO_RECORDS_FOUND": "No attributes found"
}
},
"EDIT_CONTACT": {
"BUTTON_LABEL": "Edit Contact",
"TITLE": "Edit contact",
"BUTTON_LABEL": "Əlaqəni redaktə et",
"TITLE": "Əlaqəni redaktə et",
"DESC": "Edit contact details"
},
"DELETE_CONTACT": {
@@ -71,23 +71,23 @@
"TITLE": "Confirm Deletion",
"MESSAGE": "Are you sure to delete ",
"YES": "Yes, Delete",
"NO": "No, Keep"
"NO": "Xeyr, Saxla"
},
"API": {
"SUCCESS_MESSAGE": "Contact deleted successfully",
"ERROR_MESSAGE": "Could not delete contact. Please try again later."
"ERROR_MESSAGE": "Əlaqəni silmək mümkün olmadı. Zəhmət olmasa, bir az sonra yenidən cəhd edin."
}
},
"CONTACT_FORM": {
"FORM": {
"SUBMIT": "Submit",
"CANCEL": "Cancel",
"CANCEL": "Ləğv et",
"AVATAR": {
"LABEL": "Contact Avatar"
},
"NAME": {
"PLACEHOLDER": "Enter the full name of the contact",
"LABEL": "Full Name"
"PLACEHOLDER": "Əlaqənin tam adını daxil edin",
"LABEL": "Tam Ad"
},
"BIO": {
"PLACEHOLDER": "Enter the bio of the contact",
@@ -100,30 +100,30 @@
"ERROR": "Please enter a valid email address."
},
"PHONE_NUMBER": {
"PLACEHOLDER": "Enter the phone number of the contact",
"LABEL": "Phone Number",
"HELP": "Phone number should be of E.164 format eg: +1415555555 [+][country code][area code][local phone number]. You can select the dial code from the dropdown.",
"ERROR": "Phone number should be either empty or of E.164 format",
"DIAL_CODE_ERROR": "Please select a dial code from the list",
"DUPLICATE": "This phone number is in use for another contact."
"PLACEHOLDER": "Əlaqə şəxsin telefon nömrəsini daxil edin",
"LABEL": "Telefon nömrəsi",
"HELP": "Telefon nömrəsi E.164 formatında olmalıdır, məsələn: +1415555555. Ölkə kodunu siyahıdan seçə bilərsiniz.",
"ERROR": "Telefon nömrəsi ya boş olmalıdır, ya da E.164 formatında olmalıdır",
"DIAL_CODE_ERROR": "Zəhmət olmasa siyahıdan kodu seçin",
"DUPLICATE": "Bu telefon nömrəsi başqa bir əlaqə üçün istifadə olunur."
},
"LOCATION": {
"PLACEHOLDER": "Enter the location of the contact",
"LABEL": "Location"
"PLACEHOLDER": "Əlaqə yerini daxil edin",
"LABEL": "Yer"
},
"COMPANY_NAME": {
"PLACEHOLDER": "Enter the company name",
"PLACEHOLDER": "Şirkət adını daxil edin",
"LABEL": "Company Name"
},
"COUNTRY": {
"PLACEHOLDER": "Enter the country name",
"PLACEHOLDER": "Ölkə adını daxil edin",
"LABEL": "Country Name",
"SELECT_PLACEHOLDER": "Select",
"REMOVE": "Remove",
"SELECT_COUNTRY": "Select Country"
"SELECT_PLACEHOLDER": "Seçin",
"REMOVE": "Sil",
"SELECT_COUNTRY": "Ölkəni seçin"
},
"CITY": {
"PLACEHOLDER": "Enter the city name",
"PLACEHOLDER": "Şəhərin adını daxil edin",
"LABEL": "City Name"
},
"SOCIAL_PROFILES": {
@@ -155,23 +155,23 @@
"ERROR_MESSAGE": "There was an error, please try again"
},
"NEW_CONVERSATION": {
"BUTTON_LABEL": "Start conversation",
"TITLE": "New conversation",
"BUTTON_LABEL": "Söhbətə başla",
"TITLE": "Yeni söhbət",
"DESC": "Start a new conversation by sending a new message.",
"NO_INBOX": "Couldn't find an inbox to initiate a new conversation with this contact.",
"FORM": {
"TO": {
"LABEL": "To"
"LABEL": "Kimə"
},
"INBOX": {
"LABEL": "Via Inbox",
"PLACEHOLDER": "Choose source inbox",
"ERROR": "Select an inbox"
"ERROR": "Bir qutu seçin"
},
"SUBJECT": {
"LABEL": "Subject",
"PLACEHOLDER": "Subject",
"ERROR": "Subject can't be empty"
"LABEL": "Mövzu",
"PLACEHOLDER": "Mövzu",
"ERROR": "Mövzu boş ola bilməz"
},
"MESSAGE": {
"LABEL": "Message",
@@ -183,10 +183,10 @@
"HELP_TEXT": "Drag and drop files here or choose files to attach"
},
"SUBMIT": "Send message",
"CANCEL": "Cancel",
"CANCEL": "Ləğv et",
"SUCCESS_MESSAGE": "Message sent!",
"GO_TO_CONVERSATION": "View",
"ERROR_MESSAGE": "Couldn't send! try again"
"GO_TO_CONVERSATION": "Bax",
"ERROR_MESSAGE": "Göndərmək mümkün olmadı! yenidən cəhd et"
}
},
"CONTACTS_PAGE": {
@@ -204,7 +204,7 @@
"ACTIONS": {
"COPY": "Copy attribute",
"DELETE": "Delete attribute",
"EDIT": "Edit attribute"
"EDIT": "Xüsusiyyəti redaktə et"
},
"ADD": {
"TITLE": "Create custom attribute",
@@ -212,7 +212,7 @@
},
"FORM": {
"CREATE": "Add attribute",
"CANCEL": "Cancel",
"CANCEL": "Ləğv et",
"NAME": {
"LABEL": "Custom attribute name",
"PLACEHOLDER": "Eg: shopify id",
@@ -220,12 +220,12 @@
},
"VALUE": {
"LABEL": "Attribute value",
"PLACEHOLDER": "Eg: 11901 "
"PLACEHOLDER": "Məsələn: 11901 "
},
"ADD": {
"TITLE": "Create new attribute ",
"SUCCESS": "Attribute added successfully",
"ERROR": "Unable to add attribute. Please try again later"
"SUCCESS": "Xüsusiyyət uğurla əlavə edildi",
"ERROR": "Xüsusiyyəti əlavə etmək mümkün olmadı. Zəhmət olmasa, bir az sonra yenidən cəhd edin"
},
"UPDATE": {
"SUCCESS": "Attribute updated successfully",
@@ -236,52 +236,52 @@
"ERROR": "Unable to delete attribute. Please try again later"
},
"ATTRIBUTE_SELECT": {
"TITLE": "Add attributes",
"TITLE": "Xüsusiyyətlər əlavə et",
"PLACEHOLDER": "Search attributes",
"NO_RESULT": "No attributes found"
},
"ATTRIBUTE_TYPE": {
"LIST": {
"PLACEHOLDER": "Select value",
"PLACEHOLDER": "Dəyəri seçin",
"SEARCH_INPUT_PLACEHOLDER": "Search value",
"NO_RESULT": "No result found"
}
}
},
"VALIDATIONS": {
"REQUIRED": "Valid value is required",
"INVALID_URL": "Invalid URL",
"INVALID_INPUT": "Invalid Input"
"REQUIRED": "Düzgün dəyər tələb olunur",
"INVALID_URL": "Yanlış URL",
"INVALID_INPUT": "Yanlış Giriş"
}
},
"MERGE_CONTACTS": {
"TITLE": "Merge contacts",
"DESCRIPTION": "Merge contacts to combine two profiles into one, including all attributes and conversations. In case of conflict, the Primary contacts attributes will take precedence.",
"DESCRIPTION": "İki profili bütün atributlar və söhbətlər daxil olmaqla birləşdirərək əlaqələri birləşdirin. Ziddiyyət olduqda, Əsas əlaqənin atributları üstünlük təşkil edəcək.",
"PRIMARY": {
"TITLE": "Primary contact",
"TITLE": "Əsas əlaqə",
"HELP_LABEL": "To be deleted"
},
"PARENT": {
"TITLE": "Contact to merge",
"PLACEHOLDER": "Search for a contact",
"PLACEHOLDER": "Əlaqə axtar",
"HELP_LABEL": "To be kept"
},
"SUMMARY": {
"TITLE": "Summary",
"TITLE": "Yekun",
"DELETE_WARNING": "Contact of <strong>{primaryContactName}</strong> will be deleted.",
"ATTRIBUTE_WARNING": "Contact details of <strong>{primaryContactName}</strong> will be copied to <strong>{parentContactName}</strong>."
},
"SEARCH": {
"ERROR_MESSAGE": "Something went wrong. Please try again later."
"ERROR_MESSAGE": "Nəsə səhv getdi. Zəhmət olmasa, bir az sonra yenidən cəhd edin."
},
"FORM": {
"SUBMIT": " Merge contacts",
"CANCEL": "Cancel",
"CANCEL": "Ləğv et",
"CHILD_CONTACT": {
"ERROR": "Select a child contact to merge"
"ERROR": "Birləşdirmək üçün alt əlaqəni seçin"
},
"SUCCESS_MESSAGE": "Contact merged successfully",
"ERROR_MESSAGE": "Could not merge contacts, try again!"
"ERROR_MESSAGE": "Əlaqələri birləşdirmək mümkün olmadı, yenidən cəhd edin!"
},
"DROPDOWN_ITEM": {
"ID": "(ID: {identifier})"
@@ -289,68 +289,68 @@
},
"CONTACTS_LAYOUT": {
"HEADER": {
"TITLE": "Contacts",
"SEARCH_TITLE": "Search contacts",
"ACTIVE_TITLE": "Active contacts",
"SEARCH_PLACEHOLDER": "Search...",
"TITLE": "Əlaqələr",
"SEARCH_TITLE": "Əlaqələrdə axtarış",
"ACTIVE_TITLE": "Aktiv əlaqələr",
"SEARCH_PLACEHOLDER": "Axtarış...",
"MESSAGE_BUTTON": "Message",
"SEND_MESSAGE": "Send message",
"BLOCK_CONTACT": "Block contact",
"UNBLOCK_CONTACT": "Unblock contact",
"BREADCRUMB": {
"CONTACTS": "Contacts"
"CONTACTS": "Əlaqələr"
},
"ACTIONS": {
"CONTACT_CREATION": {
"ADD_CONTACT": "Add contact",
"EXPORT_CONTACT": "Export contacts",
"IMPORT_CONTACT": "Import contacts",
"SAVE_CONTACT": "Save contact",
"ADD_CONTACT": "Əlaqə əlavə et",
"EXPORT_CONTACT": "Əlaqələri ixrac et",
"IMPORT_CONTACT": "Əlaqələri idxal et",
"SAVE_CONTACT": "Əlaqəni yadda saxla",
"EMAIL_ADDRESS_DUPLICATE": "This email address is in use for another contact.",
"PHONE_NUMBER_DUPLICATE": "This phone number is in use for another contact.",
"PHONE_NUMBER_DUPLICATE": "Bu telefon nömrəsi başqa bir əlaqə üçün istifadə olunur.",
"SUCCESS_MESSAGE": "Contact saved successfully",
"ERROR_MESSAGE": "Unable to save contact. Please try again later."
"ERROR_MESSAGE": "Əlaqəni saxlamaq mümkün olmadı. Zəhmət olmasa sonra yenidən cəhd edin."
},
"BLOCK_SUCCESS_MESSAGE": "This contact is blocked successfully",
"BLOCK_ERROR_MESSAGE": "Unable to block contact. Please try again later.",
"UNBLOCK_SUCCESS_MESSAGE": "This contact is unblocked successfully",
"UNBLOCK_SUCCESS_MESSAGE": "Bu əlaqənin bloku uğurla açıldı",
"UNBLOCK_ERROR_MESSAGE": "Unable to unblock contact. Please try again later.",
"IMPORT_CONTACT": {
"TITLE": "Import contacts",
"DESCRIPTION": "Import contacts through a CSV file.",
"TITLE": "Əlaqələri idxal et",
"DESCRIPTION": "Əlaqələri CSV faylı vasitəsilə idxal edin.",
"DOWNLOAD_LABEL": "Download a sample csv.",
"LABEL": "CSV File:",
"CHOOSE_FILE": "Choose file",
"CHANGE": "Change",
"CANCEL": "Cancel",
"IMPORT": "Import",
"SUCCESS_MESSAGE": "You will be notified via email when the import is complete.",
"LABEL": "CSV faylı:",
"CHOOSE_FILE": "Fayl seçin",
"CHANGE": "Dəyiş",
"CANCEL": "Ləğv et",
"IMPORT": "İdxal et",
"SUCCESS_MESSAGE": "İdxal bitdikdə sizə elektron bildiriş göndəriləcək.",
"ERROR_MESSAGE": "There was an error, please try again"
},
"EXPORT_CONTACT": {
"TITLE": "Export contacts",
"TITLE": "Əlaqələri ixrac et",
"DESCRIPTION": "Quickly export a csv file with comprehensive details of your contacts",
"CONFIRM": "Export",
"SUCCESS_MESSAGE": "Export is in progress. You will be notified on email when the export file is ready to download.",
"CONFIRM": "İxrac et",
"SUCCESS_MESSAGE": "İxrac davam edir. Fayl hazır olanda sizə elektron bildiriş göndəriləcək.",
"ERROR_MESSAGE": "There was an error, please try again"
},
"SORT_BY": {
"LABEL": "Sort by",
"LABEL": "Sırala",
"OPTIONS": {
"NAME": "Name",
"EMAIL": "Email",
"PHONE_NUMBER": "Phone number",
"COMPANY": "Company",
"COUNTRY": "Country",
"CITY": "City",
"LAST_ACTIVITY": "Last activity",
"NAME": "Ad",
"EMAIL": "Elektron poçt",
"PHONE_NUMBER": "Telefon nömrəsi",
"COMPANY": "Şirkət",
"COUNTRY": "Ölkə",
"CITY": "Şəhər",
"LAST_ACTIVITY": "Son fəaliyyət",
"CREATED_AT": "Created at"
}
},
"ORDER": {
"LABEL": "Ordering",
"OPTIONS": {
"ASCENDING": "Ascending",
"ASCENDING": "Artan sıra ilə",
"DESCENDING": "Descending"
}
},
@@ -358,17 +358,17 @@
"CREATE_SEGMENT": {
"TITLE": "Do you want to save this filter?",
"CONFIRM": "Save filter",
"LABEL": "Name",
"LABEL": "Ad",
"PLACEHOLDER": "Enter the name of the filter",
"ERROR": "Enter a valid name",
"ERROR": "Etibarlı ad daxil edin",
"SUCCESS_MESSAGE": "Filter saved successfully",
"ERROR_MESSAGE": "Unable to save filter. Please try again later."
},
"DELETE_SEGMENT": {
"TITLE": "Confirm Deletion",
"DESCRIPTION": "Are you sure you want to delete this filter?",
"DESCRIPTION": "Bu filtrin silinməsini təsdiqləyirsiniz?",
"CONFIRM": "Yes, Delete",
"CANCEL": "No, Cancel",
"CANCEL": "Xeyr, Ləğv et",
"SUCCESS_MESSAGE": "Filter deleted successfully",
"ERROR_MESSAGE": "Unable to delete filter. Please try again later."
}
@@ -379,18 +379,18 @@
"SHOWING": "Showing {startItem} - {endItem} of {totalItems} contacts"
},
"FILTER": {
"NAME": "Name",
"EMAIL": "Email",
"PHONE_NUMBER": "Phone number",
"NAME": "Ad",
"EMAIL": "Elektron poçt",
"PHONE_NUMBER": "Telefon nömrəsi",
"IDENTIFIER": "Identifier",
"COUNTRY": "Country",
"CITY": "City",
"COUNTRY": "Ölkə",
"CITY": "Şəhər",
"CREATED_AT": "Created at",
"LAST_ACTIVITY": "Last activity",
"LAST_ACTIVITY": "Son fəaliyyət",
"REFERER_LINK": "Referer link",
"BLOCKED": "Blocked",
"BLOCKED_TRUE": "True",
"BLOCKED_FALSE": "False",
"BLOCKED_TRUE": "Doğru",
"BLOCKED_FALSE": "Yanlış",
"BUTTONS": {
"CLEAR_FILTERS": "Clear filters",
"UPDATE_SEGMENT": "Update segment",
@@ -409,7 +409,7 @@
}
},
"CARD": {
"OF": "of",
"OF": "",
"VIEW_DETAILS": "View details",
"EDIT_DETAILS_FORM": {
"TITLE": "Edit contact details",
@@ -418,27 +418,27 @@
"PLACEHOLDER": "Enter the first name"
},
"LAST_NAME": {
"PLACEHOLDER": "Enter the last name"
"PLACEHOLDER": "Soyadı daxil edin"
},
"EMAIL_ADDRESS": {
"PLACEHOLDER": "Enter the email address",
"DUPLICATE": "This email address is in use for another contact."
},
"PHONE_NUMBER": {
"PLACEHOLDER": "Enter the phone number",
"DUPLICATE": "This phone number is in use for another contact."
"PLACEHOLDER": "Telefon nömrəsini daxil edin",
"DUPLICATE": "Bu telefon nömrəsi başqa bir əlaqə üçün istifadə olunur."
},
"CITY": {
"PLACEHOLDER": "Enter the city name"
"PLACEHOLDER": "Şəhər adını daxil edin"
},
"COUNTRY": {
"PLACEHOLDER": "Select country"
"PLACEHOLDER": "Ölkəni seçin"
},
"BIO": {
"PLACEHOLDER": "Enter the bio"
},
"COMPANY_NAME": {
"PLACEHOLDER": "Enter the company name"
"PLACEHOLDER": "Şirkət adını daxil edin"
}
},
"UPDATE_BUTTON": "Update contact",
@@ -457,6 +457,9 @@
"INSTAGRAM": {
"PLACEHOLDER": "Add Instagram"
},
"TELEGRAM": {
"PLACEHOLDER": "Add Telegram"
},
"TIKTOK": {
"PLACEHOLDER": "Add TikTok"
},
@@ -474,8 +477,8 @@
}
},
"DETAILS": {
"CREATED_AT": "Created {date}",
"LAST_ACTIVITY": "Last active {date}",
"CREATED_AT": "Yaradılıb {date}",
"LAST_ACTIVITY": "Son fəaliyyət {date}",
"DELETE_CONTACT_DESCRIPTION": "Permanently delete this contact. This action is irreversible",
"DELETE_CONTACT": "Delete contact",
"DELETE_DIALOG": {
@@ -484,7 +487,7 @@
"CONFIRM": "Yes, Delete",
"API": {
"SUCCESS_MESSAGE": "Contact deleted successfully",
"ERROR_MESSAGE": "Could not delete contact. Please try again later."
"ERROR_MESSAGE": "Əlaqəni silmək mümkün olmadı. Zəhmət olmasa sonra yenidən cəhd edin."
}
},
"AVATAR": {
@@ -493,87 +496,88 @@
"SUCCESS_MESSAGE": "Avatar uploaded successfully"
},
"DELETE": {
"SUCCESS_MESSAGE": "Avatar deleted successfully",
"SUCCESS_MESSAGE": "Avatar uğurla silindi",
"ERROR_MESSAGE": "Could not delete avatar. Please try again later."
}
}
},
"SIDEBAR": {
"TABS": {
"ATTRIBUTES": "Attributes",
"HISTORY": "History",
"NOTES": "Notes",
"ATTRIBUTES": "Xüsusiyyətlər",
"HISTORY": "Tarix",
"NOTES": "Qeydlər",
"MERGE": "Merge"
},
"HISTORY": {
"EMPTY_STATE": "There are no previous conversations associated to this contact"
"EMPTY_STATE": "Bu əlaqə ilə bağlı əvvəlki söhbətlər yoxdur"
},
"ATTRIBUTES": {
"SEARCH_PLACEHOLDER": "Search for attributes",
"UNUSED_ATTRIBUTES": "{count} Used attribute | {count} Unused attributes",
"EMPTY_STATE": "There are no contact custom attributes available in this account. You can create a custom attribute in settings.",
"YES": "Yes",
"NO": "No",
"YES": "Bəli",
"NO": "Xeyr",
"TRIGGER": {
"SELECT": "Select value",
"INPUT": "Enter value"
"SELECT": "Dəyəri seçin",
"INPUT": "Dəyər daxil edin"
},
"VALIDATIONS": {
"INVALID_NUMBER": "Invalid number",
"REQUIRED": "Valid value is required",
"INVALID_INPUT": "Invalid input",
"INVALID_URL": "Invalid URL",
"INVALID_DATE": "Invalid date"
"INVALID_NUMBER": "Yanlış nömrə",
"REQUIRED": "Düzgün dəyər tələb olunur",
"INVALID_INPUT": "Yanlış giriş",
"INVALID_URL": "Yanlış URL",
"INVALID_DATE": "Yanlış tarix"
},
"NO_ATTRIBUTES": "No attributes found",
"API": {
"SUCCESS_MESSAGE": "Attribute updated successfully",
"DELETE_SUCCESS_MESSAGE": "Attribute deleted successfully",
"UPDATE_ERROR": "Unable to update attribute. Please try again later",
"DELETE_ERROR": "Unable to delete attribute. Please try again later"
"DELETE_ERROR": "Xüsusiyyəti silmək mümkün olmadı. Zəhmət olmasa, bir az sonra yenidən cəhd edin"
}
},
"MERGE": {
"TITLE": "Merge contact",
"DESCRIPTION": "Combine two profiles into one, including all attributes and conversations. In case of conflict, the primary contacts attributes will take precedence.",
"PRIMARY": "Primary contact",
"DESCRIPTION": "İki profili bütün atributlar və söhbətlər daxil olmaqla birləşdirin. Ziddiyyət olduqda, əsas əlaqənin atributları üstünlük təşkil edəcək.",
"PRIMARY": "Əsas əlaqə",
"PRIMARY_HELP_LABEL": "To be saved",
"PRIMARY_REQUIRED_ERROR": "Please select a contact to merge with before proceeding",
"PRIMARY_REQUIRED_ERROR": "Davam etməzdən əvvəl birləşdirmək üçün əlaqə seçin",
"PARENT": "To be merged",
"PARENT_HELP_LABEL": "To be deleted",
"EMPTY_STATE": "No contacts found",
"PLACEHOLDER": "Search for primary contact",
"SEARCH_PLACEHOLDER": "Search for a contact",
"PLACEHOLDER": "Əsas əlaqəni axtar",
"SEARCH_PLACEHOLDER": "Əlaqə axtar",
"SEARCH_ERROR_MESSAGE": "Could not search for contacts. Please try again later.",
"SUCCESS_MESSAGE": "Contact merged successfully",
"ERROR_MESSAGE": "Could not merge contacts, try again!",
"ERROR_MESSAGE": "Əlaqələri birləşdirmək mümkün olmadı, yenidən cəhd edin!",
"IS_SEARCHING": "Searching...",
"BUTTONS": {
"CANCEL": "Cancel",
"CANCEL": "Ləğv et",
"CONFIRM": "Merge contact"
}
},
"NOTES": {
"PLACEHOLDER": "Add a note",
"WROTE": "wrote",
"YOU": "You",
"PLACEHOLDER": "Qeyd əlavə et",
"WROTE": "yazdı",
"YOU": "Siz",
"SAVE": "Save note",
"ADD_NOTE": "Add contact note",
"EXPAND": "Expand",
"EXPAND": "Genişləndir",
"COLLAPSE": "Collapse",
"NO_NOTES": "No notes, you can add notes from the contact details page.",
"EMPTY_STATE": "There are no notes associated to this contact. You can add a note by typing in the box above.",
"CONVERSATION_EMPTY_STATE": "There are no notes yet. Use the Add note button to create one."
"CONVERSATION_EMPTY_STATE": "Hələ qeydlər yoxdur. Yeni qeyd yaratmaq üçün Qeyd əlavə et düyməsini istifadə edin."
}
},
"EMPTY_STATE": {
"TITLE": "No contacts found in this account",
"SUBTITLE": "Start adding new contacts by clicking on the button below",
"BUTTON_LABEL": "Add contact",
"BUTTON_LABEL": "Əlaqə əlavə et",
"SEARCH_EMPTY_STATE_TITLE": "No contacts matches your search 🔍",
"LIST_EMPTY_STATE_TITLE": "No contacts available in this view 📋",
"ACTIVE_EMPTY_STATE_TITLE": "No contacts are active at the moment 🌙"
}
"LIST_EMPTY_STATE_TITLE": "Bu baxışda əlaqə mövcud deyil 📋",
"ACTIVE_EMPTY_STATE_TITLE": "Hazırda aktiv əlaqə yoxdur 🌙"
},
"LOAD_MORE": "Load more"
},
"CONTACTS_BULK_ACTIONS": {
"ASSIGN_LABELS": "Assign Labels",
@@ -581,12 +585,12 @@
"ASSIGN_LABELS_FAILED": "Failed to assign labels",
"DESCRIPTION": "Select the labels you want to add to the selected contacts.",
"NO_LABELS_FOUND": "No labels available yet.",
"SELECTED_COUNT": "{count} selected",
"SELECTED_COUNT": "{count} seçildi",
"CLEAR_SELECTION": "Clear selection",
"SELECT_ALL": "Select all ({count})",
"DELETE_CONTACTS": "Delete",
"DELETE_SUCCESS": "Contacts deleted successfully.",
"DELETE_FAILED": "Failed to delete contacts.",
"DELETE_FAILED": "Əlaqələri silmək mümkün olmadı.",
"DELETE_DIALOG": {
"TITLE": "Delete selected contacts",
"SINGULAR_TITLE": "Delete selected contact",
@@ -601,27 +605,27 @@
"ERROR_MESSAGE": "We couldnt complete the search. Please try again."
},
"FORM": {
"GO_TO_CONVERSATION": "View",
"GO_TO_CONVERSATION": "Bax",
"SUCCESS_MESSAGE": "The message was sent successfully!",
"ERROR_MESSAGE": "An error occurred while creating the conversation. Please try again later.",
"NO_INBOX_ALERT": "There are no available inboxes to start a conversation with this contact.",
"CONTACT_SELECTOR": {
"LABEL": "To:",
"TAG_INPUT_PLACEHOLDER": "Search for a contact with name, email or phone number",
"CONTACT_CREATING": "Creating contact..."
"LABEL": "Kimə:",
"TAG_INPUT_PLACEHOLDER": "Enter at least 2 characters to search by name, email, or phone number",
"CONTACT_CREATING": "Əlaqə yaradılır..."
},
"INBOX_SELECTOR": {
"LABEL": "Via:",
"BUTTON": "Show inboxes"
"BUTTON": "Qutuları göstər"
},
"EMAIL_OPTIONS": {
"SUBJECT_LABEL": "Subject :",
"SUBJECT_LABEL": "Mövzu :",
"SUBJECT_PLACEHOLDER": "Enter your email subject here",
"CC_LABEL": "Cc:",
"CC_PLACEHOLDER": "Search for a contact with their email address",
"CC_PLACEHOLDER": "Enter at least 2 characters to search by email",
"BCC_LABEL": "Bcc:",
"BCC_PLACEHOLDER": "Search for a contact with their email address",
"BCC_BUTTON": "Bcc"
"BCC_PLACEHOLDER": "Enter at least 2 characters to search by email",
"BCC_BUTTON": "Gizli nüsxə"
},
"MESSAGE_EDITOR": {
"PLACEHOLDER": "Write your message here..."
@@ -647,8 +651,8 @@
}
},
"ACTION_BUTTONS": {
"DISCARD": "Discard",
"SEND": "Send ({keyCode})"
"DISCARD": "İmtina et",
"SEND": "Göndər ({keyCode})"
}
}
}
@@ -1,439 +1,452 @@
{
"CONVERSATION": {
"SELECT_A_CONVERSATION": "Please select a conversation from left pane",
"CSAT_REPLY_MESSAGE": "Please rate the conversation",
"404": "Sorry, we cannot find the conversation. Please try again",
"SWITCH_VIEW_LAYOUT": "Switch the layout",
"DASHBOARD_APP_TAB_MESSAGES": "Messages",
"UNVERIFIED_SESSION": "The identity of this user is not verified",
"NO_MESSAGE_1": "Uh oh! Looks like there are no messages from customers in your inbox.",
"NO_MESSAGE_2": " to send a message to your page!",
"NO_INBOX_1": "Hola! Looks like you haven't added any inboxes yet.",
"NO_INBOX_2": " to get started",
"NO_INBOX_AGENT": "Uh Oh! Looks like you are not part of any inbox. Please contact your administrator",
"SEARCH_MESSAGES": "Search for messages in conversations",
"VIEW_ORIGINAL": "View original",
"VIEW_TRANSLATED": "View translated",
"SELECT_A_CONVERSATION": "Zəhmət olmasa, soldakı paneldən bir söhbət seçin",
"CSAT_REPLY_MESSAGE": "Zəhmət olmasa söhbəti qiymətləndirin",
"404": "Bağışlayın, söhbəti tapa bilmirik. Zəhmət olmasa, yenidən cəhd edin",
"SWITCH_VIEW_LAYOUT": "Düzəni dəyişdirin",
"DASHBOARD_APP_TAB_MESSAGES": "Mesajlar",
"UNVERIFIED_SESSION": "Bu istifadəçinin şəxsiyyəti təsdiqlənməyib",
"NO_MESSAGE_1": "Uh oh! Görünür qutunuzda müştərilərdən mesaj yoxdur.",
"NO_MESSAGE_2": " səhifənizə mesaj göndərmək üçün!",
"NO_INBOX_1": "Hola! Görünür hələ heç bir poçt qutusu əlavə etməmisiniz.",
"NO_INBOX_2": " başlamaq üçün",
"NO_INBOX_AGENT": "Uh Oh! Görünür heç bir poçt qutusunun üzvü deyilsiniz. Zəhmət olmasa administratorunuzla əlaqə saxlayın",
"SEARCH_MESSAGES": "Söhbətlərdə mesajları axtarın",
"VIEW_ORIGINAL": "Orijinalı göstər",
"VIEW_TRANSLATED": "Tərcüməni göstər",
"EMPTY_STATE": {
"CMD_BAR": "to open command menu",
"KEYBOARD_SHORTCUTS": "to view keyboard shortcuts"
"CMD_BAR": "əmr menyusunu açmaq üçün",
"KEYBOARD_SHORTCUTS": "klaviatura qısa yollarını görmək üçün"
},
"SEARCH": {
"TITLE": "Search messages",
"RESULT_TITLE": "Search Results",
"LOADING_MESSAGE": "Crunching data...",
"PLACEHOLDER": "Type any text to search messages",
"NO_MATCHING_RESULTS": "No results found."
"TITLE": "Mesajları axtar",
"RESULT_TITLE": "Axtarış Nəticələri",
"LOADING_MESSAGE": "Məlumatlar işlənir...",
"PLACEHOLDER": "Mesajları axtarmaq üçün istənilən mətni yazın",
"NO_MATCHING_RESULTS": "Nəticə tapılmadı."
},
"UNREAD_MESSAGES": "Unread Messages",
"UNREAD_MESSAGE": "Unread Message",
"CLICK_HERE": "Click here",
"LOADING_INBOXES": "Loading inboxes",
"LOADING_CONVERSATIONS": "Loading Conversations",
"CANNOT_REPLY": "You cannot reply due to",
"24_HOURS_WINDOW": "24 hour message window restriction",
"48_HOURS_WINDOW": "48 hour message window restriction",
"API_HOURS_WINDOW": "You can only reply to this conversation within {hours} hours",
"NOT_ASSIGNED_TO_YOU": "This conversation is not assigned to you. Would you like to assign this conversation to yourself?",
"ASSIGN_TO_ME": "Assign to me",
"BOT_HANDOFF_MESSAGE": "You are responding to a conversation which is currently handled by an assistant or a bot.",
"BOT_HANDOFF_ACTION": "Mark open and assign to you",
"BOT_HANDOFF_REOPEN_ACTION": "Mark conversation open",
"BOT_HANDOFF_SUCCESS": "Conversation has been handed over to you",
"BOT_HANDOFF_ERROR": "Failed to take over the conversation. Please try again.",
"TWILIO_WHATSAPP_CAN_REPLY": "You can only reply to this conversation using a template message due to",
"TWILIO_WHATSAPP_24_HOURS_WINDOW": "24 hour message window restriction",
"OLD_INSTAGRAM_INBOX_REPLY_BANNER": "This Instagram account was migrated to the new Instagram channel inbox. All new messages will show up there. You wont be able to send messages from this conversation anymore.",
"REPLYING_TO": "You are replying to:",
"REMOVE_SELECTION": "Remove Selection",
"DOWNLOAD": "Download",
"UNKNOWN_FILE_TYPE": "Unknown File",
"SAVE_CONTACT": "Save Contact",
"NO_CONTENT": "No content to display",
"UNREAD_MESSAGES": "Oxunmamış Mesajlar",
"UNREAD_MESSAGE": "Oxunmamış Mesaj",
"CLICK_HERE": "Buraya klik edin",
"LOADING_INBOXES": "Qutular yüklənir",
"LOADING_CONVERSATIONS": "Söhbətlər yüklənir",
"CANNOT_REPLY": "Cavab verə bilməzsiniz, çünki",
"24_HOURS_WINDOW": "24 saatlıq mesaj pəncərəsi məhdudiyyəti",
"48_HOURS_WINDOW": "48 saatlıq mesaj pəncərəsi məhdudiyyəti",
"API_HOURS_WINDOW": "Bu söhbətə yalnız {hours} saat ərzində cavab verə bilərsiniz",
"NOT_ASSIGNED_TO_YOU": "Bu söhbət sizə təyin edilməyib. Bu söhbəti özünüzə təyin etmək istərdiniz?",
"ASSIGN_TO_ME": "Mənə təyin et",
"BOT_HANDOFF_MESSAGE": "Hazırda köməkçi və ya bot tərəfindən idarə olunan söhbətə cavab verirsiniz.",
"BOT_HANDOFF_ACTION": "Açıq kimi işarələ və özünüzə təyin et",
"BOT_HANDOFF_REOPEN_ACTION": "Söhbəti açıq kimi işarələyin",
"BOT_HANDOFF_SUCCESS": "Söhbət sizə təhvil verildi",
"BOT_HANDOFF_ERROR": "Söhbəti ələ keçirmək alınmadı. Zəhmət olmasa, yenidən cəhd edin.",
"TWILIO_WHATSAPP_CAN_REPLY": "Bu söhbətə yalnız şablon mesajı ilə cavab verə bilərsiniz, çünki",
"TWILIO_WHATSAPP_24_HOURS_WINDOW": "24 saatlıq mesaj pəncərəsi məhdudiyyəti",
"OLD_INSTAGRAM_INBOX_REPLY_BANNER": "Bu Instagram hesabı yeni Instagram kanalının daxil olan qutusuna köçürülüb. Bütün yeni mesajlar orada görünəcək. Bu söhbətdən artıq mesaj göndərə bilməyəcəksiniz.",
"REPLYING_TO": "Siz cavab verirsiniz:",
"REMOVE_SELECTION": "Seçimi sil",
"DOWNLOAD": "Yüklə",
"UNKNOWN_FILE_TYPE": "Naməlum fayl",
"SAVE_CONTACT": "Əlaqəni yadda saxla",
"NO_CONTENT": "Göstəriləcək məzmun yoxdur",
"SHARED_ATTACHMENT": {
"CONTACT": "{sender} has shared a contact",
"LOCATION": "{sender} has shared a location",
"FILE": "{sender} has shared a file",
"MEETING": "{sender} has started a meeting"
"CONTACT": "{sender} bir əlaqə paylaşıb",
"LOCATION": "{sender} bir yer paylaşıb",
"FILE": "{sender} bir fayl paylaşıb",
"MEETING": "{sender} bir görüş başlayıb"
},
"UPLOADING_ATTACHMENTS": "Uploading attachments...",
"REPLIED_TO_STORY": "Replied to your story",
"UPLOADING_ATTACHMENTS": "Əlavələr yüklənir...",
"REPLIED_TO_STORY": "Hekayənizə cavab verdi",
"UNSUPPORTED_MESSAGE": "This message is unsupported. You can view this message on the Facebook / Instagram app.",
"UNSUPPORTED_MESSAGE_FACEBOOK": "This message is unsupported. You can view this message on the Facebook Messenger app.",
"UNSUPPORTED_MESSAGE_INSTAGRAM": "This message is unsupported. You can view this message on the Instagram app.",
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
"NO_RESPONSE": "No response",
"RESPONSE": "Response",
"RATING_TITLE": "Rating",
"FEEDBACK_TITLE": "Feedback",
"REPLY_MESSAGE_NOT_FOUND": "Message not available",
"UNSUPPORTED_MESSAGE_FACEBOOK": "Bu mesaj dəstəklənmir. Bu mesajı Facebook Messenger tətbiqində görə bilərsiniz.",
"UNSUPPORTED_MESSAGE_INSTAGRAM": "Bu mesaj dəstəklənmir. Bu mesajı Instagram tətbiqində görə bilərsiniz.",
"UNSUPPORTED_MESSAGE_TIKTOK": "Bu mesaj dəstəklənmir. Bu mesajı TikTok tətbiqində görə bilərsiniz.",
"SUCCESS_DELETE_MESSAGE": "Mesaj uğurla silindi",
"FAIL_DELETE_MESSSAGE": "Mesajı silmək mümkün olmadı! Yenidən cəhd edin",
"NO_RESPONSE": "Cavab yoxdur",
"RESPONSE": "Cavab",
"RATING_TITLE": "Qiymətləndirmə",
"FEEDBACK_TITLE": "Rəy",
"REPLY_MESSAGE_NOT_FOUND": "Mesaj mövcud deyil",
"CARD": {
"SHOW_LABELS": "Show labels",
"HIDE_LABELS": "Hide labels"
"SHOW_LABELS": "Etiketləri göstər",
"HIDE_LABELS": "Etiketləri gizlədin"
},
"VOICE_CALL": {
"INCOMING_CALL": "Incoming call",
"OUTGOING_CALL": "Outgoing call",
"CALL_IN_PROGRESS": "Call in progress",
"NO_ANSWER": "No answer",
"MISSED_CALL": "Missed call",
"CALL_ENDED": "Call ended",
"NOT_ANSWERED_YET": "Not answered yet",
"THEY_ANSWERED": "They answered",
"YOU_ANSWERED": "You answered"
"INCOMING_CALL": "Gələn zəng",
"OUTGOING_CALL": "Gedən zəng",
"CALL_IN_PROGRESS": "Zəng davam edir",
"NO_ANSWER": "Cavab yoxdur",
"MISSED_CALL": "Qeyri-işlək zəng",
"CALL_ENDED": "Zəng bitdi",
"NOT_ANSWERED_YET": "Hələ cavab verilməyib",
"THEY_ANSWERED": "Onlar cavab verdi",
"YOU_ANSWERED": "Siz cavab verdiniz"
},
"HEADER": {
"RESOLVE_ACTION": "Resolve",
"REOPEN_ACTION": "Reopen",
"OPEN_ACTION": "Open",
"MORE_ACTIONS": "More actions",
"OPEN": "More",
"CLOSE": "Close",
"DETAILS": "details",
"SNOOZED_UNTIL": "Snoozed until",
"SNOOZED_UNTIL_TOMORROW": "Snoozed until tomorrow",
"SNOOZED_UNTIL_NEXT_WEEK": "Snoozed until next week",
"SNOOZED_UNTIL_NEXT_REPLY": "Snoozed until next reply",
"RESOLVE_ACTION": "Həll et",
"REOPEN_ACTION": "Yenidən aç",
"OPEN_ACTION": "",
"MORE_ACTIONS": "Daha çox əməliyyat",
"OPEN": "Daha çox",
"CLOSE": "Bağla",
"DETAILS": "təfərrüatlar",
"SNOOZED_UNTIL": "Gecikdirilib",
"SNOOZED_UNTIL_TOMORROW": "Sabaha qədər təxirə salındı",
"SNOOZED_UNTIL_NEXT_WEEK": "Gələn həftəyə qədər təxirə salındı",
"SNOOZED_UNTIL_NEXT_REPLY": "Növbəti cavaba qədər təxirə salındı",
"SLA_STATUS": {
"FRT": "FRT {status}",
"NRT": "NRT {status}",
"RT": "RT {status}",
"MISSED": "missed",
"DUE": "due"
"MISSED": "qaçırıldı",
"DUE": "vaxtı çatıb"
}
},
"RESOLVE_DROPDOWN": {
"MARK_PENDING": "Mark as pending",
"SNOOZE_UNTIL": "Snooze",
"MARK_PENDING": "Gözləmədə kimi işarələyin",
"SNOOZE_UNTIL": "Gecikdir",
"SNOOZE": {
"TITLE": "Snooze until",
"NEXT_REPLY": "Next reply",
"TOMORROW": "Tomorrow",
"NEXT_WEEK": "Next week"
"TITLE": "Gecikdirin, qədər",
"NEXT_REPLY": "Növbəti cavab",
"TOMORROW": "Sabah",
"NEXT_WEEK": "Gələn həftə"
}
},
"MENTION": {
"AGENTS": "Agents",
"TEAMS": "Teams"
"AGENTS": "Agentlər",
"TEAMS": "Komandalar"
},
"CUSTOM_SNOOZE": {
"TITLE": "Snooze until",
"APPLY": "Snooze",
"CANCEL": "Cancel"
"TITLE": "Gecikdirmə müddəti",
"APPLY": "Gecikdir",
"CANCEL": "Ləğv et"
},
"PRIORITY": {
"TITLE": "Priority",
"TITLE": "Prioritet",
"OPTIONS": {
"NONE": "None",
"URGENT": "Urgent",
"HIGH": "High",
"MEDIUM": "Medium",
"LOW": "Low"
"NONE": "Heç biri",
"URGENT": "Təcili",
"HIGH": "Yüksək",
"MEDIUM": "Orta",
"LOW": "Aşağı"
},
"CHANGE_PRIORITY": {
"SELECT_PLACEHOLDER": "None",
"INPUT_PLACEHOLDER": "Select priority",
"NO_RESULTS": "No results found",
"SUCCESSFUL": "Changed priority of conversation id {conversationId} to {priority}",
"FAILED": "Couldn't change priority. Please try again."
"SELECT_PLACEHOLDER": "Heç biri",
"INPUT_PLACEHOLDER": "Prioritet seçin",
"NO_RESULTS": "Nəticə tapılmadı",
"SUCCESSFUL": "{conversationId} söhbətinin prioriteti {priority} olaraq dəyişdirildi",
"FAILED": "Prioritet dəyişdirilə bilmədi. Zəhmət olmasa yenidən cəhd edin."
}
},
"DELETE_CONVERSATION": {
"TITLE": "Delete conversation #{conversationId}",
"DESCRIPTION": "Are you sure you want to delete this conversation?",
"CONFIRM": "Delete"
"TITLE": "#{conversationId} nömrəli söhbəti sil",
"DESCRIPTION": "Bu söhbəti silmək istədiyinizə əminsiniz?",
"CONFIRM": "Sil"
},
"CARD_CONTEXT_MENU": {
"PENDING": "Mark as pending",
"RESOLVED": "Mark as resolved",
"MARK_AS_UNREAD": "Mark as unread",
"MARK_AS_READ": "Mark as read",
"REOPEN": "Reopen conversation",
"PENDING": "Gözləyən kimi işarələyin",
"RESOLVED": "Həll olundu kimi işarələyin",
"MARK_AS_UNREAD": "Oxunmamış kimi işarələyin",
"MARK_AS_READ": "Oxunmuş kimi işarələ",
"REOPEN": "Söhbəti yenidən açın",
"SNOOZE": {
"TITLE": "Snooze",
"NEXT_REPLY": "Until next reply",
"TOMORROW": "Until tomorrow",
"NEXT_WEEK": "Until next week"
"TITLE": "Gecikdir",
"NEXT_REPLY": "Növbəti cavaba qədər",
"TOMORROW": "Sabaha qədər",
"NEXT_WEEK": "Növbəti həftəyə qədər"
},
"ASSIGN_AGENT": "Assign agent",
"ASSIGN_LABEL": "Assign label",
"AGENTS_LOADING": "Loading agents...",
"ASSIGN_TEAM": "Assign team",
"DELETE": "Delete conversation",
"OPEN_IN_NEW_TAB": "Open in new tab",
"COPY_LINK": "Copy conversation link",
"COPY_LINK_SUCCESS": "Conversation link copied to clipboard",
"ASSIGN_AGENT": "Agent təyin et",
"ASSIGN_LABEL": "Etiket təyin et",
"AGENTS_LOADING": "Agentlər yüklənir...",
"ASSIGN_TEAM": "Komandaya təyin et",
"DELETE": "Söhbəti sil",
"OPEN_IN_NEW_TAB": "Yeni nişanda aç",
"COPY_LINK": "Söhbət linkini kopyala",
"COPY_LINK_SUCCESS": "Söhbət linki panoya kopyalandı",
"API": {
"AGENT_ASSIGNMENT": {
"SUCCESFUL": "Conversation id {conversationId} assigned to \"{agentName}\"",
"FAILED": "Couldn't assign agent. Please try again."
"SUCCESFUL": "{conversationId} söhbəti \"{agentName}\" agentinə təyin edildi",
"FAILED": "Agent təyin etmək mümkün olmadı. Zəhmət olmasa yenidən cəhd edin."
},
"LABEL_ASSIGNMENT": {
"SUCCESFUL": "Assigned label #{labelName} to conversation id {conversationId}",
"FAILED": "Couldn't assign label. Please try again."
"SUCCESFUL": "{conversationId} söhbətinə #{labelName} etiketi təyin edildi",
"FAILED": "Etiket təyin etmək mümkün olmadı. Zəhmət olmasa yenidən cəhd edin."
},
"LABEL_REMOVAL": {
"SUCCESFUL": "{conversationId} nömrəli söhbətdən #{labelName} etiketi silindi",
"FAILED": "Etiketi silmək mümkün olmadı. Zəhmət olmasa yenidən cəhd edin."
},
"TEAM_ASSIGNMENT": {
"SUCCESFUL": "Assigned team \"{team}\" to conversation id {conversationId}",
"FAILED": "Couldn't assign team. Please try again."
"SUCCESFUL": "Söhbət id-si {conversationId} üçün \"{team}\" komandası təyin edildi",
"FAILED": "Komanda təyin etmək mümkün olmadı. Zəhmət olmasa yenidən cəhd edin."
}
}
},
"FOOTER": {
"MESSAGE_SIGN_TOOLTIP": "Message signature",
"ENABLE_SIGN_TOOLTIP": "Enable signature",
"DISABLE_SIGN_TOOLTIP": "Disable signature",
"MSG_INPUT": "Shift + enter for new line. Start with '/' to select a Canned Response.",
"PRIVATE_MSG_INPUT": "Shift + enter for new line. This will be visible only to Agents",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Message signature is not configured, please configure it in profile settings.",
"CLICK_HERE": "Click here to update",
"WHATSAPP_TEMPLATES": "Whatsapp Templates"
"MESSAGE_SIGN_TOOLTIP": "Mesaj imzası",
"ENABLE_SIGN_TOOLTIP": "İmzaya icazə ver",
"DISABLE_SIGN_TOOLTIP": "İmzaya icazə vermə",
"MSG_INPUT": "Yeni sətr üçün Shift + enter. Canned Response seçmək üçün '/' ilə başlayın.",
"PRIVATE_MSG_INPUT": "Yeni sətr üçün Shift + enter. Bu yalnız Agentlər üçün görünəcək",
"MESSAGING_RESTRICTED": "Bu söhbətə cavab verə bilməzsiniz",
"MESSAGING_RESTRICTED_WHATSAPP": "24 saatlıq mesaj pəncərəsi məhdudiyyəti səbəbindən yalnız şablon mesajla cavab verə bilərsiniz",
"MESSAGING_RESTRICTED_API": "Mesaj pəncərəsi məhdudiyyəti səbəbindən yalnız şablon mesajla cavab verə bilərsiniz",
"MESSAGE_SIGNATURE_NOT_CONFIGURED": "Mesaj imzası qurulmayıb, zəhmət olmasa profil parametrlərində qurun.",
"COPILOT_MSG_INPUT": "Copilot üçün əlavə göstərişlər verin və ya başqa sual verin... Davam etmək üçün enter düyməsini basın",
"CLICK_HERE": "Yeniləmək üçün buraya klikləyin",
"WHATSAPP_TEMPLATES": "Whatsapp Şablonları"
},
"REPLYBOX": {
"REPLY": "Reply",
"PRIVATE_NOTE": "Private Note",
"SEND": "Send",
"CREATE": "Add Note",
"INSERT_READ_MORE": "Read more",
"DISMISS_REPLY": "Dismiss reply",
"REPLYING_TO": "Replying to:",
"TIP_EMOJI_ICON": "Show emoji selector",
"TIP_ATTACH_ICON": "Attach files",
"TIP_AUDIORECORDER_ICON": "Record audio",
"TIP_AUDIORECORDER_PERMISSION": "Allow access to audio",
"TIP_AUDIORECORDER_ERROR": "Could not open the audio",
"DRAG_DROP": "Drag and drop here to attach",
"START_AUDIO_RECORDING": "Start audio recording",
"STOP_AUDIO_RECORDING": "Stop audio recording",
"": "",
"REPLY": "Cavab ver",
"PRIVATE_NOTE": "Şəxsi Qeyd",
"SEND": "Göndər",
"CREATE": "Qeyd əlavə et",
"INSERT_READ_MORE": "Daha çox oxu",
"DISMISS_REPLY": "Cavabı ləğv et",
"REPLYING_TO": "Cavab verir:",
"TIP_EMOJI_ICON": "Emoji seçicisini göstər",
"TIP_ATTACH_ICON": "Faylları əlavə et",
"TIP_AUDIORECORDER_ICON": "Səs yaz",
"TIP_AUDIORECORDER_PERMISSION": "Səsə girişə icazə ver",
"TIP_AUDIORECORDER_ERROR": "Səsi açmaq mümkün olmadı",
"DRAG_DROP": "Qoşmaq üçün buraya sürükləyin və buraxın",
"START_AUDIO_RECORDING": "Səs yazısını başla",
"STOP_AUDIO_RECORDING": "Səs yazısını dayandırın",
"COPILOT_THINKING": "Copilot düşünür",
"EMAIL_HEAD": {
"TO": "TO",
"ADD_BCC": "Add bcc",
"TO": "KİMƏ",
"ADD_BCC": "Gizli nüsxə əlavə et",
"CC": {
"LABEL": "CC",
"PLACEHOLDER": "Emails separated by commas",
"ERROR": "Please enter valid email addresses"
"PLACEHOLDER": "Vergüllə ayrılmış elektron poçtlar",
"ERROR": "Zəhmət olmasa düzgün elektron poçt ünvanları daxil edin"
},
"BCC": {
"LABEL": "BCC",
"PLACEHOLDER": "Emails separated by commas",
"ERROR": "Please enter valid email addresses"
"PLACEHOLDER": "Vergüllə ayrılmış e-poçtlar",
"ERROR": "Zəhmət olmasa, düzgün e-poçt ünvanları daxil edin"
}
},
"UNDEFINED_VARIABLES": {
"TITLE": "Undefined variables",
"MESSAGE": "You have {undefinedVariablesCount} undefined variables in your message: {undefinedVariables}. Would you like to send the message anyway?",
"TITLE": "Təyin olunmamış dəyişənlər",
"MESSAGE": "Mesajınızda {undefinedVariablesCount} təyin olunmamış dəyişən var: {undefinedVariables}. Mesajı yenə də göndərmək istəyirsiniz?",
"CONFIRM": {
"YES": "Send",
"CANCEL": "Cancel"
"YES": "Göndər",
"CANCEL": "Ləğv et"
}
},
"QUOTED_REPLY": {
"ENABLE_TOOLTIP": "Include quoted email thread",
"DISABLE_TOOLTIP": "Don't include quoted email thread",
"REMOVE_PREVIEW": "Remove quoted email thread",
"COLLAPSE": "Collapse preview",
"EXPAND": "Expand preview"
"ENABLE_TOOLTIP": "Sitat gətirilmiş e-poçt mövzusunu daxil et",
"DISABLE_TOOLTIP": "Sitat gətirilmiş e-poçt mövzusunu daxil etmə",
"REMOVE_PREVIEW": "Sitat gətirilmiş e-poçt mövzusunu sil",
"COLLAPSE": "Önizləməni yığışdır",
"EXPAND": "Önizləməni genişləndir"
}
},
"VISIBLE_TO_AGENTS": "Private Note: Only visible to you and your team",
"CHANGE_STATUS": "Conversation status changed",
"CHANGE_STATUS_FAILED": "Conversation status change failed",
"CHANGE_AGENT": "Conversation Assignee changed",
"CHANGE_AGENT_FAILED": "Assignee change failed",
"ASSIGN_LABEL_SUCCESFUL": "Label assigned successfully",
"ASSIGN_LABEL_FAILED": "Label assignment failed",
"CHANGE_TEAM": "Conversation team changed",
"SUCCESS_DELETE_CONVERSATION": "Conversation deleted successfully",
"FAIL_DELETE_CONVERSATION": "Couldn't delete conversation! Try again",
"FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB attachment limit",
"MESSAGE_ERROR": "Unable to send this message, please try again later",
"SENT_BY": "Sent by:",
"VISIBLE_TO_AGENTS": "Şəxsi Qeyd: Yalnız siz və komandanız üçün görünür",
"CHANGE_STATUS": "Söhbət statusu dəyişdirildi",
"CHANGE_STATUS_FAILED": "Söhbətin statusunu dəyişmək mümkün olmadı",
"CHANGE_AGENT": "Söhbətin məsul şəxsi dəyişdirildi",
"CHANGE_AGENT_FAILED": "Təyinat dəyişdirilməsi uğursuz oldu",
"ASSIGN_LABEL_SUCCESFUL": "Etiket uğurla təyin edildi",
"ASSIGN_LABEL_FAILED": "Etiket təyini uğursuz oldu",
"CHANGE_TEAM": "Söhbət komandası dəyişdirildi",
"SUCCESS_DELETE_CONVERSATION": "Söhbət uğurla silindi",
"FAIL_DELETE_CONVERSATION": "Söhbəti silmək mümkün olmadı! Yenidən cəhd edin",
"FILE_SIZE_LIMIT": "Fayl {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB əlavə limitini aşır",
"FILE_TYPE_NOT_SUPPORTED": "Bu {fileName} fayl növü bu söhbətdə dəstəklənmir",
"MESSAGE_ERROR": "Bu mesajı göndərmək mümkün olmadı, zəhmət olmasa bir az sonra yenidən cəhd edin",
"SENT_BY": "Göndərən:",
"BOT": "Bot",
"SEND_FAILED": "Couldn't send message! Try again",
"TRY_AGAIN": "retry",
"NATIVE_APP": "Yerli tətbiq",
"NATIVE_APP_ADVISORY": "Bu mesaj yerli tətbiqdən göndərilib. Mesaj pəncərəsini saxlamaq üçün Chatwoot-dan cavab verin.",
"SEND_FAILED": "Mesaj göndərmək mümkün olmadı! Yenidən cəhd edin",
"TRY_AGAIN": "yenidən cəhd et",
"ASSIGNMENT": {
"SELECT_AGENT": "Select Agent",
"REMOVE": "Remove",
"ASSIGN": "Assign"
"SELECT_AGENT": "Agent seçin",
"REMOVE": "Sil",
"ASSIGN": "Təyin et"
},
"CONTEXT_MENU": {
"COPY": "Copy",
"REPLY_TO": "Reply to this message",
"DELETE": "Delete",
"CREATE_A_CANNED_RESPONSE": "Add to canned responses",
"TRANSLATE": "Translate",
"COPY_PERMALINK": "Copy link to the message",
"LINK_COPIED": "Message URL copied to the clipboard",
"COPY": "Kopyala",
"REPLY_TO": "Bu mesaja cavab ver",
"DELETE": "Sil",
"CREATE_A_CANNED_RESPONSE": "Hazır cavablara əlavə et",
"TRANSLATE": "Tərcümə et",
"COPY_PERMALINK": "Mesaja keçid linkini kopyalayın",
"LINK_COPIED": "Mesajın URL-i panoya kopyalandı",
"DELETE_CONFIRMATION": {
"TITLE": "Are you sure you want to delete this message?",
"MESSAGE": "You cannot undo this action",
"DELETE": "Delete",
"CANCEL": "Cancel"
"TITLE": "Bu mesajı silmək istədiyinizə əminsiniz?",
"MESSAGE": "Bu əməliyyatı geri qaytara bilməzsiniz",
"DELETE": "Sil",
"CANCEL": "Ləğv et"
}
},
"SIDEBAR": {
"CONTACT": "Contact",
"CONTACT": "Əlaqə",
"COPILOT": "Copilot"
},
"VOICE_WIDGET": {
"INCOMING_CALL": "Incoming call",
"OUTGOING_CALL": "Outgoing call",
"CALL_IN_PROGRESS": "Call in progress",
"NOT_ANSWERED_YET": "Not answered yet",
"HANDLED_IN_ANOTHER_TAB": "Being handled in another tab",
"REJECT_CALL": "Reject",
"JOIN_CALL": "Join call",
"END_CALL": "End call"
"INCOMING_CALL": "Gələn zəng",
"OUTGOING_CALL": "Gedən zəng",
"CALL_IN_PROGRESS": "Zəng davam edir",
"NOT_ANSWERED_YET": "Hələ cavab verilməyib",
"HANDLED_IN_ANOTHER_TAB": "Başqa sekmədə işlənir",
"REJECT_CALL": "İmtina et",
"JOIN_CALL": "Zəngə qoşul",
"END_CALL": "Zəngi bitir"
}
},
"EMAIL_TRANSCRIPT": {
"TITLE": "Send conversation transcript",
"DESC": "Send a copy of the conversation transcript to the specified email address",
"SUBMIT": "Submit",
"CANCEL": "Cancel",
"SEND_EMAIL_SUCCESS": "The chat transcript was sent successfully",
"SEND_EMAIL_ERROR": "There was an error, please try again",
"TITLE": "Söhbət transkriptini göndər",
"DESC": "Söhbət transkriptinin surətini göstərilən e-poçt ünvanına göndərin",
"SUBMIT": "Təsdiqlə",
"CANCEL": "Ləğv et",
"SEND_EMAIL_SUCCESS": "Söhbət yazısı uğurla göndərildi",
"SEND_EMAIL_ERROR": "Xəta baş verdi, zəhmət olmasa yenidən cəhd edin",
"SEND_EMAIL_PAYMENT_REQUIRED": "Cari planınızda e-poçt yazışması mövcud deyil. Bu funksiyanı istifadə etmək üçün lütfən planınızı yüksəldin.",
"FORM": {
"SEND_TO_CONTACT": "Send the transcript to the customer",
"SEND_TO_AGENT": "Send the transcript to the assigned agent",
"SEND_TO_OTHER_EMAIL_ADDRESS": "Send the transcript to another email address",
"SEND_TO_CONTACT": "Yazını müştəriyə göndər",
"SEND_TO_AGENT": "Mətni təyin olunmuş agentə göndər",
"SEND_TO_OTHER_EMAIL_ADDRESS": "Yazını başqa e-poçt ünvanına göndər",
"EMAIL": {
"PLACEHOLDER": "Enter an email address",
"ERROR": "Please enter a valid email address"
"PLACEHOLDER": "E-poçt ünvanı daxil edin",
"ERROR": "Zəhmət olmasa, düzgün e-poçt ünvanı daxil edin"
}
}
},
"ONBOARDING": {
"TITLE": "Hey 👋, Welcome to {installationName}!",
"DESCRIPTION": "Thanks for signing up. We want you to get the most out of {installationName}. Here are a few things you can do in {installationName} to make the experience delightful.",
"GREETING_MORNING": "👋 Good morning, {name}. Welcome to {installationName}.",
"GREETING_AFTERNOON": "👋 Good afternoon, {name}. Welcome to {installationName}.",
"GREETING_EVENING": "👋 Good evening, {name}. Welcome to {installationName}.",
"READ_LATEST_UPDATES": "Read our latest updates",
"TITLE": "Salam 👋, {installationName}-ə xoş gəlmisiniz!",
"DESCRIPTION": "Qeydiyyatdan keçdiyiniz üçün təşəkkür edirik. {installationName}-dən maksimum faydalanmağınızı istəyirik. Təcrübəni xoş etmək üçün {installationName}-də edə biləcəyiniz bir neçə şey var.",
"GREETING_MORNING": "👋 Sabahınız xeyir, {name}. {installationName}-ə xoş gəlmisiniz.",
"GREETING_AFTERNOON": "👋 Günortanız xeyir, {name}. {installationName}-ə xoş gəlmisiniz.",
"GREETING_EVENING": "👋 Axşamınız xeyir, {name}. {installationName}-ə xoş gəlmisiniz.",
"READ_LATEST_UPDATES": "Ən son yeniliklərimizi oxuyun",
"ALL_CONVERSATION": {
"TITLE": "All your conversations in one place",
"DESCRIPTION": "View all the conversations from your customers in one single dashboard. You can filter the conversations by the incoming channel, label and status.",
"NEW_LINK": "Click here to create an inbox"
"TITLE": "Bütün söhbətləriniz bir yerdə",
"DESCRIPTION": "Müştərilərinizdən olan bütün söhbətləri tək bir paneldə görün. Söhbətləri daxil olan kanal, etiket və vəziyyətə görə süzgəcdən keçirə bilərsiniz.",
"NEW_LINK": "Qutunu yaratmaq üçün bura klikləyin"
},
"TEAM_MEMBERS": {
"TITLE": "Invite your team members",
"DESCRIPTION": "Since you are getting ready to talk to your customer, bring in your teammates to assist you. You can invite your teammates by adding their email addresses to the agent list.",
"NEW_LINK": "Click here to invite a team member"
"TITLE": "Komanda üzvlərinizi dəvət edin",
"DESCRIPTION": "Müştərinizlə danışmağa hazırlaşdığınız üçün, sizə kömək etmək üçün komanda üzvlərinizi dəvət edin. Komanda üzvlərinizi agent siyahısına onların e-poçt ünvanlarını əlavə etməklə dəvət edə bilərsiniz.",
"NEW_LINK": "Komanda üzvünü dəvət etmək üçün buraya klikləyin"
},
"LABELS": {
"TITLE": "Organize conversations with labels",
"DESCRIPTION": "Labels provide an easier way to categorize your conversation. Create some labels like #support-enquiry, #billing-question etc., so that you can use them in a conversation later.",
"NEW_LINK": "Click here to create tags"
"TITLE": "Söhbətləri etiketlərlə təşkil edin",
"DESCRIPTION": "Etiketlər söhbətinizi kateqoriyalara ayırmağı asanlaşdırır. Sonra söhbətdə istifadə etmək üçün #support-enquiry, #billing-question və s. kimi bəzi etiketlər yaradın.",
"NEW_LINK": "Etiket yaratmaq üçün buraya klikləyin"
},
"CANNED_RESPONSES": {
"TITLE": "Create canned responses",
"DESCRIPTION": "Pre-written quick reply templates help you quickly respond to a conversation. Agents can type the '/' character followed by the shortcode to insert a response.",
"NEW_LINK": "Click here to create a canned response"
"TITLE": "Hazır cavablar yaradın",
"DESCRIPTION": "Əvvəlcədən yazılmış sürətli cavab şablonları söhbətə tez cavab verməyinizə kömək edir. Agentlər cavaba daxil etmək üçün '/' simvolunu və sonra qısa kodu yaza bilərlər.",
"NEW_LINK": "Sürətli cavab yaratmaq üçün bura klikləyin"
}
},
"CONVERSATION_SIDEBAR": {
"ASSIGNEE_LABEL": "Assigned Agent",
"SELF_ASSIGN": "Assign to me",
"TEAM_LABEL": "Assigned Team",
"ASSIGNEE_LABEL": "Təyin olunmuş agent",
"SELF_ASSIGN": "Mənə təyin et",
"TEAM_LABEL": "Təyin olunmuş komanda",
"SELECT": {
"PLACEHOLDER": "None"
"PLACEHOLDER": "Heç biri"
},
"ACCORDION": {
"CONTACT_DETAILS": "Contact Details",
"CONVERSATION_ACTIONS": "Conversation Actions",
"CONVERSATION_LABELS": "Conversation Labels",
"CONVERSATION_INFO": "Conversation Information",
"CONTACT_NOTES": "Contact Notes",
"CONTACT_ATTRIBUTES": "Contact Attributes",
"PREVIOUS_CONVERSATION": "Previous Conversations",
"MACROS": "Macros",
"LINEAR_ISSUES": "Linked Linear Issues",
"SHOPIFY_ORDERS": "Shopify Orders"
"CONTACT_DETAILS": "Əlaqə Məlumatları",
"CONVERSATION_ACTIONS": "Söhbət Əməliyyatları",
"CONVERSATION_LABELS": "Söhbət Etiketləri",
"CONVERSATION_INFO": "Söhbət Məlumatları",
"CONTACT_NOTES": "Əlaqə Qeydləri",
"CONTACT_ATTRIBUTES": "Əlaqə Xüsusiyyətləri",
"PREVIOUS_CONVERSATION": "Əvvəlki Söhbətlər",
"MACROS": "Makrolar",
"LINEAR_ISSUES": "Əlaqəli Linear məsələlər",
"SHOPIFY_ORDERS": "Shopify Sifarişləri"
},
"SHOPIFY": {
"ORDER_ID": "Order #{id}",
"ERROR": "Error loading orders",
"NO_SHOPIFY_ORDERS": "No orders found",
"ORDER_ID": "Sifariş #{id}",
"ERROR": "Sifarişlərin yüklənməsində xəta",
"NO_SHOPIFY_ORDERS": "Sifariş tapılmadı",
"FINANCIAL_STATUS": {
"PENDING": "Pending",
"AUTHORIZED": "Authorized",
"PARTIALLY_PAID": "Partially Paid",
"PAID": "Paid",
"PARTIALLY_REFUNDED": "Partially Refunded",
"REFUNDED": "Refunded",
"VOIDED": "Voided"
"PENDING": "Gözləmədə",
"AUTHORIZED": "Təsdiqlənmiş",
"PARTIALLY_PAID": "Qismən ödənilmiş",
"PAID": "Ödənilib",
"PARTIALLY_REFUNDED": "Qismən Geri Ödənilib",
"REFUNDED": "Geri Ödənilib",
"VOIDED": "Ləğv Edilib"
},
"FULFILLMENT_STATUS": {
"FULFILLED": "Fulfilled",
"PARTIALLY_FULFILLED": "Partially Fulfilled",
"UNFULFILLED": "Unfulfilled"
"FULFILLED": "Yerinə Yetirilib",
"PARTIALLY_FULFILLED": "Qismən Yerinə Yetirilib",
"UNFULFILLED": "Yerinə Yetirilməyib"
}
}
},
"CONVERSATION_CUSTOM_ATTRIBUTES": {
"ADD_BUTTON_TEXT": "Create attribute",
"NO_RECORDS_FOUND": "No attributes found",
"ADD_BUTTON_TEXT": "Xüsusiyyət yaradın",
"NO_RECORDS_FOUND": "Heç bir atribut tapılmadı",
"UPDATE": {
"SUCCESS": "Attribute updated successfully",
"ERROR": "Unable to update attribute. Please try again later"
"SUCCESS": "Xüsusiyyət uğurla yeniləndi",
"ERROR": "Xüsusiyyət yenilənə bilmədi. Zəhmət olmasa, bir az sonra yenidən cəhd edin"
},
"ADD": {
"TITLE": "Add",
"SUCCESS": "Attribute added successfully",
"ERROR": "Unable to add attribute. Please try again later"
"TITLE": "Əlavə et",
"SUCCESS": "Xüsusiyyət uğurla əlavə edildi",
"ERROR": "Xüsusiyyət əlavə edilə bilmədi. Zəhmət olmasa, bir az sonra yenidən cəhd edin"
},
"DELETE": {
"SUCCESS": "Attribute deleted successfully",
"ERROR": "Unable to delete attribute. Please try again later"
"SUCCESS": "Xüsusiyyət uğurla silindi",
"ERROR": "Atributu silmək mümkün olmadı. Zəhmət olmasa, bir az sonra yenidən cəhd edin"
},
"ATTRIBUTE_SELECT": {
"TITLE": "Add attributes",
"PLACEHOLDER": "Search attributes",
"NO_RESULT": "No attributes found"
"TITLE": "Atributlar əlavə et",
"PLACEHOLDER": "Atributlarda axtar",
"NO_RESULT": "Heç bir atribut tapılmadı"
}
},
"EMAIL_HEADER": {
"FROM": "From",
"TO": "To",
"BCC": "Bcc",
"CC": "Cc",
"SUBJECT": "Subject",
"EXPAND": "Expand email"
"FROM": "Kimdən",
"TO": "Kimə",
"BCC": "Gizli nüsxə",
"CC": "Nüsxə",
"SUBJECT": "Mövzu",
"EXPAND": "E-poçtu genişləndir"
},
"CONVERSATION_PARTICIPANTS": {
"SIDEBAR_MENU_TITLE": "Participating",
"SIDEBAR_TITLE": "Conversation participants",
"NO_RECORDS_FOUND": "No results found",
"ADD_PARTICIPANTS": "Select participants",
"REMANING_PARTICIPANTS_TEXT": "+{count} others",
"REMANING_PARTICIPANT_TEXT": "+{count} other",
"TOTAL_PARTICIPANTS_TEXT": "{count} people are participating.",
"TOTAL_PARTICIPANT_TEXT": "{count} person is participating.",
"SIDEBAR_MENU_TITLE": "İştirak edənlər",
"SIDEBAR_TITLE": "Söhbət iştirakçıları",
"NO_RECORDS_FOUND": "Nəticə tapılmadı",
"ADD_PARTICIPANTS": "İştirakçıları seçin",
"REMANING_PARTICIPANTS_TEXT": "+{count} digər",
"REMANING_PARTICIPANT_TEXT": "+{count} digər",
"TOTAL_PARTICIPANTS_TEXT": "{count} nəfər iştirak edir.",
"TOTAL_PARTICIPANT_TEXT": "{count} nəfər iştirak edir.",
"NO_PARTICIPANTS_TEXT": "No one is participating!.",
"WATCH_CONVERSATION": "Join conversation",
"YOU_ARE_WATCHING": "You are participating",
"WATCH_CONVERSATION": "Söhbətə qoşulun",
"YOU_ARE_WATCHING": "Siz iştirak edirsiniz",
"API": {
"ERROR_MESSAGE": "Could not update, try again!",
"SUCCESS_MESSAGE": "Participants updated!"
"ERROR_MESSAGE": "Yenilənmədi, yenidən cəhd edin!",
"SUCCESS_MESSAGE": "İştirakçılar yeniləndi!"
}
},
"TRANSLATE_MODAL": {
"TITLE": "View translated content",
"TITLE": "Tərcümə edilmiş məzmunu göstər",
"DESC": "You can view the translated content in each langauge.",
"ORIGINAL_CONTENT": "Original Content",
"TRANSLATED_CONTENT": "Translated Content",
"NO_TRANSLATIONS_AVAILABLE": "No translations are available for this content"
"ORIGINAL_CONTENT": "Orijinal məzmun",
"TRANSLATED_CONTENT": "Tərcümə edilmiş məzmun",
"NO_TRANSLATIONS_AVAILABLE": "Bu məzmun üçün tərcümə mövcud deyil"
},
"TYPING": {
"ONE": "{user} is typing",
"TWO": "{user} and {secondUser} are typing",
"MULTIPLE": "{user} and {count} others are typing"
"ONE": "{user} yazır",
"TWO": "{user} {secondUser} yazırlar",
"MULTIPLE": "{user} {count} başqası yazırlar"
},
"COPILOT": {
"TRY_THESE_PROMPTS": "Try these prompts"
"TRY_THESE_PROMPTS": "Bu təklifləri sınayın"
},
"GALLERY_VIEW": {
"ERROR_DOWNLOADING": "Unable to download attachment. Please try again"
"ERROR_DOWNLOADING": "Əlavəni yükləmək mümkün olmadı. Zəhmət olmasa yenidən cəhd edin"
}
}
@@ -3,8 +3,11 @@
"HEADER": "Custom Roles",
"LEARN_MORE": "Learn more about custom roles",
"DESCRIPTION": "Custom roles are roles that are created by the account owner or admin. These roles can be assigned to agents to define their access and permissions within the account. Custom roles can be created with specific permissions and access levels to suit the requirements of the organization.",
"COUNT": "{n} custom role | {n} custom roles",
"HEADER_BTN_TXT": "Add custom role",
"LOADING": "Fetching custom roles...",
"SEARCH_PLACEHOLDER": "Search custom roles...",
"NO_RESULTS": "No custom roles found matching your search",
"SEARCH_404": "There are no items matching this query.",
"PAYWALL": {
"TITLE": "Upgrade to create custom roles",
@@ -1,5 +1,8 @@
{
"DATE_PICKER": {
"PREVIOUS_PERIOD": "Previous period",
"NEXT_PERIOD": "Next period",
"WEEK_NUMBER": "Week #{weekNumber}",
"APPLY_BUTTON": "Apply",
"CLEAR_BUTTON": "Clear",
"DATE_RANGE_INPUT": {
@@ -13,6 +16,8 @@
"LAST_3_MONTHS": "Last 3 months",
"LAST_6_MONTHS": "Last 6 months",
"LAST_YEAR": "Last year",
"THIS_WEEK": "This week",
"MONTH_TO_DATE": "This month",
"CUSTOM_RANGE": "Custom date range"
}
}
@@ -7,6 +7,13 @@
},
"CLOSE": "Close",
"BETA": "Beta",
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it."
"BETA_DESCRIPTION": "This feature is in beta and may change as we improve it.",
"ACCEPT": "Accept",
"DISCARD": "Discard",
"PREFERRED": "Preferred"
},
"CHOICE_TOGGLE": {
"YES": "Yes",
"NO": "No"
}
}
@@ -182,6 +182,7 @@
},
"COMMAND_BAR": {
"SEARCH_PLACEHOLDER": "Search or jump to",
"SNOOZE_PLACEHOLDER": "Type a time e.g. tomorrow, 2 hours, next friday, jan 15...",
"SECTIONS": {
"GENERAL": "General",
"REPORTS": "Reports",

Some files were not shown because too many files have changed in this diff Show More