@umami/shiso 1.17.0 → 1.18.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 (47) hide show
  1. package/dist/chunks/App.js +147 -160
  2. package/dist/chunks/architectureDiagram-5GKGNRK7.js +1 -1
  3. package/dist/chunks/chunk-GMAD6QVW.js +1 -1
  4. package/dist/chunks/cose-bilkent-JH36ORCC.js +1 -1
  5. package/dist/chunks/dist.js +1 -1
  6. package/dist/chunks/docs.js +668 -22
  7. package/dist/chunks/ganttDiagram-EL5Y4UJY.js +1 -1
  8. package/dist/chunks/src.js +1 -1
  9. package/dist/entry-client.js +1 -1
  10. package/dist/entry-server.js +1 -1
  11. package/docs.schema.json +4 -0
  12. package/package.json +1 -1
  13. package/scripts/check-content.mjs +2 -0
  14. package/scripts/load-shiso-config.mjs +30 -1
  15. package/src/App.tsx +32 -22
  16. package/src/components/CodeBlock.tsx +3 -1
  17. package/src/components/Docs.tsx +3 -1
  18. package/src/components/Footer.tsx +3 -1
  19. package/src/components/Header.tsx +4 -3
  20. package/src/components/LanguageSwitcher.tsx +17 -4
  21. package/src/components/OpenApiOperation.tsx +22 -15
  22. package/src/components/PageActions.tsx +8 -7
  23. package/src/components/docs/Changelog.tsx +5 -5
  24. package/src/components/docs/CodeGroup.tsx +3 -1
  25. package/src/components/docs/Mermaid.tsx +8 -6
  26. package/src/components/docs/PropertiesTable.tsx +11 -6
  27. package/src/components/docs/Tabs.tsx +3 -1
  28. package/src/components/docs/Tree.tsx +3 -1
  29. package/src/components/docs/ZoomableImage.tsx +4 -2
  30. package/src/components/ui/dialog.tsx +7 -2
  31. package/src/components/ui/sheet.tsx +5 -2
  32. package/src/lib/label-context.tsx +7 -0
  33. package/src/lib/labels.ts +37 -0
  34. package/src/lib/openapi.ts +21 -8
  35. package/src/lib/site-config.ts +66 -2
  36. package/src/lib/site-model.ts +2 -32
  37. package/src/lib/standalone-pages.ts +15 -1
  38. package/src/lib/translations/de.json +74 -0
  39. package/src/lib/translations/en.json +74 -0
  40. package/src/lib/translations/es.json +74 -0
  41. package/src/lib/translations/fr.json +74 -0
  42. package/src/lib/translations/ja.json +74 -0
  43. package/src/lib/translations/zh-Hans.json +74 -0
  44. package/src/lib/translations/zh-Hant.json +74 -0
  45. package/src/lib/types.ts +20 -32
  46. package/types/config.d.ts +7 -1
  47. package/types/labels.d.ts +76 -0
