@richscripts/richtexteditor 2.15.0 → 2.16.0

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.
Files changed (96) hide show
  1. package/README.md +9 -0
  2. package/angular/build-manifest.json +4 -4
  3. package/angular/index.mjs +1 -1
  4. package/index.d.ts +42 -33
  5. package/integrations/shared.js +10 -0
  6. package/package.json +1 -1
  7. package/richtexteditor/all_plugins.js +2062 -1542
  8. package/richtexteditor/all_plugins.min.js +76 -61
  9. package/richtexteditor/lang/rte-lang-de.js +33 -0
  10. package/richtexteditor/lang/rte-lang-es.js +33 -0
  11. package/richtexteditor/lang/rte-lang-fr.js +33 -0
  12. package/richtexteditor/lang/rte-lang-it.js +33 -0
  13. package/richtexteditor/lang/rte-lang-ja.js +33 -0
  14. package/richtexteditor/lang/rte-lang-ko.js +33 -0
  15. package/richtexteditor/lang/rte-lang-nl.js +33 -0
  16. package/richtexteditor/lang/rte-lang-pt-pt.js +33 -0
  17. package/richtexteditor/lang/rte-lang-pt.js +33 -0
  18. package/richtexteditor/lang/rte-lang-ru.js +33 -0
  19. package/richtexteditor/lang/rte-lang-zh-Hans.js +33 -0
  20. package/richtexteditor/lang/rte-lang-zh-Hant.js +33 -0
  21. package/richtexteditor/plugins/a11yenhance.js +3 -1
  22. package/richtexteditor/plugins/a11yenhance.min.js +1 -1
  23. package/richtexteditor/plugins/accessibilitychecker.js +7 -7
  24. package/richtexteditor/plugins/accessibilitychecker.min.js +1 -1
  25. package/richtexteditor/plugins/aitoolkit.js +91 -83
  26. package/richtexteditor/plugins/aitoolkit.min.js +4 -4
  27. package/richtexteditor/plugins/all_plugins.js +2062 -1542
  28. package/richtexteditor/plugins/all_plugins.min.js +76 -61
  29. package/richtexteditor/plugins/autoembed.js +1 -1
  30. package/richtexteditor/plugins/autoembed.min.js +1 -1
  31. package/richtexteditor/plugins/charlimit.js +2 -2
  32. package/richtexteditor/plugins/charlimit.min.js +2 -2
  33. package/richtexteditor/plugins/comments.js +2 -2
  34. package/richtexteditor/plugins/comments.min.js +2 -2
  35. package/richtexteditor/plugins/contentminimap.js +3 -3
  36. package/richtexteditor/plugins/contentminimap.min.js +1 -1
  37. package/richtexteditor/plugins/crdt-engine.js +27 -1
  38. package/richtexteditor/plugins/documentimport.js +30 -8
  39. package/richtexteditor/plugins/documentimport.min.js +4 -4
  40. package/richtexteditor/plugins/docxexport.js +30 -1
  41. package/richtexteditor/plugins/docxexport.min.js +2 -2
  42. package/richtexteditor/plugins/emojiautocomplete.js +1 -1
  43. package/richtexteditor/plugins/emojiautocomplete.min.js +1 -1
  44. package/richtexteditor/plugins/html2pdf.js +7 -7
  45. package/richtexteditor/plugins/html2pdf.min.js +1 -1
  46. package/richtexteditor/plugins/imageeditor.js +19 -6
  47. package/richtexteditor/plugins/imageeditor.min.js +1 -1
  48. package/richtexteditor/plugins/insertcode.js +8 -8
  49. package/richtexteditor/plugins/insertcode.min.js +4 -4
  50. package/richtexteditor/plugins/insertemoji.js +4 -4
  51. package/richtexteditor/plugins/insertemoji.min.js +1 -1
  52. package/richtexteditor/plugins/insertgallery.js +4 -4
  53. package/richtexteditor/plugins/insertgallery.min.js +1 -1
  54. package/richtexteditor/plugins/inserttemplate.js +10 -2
  55. package/richtexteditor/plugins/inserttemplate.min.js +1 -1
  56. package/richtexteditor/plugins/markdownexport.js +1 -1
  57. package/richtexteditor/plugins/markdownexport.min.js +2 -2
  58. package/richtexteditor/plugins/mentionplugin.js +2 -2
  59. package/richtexteditor/plugins/mentionplugin.min.js +1 -1
  60. package/richtexteditor/plugins/mermaiddiagram.js +5 -5
  61. package/richtexteditor/plugins/mermaiddiagram.min.js +2 -2
  62. package/richtexteditor/plugins/nodetypes.js +1 -1
  63. package/richtexteditor/plugins/nodetypes.min.js +1 -1
  64. package/richtexteditor/plugins/pagination.js +2 -2
  65. package/richtexteditor/plugins/pagination.min.js +1 -1
  66. package/richtexteditor/plugins/pdfexport.js +1751 -1366
  67. package/richtexteditor/plugins/pdfexport.min.js +28 -13
  68. package/richtexteditor/plugins/readaloud.js +1 -1
  69. package/richtexteditor/plugins/readaloud.min.js +1 -1
  70. package/richtexteditor/plugins/revisionhistory.js +4 -4
  71. package/richtexteditor/plugins/revisionhistory.min.js +2 -2
  72. package/richtexteditor/plugins/rubyannotation.js +2 -2
  73. package/richtexteditor/plugins/rubyannotation.min.js +1 -1
  74. package/richtexteditor/plugins/sanitizer.js +57 -4
  75. package/richtexteditor/plugins/sanitizer.min.js +1 -1
  76. package/richtexteditor/plugins/slashcommand.js +2 -2
  77. package/richtexteditor/plugins/slashcommand.min.js +2 -2
  78. package/richtexteditor/plugins/smartchips.js +3 -3
  79. package/richtexteditor/plugins/smartchips.min.js +1 -1
  80. package/richtexteditor/plugins/spellcheck.js +3 -3
  81. package/richtexteditor/plugins/spellcheck.min.js +1 -1
  82. package/richtexteditor/plugins/stateinspector.js +2 -2
  83. package/richtexteditor/plugins/stateinspector.min.js +2 -2
  84. package/richtexteditor/plugins/structured-content-bridge.js +34 -8
  85. package/richtexteditor/plugins/structured-content-bridge.min.js +5 -5
  86. package/richtexteditor/plugins/textdirection.js +1 -1
  87. package/richtexteditor/plugins/textdirection.min.js +1 -1
  88. package/richtexteditor/plugins/trackedchanges.js +1 -1
  89. package/richtexteditor/plugins/trackedchanges.min.js +1 -1
  90. package/richtexteditor/plugins/yjscollab.js +2 -2
  91. package/richtexteditor/plugins/yjscollab.min.js +1 -1
  92. package/richtexteditor/rte-config.js +14 -36
  93. package/richtexteditor/rte-watchdog.js +3 -1
  94. package/richtexteditor/rte-webcomponent.js +3 -1
  95. package/richtexteditor/rte.js +16 -38
  96. package/richtexteditor/runtime/colorpicker_more_ns.htm +3 -1
