@smart-cloud/ai-kit-ui 1.4.6 → 1.4.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smart-cloud/ai-kit-ui",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -24,6 +24,7 @@
24
24
  "@smart-cloud/wpsuite-core": "^2.2.10",
25
25
  "@tabler/icons-react": "^3.40.0",
26
26
  "chroma-js": "^3.2.0",
27
+ "country-flag-icons": "^1.6.15",
27
28
  "react-markdown": "^10.1.0",
28
29
  "rehype-parse": "^9.0.1",
29
30
  "rehype-raw": "^7.0.0",
@@ -41,7 +41,16 @@ import {
41
41
  type WriteArgs,
42
42
  } from "@smart-cloud/ai-kit-core";
43
43
  import { I18n } from "aws-amplify/utils";
44
- import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
44
+ import * as CountryFlagIcons from "country-flag-icons/react/3x2";
45
+ import {
46
+ type ComponentProps,
47
+ FC,
48
+ useCallback,
49
+ useEffect,
50
+ useMemo,
51
+ useRef,
52
+ useState,
53
+ } from "react";
45
54
  import ReactMarkdown from "react-markdown";
46
55
  import remarkGfm from "remark-gfm";
47
56
 
@@ -80,8 +89,97 @@ type GeneratedPostMetadata = {
80
89
  excerpt?: string;
81
90
  };
82
91
 
92
+ type LanguageSelectorOption = {
93
+ value: AiKitLanguageCode;
94
+ label: string;
95
+ countryCode: string;
96
+ };
97
+
98
+ type WriterTone = "neutral" | "formal" | "casual";
99
+ type RewriterTone = "as-is" | "more-formal" | "more-casual";
100
+ type WriterLength = "short" | "medium" | "long";
101
+ type RewriterLength = "as-is" | "shorter" | "longer";
102
+ type SummarizerLength = "short" | "medium" | "long";
103
+ type SummarizerType = "headline" | "key-points" | "teaser" | "tldr";
104
+ type ProofreadResult = {
105
+ corrections: ComponentProps<typeof ProofreadDiff>["corrections"];
106
+ correctedInput?: string;
107
+ };
108
+
83
109
  const aiKit = getAiKitPlugin();
84
110
 
