@djangocfg/ext-support 1.0.21 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.js CHANGED
@@ -3,7 +3,9 @@ import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { initializeExtensionAPI, createExtensionAPI } from '@djangocfg/ext-base/api';
5
5
  import { Clock, MessageSquare, Loader2, Send, Plus, Headphones, User, ArrowLeft, LifeBuoy } from 'lucide-react';
6
- import React7, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
6
+ import React8, { createContext, useContext, useMemo, useCallback, useState, useEffect, useRef } from 'react';
7
+ import { createExtensionI18n, createTypedExtensionT } from '@djangocfg/ext-base/i18n';
8
+ import { useT } from '@djangocfg/i18n';
7
9
  import { Card, CardContent, Badge, Skeleton, ScrollArea, Button, Textarea, useToast as useToast$1, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@djangocfg/ui-core';
8
10
  import useSWR, { useSWRConfig } from 'swr';
9
11
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -1615,6 +1617,219 @@ var API = class {
1615
1617
  };
1616
1618
  initializeExtensionAPI(configureAPI);
1617
1619
  var apiSupport = createExtensionAPI(API);
1620
+
1621
+ // src/i18n/locales/en.ts
1622
+ var en = {
1623
+ layout: {
1624
+ title: "Support Center",
1625
+ titleShort: "Support",
1626
+ subtitle: "Get help from our support team",
1627
+ newTicket: "New Ticket"
1628
+ },
1629
+ status: {
1630
+ open: "Open",
1631
+ waitingForUser: "Waiting for you",
1632
+ waitingForAdmin: "Waiting for support",
1633
+ resolved: "Resolved",
1634
+ closed: "Closed"
1635
+ },
1636
+ ticketList: {
1637
+ noTickets: "No tickets yet",
1638
+ noTicketsDescription: "Create your first support ticket to get help",
1639
+ loadingMore: "Loading more...",
1640
+ loadMore: "Load more",
1641
+ allLoaded: "All {count} tickets loaded"
1642
+ },
1643
+ createTicket: {
1644
+ title: "New Support Ticket",
1645
+ description: "Describe your issue and we will help you",
1646
+ subjectLabel: "Subject",
1647
+ subjectPlaceholder: "Brief description of your issue",
1648
+ messageLabel: "Message",
1649
+ messagePlaceholder: "Describe your issue in detail...",
1650
+ cancel: "Cancel",
1651
+ creating: "Creating...",
1652
+ create: "Create Ticket"
1653
+ },
1654
+ validation: {
1655
+ subjectRequired: "Subject is required",
1656
+ subjectTooLong: "Subject is too long (max 200 characters)",
1657
+ messageRequired: "Message is required",
1658
+ messageTooLong: "Message is too long (max 5000 characters)"
1659
+ },
1660
+ messages: {
1661
+ ticketCreated: "Ticket created successfully",
1662
+ ticketCreateFailed: "Failed to create ticket",
1663
+ messageSent: "Message sent",
1664
+ messageSendFailed: "Failed to send message"
1665
+ },
1666
+ messageInput: {
1667
+ placeholder: "Type your message...",
1668
+ ticketClosed: "Ticket closed",
1669
+ ticketClosedDescription: "This ticket has been closed. Create a new ticket if you need further assistance."
1670
+ },
1671
+ messageList: {
1672
+ noTicketSelected: "No ticket selected",
1673
+ noTicketSelectedDescription: "Select a ticket from the list to view messages",
1674
+ noMessages: "No messages yet",
1675
+ noMessagesDescription: "Start the conversation by sending a message",
1676
+ loadingOlder: "Loading older messages...",
1677
+ loadOlder: "Load older messages",
1678
+ supportTeam: "Support Team",
1679
+ staff: "Staff"
1680
+ },
1681
+ time: {
1682
+ justNow: "Just now",
1683
+ minutesAgo: "{count} min ago",
1684
+ hoursAgo: "{count}h ago",
1685
+ daysAgo: "{count}d ago"
1686
+ }
1687
+ };
1688
+
1689
+ // src/i18n/locales/ru.ts
1690
+ var ru = {
1691
+ layout: {
1692
+ title: "\u0426\u0435\u043D\u0442\u0440 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1693
+ titleShort: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0430",
1694
+ subtitle: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 \u043F\u043E\u043C\u043E\u0449\u044C \u043E\u0442 \u043D\u0430\u0448\u0435\u0439 \u043A\u043E\u043C\u0430\u043D\u0434\u044B \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1695
+ newTicket: "\u041D\u043E\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435"
1696
+ },
1697
+ status: {
1698
+ open: "\u041E\u0442\u043A\u0440\u044B\u0442",
1699
+ waitingForUser: "\u041E\u0436\u0438\u0434\u0430\u0435\u0442 \u0432\u0430\u0441",
1700
+ waitingForAdmin: "\u041E\u0436\u0438\u0434\u0430\u0435\u0442 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0443",
1701
+ resolved: "\u0420\u0435\u0448\u0451\u043D",
1702
+ closed: "\u0417\u0430\u043A\u0440\u044B\u0442"
1703
+ },
1704
+ ticketList: {
1705
+ noTickets: "\u041D\u0435\u0442 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0439",
1706
+ noTicketsDescription: "\u0421\u043E\u0437\u0434\u0430\u0439\u0442\u0435 \u043F\u0435\u0440\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043F\u043E\u043C\u043E\u0449\u044C",
1707
+ loadingMore: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430...",
1708
+ loadMore: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0435\u0449\u0451",
1709
+ allLoaded: "\u0412\u0441\u0435 {count} \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E"
1710
+ },
1711
+ createTicket: {
1712
+ title: "\u041D\u043E\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435",
1713
+ description: "\u041E\u043F\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0443, \u0438 \u043C\u044B \u043F\u043E\u043C\u043E\u0436\u0435\u043C \u0432\u0430\u043C",
1714
+ subjectLabel: "\u0422\u0435\u043C\u0430",
1715
+ subjectPlaceholder: "\u041A\u0440\u0430\u0442\u043A\u043E\u0435 \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B",
1716
+ messageLabel: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
1717
+ messagePlaceholder: "\u041E\u043F\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0443 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E...",
1718
+ cancel: "\u041E\u0442\u043C\u0435\u043D\u0430",
1719
+ creating: "\u0421\u043E\u0437\u0434\u0430\u043D\u0438\u0435...",
1720
+ create: "\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435"
1721
+ },
1722
+ validation: {
1723
+ subjectRequired: "\u0422\u0435\u043C\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u0430",
1724
+ subjectTooLong: "\u0422\u0435\u043C\u0430 \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u0430\u044F (\u043C\u0430\u043A\u0441. 200 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432)",
1725
+ messageRequired: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E",
1726
+ messageTooLong: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u043E\u0435 (\u043C\u0430\u043A\u0441. 5000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432)"
1727
+ },
1728
+ messages: {
1729
+ ticketCreated: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0441\u043E\u0437\u0434\u0430\u043D\u043E",
1730
+ ticketCreateFailed: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435",
1731
+ messageSent: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E",
1732
+ messageSendFailed: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435"
1733
+ },
1734
+ messageInput: {
1735
+ placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435...",
1736
+ ticketClosed: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0437\u0430\u043A\u0440\u044B\u0442\u043E",
1737
+ ticketClosedDescription: "\u042D\u0442\u043E \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0437\u0430\u043A\u0440\u044B\u0442\u043E. \u0421\u043E\u0437\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u043E\u0435, \u0435\u0441\u043B\u0438 \u0432\u0430\u043C \u043D\u0443\u0436\u043D\u0430 \u043F\u043E\u043C\u043E\u0449\u044C."
1738
+ },
1739
+ messageList: {
1740
+ noTicketSelected: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E",
1741
+ noTicketSelectedDescription: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430 \u0434\u043B\u044F \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439",
1742
+ noMessages: "\u041D\u0435\u0442 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439",
1743
+ noMessagesDescription: "\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u0434\u0438\u0430\u043B\u043E\u0433, \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0432 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
1744
+ loadingOlder: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0441\u0442\u0430\u0440\u044B\u0445 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439...",
1745
+ loadOlder: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0441\u0442\u0430\u0440\u044B\u0435",
1746
+ supportTeam: "\u0421\u043B\u0443\u0436\u0431\u0430 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1747
+ staff: "\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A"
1748
+ },
1749
+ time: {
1750
+ justNow: "\u0422\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u043E",
1751
+ minutesAgo: "{count} \u043C\u0438\u043D \u043D\u0430\u0437\u0430\u0434",
1752
+ hoursAgo: "{count}\u0447 \u043D\u0430\u0437\u0430\u0434",
1753
+ daysAgo: "{count}\u0434 \u043D\u0430\u0437\u0430\u0434"
1754
+ }
1755
+ };
1756
+
1757
+ // src/i18n/locales/ko.ts
1758
+ var ko = {
1759
+ layout: {
1760
+ title: "\uACE0\uAC1D\uC9C0\uC6D0 \uC13C\uD130",
1761
+ titleShort: "\uACE0\uAC1D\uC9C0\uC6D0",
1762
+ subtitle: "\uACE0\uAC1D\uC9C0\uC6D0\uD300\uC758 \uB3C4\uC6C0\uC744 \uBC1B\uC73C\uC138\uC694",
1763
+ newTicket: "\uC0C8 \uBB38\uC758"
1764
+ },
1765
+ status: {
1766
+ open: "\uC5F4\uB9BC",
1767
+ waitingForUser: "\uD68C\uC2E0 \uB300\uAE30",
1768
+ waitingForAdmin: "\uC9C0\uC6D0\uD300 \uB300\uAE30",
1769
+ resolved: "\uD574\uACB0\uB428",
1770
+ closed: "\uC885\uB8CC"
1771
+ },
1772
+ ticketList: {
1773
+ noTickets: "\uBB38\uC758 \uB0B4\uC5ED \uC5C6\uC74C",
1774
+ noTicketsDescription: "\uCCAB \uBC88\uC9F8 \uBB38\uC758\uB97C \uB4F1\uB85D\uD558\uC5EC \uB3C4\uC6C0\uC744 \uBC1B\uC73C\uC138\uC694",
1775
+ loadingMore: "\uBD88\uB7EC\uC624\uB294 \uC911...",
1776
+ loadMore: "\uB354 \uBCF4\uAE30",
1777
+ allLoaded: "\uCD1D {count}\uAC1C\uC758 \uBB38\uC758\uAC00 \uB85C\uB4DC\uB428"
1778
+ },
1779
+ createTicket: {
1780
+ title: "\uC0C8 \uBB38\uC758",
1781
+ description: "\uBB38\uC81C\uB97C \uC124\uBA85\uD574 \uC8FC\uC2DC\uBA74 \uB3C4\uC6C0\uC744 \uB4DC\uB9AC\uACA0\uC2B5\uB2C8\uB2E4",
1782
+ subjectLabel: "\uC81C\uBAA9",
1783
+ subjectPlaceholder: "\uBB38\uC81C\uC5D0 \uB300\uD55C \uAC04\uB7B5\uD55C \uC124\uBA85",
1784
+ messageLabel: "\uB0B4\uC6A9",
1785
+ messagePlaceholder: "\uBB38\uC81C\uB97C \uC790\uC138\uD788 \uC124\uBA85\uD574 \uC8FC\uC138\uC694...",
1786
+ cancel: "\uCDE8\uC18C",
1787
+ creating: "\uC0DD\uC131 \uC911...",
1788
+ create: "\uBB38\uC758 \uB4F1\uB85D"
1789
+ },
1790
+ validation: {
1791
+ subjectRequired: "\uC81C\uBAA9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694",
1792
+ subjectTooLong: "\uC81C\uBAA9\uC774 \uB108\uBB34 \uAE41\uB2C8\uB2E4 (\uCD5C\uB300 200\uC790)",
1793
+ messageRequired: "\uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694",
1794
+ messageTooLong: "\uB0B4\uC6A9\uC774 \uB108\uBB34 \uAE41\uB2C8\uB2E4 (\uCD5C\uB300 5000\uC790)"
1795
+ },
1796
+ messages: {
1797
+ ticketCreated: "\uBB38\uC758\uAC00 \uB4F1\uB85D\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1798
+ ticketCreateFailed: "\uBB38\uC758 \uB4F1\uB85D\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
1799
+ messageSent: "\uBA54\uC2DC\uC9C0\uAC00 \uC804\uC1A1\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1800
+ messageSendFailed: "\uBA54\uC2DC\uC9C0 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4"
1801
+ },
1802
+ messageInput: {
1803
+ placeholder: "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694...",
1804
+ ticketClosed: "\uBB38\uC758 \uC885\uB8CC\uB428",
1805
+ ticketClosedDescription: "\uC774 \uBB38\uC758\uB294 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uCD94\uAC00 \uB3C4\uC6C0\uC774 \uD544\uC694\uD558\uC2DC\uBA74 \uC0C8 \uBB38\uC758\uB97C \uB4F1\uB85D\uD574 \uC8FC\uC138\uC694."
1806
+ },
1807
+ messageList: {
1808
+ noTicketSelected: "\uBB38\uC758\uAC00 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC74C",
1809
+ noTicketSelectedDescription: "\uBA54\uC2DC\uC9C0\uB97C \uBCF4\uB824\uBA74 \uBAA9\uB85D\uC5D0\uC11C \uBB38\uC758\uB97C \uC120\uD0DD\uD558\uC138\uC694",
1810
+ noMessages: "\uBA54\uC2DC\uC9C0 \uC5C6\uC74C",
1811
+ noMessagesDescription: "\uBA54\uC2DC\uC9C0\uB97C \uBCF4\uB0B4 \uB300\uD654\uB97C \uC2DC\uC791\uD558\uC138\uC694",
1812
+ loadingOlder: "\uC774\uC804 \uBA54\uC2DC\uC9C0 \uBD88\uB7EC\uC624\uB294 \uC911...",
1813
+ loadOlder: "\uC774\uC804 \uBA54\uC2DC\uC9C0 \uBCF4\uAE30",
1814
+ supportTeam: "\uACE0\uAC1D\uC9C0\uC6D0\uD300",
1815
+ staff: "\uB2F4\uB2F9\uC790"
1816
+ },
1817
+ time: {
1818
+ justNow: "\uBC29\uAE08 \uC804",
1819
+ minutesAgo: "{count}\uBD84 \uC804",
1820
+ hoursAgo: "{count}\uC2DC\uAC04 \uC804",
1821
+ daysAgo: "{count}\uC77C \uC804"
1822
+ }
1823
+ };
1824
+
1825
+ // src/i18n/index.ts
1826
+ var SUPPORT_NAMESPACE = "support";
1827
+ var supportI18n = createExtensionI18n({
1828
+ namespace: SUPPORT_NAMESPACE,
1829
+ defaultLocale: "en",
1830
+ locales: { en, ru, ko }
1831
+ });
1832
+ supportI18n.getAllTranslations();
1618
1833
  function useSupportTicketsList(params, client) {
1619
1834
  return useSWR(
1620
1835
  params ? ["cfg-support-tickets", params] : "cfg-support-tickets",
@@ -1829,18 +2044,36 @@ var getStatusBadgeVariant = (status) => {
1829
2044
  return "default";
1830
2045
  }
1831
2046
  };
1832
- var formatRelativeTime = (date) => {
1833
- if (!date) return "N/A";
1834
- const m = moment2.utc(date).local();
1835
- const now = moment2();
1836
- const diffInSeconds = now.diff(m, "seconds");
1837
- if (diffInSeconds < 60) return "Just now";
1838
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1839
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1840
- if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
1841
- return m.format("MMM D, YYYY");
1842
- };
1843
2047
  var TicketCard = ({ ticket, isSelected, onClick }) => {
2048
+ const baseT = useT();
2049
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2050
+ const labels = useMemo(() => ({
2051
+ status: {
2052
+ open: st("status.open"),
2053
+ waiting_for_user: st("status.waitingForUser"),
2054
+ waiting_for_admin: st("status.waitingForAdmin"),
2055
+ resolved: st("status.resolved"),
2056
+ closed: st("status.closed")
2057
+ },
2058
+ time: {
2059
+ justNow: st("time.justNow"),
2060
+ minutesAgo: st("time.minutesAgo"),
2061
+ hoursAgo: st("time.hoursAgo"),
2062
+ daysAgo: st("time.daysAgo")
2063
+ }
2064
+ }), [st]);
2065
+ const formatRelativeTime = useCallback((date) => {
2066
+ if (!date) return "N/A";
2067
+ const m = moment2.utc(date).local();
2068
+ const now = moment2();
2069
+ const diffInSeconds = now.diff(m, "seconds");
2070
+ if (diffInSeconds < 60) return labels.time.justNow;
2071
+ if (diffInSeconds < 3600) return labels.time.minutesAgo.replace("{count}", String(Math.floor(diffInSeconds / 60)));
2072
+ if (diffInSeconds < 86400) return labels.time.hoursAgo.replace("{count}", String(Math.floor(diffInSeconds / 3600)));
2073
+ if (diffInSeconds < 604800) return labels.time.daysAgo.replace("{count}", String(Math.floor(diffInSeconds / 86400)));
2074
+ return m.format("MMM D, YYYY");
2075
+ }, [labels.time]);
2076
+ const statusLabel = labels.status[ticket.status] || ticket.status || labels.status.open;
1844
2077
  return /* @__PURE__ */ jsx(
1845
2078
  Card,
1846
2079
  {
@@ -1864,7 +2097,7 @@ var TicketCard = ({ ticket, isSelected, onClick }) => {
1864
2097
  )
1865
2098
  ] }),
1866
2099
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1867
- /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
2100
+ /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: statusLabel }),
1868
2101
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1869
2102
  /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