@@ -99,6 +99,15 @@ function RTE_Plugin_AIToolkit() {
99
99
  var obj = this;
100
100
  var config;
101
101
  var editor;
102
+ // 2026-10-25 UI words outside InitConfig (inline review chips, review shortcuts, Ask AI result / plan, the legacy
103
+ // review layout) read config.text_ keys with English as the fallback; {0} and {1} take the values.
104
+ // tools/i18n/ai-review-chips-language.mjs
105
+ function uiT(key, fallback, a, b) {
106
+ var s = (config && config["text_" + key]) || fallback;
107
+ if (a !== undefined) s = s.split("{0}").join(String(a));
108
+ if (b !== undefined) s = s.split("{1}").join(String(b));
109
+ return s;
110
+ }
102
111
 
103
112
  obj.PluginName = "AIToolkit";
104
113
 
@@ -193,7 +202,6 @@ function RTE_Plugin_AIToolkit() {
193
202
  config.aiToolkitSuggestionLedgerUrl = config.aiToolkitSuggestionLedgerUrl || "";
194
203
  config.aiToolkitReviewLogUrl = config.aiToolkitReviewLogUrl || "";
195
204
  config.aiToolkitAutoToolbarButtons = config.aiToolkitAutoToolbarButtons !== false;
196
- config.aiToolkitUiVersion = config.aiToolkitUiVersion || "v20260520k";
197
205
 
198
206
  appendToolbarCommand("toolbar_default", "#{aiassist}");
199
207
  appendToolbarCommand("toolbar_basic", "#{aiassist}");
@@ -3127,7 +3135,7 @@ function RTE_Plugin_AIToolkit() {
3127
3135
  if (!html) return "";
3128
3136
  html = String(html);
3129
3137
  if (typeof editor.sanitizeHtml === "function") html = editor.sanitizeHtml(html);
3130
- var doc = new DOMParser().parseFromString("<body>" + html + "</body>", "text/html");
3138
+ var doc = new DOMParser().parseFromString(__RTE_TT("<body>" + html + "</body>"), "text/html");
3131
3139
  var styled = doc.body.querySelectorAll("[style]");
3132
3140
  for (var i = 0; i < styled.length; i++) {
3133
3141
  var st = styled[i].style;
@@ -3600,7 +3608,7 @@ function RTE_Plugin_AIToolkit() {
3600
3608
 
3601
3609
  if (suggestion.status === "pending") {
3602
3610
  if (resolvedWrapper) {
3603
- resolvedWrapper.outerHTML = createInlinePreviewHtml(suggestion);
3611
+ resolvedWrapper.outerHTML = __RTE_TT(createInlinePreviewHtml(suggestion));
3604
3612
  updated = true;
3605
3613
  }
3606
3614
  continue;
@@ -3609,7 +3617,7 @@ function RTE_Plugin_AIToolkit() {
3609
3617
  if (suggestion.status === "accepted" || suggestion.status === "rejected" || suggestion.status === "stale") {
3610
3618
  var resolvedHtml = getResolvedSuggestionHtml(suggestion, suggestion.status);
3611
3619
  if (previewWrapper) {
3612
- previewWrapper.outerHTML = resolvedHtml;
3620
+ previewWrapper.outerHTML = __RTE_TT(resolvedHtml);
3613
3621
  updated = true;
3614
3622
  }
3615
3623
  else if (resolvedWrapper && (
@@ -3618,7 +3626,7 @@ function RTE_Plugin_AIToolkit() {
3618
3626
  ? (suggestion.resultHtml || textToInlineHtml(suggestion.resultText || ""))
3619
3627
  : (suggestion.originalHtml || textToInlineHtml(suggestion.originalText || "")))
3620
3628
  )) {
3621
- resolvedWrapper.outerHTML = resolvedHtml;
3629
+ resolvedWrapper.outerHTML = __RTE_TT(resolvedHtml);
3622
3630
  updated = true;
3623
3631
  }
3624
3632
  }
@@ -4404,7 +4412,7 @@ function RTE_Plugin_AIToolkit() {
4404
4412
  }
4405
4413
 
4406
4414
  remoteChip.textContent = sharedUpdateCount > 1 ? sharedUpdateCount + " shared updates" : "Shared update";
4407
- remoteChip.setAttribute("aria-label", "Shared AI review updates");
4415
+ remoteChip.setAttribute("aria-label", uiT("aiu_sharedupdates", "Shared AI review updates"));
4408
4416
 
4409
4417
  var referenceNode = anchorNode && anchorNode.parentNode === wrapper ? anchorNode : (wrapper.querySelector ? wrapper.querySelector(".rte-ai-inline-preview-actions") : null);
4410
4418
  if (referenceNode && referenceNode.parentNode === wrapper) {
@@ -4600,7 +4608,7 @@ function RTE_Plugin_AIToolkit() {
4600
4608
  wrappers[i].appendChild(openedChip);
4601
4609
  }
4602
4610
  }
4603
- openedChip.textContent = "Queue opened";
4611
+ openedChip.textContent = uiT("aiu_queueopened", "Queue opened");
4604
4612
  openedChip.setAttribute("aria-label", "AI review queue opened");
4605
4613
  }
4606
4614
  else if (openedChip && openedChip.parentNode) {
@@ -4631,7 +4639,7 @@ function RTE_Plugin_AIToolkit() {
4631
4639
  wrappers[i].appendChild(focusChip);
4632
4640
  }
4633
4641
  }
4634
- focusChip.textContent = "Focus " + queueFocusLabel;
4642
+ focusChip.textContent = uiT("aiu_focus", "Focus {0}", aiqText(queueFocusLabel) || queueFocusLabel);
4635
4643
  focusChip.setAttribute("aria-label", "Queue opens on " + queueFocusLabel);
4636
4644
  }
4637
4645
  else if (focusChip && focusChip.parentNode) {
@@ -4717,9 +4725,9 @@ function RTE_Plugin_AIToolkit() {
4717
4725
  actionsNodeForSharedState.appendChild(sharedSeenButton);
4718
4726
  }
4719
4727
  }
4720
- sharedSeenButton.textContent = "Got it";
4721
- sharedSeenButton.setAttribute("aria-label", "Clear shared AI review update notice");
4722
- sharedSeenButton.title = "Clear shared AI review update notice";
4728
+ sharedSeenButton.textContent = uiT("aiu_gotit", "Got it");
4729
+ sharedSeenButton.setAttribute("aria-label", uiT("aiu_clearshared", "Clear shared AI review update notice"));
4730
+ sharedSeenButton.title = uiT("aiu_clearshared", "Clear shared AI review update notice");
4723
4731
  applyInlineReviewButtonShortcutState(sharedSeenButton, "Clear shared AI review update notice", inlineButtonShortcutOptions);
4724
4732
  }
4725
4733
  else if (sharedSeenButton && sharedSeenButton.parentNode) {
@@ -4775,8 +4783,8 @@ function RTE_Plugin_AIToolkit() {
4775
4783
  }
4776
4784
  }
4777
4785
  }
4778
- queueChip.textContent = "Item " + pendingPosition.index + " of " + pendingPosition.total;
4779
- queueChip.setAttribute("aria-label", "Current AI review queue position");
4786
+ queueChip.textContent = uiT("aiu_itemof", "Item {0} of {1}", pendingPosition.index, pendingPosition.total);
4787
+ queueChip.setAttribute("aria-label", uiT("aiu_queuepos", "Current AI review queue position"));
4780
4788
  }
4781
4789
  else if (queueChip && queueChip.parentNode) {
4782
4790
  queueChip.parentNode.removeChild(queueChip);
@@ -4852,7 +4860,7 @@ function RTE_Plugin_AIToolkit() {
4852
4860
  wrappers[i].appendChild(undoNextChip);
4853
4861
  }
4854
4862
  }
4855
- undoNextChip.textContent = "Then " + undoInlineNextItem.label;
4863
+ undoNextChip.textContent = uiT("aiu_then", "Then {0}", aiqText(undoInlineNextItem.label) || undoInlineNextItem.label);
4856
4864
  undoNextChip.setAttribute("aria-label", "Undo after this: " + undoInlineNextItem.detail);
4857
4865
  }
4858
4866
  else if (undoNextChip && undoNextChip.parentNode) {
@@ -4888,7 +4896,7 @@ function RTE_Plugin_AIToolkit() {
4888
4896
  wrappers[i].appendChild(redoNextChip);
4889
4897
  }
4890
4898
  }
4891
- redoNextChip.textContent = "Then " + redoInlineNextItem.label;
4899
+ redoNextChip.textContent = uiT("aiu_then", "Then {0}", aiqText(redoInlineNextItem.label) || redoInlineNextItem.label);
4892
4900
  redoNextChip.setAttribute("aria-label", "Redo after this: " + redoInlineNextItem.detail);
4893
4901
  }