@@ -1,4 +1,4 @@
1
- import { $ as useFloatingNodeId, $n as useRenderElement, $t as resolveIcon, A as safePolygon, An as isElementVisible, B as attachPreventUnmountOnClose, Bn as getTarget, Cn as getNextTabbable, D as useAnchorPositioning, Dn as findNonDisabledListIndex, Dt as Collapsible, E as getDisabledMountTransitionStyles, En as isOutsideEvent, Er as useNavigate, Et as Expandable, F as createInitialPopupStoreState, Fn as stopEvent, Ft as useCompositeItem, G as useTriggerDataForwarding, Gn as jsdom, H as useImplicitActiveTrigger, Hn as ARROW_LEFT, I as popupStoreSelectors, In as getFloatingFocusElement, J as useDismiss, Jn as useBaseUiId, K as useSyncedFloatingRootContext, Kn as webkit, L as PopupTriggerMap, Ln as isTypeableCombobox, M as useHoverFloatingInteraction, Mn as isListIndexDisabled, Mt as CodeGroup, N as useFocus, Nn as isVirtualClick, Nt as COMPOSITE_KEYS, O as popupTransitionStateMapping, On as getMaxListIndex, Ot as CollapsibleContent, P as usePopupHandleStore, Pn as isVirtualPointerEvent, Pt as inertValue, Q as FloatingTree, Qn as cn, R as FOCUSABLE_POPUP_PROPS, Rn as activeElement, Sn as useDirection, Sr as Route, T as usePositioner, Tn as getTabbableBeforeElement, Tr as useLocation, Tt as renderInlineMarkdown, U as useOpenStateTransitions, Un as ARROW_RIGHT, V as setPopupOpenState, Vn as ARROW_DOWN, W as usePopupInteractionProps, Wn as ARROW_UP, X as FloatingFocusManager, Xn as useTimeout, Xt as Badge$1, Y as useClick, Yn as useId$2, Yt as Badge, Z as FloatingNode, Zn as Button, _n as triggerPress, _r as Check, a as DialogTitle, an as useAnimationFrame, ar as ownerDocument, at as POPUP_COLLISION_AVOIDANCE, br as Link, bt as usePanelContent, c as useOpenInteractionType, cn as escapeKey, cr as useIsoLayoutEffect, ct as fastComponent, d as useScrollLock, dn as itemPress, dr as getParentNode, en as getIcon, er as EMPTY_ARRAY, et as useFloatingParentNodeId, f as DialogPortal$1, fn as listNavigation, fr as getWindow, g as DialogBackdrop, gn as triggerHover, gr as ChevronRight, gt as PropertiesTable, h as DialogClose, hn as triggerFocus, hr as X$1, i as DialogContent$1, in as useCompositeListItem, ir as dispatchClickWithModifiers, it as DROPDOWN_COLLISION_AVOIDANCE, j as useHoverReferenceInteraction, jn as isIndexOutOfListBounds, k as pressableTriggerOpenStateMapping, kn as getMinListIndex, kt as CollapsibleTrigger, l as DialogTitle$1, ln as focusOut, lr as useStableCallback, lt as fastComponentRef, m as DialogPopup, mn as siblingOpen, mr as isLastTraversableNode, n as ZoomableImage, nn as useAnimationsFinished, nr as useMergedRefs, nt as FloatingTreeStore, o as DialogTrigger, on as createChangeEventDetails, or as useCompositeRootContext, ot as enqueueFocus, p as InternalBackdrop, pn as outsidePress, pr as isHTMLElement, q as ReactStore, qn as mac, r as Dialog$1, rn as useValueAsRef, rr as useButton, rt as FloatingPortal, s as DialogTrigger$1, sn as cancelOpen, sr as mergeProps$1, st as FocusGuard, t as docs_exports, tn as useOpenChangeComplete, tr as EMPTY_OBJECT, tt as useFloatingTree, u as DialogRoot, un as imperativeAction, ur as useRefWithInit, vn as CompositeList, vr as createLucideIcon, w as TooltipProvider, wn as getTabbableAfterElement, wr as Routes, xn as addEventListener, xr as Navigate, yn as Mermaid, yt as PanelProvider, z as PopupHandleAttachment, zn as contains } from "./docs.js";
1
+ import { $ as useFloatingNodeId, $n as jsdom, $t as resolveIcon, A as safePolygon, An as useDirection, Ar as Route, B as attachPreventUnmountOnClose, Bn as isListIndexDisabled, Cn as englishLabels, Cr as X$1, D as useAnchorPositioning, Dn as isValidLocale, Dt as Collapsible, E as getDisabledMountTransitionStyles, En as getTextDirection, Er as createLucideIcon, Et as Expandable, F as createInitialPopupStoreState, Fn as findNonDisabledListIndex, Ft as useCompositeItem, G as useTriggerDataForwarding, Gn as isTypeableCombobox, H as useImplicitActiveTrigger, Hn as isVirtualPointerEvent, I as popupStoreSelectors, In as getMaxListIndex, J as useDismiss, Jn as getTarget, K as useSyncedFloatingRootContext, Kn as activeElement, L as PopupTriggerMap, Ln as getMinListIndex, M as useHoverFloatingInteraction, Mn as getTabbableAfterElement, Mr as Routes, Mt as CodeGroup, N as useFocus, Nn as getTabbableBeforeElement, Nr as useLocation, Nt as COMPOSITE_KEYS, O as popupTransitionStateMapping, On as resolveLocale, Or as Link, Ot as CollapsibleContent, P as usePopupHandleStore, Pn as isOutsideEvent, Pr as useNavigate, Pt as inertValue, Q as FloatingTree, Qn as ARROW_UP, R as FOCUSABLE_POPUP_PROPS, Rn as isElementVisible, Sn as useLabels, Sr as isLastTraversableNode, T as usePositioner, Tn as getLanguageName, Tr as Check, Tt as renderInlineMarkdown, U as useOpenStateTransitions, Un as stopEvent, V as setPopupOpenState, Vn as isVirtualClick, W as usePopupInteractionProps, Wn as getFloatingFocusElement, X as FloatingFocusManager, Xn as ARROW_LEFT, Xt as Badge$1, Y as useClick, Yn as ARROW_DOWN, Yt as Badge, Z as FloatingNode, Zn as ARROW_RIGHT, _n as triggerPress, _r as useStableCallback, a as DialogTitle, an as useAnimationFrame, ar as Button, at as POPUP_COLLISION_AVOIDANCE, br as getWindow, bt as usePanelContent, c as useOpenInteractionType, cn as escapeKey, cr as EMPTY_ARRAY, ct as fastComponent, d as useScrollLock, dn as itemPress, dr as useButton, en as getIcon, er as webkit, et as useFloatingParentNodeId, f as DialogPortal$1, fn as listNavigation, fr as dispatchClickWithModifiers, g as DialogBackdrop, gn as triggerHover, gr as useIsoLayoutEffect, gt as PropertiesTable, h as DialogClose, hn as triggerFocus, hr as mergeProps$1, i as DialogContent$1, in as useCompositeListItem, ir as useTimeout, it as DROPDOWN_COLLISION_AVOIDANCE, j as useHoverReferenceInteraction, jn as getNextTabbable, k as pressableTriggerOpenStateMapping, kn as addEventListener, kr as Navigate, kt as CollapsibleTrigger, l as DialogTitle$1, ln as focusOut, lr as EMPTY_OBJECT, lt as fastComponentRef, m as DialogPopup, mn as siblingOpen, mr as useCompositeRootContext, n as ZoomableImage, nn as useAnimationsFinished, nr as useBaseUiId, nt as FloatingTreeStore, o as DialogTrigger, on as createChangeEventDetails, or as cn, ot as enqueueFocus, p as InternalBackdrop, pn as outsidePress, pr as ownerDocument, q as ReactStore, qn as contains, r as Dialog$1, rn as useValueAsRef, rr as useId$2, rt as FloatingPortal, s as DialogTrigger$1, sn as cancelOpen, sr as useRenderElement, st as FocusGuard, t as docs_exports, tn as useOpenChangeComplete, tr as mac, tt as useFloatingTree, u as DialogRoot, un as imperativeAction, ur as useMergedRefs, vn as CompositeList, vr as useRefWithInit, w as TooltipProvider, wn as resolveLabels, wr as ChevronRight, xn as LabelContext, xr as isHTMLElement, yn as Mermaid, yr as getParentNode, yt as PanelProvider, z as PopupHandleAttachment, zn as isIndexOutOfListBounds } from "./docs.js";
2
2
  import { n as highlightTerms } from "./search.js";
