@hagicode/hagilight 0.1.2-dev.6.1.f3f7b3d → 0.1.2-dev.7.1.c02207e
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/PromotoBanner.astro +37 -13
- package/logo.png +0 -0
- package/package.json +5 -2
- package/promoto-banner.ts +1 -0
- package/related-sites.json +226 -0
- package/site-links.ts +218 -46
package/PromotoBanner.astro
CHANGED
|
@@ -112,11 +112,15 @@ const { fallback, locale = Astro.currentLocale ?? 'en' } = Astro.props;
|
|
|
112
112
|
|
|
113
113
|
.hagilight-promoto__title,
|
|
114
114
|
.hagilight-promoto__description {
|
|
115
|
+
display: -webkit-box;
|
|
116
|
+
overflow: hidden;
|
|
115
117
|
margin: 0;
|
|
116
118
|
color: var(--sl-color-text-high, #111827);
|
|
117
119
|
font-size: var(--sl-text-sm);
|
|
118
120
|
font-weight: 600;
|
|
119
121
|
line-height: 1.35;
|
|
122
|
+
-webkit-box-orient: vertical;
|
|
123
|
+
-webkit-line-clamp: 2;
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
.hagilight-promoto__description {
|
|
@@ -230,13 +234,14 @@ const { fallback, locale = Astro.currentLocale ?? 'en' } = Astro.props;
|
|
|
230
234
|
}
|
|
231
235
|
|
|
232
236
|
.hagilight-promoto__slide {
|
|
233
|
-
grid-template-columns: minmax(0, 1fr)
|
|
234
|
-
gap: 0.
|
|
235
|
-
padding: 0.
|
|
237
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
238
|
+
gap: 0.5rem;
|
|
239
|
+
padding: 0.65rem 3.25rem 0.65rem 0.75rem;
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
.hagilight-promoto__copy {
|
|
239
|
-
grid-column: 1
|
|
243
|
+
grid-column: 1;
|
|
244
|
+
grid-row: 1 / 3;
|
|
240
245
|
}
|
|
241
246
|
|
|
242
247
|
.hagilight-promoto__title {
|
|
@@ -244,31 +249,50 @@ const { fallback, locale = Astro.currentLocale ?? 'en' } = Astro.props;
|
|
|
244
249
|
}
|
|
245
250
|
|
|
246
251
|
.hagilight-promoto__description {
|
|
247
|
-
display: -webkit-box;
|
|
248
|
-
overflow: hidden;
|
|
249
252
|
font-size: var(--sl-text-xs);
|
|
250
253
|
font-weight: 500;
|
|
251
|
-
-webkit-box-orient: vertical;
|
|
252
|
-
-webkit-line-clamp: 2;
|
|
253
254
|
}
|
|
254
255
|
|
|
255
256
|
.hagilight-promoto__image {
|
|
256
257
|
grid-column: 2;
|
|
257
258
|
grid-row: 1;
|
|
258
|
-
width:
|
|
259
|
+
width: 3rem;
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
.hagilight-promoto__cta {
|
|
262
|
-
grid-column:
|
|
263
|
-
|
|
264
|
-
min-
|
|
263
|
+
grid-column: 2;
|
|
264
|
+
grid-row: 2;
|
|
265
|
+
min-width: 4rem;
|
|
266
|
+
min-height: 1.9rem;
|
|
267
|
+
padding-inline: 0.5rem;
|
|
268
|
+
font-size: var(--sl-text-xs);
|
|
269
|
+
overflow-wrap: anywhere;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.hagilight-promoto__slide[data-has-image='false'] {
|
|
273
|
+
grid-template-rows: auto;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.hagilight-promoto__slide[data-has-image='false'] .hagilight-promoto__copy,
|
|
277
|
+
.hagilight-promoto__slide[data-has-image='false'] .hagilight-promoto__cta {
|
|
278
|
+
grid-row: 1;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.hagilight-promoto__slide[data-has-image='false'] .hagilight-promoto__cta {
|
|
282
|
+
min-width: 4.5rem;
|
|
265
283
|
}
|
|
266
284
|
|
|
267
285
|
.hagilight-promoto__controls {
|
|
268
286
|
justify-content: flex-start;
|
|
269
287
|
flex-wrap: wrap;
|
|
270
288
|
gap: 0.35rem;
|
|
271
|
-
padding: 0 0.
|
|
289
|
+
padding: 0 0.75rem 0.6rem;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.hagilight-promoto__control {
|
|
293
|
+
min-width: 2rem;
|
|
294
|
+
min-height: 2rem;
|
|
295
|
+
padding-inline: 0.5rem;
|
|
272
296
|
}
|
|
273
297
|
}
|
|
274
298
|
|
package/logo.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hagicode/hagilight",
|
|
3
|
-
"version": "0.1.2-dev.
|
|
3
|
+
"version": "0.1.2-dev.7.1.c02207e",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared Astro components for HagiCode sites",
|
|
6
6
|
"repository": {
|
|
@@ -15,13 +15,16 @@
|
|
|
15
15
|
"exports": {
|
|
16
16
|
"./Copyright": "./Copyright.astro",
|
|
17
17
|
"./PromotoBanner": "./PromotoBanner.astro",
|
|
18
|
+
"./logo.png": "./logo.png",
|
|
18
19
|
"./site-links": "./site-links.ts",
|
|
19
20
|
"./GoogleAnalytics": "./GoogleAnalytics.astro",
|
|
20
21
|
"./Analytics51LA": "./Analytics51LA.astro"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"*.astro",
|
|
24
|
-
"*.
|
|
25
|
+
"*.png",
|
|
26
|
+
"*.ts",
|
|
27
|
+
"*.json"
|
|
25
28
|
],
|
|
26
29
|
"peerDependencies": {
|
|
27
30
|
"astro": "^7.3.5"
|
package/promoto-banner.ts
CHANGED
|
@@ -216,6 +216,7 @@ export function definePromotoBannerElement(): void {
|
|
|
216
216
|
this.cards.forEach((card, index) => {
|
|
217
217
|
const slide = document.createElement('article');
|
|
218
218
|
slide.className = 'hagilight-promoto__slide';
|
|
219
|
+
slide.dataset.hasImage = String(Boolean(card.image));
|
|
219
220
|
slide.setAttribute('aria-hidden', index === this.currentIndex ? 'false' : 'true');
|
|
220
221
|
if (index !== this.currentIndex) slide.setAttribute('inert', '');
|
|
221
222
|
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "hagicode-main",
|
|
4
|
+
"name": {
|
|
5
|
+
"zh-CN": "HagiCode 主站",
|
|
6
|
+
"zh-Hant": "HagiCode 主站",
|
|
7
|
+
"en-US": "HagiCode Main Site",
|
|
8
|
+
"ja-JP": "HagiCode 公式サイト",
|
|
9
|
+
"ko-KR": "HagiCode 메인 사이트",
|
|
10
|
+
"de-DE": "HagiCode Hauptseite",
|
|
11
|
+
"fr-FR": "Site principal HagiCode",
|
|
12
|
+
"es-ES": "Sitio principal de HagiCode",
|
|
13
|
+
"pt-BR": "Site principal da HagiCode",
|
|
14
|
+
"ru-RU": "Главный сайт HagiCode"
|
|
15
|
+
},
|
|
16
|
+
"description": {
|
|
17
|
+
"zh-CN": "产品入口",
|
|
18
|
+
"zh-Hant": "產品入口",
|
|
19
|
+
"en-US": "Primary product entry.",
|
|
20
|
+
"ja-JP": "製品全体の入口です。",
|
|
21
|
+
"ko-KR": "제품으로 들어가는 기본 진입점입니다.",
|
|
22
|
+
"de-DE": "Zentraler Einstieg zum Produkt.",
|
|
23
|
+
"fr-FR": "Point d'entrée principal du produit.",
|
|
24
|
+
"es-ES": "Entrada principal al producto.",
|
|
25
|
+
"pt-BR": "Entrada principal do produto.",
|
|
26
|
+
"ru-RU": "Основной вход в продукт."
|
|
27
|
+
},
|
|
28
|
+
"url": "https://www.hagicode.com/"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "newbe-blog",
|
|
32
|
+
"name": {
|
|
33
|
+
"zh-CN": "newbe",
|
|
34
|
+
"zh-Hant": "newbe",
|
|
35
|
+
"en-US": "newbe",
|
|
36
|
+
"ja-JP": "newbe",
|
|
37
|
+
"ko-KR": "newbe",
|
|
38
|
+
"de-DE": "newbe",
|
|
39
|
+
"fr-FR": "newbe",
|
|
40
|
+
"es-ES": "newbe",
|
|
41
|
+
"pt-BR": "newbe",
|
|
42
|
+
"ru-RU": "newbe"
|
|
43
|
+
},
|
|
44
|
+
"description": {
|
|
45
|
+
"zh-CN": "作者博客",
|
|
46
|
+
"zh-Hant": "作者部落格",
|
|
47
|
+
"en-US": "Author blog.",
|
|
48
|
+
"ja-JP": "作者ブログです。",
|
|
49
|
+
"ko-KR": "작성자 블로그입니다.",
|
|
50
|
+
"de-DE": "Blog des Autors.",
|
|
51
|
+
"fr-FR": "Blog de l'auteur.",
|
|
52
|
+
"es-ES": "Blog del autor.",
|
|
53
|
+
"pt-BR": "Blog do autor.",
|
|
54
|
+
"ru-RU": "Блог автора."
|
|
55
|
+
},
|
|
56
|
+
"url": "https://newbe.hagicode.com/"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "index-data",
|
|
60
|
+
"name": {
|
|
61
|
+
"zh-CN": "Index Data Mirror",
|
|
62
|
+
"zh-Hant": "Index Data Mirror",
|
|
63
|
+
"en-US": "Index Data Mirror",
|
|
64
|
+
"ja-JP": "Index Data Mirror",
|
|
65
|
+
"ko-KR": "Index Data Mirror",
|
|
66
|
+
"de-DE": "Index Data Mirror",
|
|
67
|
+
"fr-FR": "Index Data Mirror",
|
|
68
|
+
"es-ES": "Index Data Mirror",
|
|
69
|
+
"pt-BR": "Index Data Mirror",
|
|
70
|
+
"ru-RU": "Index Data Mirror"
|
|
71
|
+
},
|
|
72
|
+
"description": {
|
|
73
|
+
"zh-CN": "公开数据",
|
|
74
|
+
"zh-Hant": "公開資料",
|
|
75
|
+
"en-US": "Public data mirror.",
|
|
76
|
+
"ja-JP": "公開データミラーです。",
|
|
77
|
+
"ko-KR": "공개 데이터 미러입니다.",
|
|
78
|
+
"de-DE": "Öffentlicher Daten-Spiegel.",
|
|
79
|
+
"fr-FR": "Miroir de données public.",
|
|
80
|
+
"es-ES": "Espejo de datos público.",
|
|
81
|
+
"pt-BR": "Espelho público de dados.",
|
|
82
|
+
"ru-RU": "Публичное зеркало данных."
|
|
83
|
+
},
|
|
84
|
+
"url": "https://index.hagicode.com/data/"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "compose-builder",
|
|
88
|
+
"name": {
|
|
89
|
+
"zh-CN": "Docker Compose Builder",
|
|
90
|
+
"zh-Hant": "Docker Compose Builder",
|
|
91
|
+
"en-US": "Docker Compose Builder",
|
|
92
|
+
"ja-JP": "Docker Compose Builder",
|
|
93
|
+
"ko-KR": "Docker Compose Builder",
|
|
94
|
+
"de-DE": "Docker Compose Builder",
|
|
95
|
+
"fr-FR": "Docker Compose Builder",
|
|
96
|
+
"es-ES": "Docker Compose Builder",
|
|
97
|
+
"pt-BR": "Docker Compose Builder",
|
|
98
|
+
"ru-RU": "Docker Compose Builder"
|
|
99
|
+
},
|
|
100
|
+
"description": {
|
|
101
|
+
"zh-CN": "Docker 部署 Hagicode",
|
|
102
|
+
"zh-Hant": "使用 Docker 部署 Hagicode",
|
|
103
|
+
"en-US": "Deploy HagiCode with Docker.",
|
|
104
|
+
"ja-JP": "Docker で HagiCode をデプロイします。",
|
|
105
|
+
"ko-KR": "Docker로 HagiCode를 배포합니다.",
|
|
106
|
+
"de-DE": "HagiCode mit Docker bereitstellen.",
|
|
107
|
+
"fr-FR": "Déployer HagiCode avec Docker.",
|
|
108
|
+
"es-ES": "Despliega HagiCode con Docker.",
|
|
109
|
+
"pt-BR": "Implante a HagiCode com Docker.",
|
|
110
|
+
"ru-RU": "Развёртывание HagiCode через Docker."
|
|
111
|
+
},
|
|
112
|
+
"url": "https://builder.hagicode.com/"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "status-page",
|
|
116
|
+
"name": {
|
|
117
|
+
"zh-CN": "HagiCode Status",
|
|
118
|
+
"zh-Hant": "HagiCode Status",
|
|
119
|
+
"en-US": "HagiCode Status",
|
|
120
|
+
"ja-JP": "HagiCode Status",
|
|
121
|
+
"ko-KR": "HagiCode Status",
|
|
122
|
+
"de-DE": "HagiCode Status",
|
|
123
|
+
"fr-FR": "HagiCode Status",
|
|
124
|
+
"es-ES": "HagiCode Status",
|
|
125
|
+
"pt-BR": "HagiCode Status",
|
|
126
|
+
"ru-RU": "HagiCode Status"
|
|
127
|
+
},
|
|
128
|
+
"description": {
|
|
129
|
+
"zh-CN": "服务状态",
|
|
130
|
+
"zh-Hant": "服務狀態",
|
|
131
|
+
"en-US": "Service status.",
|
|
132
|
+
"ja-JP": "サービス状態の確認ページです。",
|
|
133
|
+
"ko-KR": "서비스 상태를 확인하는 페이지입니다.",
|
|
134
|
+
"de-DE": "Dienststatus.",
|
|
135
|
+
"fr-FR": "État des services.",
|
|
136
|
+
"es-ES": "Estado del servicio.",
|
|
137
|
+
"pt-BR": "Status do serviço.",
|
|
138
|
+
"ru-RU": "Статус сервисов."
|
|
139
|
+
},
|
|
140
|
+
"url": "https://status.hagicode.com/"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "awesome-design-gallery",
|
|
144
|
+
"name": {
|
|
145
|
+
"zh-CN": "Awesome Design MD",
|
|
146
|
+
"zh-Hant": "Awesome Design MD",
|
|
147
|
+
"en-US": "Awesome Design MD",
|
|
148
|
+
"ja-JP": "Awesome Design MD",
|
|
149
|
+
"ko-KR": "Awesome Design MD",
|
|
150
|
+
"de-DE": "Awesome Design MD",
|
|
151
|
+
"fr-FR": "Awesome Design MD",
|
|
152
|
+
"es-ES": "Awesome Design MD",
|
|
153
|
+
"pt-BR": "Awesome Design MD",
|
|
154
|
+
"ru-RU": "Awesome Design MD"
|
|
155
|
+
},
|
|
156
|
+
"description": {
|
|
157
|
+
"zh-CN": "超酷的AI Web 设计",
|
|
158
|
+
"zh-Hant": "超酷的 AI Web 設計",
|
|
159
|
+
"en-US": "A gallery of standout AI web design work.",
|
|
160
|
+
"ja-JP": "印象的な AI Web デザインを集めたギャラリーです。",
|
|
161
|
+
"ko-KR": "인상적인 AI 웹 디자인을 모아 둔 갤러리입니다.",
|
|
162
|
+
"de-DE": "Galerie mit markanten AI-Webdesigns.",
|
|
163
|
+
"fr-FR": "Galerie de designs web IA remarquables.",
|
|
164
|
+
"es-ES": "Galería de diseños web de IA destacados.",
|
|
165
|
+
"pt-BR": "Galeria com designs web de IA de destaque.",
|
|
166
|
+
"ru-RU": "Галерея выразительных AI web-дизайнов."
|
|
167
|
+
},
|
|
168
|
+
"url": "https://design.hagicode.com/"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "soul-builder",
|
|
172
|
+
"name": {
|
|
173
|
+
"zh-CN": "Soul Builder",
|
|
174
|
+
"zh-Hant": "Soul Builder",
|
|
175
|
+
"en-US": "Soul Builder",
|
|
176
|
+
"ja-JP": "Soul Builder",
|
|
177
|
+
"ko-KR": "Soul Builder",
|
|
178
|
+
"de-DE": "Soul Builder",
|
|
179
|
+
"fr-FR": "Soul Builder",
|
|
180
|
+
"es-ES": "Soul Builder",
|
|
181
|
+
"pt-BR": "Soul Builder",
|
|
182
|
+
"ru-RU": "Soul Builder"
|
|
183
|
+
},
|
|
184
|
+
"description": {
|
|
185
|
+
"zh-CN": "Agent之魂",
|
|
186
|
+
"zh-Hant": "Agent 之魂",
|
|
187
|
+
"en-US": "Define the soul of an agent.",
|
|
188
|
+
"ja-JP": "Agent の魂を形にする体験です。",
|
|
189
|
+
"ko-KR": "에이전트의 영혼을 설계하는 경험입니다.",
|
|
190
|
+
"de-DE": "Forme die Seele eines Agenten.",
|
|
191
|
+
"fr-FR": "Façonnez l'âme d'un agent.",
|
|
192
|
+
"es-ES": "Define el alma de un agente.",
|
|
193
|
+
"pt-BR": "Defina a alma de um agente.",
|
|
194
|
+
"ru-RU": "Определите душу агента."
|
|
195
|
+
},
|
|
196
|
+
"url": "https://soul.hagicode.com/"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "trait-builder",
|
|
200
|
+
"name": {
|
|
201
|
+
"zh-CN": "Trait Builder",
|
|
202
|
+
"zh-Hant": "Trait Builder",
|
|
203
|
+
"en-US": "Trait Builder",
|
|
204
|
+
"ja-JP": "Trait Builder",
|
|
205
|
+
"ko-KR": "Trait Builder",
|
|
206
|
+
"de-DE": "Trait Builder",
|
|
207
|
+
"fr-FR": "Trait Builder",
|
|
208
|
+
"es-ES": "Trait Builder",
|
|
209
|
+
"pt-BR": "Trait Builder",
|
|
210
|
+
"ru-RU": "Trait Builder"
|
|
211
|
+
},
|
|
212
|
+
"description": {
|
|
213
|
+
"zh-CN": "Agent之能",
|
|
214
|
+
"zh-Hant": "Agent 之能",
|
|
215
|
+
"en-US": "Shape what an agent can do.",
|
|
216
|
+
"ja-JP": "Agent の能力を組み立てる体験です。",
|
|
217
|
+
"ko-KR": "에이전트의 능력을 설계하는 경험입니다.",
|
|
218
|
+
"de-DE": "Definiere, was ein Agent kann.",
|
|
219
|
+
"fr-FR": "Définissez ce qu'un agent peut faire.",
|
|
220
|
+
"es-ES": "Define lo que un agente puede hacer.",
|
|
221
|
+
"pt-BR": "Defina o que um agente pode fazer.",
|
|
222
|
+
"ru-RU": "Соберите способности агента."
|
|
223
|
+
},
|
|
224
|
+
"url": "https://trait.hagicode.com/"
|
|
225
|
+
}
|
|
226
|
+
]
|
package/site-links.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import docsRelatedSites from './related-sites.json' with { type: 'json' };
|
|
2
|
+
|
|
1
3
|
export type SiteLinkKey =
|
|
2
4
|
| 'home'
|
|
3
5
|
| 'blog'
|
|
@@ -6,20 +8,26 @@ export type SiteLinkKey =
|
|
|
6
8
|
| 'about'
|
|
7
9
|
| 'dockerCompose'
|
|
8
10
|
| 'productDocs'
|
|
11
|
+
| 'blogPosts'
|
|
9
12
|
| 'rss'
|
|
10
13
|
| 'costCalculator'
|
|
11
14
|
| 'github'
|
|
12
15
|
| 'discord'
|
|
16
|
+
| 'issueFeedback'
|
|
17
|
+
| 'contactEmail'
|
|
13
18
|
| 'qqGroup'
|
|
14
|
-
| 'steam'
|
|
19
|
+
| 'steam'
|
|
20
|
+
| 'icpFiling'
|
|
21
|
+
| 'publicSecurityFiling';
|
|
15
22
|
|
|
16
|
-
export type LinkGroup = 'header' | 'quick' | 'community';
|
|
23
|
+
export type LinkGroup = 'header' | 'quick' | 'community' | 'filings';
|
|
17
24
|
type LocalizedText = string | Readonly<Record<string, string>>;
|
|
18
25
|
|
|
19
26
|
export interface SiteLink {
|
|
20
27
|
id: SiteLinkKey | string;
|
|
21
28
|
label: string;
|
|
22
29
|
href: string;
|
|
30
|
+
ariaLabel?: string;
|
|
23
31
|
target?: '_blank';
|
|
24
32
|
rel?: 'noopener noreferrer';
|
|
25
33
|
}
|
|
@@ -54,44 +62,156 @@ interface LinkDefinition {
|
|
|
54
62
|
label: LocalizedText;
|
|
55
63
|
href: string | ((locale: string) => string);
|
|
56
64
|
external?: boolean;
|
|
65
|
+
ariaLabel?: LocalizedText;
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
const translations = {
|
|
60
|
-
home: {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
home: {
|
|
70
|
+
'zh-CN': '首页', 'zh-Hant': '首頁', 'en-US': 'Home', 'ja-JP': 'ホーム',
|
|
71
|
+
'ko-KR': '홈', 'de-DE': 'Startseite', 'fr-FR': 'Accueil', 'es-ES': 'Inicio',
|
|
72
|
+
'pt-BR': 'Início', 'ru-RU': 'Главная',
|
|
73
|
+
},
|
|
74
|
+
blog: {
|
|
75
|
+
'zh-CN': '博客', 'zh-Hant': '部落格', 'en-US': 'Blog', 'ja-JP': 'ブログ',
|
|
76
|
+
'ko-KR': '블로그', 'de-DE': 'Blog', 'fr-FR': 'Blog', 'es-ES': 'Blog',
|
|
77
|
+
'pt-BR': 'Blog', 'ru-RU': 'Блог',
|
|
78
|
+
},
|
|
79
|
+
support: {
|
|
80
|
+
'zh-CN': '获取技术支持', 'zh-Hant': '獲取技術支援', 'en-US': 'Get Support',
|
|
81
|
+
'ja-JP': 'サポート', 'ko-KR': '기술 지원', 'de-DE': 'Support',
|
|
82
|
+
'fr-FR': 'Assistance', 'es-ES': 'Soporte', 'pt-BR': 'Suporte', 'ru-RU': 'Поддержка',
|
|
83
|
+
},
|
|
84
|
+
downloadClient: {
|
|
85
|
+
'zh-CN': '下载客户端', 'zh-Hant': '下載客戶端', 'en-US': 'Download Client',
|
|
86
|
+
'ja-JP': 'クライアントをダウンロード', 'ko-KR': '클라이언트 다운로드',
|
|
87
|
+
'de-DE': 'Client herunterladen', 'fr-FR': 'Télécharger le client',
|
|
88
|
+
'es-ES': 'Descargar cliente', 'pt-BR': 'Baixar cliente', 'ru-RU': 'Скачать клиент',
|
|
89
|
+
},
|
|
90
|
+
about: {
|
|
91
|
+
'zh-CN': '关于 HagiCode', 'zh-Hant': '關於 HagiCode', 'en-US': 'About HagiCode',
|
|
92
|
+
'ja-JP': 'HagiCode について', 'ko-KR': 'HagiCode 소개', 'de-DE': 'Über HagiCode',
|
|
93
|
+
'fr-FR': 'À propos de HagiCode', 'es-ES': 'Acerca de HagiCode',
|
|
94
|
+
'pt-BR': 'Sobre a HagiCode', 'ru-RU': 'О HagiCode',
|
|
95
|
+
},
|
|
96
|
+
dockerCompose: {
|
|
97
|
+
'zh-CN': 'Docker Compose 安装', 'zh-Hant': 'Docker Compose 安裝',
|
|
98
|
+
'en-US': 'Docker Compose Installation', 'ja-JP': 'Docker Compose インストール',
|
|
99
|
+
'ko-KR': 'Docker Compose 설치', 'de-DE': 'Docker-Compose-Installation',
|
|
100
|
+
'fr-FR': 'Installation de Docker Compose', 'es-ES': 'Instalación de Docker Compose',
|
|
101
|
+
'pt-BR': 'Instalação do Docker Compose', 'ru-RU': 'Установка Docker Compose',
|
|
102
|
+
},
|
|
103
|
+
productDocs: {
|
|
104
|
+
'zh-CN': '产品文档', 'zh-Hant': '產品文件', 'en-US': 'Product Docs',
|
|
105
|
+
'ja-JP': '製品ドキュメント', 'ko-KR': '제품 문서', 'de-DE': 'Produktdokumentation',
|
|
106
|
+
'fr-FR': 'Documentation produit', 'es-ES': 'Documentación del producto',
|
|
107
|
+
'pt-BR': 'Documentação do produto', 'ru-RU': 'Документация продукта',
|
|
108
|
+
},
|
|
109
|
+
blogPosts: {
|
|
110
|
+
'zh-CN': '博客文章', 'zh-Hant': '部落格文章', 'en-US': 'Blog Posts',
|
|
111
|
+
'ja-JP': 'ブログ記事', 'ko-KR': '블로그 글', 'de-DE': 'Blogbeiträge',
|
|
112
|
+
'fr-FR': 'Articles du blog', 'es-ES': 'Artículos del blog',
|
|
113
|
+
'pt-BR': 'Posts do blog', 'ru-RU': 'Статьи блога',
|
|
114
|
+
},
|
|
115
|
+
rss: {
|
|
116
|
+
'zh-CN': 'RSS 订阅', 'zh-Hant': 'RSS 訂閱', 'en-US': 'RSS Feed',
|
|
117
|
+
'ja-JP': 'RSS 配信', 'ko-KR': 'RSS 구독', 'de-DE': 'RSS-Feed',
|
|
118
|
+
'fr-FR': 'Flux RSS', 'es-ES': 'RSS', 'pt-BR': 'Feed RSS', 'ru-RU': 'RSS-лента',
|
|
119
|
+
},
|
|
120
|
+
costCalculator: {
|
|
121
|
+
'zh-CN': '算一算,AI会不会淘汰我', 'zh-Hant': '算一算,AI 會不會淘汰我',
|
|
122
|
+
'en-US': 'Will AI Replace Me?', 'ja-JP': 'AI に置き換えられるか診断',
|
|
123
|
+
'ko-KR': 'AI가 나를 대체할까?', 'de-DE': 'Wird KI mich ersetzen?',
|
|
124
|
+
'fr-FR': "L'IA va-t-elle me remplacer ?", 'es-ES': 'Me reemplazará la IA?',
|
|
125
|
+
'pt-BR': 'A IA vai me substituir?', 'ru-RU': 'Заменит ли меня ИИ?',
|
|
126
|
+
},
|
|
127
|
+
github: {
|
|
128
|
+
'zh-CN': 'GitHub', 'zh-Hant': 'GitHub', 'en-US': 'GitHub', 'ja-JP': 'GitHub',
|
|
129
|
+
'ko-KR': 'GitHub', 'de-DE': 'GitHub', 'fr-FR': 'GitHub', 'es-ES': 'GitHub',
|
|
130
|
+
'pt-BR': 'GitHub', 'ru-RU': 'GitHub',
|
|
131
|
+
},
|
|
132
|
+
discord: {
|
|
133
|
+
'zh-CN': 'Discord', 'zh-Hant': 'Discord', 'en-US': 'Discord', 'ja-JP': 'Discord',
|
|
134
|
+
'ko-KR': 'Discord', 'de-DE': 'Discord', 'fr-FR': 'Discord', 'es-ES': 'Discord',
|
|
135
|
+
'pt-BR': 'Discord', 'ru-RU': 'Discord',
|
|
136
|
+
},
|
|
137
|
+
issueFeedback: {
|
|
138
|
+
'zh-CN': '问题反馈', 'zh-Hant': '問題回饋', 'en-US': 'Issue Feedback',
|
|
139
|
+
'ja-JP': '問題の報告', 'ko-KR': '문제 신고', 'de-DE': 'Probleme melden',
|
|
140
|
+
'fr-FR': 'Signaler un problème', 'es-ES': 'Reportar un problema',
|
|
141
|
+
'pt-BR': 'Relatar problema', 'ru-RU': 'Сообщить о проблеме',
|
|
142
|
+
},
|
|
143
|
+
contactEmail: {
|
|
144
|
+
'zh-CN': '联系邮箱', 'zh-Hant': '聯絡信箱', 'en-US': 'Contact Email',
|
|
145
|
+
'ja-JP': '連絡先メール', 'ko-KR': '문의 이메일', 'de-DE': 'Kontakt-E-Mail',
|
|
146
|
+
'fr-FR': 'E-mail de contact', 'es-ES': 'Correo de contacto',
|
|
147
|
+
'pt-BR': 'E-mail de contato', 'ru-RU': 'Контактный email',
|
|
148
|
+
},
|
|
149
|
+
qqGroup: {
|
|
150
|
+
'zh-CN': 'QQ 群 610394020', 'zh-Hant': 'QQ 群 610394020',
|
|
151
|
+
'en-US': 'QQ Group 610394020', 'ja-JP': 'QQ グループ 610394020',
|
|
152
|
+
'ko-KR': 'QQ 그룹 610394020', 'de-DE': 'QQ-Gruppe 610394020',
|
|
153
|
+
'fr-FR': 'Groupe QQ 610394020', 'es-ES': 'Grupo QQ 610394020',
|
|
154
|
+
'pt-BR': 'Grupo QQ 610394020', 'ru-RU': 'Группа QQ 610394020',
|
|
155
|
+
},
|
|
156
|
+
steam: {
|
|
157
|
+
'zh-CN': 'Steam', 'zh-Hant': 'Steam', 'en-US': 'Steam', 'ja-JP': 'Steam',
|
|
158
|
+
'ko-KR': 'Steam', 'de-DE': 'Steam', 'fr-FR': 'Steam', 'es-ES': 'Steam',
|
|
159
|
+
'pt-BR': 'Steam', 'ru-RU': 'Steam',
|
|
160
|
+
},
|
|
161
|
+
icpFiling: '闽ICP备2026004153号-1',
|
|
162
|
+
publicSecurityFiling: '闽公网安备35011102351148号',
|
|
73
163
|
} satisfies Record<SiteLinkKey, LocalizedText>;
|
|
74
164
|
|
|
75
165
|
const defaultLinks: Record<SiteLinkKey, LinkDefinition> = {
|
|
76
|
-
home: { label: translations.home, href: '
|
|
166
|
+
home: { label: translations.home, href: (locale) => marketingPath(locale, '/') },
|
|
77
167
|
blog: { label: translations.blog, href: (locale) => docsPath(locale, '/blog/') },
|
|
78
|
-
support: { label: translations.support, href: '
|
|
79
|
-
downloadClient: { label: translations.downloadClient, href: '
|
|
80
|
-
about: { label: translations.about, href: '
|
|
168
|
+
support: { label: translations.support, href: (locale) => marketingPath(locale, '/about/') },
|
|
169
|
+
downloadClient: { label: translations.downloadClient, href: (locale) => marketingPath(locale, '/desktop/') },
|
|
170
|
+
about: { label: translations.about, href: (locale) => marketingPath(locale, '/about/') },
|
|
81
171
|
dockerCompose: { label: translations.dockerCompose, href: (locale) => docsPath(locale, '/installation/docker-compose/') },
|
|
82
172
|
productDocs: { label: translations.productDocs, href: (locale) => docsPath(locale, '/product-overview/') },
|
|
83
|
-
|
|
173
|
+
blogPosts: { label: translations.blogPosts, href: (locale) => docsPath(locale, '/blog/') },
|
|
174
|
+
rss: { label: translations.rss, href: (locale) => `https://docs.hagicode.com/blog/rss.${locale}.xml` },
|
|
84
175
|
costCalculator: { label: translations.costCalculator, href: 'https://cost.hagicode.com', external: true },
|
|
85
176
|
github: { label: translations.github, href: 'https://github.com/HagiCode-org/site', external: true },
|
|
86
177
|
discord: { label: translations.discord, href: 'https://discord.gg/qY662sJK', external: true },
|
|
178
|
+
issueFeedback: { label: translations.issueFeedback, href: 'https://github.com/HagiCode-org/site/issues', external: true },
|
|
179
|
+
contactEmail: { label: translations.contactEmail, href: 'mailto:support@hagicode.com' },
|
|
87
180
|
qqGroup: { label: translations.qqGroup, href: 'https://qm.qq.com/q/Fwb0o094kw', external: true },
|
|
88
181
|
steam: { label: translations.steam, href: 'https://store.steampowered.com/app/4625540/Hagicode/', external: true },
|
|
182
|
+
icpFiling: {
|
|
183
|
+
label: translations.icpFiling,
|
|
184
|
+
href: 'https://beian.miit.gov.cn/',
|
|
185
|
+
external: true,
|
|
186
|
+
ariaLabel: {
|
|
187
|
+
'zh-CN': '查看 ICP 备案信息', 'zh-Hant': '查看 ICP 備案資訊',
|
|
188
|
+
'en-US': 'View ICP filing information', 'ja-JP': 'ICP 登録情報を表示',
|
|
189
|
+
'ko-KR': 'ICP 등록 정보 보기', 'de-DE': 'ICP-Registrierungsinformationen anzeigen',
|
|
190
|
+
'fr-FR': 'Voir les informations de dépôt ICP', 'es-ES': 'Ver la información de registro ICP',
|
|
191
|
+
'pt-BR': 'Ver informações de registro ICP', 'ru-RU': 'Показать информацию о регистрации ICP',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
publicSecurityFiling: {
|
|
195
|
+
label: translations.publicSecurityFiling,
|
|
196
|
+
href: 'http://www.beian.gov.cn/portal/registerSystemInfo',
|
|
197
|
+
external: true,
|
|
198
|
+
ariaLabel: {
|
|
199
|
+
'zh-CN': '查看公安备案信息', 'zh-Hant': '查看公安備案資訊',
|
|
200
|
+
'en-US': 'View public security filing information', 'ja-JP': '公安登録情報を表示',
|
|
201
|
+
'ko-KR': '공안 등록 정보 보기', 'de-DE': 'Informationen zur Sicherheitsregistrierung anzeigen',
|
|
202
|
+
'fr-FR': 'Voir les informations de dépôt de sécurité publique',
|
|
203
|
+
'es-ES': 'Ver la información de registro de seguridad pública',
|
|
204
|
+
'pt-BR': 'Ver informações de registro de segurança pública',
|
|
205
|
+
'ru-RU': 'Показать информацию о регистрации в органах общественной безопасности',
|
|
206
|
+
},
|
|
207
|
+
},
|
|
89
208
|
};
|
|
90
209
|
|
|
91
210
|
const groups: Record<LinkGroup, readonly SiteLinkKey[]> = {
|
|
92
211
|
header: ['home', 'blog', 'support'],
|
|
93
|
-
quick: ['downloadClient', 'about', 'dockerCompose', 'productDocs', '
|
|
94
|
-
community: ['github', 'discord', 'qqGroup', 'steam'],
|
|
212
|
+
quick: ['downloadClient', 'about', 'dockerCompose', 'productDocs', 'blogPosts', 'rss'],
|
|
213
|
+
community: ['github', 'discord', 'issueFeedback', 'contactEmail', 'qqGroup', 'costCalculator', 'steam'],
|
|
214
|
+
filings: ['icpFiling', 'publicSecurityFiling'],
|
|
95
215
|
};
|
|
96
216
|
|
|
97
217
|
function normalizeLocale(locale?: string | null): string {
|
|
@@ -105,24 +225,19 @@ function normalizeLocale(locale?: string | null): string {
|
|
|
105
225
|
if (normalized === 'en' || normalized === 'en-us' || !normalized) {
|
|
106
226
|
return 'en-US';
|
|
107
227
|
}
|
|
108
|
-
const canonical = [
|
|
109
|
-
|
|
110
|
-
].find((candidate) => candidate.toLowerCase() === normalized);
|
|
228
|
+
const canonical = ['ja-JP', 'ko-KR', 'de-DE', 'fr-FR', 'es-ES', 'pt-BR', 'ru-RU']
|
|
229
|
+
.find((candidate) => candidate.toLowerCase() === normalized);
|
|
111
230
|
if (canonical) return canonical;
|
|
112
|
-
return
|
|
231
|
+
return 'en-US';
|
|
113
232
|
}
|
|
114
233
|
|
|
115
234
|
function docsPath(locale: string, pathname: string): string {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
]);
|
|
123
|
-
const routeLocale = supportedRouteLocales.has(locale) ? locale : 'en-US';
|
|
124
|
-
const prefix = routeLocale === 'zh-CN' ? '' : `/${routeLocale}`;
|
|
125
|
-
return `https://docs.hagicode.com${prefix}${pathname}`;
|
|
235
|
+
const routePrefix = locale === 'zh-CN' ? '' : `/${locale}`;
|
|
236
|
+
return `https://docs.hagicode.com${routePrefix}${pathname}`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function marketingPath(locale: string, pathname: string): string {
|
|
240
|
+
return `https://www.hagicode.com/${locale}${pathname}`;
|
|
126
241
|
}
|
|
127
242
|
|
|
128
243
|
function resolveLocalized(value: LocalizedText, locale: string, fallback: string): string {
|
|
@@ -165,6 +280,9 @@ function resolveLink(
|
|
|
165
280
|
id: key,
|
|
166
281
|
label,
|
|
167
282
|
href,
|
|
283
|
+
...(definition.ariaLabel
|
|
284
|
+
? { ariaLabel: resolveLocalized(definition.ariaLabel, locale, label) }
|
|
285
|
+
: {}),
|
|
168
286
|
...(external ? { target: '_blank', rel: 'noopener noreferrer' } : {}),
|
|
169
287
|
};
|
|
170
288
|
}
|
|
@@ -173,9 +291,11 @@ export function resolveSiteLinks(localeInput?: string | null, options: SiteLinks
|
|
|
173
291
|
const locale = normalizeLocale(localeInput);
|
|
174
292
|
const resolvedGroups = Object.fromEntries(
|
|
175
293
|
(Object.keys(groups) as LinkGroup[]).map((group) => {
|
|
176
|
-
const catalogLinks = groups[group].map((key) =>
|
|
177
|
-
|
|
178
|
-
|
|
294
|
+
const catalogLinks = groups[group].map((key) => {
|
|
295
|
+
const override = options.overrides?.[key]
|
|
296
|
+
?? (key === 'blogPosts' ? options.overrides?.blog : undefined);
|
|
297
|
+
return resolveLink(key, locale, defaultLinks[key], override);
|
|
298
|
+
});
|
|
179
299
|
const extraLinks = (options.extraLinks?.[group] ?? []).map((entry, index) => {
|
|
180
300
|
const definition: LinkDefinition = {
|
|
181
301
|
label: entry.label,
|
|
@@ -189,14 +309,18 @@ export function resolveSiteLinks(localeInput?: string | null, options: SiteLinks
|
|
|
189
309
|
) as Record<LinkGroup, SiteLink[]>;
|
|
190
310
|
|
|
191
311
|
const renderedUrls = new Set(
|
|
192
|
-
|
|
312
|
+
[...resolvedGroups.quick, ...resolvedGroups.community, ...resolvedGroups.filings]
|
|
313
|
+
.map((link) => normalizeUrl(link.href)),
|
|
193
314
|
);
|
|
194
315
|
if (options.siteUrl) renderedUrls.add(normalizeUrl(options.siteUrl));
|
|
195
316
|
|
|
196
317
|
const relatedIds = new Set<string>();
|
|
197
318
|
const relatedUrls = new Set<string>();
|
|
198
|
-
const relatedSites = (options.relatedSites ??
|
|
199
|
-
const
|
|
319
|
+
const relatedSites = (options.relatedSites ?? docsRelatedSites).flatMap((site) => {
|
|
320
|
+
const href = site.id === 'hagicode-main' && !options.relatedSites
|
|
321
|
+
? marketingPath(locale, '/')
|
|
322
|
+
: site.url;
|
|
323
|
+
const normalizedUrl = normalizeUrl(href);
|
|
200
324
|
if (site.id === options.siteId || renderedUrls.has(normalizedUrl)
|
|
201
325
|
|| relatedIds.has(site.id) || relatedUrls.has(normalizedUrl)) {
|
|
202
326
|
return [];
|
|
@@ -209,20 +333,68 @@ export function resolveSiteLinks(localeInput?: string | null, options: SiteLinks
|
|
|
209
333
|
description: site.description
|
|
210
334
|
? resolveLocalized(site.description, locale, '')
|
|
211
335
|
: undefined,
|
|
212
|
-
href
|
|
336
|
+
href,
|
|
337
|
+
target: '_blank' as const,
|
|
338
|
+
rel: 'noopener noreferrer' as const,
|
|
213
339
|
}];
|
|
214
340
|
});
|
|
215
341
|
|
|
216
342
|
return {
|
|
217
343
|
locale,
|
|
218
344
|
labels: {
|
|
219
|
-
relatedSites: resolveLocalized({
|
|
220
|
-
|
|
221
|
-
|
|
345
|
+
relatedSites: resolveLocalized({
|
|
346
|
+
'zh-CN': '生态站点', 'zh-Hant': '生態站點', 'en-US': 'Ecosystem Sites',
|
|
347
|
+
'ja-JP': 'エコシステムサイト', 'ko-KR': '에코시스템 사이트',
|
|
348
|
+
'de-DE': 'Ökosystem-Seiten', 'fr-FR': "Sites de l'écosystème",
|
|
349
|
+
'es-ES': 'Sitios del ecosistema', 'pt-BR': 'Sites do ecossistema',
|
|
350
|
+
'ru-RU': 'Сайты экосистемы',
|
|
351
|
+
}, locale, 'Ecosystem Sites'),
|
|
352
|
+
quickLinks: resolveLocalized({
|
|
353
|
+
'zh-CN': '快速链接', 'zh-Hant': '快速連結', 'en-US': 'Quick Links',
|
|
354
|
+
'ja-JP': 'クイックリンク', 'ko-KR': '빠른 링크', 'de-DE': 'Schnellzugriffe',
|
|
355
|
+
'fr-FR': 'Liens rapides', 'es-ES': 'Enlaces rápidos',
|
|
356
|
+
'pt-BR': 'Links rápidos', 'ru-RU': 'Быстрые ссылки',
|
|
357
|
+
}, locale, 'Quick Links'),
|
|
358
|
+
community: resolveLocalized({
|
|
359
|
+
'zh-CN': '社区', 'zh-Hant': '社群', 'en-US': 'Community',
|
|
360
|
+
'ja-JP': 'コミュニティ', 'ko-KR': '커뮤니티', 'de-DE': 'Community',
|
|
361
|
+
'fr-FR': 'Communauté', 'es-ES': 'Comunidad',
|
|
362
|
+
'pt-BR': 'Comunidade', 'ru-RU': 'Сообщество',
|
|
363
|
+
}, locale, 'Community'),
|
|
364
|
+
navigation: {
|
|
365
|
+
relatedSites: resolveLocalized({
|
|
366
|
+
'zh-CN': '生态站点链接', 'zh-Hant': '生態站點連結', 'en-US': 'Ecosystem site links',
|
|
367
|
+
'ja-JP': 'エコシステムサイトへのリンク', 'ko-KR': '에코시스템 사이트 링크',
|
|
368
|
+
'de-DE': 'Links zu Ökosystem-Seiten', 'fr-FR': "Liens vers les sites de l'écosystème",
|
|
369
|
+
'es-ES': 'Enlaces de sitios del ecosistema', 'pt-BR': 'Links dos sites do ecossistema',
|
|
370
|
+
'ru-RU': 'Ссылки на сайты экосистемы',
|
|
371
|
+
}, locale, 'Ecosystem site links'),
|
|
372
|
+
quickLinks: resolveLocalized({
|
|
373
|
+
'zh-CN': '快速链接', 'zh-Hant': '快速連結', 'en-US': 'Quick links',
|
|
374
|
+
'ja-JP': 'クイックリンク', 'ko-KR': '빠른 링크', 'de-DE': 'Schnellzugriffe',
|
|
375
|
+
'fr-FR': 'Liens rapides', 'es-ES': 'Enlaces rápidos',
|
|
376
|
+
'pt-BR': 'Links rápidos', 'ru-RU': 'Быстрые ссылки',
|
|
377
|
+
}, locale, 'Quick links'),
|
|
378
|
+
community: resolveLocalized({
|
|
379
|
+
'zh-CN': '社区链接', 'zh-Hant': '社群連結', 'en-US': 'Community links',
|
|
380
|
+
'ja-JP': 'コミュニティリンク', 'ko-KR': '커뮤니티 링크',
|
|
381
|
+
'de-DE': 'Community-Links', 'fr-FR': 'Liens communautaires',
|
|
382
|
+
'es-ES': 'Enlaces de la comunidad', 'pt-BR': 'Links da comunidade',
|
|
383
|
+
'ru-RU': 'Ссылки сообщества',
|
|
384
|
+
}, locale, 'Community links'),
|
|
385
|
+
filings: resolveLocalized({
|
|
386
|
+
'zh-CN': '查看备案信息', 'zh-Hant': '查看備案資訊',
|
|
387
|
+
'en-US': 'View filing information', 'ja-JP': '登録情報を表示',
|
|
388
|
+
'ko-KR': '등록 정보 보기', 'de-DE': 'Registrierungsinformationen anzeigen',
|
|
389
|
+
'fr-FR': 'Voir les informations de dépôt', 'es-ES': 'Ver información de registro',
|
|
390
|
+
'pt-BR': 'Ver informações de registro', 'ru-RU': 'Показать информацию о регистрации',
|
|
391
|
+
}, locale, 'View filing information'),
|
|
392
|
+
},
|
|
222
393
|
},
|
|
223
394
|
header: resolvedGroups.header,
|
|
224
395
|
quick: resolvedGroups.quick,
|
|
225
396
|
community: resolvedGroups.community,
|
|
397
|
+
filings: resolvedGroups.filings,
|
|
226
398
|
relatedSites,
|
|
227
399
|
};
|
|
228
400
|
}
|