@ssml-builder-js/ssml-editor-react 2.12.0 → 2.14.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.
package/dist/index.mjs CHANGED
@@ -782,6 +782,152 @@ var SILENCE_VALUE_DESCRIPTIONS = {
782
782
  };
783
783
 
784
784
  // src/locales.ts
785
+ var SSML_ELEMENT_COPY = {
786
+ ja: {
787
+ dialog: {
788
+ label: "\u30C0\u30A4\u30A2\u30ED\u30B0",
789
+ description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002",
790
+ validationErrors: { turn: "turn \u306F dialog \u306E\u76F4\u4E0B\u306B\u914D\u7F6E\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
791
+ },
792
+ "mstts:dialog": {
793
+ label: "\u30C0\u30A4\u30A2\u30ED\u30B0",
794
+ description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002",
795
+ validationErrors: { turn: "turn \u306F dialog \u306E\u76F4\u4E0B\u306B\u914D\u7F6E\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
796
+ },
797
+ turn: {
798
+ label: "\u8A71\u8005\u30BF\u30FC\u30F3",
799
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
800
+ validationErrors: { voice: "voice \u307E\u305F\u306F speaker \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
801
+ },
802
+ "mstts:turn": {
803
+ label: "\u8A71\u8005\u30BF\u30FC\u30F3",
804
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
805
+ validationErrors: { voice: "voice \u307E\u305F\u306F speaker \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
806
+ },
807
+ backgroundaudio: {
808
+ label: "\u80CC\u666F\u97F3\u58F0",
809
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
810
+ validationErrors: { src: "\u80CC\u666F\u97F3\u58F0\u306B\u306F URL \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
811
+ },
812
+ "mstts:backgroundaudio": {
813
+ label: "\u80CC\u666F\u97F3\u58F0",
814
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
815
+ validationErrors: { src: "\u80CC\u666F\u97F3\u58F0\u306B\u306F URL \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
816
+ },
817
+ ttsembedding: {
818
+ label: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
819
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
820
+ validationErrors: { speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
821
+ },
822
+ "mstts:ttsembedding": {
823
+ label: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
824
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
825
+ validationErrors: { speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
826
+ },
827
+ embedding: {
828
+ label: "\u57CB\u3081\u8FBC\u307F",
829
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
830
+ validationErrors: {}
831
+ },
832
+ "mstts:embedding": {
833
+ label: "\u57CB\u3081\u8FBC\u307F",
834
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
835
+ validationErrors: {}
836
+ },
837
+ silence: {
838
+ label: "\u7121\u97F3",
839
+ description: "\u767A\u8A71\u524D\u5F8C\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u306B\u7121\u97F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002",
840
+ validationErrors: { value: "\u7121\u97F3\u306E\u9577\u3055\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
841
+ },
842
+ "mstts:silence": {
843
+ label: "\u7121\u97F3",
844
+ description: "\u767A\u8A71\u524D\u5F8C\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u306B\u7121\u97F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002",
845
+ validationErrors: { value: "\u7121\u97F3\u306E\u9577\u3055\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }
846
+ },
847
+ voiceconversion: {
848
+ label: "\u97F3\u58F0\u5909\u63DB",
849
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
850
+ validationErrors: {}
851
+ },
852
+ "mstts:voiceconversion": {
853
+ label: "\u97F3\u58F0\u5909\u63DB",
854
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
855
+ validationErrors: {}
856
+ }
857
+ },
858
+ en: {
859
+ dialog: {
860
+ label: "Dialog",
861
+ description: "Groups multiple speaker turns.",
862
+ validationErrors: { turn: "Place turns directly inside a dialog." }
863
+ },
864
+ "mstts:dialog": {
865
+ label: "Dialog",
866
+ description: "Groups multiple speaker turns.",
867
+ validationErrors: { turn: "Place turns directly inside a dialog." }
868
+ },
869
+ turn: {
870
+ label: "Dialog turn",
871
+ description: "Specifies a speaker and utterance within a dialog.",
872
+ validationErrors: { voice: "Provide a voice or speaker." }
873
+ },
874
+ "mstts:turn": {
875
+ label: "Dialog turn",
876
+ description: "Specifies a speaker and utterance within a dialog.",
877
+ validationErrors: { voice: "Provide a voice or speaker." }
878
+ },
879
+ backgroundaudio: {
880
+ label: "Background audio",
881
+ description: "Specifies an audio file played behind synthesized speech.",
882
+ validationErrors: { src: "Provide a background audio URL." }
883
+ },
884
+ "mstts:backgroundaudio": {
885
+ label: "Background audio",
886
+ description: "Specifies an audio file played behind synthesized speech.",
887
+ validationErrors: { src: "Provide a background audio URL." }
888
+ },
889
+ ttsembedding: {
890
+ label: "TTS embedding",
891
+ description: "Embeds custom voice or speaker profile metadata.",
892
+ validationErrors: { speakerProfileId: "Provide a speaker profile ID." }
893
+ },
894
+ "mstts:ttsembedding": {
895
+ label: "TTS embedding",
896
+ description: "Embeds custom voice or speaker profile metadata.",
897
+ validationErrors: { speakerProfileId: "Provide a speaker profile ID." }
898
+ },
899
+ embedding: {
900
+ label: "Embedding",
901
+ description: "Specifies speaker embedding metadata.",
902
+ validationErrors: {}
903
+ },
904
+ "mstts:embedding": {
905
+ label: "Embedding",
906
+ description: "Specifies speaker embedding metadata.",
907
+ validationErrors: {}
908
+ },
909
+ silence: {
910
+ label: "Silence",
911
+ description: "Adds silence before, after, or around punctuation.",
912
+ validationErrors: { value: "Provide a silence duration." }
913
+ },
914
+ "mstts:silence": {
915
+ label: "Silence",
916
+ description: "Adds silence before, after, or around punctuation.",
917
+ validationErrors: { value: "Provide a silence duration." }
918
+ },
919
+ voiceconversion: {
920
+ label: "Voice conversion",
921
+ description: "Specifies custom voice conversion metadata.",
922
+ validationErrors: {}
923
+ },
924
+ "mstts:voiceconversion": {
925
+ label: "Voice conversion",
926
+ description: "Specifies custom voice conversion metadata.",
927
+ validationErrors: {}
928
+ }
929
+ }
930
+ };
785
931
  var EDITOR_COPY = {
786
932
  ja: {
787
933
  editorAriaLabel: "SSML\u30A8\u30C7\u30A3\u30BF\u30FC",
@@ -999,6 +1145,42 @@ var SSML_HOVER_COPY = {
999
1145
  parameters: {
1000
1146
  value: { title: "value", description: "\u76EE\u6A19\u6642\u9593\u3002\u4F8B: `10s`\u3001`5000ms`\u3001`00:00:10`\u3002" }
1001
1147
  }
1148
+ },
1149
+ "mstts:dialog": { title: "\u30C0\u30A4\u30A2\u30ED\u30B0", description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
1150
+ "mstts:turn": {
1151
+ title: "\u8A71\u8005\u30BF\u30FC\u30F3",
1152
+ description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1153
+ parameters: {
1154
+ voice: { title: "voice", description: "\u3053\u306E\u30BF\u30FC\u30F3\u3067\u4F7F\u7528\u3059\u308B Azure \u97F3\u58F0\u540D\u3002" },
1155
+ speaker: { title: "speaker", description: "\u8A71\u8005\u8B58\u5225\u5B50\u3002" }
1156
+ }
1157
+ },
1158
+ "mstts:backgroundaudio": {
1159
+ title: "\u80CC\u666F\u97F3\u58F0",
1160
+ description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1161
+ parameters: { src: { title: "src", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u306E HTTPS URL\u3002" } }
1162
+ },
1163
+ "mstts:ttsembedding": {
1164
+ title: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
1165
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
1166
+ parameters: { speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" } }
1167
+ },
1168
+ "mstts:embedding": {
1169
+ title: "\u57CB\u3081\u8FBC\u307F",
1170
+ description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1171
+ parameters: {
1172
+ id: { title: "id", description: "\u57CB\u3081\u8FBC\u307F ID\u3002" },
1173
+ speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
1174
+ }
1175
+ },
1176
+ "mstts:voiceconversion": {
1177
+ title: "\u97F3\u58F0\u5909\u63DB",
1178
+ description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
1179
+ parameters: {
1180
+ url: { title: "url", description: "\u97F3\u58F0\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB URL\u3002" },
1181
+ profile: { title: "profile", description: "\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3002" },
1182
+ speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
1183
+ }
1002
1184
  }
1003
1185
  }
1004
1186
  },
@@ -1163,6 +1345,42 @@ var SSML_HOVER_COPY = {
1163
1345
  parameters: {
1164
1346
  value: { title: "value", description: "The target duration, such as `10s`, `5000ms`, or `00:00:10`." }
1165
1347
  }
1348
+ },
1349
+ "mstts:dialog": { title: "Dialog", description: "Groups multiple speaker turns.", parameters: {} },
1350
+ "mstts:turn": {
1351
+ title: "Dialog turn",
1352
+ description: "Specifies a speaker and utterance within a dialog.",
1353
+ parameters: {
1354
+ voice: { title: "voice", description: "The Azure voice used by this turn." },
1355
+ speaker: { title: "speaker", description: "The speaker identifier." }
1356
+ }
1357
+ },
1358
+ "mstts:backgroundaudio": {
1359
+ title: "Background audio",
1360
+ description: "Specifies an audio file played behind synthesized speech.",
1361
+ parameters: { src: { title: "src", description: "The HTTPS URL of the audio file." } }
1362
+ },
1363
+ "mstts:ttsembedding": {
1364
+ title: "TTS embedding",
1365
+ description: "Embeds custom voice or speaker profile metadata.",
1366
+ parameters: { speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." } }
1367
+ },
1368
+ "mstts:embedding": {
1369
+ title: "Embedding",
1370
+ description: "Specifies speaker embedding metadata.",
1371
+ parameters: {
1372
+ id: { title: "id", description: "The embedding ID." },
1373
+ speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
1374
+ }
1375
+ },
1376
+ "mstts:voiceconversion": {
1377
+ title: "Voice conversion",
1378
+ description: "Specifies custom voice conversion metadata.",
1379
+ parameters: {
1380
+ url: { title: "url", description: "The voice conversion profile URL." },
1381
+ profile: { title: "profile", description: "The conversion profile." },
1382
+ speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
1383
+ }
1166
1384
  }
1167
1385
  }
1168
1386
  }
@@ -4775,14 +4993,102 @@ var VISUAL_ELEMENT_FIELDS = {
4775
4993
  function getElementFields(element) {
4776
4994
  return VISUAL_ELEMENT_FIELDS[elementLabel(element)] ?? [];
4777
4995
  }
4996
+ function localizedElementLabel(element, locale) {
4997
+ return SSML_ELEMENT_COPY[locale][elementLabel(element)]?.label ?? elementLabel(element);
4998
+ }
4999
+ function filteredVoices(voiceCatalog, locale, region, style) {
5000
+ return (voiceCatalog ?? []).filter((voice) => {
5001
+ if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
5002
+ const regions = [voice.region, ...voice.regions ?? []].filter(
5003
+ (candidate) => Boolean(candidate)
5004
+ );
5005
+ if (region && regions.length > 0 && !regions.some((candidate) => candidate.toLowerCase() === region.toLowerCase()))
5006
+ return false;
5007
+ if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
5008
+ return true;
5009
+ });
5010
+ }
5011
+ function VoiceCapabilityMatrix({
5012
+ voice,
5013
+ locale
5014
+ }) {
5015
+ const status = voice.status ?? (voice.preview ? "preview" : void 0);
5016
+ return /* @__PURE__ */ jsxs2("div", { className: "ssml-editor-voice-capabilities", "data-voice-capabilities": "", children: [
5017
+ /* @__PURE__ */ jsxs2("div", { children: [
5018
+ locale === "ja" ? "\u30B9\u30C6\u30FC\u30BF\u30B9" : "Status",
5019
+ ": ",
5020
+ status?.toUpperCase() ?? (locale === "ja" ? "GA" : "GA"),
5021
+ status === "preview" || status === "deprecated" ? /* @__PURE__ */ jsx6("span", { role: "status", "aria-label": status, className: "ssml-editor-voice-warning-badge", children: status === "preview" ? "\u26A0 Preview" : "\u26A0 Deprecated" }) : null
5022
+ ] }),
5023
+ (voice.regions?.length || voice.region) && /* @__PURE__ */ jsxs2("div", { children: [
5024
+ locale === "ja" ? "\u30EA\u30FC\u30B8\u30E7\u30F3" : "Regions",
5025
+ ":",
5026
+ " ",
5027
+ [...voice.regions ?? [], ...voice.region ? [voice.region] : []].filter((region, index, all) => all.indexOf(region) === index).join(", ")
5028
+ ] }),
5029
+ voice.supportedTags && voice.supportedTags.length > 0 && /* @__PURE__ */ jsxs2("div", { children: [
5030
+ locale === "ja" ? "\u5BFE\u5FDC\u30BF\u30B0" : "Supported tags",
5031
+ ": ",
5032
+ voice.supportedTags.join(", ")
5033
+ ] }),
5034
+ voice.unsupportedTags && voice.unsupportedTags.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "ssml-editor-voice-unsupported", children: [
5035
+ locale === "ja" ? "\u975E\u5BFE\u5FDC\u30BF\u30B0" : "Unsupported tags",
5036
+ ": ",
5037
+ voice.unsupportedTags.join(", ")
5038
+ ] })
5039
+ ] });
5040
+ }
5041
+ function DefaultVoiceSelector({
5042
+ value,
5043
+ voices,
5044
+ selectedVoice,
5045
+ readOnly,
5046
+ locale,
5047
+ onChange
5048
+ }) {
5049
+ return /* @__PURE__ */ jsxs2(Fragment3, { children: [
5050
+ /* @__PURE__ */ jsxs2(
5051
+ "select",
5052
+ {
5053
+ "aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
5054
+ value,
5055
+ disabled: readOnly,
5056
+ onChange: (event) => onChange(event.target.value),
5057
+ children: [
5058
+ /* @__PURE__ */ jsx6("option", { value: "", children: locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice" }),
5059
+ voices.map((voice) => /* @__PURE__ */ jsxs2("option", { value: voice.name, children: [
5060
+ voice.name,
5061
+ voice.preview || voice.status === "preview" ? " (preview)" : ""
5062
+ ] }, voice.name))
5063
+ ]
5064
+ }
5065
+ ),
5066
+ selectedVoice ? /* @__PURE__ */ jsx6(VoiceCapabilityMatrix, { voice: selectedVoice, locale }) : null
5067
+ ] });
5068
+ }
4778
5069
  function VisualElementInspector({
4779
5070
  document: document2,
4780
5071
  element,
4781
5072
  path,
4782
5073
  readOnly,
4783
- commit
5074
+ commit,
5075
+ locale,
5076
+ customInspector,
5077
+ renderVoiceSelector,
5078
+ voiceCatalog,
5079
+ voiceLocale,
5080
+ voiceRegion,
5081
+ voiceStyle
4784
5082
  }) {
5083
+ if (customInspector) {
5084
+ return /* @__PURE__ */ jsx6(Fragment3, { children: customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }) });
5085
+ }
4785
5086
  const fields = getElementFields(element);
5087
+ const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
5088
+ const selectedVoice = voiceCatalog?.find(
5089
+ (voice) => voice.name === (element.type === "voice" ? element.name : void 0)
5090
+ );
5091
+ const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
4786
5092
  return /* @__PURE__ */ jsxs2("fieldset", { children: [
4787
5093
  /* @__PURE__ */ jsx6("legend", { children: `<${elementLabel(element)}>` }),
4788
5094
  fields.length === 0 ? /* @__PURE__ */ jsx6("p", { children: "This element is preserved in the visual tree. Edit its attributes in Code mode." }) : fields.map((field) => {
@@ -4790,8 +5096,48 @@ function VisualElementInspector({
4790
5096
  const inputValue = value === void 0 ? "" : String(value);
4791
5097
  const inputId = `ssml-visual-${field.key}`;
4792
5098
  return /* @__PURE__ */ jsxs2("label", { htmlFor: inputId, children: [
4793
- field.label,
4794
- field.multiline ? /* @__PURE__ */ jsx6(
5099
+ locale === "ja" ? {
5100
+ name: "\u540D\u524D",
5101
+ effect: "\u52B9\u679C",
5102
+ rate: "\u901F\u5EA6",
5103
+ pitch: "\u30D4\u30C3\u30C1",
5104
+ volume: "\u97F3\u91CF",
5105
+ contour: "\u30D4\u30C3\u30C1\u66F2\u7DDA",
5106
+ range: "\u7BC4\u56F2",
5107
+ style: "\u30B9\u30BF\u30A4\u30EB",
5108
+ styleDegree: "\u30B9\u30BF\u30A4\u30EB\u5F37\u5EA6",
5109
+ role: "\u5F79\u5272",
5110
+ interpretAs: "\u89E3\u91C8",
5111
+ alphabet: "\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8",
5112
+ ph: "\u767A\u97F3",
5113
+ level: "\u5F37\u8ABF\u30EC\u30D9\u30EB",
5114
+ src: "\u97F3\u58F0 URL",
5115
+ desc: "\u8AAC\u660E",
5116
+ clipBegin: "\u958B\u59CB\u4F4D\u7F6E",
5117
+ clipEnd: "\u7D42\u4E86\u4F4D\u7F6E",
5118
+ speed: "\u901F\u5EA6",
5119
+ repeatCount: "\u7E70\u308A\u8FD4\u3057\u56DE\u6570",
5120
+ repeatDuration: "\u7E70\u308A\u8FD4\u3057\u6642\u9593",
5121
+ soundLevel: "\u97F3\u91CF\u30EC\u30D9\u30EB",
5122
+ mark: "\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u540D",
5123
+ alias: "\u5225\u540D",
5124
+ lang: "\u8A00\u8A9E",
5125
+ uri: "\u8F9E\u66F8 URI",
5126
+ typeValue: "\u7121\u97F3\u306E\u7A2E\u985E",
5127
+ value: "\u5024",
5128
+ id: "\u57CB\u3081\u8FBC\u307F ID",
5129
+ speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID",
5130
+ url: "\u97F3\u58F0\u5909\u63DB URL",
5131
+ profile: "\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB"
5132
+ }[field.key] ?? field.label : field.label,
5133
+ field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
5134
+ value: inputValue,
5135
+ voices: availableVoices,
5136
+ selectedVoice,
5137
+ readOnly,
5138
+ locale,
5139
+ onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
5140
+ }) : field.multiline ? /* @__PURE__ */ jsx6(
4795
5141
  "textarea",
4796
5142
  {
4797
5143
  id: inputId,
@@ -4887,13 +5233,21 @@ function VisualSsmlEditor({
4887
5233
  document: document2,
4888
5234
  readOnly = false,
4889
5235
  onChange,
4890
- onPreviewSelection
5236
+ onPreviewSelection,
5237
+ locale = "en",
5238
+ customInspectors,
5239
+ renderVoiceSelector,
5240
+ voiceCatalog,
5241
+ voiceLocale,
5242
+ voiceRegion,
5243
+ voiceStyle
4891
5244
  }) {
4892
5245
  const [selectedPath, setSelectedPath] = useState2(null);
4893
5246
  const [selection, setSelection] = useState2({ start: 0, end: 0 });
4894
5247
  const textLeaves = useMemo(() => collectTextLeaves(document2.children ?? []), [document2]);
4895
5248
  const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
4896
5249
  const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
5250
+ const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
4897
5251
  const diagnostics = useMemo(() => validateAzureSsml(buildSsml3(document2)), [document2]);
4898
5252
  const commit = (nextDocument) => onChange?.(nextDocument);
4899
5253
  const applyWrapper = (tag, attributes) => {
@@ -4928,25 +5282,40 @@ function VisualSsmlEditor({
4928
5282
  isElement(node) ? elementLabel(node) : JSON.stringify(node)
4929
5283
  )) })
4930
5284
  ] }),
4931
- /* @__PURE__ */ jsx6("div", { className: "ssml-editor-visual-form", children: selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ jsxs2("fieldset", { children: [
4932
- /* @__PURE__ */ jsx6("legend", { children: "Dialog" }),
4933
- /* @__PURE__ */ jsx6("p", { children: "Add and edit speaker turns in this dialog." }),
5285
+ /* @__PURE__ */ jsx6("div", { className: "ssml-editor-visual-form", children: selectedCustomInspector && selectedElement && isElement(selectedElement) ? selectedCustomInspector({
5286
+ document: document2,
5287
+ element: selectedElement,
5288
+ path: selectedPath ?? [],
5289
+ readOnly,
5290
+ onChange: commit,
5291
+ locale
5292
+ }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ jsxs2("fieldset", { children: [
5293
+ /* @__PURE__ */ jsx6("legend", { children: localizedElementLabel(selectedElement, locale) }),
5294
+ /* @__PURE__ */ jsx6("p", { children: SSML_ELEMENT_COPY[locale][elementLabel(selectedElement)]?.description }),
4934
5295
  /* @__PURE__ */ jsx6(
4935
5296
  "button",
4936
5297
  {
4937
5298
  type: "button",
4938
5299
  disabled: readOnly,
4939
5300
  onClick: () => commit(addDialogTurn(document2, selectedPath ?? [])),
4940
- children: "Add turn"
5301
+ children: locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
4941
5302
  }
4942
5303
  )
4943
5304
  ] }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ jsxs2("fieldset", { children: [
4944
- /* @__PURE__ */ jsx6("legend", { children: "Dialog turn" }),
4945
- /* @__PURE__ */ jsxs2("label", { children: [
4946
- "Voice",
4947
- /* @__PURE__ */ jsx6(
5305
+ /* @__PURE__ */ jsx6("legend", { children: localizedElementLabel(selectedElement, locale) }),
5306
+ /* @__PURE__ */ jsxs2("label", { htmlFor: "ssml-visual-turn-voice", children: [
5307
+ locale === "ja" ? "\u97F3\u58F0" : "Voice",
5308
+ voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
5309
+ value: selectedElement.voice ?? "",
5310
+ voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
5311
+ selectedVoice: voiceCatalog?.find((voice) => voice.name === selectedElement.voice),
5312
+ readOnly,
5313
+ locale,
5314
+ onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
5315
+ }) : /* @__PURE__ */ jsx6(
4948
5316
  "input",
4949
5317
  {
5318
+ id: "ssml-visual-turn-voice",
4950
5319
  value: selectedElement.voice ?? "",
4951
5320
  readOnly,
4952
5321
  onChange: (event) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", event.target.value))
@@ -4954,7 +5323,7 @@ function VisualSsmlEditor({
4954
5323
  )
4955
5324
  ] }),
4956
5325
  /* @__PURE__ */ jsxs2("label", { children: [
4957
- "Speaker",
5326
+ locale === "ja" ? "\u8A71\u8005" : "Speaker",
4958
5327
  /* @__PURE__ */ jsx6(
4959
5328
  "input",
4960
5329
  {
@@ -4965,7 +5334,7 @@ function VisualSsmlEditor({
4965
5334
  )
4966
5335
  ] }),
4967
5336
  /* @__PURE__ */ jsxs2("label", { children: [
4968
- "Turn text",
5337
+ locale === "ja" ? "\u767A\u8A71\u30C6\u30AD\u30B9\u30C8" : "Turn text",
4969
5338
  /* @__PURE__ */ jsx6(
4970
5339
  "textarea",
4971
5340
  {
@@ -4982,9 +5351,9 @@ function VisualSsmlEditor({
4982
5351
  )
4983
5352
  ] })
4984
5353
  ] }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:backgroundaudio" ? /* @__PURE__ */ jsxs2("fieldset", { children: [
4985
- /* @__PURE__ */ jsx6("legend", { children: "Background audio" }),
5354
+ /* @__PURE__ */ jsx6("legend", { children: localizedElementLabel(selectedElement, locale) }),
4986
5355
  /* @__PURE__ */ jsxs2("label", { children: [
4987
- "Source URL",
5356
+ locale === "ja" ? "\u97F3\u58F0 URL" : "Source URL",
4988
5357
  /* @__PURE__ */ jsx6(
4989
5358
  "input",
4990
5359
  {
@@ -4995,7 +5364,7 @@ function VisualSsmlEditor({
4995
5364
  )
4996
5365
  ] }),
4997
5366
  /* @__PURE__ */ jsxs2("label", { children: [
4998
- "Volume",
5367
+ locale === "ja" ? "\u97F3\u91CF" : "Volume",
4999
5368
  /* @__PURE__ */ jsx6(
5000
5369
  "input",
5001
5370
  {
@@ -5006,7 +5375,7 @@ function VisualSsmlEditor({
5006
5375
  )
5007
5376
  ] }),
5008
5377
  /* @__PURE__ */ jsxs2("label", { children: [
5009
- "Fade in",
5378
+ locale === "ja" ? "\u30D5\u30A7\u30FC\u30C9\u30A4\u30F3" : "Fade in",
5010
5379
  /* @__PURE__ */ jsx6(
5011
5380
  "input",
5012
5381
  {
@@ -5017,7 +5386,7 @@ function VisualSsmlEditor({
5017
5386
  )
5018
5387
  ] }),
5019
5388
  /* @__PURE__ */ jsxs2("label", { children: [
5020
- "Fade out",
5389
+ locale === "ja" ? "\u30D5\u30A7\u30FC\u30C9\u30A2\u30A6\u30C8" : "Fade out",
5021
5390
  /* @__PURE__ */ jsx6(
5022
5391
  "input",
5023
5392
  {
@@ -5034,7 +5403,14 @@ function VisualSsmlEditor({
5034
5403
  element: selectedElement,
5035
5404
  path: selectedPath ?? [],
5036
5405
  readOnly,
5037
- commit
5406
+ commit,
5407
+ locale,
5408
+ customInspector: customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type],
5409
+ renderVoiceSelector,
5410
+ voiceCatalog,
5411
+ voiceLocale,
5412
+ voiceRegion,
5413
+ voiceStyle
5038
5414
  }
5039
5415
  ) : selectedLeaf ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
5040
5416
  /* @__PURE__ */ jsxs2("label", { children: [
@@ -5673,6 +6049,12 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
5673
6049
  insertionGroups,
5674
6050
  customInsertions,
5675
6051
  additionalInsertions,
6052
+ customInspectors,
6053
+ renderVoiceSelector,
6054
+ voiceCatalog,
6055
+ voiceLocale,
6056
+ voiceRegion,
6057
+ voiceStyle,
5676
6058
  emotionStyles,
5677
6059
  className,
5678
6060
  style,
@@ -6114,7 +6496,14 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
6114
6496
  document: draftDocument,
6115
6497
  readOnly: isReadOnly,
6116
6498
  onChange: commit,
6117
- onPreviewSelection
6499
+ onPreviewSelection,
6500
+ locale: localeProp ?? languageProp,
6501
+ customInspectors,
6502
+ renderVoiceSelector,
6503
+ voiceCatalog,
6504
+ voiceLocale,
6505
+ voiceRegion,
6506
+ voiceStyle
6118
6507
  }
6119
6508
  ) }) : /* @__PURE__ */ jsxs3("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight }, children: [
6120
6509
  /* @__PURE__ */ jsx7(
@@ -6192,6 +6581,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
6192
6581
  export {
6193
6582
  EDITOR_COPY,
6194
6583
  INLINE_BADGE_COPY,
6584
+ SSML_ELEMENT_COPY,
6195
6585
  SSML_HOVER_COPY,
6196
6586
  SSML_INSERTIONS,
6197
6587
  SsmlEditor,