chainlit 2.7.0__py3-none-any.whl → 2.7.1__py3-none-any.whl

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.

Potentially problematic release.


This version of chainlit might be problematic. Click here for more details.

Files changed (85) hide show
  1. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/METADATA +1 -1
  2. chainlit-2.7.1.dist-info/RECORD +4 -0
  3. chainlit/__init__.py +0 -207
  4. chainlit/__main__.py +0 -4
  5. chainlit/_utils.py +0 -8
  6. chainlit/action.py +0 -33
  7. chainlit/auth/__init__.py +0 -95
  8. chainlit/auth/cookie.py +0 -197
  9. chainlit/auth/jwt.py +0 -42
  10. chainlit/cache.py +0 -45
  11. chainlit/callbacks.py +0 -433
  12. chainlit/chat_context.py +0 -64
  13. chainlit/chat_settings.py +0 -34
  14. chainlit/cli/__init__.py +0 -235
  15. chainlit/config.py +0 -621
  16. chainlit/context.py +0 -112
  17. chainlit/data/__init__.py +0 -111
  18. chainlit/data/acl.py +0 -19
  19. chainlit/data/base.py +0 -107
  20. chainlit/data/chainlit_data_layer.py +0 -687
  21. chainlit/data/dynamodb.py +0 -616
  22. chainlit/data/literalai.py +0 -501
  23. chainlit/data/sql_alchemy.py +0 -741
  24. chainlit/data/storage_clients/__init__.py +0 -0
  25. chainlit/data/storage_clients/azure.py +0 -84
  26. chainlit/data/storage_clients/azure_blob.py +0 -94
  27. chainlit/data/storage_clients/base.py +0 -28
  28. chainlit/data/storage_clients/gcs.py +0 -101
  29. chainlit/data/storage_clients/s3.py +0 -88
  30. chainlit/data/utils.py +0 -29
  31. chainlit/discord/__init__.py +0 -6
  32. chainlit/discord/app.py +0 -364
  33. chainlit/element.py +0 -454
  34. chainlit/emitter.py +0 -450
  35. chainlit/hello.py +0 -12
  36. chainlit/input_widget.py +0 -182
  37. chainlit/langchain/__init__.py +0 -6
  38. chainlit/langchain/callbacks.py +0 -682
  39. chainlit/langflow/__init__.py +0 -25
  40. chainlit/llama_index/__init__.py +0 -6
  41. chainlit/llama_index/callbacks.py +0 -206
  42. chainlit/logger.py +0 -16
  43. chainlit/markdown.py +0 -57
  44. chainlit/mcp.py +0 -99
  45. chainlit/message.py +0 -619
  46. chainlit/mistralai/__init__.py +0 -50
  47. chainlit/oauth_providers.py +0 -835
  48. chainlit/openai/__init__.py +0 -53
  49. chainlit/py.typed +0 -0
  50. chainlit/secret.py +0 -9
  51. chainlit/semantic_kernel/__init__.py +0 -111
  52. chainlit/server.py +0 -1616
  53. chainlit/session.py +0 -304
  54. chainlit/sidebar.py +0 -55
  55. chainlit/slack/__init__.py +0 -6
  56. chainlit/slack/app.py +0 -427
  57. chainlit/socket.py +0 -381
  58. chainlit/step.py +0 -490
  59. chainlit/sync.py +0 -43
  60. chainlit/teams/__init__.py +0 -6
  61. chainlit/teams/app.py +0 -348
  62. chainlit/translations/bn.json +0 -214
  63. chainlit/translations/el-GR.json +0 -214
  64. chainlit/translations/en-US.json +0 -214
  65. chainlit/translations/fr-FR.json +0 -214
  66. chainlit/translations/gu.json +0 -214
  67. chainlit/translations/he-IL.json +0 -214
  68. chainlit/translations/hi.json +0 -214
  69. chainlit/translations/ja.json +0 -214
  70. chainlit/translations/kn.json +0 -214
  71. chainlit/translations/ml.json +0 -214
  72. chainlit/translations/mr.json +0 -214
  73. chainlit/translations/nl.json +0 -214
  74. chainlit/translations/ta.json +0 -214
  75. chainlit/translations/te.json +0 -214
  76. chainlit/translations/zh-CN.json +0 -214
  77. chainlit/translations.py +0 -60
  78. chainlit/types.py +0 -334
  79. chainlit/user.py +0 -43
  80. chainlit/user_session.py +0 -153
  81. chainlit/utils.py +0 -173
  82. chainlit/version.py +0 -8
  83. chainlit-2.7.0.dist-info/RECORD +0 -84
  84. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/WHEEL +0 -0
  85. {chainlit-2.7.0.dist-info → chainlit-2.7.1.dist-info}/entry_points.txt +0 -0