111
+ const LANGUAGE_TO_COUNTRY_CODE: Record<AiKitLanguageCode, string> = {
112
+ ar: "SA",
113
+ en: "US",
114
+ zh: "CN",
115
+ nl: "NL",
116
+ fr: "FR",
117
+ de: "DE",
118
+ he: "IL",
119
+ hi: "IN",
120
+ hu: "HU",
121
+ id: "ID",
122
+ it: "IT",
123
+ ja: "JP",
124
+ ko: "KR",
125
+ no: "NO",
126
+ pl: "PL",
127
+ pt: "PT",
128
+ ru: "RU",
129
+ es: "ES",
130
+ sv: "SE",
131
+ th: "TH",
132
+ tr: "TR",
133
+ uk: "UA",
134
+ };
135
+
136
+ const RTL_LANGUAGES = new Set<AiKitLanguageCode>(["ar", "he"]);
137
+
138
+ function LanguageFlag(props: { countryCode?: string; size?: number }) {
139
+ const { countryCode, size = 18 } = props;
140
+
141
+ if (!countryCode) {
142
+ return null;
143
+ }
144
+
145
+ const Flag = CountryFlagIcons[
146
+ countryCode as keyof typeof CountryFlagIcons
147
+ ] as FC<ComponentProps<"svg">> | undefined;
148
+
149
+ if (!Flag) {
150
+ return null;
151
+ }
152
+
153
+ return (
154
+ <Flag
155
+ aria-hidden="true"
156
+ focusable="false"
157
+ style={{
158
+ display: "block",
159
+ flex: "none",
160
+ height: size,
161
+ width: Math.round(size * (4 / 3)),
162
+ }}
163
+ />
164
+ );
165
+ }
166
+
167
+ function isRtlLanguage(code?: AiKitLanguageCode | "" | null): boolean {
168
+ return Boolean(code && RTL_LANGUAGES.has(code as AiKitLanguageCode));
169
+ }
170
+
171
+ function getSupportedLanguageOptions(): LanguageSelectorOption[] {
172
+ return LANGUAGE_OPTIONS.map((languageOption) => {
173
+ const countryCode = LANGUAGE_TO_COUNTRY_CODE[languageOption.value];
174
+
175
+ return {
176
+ value: languageOption.value,
177
+ label: languageOption.label,
178
+ countryCode,
179
+ };
180
+ });
181
+ }
182
+
85
183
  const postResponseConstraint = {
86
184
  type: "object",
87
185
  properties: {
@@ -314,9 +412,30 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
314
412
  onAccept,
315
413
  onOptionsChanged,
316
414
  language,
415
+ direction,
317
416
  rootElement,
318
417
  } = props;
319
418
 
419
+ const [languageOverride, setLanguageOverride] = useState<
420
+ AiKitLanguageCode | undefined
421
+ >();
422
+ const [directionOverride, setDirectionOverride] = useState<
423
+ "ltr" | "rtl" | "auto" | undefined
424
+ >();
425
+
426
+ const effectiveUiLanguage = languageOverride ?? normalizeLang(language);
427
+ I18n.setLanguage(effectiveUiLanguage || "en");
428
+ const currentUiLanguage = effectiveUiLanguage || "en";
429
+ const effectiveDirection = useMemo(() => {
430
+ const activeDirection = languageOverride ? directionOverride : direction;
431
+
432
+ if (!activeDirection || activeDirection === "auto") {
433
+ return isRtlLanguage(effectiveUiLanguage) ? "rtl" : "ltr";
434
+ }
435
+
436
+ return activeDirection;
437
+ }, [direction, directionOverride, effectiveUiLanguage, languageOverride]);
438
+
320
439
  const allowOverride = {
321
440
  text: allowOverrideDefaults?.text ?? true,
322
441
  instructions: allowOverrideDefaults?.instructions ?? true,
@@ -341,7 +460,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
341
460
  (mode === "summarize" && allowOverride?.type) ||
342
461
  allowOverride?.outputLanguage,
343
462
  );
344
- }, [allowOverride]);
463
+ }, [allowOverride, mode]);
345
464
 
346
465
  const [state, setState] = useState<string>();
347
466
  const [featureOpen, setFeatureOpen] = useState<boolean>(!showOpenButton);
@@ -375,13 +494,17 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
375
494
  defaults?.tone,
376
495
  );
377
496
  const [type, setType] = useState<SummarizerType | undefined>(defaults?.type);
497
+ const [generatedContentLanguage, setGeneratedContentLanguage] = useState<
498
+ AiKitLanguageCode | ""
499
+ >("");
378
500
 
379
501
  const autoRunOnceRef = useRef(false);
502
+ const supportedLanguageOptions = useMemo(
503
+ () => getSupportedLanguageOptions(),
504
+ [],
505
+ );
380
506
 
381
507
  const defaultTitle = useMemo(() => {
382
- if (language) {
383
- I18n.setLanguage(language || "en");
384
- }
385
508
  if (title) {
386
509
  return title;
387
510
  }
@@ -411,7 +534,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
411
534
  break;
412
535
  }
413
536
  return t;
414
- }, [title, mode, language]);
537
+ }, [title, mode, effectiveUiLanguage]);
415
538
 
416
539
  const formatAiKitStatus = useCallback(
417
540
  (e: AiKitStatusEvent | null): string | null => {
@@ -464,7 +587,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
464
587
  return msg || I18n.get("Working...");
465
588
  }
466
589
  },
467
- [language, mode],
590
+ [effectiveUiLanguage, mode],
468
591
  );
469
592
 