4894
4902
  else if (redoNextChip && redoNextChip.parentNode) {
@@ -4907,7 +4915,7 @@ function RTE_Plugin_AIToolkit() {
4907
4915
  }
4908
4916
  }
4909
4917
  shortcutsChip.textContent = getSuggestionQueueShortcutHint(suggestion);
4910
- shortcutsChip.setAttribute("aria-label", "Inline queue preview shortcut");
4918
+ shortcutsChip.setAttribute("aria-label", uiT("aiu_previewshortcut", "Inline queue preview shortcut"));
4911
4919
  }
4912
4920
  else if (!shortcutsChip) {
4913
4921
  shortcutsChip = document.createElement("span");
@@ -5087,7 +5095,7 @@ function RTE_Plugin_AIToolkit() {
5087
5095
  wrappers[i].appendChild(focusChip);
5088
5096
  }
5089
5097
  }
5090
- focusChip.textContent = "Focus " + reviewFocusLabel;
5098
+ focusChip.textContent = uiT("aiu_focus", "Focus {0}", aiqText(reviewFocusLabel) || reviewFocusLabel);
5091
5099
  focusChip.setAttribute("aria-label", "Review opens on " + reviewFocusLabel);
5092
5100
  }
5093
5101
  else if (focusChip && focusChip.parentNode) {
@@ -5599,17 +5607,17 @@ function RTE_Plugin_AIToolkit() {
5599
5607
  shortcutsChip.classList.toggle("is-preview", state === "preview");
5600
5608
  if (state === "preview") {
5601
5609
  renderInlineReviewShortcutDisplayContent(shortcutsChip, "Queue shortcut", getSuggestionQueueShortcutHint(options.suggestion));
5602
- shortcutsChip.setAttribute("aria-label", "Inline queue preview shortcut");
5610
+ shortcutsChip.setAttribute("aria-label", uiT("aiu_previewshortcut", "Inline queue preview shortcut"));
5603
5611
  return true;
5604
5612
  }
5605
5613
  if (state && state !== "wrapper") {
5606
5614
  shortcutsChip.classList.add("is-action");
5607
5615
  renderInlineReviewShortcutDisplayContent(shortcutsChip, "Keyboard guide", getInlineReviewActionShortcutHint(state, options));
5608
- shortcutsChip.setAttribute("aria-label", "Inline AI review action shortcuts");
5616
+ shortcutsChip.setAttribute("aria-label", uiT("aiu_actionshortcuts", "Inline AI review action shortcuts"));
5609
5617
  return true;
5610
5618
  }
5611
5619
  renderInlineReviewShortcutDisplayContent(shortcutsChip, "Keyboard guide", getInlineReviewWrapperShortcutHint(options));
5612
- shortcutsChip.setAttribute("aria-label", "Inline AI review shortcuts");
5620
+ shortcutsChip.setAttribute("aria-label", uiT("aiu_reviewshortcuts", "Inline AI review shortcuts"));
5613
5621
  return true;
5614
5622
  }
5615
5623
 
@@ -6315,7 +6323,7 @@ function RTE_Plugin_AIToolkit() {
6315
6323
  labelNode.className = "rte-ai-inline-preview-reason-label";
6316
6324
  reasonNode.appendChild(labelNode);
6317
6325
  }
6318
- labelNode.textContent = "Why";
6326
+ labelNode.textContent = uiT("air_why", "Why");
6319
6327
  if (!copyNode) {
6320
6328
  copyNode = document.createElement("span");
6321
6329
  copyNode.className = "rte-ai-inline-preview-reason-copy";
@@ -6928,7 +6936,7 @@ function RTE_Plugin_AIToolkit() {
6928
6936
  info.className = "rte-ai-menu-info is-minimal is-detached";
6929
6937
  var titleRow = append(info, "div", "", "rte-ai-menu-title-row");
6930
6938
  var titleIcon = append(titleRow, "span", "", "rte-ai-menu-title-icon");
6931
- titleIcon.innerHTML = config.svgCode_aiassist || "";
6939
+ titleIcon.innerHTML = __RTE_TT(config.svgCode_aiassist || "");
6932
6940
  append(titleRow, "div", "", "rte-ai-menu-title", config.text_aiassist || "Ask AI");
6933
6941
 
6934
6942
  // 2026-05-27 (v20260527a): type-to-filter search bar pinned to the
@@ -6960,7 +6968,7 @@ function RTE_Plugin_AIToolkit() {
6960
6968
  // still click anywhere in the input to focus the textbox.
6961
6969
  var searchIcon = append(searchRow, "span", "", "rte-ai-menu-search-icon");
6962
6970
  searchIcon.setAttribute("aria-hidden", "true");
6963
- searchIcon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="10.5" cy="10.5" r="6"/><path d="M19 19l-3.4-3.4"/></svg>';
6971
+ searchIcon.innerHTML = __RTE_TT('<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="10.5" cy="10.5" r="6"/><path d="M19 19l-3.4-3.4"/></svg>');
6964
6972
  var searchInput = panel.ownerDocument.createElement("input");
6965
6973
  searchInput.type = "text";
6966
6974
  searchInput.className = "rte-ai-menu-search-input";
@@ -7028,7 +7036,7 @@ function RTE_Plugin_AIToolkit() {
7028
7036
  button.setAttribute("aria-label", (action.title || action.id) + " \u2014 " + action.description);
7029
7037
  }
7030
7038
  var icon = append(button, "span", "", "rte-ai-menu-item-icon");
7031
- icon.innerHTML = getActionIconSvg(action);
7039
+ icon.innerHTML = __RTE_TT(getActionIconSvg(action));
7032
7040
  var body = append(button, "span", "", "rte-ai-menu-item-body");
7033
7041
  append(body, "span", "", "rte-ai-menu-item-title", action.title || action.id);
7034
7042
  append(body, "span", "", "rte-ai-menu-item-copy", action.description || "");
@@ -7394,7 +7402,7 @@ function RTE_Plugin_AIToolkit() {
7394
7402
  return false;
7395
7403
  }
7396
7404
 
7397
- wrapper.outerHTML = getResolvedSuggestionHtml(previewState, "accepted");
7405
+ wrapper.outerHTML = __RTE_TT(getResolvedSuggestionHtml(previewState, "accepted"));
7398
7406
  previewState.status = "accepted";
7399
7407
  previewState.decidedAt = new Date().getTime();
7400
7408
  setLastReviewDecision(previewState, "accepted");
@@ -7432,7 +7440,7 @@ function RTE_Plugin_AIToolkit() {
7432
7440
  return false;
7433
7441
  }
7434
7442
 
7435
- wrapper.outerHTML = getResolvedSuggestionHtml(previewState, "rejected");
7443
+ wrapper.outerHTML = __RTE_TT(getResolvedSuggestionHtml(previewState, "rejected"));
7436
7444
  previewState.status = "rejected";
7437
7445
  previewState.decidedAt = new Date().getTime();
7438
7446
  setLastReviewDecision(previewState, "rejected");
@@ -7468,7 +7476,7 @@ function RTE_Plugin_AIToolkit() {
7468
7476
 
7469
7477
  suggestion.status = "pending";
7470
7478
  suggestion.decidedAt = 0;
7471
- wrapper.outerHTML = createInlinePreviewHtml(suggestion);
7479
+ wrapper.outerHTML = __RTE_TT(createInlinePreviewHtml(suggestion));
7472
7480
  getReviewState().showResolved = false;
7473
7481
  pushRedoReviewDecision(suggestion, undoable.status);
7474
7482
  popLastReviewDecision();
@@ -7507,7 +7515,7 @@ function RTE_Plugin_AIToolkit() {
7507
7515
  return false;
7508
7516
  }
7509
7517
 
7510
- wrapper.outerHTML = getResolvedSuggestionHtml(suggestion, redoable.status);
7518
+ wrapper.outerHTML = __RTE_TT(getResolvedSuggestionHtml(suggestion, redoable.status));
7511
7519
  suggestion.status = redoable.status;
7512
7520
  suggestion.decidedAt = new Date().getTime();
7513
7521
  getReviewState().showResolved = false;
@@ -8356,7 +8364,7 @@ function RTE_Plugin_AIToolkit() {
8356
8364
  || "Locate";
8357
8365
  actionNode.innerText = focusLabel;
8358
8366
  if (detailNode) {
8359
- detailNode.innerText = "Press Enter to reopen this suggestion and land on " + focusLabel + ".";
8367
+ detailNode.innerText = uiT("aiu_reopenhint", "Press Enter to reopen this suggestion and land on {0}.", aiqText(focusLabel) || focusLabel);
8360
8368
  }
8361
8369
  if (item && item.setAttribute) {
8362
8370
  item.setAttribute("data-rte-ai-review-open-action-label", focusLabel);
@@ -8382,7 +8390,7 @@ function RTE_Plugin_AIToolkit() {
8382
8390
  if (!titleNode) {
8383
8391
  titleNode = append(moduleNode, "span", "", "rte-ai-review-item-condensed-shortcuts-title");
8384
8392
  }
8385
- titleNode.textContent = "More keys";
8393
+ titleNode.textContent = uiT("aiu_morekeys", "More keys");
8386
8394
  var bodyNode = moduleNode.querySelector ? moduleNode.querySelector(".rte-ai-review-item-condensed-shortcuts-body") : null;
8387
8395
  if (!bodyNode) {
8388
8396
  bodyNode = append(moduleNode, "div", "", "rte-ai-review-shortcuts rte-ai-review-item-condensed-shortcuts-body");
@@ -8662,7 +8670,7 @@ function RTE_Plugin_AIToolkit() {
8662
8670
  wrapper.appendChild(focusChip);
8663
8671
  }
8664
8672
  }
8665
- focusChip.textContent = "Focus " + reviewFocusLabel;
8673
+ focusChip.textContent = uiT("aiu_focus", "Focus {0}", aiqText(reviewFocusLabel) || reviewFocusLabel);
8666
8674
  focusChip.setAttribute("aria-label", "Review opens on " + reviewFocusLabel);
8667
8675
  }
8668
8676
  else if (focusChip && focusChip.parentNode) {
@@ -12276,17 +12284,17 @@ function RTE_Plugin_AIToolkit() {
12276
12284
  }
12277
12285
  var headerStatusNode = panel.querySelector(".rte-ai-chat-header-status.is-status");
12278
12286
  if (headerStatusNode) {
12279
- headerStatusNode.innerHTML = "";
12287
+ headerStatusNode.innerHTML = __RTE_TT("");
12280
12288
  headerStatusNode.innerText = headerData.statusLabel;
12281
12289
  }
12282
12290
  var headerScopeNode = panel.querySelector(".rte-ai-chat-header-status.is-scope");
12283
12291
  if (headerScopeNode) {
12284
- headerScopeNode.innerHTML = "";
12292
+ headerScopeNode.innerHTML = __RTE_TT("");
12285
12293
  headerScopeNode.innerText = headerData.scopeFocusLabel;
12286
12294
  }
12287
12295
  var headerSubtitleNode = panel.querySelector(".rte-ai-chat-subtitle");
12288
12296
  if (headerSubtitleNode) {
12289
- headerSubtitleNode.innerHTML = "";
12297
+ headerSubtitleNode.innerHTML = __RTE_TT("");
12290
12298
  headerSubtitleNode.innerText = headerData.subtitle;
12291
12299
  }
12292
12300
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-header-meta"), headerData.metaPills, "rte-ai-chat-header-meta-pill");
@@ -12327,7 +12335,7 @@ function RTE_Plugin_AIToolkit() {
12327
12335
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-context-summary-meta"), contextData.summaryPills, "rte-ai-chat-context-summary-pill");
12328
12336
  var contextSummaryTextNode = panel.querySelector(".rte-ai-chat-context-summary-text");
12329
12337
  if (contextSummaryTextNode) {
12330
- contextSummaryTextNode.innerHTML = "";
12338
+ contextSummaryTextNode.innerHTML = __RTE_TT("");
12331
12339
  contextSummaryTextNode.innerText = contextData.detail;
12332
12340
  }
12333
12341
  var contextPreviewNode = panel.querySelector(".rte-ai-chat-context-preview");
@@ -12337,13 +12345,13 @@ function RTE_Plugin_AIToolkit() {
12337
12345
  }
12338
12346
  var contextPreviewTitleNode = panel.querySelector(".rte-ai-chat-context-preview-title");
12339
12347
  if (contextPreviewTitleNode) {
12340
- contextPreviewTitleNode.innerHTML = "";
12348
+ contextPreviewTitleNode.innerHTML = __RTE_TT("");
12341
12349
  contextPreviewTitleNode.innerText = contextData.previewTitle;
12342
12350
  }
12343
12351
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-context-preview-meta"), contextData.previewMetaPills, "rte-ai-chat-context-preview-pill");
12344
12352
  var contextPreviewCopyNode = panel.querySelector(".rte-ai-chat-context-preview-copy");
12345
12353
  if (contextPreviewCopyNode) {
12346
- contextPreviewCopyNode.innerHTML = "";
12354
+ contextPreviewCopyNode.innerHTML = __RTE_TT("");
12347
12355
  contextPreviewCopyNode.innerText = contextData.previewSummary;
12348
12356
  }
12349
12357
 
@@ -12370,7 +12378,7 @@ function RTE_Plugin_AIToolkit() {
12370
12378
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-quick-summary-meta"), quickStartData.metaPills, "rte-ai-chat-quick-summary-pill");
12371
12379
  var quickSummaryTextNode = panel.querySelector(".rte-ai-chat-quick-summary-text");
12372
12380
  if (quickSummaryTextNode) {
12373
- quickSummaryTextNode.innerHTML = "";
12381
+ quickSummaryTextNode.innerHTML = __RTE_TT("");
12374
12382
  quickSummaryTextNode.innerText = quickStartData.detail;
12375
12383
  }
12376
12384
 
@@ -12399,12 +12407,12 @@ function RTE_Plugin_AIToolkit() {
12399
12407
  var composerStatusPillNode = panel.querySelector(".rte-ai-chat-status-pill");
12400
12408
  if (composerStatusPillNode) {
12401
12409
  composerStatusPillNode.className = "rte-ai-chat-status-pill is-" + composerData.statusTone;
12402
- composerStatusPillNode.innerHTML = "";
12410
+ composerStatusPillNode.innerHTML = __RTE_TT("");
12403
12411
  composerStatusPillNode.innerText = composerData.statusLabel;
12404
12412
  }
12405
12413
  var composerStatusTextNode = panel.querySelector(".rte-ai-chat-status-text");
12406
12414
  if (composerStatusTextNode) {
12407
- composerStatusTextNode.innerHTML = "";
12415
+ composerStatusTextNode.innerHTML = __RTE_TT("");
12408
12416
  composerStatusTextNode.innerText = composerData.statusText;
12409
12417
  }
12410
12418
  var composerActionsNode = panel.querySelector(".rte-ai-chat-composer-actions");
@@ -12434,12 +12442,12 @@ function RTE_Plugin_AIToolkit() {
12434
12442
  }
12435
12443
  var feedIntroTitleNode = panel.querySelector(".rte-ai-chat-feed-intro-title");
12436
12444
  if (feedIntroTitleNode) {
12437
- feedIntroTitleNode.innerHTML = "";
12445
+ feedIntroTitleNode.innerHTML = __RTE_TT("");
12438
12446
  feedIntroTitleNode.innerText = feedIntroData.title;
12439
12447
  }
12440
12448
  var feedIntroDetailNode = panel.querySelector(".rte-ai-chat-feed-intro-detail");
12441
12449
  if (feedIntroDetailNode) {
12442
- feedIntroDetailNode.innerHTML = "";
12450
+ feedIntroDetailNode.innerHTML = __RTE_TT("");
12443
12451
  feedIntroDetailNode.innerText = feedIntroData.detail;
12444
12452
  }
12445
12453
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-feed-intro-meta"), feedIntroData.metaPills, "rte-ai-chat-feed-intro-pill");
@@ -12450,12 +12458,12 @@ function RTE_Plugin_AIToolkit() {
12450
12458
  }
12451
12459
  var emptyTitleNode = panel.querySelector(".rte-ai-chat-empty-title");
12452
12460
  if (emptyTitleNode && emptyStateData) {
12453
- emptyTitleNode.innerHTML = "";
12461
+ emptyTitleNode.innerHTML = __RTE_TT("");
12454
12462
  emptyTitleNode.innerText = emptyStateData.title;
12455
12463
  }
12456
12464
  var emptyDetailNode = panel.querySelector(".rte-ai-chat-empty-detail");
12457
12465
  if (emptyDetailNode && emptyStateData) {
12458
- emptyDetailNode.innerHTML = "";
12466
+ emptyDetailNode.innerHTML = __RTE_TT("");
12459
12467
  emptyDetailNode.innerText = emptyStateData.detail;
12460
12468
  }
12461
12469
  syncChatPillGroup(panel.querySelector(".rte-ai-chat-empty-meta"), emptyStateData ? emptyStateData.metaPills : [], "rte-ai-chat-empty-pill");
@@ -12617,7 +12625,7 @@ function RTE_Plugin_AIToolkit() {
12617
12625
  var headerCopy = append(header, "div", "", "rte-ai-chat-header-copy");
12618
12626
  var titleRow = append(headerCopy, "div", "", "rte-ai-chat-title-row");
12619
12627
  var titleIcon = append(titleRow, "span", "", "rte-ai-chat-title-icon");
12620
- titleIcon.innerHTML = config.svgCode_aiassist_chat || config.svgCode_aiassist || "";
12628
+ titleIcon.innerHTML = __RTE_TT(config.svgCode_aiassist_chat || config.svgCode_aiassist || "");
12621
12629
  append(titleRow, "div", "", "rte-ai-chat-title", headerTitleText);
12622
12630
  var headerActions = append(header, "div", "", "rte-ai-chat-header-actions");
12623
12631
  // 2026-05-15 (v20260515c): New chat button → icon-only. Sat next
@@ -12645,7 +12653,7 @@ function RTE_Plugin_AIToolkit() {
12645
12653
  closeButton.setAttribute("data-rte-ai-chat-header-action", "close");
12646
12654
  closeButton.setAttribute("aria-label", (obj.__aiT ? obj.__aiT("aic_closechat", "Close AI chat") : "Close AI chat"));
12647
12655
  closeButton.title = (obj.__aiT ? obj.__aiT("aic_close", "Close") : "Close");
12648
- closeButton.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>';
12656
+ closeButton.innerHTML = __RTE_TT('<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>');
12649
12657
  closeButton.onclick = function () {
12650
12658
  closeChatPanel({ restoreFocus: true });
12651
12659
  };
@@ -12962,11 +12970,11 @@ function RTE_Plugin_AIToolkit() {
12962
12970
  var avatarKind = message.isError ? "error" : message.role;
12963
12971
  var avatar = append(messageHeader, "span", "", "rte-ai-chat-message-avatar is-" + avatarKind);
12964
12972
  avatar.setAttribute("aria-hidden", "true");
12965
- avatar.innerHTML = avatarKind === "user"
12973
+ avatar.innerHTML = __RTE_TT(avatarKind === "user"
12966
12974
  ? '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><circle cx="8" cy="5.5" r="2.8"/><path d="M8 9.4c-2.8 0-5.2 1.5-5.2 3.4 0 .4.3.7.7.7h9c.4 0 .7-.3.7-.7 0-1.9-2.4-3.4-5.2-3.4z"/></svg>'
12967
12975
  : (avatarKind === "error"
12968
12976
  ? '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="8" cy="8" r="6.5"/><path d="M8 5v3.5M8 11.2v.1"/></svg>'
12969
- : '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><rect x="3" y="5" width="10" height="8" rx="2"/><circle cx="8" cy="3" r="0.9"/><line x1="8" y1="3.9" x2="8" y2="5" stroke="currentColor" stroke-width="1"/><circle cx="6" cy="9" r="1.1" fill="#ffffff"/><circle cx="10" cy="9" r="1.1" fill="#ffffff"/></svg>');
12977
+ : '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><rect x="3" y="5" width="10" height="8" rx="2"/><circle cx="8" cy="3" r="0.9"/><line x1="8" y1="3.9" x2="8" y2="5" stroke="currentColor" stroke-width="1"/><circle cx="6" cy="9" r="1.1" fill="#ffffff"/><circle cx="10" cy="9" r="1.1" fill="#ffffff"/></svg>'));
12970
12978
  append(messageHeader, "span", "", "rte-ai-chat-message-role is-" + (message.isError ? "error" : message.role), getChatMessageRoleLabel(message));
12971
12979
  append(item, "div", "", "rte-ai-chat-message-text", message.text || "");
12972
12980
  // 2026-05-08: per-message Copy + Regenerate row for assistant
@@ -14825,7 +14833,7 @@ function RTE_Plugin_AIToolkit() {
14825
14833
  if (prefixMatch) {
14826
14834
  var label = ownerDocument.createElement("span");
14827
14835
  label.className = "rte-ai-review-shortcuts-label";
14828
- label.innerText = "Shortcuts:";
14836
+ label.innerText = uiT("aiu_shortcuts", "Shortcuts:");
14829
14837
  node.appendChild(label);
14830
14838
  node.appendChild(ownerDocument.createTextNode(" "));
14831
14839
  }
@@ -14917,7 +14925,7 @@ function RTE_Plugin_AIToolkit() {
14917
14925
  titleNode.className = "rte-ai-review-item-shortcuts-title";
14918
14926
  moduleNode.appendChild(titleNode);
14919
14927
  }
14920
- titleNode.textContent = "Keyboard guide";
14928
+ titleNode.textContent = uiT("aiq_kbguide", "Keyboard guide");
14921
14929
  var bodyNode = moduleNode.querySelector ? moduleNode.querySelector(".rte-ai-review-item-shortcuts-body") : null;
14922
14930
  if (!bodyNode) {
14923
14931
  bodyNode = document.createElement("div");
@@ -15379,7 +15387,7 @@ function RTE_Plugin_AIToolkit() {
15379
15387
  var iconSpan = btn.ownerDocument.createElement("span");
15380
15388
  iconSpan.className = "rte-ai-review-v2-action-icon";
15381
15389
  iconSpan.setAttribute("aria-hidden", "true");
15382
- iconSpan.innerHTML = REVIEW_V2_ICONS[iconKey];
15390
+ iconSpan.innerHTML = __RTE_TT(REVIEW_V2_ICONS[iconKey]);
15383
15391
  btn.appendChild(iconSpan);
15384
15392
  }
15385
15393
  if (label) {
@@ -15449,7 +15457,7 @@ function RTE_Plugin_AIToolkit() {
15449
15457
  // Header
15450
15458
  var header = append(panel, "div", "", "rte-ai-review-v2-header");
15451
15459
  var iconWrap = append(header, "span", "", "rte-ai-review-v2-icon");
15452
- iconWrap.innerHTML = config.svgCode_aiassist_review || config.svgCode_aiassist || "";
15460
+ iconWrap.innerHTML = __RTE_TT(config.svgCode_aiassist_review || config.svgCode_aiassist || "");
15453
15461
  append(header, "div", "", "rte-ai-review-v2-title", config.text_aireview || "AI Review");
15454
15462
  // Pending count moved into the "To review" tab badge below; the
15455
15463
  // header pill would have duplicated that signal.
@@ -15457,7 +15465,7 @@ function RTE_Plugin_AIToolkit() {
15457
15465
  closeBtn.type = "button";
15458
15466
  closeBtn.setAttribute("aria-label", (obj.__aiT ? obj.__aiT("air_closearia", "Close AI review") : "Close AI review"));
15459
15467
  closeBtn.title = (obj.__aiT ? obj.__aiT("air_close", "Close") : "Close");
15460
- closeBtn.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>';
15468
+ closeBtn.innerHTML = __RTE_TT('<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>');
15461
15469
  closeBtn.onclick = function () {
15462
15470
  closeReviewPanel();
15463
15471
  editor.focus();
@@ -15481,7 +15489,7 @@ function RTE_Plugin_AIToolkit() {
15481
15489
  var iconSpan = tab.ownerDocument.createElement("span");
15482
15490
  iconSpan.className = "rte-ai-review-v2-tab-icon";
15483
15491
  iconSpan.setAttribute("aria-hidden", "true");
15484
- iconSpan.innerHTML = REVIEW_V2_ICONS[iconKey];
15492
+ iconSpan.innerHTML = __RTE_TT(REVIEW_V2_ICONS[iconKey]);
15485
15493
  tab.appendChild(iconSpan);
15486
15494
  }
15487
15495
  var labelSpan = tab.ownerDocument.createElement("span");
@@ -15666,7 +15674,7 @@ function RTE_Plugin_AIToolkit() {
15666
15674
  // grid pointing from Current -> Suggested.
15667
15675
  var compareArrow = append(compare, "span", "", "rte-ai-review-v2-compare-arrow");
15668
15676
  compareArrow.setAttribute("aria-hidden", "true");
15669
- compareArrow.innerHTML = REVIEW_V2_ICONS.arrowRight;
15677
+ compareArrow.innerHTML = __RTE_TT(REVIEW_V2_ICONS.arrowRight);
15670
15678
  var after = append(compare, "div", "", "rte-ai-review-v2-after");
15671
15679
  append(after, "span", "", "rte-ai-review-v2-compare-label", (obj.__aiT ? obj.__aiT("air_suggested", "Suggested") : "Suggested"));
15672
15680
  append(after, "div", "", "rte-ai-review-v2-compare-text", normalizeText(sug.resultText));
@@ -15677,7 +15685,7 @@ function RTE_Plugin_AIToolkit() {
15677
15685
  var bulbWrap = reason.ownerDocument.createElement("span");
15678
15686
  bulbWrap.className = "rte-ai-review-v2-reason-icon";
15679
15687
  bulbWrap.setAttribute("aria-hidden", "true");
15680
- bulbWrap.innerHTML = REVIEW_V2_ICONS.bulb;
15688
+ bulbWrap.innerHTML = __RTE_TT(REVIEW_V2_ICONS.bulb);
15681
15689
  reasonLabel.appendChild(bulbWrap);
15682
15690
  var reasonLabelText = reason.ownerDocument.createElement("span");
15683
15691
  reasonLabelText.textContent = (obj.__aiT ? obj.__aiT("air_why", "Why") : "Why");
@@ -15951,7 +15959,7 @@ function RTE_Plugin_AIToolkit() {
15951
15959
  }
15952
15960
  var titleRow = append(headerCopy, "div", "", "rte-ai-review-title-row");
15953
15961
  var titleIcon = append(titleRow, "span", "", "rte-ai-review-title-icon");
15954
- titleIcon.innerHTML = config.svgCode_aiassist_review || config.svgCode_aiassist || "";
15962
+ titleIcon.innerHTML = __RTE_TT(config.svgCode_aiassist_review || config.svgCode_aiassist || "");
15955
15963
  append(titleRow, "div", "", "rte-ai-review-title", config.text_aireview || "AI Review");
15956
15964
  if (hasRemoteReviewSync()) {
15957
15965
  editor.__aiReviewSyncBadgeNode = append(titleRow, "span", "", "rte-ai-review-sync-badge", "");
@@ -15994,7 +16002,7 @@ function RTE_Plugin_AIToolkit() {
15994
16002
  var newestSharedButton = append(headerGroupContext, "button", "", "secondary rte-ai-review-header-button is-shared", "Newest shared");
15995
16003
  newestSharedButton.type = "button";
15996
16004
  newestSharedButton.setAttribute("data-rte-ai-review-focus-key", "newest-shared");
15997
- newestSharedButton.setAttribute("aria-label", "Jump to the newest shared AI review update");
16005
+ newestSharedButton.setAttribute("aria-label", uiT("aiu_jumpnewest", "Jump to the newest shared AI review update"));
15998
16006
  newestSharedButton.onclick = function () {
15999
16007
  locateSuggestion(latestRemoteSuggestionId);
16000
16008
  };
@@ -16004,7 +16012,7 @@ function RTE_Plugin_AIToolkit() {
16004
16012
  var currentPendingButton = append(headerGroupContext, "button", "", "secondary rte-ai-review-header-button is-locate-current", "Locate current");
16005
16013
  currentPendingButton.type = "button";
16006
16014
  currentPendingButton.setAttribute("data-rte-ai-review-focus-key", "locate-current");
16007
- currentPendingButton.setAttribute("aria-label", "Locate the current active AI review item in the editor");
16015
+ currentPendingButton.setAttribute("aria-label", uiT("aiu_locatecurrent", "Locate the current active AI review item in the editor"));
16008
16016
  currentPendingButton.onclick = function () {
16009
16017
  locateSuggestion(activeFilteredSuggestionId);
16010
16018
  };
@@ -16015,7 +16023,7 @@ function RTE_Plugin_AIToolkit() {
16015
16023
  var previousPendingButton = append(headerGroupMove, "button", "", "secondary rte-ai-review-header-button is-nav", "Previous");
16016
16024
  previousPendingButton.type = "button";
16017
16025
  previousPendingButton.setAttribute("data-rte-ai-review-focus-key", "previous-pending");
16018
- previousPendingButton.setAttribute("aria-label", "Jump to the previous pending AI review item in the current filter");
16026
+ previousPendingButton.setAttribute("aria-label", uiT("aiu_jumpprev", "Jump to the previous pending AI review item in the current filter"));
16019
16027
  previousPendingButton.onclick = function () {
16020
16028
  activateReviewSuggestionWithDefaultActionFocus(previousPendingSuggestionId, { focusPanel: true });
16021
16029
  };
@@ -16025,7 +16033,7 @@ function RTE_Plugin_AIToolkit() {
16025
16033
  var nextPendingButton = append(headerGroupMove, "button", "", "secondary rte-ai-review-header-button is-nav", "Next pending");
16026
16034
  nextPendingButton.type = "button";
16027
16035
  nextPendingButton.setAttribute("data-rte-ai-review-focus-key", "next-pending");
16028
- nextPendingButton.setAttribute("aria-label", "Jump to the next pending AI review item in the current filter");
16036
+ nextPendingButton.setAttribute("aria-label", uiT("aiu_jumpnext", "Jump to the next pending AI review item in the current filter"));
16029
16037
  nextPendingButton.onclick = function () {
16030
16038
  activateReviewSuggestionWithDefaultActionFocus(nextPendingSuggestionId, { focusPanel: true });
16031
16039
  };
@@ -16057,9 +16065,9 @@ function RTE_Plugin_AIToolkit() {
16057
16065
  var closeButton = append(headerUtility, "button", "", "rte-ai-panel-close-button is-review-close");
16058
16066
  closeButton.type = "button";
16059
16067
  closeButton.setAttribute("data-rte-ai-review-focus-key", "close-review");
16060
- closeButton.setAttribute("aria-label", "Close AI review");
16061
- closeButton.title = "Close";
16062
- closeButton.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>';
16068
+ closeButton.setAttribute("aria-label", uiT("air_closearia", "Close AI review"));
16069
+ closeButton.title = uiT("air_close", "Close");
16070
+ closeButton.innerHTML = __RTE_TT('<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12"/><path d="M18 6L6 18"/></svg>');
16063
16071
  closeButton.onclick = function () {
16064
16072
  closeReviewPanel();
16065
16073
  };
@@ -16175,7 +16183,7 @@ function RTE_Plugin_AIToolkit() {
16175
16183
  var dismissActivityButton = append(activityCard, "button", "", "secondary rte-ai-review-activity-button", "Got it");
16176
16184
  dismissActivityButton.type = "button";
16177
16185
  dismissActivityButton.setAttribute("data-rte-ai-review-focus-key", "dismiss-activity");
16178
- dismissActivityButton.setAttribute("aria-label", "Dismiss shared AI review update notice");
16186
+ dismissActivityButton.setAttribute("aria-label", uiT("aiu_dismissshared", "Dismiss shared AI review update notice"));
16179
16187
  dismissActivityButton.onclick = function () {
16180
16188
  markReviewActivitySeen();
16181
16189
  renderReviewPanel(true);
@@ -16214,7 +16222,7 @@ function RTE_Plugin_AIToolkit() {
16214
16222
  acceptAllButton.setAttribute("data-rte-ai-review-focus-key", "accept-all");
16215
16223
  acceptAllButton.disabled = typeFilter === "all" ? !counts.pending : !filteredPendingCount;
16216
16224
  if (typeFilter !== "all") {
16217
- acceptAllButton.innerText = "Accept filtered";
16225
+ acceptAllButton.innerText = uiT("aiu_acceptfiltered", "Accept filtered");
16218
16226
  }
16219
16227
  acceptAllButton.onclick = function () {
16220
16228
  if (acceptPendingSuggestionsByType(typeFilter)) {
@@ -16226,7 +16234,7 @@ function RTE_Plugin_AIToolkit() {
16226
16234
  rejectAllButton.setAttribute("data-rte-ai-review-focus-key", "reject-all");
16227
16235
  rejectAllButton.disabled = typeFilter === "all" ? !counts.pending : !filteredPendingCount;
16228
16236
  if (typeFilter !== "all") {
16229
- rejectAllButton.innerText = "Reject filtered";
16237
+ rejectAllButton.innerText = uiT("aiu_rejectfiltered", "Reject filtered");
16230
16238
  }
16231
16239
  rejectAllButton.onclick = function () {
16232
16240
  if (rejectPendingSuggestionsByType(typeFilter)) {
@@ -16519,7 +16527,7 @@ function RTE_Plugin_AIToolkit() {
16519
16527
  appendPanelSectionLabel(previewSection, "rte-ai-review-section-label is-feed", emptyState.previewItems.length > 1 ? "Next queues" : "Next queue");
16520
16528
  var emptyPreviewList = append(previewSection, "div", "", "rte-ai-review-empty-previews");
16521
16529
  emptyPreviewList.setAttribute("role", "toolbar");
16522
- emptyPreviewList.setAttribute("aria-label", "Next review queues");
16530
+ emptyPreviewList.setAttribute("aria-label", uiT("aiu_nextqueues", "Next review queues"));
16523
16531
  for (var previewIndex = 0; previewIndex < emptyState.previewItems.length; previewIndex++) {
16524
16532
  var previewItem = emptyState.previewItems[previewIndex];
16525
16533
  var previewTag = previewItem.typeValue ? "button" : "div";
@@ -17295,8 +17303,8 @@ function RTE_Plugin_AIToolkit() {
17295
17303
  // 540px dialog width.
17296
17304
  var copyButton = append(runRow, "button", "", "secondary is-icon-only");
17297
17305
  copyButton.type = "button";
17298
- copyButton.title = "Copy result into source";
17299
- copyButton.setAttribute("aria-label", "Copy result into source");
17306
+ copyButton.title = uiT("aiu_copytosource", "Copy result into source");
17307
+ copyButton.setAttribute("aria-label", uiT("aiu_copytosource", "Copy result into source"));
17300
17308
  copyButton.setAttribute("data-rte-ai-dialog-action", "copy-to-source");
17301
17309
  setReviewV2ButtonContent(copyButton, "checkAll", "");
17302
17310
 
@@ -17474,7 +17482,7 @@ function RTE_Plugin_AIToolkit() {
17474
17482
  // without throwing.
17475
17483
  var resultLabel = document.createElement("span");
17476
17484
  resultLabel.className = "demo-ai-text-label-inline is-detached";
17477
- resultLabel.innerText = "Result";
17485
+ resultLabel.innerText = uiT("aiu_result", "Result");
17478
17486
  var resultHelp = append(resultField, "span", "", "demo-ai-field-help is-detached", "Review the generated AI suggestion before applying it.");
17479
17487
  resultHelp.id = resultHelpId;
17480
17488
  // 2026-06-03 (v20260603a): real "Copy to clipboard" affordance
@@ -17613,7 +17621,7 @@ function RTE_Plugin_AIToolkit() {
17613
17621
  var refineRow = document.createElement("div");
17614
17622
  refineRow.className = "demo-ai-refine-row is-detached";
17615
17623
  refineRow.setAttribute("role", "group");
17616
- refineRow.setAttribute("aria-label", "Refine AI suggestion");
17624
+ refineRow.setAttribute("aria-label", uiT("aiu_refine", "Refine AI suggestion"));
17617
17625
  // Keep the (now empty) refineRow attached to the dialog grid so any
17618
17626
  // external integration that walks `.demo-ai-refine-row` from the
17619
17627
  // dialog root keeps resolving. The `is-detached` class collapses it
@@ -17691,7 +17699,7 @@ function RTE_Plugin_AIToolkit() {
17691
17699
  var refineWhyChip = document.createElement("button");
17692
17700
  refineWhyChip.type = "button";
17693
17701
  refineWhyChip.className = "secondary demo-ai-refine-chip demo-ai-refine-why-chip is-detached";
17694
- refineWhyChip.innerText = "Why";
17702
+ refineWhyChip.innerText = uiT("air_why", "Why");
17695
17703
  refineWhyChip.title = (obj.__aiT ? obj.__aiT("ai2_whyaria", "Show why this AI suggestion was generated") : "Show why this AI suggestion was generated");
17696
17704
  refineWhyChip.setAttribute("data-rte-ai-dialog-action", "refine-why");
17697
17705
  refineWhyChip.setAttribute("aria-expanded", "false");
@@ -17905,7 +17913,7 @@ function RTE_Plugin_AIToolkit() {
17905
17913
  detailsToggle.type = "button";
17906
17914
  detailsToggle.setAttribute("aria-expanded", "false");
17907
17915
  detailsToggle.setAttribute("aria-controls", "rte-ai-details-" + dialogIdSuffix);
17908
- detailsToggle.title = "Show why and the operation plan";
17916
+ detailsToggle.title = uiT("aiu_showwhy", "Show why and the operation plan");
17909
17917
 
17910
17918
  var insightGrid = append(grid, "div", "", "demo-ai-insight-grid is-collapsed");
17911
17919
  insightGrid.id = detailsToggle.getAttribute("aria-controls");
@@ -17977,7 +17985,7 @@ function RTE_Plugin_AIToolkit() {
17977
17985
 
17978
17986
  function populateDialogModes() {
17979
17987
  var modes = getDialogModes();
17980
- modeSelect.innerHTML = "";
17988
+ modeSelect.innerHTML = __RTE_TT("");
17981
17989
  // 2026-05-20 (v20260520g) — Pass 59: group the 7-mode picker
17982
17990
  // into 2 <optgroup> sections so the dropdown reads as one
17983
17991
  // semantic cluster per intent ("Edit text" vs "Transform")
@@ -18066,7 +18074,7 @@ function RTE_Plugin_AIToolkit() {
18066
18074
 
18067
18075
  function populateTranslateLanguages() {
18068
18076
  var languages = getTranslateLanguages();
18069
- languageSelect.innerHTML = "";
18077
+ languageSelect.innerHTML = __RTE_TT("");
18070
18078
  for (var index = 0; index < languages.length; index++) {
18071
18079
  var option = append(languageSelect, "option", "", "", getTranslateLanguageDisplay(languages[index]));
18072
18080
  option.value = languages[index].value || languages[index].label;
@@ -19123,7 +19131,7 @@ function RTE_Plugin_AIToolkit() {
19123
19131
  applyGuidance.style.display = "none";
19124
19132
  applyGuidanceBadge.innerText = "";
19125
19133
  applyGuidanceDetail.innerText = "";
19126
- applyGuidance.setAttribute("aria-label", "No recommended Ask AI follow-up action yet.");
19134
+ applyGuidance.setAttribute("aria-label", uiT("aiu_norecommended", "No recommended Ask AI follow-up action yet."));
19127
19135
  return;
19128
19136
  }
19129
19137
  applyGuidance.style.display = "";
@@ -19158,7 +19166,7 @@ function RTE_Plugin_AIToolkit() {
19158
19166
  function renderOperationPlan(resolved) {
19159
19167
  var operations = resolved && resolved.operations ? resolved.operations : [];
19160
19168
  var actionState = getDialogActionState();
19161
- planList.innerHTML = "";
19169
+ planList.innerHTML = __RTE_TT("");
19162
19170
  planStatusMessage.innerText = dialoginner.__aiPlanStale
19163
19171
  ? (dialoginner.__aiPlanStaleReason || "Editor changed. Re-run to refresh.")
19164
19172
  : "";
@@ -19178,7 +19186,7 @@ function RTE_Plugin_AIToolkit() {
19178
19186
  planSummary.innerText = "";
19179
19187
  planStatusAction.style.display = "none";
19180
19188
  applyPlanButton.disabled = true;
19181
- applyPlanButton.innerText = "Apply";
19189
+ applyPlanButton.innerText = uiT("aiu_apply", "Apply");
19182
19190
  return;
19183
19191
  }
19184
19192
 
@@ -19261,10 +19269,10 @@ function RTE_Plugin_AIToolkit() {
19261
19269
  + " \u2022 " + skippedCount + " skipped";
19262
19270
  applyPlanButton.disabled = !pendingIndexes.length || !!dialoginner.__aiPlanStale || !actionState.canApplyPlan;
19263
19271
  if (dialoginner.__aiPlanStale) {
19264
- applyPlanButton.innerText = "Re-run to refresh plan";
19272
+ applyPlanButton.innerText = uiT("aiu_rerunplan", "Re-run to refresh plan");
19265
19273
  }
19266
19274
  else if (!pendingIndexes.length) {
19267
- applyPlanButton.innerText = "No pending steps";
19275
+ applyPlanButton.innerText = uiT("aiu_nopending", "No pending steps");
19268
19276
  }
19269
19277
  else if (actionState.pendingSelectionDependent && !actionState.hasSelection) {
19270
19278
  applyPlanButton.innerText = getSelectionRequiredPlanButtonLabel(pendingOperations);
@@ -19273,7 +19281,7 @@ function RTE_Plugin_AIToolkit() {
19273
19281
  applyPlanButton.innerText = getOperationPlanButtonLabel(resolved);
19274
19282
  }
19275
19283
  else {
19276
- applyPlanButton.innerText = "Apply " + pendingIndexes.length + " pending steps";
19284
+ applyPlanButton.innerText = uiT("aiu_applypending", "Apply {0} pending steps", pendingIndexes.length);
19277
19285
  }
19278
19286
  }
19279
19287
 
@@ -19654,7 +19662,7 @@ function RTE_Plugin_AIToolkit() {
19654
19662
  }
19655
19663
  syncDialogScopeUi();
19656
19664
  if (!normalizeText(sourceArea.value)) {
19657
- status.innerText = "Load or type source text before running Ask AI.";
19665
+ status.innerText = uiT("aiu_loadsource", "Load or type source text before running Ask AI.");
19658
19666
  updatePreview();
19659
19667
  return;
19660
19668
  }