3
3
  import { resolveSearchProvider } from "../search.js";
4
4
  import * as React from "react";
@@ -1203,6 +1203,7 @@ function copyText(pre, language) {
1203
1203
  return lines.filter((line) => language === "diff" || line.dataset.diff !== "remove").map((line) => line.textContent || "").join("\n");
1204
1204
  }
1205
1205
  function CodeBlock({ children, className, style, ...rest }) {
1206
+ const labels = useLabels();
1206
1207
  const { "data-title": title, "data-language": language, "data-line-start": lineStart, "data-line-count": lineCount, "data-placement": placement, "data-actions": actions, ...preProps } = rest;
1207
1208
  const textInput = useRef(null);
1208
1209
  const [copied, setCopied] = useState(false);
@@ -1253,7 +1254,7 @@ function CodeBlock({ children, className, style, ...rest }) {
1253
1254
  size: "icon-sm",
1254
1255
  className: cn("absolute right-3 inline-flex size-7 items-center justify-center rounded-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground", title ? "top-1" : "top-2.5"),
1255
1256
  onClick: handleCopy,
1256
- "aria-label": "Copy code",
1257
+ "aria-label": copied ? labels.copied : labels.copyCode,
1257
1258
  children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-primary" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
1258
1259
  })
1259
1260
  ]
@@ -4076,66 +4077,6 @@ function isNodeHidden(node) {
4076
4077
  return !!node.hidden || node.children.every(isNodeHidden);
4077
4078
  }
4078
4079
 
4079
- //#endregion
4080
- //#region src/lib/locale.ts
4081
- /** Primary language subtags written right-to-left. */
4082
- const RTL_LANGUAGES = /* @__PURE__ */ new Set([
4083
- "ar",
4084
- "ckb",
4085
- "dv",
4086
- "fa",
4087
- "he",
4088
- "iw",
4089
- "ps",
4090
- "sd",
4091
- "ug",
4092
- "ur",
4093
- "yi"
4094
- ]);
4095
- /** BCP 47-shaped tags with a 2-3 letter primary subtag, e.g. "es" or "pt-BR". */
4096
- const LOCALE_PATTERN = /^[a-z]{2,3}(-[a-z0-9]{2,8})*$/i;
4097
- function isValidLocale(value) {
4098
- if (!value || !LOCALE_PATTERN.test(value)) return false;
4099
- try {
4100
- return Intl.getCanonicalLocales(value).length > 0;
4101
- } catch {
4102
- return false;
4103
- }
4104
- }
4105
- /**
4106
- * Locale for a page: its scope's language code when valid, then the
4107
- * site-wide shiso.config `locale`, then en-US.
4108
- */
4109
- function resolveLocale(language, fallback) {
4110
- if (isValidLocale(language)) return Intl.getCanonicalLocales(language)[0];
4111
- if (isValidLocale(fallback)) return Intl.getCanonicalLocales(fallback)[0];
4112
- return "en-US";
4113
- }
4114
- /** Document direction for a locale, e.g. "ar" and "he" read right-to-left. */
4115
- function getTextDirection(locale) {
4116
- const primary = locale.split("-")[0]?.toLowerCase() || "";
4117
- return RTL_LANGUAGES.has(primary) ? "rtl" : "ltr";
4118
- }
4119
- /**
4120
- * A language's name written in that language, for language selectors:
4121
- * "ja" -> "日本語", "zh-Hant" -> "繁體中文", "es" -> "Español". Labels that
4122
- * are not valid locale codes (e.g. "English") are returned unchanged.
4123
- */
4124
- function getLanguageName(language) {
4125
- if (!isValidLocale(language)) return language;
4126
- const locale = Intl.getCanonicalLocales(language)[0];
4127
- try {
4128
- const name = new Intl.DisplayNames([locale], {
4129
- type: "language",
4130
- fallback: "none"
4131
- }).of(locale);
4132
- if (!name) return language;
4133
- return name.charAt(0).toLocaleUpperCase(locale) + name.slice(1);
4134
- } catch {
4135
- return language;
4136
- }
4137
- }
4138
-
4139
4080
  //#endregion
4140
4081
  //#region src/lib/content.ts