470
593
  const inputText = useMemo(() => {
@@ -520,6 +643,18 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
520
643
  const statusText =
521
644
  formatAiKitStatus(ai.statusEvent) ?? (state ? I18n.get(state) : null);
522
645
 
646
+ const setGeneratedResultLanguage = useCallback(
647
+ (nextLanguage?: AiKitLanguageCode | "auto" | "" | null) => {
648
+ if (nextLanguage && nextLanguage !== "auto") {
649
+ setGeneratedContentLanguage(nextLanguage);
650
+ return;
651
+ }
652
+
653
+ setGeneratedContentLanguage(readDefaultOutputLanguage() || "");
654
+ },
655
+ [],
656
+ );
657
+
523
658
  const runGenerate = useCallback(
524
659
  async (modeOverride?: AiModePreference) => {
525
660
  if (!canGenerate) {
@@ -538,11 +673,11 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
538
673
  typeof input === "function" ? await Promise.resolve(input()) : input;
539
674
  switch (mode) {
540
675
  case "summarize": {
676
+ const outLang =
677
+ (outputLanguage && outputLanguage !== "auto"
678
+ ? outputLanguage
679
+ : null) || readDefaultOutputLanguage();
541
680
  const res = await ai.run(async ({ signal, onStatus }) => {
542
- const outLang =
543
- (outputLanguage && outputLanguage !== "auto"
544
- ? outputLanguage
545
- : null) || readDefaultOutputLanguage();
546
681
  const args: SummarizeArgs = {
547
682
  text: text!.trim(),
548
683
  format:
@@ -564,6 +699,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
564
699
  const out = await summarize(args, featureOptions);
565
700
  return out.result;
566
701
  });
702
+ setGeneratedResultLanguage(outLang || "");
567
703
  setGenerated((res as never) ?? "");
568
704
  break;
569
705
  }
@@ -606,6 +742,10 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
606
742
  break;
607
743
  }
608
744
  case "translate": {
745
+ const outLang =
746
+ (outputLanguage && outputLanguage !== "auto"
747
+ ? outputLanguage
748
+ : null) || readDefaultOutputLanguage();
609
749
  const res = await ai.run(async ({ signal, onStatus }) => {
610
750
  let inputLang = inputLanguage ?? "auto";
611
751
  if (inputLang === "auto") {
@@ -621,10 +761,6 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
621
761
  } else {
622
762
  setDetectedLanguage(inputLang);
623
763
  }
624
- const outLang =
625
- (outputLanguage && outputLanguage !== "auto"
626
- ? outputLanguage
627
- : null) || readDefaultOutputLanguage();
628
764
  if (outLang === inputLang) {
629
765
  console.warn(
630
766
  "AI Kit: input and output languages are the same",
@@ -658,10 +794,12 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
658
794
  const out = await translate(args, featureOptions);
659
795
  return out.result;
660
796
  });
797
+ setGeneratedResultLanguage(outLang || "");
661
798
  setGenerated((res as never) ?? "");
662
799
  break;
663
800
  }
664
801
  case "rewrite": {
802
+ let generatedLanguage: AiKitLanguageCode | "" = "";
665
803
  const res = await ai.run(async ({ signal, onStatus }) => {
666
804
  let outLang =
667
805
  (outputLanguage && outputLanguage !== "auto"
@@ -678,6 +816,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
678
816
  });
679
817
  setOutputLanguage(outLang);
680
818
  }
819
+ generatedLanguage = outLang || "";
681
820
  const args: RewriteArgs = {
682
821
  text: text!.trim(),
683
822
  context: instructions?.trim() || undefined,
@@ -700,6 +839,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
700
839
  const out = await rewrite(args, featureOptions);
701
840
  return out.result;
702
841
  });
842
+ setGeneratedResultLanguage(generatedLanguage);
703
843
  setGenerated((res as never) ?? "");
704
844
  break;
705
845
  }
@@ -763,6 +903,7 @@ const AiFeatureBase: FC<AiFeatureProps & AiKitShellInjectedProps> = (props) => {
763
903
  });
764
904
  return out.result;
765
905
  });
906
+ setGeneratedResultLanguage(outLang || "");
766
907
  setGenerated((res as never) ?? "");
767
908
  break;
768
909
  }
@@ -996,7 +1137,7 @@ Follow these additional instructions: ${instructions}`
996
1137
  default:
997
1138
  return ai.lastSource ? I18n.get("Regenerate") : I18n.get("Generate");
998
1139
  }
999
- }, [language, ai.lastSource, mode]);
1140
+ }, [effectiveUiLanguage, ai.lastSource, mode]);
1000
1141
 
1001
1142
  const getRegenerateOnBackendTitle = useCallback(() => {
1002
1143
  switch (mode) {
@@ -1011,7 +1152,7 @@ Follow these additional instructions: ${instructions}`
1011
1152
  default:
1012
1153
  return I18n.get("Regenerate on Backend");
1013
1154
  }
1014
- }, [language, mode]);
1155
+ }, [effectiveUiLanguage, mode]);
1015
1156
 