1870
2103
  /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
@@ -2139,6 +2372,8 @@ function useSupportLayoutContext() {
2139
2372
  return context;
2140
2373
  }
2141
2374
  var TicketList = () => {
2375
+ const baseT = useT();
2376
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2142
2377
  const { selectedTicket, selectTicket } = useSupportLayoutContext();
2143
2378
  const {
2144
2379
  tickets,
@@ -2149,6 +2384,13 @@ var TicketList = () => {
2149
2384
  totalCount,
2150
2385
  refresh
2151
2386
  } = useInfiniteTickets();
2387
+ const labels = useMemo(() => ({
2388
+ noTickets: st("ticketList.noTickets"),
2389
+ noTicketsDescription: st("ticketList.noTicketsDescription"),
2390
+ loadingMore: st("ticketList.loadingMore"),
2391
+ loadMore: st("ticketList.loadMore"),
2392
+ allLoaded: st("ticketList.allLoaded")
2393
+ }), [st]);
2152
2394
  const scrollRef = useRef(null);
2153
2395
  const observerRef = useRef(null);
2154
2396
  const loadMoreRef = useRef(null);
@@ -2194,8 +2436,8 @@ var TicketList = () => {
2194
2436
  if (!tickets || tickets.length === 0) {
2195
2437
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2196
2438
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2197
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No tickets yet" }),
2198
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Create your first support ticket to get help from our team" })
2439
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noTickets }),
2440
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noTicketsDescription })
2199
2441
  ] });