4141
4082
  /**
@@ -4243,36 +4184,6 @@ function resolveSearchConfig(config) {
4243
4184
 
4244
4185
  //#endregion
4245
4186
  //#region src/lib/site-model.ts
4246
- const SHISO_THEME_LABELS = {
4247
- menu: "Menu",
4248
- documentationNavigation: "Documentation navigation",
4249
- sections: "Sections",
4250
- tableOfContents: "On this page",
4251
- tableOfContentsNavigation: "Table of contents",
4252
- searchTitle: "Search",
4253
- searching: "Searching...",
4254
- searchUnavailable: "Search unavailable",
4255
- noResults: "No results",
4256
- lastUpdated: "Last updated on",
4257
- relatedTopics: "Related topics",
4258
- previousPage: "Previous",
4259
- nextPage: "Next",
4260
- notFound: "Page not found",
4261
- dismissBanner: "Dismiss banner",
4262
- toggleTheme: "Toggle theme",
4263
- moreOptions: "More options",
4264
- copied: "Copied",
4265
- expand: "Expand",
4266
- collapse: "Collapse",
4267
- copyPage: "Copy page",
4268
- copyPageDescription: "Copy this page as Markdown",
4269
- viewMarkdown: "View as Markdown",
4270
- viewMarkdownDescription: "Open this page as plain Markdown",
4271
- openInChatGPT: "Open in ChatGPT",
4272
- openInClaude: "Open in Claude",
4273
- openInPerplexity: "Open in Perplexity",
4274
- askQuestionsAboutPage: "Ask questions about this page"
4275
- };
4276
4187
  function isInternalHref(href) {
4277
4188
  return /^(?:#|\/|\.\.?\/)/.test(href);
4278
4189
  }
@@ -4353,14 +4264,14 @@ function resolveSiteModel(config, docs, shiso) {
4353
4264
  showTimestamp: config.metadata?.timestamp === true,
4354
4265
  drilldown: config.interaction?.drilldown,
4355
4266
  locale: shiso?.locale || "en-US",
4356
- labels: SHISO_THEME_LABELS,
4267
+ labels: resolveLabels(shiso?.locale || "en-US", shiso?.translations),
4357
4268
  docs
4358
4269
  };
4359
4270
  }
4360
4271
  function aiPrompt(mdUrl) {
4361
4272
  return `Read ${mdUrl} so I can ask questions about it.`;
4362
4273
  }
4363
- function resolveContextualOptions(options, page, labels = SHISO_THEME_LABELS) {
4274
+ function resolveContextualOptions(options, page, labels = englishLabels) {
4364
4275
  const mdHref = `${toHref(page.url)}.md`;
4365
4276
  const absolutePageUrl = toAbsoluteUrl(page.url);
4366
4277
  const mdUrl = absolutePageUrl ? `${absolutePageUrl}.md` : void 0;
@@ -4463,10 +4374,15 @@ function normalizeStandalonePages(config, resolvePageFile, site, options = {}) {
4463
4374
  const fileSlug = normalizePageSlug(item?.page);
4464
4375
  const filePath = resolvePageFile(fileSlug);
4465
4376
  if (!filePath) throw new Error(`Missing standalone page file for "${fileSlug}": expected "content/pages/${fileSlug}.tsx", ".mdx", or ".md".`);
4377
+ const language = item?.language?.trim() || void 0;
4378
+ if (language && !site.scopes.some((scope) => scope.language === language)) throw invalid(`standalone page "${path}" uses language "${language}", which is not declared in navigation.languages.`);
4379
+ const key = language && fileSlug.startsWith(`${language}/`) ? fileSlug.slice(language.length + 1) : fileSlug;
4466
4380
  pages.push({
4467
4381
  path,
4468
4382
  filePath,
4469
- title: item?.title?.trim() || void 0
4383
+ title: item?.title?.trim() || void 0,
4384
+ language,
4385
+ key
4470
4386
  });
4471
4387
  }
4472
4388
  return pages;
@@ -4499,10 +4415,38 @@ const hasRootStandalonePage = standalonePages.some((page) => page.path === "/");
4499
4415
  function getStandalonePage(pathname) {
4500
4416
  return getStandalonePageByPathname(standalonePages, stripBase(pathname));
4501
4417
  }
4502
- /** Scope that owns the current pathname; the default scope for unknown paths. */
4418
+ /** Landing scope of a language: its default version. */
4419
+ function getLanguageScope(language) {
4420
+ return docsSite.scopes.find((scope) => scope.language === language && scope.isLanguageDefault);
4421
+ }
4422
+ /**
4423
+ * Scope that owns the current pathname. A standalone page tagged with a
4424
+ * `language` belongs to that language's landing scope; unknown paths and
4425
+ * untagged standalone pages belong to the default scope.
4426
+ */
4503
4427
  function getScopeByPathname(pathname) {
4504
4428
  const page = getPageByPathname(pathname);
4505
- return page ? getScopeForPage(docsSite, page) : getDefaultScope(docsSite);
4429
+ if (page) return getScopeForPage(docsSite, page);
4430
+ const standalone = getStandalonePage(pathname);
4431
+ return (standalone?.language ? getLanguageScope(standalone.language) : void 0) || getDefaultScope(docsSite);
4432
+ }
4433
+ /**
4434
+ * The same standalone page in another language, matched by `key`. Untagged
4435
+ * pages count as the default scope's language.
4436
+ */
4437
+ function getStandaloneCounterpart(page, language) {
4438
+ const defaultLanguage = getDefaultScope(docsSite).language;
4439
+ return standalonePages.find((candidate) => candidate.key === page.key && (candidate.language || defaultLanguage) === language) || null;
4440
+ }
4441
+ /**
4442
+ * Home link for the current pathname: the "/" standalone page in the current
4443
+ * language when one exists, else "/", else the docs home when nothing owns "/".
4444
+ */
4445
+ function getHomeHref(pathname) {
4446
+ const root = standalonePages.find((page) => page.path === "/");
4447
+ if (!root) return docsHomeUrl;
4448
+ const language = getScopeByPathname(pathname).language;
4449
+ return language && getStandaloneCounterpart(root, language)?.path || "/";
4506
4450
  }
4507
4451
  /** Document language and direction for a pathname, from its scope's language. */
4508
4452
  function getLocaleByPathname(pathname) {
@@ -4512,6 +4456,20 @@ function getLocaleByPathname(pathname) {
4512
4456
  dir: getTextDirection(lang)
4513
4457
  };
4514
4458
  }
4459
+ /** Resolve UI text on every route, including standalone pages and language switches. */
4460
+ function getSiteModelByPathname(pathname) {
4461
+ const { lang } = getLocaleByPathname(pathname);
4462
+ const labels = resolveLabels(lang, shiso.translations);
4463
+ const customPrompt = typeof siteConfig.search === "object" ? siteConfig.search.prompt?.trim() : void 0;
4464
+ return {
4465
+ ...siteModel,
4466
+ labels,
4467
+ search: {
4468
+ ...siteModel.search,
4469
+ prompt: customPrompt || labels.searchPlaceholder
4470
+ }
4471
+ };
4472
+ }
4515
4473
  const siteName = siteModel.name;