1016
1157
  const close = useCallback(async () => {
1017
1158
  setFeatureOpen(false);
@@ -1082,6 +1223,16 @@ Follow these additional instructions: ${instructions}`
1082
1223
  };
1083
1224
  }, []);
1084
1225
 
1226
+ useEffect(() => {
1227
+ if (!languageOverride) {
1228
+ return;
1229
+ }
1230
+
1231
+ setDirectionOverride("auto");
1232
+ setOutputLanguage(languageOverride);
1233
+ setDetectedLanguage(undefined);
1234
+ }, [languageOverride]);
1235
+
1085
1236
  const optionsSummary = useMemo(() => {
1086
1237
  const parts: string[] = [];
1087
1238
 
@@ -1126,7 +1277,7 @@ Follow these additional instructions: ${instructions}`
1126
1277
 
1127
1278
  return parts.length ? parts.join(" • ") : I18n.get("No overrides");
1128
1279
  }, [
1129
- language,
1280
+ effectiveUiLanguage,
1130
1281
  mode,
1131
1282
  inputLanguage,
1132
1283
  outputLanguage,
@@ -1151,6 +1302,111 @@ Follow these additional instructions: ${instructions}`
1151
1302
  const CollapseComponent = optionsDisplay === "collapse" ? Collapse : Stack;
1152
1303
  const OptionsComponent = optionsDisplay === "horizontal" ? Group : Stack;
1153
1304
 
1305
+ const selectedLanguageOption = useMemo(
1306
+ () =>
1307
+ supportedLanguageOptions.find(
1308
+ (option) => option.value === currentUiLanguage,
1309
+ ) ?? supportedLanguageOptions[0],
1310
+ [currentUiLanguage, supportedLanguageOptions],
1311
+ );
1312
+
1313
+ const renderLanguageOverrideSelect = useCallback(
1314
+ (size: "xs" | "sm" = "sm") => (
1315
+ <Select
1316
+ allowDeselect={false}
1317
+ aria-label={I18n.get("Interface language")}
1318
+ checkIconPosition="right"
1319
+ className="ai-feature-language-selector"
1320
+ data={supportedLanguageOptions.map((option) => ({
1321
+ value: option.value,
1322
+ label: "",
1323
+ }))}
1324
+ disabled={ai.busy}
1325
+ leftSection={
1326
+ selectedLanguageOption?.countryCode ? (
1327
+ <LanguageFlag
1328
+ countryCode={selectedLanguageOption.countryCode}
1329
+ size={18}
1330
+ />
1331
+ ) : null
1332
+ }
1333
+ onChange={(value) => {
1334
+ const nextLanguage = normalizeLang(value);
1335
+
1336
+ if (!nextLanguage) {
1337
+ return;
1338
+ }
1339
+
1340
+ setLanguageOverride(nextLanguage);
1341
+ }}
1342
+ renderOption={({ option }) => {
1343
+ const languageOption = supportedLanguageOptions.find(
1344
+ (item) => item.value === option.value,
1345
+ );
1346
+
1347
+ if (!languageOption) {
1348
+ return option.label;
1349
+ }
1350
+
1351
+ return (
1352
+ <Group gap="xs" wrap="nowrap">
1353
+ {languageOption.countryCode ? (
1354
+ <LanguageFlag
1355
+ countryCode={languageOption.countryCode}
1356
+ size={18}
1357
+ />
1358
+ ) : null}
1359
+ <span>{I18n.get(languageOption.label)}</span>
1360
+ </Group>
1361
+ );
1362
+ }}
1363
+ rightSection={null}
1364
+ searchable={false}
1365
+ size={size}
1366
+ styles={{
1367
+ dropdown: {
1368
+ minWidth: 220,
1369
+ },
1370
+ input: {
1371
+ backgroundColor: "transparent",
1372
+ border: 0,
1373
+ boxShadow: "none",
1374
+ color: "inherit",
1375
+ fontSize: 18,
1376
+ lineHeight: 1,
1377
+ minHeight: size === "sm" ? 36 : 28,
1378
+ paddingInlineStart: 0,
1379
+ paddingInlineEnd: 0,
1380
+ backgroundImage: "none",
1381
+ width: size === "sm" ? 44 : 36,
1382
+ },
1383
+ option: {
1384
+ color: "inherit",
1385
+ },
1386
+ section: {
1387
+ color: "inherit",
1388
+ alignItems: "center",
1389
+ display: "flex",
1390
+ height: "100%",
1391
+ insetInlineStart: 0,
1392
+ justifyContent: "center",
1393
+ pointerEvents: "none",
1394
+ width: "100%",
1395
+ },
1396
+ }}
1397
+ value={selectedLanguageOption?.value || null}
1398
+ w={size === "sm" ? 44 : 36}
1399
+ />
1400
+ ),
1401
+ [
1402
+ ai.busy,
1403
+ selectedLanguageOption?.countryCode,
1404
+ selectedLanguageOption?.value,
1405
+ setLanguageOverride,
1406
+ supportedLanguageOptions,
1407
+ ],
1408
+ );
1409
+
1154
1410
  useEffect(() => {
1155
1411
  if (variation !== "modal" || !featureOpen) {
1156
1412
  return;
@@ -1214,14 +1470,25 @@ Follow these additional instructions: ${instructions}`
1214
1470
  {variation === "modal" && <Modal.Overlay />}
1215
1471
  <ContentComponent
1216
1472
  w="100%"
1473
+ dir={effectiveDirection}
1217
1474
  style={{
1218
1475
  left: 0,
1219
1476
  }}
1220
1477
  >
1221
1478
  {variation === "modal" && (
1222
- <Modal.Header style={{ zIndex: 1000 }}>
1479
+ <Modal.Header dir={effectiveDirection} style={{ zIndex: 1000 }}>
1223
1480
  {getOpenButtonDefaultIcon("ai-feature-title-icon")}
1224
1481
  <Modal.Title>{I18n.get(defaultTitle)}</Modal.Title>
1482
+ <div
1483
+ style={{
1484
+ display: "flex",
1485
+ flex: 1,
1486
+ justifyContent: "flex-start",
1487
+ marginRight: 8,
1488
+ }}
1489
+ >
1490
+ {renderLanguageOverrideSelect("xs")}
1491
+ </div>
1225
1492
  <Modal.CloseButton />
1226
1493
  </Modal.Header>
1227
1494
  )}
@@ -1231,7 +1498,13 @@ Follow these additional instructions: ${instructions}`
1231
1498
  working={ai.busy}
1232
1499
  variation={variation}
1233
1500
  >
1234
- <Stack gap="sm" mb="sm" p="sm">
1501
+ <Stack gap="sm" mb="sm" p="sm" dir={effectiveDirection}>
1502
+ {variation !== "modal" && (
1503
+ <Group justify="flex-end">
1504
+ {renderLanguageOverrideSelect()}
1505
+ </Group>
1506
+ )}
1507
+
1235
1508
  {/* ERROR */}
1236
1509
  {error && <Alert color="red">{I18n.get(error)}</Alert>}
1237
1510
 
@@ -1877,6 +2150,7 @@ Follow these additional instructions: ${instructions}`
1877
2150
  mode !== "generatePostMetadata" &&
1878
2151
  typeof generated === "string" && (
1879
2152
  <MarkdownResult
2153
+ contentLanguage={generatedContentLanguage}
1880
2154
  value={generated}
1881
2155
  editable={!!editable}
1882
2156
  onChange={(v) => {
@@ -1887,7 +2161,11 @@ Follow these additional instructions: ${instructions}`
1887
2161
  </Stack>
1888
2162
  )}
1889
2163
  {generated === "" && (
1890
- <MarkdownResult value={generated} editable={false} />
2164
+ <MarkdownResult
2165
+ contentLanguage={generatedContentLanguage}
2166
+ value={generated}
2167
+ editable={false}
2168
+ />
1891
2169
  )}
1892
2170
  </Stack>
1893
2171
  {/* ACTIONS */}
@@ -1974,15 +2252,23 @@ Follow these additional instructions: ${instructions}`
1974
2252
  };
1975
2253
 
1976
2254
  function MarkdownResult(props: {
2255
+ contentLanguage?: AiKitLanguageCode | "";
1977
2256
  value: string;
1978
2257
  editable: boolean;
1979
2258
  onChange?: (v: string) => void;
1980
2259
  }) {
1981
- const { value, editable, onChange } = props;
2260
+ const { contentLanguage, value, editable, onChange } = props;
2261
+ const contentDirection = isRtlLanguage(contentLanguage) ? "rtl" : "ltr";
2262
+ const contentAlign = contentDirection === "rtl" ? "right" : "left";
1982
2263
 
1983
2264
  if (editable) {
1984
2265
  return (
1985
- <Stack p={0} gap="sm">
2266
+ <Stack
2267
+ p={0}
2268
+ gap="sm"
2269
+ dir={contentDirection}
2270
+ style={{ textAlign: contentAlign }}
2271
+ >
1986
2272
  <Input.Label>{I18n.get("Generated content")}</Input.Label>
1987
2273
  <Textarea
1988
2274
  value={value}
@@ -1992,10 +2278,17 @@ function MarkdownResult(props: {
1992
2278
  maxRows={12}
1993
2279
  p={0}
1994
2280
  className="ai-feature-generated-content ai-feature-editor"
2281
+ styles={{
2282
+ input: { direction: contentDirection, textAlign: contentAlign },
2283
+ }}
1995
2284
  />
1996
2285
 
1997
2286
  <Input.Label>{I18n.get("Preview")}</Input.Label>
1998
- <Stack className="ai-feature-generated-content ai-feature-preview">
2287
+ <Stack
2288
+ className="ai-feature-generated-content ai-feature-preview"
2289
+ dir={contentDirection}
2290
+ style={{ textAlign: contentAlign }}
2291
+ >
1999
2292
  <ReactMarkdown remarkPlugins={[remarkGfm]}>{value}</ReactMarkdown>
2000
2293
  </Stack>
2001
2294
  </Stack>
@@ -2003,7 +2296,11 @@ function MarkdownResult(props: {
2003
2296
  }
2004
2297
 
2005
2298
  return (
2006
- <Stack className="ai-feature-generated-content">
2299
+ <Stack
2300
+ className="ai-feature-generated-content"
2301
+ dir={contentDirection}
2302
+ style={{ textAlign: contentAlign }}
2303
+ >
2007
2304
  {value ? (
2008
2305
  <ReactMarkdown remarkPlugins={[remarkGfm]}>{value}</ReactMarkdown>
2009
2306
  ) : (
package/src/i18n/ar.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export const arDict: Record<string, string> = {
2
2
  "--- Select ---": "--- اختر ---",
3
- Accept: "يقبل",
3
+ Accept: "قبول",
4
4
  "Accept response": "قبول الرد",
5
5
  Add: "إضافة",
6
6
  "Add image": "إضافة صورة",
@@ -24,7 +24,7 @@ export const arDict: Record<string, string> = {
24
24
  "Audio no longer available": "الرسالة الصوتية لم تعد متاحة",
25
25
  "Audio recorded": "تم تسجيل الصوت",
26
26
  auto: "آلي",
27
- "Auto-detect": "الكشف التلقائي",
27
+ "Auto-detect": "اكتشاف تلقائي",
28
28
  Cancel: "يلغي",
29
29
  Caption: "التسمية التوضيحية",
30
30
  Casual: "غير رسمي",
@@ -32,7 +32,7 @@ export const arDict: Record<string, string> = {
32
32
  Categories: "الفئات",
33
33
  "Checking capabilities…": "إمكانيات الفحص…",
34
34
  Chinese: "الصينية",
35
- Clear: "",
35
+ Clear: "مسح",
36
36
  "Clear audio": "مسح الصوت",
37
37
  "Click again to confirm": "انقر مرة أخرى للتأكيد",
38
38
  Close: "يغلق",
@@ -63,7 +63,7 @@ export const arDict: Record<string, string> = {
63
63
  Formal: "رَسمِيّ",
64
64
  formal: "رَسمِيّ",
65
65
  French: "فرنسي",
66
- Generate: "يولد",
66
+ Generate: "إنشاء",
67
67
  "Generate Image Metadata": "إنشاء بيانات وصفية للصورة",
68
68
  "Generate Post Metadata": "إنشاء بيانات وصفية للمقال",
69
69
  "Generated content": "المحتوى المُنشأ",
@@ -98,7 +98,7 @@ export const arDict: Record<string, string> = {
98
98
  long: "طويل",
99
99
  Longer: "أطول",
100
100
  longer: "أطول",
101
- Markdown: "تخفيض السعر",
101
+ Markdown: "Markdown",
102
102
  Maximize: "تكبير",
103
103
  Medium: "واسطة",
104
104
  medium: "واسطة",
@@ -127,14 +127,14 @@ export const arDict: Record<string, string> = {
127
127
  Preview: "معاينة",
128
128
  Proofread: "التدقيق اللغوي",
129
129
  "Proofread again": "راجع النص مرة أخرى",
130
- "Proofread on Backend": "تمت المراجعة في الواجهة الخلفية",
130
+ "Proofread on Backend": "تدقيق لغوي على الخادم",
131
131
  Proofreading: "التدقيق اللغوي",
132
132
  "Proofreading part {current}/{total}...":
133
133
  "جارٍ تدقيق الجزء {current}/{total}...",
134
134
  "Ready.": "جاهز.",
135
135
  "Received backend response.": "تم استلام رد من الخادم الخلفي.",
136
136
  "Receiving response...": "جارٍ استلام الرد...",
137
- Record: "",
137
+ Record: "تسجيل",
138
138
  "Record audio": "تسجيل الصوت",
139
139
  "Recorded audio:": "صوت مسجّل:",
140
140
  "Recording...": "جارٍ التسجيل...",
@@ -151,7 +151,7 @@ export const arDict: Record<string, string> = {
151
151
  "Restore size": "استعادة الحجم",
152
152
  Rewrite: "إعادة كتابة",
153
153
  "Rewrite again": "أعد الكتابة مرة أخرى",
154
- "Rewrite on Backend": "إعادة كتابة الكود في الواجهة الخلفية",
154
+ "Rewrite on Backend": "إعادة كتابة على الخادم",
155
155
  "Rewriting part {current}/{total}...":
156
156
  "جارٍ إعادة كتابة الجزء {current}/{total}...",
157
157
  "Rewriting text": "إعادة كتابة النص",
@@ -179,13 +179,13 @@ export const arDict: Record<string, string> = {
179
179
  "Suggested change": "التغيير المقترح",
180
180
  Summarize: "لخص",
181
181
  "Summarize again": "أعد التلخيص",
182
- "Summarize on Backend": "تلخيص على الواجهة الخلفية",
182
+ "Summarize on Backend": "تلخيص على الخادم",
183
183
  Summarizing: "ملخص",
184
184
  "Summarizing part {current}/{total}...":
185
185
  "جارٍ تلخيص الجزء {current}/{total}...",
186
186
  Swedish: "السويدية",
187
187
  Tags: "الوسوم",
188
- Teaser: "إعلان تشويقي",
188
+ Teaser: "نص تمهيدي",
189
189
  teaser: "إعلان تشويقي",
190
190
  Thai: "تايلاندي",
191
191
  "The alt text for the image.": "النص البديل للصورة.",
@@ -208,11 +208,11 @@ export const arDict: Record<string, string> = {
208
208
  Title: "عنوان",
209
209
  "TL;DR": "باختصار شديد",
210
210
  tldr: "باختصار",
211
- Tone: "نغمة",
212
- Topic: "عنوان",
211
+ Tone: "الأسلوب",
212
+ Topic: "الموضوع",
213
213
  Translate: "يترجم",
214
214
  "Translate again": "ترجم مرة أخرى",
215
- "Translate on Backend": "الترجمة في الواجهة الخلفية",
215
+ "Translate on Backend": "ترجمة على الخادم",
216
216
  Translating: "الترجمة",
217
217
  "Translating part {current}/{total}...":
218
218
  "جارٍ ترجمة الجزء {current}/{total}...",