2200
2442
  }
2201
2443
  return /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", viewportRef: scrollRef, children: /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
@@ -2218,7 +2460,7 @@ var TicketList = () => {
2218
2460
  /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "h-2" }),
2219
2461
  isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
2220
2462
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
2221
- /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Loading more tickets..." })
2463
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: labels.loadingMore })
2222
2464
  ] }) }),
2223
2465
  hasMore && !isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs(
2224
2466
  Button,
@@ -2228,17 +2470,14 @@ var TicketList = () => {
2228
2470
  onClick: loadMore,
2229
2471
  className: "text-xs",
2230
2472
  children: [
2231
- "Load more (",
2473
+ labels.loadMore,
2474
+ " (",
2232
2475
  totalCount > 0 ? `${tickets.length}/${totalCount}` : "",
2233
2476
  ")"
2234
2477
  ]
2235
2478
  }
2236
2479
  ) }),
2237
- !hasMore && tickets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-4 text-sm text-muted-foreground", children: [
2238
- "All ",
2239
- totalCount,
2240
- " tickets loaded"
2241
- ] })
2480
+ !hasMore && tickets.length > 0 && /* @__PURE__ */ jsx("div", { className: "text-center py-4 text-sm text-muted-foreground", children: labels.allLoaded.replace("{count}", String(totalCount)) })
2242
2481
  ] }) });