4516
4474
  /** Trailing-slash-insensitive route key for redirect matching. */
4517
4475
  function toRouteKey(routePath) {
@@ -4565,8 +4523,10 @@ function getPageTitle(pageTitle) {
4565
4523
  //#region src/components/LanguageSwitcher.tsx
4566
4524
  /**
4567
4525
  * Language selector for multi-language sites. Each option is a language's
4568
- * landing scope — its default version — so switching languages always lands
4569
- * on that language's default-version first page. Hidden languages never
4526
+ * landing scope — its default version — so switching languages lands on that
4527
+ * language's default-version first page. On a standalone page (e.g. a home
4528
+ * page) it lands on the same page in the chosen language when one exists.
4529
+ * Hidden languages never
4570
4530
  * appear as options. Each language is shown by its native name, e.g. "ja"
4571
4531
  * as "日本語".
4572
4532
  */
@@ -4575,6 +4535,7 @@ function LanguageSwitcher() {
4575
4535
  const navigate = useNavigate();
4576
4536
  const current = getScopeByPathname(pathname);
4577
4537
  const options = getLanguageScopes(docsSite);
4538
+ const standalone = getStandalonePage(pathname);
4578
4539
  if (!current.language || options.length < 2 && !current.hidden) return null;
4579
4540
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
4580
4541
  render: /* @__PURE__ */ jsx(Button, {
@@ -4587,7 +4548,10 @@ function LanguageSwitcher() {
4587
4548
  className: "min-w-32",
4588
4549
  children: options.map((scope) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
4589
4550
  onClick: () => {
4590
- if (scope.language !== current.language) navigate(scope.firstPageUrl);
4551
+ if (scope.language !== current.language) {
4552
+ const counterpart = standalone && scope.language ? getStandaloneCounterpart(standalone, scope.language) : null;
4553
+ navigate(counterpart?.path || scope.firstPageUrl);
4554
+ }
4591
4555
  },
4592
4556
  children: [/* @__PURE__ */ jsx("span", {
4593
4557
  className: "grow",
@@ -7749,7 +7713,7 @@ function Header({ site }) {
7749
7713
  const { logo, navbar, name, appearance, labels } = site;
7750
7714
  const { pathname } = useLocation();
7751
7715
  const docs = getScopeByPathname(pathname).docs;
7752
- const brandHref = logo?.href || (hasRootStandalonePage ? "/" : docsHomeUrl);
7716
+ const brandHref = logo?.href || getHomeHref(pathname);
7753
7717
  const hasBrand = !!name || !!logo?.light || !!logo?.dark;
7754
7718
  const brandClassName = "inline-flex items-center gap-2 text-xl font-bold text-foreground tracking-[-0.03em]";
7755
7719
  const brandContent = /* @__PURE__ */ jsxs(Fragment$1, { children: [logo?.invert && logo.light ? /* @__PURE__ */ jsx("img", {
@@ -8132,23 +8096,23 @@ function getOperation(key) {
8132
8096
  return OPENAPI_OPERATIONS[`${method.toUpperCase()} ${rest.join(" ")}`];
8133
8097
  }
8134
8098
  /** Parameter groups shared by the renderer and table of contents. */
8135
- function operationParameterSections(operation) {
8099
+ function operationParameterSections(operation, labels = englishLabels) {
8136
8100
  return [
8137
8101
  {
8138
8102
  location: "header",
8139
- name: "Headers"
8103
+ name: labels.apiHeaders
8140
8104
  },
8141
8105
  {
8142
8106
  location: "path",
8143
- name: "Path parameters"
8107
+ name: labels.apiPathParameters
8144
8108
  },
8145
8109
  {
8146
8110
  location: "query",
8147
- name: "Query parameters"
8111
+ name: labels.apiQueryParameters
8148
8112
  },
8149
8113
  {
8150
8114
  location: "cookie",
8151
- name: "Cookie parameters"
8115
+ name: labels.apiCookieParameters
8152
8116
  }
8153
8117
  ].filter(({ location }) => operation.parameters[location].length > 0 || location === "header" && operation.security.length > 0);
8154
8118
  }
@@ -8157,15 +8121,22 @@ function operationParameterSections(operation) {
8157
8121
  * truth for section ids: the component, the table of contents, the content
8158
8122
  * checker, and the search indexer all derive their anchors from these labels.
8159
8123
  */
8160
- function operationSections(operation) {
8124
+ function operationSections(operation, labels = englishLabels) {
8161
8125
  const slugger = createSlugger();
8162
- return [
8126
+ const names = [
8163
8127
  ...operationParameterSections(operation).map((section) => section.name),
8164
8128
  operation.requestBody ? "Request body" : void 0,
8165
8129
  operation.responses.length ? "Responses" : void 0,
8166
8130
  operation.samples.length ? "Code samples" : void 0
8167
- ].filter((name) => Boolean(name)).map((name) => ({
8168
- name,
8131
+ ].filter((name) => Boolean(name));
8132
+ const translated = [
8133
+ ...operationParameterSections(operation, labels).map((section) => section.name),
8134
+ ...operation.requestBody ? [labels.apiRequestBody] : [],
8135
+ ...operation.responses.length ? [labels.apiResponses] : [],
8136
+ ...operation.samples.length ? [labels.apiCodeSamples] : []
8137
+ ];
8138
+ return names.map((name, index) => ({
8139
+ name: translated[index],
8169
8140
  id: slugger.slug(name),
8170
8141
  size: 2
8171
8142
  }));
@@ -8174,30 +8145,32 @@ function operationSections(operation) {
8174
8145
  //#endregion
8175
8146
  //#region src/components/OpenApiOperation.tsx
8176
8147
  function FieldChildren({ node }) {
8148
+ const labels = useLabels();
8177
8149
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [node.description, node.enum && node.enum.length > 0 && /* @__PURE__ */ jsxs("div", {
8178
8150
  className: "mt-1",
8179
8151
  children: [
8180
- "Options:",
8152
+ labels.fieldOptions,
8181
8153
  " ",
8182
8154
  node.enum.map((value, index) => /* @__PURE__ */ jsxs("span", { children: [index > 0 && ", ", /* @__PURE__ */ jsx("code", { children: value })] }, value))
8183
8155
  ]
8184
8156
  })] });
8185
8157
  }
8186
- function schemaDetails(node) {
8158
+ function schemaDetails(node, labels) {
8187
8159
  if (!node.children?.length) return void 0;
8188
8160
  return /* @__PURE__ */ jsx(Expandable, {
8189
- title: node.type === "oneOf" || node.type === "anyOf" ? "Allowed types" : "properties",
8161
+ title: node.type === "oneOf" || node.type === "anyOf" ? labels.allowedTypes : labels.properties,
8190
8162
  children: /* @__PURE__ */ jsx(SchemaTable, { nodes: node.children })
8191
8163
  });
8192
8164
  }
8193
8165
  function SchemaTable({ nodes }) {
8166
+ const labels = useLabels();
8194
8167
  return /* @__PURE__ */ jsx(PropertiesTable, { children: nodes.map((node) => /* @__PURE__ */ jsx(PropertiesTable.Row, {
8195
8168
  name: node.name || node.type,
8196
8169
  type: node.type,
8197
8170
  required: node.required,
8198
8171
  deprecated: node.deprecated,
8199
8172
  default: node.default,
8200
- details: schemaDetails(node),
8173
+ details: schemaDetails(node, labels),
8201
8174
  children: /* @__PURE__ */ jsx(FieldChildren, { node })
8202
8175
  }, node.name || node.type)) });
8203
8176
  }
@@ -8222,19 +8195,22 @@ function HighlightedCode({ language, title, html, source, lineCount }) {
8222
8195
  }
8223
8196
  /** The generated reference for one API operation, rendered under the page body. */
8224
8197
  function OpenApiOperation({ operation }) {
8225
- const sections = new Map(operationSections(operation).map((entry) => [entry.name, entry.id]));
8198
+ const labels = useLabels();
8199
+ const sectionEntries = operationSections(operation);
8200
+ const sections = new Map(sectionEntries.map((entry) => [entry.name, entry.id]));
8226
8201
  return /* @__PURE__ */ jsxs("div", {
8227
8202
  className: "docs-markdown",
8228
8203
  children: [
8229
- operationParameterSections(operation).map(({ location, name }) => /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", {
8230
- id: sections.get(name),
8204
+ operationParameterSections(operation, labels).map(({ location, name }, index) => /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", {
8205
+ id: sectionEntries[index].id,
8231
8206
  children: name
8232
8207
  }), /* @__PURE__ */ jsxs(PropertiesTable, { children: [location === "header" && operation.security.length > 0 && /* @__PURE__ */ jsxs(PropertiesTable.Row, {
8233
8208
  name: "Authorization",
8234
8209
  type: "string",
8235
8210
  required: true,
8236
8211
  children: [
8237
- "Authentication credentials, e.g. ",
8212
+ labels.apiCredentials,
8213
+ " ",
8238
8214
  /* @__PURE__ */ jsx("code", { children: "Bearer <token>" }),
8239
8215
  "."
8240
8216
  ]
@@ -8244,25 +8220,25 @@ function OpenApiOperation({ operation }) {
8244
8220
  required: parameter.required,
8245
8221
  deprecated: parameter.deprecated,
8246
8222
  default: parameter.default,
8247
- details: schemaDetails(parameter),
8223
+ details: schemaDetails(parameter, labels),
8248
8224
  children: /* @__PURE__ */ jsx(FieldChildren, { node: parameter })
8249
8225
  }, parameter.name))] })] }, location)),
8250
8226
  operation.requestBody && /* @__PURE__ */ jsxs("section", { children: [
8251
8227
  /* @__PURE__ */ jsx("h2", {
8252
8228
  id: sections.get("Request body"),
8253
- children: "Request body"
8229
+ children: labels.apiRequestBody
8254
8230
  }),
8255
8231
  /* @__PURE__ */ jsx(SchemaFields, { node: operation.requestBody.schema }),
8256
8232
  operation.requestBody.example && /* @__PURE__ */ jsx(HighlightedCode, {
8257
8233
  language: "json",
8258
- title: "Example request",
8234
+ title: labels.apiExampleRequest,
8259
8235
  html: operation.requestBody.exampleHtml,
8260
8236
  source: operation.requestBody.example
8261
8237
  })
8262
8238
  ] }),
8263
8239
  operation.responses.length > 0 && /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", {
8264
8240
  id: sections.get("Responses"),
8265
- children: "Responses"
8241
+ children: labels.apiResponses
8266
8242
  }), operation.responses.map((response) => /* @__PURE__ */ jsxs("div", {
8267
8243
  className: "mt-6 first:mt-0",
8268
8244
  children: [
@@ -8280,7 +8256,7 @@ function OpenApiOperation({ operation }) {
8280
8256
  response.schema && /* @__PURE__ */ jsx(SchemaFields, { node: response.schema }),
8281
8257
  response.example && /* @__PURE__ */ jsx(HighlightedCode, {
8282
8258
  language: "json",
8283
- title: `${response.status} example`,
8259
+ title: labels.apiExampleResponse.replace("{status}", () => response.status),
8284
8260
  html: response.exampleHtml,
8285
8261
  source: response.example
8286
8262
  })
@@ -8288,7 +8264,7 @@ function OpenApiOperation({ operation }) {
8288
8264
  }, response.status))] }),
8289
8265
  operation.samples.length > 0 && /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", {
8290
8266
  id: sections.get("Code samples"),
8291
- children: "Code samples"
8267
+ children: labels.apiCodeSamples
8292
8268
  }), /* @__PURE__ */ jsx(CodeGroup, { children: operation.samples.map((sample) => /* @__PURE__ */ jsx(HighlightedCode, {
8293
8269
  language: sample.language,
8294
8270
  title: sample.label,
@@ -8360,7 +8336,7 @@ function PageActions({ page, frontmatter, site, lastUpdated }) {
8360
8336
  target: "_blank",
8361
8337
  rel: "noopener noreferrer",
8362
8338
  className: "ml-auto inline-flex shrink-0 items-center gap-1.5 text-right no-underline hover:text-primary",
8363
- children: [site.editLink?.label || "Edit this page", /* @__PURE__ */ jsx(ExternalLink, {
8339
+ children: [site.editLink?.label || site.labels.editPage, /* @__PURE__ */ jsx(ExternalLink, {
8364
8340
  size: 14,
8365
8341
  "aria-hidden": "true"
8366
8342
  })]
@@ -8370,24 +8346,24 @@ function PageActions({ page, frontmatter, site, lastUpdated }) {
8370
8346
  "aria-busy": status === "pending",
8371
8347
  "data-pagefind-ignore": true,
8372
8348
  children: [/* @__PURE__ */ jsxs("fieldset", {
8373
- "aria-label": feedback.prompt || "Was this page helpful?",
8349
+ "aria-label": feedback.prompt || site.labels.feedbackPrompt,
8374
8350
  className: "flex flex-wrap items-center gap-2",
8375
8351
  children: [/* @__PURE__ */ jsx("span", {
8376
8352
  className: "mr-2 text-muted-foreground",
8377
- children: feedback.prompt || "Was this page helpful?"
8353
+ children: feedback.prompt || site.labels.feedbackPrompt
8378
8354
  }), [true, false].map((helpful) => /* @__PURE__ */ jsx("button", {
8379
8355
  type: "button",
8380
8356
  "aria-pressed": rating === helpful,
8381
8357
  disabled: status === "pending" || status === "success",
8382
8358
  onClick: () => void submit(helpful),
8383
8359
  className: "rounded-md border border-border px-3 py-1.5 text-foreground hover:bg-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-default disabled:opacity-60 aria-pressed:border-primary aria-pressed:text-primary",
8384
- children: helpful ? feedback.helpfulLabel || "Yes" : feedback.unhelpfulLabel || "No"
8360
+ children: helpful ? feedback.helpfulLabel || site.labels.feedbackYes : feedback.unhelpfulLabel || site.labels.feedbackNo
8385
8361
  }, String(helpful)))]
8386
8362
  }), /* @__PURE__ */ jsxs("div", {
8387
8363
  role: "status",
8388
8364
  "aria-live": "polite",
8389
8365
  className: "text-muted-foreground",
8390
- children: [status === "success" && (feedback.successMessage || "Thanks for your feedback!"), status === "error" && (feedback.errorMessage || "Could not send feedback. Please try again.")]
8366
+ children: [status === "success" && (feedback.successMessage || site.labels.feedbackSuccess), status === "error" && (feedback.errorMessage || site.labels.feedbackError)]
8391
8367
  })]
8392
8368
  })] });
8393
8369
  }
@@ -8580,6 +8556,7 @@ const NavigationButton = ({ label, url, eyebrow, isPrev }) => {
8580
8556
  //#endregion
8581
8557
  //#region src/components/Footer.tsx
8582
8558
  function Footer({ footer, className = "" }) {
8559
+ const labels = useLabels();
8583
8560
  if (!footer) return null;
8584
8561
  const { socials, links: columns, attribution } = footer;
8585
8562
  return /* @__PURE__ */ jsxs("footer", {
@@ -8604,10 +8581,14 @@ function Footer({ footer, className = "" }) {
8604
8581
  children: [attribution ? /* @__PURE__ */ jsxs("a", {
8605
8582
  href: "https://shiso.umami.is?ref=docs-footer",
8606
8583
  className: "text-sm hover:text-foreground",
8607
- children: ["Powered by ", /* @__PURE__ */ jsx("span", {
8608
- className: "font-bold",
8609
- children: "shiso"
8610
- })]
8584
+ children: [
8585
+ labels.poweredBy,
8586
+ " ",
8587
+ /* @__PURE__ */ jsx("span", {
8588
+ className: "font-bold",
8589
+ children: "shiso"
8590
+ })
8591
+ ]
8611
8592
  }) : /* @__PURE__ */ jsx("span", {}), socials.length > 0 && /* @__PURE__ */ jsx("div", {
8612
8593
  className: "flex items-center gap-1",
8613
8594
  children: socials.map((link) => {
@@ -8911,6 +8892,7 @@ function SheetOverlay({ className, ...props }) {
8911
8892
  });
8912
8893
  }
8913
8894
  function SheetContent({ className, children, side = "right", showCloseButton = true, ...props }) {
8895
+ const labels = useLabels();
8914
8896
  return /* @__PURE__ */ jsxs(SheetPortal, { children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(DialogPopup, {
8915
8897
  "data-slot": "sheet-content",
8916
8898
  "data-side": side,
@@ -8925,7 +8907,7 @@ function SheetContent({ className, children, side = "right", showCloseButton = t
8925
8907
  }),
8926
8908
  children: [/* @__PURE__ */ jsx(X$1, {}), /* @__PURE__ */ jsx("span", {
8927
8909
  className: "sr-only",
8928
- children: "Close"
8910
+ children: labels.close
8929
8911
  })]
8930
8912
  })]
8931
8913
  })] });
@@ -8966,7 +8948,7 @@ function Docs({ page, doc, site }) {
8966
8948
  }), /* @__PURE__ */ jsx(Footer, { footer: site.footer })]
8967
8949
  });
8968
8950
  const operation = getOperation(doc.frontmatter?.openapi);
8969
- const toc = operation ? [...doc.toc || [], ...operationSections(operation)] : doc.toc;
8951
+ const toc = operation ? [...doc.toc || [], ...operationSections(operation, site.labels)] : doc.toc;
8970
8952
  return /* @__PURE__ */ jsx(PanelProvider, { children: /* @__PURE__ */ jsx(DocsBody, {
8971
8953
  page,
8972
8954
  doc,
@@ -9138,32 +9120,37 @@ const mdxComponents = {
9138
9120
  pre: CodeBlock
9139
9121
  };
9140
9122
  function App() {
9141
- return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(MDXProvider, {
9142
- components: mdxComponents,
9143
- children: /* @__PURE__ */ jsx(Layout, {
9144
- site: siteModel,
9145
- children: /* @__PURE__ */ jsxs(Routes, { children: [
9146
- standalonePages.map((page) => /* @__PURE__ */ jsx(Route, {
9147
- path: page.path,
9148
- element: /* @__PURE__ */ jsx(StandalonePageView, {
9149
- page,
9150
- site: siteModel
9151
- })
9152
- }, page.path)),
9153
- docsHomeUrl !== "/" && !hasRootStandalonePage ? /* @__PURE__ */ jsx(Route, {
9154
- path: "/",
9155
- element: /* @__PURE__ */ jsx(Navigate, {
9156
- to: docsHomeUrl,
9157
- replace: true
9123
+ const { pathname } = useLocation();
9124
+ const siteModel = getSiteModelByPathname(pathname);
9125
+ return /* @__PURE__ */ jsx(LabelContext.Provider, {
9126
+ value: siteModel.labels,
9127
+ children: /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(MDXProvider, {
9128
+ components: mdxComponents,
9129
+ children: /* @__PURE__ */ jsx(Layout, {
9130
+ site: siteModel,
9131
+ children: /* @__PURE__ */ jsxs(Routes, { children: [
9132
+ standalonePages.map((page) => /* @__PURE__ */ jsx(Route, {
9133
+ path: page.path,
9134
+ element: /* @__PURE__ */ jsx(StandalonePageView, {
9135
+ page,
9136
+ site: siteModel
9137
+ })
9138
+ }, page.path)),
9139
+ docsHomeUrl !== "/" && !hasRootStandalonePage ? /* @__PURE__ */ jsx(Route, {
9140
+ path: "/",
9141
+ element: /* @__PURE__ */ jsx(Navigate, {
9142
+ to: docsHomeUrl,
9143
+ replace: true
9144
+ })
9145
+ }) : null,
9146
+ /* @__PURE__ */ jsx(Route, {
9147
+ path: "*",
9148
+ element: /* @__PURE__ */ jsx(DocPage, { site: siteModel })
9158
9149
  })
9159
- }) : null,
9160
- /* @__PURE__ */ jsx(Route, {
9161
- path: "*",
9162
- element: /* @__PURE__ */ jsx(DocPage, { site: siteModel })
9163
- })
9164
- ] })
9165
- })
9166
- }) });
9150
+ ] })
9151
+ })
9152
+ }) })
9153
+ });
9167
9154
  }
9168
9155
 
9169
9156
  //#endregion
@@ -1,4 +1,4 @@
1
- import { Ar as __commonJSMin, jr as __toESM } from "./docs.js";
1
+ import { Rr as __commonJSMin, zr as __toESM } from "./docs.js";
2
2
  import { n as parse } from "./mermaid-parser.core.js";
3
3
  import { n as __name } from "./chunk-Y2CYZVJY.js";
4
4
  import { m as log, p as select_default } from "./src.js";
@@ -1,4 +1,4 @@
1
- import { Ar as __commonJSMin, jr as __toESM } from "./docs.js";
1
+ import { Rr as __commonJSMin, zr as __toESM } from "./docs.js";
2
2
  import { n as __name } from "./chunk-Y2CYZVJY.js";
3
3
  import { m as log, p as select_default } from "./src.js";
4
4
  import { A as hasKatex, F as renderKatexSanitized, b as getConfig, s as common_default, z as sanitizeText } from "./chunk-DU6HZSFF.js";
@@ -1,4 +1,4 @@
1
- import { Ar as __commonJSMin, jr as __toESM } from "./docs.js";
1
+ import { Rr as __commonJSMin, zr as __toESM } from "./docs.js";
2
2
  import { n as __name } from "./chunk-Y2CYZVJY.js";
3
3
  import { m as log, p as select_default } from "./src.js";
4
4
  import { t as cytoscape$1 } from "./cytoscape.esm.js";
@@ -1,4 +1,4 @@
1
- import { Ar as __commonJSMin } from "./docs.js";
1
+ import { Rr as __commonJSMin } from "./docs.js";
2
2
 
3
3
  //#region ../../node_modules/.pnpm/d3-shape@3.2.0/node_modules/d3-shape/src/math.js
4
4
  const abs = Math.abs;