@jjlmoya/utils-audiovisual 1.6.0 → 1.8.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/package.json +59 -58
- package/src/category/i18n/de.ts +198 -0
- package/src/category/i18n/fr.ts +1 -1
- package/src/category/i18n/id.ts +198 -0
- package/src/category/i18n/it.ts +198 -0
- package/src/category/i18n/ja.ts +198 -0
- package/src/category/i18n/ko.ts +198 -0
- package/src/category/i18n/nl.ts +198 -0
- package/src/category/i18n/pl.ts +198 -0
- package/src/category/i18n/pt.ts +198 -0
- package/src/category/i18n/ru.ts +198 -0
- package/src/category/i18n/sv.ts +198 -0
- package/src/category/i18n/tr.ts +198 -0
- package/src/category/i18n/zh.ts +198 -0
- package/src/category/index.ts +31 -3
- package/src/tests/i18n_coverage.test.ts +36 -0
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tool/chromaticLens/i18n/de.ts +246 -0
- package/src/tool/chromaticLens/i18n/en.ts +1 -1
- package/src/tool/chromaticLens/i18n/es.ts +1 -1
- package/src/tool/chromaticLens/i18n/fr.ts +1 -1
- package/src/tool/chromaticLens/i18n/id.ts +246 -0
- package/src/tool/chromaticLens/i18n/it.ts +246 -0
- package/src/tool/chromaticLens/i18n/ja.ts +246 -0
- package/src/tool/chromaticLens/i18n/ko.ts +246 -0
- package/src/tool/chromaticLens/i18n/nl.ts +246 -0
- package/src/tool/chromaticLens/i18n/pl.ts +246 -0
- package/src/tool/chromaticLens/i18n/pt.ts +246 -0
- package/src/tool/chromaticLens/i18n/ru.ts +246 -0
- package/src/tool/chromaticLens/i18n/sv.ts +246 -0
- package/src/tool/chromaticLens/i18n/tr.ts +246 -0
- package/src/tool/chromaticLens/i18n/zh.ts +246 -0
- package/src/tool/chromaticLens/index.ts +15 -7
- package/src/tool/collageMaker/i18n/de.ts +233 -0
- package/src/tool/collageMaker/i18n/en.ts +1 -1
- package/src/tool/collageMaker/i18n/es.ts +1 -1
- package/src/tool/collageMaker/i18n/fr.ts +1 -1
- package/src/tool/collageMaker/i18n/id.ts +233 -0
- package/src/tool/collageMaker/i18n/it.ts +233 -0
- package/src/tool/collageMaker/i18n/ja.ts +233 -0
- package/src/tool/collageMaker/i18n/ko.ts +233 -0
- package/src/tool/collageMaker/i18n/nl.ts +233 -0
- package/src/tool/collageMaker/i18n/pl.ts +233 -0
- package/src/tool/collageMaker/i18n/pt.ts +233 -0
- package/src/tool/collageMaker/i18n/ru.ts +233 -0
- package/src/tool/collageMaker/i18n/sv.ts +233 -0
- package/src/tool/collageMaker/i18n/tr.ts +233 -0
- package/src/tool/collageMaker/i18n/zh.ts +233 -0
- package/src/tool/collageMaker/index.ts +15 -6
- package/src/tool/exifCleaner/i18n/de.ts +277 -0
- package/src/tool/exifCleaner/i18n/en.ts +2 -2
- package/src/tool/exifCleaner/i18n/es.ts +2 -2
- package/src/tool/exifCleaner/i18n/fr.ts +4 -4
- package/src/tool/exifCleaner/i18n/id.ts +277 -0
- package/src/tool/exifCleaner/i18n/it.ts +277 -0
- package/src/tool/exifCleaner/i18n/ja.ts +277 -0
- package/src/tool/exifCleaner/i18n/ko.ts +277 -0
- package/src/tool/exifCleaner/i18n/nl.ts +277 -0
- package/src/tool/exifCleaner/i18n/pl.ts +277 -0
- package/src/tool/exifCleaner/i18n/pt.ts +277 -0
- package/src/tool/exifCleaner/i18n/ru.ts +277 -0
- package/src/tool/exifCleaner/i18n/sv.ts +277 -0
- package/src/tool/exifCleaner/i18n/tr.ts +277 -0
- package/src/tool/exifCleaner/i18n/zh.ts +277 -0
- package/src/tool/exifCleaner/index.ts +16 -8
- package/src/tool/imageCompressor/i18n/de.ts +242 -0
- package/src/tool/imageCompressor/i18n/en.ts +2 -2
- package/src/tool/imageCompressor/i18n/es.ts +2 -2
- package/src/tool/imageCompressor/i18n/id.ts +242 -0
- package/src/tool/imageCompressor/i18n/it.ts +242 -0
- package/src/tool/imageCompressor/i18n/ja.ts +242 -0
- package/src/tool/imageCompressor/i18n/ko.ts +242 -0
- package/src/tool/imageCompressor/i18n/nl.ts +242 -0
- package/src/tool/imageCompressor/i18n/pl.ts +242 -0
- package/src/tool/imageCompressor/i18n/pt.ts +242 -0
- package/src/tool/imageCompressor/i18n/ru.ts +242 -0
- package/src/tool/imageCompressor/i18n/sv.ts +242 -0
- package/src/tool/imageCompressor/i18n/tr.ts +242 -0
- package/src/tool/imageCompressor/i18n/zh.ts +244 -0
- package/src/tool/imageCompressor/index.ts +15 -7
- package/src/tool/printQualityCalculator/i18n/de.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/en.ts +2 -2
- package/src/tool/printQualityCalculator/i18n/es.ts +3 -3
- package/src/tool/printQualityCalculator/i18n/fr.ts +3 -3
- package/src/tool/printQualityCalculator/i18n/id.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/it.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/ja.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/ko.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/nl.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/pl.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/pt.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/ru.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/sv.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/tr.ts +261 -0
- package/src/tool/printQualityCalculator/i18n/zh.ts +261 -0
- package/src/tool/printQualityCalculator/index.ts +15 -7
- package/src/tool/privacyBlur/i18n/de.ts +238 -0
- package/src/tool/privacyBlur/i18n/en.ts +1 -1
- package/src/tool/privacyBlur/i18n/es.ts +1 -1
- package/src/tool/privacyBlur/i18n/fr.ts +1 -1
- package/src/tool/privacyBlur/i18n/id.ts +238 -0
- package/src/tool/privacyBlur/i18n/it.ts +238 -0
- package/src/tool/privacyBlur/i18n/ja.ts +238 -0
- package/src/tool/privacyBlur/i18n/ko.ts +238 -0
- package/src/tool/privacyBlur/i18n/nl.ts +238 -0
- package/src/tool/privacyBlur/i18n/pl.ts +238 -0
- package/src/tool/privacyBlur/i18n/pt.ts +238 -0
- package/src/tool/privacyBlur/i18n/ru.ts +238 -0
- package/src/tool/privacyBlur/i18n/sv.ts +238 -0
- package/src/tool/privacyBlur/i18n/tr.ts +238 -0
- package/src/tool/privacyBlur/i18n/zh.ts +238 -0
- package/src/tool/privacyBlur/index.ts +15 -7
- package/src/tool/subtitleSync/i18n/de.ts +241 -0
- package/src/tool/subtitleSync/i18n/en.ts +1 -1
- package/src/tool/subtitleSync/i18n/es.ts +1 -1
- package/src/tool/subtitleSync/i18n/fr.ts +8 -8
- package/src/tool/subtitleSync/i18n/id.ts +241 -0
- package/src/tool/subtitleSync/i18n/it.ts +241 -0
- package/src/tool/subtitleSync/i18n/ja.ts +241 -0
- package/src/tool/subtitleSync/i18n/ko.ts +241 -0
- package/src/tool/subtitleSync/i18n/nl.ts +241 -0
- package/src/tool/subtitleSync/i18n/pl.ts +241 -0
- package/src/tool/subtitleSync/i18n/pt.ts +241 -0
- package/src/tool/subtitleSync/i18n/ru.ts +241 -0
- package/src/tool/subtitleSync/i18n/sv.ts +241 -0
- package/src/tool/subtitleSync/i18n/tr.ts +241 -0
- package/src/tool/subtitleSync/i18n/zh.ts +241 -0
- package/src/tool/subtitleSync/index.ts +15 -7
- package/src/tool/timelapseCalculator/i18n/de.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/fr.ts +2 -2
- package/src/tool/timelapseCalculator/i18n/id.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/it.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/ja.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/ko.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/nl.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/pl.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/pt.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/ru.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/sv.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/tr.ts +169 -0
- package/src/tool/timelapseCalculator/i18n/zh.ts +169 -0
- package/src/tool/timelapseCalculator/index.ts +16 -8
- package/src/tool/tvDistance/i18n/de.ts +223 -0
- package/src/tool/tvDistance/i18n/en.ts +1 -1
- package/src/tool/tvDistance/i18n/es.ts +1 -1
- package/src/tool/tvDistance/i18n/fr.ts +1 -1
- package/src/tool/tvDistance/i18n/id.ts +223 -0
- package/src/tool/tvDistance/i18n/it.ts +223 -0
- package/src/tool/tvDistance/i18n/ja.ts +223 -0
- package/src/tool/tvDistance/i18n/ko.ts +223 -0
- package/src/tool/tvDistance/i18n/nl.ts +223 -0
- package/src/tool/tvDistance/i18n/pl.ts +223 -0
- package/src/tool/tvDistance/i18n/pt.ts +223 -0
- package/src/tool/tvDistance/i18n/ru.ts +223 -0
- package/src/tool/tvDistance/i18n/sv.ts +223 -0
- package/src/tool/tvDistance/i18n/tr.ts +223 -0
- package/src/tool/tvDistance/i18n/zh.ts +223 -0
- package/src/tool/tvDistance/index.ts +15 -7
- package/src/tool/videoFrameExtractor/i18n/de.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/en.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/es.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/fr.ts +1 -1
- package/src/tool/videoFrameExtractor/i18n/id.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/it.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/ja.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/ko.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/nl.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/pl.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/pt.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/ru.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/sv.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/tr.ts +235 -0
- package/src/tool/videoFrameExtractor/i18n/zh.ts +235 -0
- package/src/tool/videoFrameExtractor/index.ts +16 -8
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import type { CategoryLocaleContent } from '../../types';
|
|
2
|
+
|
|
3
|
+
export const content: CategoryLocaleContent = {
|
|
4
|
+
slug: 'audiovisual-photography',
|
|
5
|
+
title: '音视频与摄影工具',
|
|
6
|
+
description: '为电影制作人、摄影师和数字音视频内容创作者提供的专业工具和计算器。',
|
|
7
|
+
seo: [
|
|
8
|
+
{
|
|
9
|
+
type: 'summary',
|
|
10
|
+
title: '专业音视频工具',
|
|
11
|
+
items: [
|
|
12
|
+
'用于延时摄影、特效和构图的智能计算器。',
|
|
13
|
+
'用于清理 EXIF 元数据的隐私工具。',
|
|
14
|
+
'字幕同步和时间轴编辑。',
|
|
15
|
+
'分辨率分析、打印质量和最佳观看距离。'
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: 'title',
|
|
20
|
+
text: '音视频制作专业工具箱',
|
|
21
|
+
level: 2,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'paragraph',
|
|
25
|
+
html: '我们的综合实用程序套件解决了音视频制作各个阶段最常见的技术挑战。从电影级延时摄影的精确间隔计算,到通过清理多媒体文件中的 EXIF 元数据来保护隐私。',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'stats',
|
|
29
|
+
items: [
|
|
30
|
+
{
|
|
31
|
+
value: '12+',
|
|
32
|
+
label: '专用工具',
|
|
33
|
+
icon: 'mdi:cog'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
value: '100%',
|
|
37
|
+
label: '精确计算',
|
|
38
|
+
icon: 'mdi:chart-line'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
value: '0%',
|
|
42
|
+
label: '数据存储在服务器上',
|
|
43
|
+
icon: 'mdi:shield-check'
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
columns: 3
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'title',
|
|
50
|
+
text: '工具类别',
|
|
51
|
+
level: 3,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: 'comparative',
|
|
55
|
+
items: [
|
|
56
|
+
{
|
|
57
|
+
title: '延时摄影与电影感',
|
|
58
|
+
description: '为您的电影镜头计算拍摄间隔、总时长和帧率。',
|
|
59
|
+
icon: 'mdi:film',
|
|
60
|
+
points: [
|
|
61
|
+
'所需帧数计算',
|
|
62
|
+
'时长(秒/分钟)',
|
|
63
|
+
'可变播放速度'
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: '隐私与元数据',
|
|
68
|
+
description: '通过删除文件中的 EXIF 数据和敏感元数据来保护您的隐私。',
|
|
69
|
+
icon: 'mdi:lock',
|
|
70
|
+
points: [
|
|
71
|
+
'EXIF 数据分析',
|
|
72
|
+
'地点元数据清理',
|
|
73
|
+
'设备信息移除'
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
title: '字幕编辑',
|
|
78
|
+
description: '以毫秒级的精度同步、调整和编辑字幕。',
|
|
79
|
+
icon: 'mdi:text',
|
|
80
|
+
points: [
|
|
81
|
+
'实时同步',
|
|
82
|
+
'入点/出点时间编辑',
|
|
83
|
+
'全局延迟调整'
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title: '图像分析',
|
|
88
|
+
description: '计算分辨率、打印和观看距离的技术参数。',
|
|
89
|
+
icon: 'mdi:image',
|
|
90
|
+
points: [
|
|
91
|
+
'DPI 与分辨率计算',
|
|
92
|
+
'推荐观看距离',
|
|
93
|
+
'打印质量分析'
|
|
94
|
+
],
|
|
95
|
+
highlight: true
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
columns: 2
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
type: 'title',
|
|
102
|
+
text: '为什么选择我们的工具',
|
|
103
|
+
level: 3,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'proscons',
|
|
107
|
+
items: [
|
|
108
|
+
{
|
|
109
|
+
pro: '100% 基于浏览器处理 - 您的数据永远不会上传到服务器',
|
|
110
|
+
con: '需要支持 JavaScript 的现代浏览器'
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
pro: '所有音视频计算均具有数学精度',
|
|
114
|
+
con: '极少特定情况可能需要人工核对'
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
pro: '专为行业专业人士设计的直观界面',
|
|
118
|
+
con: '在桌面/平板电脑屏幕上体验最佳'
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
pro: '完全免费的工具,无使用限制',
|
|
122
|
+
con: '无专门的高级支持(提供社区支持)'
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
proTitle: '优势',
|
|
126
|
+
conTitle: '注意事项'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'title',
|
|
130
|
+
text: '快速入门指南',
|
|
131
|
+
level: 3,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: 'list',
|
|
135
|
+
items: [
|
|
136
|
+
'根据您的项目类型选择所需的工具',
|
|
137
|
+
'输入技术参数(帧数、分辨率、时间等)',
|
|
138
|
+
'立即获得计算结果和精确数据',
|
|
139
|
+
'导出结果或将其应用到您的工作流程中',
|
|
140
|
+
'可以无限制地为多个项目重复此过程'
|
|
141
|
+
],
|
|
142
|
+
icon: 'mdi:arrow-right'
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'tip',
|
|
146
|
+
title: '专业提示',
|
|
147
|
+
html: '在处理多个片段或序列时,我们建议将关键参数(相机分辨率、常用帧率、字幕语言)保存在文档中。这样您可以快速访问它们,而无需每次重新计算。'
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'glossary',
|
|
151
|
+
items: [
|
|
152
|
+
{
|
|
153
|
+
term: 'EXIF',
|
|
154
|
+
definition: '在数字图像中存储元数据(日期、相机、GPS 位置等)的文件格式。它可能带来隐私风险。'
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
term: 'FPS (每秒帧数)',
|
|
158
|
+
definition: '每秒播放的帧数。常见值:24 fps(电影)、25 fps(PAL)、30 fps(NTSC)、60 fps(平滑视频)。'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
term: 'DPI (每英寸点数)',
|
|
162
|
+
definition: '打印中的分辨率衡量标准。DPI 越高 = 质量越好。对于专业摄影,建议至少 300 DPI。'
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
term: '延时摄影 (Timelapse)',
|
|
166
|
+
definition: '一种电影摄制技术,通过定期拍摄帧来加速时间,创造出快速移动的效果。'
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
term: '字幕同步',
|
|
170
|
+
definition: '将字幕的开始/结束时间与电影或剧集的音频及视频对齐的过程。'
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
term: '元数据 (Metadata)',
|
|
174
|
+
definition: '媒体文件中描述内容的隐藏信息(作者、创建日期、所用设备、地点等)。'
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'diagnostic',
|
|
180
|
+
variant: 'info',
|
|
181
|
+
title: '如何选择正确的工具',
|
|
182
|
+
icon: 'mdi:help-circle',
|
|
183
|
+
badge: '选择指南',
|
|
184
|
+
html: '<strong>正在创建延时摄影?</strong> -> 使用延时摄影计算器。<br><strong>需要保护隐私?</strong> -> 元数据清理工具。<br><strong>正在处理字幕?</strong> -> 字幕同步与编辑器。<br><strong>需要优化图像?</strong> -> 分辨率和观看距离计算器。'
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
type: 'card',
|
|
188
|
+
title: '核心功能',
|
|
189
|
+
html: '我们所有的工具都在您的浏览器中 <strong>100% 本地</strong>运行。这意味着最高限度的隐私保护、即时的响应速度以及(初次加载后的)离线访问。'
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
type: 'message',
|
|
193
|
+
title: '隐私保护',
|
|
194
|
+
ariaLabel: '关于隐私和数据存储的信息',
|
|
195
|
+
html: '我们不存储、处理或共享您的音视频数据。所有计算和元数据清理工作仅在您的设备上进行。您对自己的内容拥有完全的控制权。'
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
};
|
package/src/category/index.ts
CHANGED
|
@@ -1,17 +1,45 @@
|
|
|
1
1
|
import type { AudiovisualCategoryEntry, AudiovisualToolEntry } from '../types';
|
|
2
2
|
import { timelapseCalculator } from '../tool/timelapseCalculator/index';
|
|
3
3
|
import { exifCleaner } from '../tool/exifCleaner/index';
|
|
4
|
+
import { subtitleSync } from '../tool/subtitleSync/index';
|
|
5
|
+
import { privacyBlur } from '../tool/privacyBlur/index';
|
|
6
|
+
import { chromaticLens } from '../tool/chromaticLens/index';
|
|
7
|
+
import { printQualityCalculator } from '../tool/printQualityCalculator/index';
|
|
8
|
+
import { tvDistance } from '../tool/tvDistance/index';
|
|
9
|
+
import { imageCompressor } from '../tool/imageCompressor/index';
|
|
10
|
+
import { collageMaker } from '../tool/collageMaker/index';
|
|
11
|
+
import { videoFrameExtractor } from '../tool/videoFrameExtractor/index';
|
|
4
12
|
|
|
5
13
|
export const audiovisualCategory: AudiovisualCategoryEntry = {
|
|
6
14
|
icon: 'mdi:camera-iris',
|
|
7
15
|
tools: [
|
|
8
16
|
timelapseCalculator as AudiovisualToolEntry,
|
|
9
17
|
exifCleaner as AudiovisualToolEntry,
|
|
18
|
+
subtitleSync as AudiovisualToolEntry,
|
|
19
|
+
privacyBlur as AudiovisualToolEntry,
|
|
20
|
+
chromaticLens as AudiovisualToolEntry,
|
|
21
|
+
printQualityCalculator as AudiovisualToolEntry,
|
|
22
|
+
tvDistance as AudiovisualToolEntry,
|
|
23
|
+
imageCompressor as AudiovisualToolEntry,
|
|
24
|
+
collageMaker as AudiovisualToolEntry,
|
|
25
|
+
videoFrameExtractor as AudiovisualToolEntry,
|
|
10
26
|
],
|
|
11
27
|
i18n: {
|
|
12
|
-
es: () => import('./i18n/es')
|
|
13
|
-
en: () => import('./i18n/en')
|
|
14
|
-
fr: () => import('./i18n/fr')
|
|
28
|
+
es: async () => (await import('./i18n/es')).content,
|
|
29
|
+
en: async () => (await import('./i18n/en')).content,
|
|
30
|
+
fr: async () => (await import('./i18n/fr')).content,
|
|
31
|
+
de: async () => (await import('./i18n/de')).content,
|
|
32
|
+
it: async () => (await import('./i18n/it')).content,
|
|
33
|
+
pt: async () => (await import('./i18n/pt')).content,
|
|
34
|
+
id: async () => (await import('./i18n/id')).content,
|
|
35
|
+
ja: async () => (await import('./i18n/ja')).content,
|
|
36
|
+
ko: async () => (await import('./i18n/ko')).content,
|
|
37
|
+
nl: async () => (await import('./i18n/nl')).content,
|
|
38
|
+
pl: async () => (await import('./i18n/pl')).content,
|
|
39
|
+
ru: async () => (await import('./i18n/ru')).content,
|
|
40
|
+
sv: async () => (await import('./i18n/sv')).content,
|
|
41
|
+
tr: async () => (await import('./i18n/tr')).content,
|
|
42
|
+
zh: async () => (await import('./i18n/zh')).content,
|
|
15
43
|
},
|
|
16
44
|
};
|
|
17
45
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ALL_TOOLS } from '../tools';
|
|
3
|
+
|
|
4
|
+
const EXPECTED_LOCALES = [
|
|
5
|
+
'de', 'en', 'es', 'fr', 'id', 'it', 'ja', 'ko', 'nl', 'pl', 'pt', 'ru', 'sv', 'tr', 'zh'
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
describe('I18n Coverage Validation', () => {
|
|
9
|
+
it('all tools should be registered', () => {
|
|
10
|
+
expect(ALL_TOOLS.length).toBeGreaterThan(0);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
ALL_TOOLS.forEach(({ entry }: { entry: any }) => {
|
|
14
|
+
describe(`Tool: ${entry.id}`, () => {
|
|
15
|
+
it('should have all 15 required locales', () => {
|
|
16
|
+
const registeredLocales = Object.keys(entry.i18n);
|
|
17
|
+
EXPECTED_LOCALES.forEach((locale) => {
|
|
18
|
+
expect(
|
|
19
|
+
registeredLocales,
|
|
20
|
+
`Tool "${entry.id}" is missing locale "${locale}"`,
|
|
21
|
+
).toContain(locale);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('all locale loaders should be functions', () => {
|
|
26
|
+
EXPECTED_LOCALES.forEach((locale) => {
|
|
27
|
+
const loader = entry.i18n[locale as keyof typeof entry.i18n];
|
|
28
|
+
expect(
|
|
29
|
+
typeof loader,
|
|
30
|
+
`Tool "${entry.id}" locale "${locale}" loader is not a function`,
|
|
31
|
+
).toBe('function');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ALL_TOOLS } from '../tools';
|
|
3
|
+
import type { ToolLocaleContent } from '../types';
|
|
4
|
+
|
|
5
|
+
describe('Schemas Fulfillment Validation', () => {
|
|
6
|
+
ALL_TOOLS.forEach((tool) => {
|
|
7
|
+
describe(`Tool: ${tool.entry.id}`, () => {
|
|
8
|
+
Object.keys(tool.entry.i18n).forEach((locale) => {
|
|
9
|
+
it(`Locale: ${locale} should have faqSchema, appSchema and howToSchema`, async () => {
|
|
10
|
+
const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
|
|
11
|
+
if (!loader) return;
|
|
12
|
+
const content = (await loader()) as ToolLocaleContent;
|
|
13
|
+
|
|
14
|
+
const schemaTypes = content.schemas.map((s: any) => s['@type']);
|
|
15
|
+
|
|
16
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing FAQPage schema`).toContain('FAQPage');
|
|
17
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing SoftwareApplication schema`).toContain('SoftwareApplication');
|
|
18
|
+
expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing HowTo schema`).toContain('HowTo');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
function getFiles(dir: string, ext: string[]): string[] {
|
|
6
|
+
const results: string[] = [];
|
|
7
|
+
if (!fs.existsSync(dir)) return results;
|
|
8
|
+
const list = fs.readdirSync(dir);
|
|
9
|
+
for (const file of list) {
|
|
10
|
+
const fullPath = path.join(dir, file);
|
|
11
|
+
const stat = fs.statSync(fullPath);
|
|
12
|
+
if (stat && stat.isDirectory()) {
|
|
13
|
+
results.push(...getFiles(fullPath, ext));
|
|
14
|
+
} else if (ext.some((e) => file.endsWith(e))) {
|
|
15
|
+
results.push(fullPath);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return results;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const SRC_DIR = path.join(process.cwd(), 'src');
|
|
22
|
+
|
|
23
|
+
describe('Project Titles - Separator Validation', () => {
|
|
24
|
+
const files = [
|
|
25
|
+
...getFiles(path.join(SRC_DIR, 'tool'), ['.ts']),
|
|
26
|
+
...getFiles(path.join(SRC_DIR, 'category'), ['.ts']),
|
|
27
|
+
].filter(f => f.includes('i18n'));
|
|
28
|
+
|
|
29
|
+
it.each(files)('Verify that titles in %s do not contain | or -', (filePath) => {
|
|
30
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
31
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
32
|
+
|
|
33
|
+
const titlePatterns = [
|
|
34
|
+
/const\s+title\s*=\s*['"]([^'"]+)['"]/g,
|
|
35
|
+
/title\s*:\s*['"]([^'"]+)['"]/g,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const findings: string[] = [];
|
|
39
|
+
|
|
40
|
+
for (const pattern of titlePatterns) {
|
|
41
|
+
let match;
|
|
42
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
43
|
+
const title = match[1];
|
|
44
|
+
if (title.includes('|') || title.includes('-')) {
|
|
45
|
+
findings.push(title);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (findings.length > 0) {
|
|
51
|
+
const list = findings.map((f) => ` - "${f}"`).join('\n');
|
|
52
|
+
throw new Error(`Forbidden separators (| or -) found in titles in ${relativePath}:\n${list}`);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
|
+
|
|
4
|
+
const slug = 'chromatic-lens-farbpaletten-extraktion-online';
|
|
5
|
+
const title = 'Chromatic Lens: Online Extraktion von Farbpaletten';
|
|
6
|
+
const description = 'Extrahieren Sie kostenlos professionelle Farbpaletten aus jedem Bild. Identifizieren Sie dominante Farben in Ihren Fotos mithilfe mathematischer Algorithmen.';
|
|
7
|
+
|
|
8
|
+
const ui: ChromaticLensUI = {
|
|
9
|
+
dropTitle: "Farben analysieren",
|
|
10
|
+
dropSubtitle: "Ziehen Sie ein Bild hierher, um seine chromatische DNA zu extrahieren.",
|
|
11
|
+
processingLabel: "Palette wird extrahiert...",
|
|
12
|
+
paletteTitle: "Extrahierte Palette",
|
|
13
|
+
copyLabel: "HEX kopieren",
|
|
14
|
+
copiedLabel: "Kopiert!",
|
|
15
|
+
colorCountLabel: "Anzahl der Farben",
|
|
16
|
+
changeImage: "Bild ändern",
|
|
17
|
+
faqTitle: "Häufig gestellte Fragen zur Farbetraktion",
|
|
18
|
+
bibliographyTitle: "Ressourcen und technische Dokumentation"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const faq: ChromaticLensLocaleContent['faq'] = [
|
|
22
|
+
{
|
|
23
|
+
question: "Wie funktioniert die Farbetraktion?",
|
|
24
|
+
answer: "Wir verwenden den 'Median Cut' Algorithmus, der Bildpixel basierend auf ihrer Nähe im RGB-Farbraum gruppiert, um die repräsentativsten Töne zu finden.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: "Kann ich Farben in meinen Design-Editor kopieren?",
|
|
28
|
+
answer: "Ja, durch Klicken auf jede Farbe wird der HEX-Code automatisch in Ihre Zwischenablage kopiert, bereit zum Einfügen in Photoshop, Figma oder CSS.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
question: "Welche Bildtypen kann ich analysieren?",
|
|
32
|
+
answer: "Jede JPG-, PNG- oder WebP-Datei. Die Verarbeitung erfolgt lokal, sodass auch große Bilder schnell ohne Netzwerkkosten analysiert werden.",
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const howTo: ChromaticLensLocaleContent['howTo'] = [
|
|
37
|
+
{
|
|
38
|
+
name: "Bild hochladen",
|
|
39
|
+
text: "Laden Sie das Foto hoch, aus dem Sie chromatische Inspiration extrahieren möchten.",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "Präzision anpassen",
|
|
43
|
+
text: "Wählen Sie aus, wie viele dominante Farben das Tool identifizieren soll (von 3 bis 12).",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "Ergebnis analysieren",
|
|
47
|
+
text: "Die Palette erscheint sofort mit den entsprechenden Hexadezimal Codes.",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "Kopieren und verwenden",
|
|
51
|
+
text: "Klicken Sie auf die Töne, um sie zu speichern und in Ihrem Designprojekt anzuwenden.",
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const bibliography: ChromaticLensLocaleContent['bibliography'] = [
|
|
56
|
+
{
|
|
57
|
+
name: "Median Cut Algorithm - Wikipedia",
|
|
58
|
+
url: "https://en.wikipedia.org/wiki/Median_cut",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "Farblehre für Designer",
|
|
62
|
+
url: "https://www.smashingmagazine.com/2010/01/color-theory-for-designers-part-1-the-meaning-of-color/",
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const seo: ChromaticLensLocaleContent['seo'] = [
|
|
67
|
+
{
|
|
68
|
+
type: 'summary',
|
|
69
|
+
title: 'Intelligente Extraktion von Farbpaletten',
|
|
70
|
+
items: [
|
|
71
|
+
'Professioneller Median-Cut-Algorithmus zur Farbanalyse',
|
|
72
|
+
'Extraktion von 3–12 dominanten Farben aus jedem Bild',
|
|
73
|
+
'HEX-Codes direkt in die Zwischenablage kopierbar',
|
|
74
|
+
'100% lokale Verarbeitung – ideal für Kreative'
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{ type: 'title', text: 'Farbetraktion: Wissenschaft und Design', level: 2 },
|
|
78
|
+
{ type: 'paragraph', html: 'Haben Sie sich jemals gefragt, warum ein Filmfoto so harmonisch wirkt? Das ist kein Zufall, sondern angewandte Farblehre. Chromatic Lens ermöglicht es Ihnen, diese Harmonie direkt aus den Pixeln zu extrahieren und in HEX-Codes umzuwandeln, die Sie in Ihren Designprojekten verwenden können.' },
|
|
79
|
+
|
|
80
|
+
{ type: 'stats', items: [
|
|
81
|
+
{ value: 'Sofort', label: 'Farbanalyse', icon: 'mdi:lightning-bolt' },
|
|
82
|
+
{ value: '100%', label: 'Lokale Privatsphäre', icon: 'mdi:lock' },
|
|
83
|
+
{ value: 'RGB', label: 'Präziser Farbraum', icon: 'mdi:palette' }
|
|
84
|
+
], columns: 3 },
|
|
85
|
+
|
|
86
|
+
{ type: 'title', text: 'Der Median Cut Algorithmus erklärt', level: 3 },
|
|
87
|
+
{ type: 'paragraph', html: 'Die intelligente Palettenextraktion ist keine einfache Zufallsauswahl von Pixeln. Sie nutzt den Median-Cut-Algorithmus, eine rekursive Zerlegungstechnik, die eine originalgetreue Darstellung gewährleistet:' },
|
|
88
|
+
{ type: 'list', items: [
|
|
89
|
+
'<strong>Rekursive Teilung:</strong> Der RGB-\"Farbwürfel\" des Bildes wird rekursiv in kleinere Boxen unterteilt.',
|
|
90
|
+
'<strong>Volumen-Balance:</strong> Jede Partition sucht nach Gruppen von Pixeln aus dem gleichen Farbraum mit ähnlichen Volumina.',
|
|
91
|
+
'<strong>Gewichteter Durchschnitt:</strong> Die resultierende Farbe jeder Box ist der Durchschnitt aller darin enthaltenen Pixel.',
|
|
92
|
+
'<strong>Originalgetreue Darstellung:</strong> Die dominanten Farben spiegeln die reale visuelle Atmosphäre des Bildes wider, nicht nur eine simple Stichprobe.'
|
|
93
|
+
], icon: 'mdi:check' },
|
|
94
|
+
|
|
95
|
+
{ type: 'card', title: 'Kreativer Workflow', html: 'Ideal für Webentwickler, UX/UI-Designer, digitale Künstler und Kreative, die die visuelle Essenz eines Fotos, Films oder einer Vorlage sofort erfassen möchten, um sie in ihren Interfaces, Illustrationen oder Markenpaletten anzuwenden.' },
|
|
96
|
+
|
|
97
|
+
{ type: 'title', text: 'Anwendungsfälle im digitalen Design', level: 3 },
|
|
98
|
+
{ type: 'comparative', items: [
|
|
99
|
+
{
|
|
100
|
+
title: 'UX/UI Designer',
|
|
101
|
+
description: 'Paletten aus Hero-Images extrahieren, um stimmige Interfaces zu erstellen',
|
|
102
|
+
icon: 'mdi:palette',
|
|
103
|
+
points: [
|
|
104
|
+
'Harmonische Hintergrundfarben',
|
|
105
|
+
'Buttons und sekundäre Elemente',
|
|
106
|
+
'Automatisch berechneter Kontrast'
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
title: 'Webentwickler',
|
|
111
|
+
description: 'CSS-Stylesheets direkt aus visuellen Referenzen erstellen',
|
|
112
|
+
icon: 'mdi:code-braces',
|
|
113
|
+
points: [
|
|
114
|
+
'HEX direkt in CSS kopieren',
|
|
115
|
+
'Farbvariablen in SCSS/CSS',
|
|
116
|
+
'Konsistente Themes ohne vorheriges Design'
|
|
117
|
+
],
|
|
118
|
+
highlight: true
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
title: 'Digitale Künstler und Illustratoren',
|
|
122
|
+
description: 'Chromatische Referenzen aus Filmen, Natur oder Kunst einfangen',
|
|
123
|
+
icon: 'mdi:brush',
|
|
124
|
+
points: [
|
|
125
|
+
'Referenzpaletten aus Meisterwerken',
|
|
126
|
+
'Cineastische Farbstudien',
|
|
127
|
+
'Sofortige visuelle Inspiration'
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
title: 'Branding Spezialisten',
|
|
132
|
+
description: 'Visuelle Identitäten basierend auf Beispielfotos entwickeln',
|
|
133
|
+
icon: 'mdi:tag-multiple',
|
|
134
|
+
points: [
|
|
135
|
+
'Markenfarben aus Bildern extrahieren',
|
|
136
|
+
'Professionelle Farb-Guides erstellen',
|
|
137
|
+
'Visuelle Konsistenz gewährleisten'
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
], columns: 2 },
|
|
141
|
+
|
|
142
|
+
{ type: 'title', text: 'Angewandte Farblehre', level: 3 },
|
|
143
|
+
{ type: 'table', headers: ['Farbkonzept', 'Definition', 'Praktische Anwendung'], rows: [
|
|
144
|
+
['Farharmonie', 'Farbkombination, die visuell ausgewogen ist', 'Konsistente visuelle Identität im UI'],
|
|
145
|
+
['Kontrast', 'Helligkeitsunterschied zwischen Farben', 'Lesbarkeit und visuelle Hierarchie'],
|
|
146
|
+
['Sättigung', 'Farbintensität eines Tons', 'Professionalität (niedrig) vs. Energie (hoch)'],
|
|
147
|
+
['Farbtemperatur', 'Warme Farben (Rot) vs. kühle Farben (Blau)', 'Emotionspsychologie im Design'],
|
|
148
|
+
['Monochromatische Palette', 'Variationen eines einzelnen Tons', 'Eleganz und Minimalismus']
|
|
149
|
+
] },
|
|
150
|
+
|
|
151
|
+
{ type: 'proscons', items: [
|
|
152
|
+
{
|
|
153
|
+
pro: 'Mathematische Präzision bei der Extraktion – keine ungefähre visuelle Auswahl',
|
|
154
|
+
con: 'Kaum sichtbare Farben können enthalten sein, wenn sie viele Pixel haben'
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
pro: 'Sofortiges Kopieren in die Zwischenablage – perfekte Integration in den Workflow',
|
|
158
|
+
con: 'Benötigt einen modernen Browser, der mit der Canvas-API kompatibel ist'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
pro: 'Vollständige Privatsphäre – 100% lokale Analyse ohne Datenübermittlung',
|
|
162
|
+
con: 'Kein Verlauf früherer Analysen gespeichert'
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
pro: 'Kompatibel mit jedem digitalen Bildformat',
|
|
166
|
+
con: 'Endgültige Farben hängen von der Bildkompression und Qualität ab'
|
|
167
|
+
}
|
|
168
|
+
], proTitle: 'Vorteile', conTitle: 'Einschränkungen' },
|
|
169
|
+
|
|
170
|
+
{ type: 'diagnostic', variant: 'success', title: 'Realistische Farbdarstellung', icon: 'mdi:check-circle-outline', badge: 'Fortgeschrittener Algorithmus', html: 'Im Gegensatz zu Tools, die einfach zufällige Pixel abfragen, verwendet unser System den Median-Cut-Algorithmus, der die gesamte Pixelanzahl jedes Tons gewichtet. So wird sichergestellt, dass die resultierende Palette die visuelle Atmosphäre und Farbpsychologie des Originalbildes originalgetreu widerspiegelt.' },
|
|
171
|
+
|
|
172
|
+
{ type: 'glossary', items: [
|
|
173
|
+
{
|
|
174
|
+
term: 'Median Cut',
|
|
175
|
+
definition: 'Farbauswahl-Algorithmus, der den RGB-Raum rekursiv in Boxen unterteilt und so eine gleichmäßige Verteilung gewährleistet. Historisch für GIF- und indizierte Farbtechnologien genutzt.'
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
term: 'RGB-Farbraum',
|
|
179
|
+
definition: 'Farbmodell basierend auf Rot, Grün und Blau. Jede Farbe wird als Kombination dieser drei Werte (0–255) dargestellt. Standard für Bildschirme und Web.'
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
term: 'HEX-Code',
|
|
183
|
+
definition: '6-stellige hexadezimale Notation (#RRGGBB) zur Darstellung von Farben im Web: #FF0000 (Rot), #00FF00 (Grün), #0000FF (Blau). Universell in CSS, Figma und Adobe.'
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
term: 'Farbsättigung',
|
|
187
|
+
definition: 'Intensität oder Reinheit der Farbe. Hohe Sättigung = lebendige Farbe; niedrige Sättigung = gräuliche Farbe. Beeinflusst die emotionale Wahrnehmung.'
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
term: 'Farbharmonie',
|
|
191
|
+
definition: 'Auswahl und Kombination von Farben, die zu einem visuell ansprechenden Ergebnis führen. Kann monochromatisch, komplementär, analog oder triadisch sein.'
|
|
192
|
+
}
|
|
193
|
+
] },
|
|
194
|
+
|
|
195
|
+
{ type: 'message', title: 'Professionelle Farbanalyse', ariaLabel: 'Technische Informationen zur Farbanalyse', html: 'Chromatic Lens verwandelt manuelle visuelle Analyse in algorithmische Präzision. Es extrahiert nicht nur Farben: Es fängt die emotionale und visuelle Essenz jedes Bildes ein und legt sie als einsatzbereite HEX-Codes direkt in Ihre Zwischenablage. Volle Privatsphäre, keine Limits.' },
|
|
196
|
+
|
|
197
|
+
{ type: 'title', text: 'Design aus visueller Inspiration', level: 3 },
|
|
198
|
+
{ type: 'paragraph', html: 'Die beste Farbpalette ist diejenige, die die visuelle Absicht Ihrer Referenz einfängt. Chromatic Lens automatisiert den ehemals manuellen Prozess: beobachten, analysieren, notieren. Jetzt ziehen Sie einfach ein Bild und erhalten in Sekunden professionelle HEX-Codes.' }
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
202
|
+
'@context': 'https://schema.org',
|
|
203
|
+
'@type': 'FAQPage',
|
|
204
|
+
mainEntity: faq.map((item) => ({
|
|
205
|
+
'@type': 'Question',
|
|
206
|
+
name: item.question,
|
|
207
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
208
|
+
})),
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const howToSchema: WithContext<HowTo> = {
|
|
212
|
+
'@context': 'https://schema.org',
|
|
213
|
+
'@type': 'HowTo',
|
|
214
|
+
name: title,
|
|
215
|
+
description,
|
|
216
|
+
step: howTo.map((step) => ({
|
|
217
|
+
'@type': 'HowToStep',
|
|
218
|
+
name: step.name,
|
|
219
|
+
text: step.text,
|
|
220
|
+
})),
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
224
|
+
'@context': 'https://schema.org',
|
|
225
|
+
'@type': 'SoftwareApplication',
|
|
226
|
+
name: title,
|
|
227
|
+
description,
|
|
228
|
+
applicationCategory: 'UtilitiesApplication',
|
|
229
|
+
operatingSystem: 'Web',
|
|
230
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
231
|
+
inLanguage: 'de',
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export const content: ChromaticLensLocaleContent = {
|
|
235
|
+
slug,
|
|
236
|
+
title,
|
|
237
|
+
description,
|
|
238
|
+
ui,
|
|
239
|
+
seo,
|
|
240
|
+
faqTitle: "Häufig gestellte Fragen",
|
|
241
|
+
faq,
|
|
242
|
+
bibliographyTitle: "Referenzen",
|
|
243
|
+
bibliography,
|
|
244
|
+
howTo,
|
|
245
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
246
|
+
};
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'chromatic-lens-color-palette-extraction-online';
|
|
5
|
-
const title = 'Chromatic Lens
|
|
5
|
+
const title = 'Chromatic Lens: Online Color Palette Extraction';
|
|
6
6
|
const description = 'Extract professional color palettes from any image for free. Identify dominant colors in your photos using mathematical algorithms.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'lente-cromatica';
|
|
5
|
-
const title = 'Lente Cromática
|
|
5
|
+
const title = 'Lente Cromática: Extracción de Paletas de Color Online';
|
|
6
6
|
const description = 'Extrae paletas de colores profesionales de cualquier imagen de forma gratuita. Identifica los colores dominantes de tus fotos mediante algoritmos matemáticos.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|
|
@@ -2,7 +2,7 @@ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dt
|
|
|
2
2
|
import type { ChromaticLensUI, ChromaticLensLocaleContent } from '../index';
|
|
3
3
|
|
|
4
4
|
const slug = 'lentille-chromatique-extraction-palette-couleurs-ligne';
|
|
5
|
-
const title = 'Lentille Chromatique
|
|
5
|
+
const title = 'Lentille Chromatique: Extraction de Palette de Couleurs en Ligne';
|
|
6
6
|
const description = 'Extrayez gratuitement des palettes de couleurs professionnelles à partir de n\'importe quelle image. Identifiez les couleurs dominantes à l\'aide d\'algorithmes mathématiques.';
|
|
7
7
|
|
|
8
8
|
const ui: ChromaticLensUI = {
|