2243
2482
  };
2244
2483
  var formatTime = (date) => {
@@ -2249,7 +2488,7 @@ var formatDate = (date) => {
2249
2488
  if (!date) return "";
2250
2489
  return moment2.utc(date).local().format("MMM D, YYYY");
2251
2490
  };
2252
- var MessageBubble = ({ message, isFromUser, currentUser }) => {
2491
+ var MessageBubble = ({ message, isFromUser, currentUser, labels }) => {
2253
2492
  const sender = message.sender;
2254
2493
  const senderInitial = sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S";
2255
2494
  const userInitial = currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || null;
@@ -2259,11 +2498,11 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2259
2498
  className: `flex gap-3 ${isFromUser ? "justify-end" : "justify-start"}
2260
2499
  animate-in fade-in slide-in-from-bottom-2 duration-300`,
2261
2500
  children: [
2262
- !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2501
+ !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || labels.supportTeam }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2263
2502
  /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-1 flex-1 max-w-[80%] ${isFromUser ? "items-end" : "items-start"}`, children: [
2264
2503
  !isFromUser && sender && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-1", children: [
2265
- sender.display_username || sender.email || "Support Team",
2266
- sender.is_staff && " (Staff)"
2504
+ sender.display_username || sender.email || labels.supportTeam,
2505
+ sender.is_staff && ` (${labels.staff})`
2267
2506
  ] }),
2268
2507
  /* @__PURE__ */ jsx(
2269
2508
  Card,
@@ -2280,8 +2519,20 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2280
2519
  );
2281
2520
  };
2282
2521
  var MessageList = () => {
2522
+ const baseT = useT();
2523
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2283
2524
  const { selectedTicket } = useSupportLayoutContext();
2284
2525
  const { user } = useAuth();
2526
+ const labels = useMemo(() => ({
2527
+ noTicketSelected: st("messageList.noTicketSelected"),
2528
+ noTicketSelectedDescription: st("messageList.noTicketSelectedDescription"),
2529
+ noMessages: st("messageList.noMessages"),
2530
+ noMessagesDescription: st("messageList.noMessagesDescription"),
2531
+ loadingOlder: st("messageList.loadingOlder"),
2532
+ loadOlder: st("messageList.loadOlder"),
2533
+ supportTeam: st("messageList.supportTeam"),
2534
+ staff: st("messageList.staff")
2535
+ }), [st]);
2285
2536
  const {
2286
2537
  messages,
2287
2538
  isLoading,
@@ -2339,8 +2590,8 @@ var MessageList = () => {
2339
2590
  if (!selectedTicket) {
2340
2591
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2341
2592
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2342
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No ticket selected" }),
2343
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Select a ticket from the list to view the conversation" })
2593
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noTicketSelected }),
2594
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noTicketSelectedDescription })
2344
2595
  ] });
2345
2596
  }
2346
2597
  if (isLoading) {
@@ -2360,15 +2611,15 @@ var MessageList = () => {
2360
2611
  if (!messages || messages.length === 0) {
2361
2612
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2362
2613
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2363
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No messages yet" }),
2364
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Start the conversation by sending a message below" })
2614
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noMessages }),
2615
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noMessagesDescription })
2365
2616
  ] });
2366
2617
  }
2367
2618
  return /* @__PURE__ */ jsx(ScrollArea, { className: "h-full bg-muted/50", viewportRef: scrollAreaRef, children: /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-4", ref: scrollRef, children: [
2368
2619
  /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "h-2" }),
2369
2620
  isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
2370
2621
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
2371
- /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Loading older messages..." })
2622
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: labels.loadingOlder })
2372
2623
  ] }) }),
2373
2624
  hasMore && !isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs(
2374
2625
  Button,
@@ -2378,7 +2629,8 @@ var MessageList = () => {
2378
2629
  onClick: handleLoadMore,
2379
2630
  className: "text-xs",
2380
2631
  children: [
2381
- "Load older messages (",
2632
+ labels.loadOlder,
2633
+ " (",
2382
2634
  totalCount > 0 ? `${messages.length}/${totalCount}` : "",
2383
2635
  ")"
2384
2636
  ]
@@ -2393,7 +2645,7 @@ var MessageList = () => {
2393
2645
  const isFromUser = message.sender?.id && user?.id && String(message.sender.id) === String(user.id) || message.sender?.email && user?.email && message.sender.email === user.email || message.is_from_author && selectedTicket?.user && user?.id && String(selectedTicket.user) === String(user.id);
2394
2646
  const previousMessage = index > 0 ? messages[index - 1] : null;
2395
2647
  const showDateSeparator = previousMessage && moment2.utc(previousMessage.created_at || "").format("YYYY-MM-DD") !== moment2.utc(message.created_at || "").format("YYYY-MM-DD");
2396
- return /* @__PURE__ */ jsxs(React7.Fragment, { children: [
2648
+ return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
2397
2649
  showDateSeparator && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 my-4", children: [
2398
2650
  /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
2399
2651
  /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: formatDate(message.created_at) }),
@@ -2404,7 +2656,8 @@ var MessageList = () => {
2404
2656
  {
2405
2657
  message,
2406
2658
  isFromUser: !!isFromUser,
2407
- currentUser: user
2659
+ currentUser: user,
2660
+ labels: { supportTeam: labels.supportTeam, staff: labels.staff }
2408
2661
  }
2409
2662
  ) })
2410
2663
  ] }, message.uuid);
@@ -2418,10 +2671,19 @@ var logger = createConsola({
2418
2671
  }).withTag("ext-support");
2419
2672
  var supportLogger = logger;
2420
2673
  var MessageInput = () => {
2674
+ const baseT = useT();
2675
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2421
2676
  const { selectedTicket, sendMessage } = useSupportLayoutContext();
2422
2677
  const { toast } = useToast();
2423
2678
  const [message, setMessage] = useState("");
2424
2679
  const [isSending, setIsSending] = useState(false);
2680
+ const labels = useMemo(() => ({
2681
+ placeholder: st("messageInput.placeholder"),
2682
+ ticketClosed: st("messageInput.ticketClosed"),
2683
+ ticketClosedDescription: st("messageInput.ticketClosedDescription"),
2684
+ messageSent: st("messages.messageSent"),
2685
+ messageSendFailed: st("messages.messageSendFailed")
2686
+ }), [st]);
2425
2687
  const handleSubmit = async (e) => {
2426
2688
  e.preventDefault();
2427
2689
  if (!message.trim() || !selectedTicket) return;
@@ -2429,10 +2691,10 @@ var MessageInput = () => {
2429
2691
  try {
2430
2692
  await sendMessage(message.trim());
2431
2693
  setMessage("");
2432
- toast.success("Message sent successfully");
2694
+ toast.success(labels.messageSent);
2433
2695
  } catch (error) {
2434
2696
  supportLogger.error("Failed to send message:", error);
2435
- toast.error("Failed to send message");
2697
+ toast.error(labels.messageSendFailed);
2436
2698
  } finally {
2437
2699
  setIsSending(false);
2438
2700
  }
@@ -2455,8 +2717,8 @@ var MessageInput = () => {
2455
2717
  value: message,
2456
2718
  onChange: (e) => setMessage(e.target.value),
2457
2719
  onKeyDown: handleKeyDown,
2458
- placeholder: canSendMessage ? "Type your message... (Shift+Enter for new line)" : "This ticket is closed",
2459
- className: "min-h-[60px] max-h-[200px] transition-all duration-200 \n focus:ring-2 focus:ring-primary/20",
2720
+ placeholder: canSendMessage ? labels.placeholder : labels.ticketClosed,
2721
+ className: "min-h-[60px] max-h-[200px] transition-all duration-200\n focus:ring-2 focus:ring-primary/20",
2460
2722
  disabled: !canSendMessage || isSending
2461
2723
  }
2462
2724
  ),
@@ -2471,17 +2733,38 @@ var MessageInput = () => {
2471
2733
  }
2472
2734
  )
2473
2735
  ] }),
2474
- !canSendMessage && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2 animate-in fade-in slide-in-from-top-1 duration-200", children: "This ticket is closed. You cannot send new messages." })
2736
+ !canSendMessage && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2 animate-in fade-in slide-in-from-top-1 duration-200", children: labels.ticketClosedDescription })
2475
2737
  ] });
2476
2738
  };
2477
- var createTicketSchema = z.object({
2478
- subject: z.string().min(1, "Subject is required").max(200, "Subject too long"),
2479
- message: z.string().min(1, "Message is required").max(5e3, "Message too long")
2480
- });
2481
2739
  var CreateTicketDialog = () => {
2740
+ const baseT = useT();
2741
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2482
2742
  const { uiState, createTicket, closeCreateDialog } = useSupportLayoutContext();
2483
2743
  const { toast } = useToast$1();
2484
- const [isSubmitting, setIsSubmitting] = React7.useState(false);
2744
+ const [isSubmitting, setIsSubmitting] = React8.useState(false);
2745
+ const labels = useMemo(() => ({
2746
+ title: st("createTicket.title"),
2747
+ description: st("createTicket.description"),
2748
+ subjectLabel: st("createTicket.subjectLabel"),
2749
+ subjectPlaceholder: st("createTicket.subjectPlaceholder"),
2750
+ messageLabel: st("createTicket.messageLabel"),
2751
+ messagePlaceholder: st("createTicket.messagePlaceholder"),
2752
+ cancel: st("createTicket.cancel"),
2753
+ creating: st("createTicket.creating"),
2754
+ create: st("createTicket.create"),
2755
+ ticketCreated: st("messages.ticketCreated"),
2756
+ ticketCreateFailed: st("messages.ticketCreateFailed"),
2757
+ validation: {
2758
+ subjectRequired: st("validation.subjectRequired"),
2759
+ subjectTooLong: st("validation.subjectTooLong"),
2760
+ messageRequired: st("validation.messageRequired"),
2761
+ messageTooLong: st("validation.messageTooLong")
2762
+ }
2763
+ }), [st]);
2764
+ const createTicketSchema = useMemo(() => z.object({
2765
+ subject: z.string().min(1, labels.validation.subjectRequired).max(200, labels.validation.subjectTooLong),
2766
+ message: z.string().min(1, labels.validation.messageRequired).max(5e3, labels.validation.messageTooLong)
2767
+ }), [labels.validation]);
2485
2768
  const form = useForm({
2486
2769
  resolver: zodResolver(createTicketSchema),
2487
2770
  defaultValues: {
@@ -2494,10 +2777,10 @@ var CreateTicketDialog = () => {
2494
2777
  try {
2495
2778
  await createTicket(data);
2496
2779
  form.reset();
2497
- toast.success("Support ticket created successfully");
2780
+ toast.success(labels.ticketCreated);
2498
2781
  } catch (error) {
2499
2782
  supportLogger.error("Failed to create ticket:", error);
2500
- toast.error("Failed to create ticket. Please try again.");
2783
+ toast.error(labels.ticketCreateFailed);
2501
2784
  } finally {
2502
2785
  setIsSubmitting(false);
2503
2786
  }
@@ -2510,9 +2793,9 @@ var CreateTicketDialog = () => {
2510
2793
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
2511
2794
  /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
2512
2795
  /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" }),
2513
- "Create Support Ticket"
2796
+ labels.title
2514
2797
  ] }),
2515
- /* @__PURE__ */ jsx(DialogDescription, { children: "Describe your issue and we'll help you resolve it as quickly as possible." })
2798
+ /* @__PURE__ */ jsx(DialogDescription, { children: labels.description })
2516
2799
  ] }),
2517
2800
  /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "space-y-6", children: [
2518
2801
  /* @__PURE__ */ jsx(
@@ -2521,8 +2804,8 @@ var CreateTicketDialog = () => {
2521
2804
  control: form.control,
2522
2805
  name: "subject",
2523
2806
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2524
- /* @__PURE__ */ jsx(FormLabel, { children: "Subject" }),
2525
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, { placeholder: "Brief description of your issue...", ...field }) }),
2807
+ /* @__PURE__ */ jsx(FormLabel, { children: labels.subjectLabel }),
2808
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, { placeholder: labels.subjectPlaceholder, ...field }) }),
2526
2809
  /* @__PURE__ */ jsx(FormMessage, {})
2527
2810
  ] })
2528
2811
  }
@@ -2533,11 +2816,11 @@ var CreateTicketDialog = () => {
2533
2816
  control: form.control,
2534
2817
  name: "message",
2535
2818
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2536
- /* @__PURE__ */ jsx(FormLabel, { children: "Message" }),
2819
+ /* @__PURE__ */ jsx(FormLabel, { children: labels.messageLabel }),
2537
2820
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2538
2821
  Textarea,
2539
2822
  {
2540
- placeholder: "Describe your issue in detail. Include any error messages, steps to reproduce, or relevant information...",
2823
+ placeholder: labels.messagePlaceholder,
2541
2824
  className: "min-h-[120px]",
2542
2825
  ...field
2543
2826
  }
@@ -2554,24 +2837,32 @@ var CreateTicketDialog = () => {
2554
2837
  variant: "outline",
2555
2838
  onClick: handleClose,
2556
2839
  disabled: isSubmitting,
2557
- children: "Cancel"
2840
+ children: labels.cancel
2558
2841
  }
2559
2842
  ),
2560
2843
  /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2561
2844
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
2562
- "Creating..."
2845
+ labels.creating
2563
2846
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2564
2847
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2565
- "Create Ticket"
2848
+ labels.create
2566
2849
  ] }) })
2567
2850
  ] })
2568
2851
  ] }) })
2569
2852
  ] }) });
2570
2853
  };
2571
2854
  var SupportLayoutContent = () => {
2855
+ const baseT = useT();
2856
+ const st = createTypedExtensionT(baseT, SUPPORT_NAMESPACE);
2572
2857
  const { selectedTicket, selectTicket, openCreateDialog, getUnreadCount } = useSupportLayoutContext();
2573
- const [isMobile, setIsMobile] = React7.useState(false);
2574
- React7.useEffect(() => {
2858
+ const [isMobile, setIsMobile] = React8.useState(false);
2859
+ const labels = useMemo(() => ({
2860
+ title: st("layout.title"),
2861
+ titleShort: st("layout.titleShort"),
2862
+ subtitle: st("layout.subtitle"),
2863
+ newTicket: st("layout.newTicket")
2864
+ }), [st]);
2865
+ React8.useEffect(() => {
2575
2866
  const checkMobile = () => setIsMobile(window.innerWidth <= 768);
2576
2867
  checkMobile();
2577
2868
  window.addEventListener("resize", checkMobile);
@@ -2592,12 +2883,12 @@ var SupportLayoutContent = () => {
2592
2883
  children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-5 w-5" })
2593
2884
  }
2594
2885
  ) : /* @__PURE__ */ jsx(LifeBuoy, { className: "h-6 w-6 text-primary" }),
2595
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: selectedTicket ? selectedTicket.subject : "Support" }),
2886
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: selectedTicket ? selectedTicket.subject : labels.titleShort }),
2596
2887
  unreadCount > 0 && !selectedTicket && /* @__PURE__ */ jsx("div", { className: "h-5 w-5 bg-red-500 text-white text-xs rounded-full flex items-center justify-center", children: unreadCount })
2597
2888
  ] }),
2598
2889
  !selectedTicket && /* @__PURE__ */ jsxs(Button, { onClick: openCreateDialog, size: "sm", children: [
2599
2890
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2600
- "New Ticket"
2891
+ labels.newTicket
2601
2892
  ] })
2602
2893
  ] }),
2603
2894
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: selectedTicket ? (
@@ -2618,14 +2909,14 @@ var SupportLayoutContent = () => {
2618
2909
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2619
2910
  /* @__PURE__ */ jsx(LifeBuoy, { className: "h-7 w-7 text-primary" }),
2620
2911
  /* @__PURE__ */ jsxs("div", { children: [
2621
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: "Support Center" }),
2622
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Get help from our support team" })
2912
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: labels.title }),
2913
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: labels.subtitle })
2623
2914
  ] }),
2624
2915
  unreadCount > 0 && /* @__PURE__ */ jsx("div", { className: "h-6 w-6 bg-red-500 text-white text-sm rounded-full flex items-center justify-center", children: unreadCount })
2625
2916
  ] }),
2626
2917
  /* @__PURE__ */ jsxs(Button, { onClick: openCreateDialog, children: [
2627
2918
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2628
- "New Ticket"
2919
+ labels.newTicket
2629
2920
  ] })
2630
2921
  ] }),
2631
2922
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxs(ResizablePanelGroup, { direction: "horizontal", className: "h-full", children: [
@@ -2646,7 +2937,7 @@ var SupportLayout = () => {
2646
2937
  // package.json
2647
2938
  var package_default = {
2648
2939
  name: "@djangocfg/ext-support",
2649
- version: "1.0.21",
2940
+ version: "1.0.22",
2650
2941
  description: "Support ticket system extension for DjangoCFG",
2651
2942
  keywords: [
2652
2943
  "django",
@@ -2692,6 +2983,11 @@ var package_default = {
2692
2983
  types: "./dist/config.d.ts",
2693
2984
  import: "./dist/config.js",
2694
2985
  require: "./dist/config.cjs"
2986
+ },
2987
+ "./i18n": {
2988
+ types: "./dist/i18n.d.ts",
2989
+ import: "./dist/i18n.js",
2990
+ require: "./dist/i18n.cjs"
2695
2991
  }
2696
2992
  },
2697
2993
  files: [
@@ -2707,6 +3003,7 @@ var package_default = {
2707
3003
  peerDependencies: {
2708
3004
  "@djangocfg/api": "workspace:*",
2709
3005
  "@djangocfg/ext-base": "workspace:*",
3006
+ "@djangocfg/i18n": "workspace:*",
2710
3007
  "@djangocfg/ui-core": "workspace:*",
2711
3008
  consola: "^3.4.2",
2712
3009
  "lucide-react": "^0.545.0",
@@ -2722,6 +3019,7 @@ var package_default = {
2722
3019
  devDependencies: {
2723
3020
  "@djangocfg/api": "workspace:*",
2724
3021
  "@djangocfg/ext-base": "workspace:*",
3022
+ "@djangocfg/i18n": "workspace:*",
2725
3023
  "@djangocfg/ui-core": "workspace:*",
2726
3024
  "@djangocfg/typescript-config": "workspace:*",
2727
3025
  "@types/node": "^24.7.2",