chainlit/teams/app.py DELETED
@@ -1,348 +0,0 @@
1
- import asyncio
2
- import base64
3
- import mimetypes
4
- import os
5
- import uuid
6
- from datetime import datetime
7
- from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Union
8
-
9
- import filetype
10
-
11
- if TYPE_CHECKING:
12
- from botbuilder.core import TurnContext
13
- from botbuilder.schema import Activity
14
-
15
- import httpx
16
- from botbuilder.core import (
17
- BotFrameworkAdapter,
18
- BotFrameworkAdapterSettings,
19
- MessageFactory,
20
- TurnContext,
21
- )
22
- from botbuilder.schema import (
23
- ActionTypes,
24
- Activity,
25
- ActivityTypes,
26
- Attachment,
27
- CardAction,
28
- ChannelAccount,
29
- HeroCard,
30
- )
31
-
32
- from chainlit.config import config
33
- from chainlit.context import ChainlitContext, HTTPSession, context, context_var
34
- from chainlit.data import get_data_layer
35
- from chainlit.element import Element, ElementDict
36
- from chainlit.emitter import BaseChainlitEmitter
37
- from chainlit.logger import logger
38
- from chainlit.message import Message, StepDict
39
- from chainlit.types import Feedback
40
- from chainlit.user import PersistedUser, User
41
- from chainlit.user_session import user_session
42
-
43
-
44
- class TeamsEmitter(BaseChainlitEmitter):
45
- def __init__(self, session: HTTPSession, turn_context: TurnContext):
46
- super().__init__(session)
47
- self.turn_context = turn_context
48
-
49
- async def send_element(self, element_dict: ElementDict):
50
- if element_dict.get("display") != "inline":
51
- return
52
-
53
- persisted_file = self.session.files.get(element_dict.get("chainlitKey") or "")
54
- attachment: Optional[Attachment] = None
55
- mime: Optional[str] = None
56
-
57
- element_name: str = element_dict.get("name", "Untitled")
58
-
59
- if mime:
60
- file_extension = mimetypes.guess_extension(mime)
61
- if file_extension:
62
- element_name += file_extension
63
-
64
- if persisted_file:
65
- mime = element_dict.get("mime")
66
- with open(persisted_file["path"], "rb") as file:
67
- dencoded_string = base64.b64encode(file.read()).decode()
68
- content_url = f"data:{mime};base64,{dencoded_string}"
69
- attachment = Attachment(
70
- content_type=mime, content_url=content_url, name=element_name
71
- )
72
-
73
- elif url := element_dict.get("url"):
74
- attachment = Attachment(
75
- content_type=mime, content_url=url, name=element_name
76
- )
77
-
78
- if not attachment:
79
- return
80
-
81
- await self.turn_context.send_activity(Activity(attachments=[attachment]))
82
-
83
- async def send_step(self, step_dict: StepDict):
84
- if not step_dict["type"] == "assistant_message":
85
- return
86
-
87
- step_type = step_dict.get("type")
88
- is_message = step_type in [
89
- "user_message",
90
- "assistant_message",
91
- ]
92
- is_empty_output = not step_dict.get("output")
93
-
94
- if is_empty_output or not is_message:
95
- return
96
- else:
97
- reply = MessageFactory.text(step_dict["output"])
98
- enable_feedback = get_data_layer()
99
- if enable_feedback:
100
- current_run = context.current_run
101
- scorable_id = current_run.id if current_run else step_dict["id"]
102
- like_button = CardAction(
103
- type=ActionTypes.message_back,
104
- title="👍",
105
- text="like",
106
- value={"feedback": "like", "step_id": scorable_id},
107
- )
108
- dislike_button = CardAction(
109
- type=ActionTypes.message_back,
110
- title="👎",
111
- text="dislike",
112
- value={"feedback": "dislike", "step_id": scorable_id},
113
- )
114
- card = HeroCard(buttons=[like_button, dislike_button])
115
- attachment = Attachment(
116
- content_type="application/vnd.microsoft.card.hero", content=card
117
- )
118
- reply.attachments = [attachment]
119
-
120
- await self.turn_context.send_activity(reply)
121
-
122
- async def update_step(self, step_dict: StepDict):
123
- if not step_dict["type"] == "assistant_message":
124
- return
125
-
126
- await self.send_step(step_dict)
127
-
128
-
129
- adapter_settings = BotFrameworkAdapterSettings(
130
- app_id=os.environ.get("TEAMS_APP_ID"),
131
- app_password=os.environ.get("TEAMS_APP_PASSWORD"),
132
- )
133
- adapter = BotFrameworkAdapter(adapter_settings)
134
-
135
-
136
- def init_teams_context(
137
- session: HTTPSession,
138
- turn_context: TurnContext,
139
- ) -> ChainlitContext:
140
- emitter = TeamsEmitter(session=session, turn_context=turn_context)
141
- context = ChainlitContext(session=session, emitter=emitter)
142
- context_var.set(context)
143
- user_session.set("teams_turn_context", turn_context)
144
- return context
145
-
146
-
147
- users_by_teams_id: Dict[str, Union[User, PersistedUser]] = {}
148
-
149
- USER_PREFIX = "teams_"
150
-
151
-
152
- async def get_user(teams_user: ChannelAccount):
153
- if teams_user.id in users_by_teams_id:
154
- return users_by_teams_id[teams_user.id]
155
-
156
- metadata = {
157
- "name": teams_user.name,
158
- "id": teams_user.id,
159
- }
160
- user = User(identifier=USER_PREFIX + str(teams_user.name), metadata=metadata)
161
-
162
- users_by_teams_id[teams_user.id] = user
163
-
164
- if data_layer := get_data_layer():
165
- try:
166
- persisted_user = await data_layer.create_user(user)
167
- if persisted_user:
168
- users_by_teams_id[teams_user.id] = persisted_user
169
- except Exception as e:
170
- logger.error(f"Error creating user: {e}")
171
-
172
- return users_by_teams_id[teams_user.id]
173
-
174
-
175
- async def download_teams_file(url: str):
176
- async with httpx.AsyncClient() as client:
177
- response = await client.get(url)
178
- if response.status_code == 200:
179
- return response.content
180
- else:
181
- return None
182
-
183
-
184
- async def download_teams_files(
185
- session: HTTPSession, attachments: Optional[List[Attachment]] = None
186
- ):
187
- if not attachments:
188
- return []
189
-
190
- attachments = [
191
- attachment for attachment in attachments if isinstance(attachment.content, dict)
192
- ]
193
- download_coros = [
194
- download_teams_file(attachment.content.get("downloadUrl"))
195
- for attachment in attachments
196
- ]
197
- file_bytes_list = await asyncio.gather(*download_coros)
198
- file_refs = []
199
- for idx, file_bytes in enumerate(file_bytes_list):
200
- if file_bytes:
201
- name = attachments[idx].name
202
- mime_type = filetype.guess_mime(file_bytes) or "application/octet-stream"
203
- file_ref = await session.persist_file(
204
- name=name, mime=mime_type, content=file_bytes
205
- )
206
- file_refs.append(file_ref)
207
-
208
- files_dicts = [
209
- session.files[file["id"]] for file in file_refs if file["id"] in session.files
210
- ]
211
-
212
- elements = [
213
- Element.from_dict(
214
- {
215
- "id": file["id"],
216
- "name": file["name"],
217
- "path": str(file["path"]),
218
- "chainlitKey": file["id"],
219
- "display": "inline",
220
- "type": Element.infer_type_from_mime(file["type"]),
221
- }
222
- )
223
- for file in files_dicts
224
- ]
225
-
226
- return elements
227
-
228
-
229
- def clean_content(activity: Activity):
230
- return activity.text.strip()
231
-
232
-
233
- async def process_teams_message(
234
- turn_context: TurnContext,
235
- thread_name: str,
236
- ):
237
- user = await get_user(turn_context.activity.from_property)
238
-
239
- thread_id = str(
240
- uuid.uuid5(
241
- uuid.NAMESPACE_DNS,
242
- str(
243
- turn_context.activity.conversation.id
244
- + datetime.today().strftime("%Y-%m-%d")
245
- ),
246
- )
247
- )
248
-
249
- text = clean_content(turn_context.activity)
250
- teams_files = turn_context.activity.attachments
251
-
252
- session_id = str(uuid.uuid4())
253
-
254
- session = HTTPSession(
255
- id=session_id,
256
- thread_id=thread_id,
257
- user=user,
258
- client_type="teams",
259
- )
260
-
261
- ctx = init_teams_context(
262
- session=session,
263
- turn_context=turn_context,
264
- )
265
-
266
- file_elements = await download_teams_files(session, teams_files)
267
-
268
- if on_chat_start := config.code.on_chat_start:
269
- await on_chat_start()
270
-
271
- msg = Message(
272
- content=text,
273
- elements=file_elements,
274
- type="user_message",
275
- author=user.metadata.get("name"),
276
- )
277
-
278
- await msg.send()
279
-
280
- if on_message := config.code.on_message:
281
- await on_message(msg)
282
-
283
- if on_chat_end := config.code.on_chat_end:
284
- await on_chat_end()
285
-
286
- if data_layer := get_data_layer():
287
- if isinstance(user, PersistedUser):
288
- try:
289
- await data_layer.update_thread(
290
- thread_id=thread_id,
291
- name=thread_name,
292
- metadata=ctx.session.to_persistable(),
293
- user_id=user.id,
294
- )
295
- except Exception as e:
296
- logger.error(f"Error updating thread: {e}")
297
-
298
- await ctx.session.delete()
299
-
300
-
301
- async def handle_message(turn_context: TurnContext):
302
- if turn_context.activity.type == ActivityTypes.message:
303
- if (
304
- turn_context.activity.text == "like"
305
- or turn_context.activity.text == "dislike"
306
- ):
307
- feedback_value: Literal[0, 1] = (
308
- 0 if turn_context.activity.text == "dislike" else 1
309
- )
310
- step_id = turn_context.activity.value.get("step_id")
311
- if data_layer := get_data_layer():
312
- await data_layer.upsert_feedback(
313
- Feedback(forId=step_id, value=feedback_value)
314
- )
315
- updated_text = "👍" if turn_context.activity.text == "like" else "👎"
316
- # Update the existing message to remove the buttons
317
- updated_message = Activity(
318
- type=ActivityTypes.message,
319
- id=turn_context.activity.reply_to_id,
320
- text=updated_text,
321
- attachments=[],
322
- )
323
- await turn_context.update_activity(updated_message)
324
- else:
325
- # Send typing activity
326
- typing_activity = Activity(
327
- type=ActivityTypes.typing,
328
- from_property=turn_context.activity.recipient,
329
- recipient=turn_context.activity.from_property,
330
- conversation=turn_context.activity.conversation,
331
- )
332
- await turn_context.send_activity(typing_activity)
333
- thread_name = f"{turn_context.activity.from_property.name} Teams DM {datetime.today().strftime('%Y-%m-%d')}"
334
- await process_teams_message(turn_context, thread_name)
335
-
336
-
337
- async def on_turn(turn_context: TurnContext):
338
- await handle_message(turn_context)
339
-
340
-
341
- # Create the main bot class
342
- class TeamsBot:
343
- async def on_turn(self, turn_context: TurnContext):
344
- await on_turn(turn_context)
345
-
346
-
347
- # Create the bot instance
348
- bot = TeamsBot()
@@ -1,214 +0,0 @@
1
- {
2
- "common": {
3
- "actions": {
4
- "cancel": "বাতিল করুন",
5
- "confirm": "নিশ্চিত করুন",
6
- "continue": "চালিয়ে যান",
7
- "goBack": "পিছনে যান",
8
- "reset": "রিসেট করুন",
9
- "submit": "জমা দিন"
10
- },
11
- "status": {
12
- "loading": "লোড হচ্ছে...",
13
- "error": {
14
- "default": "একটি ত্রুটি ঘটেছে",
15
- "serverConnection": "সার্ভারের সাথে সংযোগ করা যাচ্ছে না"
16
- }
17
- }
18
- },
19
- "auth": {
20
- "login": {
21
- "title": "অ্যাপ্লিকেশন ব্যবহার করতে লগইন করুন",
22
- "form": {
23
- "email": {
24
- "label": "ইমেইল ঠিকানা",
25
- "required": "ইমেইল একটি আবশ্যক ক্ষেত্র"
26
- },
27
- "password": {
28
- "label": "পাসওয়ার্ড",
29
- "required": "পাসওয়ার্ড একটি আবশ্যক ক্ষেত্র"
30
- },
31
- "actions": {
32
- "signin": "সাইন ইন করুন"
33
- },
34
- "alternativeText": {
35
- "or": "অথবা"
36
- }
37
- },
38
- "errors": {
39
- "default": "সাইন ইন করা সম্ভব হচ্ছে না",
40
- "signin": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
41
- "oauthSignin": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
42
- "redirectUriMismatch": "রিডাইরেক্ট URI ওআথ অ্যাপ কনফিগারেশনের সাথে মিলছে না",
43
- "oauthCallback": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
44
- "oauthCreateAccount": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
45
- "emailCreateAccount": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
46
- "callback": "অন্য একটি অ্যাকাউন্ট দিয়ে সাইন ইন করার চেষ্টা করুন",
47
- "oauthAccountNotLinked": "আপনার পরিচয় নিশ্চিত করতে, আপনি যে অ্যাকাউন্টটি মূলত ব্যবহার করেছিলেন সেটি দিয়ে সাইন ইন করুন",
48
- "emailSignin": "ইমেইল পাঠানো যায়নি",
49
- "emailVerify": "অনুগ্রহ করে আপনার ইমেইল যাচাই করুন, একটি নতুন ইমেইল পাঠানো হয়েছে",
50
- "credentialsSignin": "সাইন ইন ব্যর্থ হয়েছে। আপনার দেওয়া তথ্য সঠিক কিনা যাচাই করুন",
51
- "sessionRequired": "এই পৃষ্ঠা দেখতে অনুগ্রহ করে সাইন ইন করুন"
52
- }
53
- },
54
- "provider": {
55
- "continue": "{{provider}} দিয়ে চালিয়ে যান"
56
- }
57
- },
58
- "chat": {
59
- "input": {
60
- "placeholder": "আপনার বার্তা এখানে টাইপ করুন...",
61
- "actions": {
62
- "send": "বার্তা পাঠান",
63
- "stop": "কাজ বন্ধ করুন",
64
- "attachFiles": "ফাইল সংযুক্ত করুন"
65
- }
66
- },
67
- "speech": {
68
- "start": "রেকর্ডিং শুরু করুন",
69
- "stop": "রেকর্ডিং বন্ধ করুন",
70
- "connecting": "সংযোগ করা হচ্ছে"
71
- },
72
- "fileUpload": {
73
- "dragDrop": "এখানে ফাইল টেনে আনুন",
74
- "browse": "ফাইল ব্রাউজ করুন",
75
- "sizeLimit": "সীমা:",
76
- "errors": {
77
- "failed": "আপলোড ব্যর্থ হয়েছে",
78
- "cancelled": "আপলোড বাতিল করা হয়েছে"
79
- }
80
- },
81
- "messages": {
82
- "status": {
83
- "using": "ব্যবহার করছে",
84
- "used": "ব্যবহৃত"
85
- },
86
- "actions": {
87
- "copy": {
88
- "button": "ক্লিপবোর্ডে কপি করুন",
89
- "success": "কপি করা হয়েছে!"
90
- }
91
- },
92
- "feedback": {
93
- "positive": "সহায়ক",
94
- "negative": "সহায়ক নয়",
95
- "edit": "প্রতিক্রিয়া সম্পাদনা করুন",
96
- "dialog": {
97
- "title": "মন্তব্য যোগ করুন",
98
- "submit": "প্রতিক্রিয়া জমা দিন"
99
- },
100
- "status": {
101
- "updating": "হালনাগাদ করা হচ্ছে",
102
- "updated": "প্রতিক্রিয়া হালনাগাদ করা হয়েছে"
103
- }
104
- }
105
- },
106
- "history": {
107
- "title": "সর্বশেষ ইনপুট",
108
- "empty": "কোনো তথ্য নেই...",
109
- "show": "ইতিহাস দেখুন"
110
- },
111
- "settings": {
112
- "title": "সেটিংস প্যানেল"
113
- },
114
- "watermark": "এলএলএম ভুল করতে পারে। গুরুত্বপূর্ণ তথ্য যাচাই করার কথা বিবেচনা করুন।"
115
- },
116
- "threadHistory": {
117
- "sidebar": {
118
- "title": "পূর্ববর্তী চ্যাট",
119
- "filters": {
120
- "search": "অনুসন্ধান",
121
- "placeholder": "Search conversations..."
122
- },
123
- "timeframes": {
124
- "today": "আজ",
125
- "yesterday": "গতকাল",
126
- "previous7days": "গত ৭ দিন",
127
- "previous30days": "গত ৩০ দিন"
128
- },
129
- "empty": "কোনো থ্রেড পাওয়া যায়নি",
130
- "actions": {
131
- "close": "সাইডবার বন্ধ করুন",
132
- "open": "সাইডবার খুলুন"
133
- }
134
- },
135
- "thread": {
136
- "untitled": "শিরোনামহীন আলোচনা",
137
- "menu": {
138
- "rename": "Rename",
139
- "delete": "Delete"
140
- },
141
- "actions": {
142
- "delete": {
143
- "title": "মুছে ফেলা নিশ্চিত করুন",
144
- "description": "এটি থ্রেড এবং এর বার্তা ও উপাদানগুলি মুছে ফেলবে। এই কাজটি পূর্বাবস্থায় ফেরানো যাবে না",
145
- "success": "চ্যাট মুছে ফেলা হয়েছে",
146
- "inProgress": "চ্যাট মুছে ফেলা হচ্ছে"
147
- },
148
- "rename": {
149
- "title": "থ্রেডের নাম পরিবর্তন করুন",
150
- "description": "এই থ্রেডের জন্য একটি নতুন নাম দিন",
151
- "form": {
152
- "name": {
153
- "label": "নাম",
154
- "placeholder": "নতুন নাম লিখুন"
155
- }
156
- },
157
- "success": "থ্রেডের নাম পরিবর্তন করা হয়েছে!",
158
- "inProgress": "থ্রেডের নাম পরিবর্তন করা হচ্ছে"
159
- }
160
- }
161
- }
162
- },
163
- "navigation": {
164
- "header": {
165
- "chat": "চ্যাট",
166
- "readme": "রিডমি",
167
- "theme": {
168
- "light": "Light Theme",
169
- "dark": "Dark Theme",
170
- "system": "Follow System"
171
- }
172
- },
173
- "newChat": {
174
- "button": "নতুন চ্যাট",
175
- "dialog": {
176
- "title": "নতুন চ্যাট তৈরি করুন",
177
- "description": "এটি আপনার বর্তমান চ্যাট ইতিহাস মুছে ফেলবে। আপনি কি চালিয়ে যেতে চান?",
178
- "tooltip": "নতুন চ্যাট"
179
- }
180
- },
181
- "user": {
182
- "menu": {
183
- "settings": "সেটিংস",
184
- "settingsKey": "S",
185
- "apiKeys": "এপিআই কী",
186
- "logout": "লগআউট"
187
- }
188
- }
189
- },
190
- "apiKeys": {
191
- "title": "প্রয়োজনীয় এপিআই কী",
192
- "description": "এই অ্যাপ্লিকেশন ব্যবহার করতে নিম্নলিখিত এপিআই কী প্রয়োজন। কীগুলি আপনার ডিভাইসের লোকাল স্টোরেজে সংরক্ষিত থাকে।",
193
- "success": {
194
- "saved": "সফলভাবে সংরক্ষিত হয়েছে"
195
- }
196
- },
197
- "alerts": {
198
- "info": "Info",
199
- "note": "Note",
200
- "tip": "Tip",
201
- "important": "Important",
202
- "warning": "Warning",
203
- "caution": "Caution",
204
- "debug": "Debug",
205
- "example": "Example",
206
- "success": "Success",
207
- "help": "Help",
208
- "idea": "Idea",
209
- "pending": "Pending",
210
- "security": "Security",
211
- "beta": "Beta",
212
- "best-practice": "Best Practice"
213
- }
214
- }