@f5-sales-demo/docs-theme 3.9.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/LICENSE +21 -0
- package/README.md +36 -0
- package/assets/f5-distributed-cloud.svg +1 -0
- package/assets/f5-logo.svg +1 -0
- package/assets/github-avatar.png +0 -0
- package/astro.config.mjs +3 -0
- package/bin/translate.mjs +113 -0
- package/components/Banner.astro +51 -0
- package/components/EditLink.astro +3 -0
- package/components/Footer.astro +47 -0
- package/components/Icon.astro +100 -0
- package/components/LinkCard.astro +110 -0
- package/components/MarkdownContent.astro +7 -0
- package/components/Screenshot.astro +31 -0
- package/components/SiteTitle.astro +56 -0
- package/config.ts +816 -0
- package/fonts/font-face.css +79 -0
- package/fonts/neusaNextProWide-300.woff2 +0 -0
- package/fonts/neusaNextProWide-400.woff2 +0 -0
- package/fonts/neusaNextProWide-400i.woff2 +0 -0
- package/fonts/neusaNextProWide-500.woff2 +0 -0
- package/fonts/neusaNextProWide-700.woff2 +0 -0
- package/fonts/neusaNextProWide-700i.woff2 +0 -0
- package/fonts/proximaNova-400.woff2 +0 -0
- package/fonts/proximaNova-500.woff2 +0 -0
- package/fonts/proximaNova-600.woff2 +0 -0
- package/fonts/proximaNova-700.woff2 +0 -0
- package/index.ts +36 -0
- package/package.json +135 -0
- package/route-middleware.ts +73 -0
- package/src/content.config.ts +10 -0
- package/src/i18n/glossary.ts +18 -0
- package/src/i18n/locales.test.ts +56 -0
- package/src/i18n/locales.ts +7 -0
- package/src/i18n/mega-menu-translations.ts +1363 -0
- package/src/i18n/prompt.ts +30 -0
- package/src/i18n/translations.ts +733 -0
- package/src/i18n/translator.ts +120 -0
- package/src/plugins/remark-mermaid.mjs +24 -0
- package/src/types/icon.ts +6 -0
- package/src/utils/localize-ecosystem-href.test.ts +65 -0
- package/src/utils/localize-ecosystem-href.ts +34 -0
- package/src/utils/resolve-icon.ts +70 -0
- package/src/utils/subcategory-sidebar.test.ts +25 -0
- package/src/utils/subcategory-sidebar.ts +316 -0
- package/styles/custom.css +807 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: neusaNextProWide;
|
|
3
|
+
font-weight: 300;
|
|
4
|
+
font-style: normal;
|
|
5
|
+
font-display: swap;
|
|
6
|
+
src: url("./neusaNextProWide-300.woff2") format("woff2");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: neusaNextProWide;
|
|
11
|
+
font-weight: 400;
|
|
12
|
+
font-style: normal;
|
|
13
|
+
font-display: swap;
|
|
14
|
+
src: url("./neusaNextProWide-400.woff2") format("woff2");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: neusaNextProWide;
|
|
19
|
+
font-weight: 500;
|
|
20
|
+
font-style: normal;
|
|
21
|
+
font-display: swap;
|
|
22
|
+
src: url("./neusaNextProWide-500.woff2") format("woff2");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@font-face {
|
|
26
|
+
font-family: neusaNextProWide;
|
|
27
|
+
font-weight: 700;
|
|
28
|
+
font-style: normal;
|
|
29
|
+
font-display: swap;
|
|
30
|
+
src: url("./neusaNextProWide-700.woff2") format("woff2");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@font-face {
|
|
34
|
+
font-family: neusaNextProWide;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
font-style: italic;
|
|
37
|
+
font-display: swap;
|
|
38
|
+
src: url("./neusaNextProWide-400i.woff2") format("woff2");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@font-face {
|
|
42
|
+
font-family: neusaNextProWide;
|
|
43
|
+
font-weight: 700;
|
|
44
|
+
font-style: italic;
|
|
45
|
+
font-display: swap;
|
|
46
|
+
src: url("./neusaNextProWide-700i.woff2") format("woff2");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@font-face {
|
|
50
|
+
font-family: proximaNova;
|
|
51
|
+
font-weight: 400;
|
|
52
|
+
font-style: normal;
|
|
53
|
+
font-display: swap;
|
|
54
|
+
src: url("./proximaNova-400.woff2") format("woff2");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@font-face {
|
|
58
|
+
font-family: proximaNova;
|
|
59
|
+
font-weight: 500;
|
|
60
|
+
font-style: normal;
|
|
61
|
+
font-display: swap;
|
|
62
|
+
src: url("./proximaNova-500.woff2") format("woff2");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@font-face {
|
|
66
|
+
font-family: proximaNova;
|
|
67
|
+
font-weight: 600;
|
|
68
|
+
font-style: normal;
|
|
69
|
+
font-display: swap;
|
|
70
|
+
src: url("./proximaNova-600.woff2") format("woff2");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@font-face {
|
|
74
|
+
font-family: proximaNova;
|
|
75
|
+
font-weight: 700;
|
|
76
|
+
font-style: normal;
|
|
77
|
+
font-display: swap;
|
|
78
|
+
src: url("./proximaNova-700.woff2") format("woff2");
|
|
79
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StarlightPlugin } from '@astrojs/starlight/types';
|
|
2
|
+
import { translations } from './src/i18n/translations.ts';
|
|
3
|
+
|
|
4
|
+
export default function f5xcDocsTheme(): StarlightPlugin {
|
|
5
|
+
return {
|
|
6
|
+
name: '@f5xc-salesdemos/docs-theme',
|
|
7
|
+
hooks: {
|
|
8
|
+
'i18n:setup'({ injectTranslations }) {
|
|
9
|
+
injectTranslations(translations);
|
|
10
|
+
},
|
|
11
|
+
'config:setup'({ config, updateConfig, addRouteMiddleware, logger }) {
|
|
12
|
+
addRouteMiddleware({
|
|
13
|
+
entrypoint: '@f5xc-salesdemos/docs-theme/route-middleware',
|
|
14
|
+
order: 'pre',
|
|
15
|
+
});
|
|
16
|
+
updateConfig({
|
|
17
|
+
customCss: [
|
|
18
|
+
...(config.customCss ?? []),
|
|
19
|
+
'@f5xc-salesdemos/docs-theme/fonts/font-face.css',
|
|
20
|
+
'@f5xc-salesdemos/docs-theme/styles/custom.css',
|
|
21
|
+
],
|
|
22
|
+
components: {
|
|
23
|
+
...config.components,
|
|
24
|
+
Banner: '@f5xc-salesdemos/docs-theme/components/Banner.astro',
|
|
25
|
+
EditLink: '@f5xc-salesdemos/docs-theme/components/EditLink.astro',
|
|
26
|
+
Footer: '@f5xc-salesdemos/docs-theme/components/Footer.astro',
|
|
27
|
+
SiteTitle: '@f5xc-salesdemos/docs-theme/components/SiteTitle.astro',
|
|
28
|
+
MarkdownContent:
|
|
29
|
+
process.env.DOCS_MARKDOWN_CONTENT || '@f5xc-salesdemos/docs-theme/components/MarkdownContent.astro',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
logger.info('F5 XC docs theme loaded');
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@f5-sales-demo/docs-theme",
|
|
3
|
+
"_scope_migrated": true,
|
|
4
|
+
"version": "3.9.0",
|
|
5
|
+
"description": "F5 Distributed Cloud branded Starlight documentation theme",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"docs-translate": "./bin/translate.mjs"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://f5-sales-demo.github.io/docs-theme",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/f5-sales-demo/docs-theme"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/f5-sales-demo/docs-theme/issues"
|
|
18
|
+
},
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./index.ts",
|
|
21
|
+
"./fonts/font-face.css": "./fonts/font-face.css",
|
|
22
|
+
"./styles/custom.css": "./styles/custom.css",
|
|
23
|
+
"./components/Banner.astro": "./components/Banner.astro",
|
|
24
|
+
"./components/EditLink.astro": "./components/EditLink.astro",
|
|
25
|
+
"./components/Footer.astro": "./components/Footer.astro",
|
|
26
|
+
"./components/SiteTitle.astro": "./components/SiteTitle.astro",
|
|
27
|
+
"./components/MarkdownContent.astro": "./components/MarkdownContent.astro",
|
|
28
|
+
"./assets/f5-logo.svg": "./assets/f5-logo.svg",
|
|
29
|
+
"./assets/github-avatar.png": "./assets/github-avatar.png",
|
|
30
|
+
"./assets/f5-distributed-cloud.svg": "./assets/f5-distributed-cloud.svg",
|
|
31
|
+
"./config": "./config.ts",
|
|
32
|
+
"./route-middleware": "./route-middleware.ts",
|
|
33
|
+
"./src/plugins/remark-mermaid.mjs": "./src/plugins/remark-mermaid.mjs",
|
|
34
|
+
"./components/Icon.astro": "./components/Icon.astro",
|
|
35
|
+
"./components/LinkCard.astro": "./components/LinkCard.astro",
|
|
36
|
+
"./components/Screenshot.astro": "./components/Screenshot.astro",
|
|
37
|
+
"./src/utils/resolve-icon.ts": "./src/utils/resolve-icon.ts",
|
|
38
|
+
"./src/i18n/locales.ts": "./src/i18n/locales.ts",
|
|
39
|
+
"./src/i18n/translator.ts": "./src/i18n/translator.ts",
|
|
40
|
+
"./src/i18n/prompt.ts": "./src/i18n/prompt.ts",
|
|
41
|
+
"./src/utils/localize-ecosystem-href.ts": "./src/utils/localize-ecosystem-href.ts"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"index.ts",
|
|
45
|
+
"config.ts",
|
|
46
|
+
"route-middleware.ts",
|
|
47
|
+
"astro.config.mjs",
|
|
48
|
+
"bin/",
|
|
49
|
+
"fonts/",
|
|
50
|
+
"styles/",
|
|
51
|
+
"assets/",
|
|
52
|
+
"components/",
|
|
53
|
+
"src/"
|
|
54
|
+
],
|
|
55
|
+
"keywords": [
|
|
56
|
+
"starlight",
|
|
57
|
+
"theme",
|
|
58
|
+
"astro",
|
|
59
|
+
"withastro",
|
|
60
|
+
"starlight-theme",
|
|
61
|
+
"f5",
|
|
62
|
+
"f5xc",
|
|
63
|
+
"documentation",
|
|
64
|
+
"docs-theme"
|
|
65
|
+
],
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@playwright/test": "^1.50.0",
|
|
71
|
+
"vitest": "^4.1.9"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"test": "vitest run",
|
|
75
|
+
"test:watch": "vitest",
|
|
76
|
+
"test:visual": "playwright test",
|
|
77
|
+
"test:visual:update": "playwright test --update-snapshots"
|
|
78
|
+
},
|
|
79
|
+
"peerDependencies": {
|
|
80
|
+
"@astrojs/markdown-remark": ">=7.0.0",
|
|
81
|
+
"@astrojs/starlight": ">=0.38.0",
|
|
82
|
+
"@f5-sales-demo/icons-f5-brand": "*",
|
|
83
|
+
"@f5-sales-demo/icons-f5xc": "*",
|
|
84
|
+
"@f5-sales-demo/icons-hashicorp-flight": "*",
|
|
85
|
+
"@iconify-json/carbon": "*",
|
|
86
|
+
"@iconify-json/lucide": "*",
|
|
87
|
+
"@iconify-json/mdi": "*",
|
|
88
|
+
"@iconify-json/ph": "*",
|
|
89
|
+
"@iconify-json/tabler": "*",
|
|
90
|
+
"astro": ">=6.0.0"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"@iconify-json/lucide": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"@iconify-json/carbon": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"@iconify-json/mdi": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"@iconify-json/ph": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"@iconify-json/tabler": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"@f5-sales-demo/icons-f5-brand": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
111
|
+
"@f5-sales-demo/icons-f5xc": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"@f5-sales-demo/icons-hashicorp-flight": {
|
|
115
|
+
"optional": true
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"dependencies": {
|
|
119
|
+
"@anthropic-ai/sdk": "^0.106.0",
|
|
120
|
+
"@astrojs/react": "^6.0.0",
|
|
121
|
+
"@f5-sales-demo/i18n-core": "^1.0.0",
|
|
122
|
+
"@f5-sales-demo/starlight-llms-txt": "1.3.1",
|
|
123
|
+
"@f5-sales-demo/starlight-mega-menu": "^2.0.0",
|
|
124
|
+
"gray-matter": "^4.0.3",
|
|
125
|
+
"remark-code-import": "^1.2.0",
|
|
126
|
+
"starlight-heading-badges": "^0.7.0",
|
|
127
|
+
"starlight-image-zoom": "^0.15.0",
|
|
128
|
+
"starlight-openapi": "^0.25.3",
|
|
129
|
+
"starlight-page-actions": "^0.6.0",
|
|
130
|
+
"starlight-plugin-icons": "^1.1.3",
|
|
131
|
+
"starlight-scroll-to-top": "^1.0.1",
|
|
132
|
+
"starlight-videos": "^0.4.0",
|
|
133
|
+
"unist-util-visit": "^5.0.0"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
2
|
+
import { defineRouteMiddleware } from '@astrojs/starlight/route-data';
|
|
3
|
+
import { itemLabels, menuLabels } from './src/i18n/mega-menu-translations.ts';
|
|
4
|
+
|
|
5
|
+
const titleTranslations: Record<string, Record<string, string>> = { ...menuLabels, ...itemLabels };
|
|
6
|
+
|
|
7
|
+
type SidebarEntry = StarlightRouteData['sidebar'][number];
|
|
8
|
+
|
|
9
|
+
function isIndexPage(filePath: string | undefined): boolean {
|
|
10
|
+
if (!filePath) return false;
|
|
11
|
+
return /(?:^|[\\/])index\.mdx?$/.test(filePath);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function hrefToSlug(href: string): string {
|
|
15
|
+
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
|
16
|
+
let s = href;
|
|
17
|
+
if (base && s.startsWith(base)) s = s.slice(base.length);
|
|
18
|
+
s = s.replace(/^\/+|\/+$/g, '');
|
|
19
|
+
if (s.endsWith('.html')) s = s.slice(0, -5);
|
|
20
|
+
if (s === 'index') s = '';
|
|
21
|
+
return s;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Discover all index pages at build time via Vite glob — no astro:content needed
|
|
25
|
+
const indexPaths = Object.keys(
|
|
26
|
+
import.meta.glob(['/src/content/docs/**/index.md', '/src/content/docs/**/index.mdx'], { eager: false }),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const indexSlugs = new Set<string>(
|
|
30
|
+
indexPaths.map((p) => {
|
|
31
|
+
const relative = p.replace(/^\/src\/content\/docs\//, '').replace(/\/?index\.mdx?$/, '');
|
|
32
|
+
// Strip locale prefix (e.g., "en/guides" → "guides")
|
|
33
|
+
return relative.replace(/^[a-z]{2}(-[a-z]{2,4})?\/?/, '');
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
function filterIndexPages(entries: SidebarEntry[], slugs: Set<string>): SidebarEntry[] {
|
|
38
|
+
return entries.reduce<SidebarEntry[]>((acc, entry) => {
|
|
39
|
+
if (entry.type === 'link') {
|
|
40
|
+
const slug = hrefToSlug(entry.href);
|
|
41
|
+
if (!slugs.has(slug)) {
|
|
42
|
+
acc.push(entry);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
acc.push({
|
|
46
|
+
...entry,
|
|
47
|
+
entries: filterIndexPages(entry.entries, slugs),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return acc;
|
|
51
|
+
}, []);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const onRequest = defineRouteMiddleware(async (context, next) => {
|
|
55
|
+
const route = context.locals.starlightRoute;
|
|
56
|
+
const entry = route.entry;
|
|
57
|
+
|
|
58
|
+
if (isIndexPage(entry.filePath)) {
|
|
59
|
+
// Unconditionally hide TOC on index pages
|
|
60
|
+
route.toc = undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (indexSlugs.size > 0) {
|
|
64
|
+
route.sidebar = filterIndexPages(route.sidebar, indexSlugs);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (route.lang && route.lang !== 'en') {
|
|
68
|
+
const translated = titleTranslations[route.siteTitle]?.[route.lang];
|
|
69
|
+
if (translated) route.siteTitle = translated;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
await next();
|
|
73
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineCollection, z } from 'astro:content';
|
|
2
|
+
import { docsLoader } from '@astrojs/starlight/loaders';
|
|
3
|
+
import { docsSchema } from '@astrojs/starlight/schema';
|
|
4
|
+
|
|
5
|
+
export const collections = {
|
|
6
|
+
docs: defineCollection({
|
|
7
|
+
loader: docsLoader(),
|
|
8
|
+
schema: docsSchema({ extend: z.object({ subcategory: z.string().optional() }) }),
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { categoryTitles, itemLabels, menuLabels } from './mega-menu-translations.ts';
|
|
2
|
+
|
|
3
|
+
const allTerms: Record<string, Record<string, string>> = {
|
|
4
|
+
...menuLabels,
|
|
5
|
+
...categoryTitles,
|
|
6
|
+
...itemLabels,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function getGlossary(localeCode: string): Record<string, string> {
|
|
10
|
+
const result: Record<string, string> = {};
|
|
11
|
+
for (const [english, translations] of Object.entries(allTerms)) {
|
|
12
|
+
const translated = translations[localeCode];
|
|
13
|
+
if (translated && translated !== english) {
|
|
14
|
+
result[english] = translated;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { defaultLocale, f5xcDefaultLocales } from './locales';
|
|
3
|
+
|
|
4
|
+
describe('f5xcDefaultLocales', () => {
|
|
5
|
+
it('contains 13 locales', () => {
|
|
6
|
+
expect(Object.keys(f5xcDefaultLocales)).toHaveLength(13);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('uses slug format for keys', () => {
|
|
10
|
+
for (const key of Object.keys(f5xcDefaultLocales)) {
|
|
11
|
+
expect(key).toMatch(/^[a-z]+(-[a-z]+)?$/);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('has BCP-47 lang property for each locale', () => {
|
|
16
|
+
for (const [_slug, config] of Object.entries(f5xcDefaultLocales)) {
|
|
17
|
+
expect(config.lang).toBeTruthy();
|
|
18
|
+
expect(config.label).toBeTruthy();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('maps pt-br to BCP-47 pt-BR', () => {
|
|
23
|
+
expect(f5xcDefaultLocales['pt-br'].lang).toBe('pt-BR');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('maps zh-cn to BCP-47 zh-CN', () => {
|
|
27
|
+
expect(f5xcDefaultLocales['zh-cn'].lang).toBe('zh-CN');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('maps zh-tw to BCP-47 zh-TW', () => {
|
|
31
|
+
expect(f5xcDefaultLocales['zh-tw'].lang).toBe('zh-TW');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('has RTL dir only for Arabic', () => {
|
|
35
|
+
expect(f5xcDefaultLocales.ar.dir).toBe('rtl');
|
|
36
|
+
expect(f5xcDefaultLocales.en.dir).toBeUndefined();
|
|
37
|
+
expect(f5xcDefaultLocales.fr.dir).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('includes all expected locales', () => {
|
|
41
|
+
const expected = ['en', 'fr', 'es', 'de', 'pt-br', 'ja', 'ko', 'zh-cn', 'zh-tw', 'ar', 'it', 'hi', 'th'];
|
|
42
|
+
for (const slug of expected) {
|
|
43
|
+
expect(f5xcDefaultLocales).toHaveProperty(slug);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('defaultLocale', () => {
|
|
49
|
+
it('is "en"', () => {
|
|
50
|
+
expect(defaultLocale).toBe('en');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('exists in f5xcDefaultLocales', () => {
|
|
54
|
+
expect(f5xcDefaultLocales).toHaveProperty(defaultLocale);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DEFAULT_LOCALE, type StarlightLocaleConfig, toStarlightLocales } from '@f5xc-salesdemos/i18n-core';
|
|
2
|
+
|
|
3
|
+
export type LocaleConfig = StarlightLocaleConfig;
|
|
4
|
+
|
|
5
|
+
export const f5xcDefaultLocales = toStarlightLocales();
|
|
6
|
+
|
|
7
|
+
export const defaultLocale = DEFAULT_LOCALE;
|