@jjlmoya/utils-creative 1.21.0 → 1.23.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 (107) hide show
  1. package/package.json +5 -3
  2. package/src/category/i18n/de.ts +1 -1
  3. package/src/category/i18n/ru.ts +1 -1
  4. package/src/layouts/PreviewLayout.astro +7 -2
  5. package/src/tests/diacritics_density.test.ts +118 -0
  6. package/src/tests/inverted_punctuation.test.ts +84 -0
  7. package/src/tests/no_en_dash.test.ts +70 -0
  8. package/src/tests/pagespeed_best_practices.test.ts +198 -0
  9. package/src/tests/script_density.test.ts +94 -0
  10. package/src/tests/seo_parity.test.ts +60 -0
  11. package/src/tests/translation_copy.test.ts +124 -0
  12. package/src/tool/bead-pattern-generator/component.astro +2 -2
  13. package/src/tool/bead-pattern-generator/i18n/de.ts +2 -2
  14. package/src/tool/bead-pattern-generator/i18n/en.ts +2 -2
  15. package/src/tool/bead-pattern-generator/i18n/es.ts +3 -10
  16. package/src/tool/bead-pattern-generator/i18n/fr.ts +3 -3
  17. package/src/tool/bead-pattern-generator/i18n/id.ts +2 -2
  18. package/src/tool/bead-pattern-generator/i18n/it.ts +2 -2
  19. package/src/tool/bead-pattern-generator/i18n/ja.ts +2 -2
  20. package/src/tool/bead-pattern-generator/i18n/ko.ts +2 -2
  21. package/src/tool/bead-pattern-generator/i18n/nl.ts +2 -2
  22. package/src/tool/bead-pattern-generator/i18n/pl.ts +2 -2
  23. package/src/tool/bead-pattern-generator/i18n/pt.ts +2 -2
  24. package/src/tool/bead-pattern-generator/i18n/ru.ts +6 -6
  25. package/src/tool/bead-pattern-generator/i18n/sv.ts +2 -2
  26. package/src/tool/bead-pattern-generator/i18n/tr.ts +2 -2
  27. package/src/tool/bead-pattern-generator/i18n/zh.ts +5 -5
  28. package/src/tool/dice-roller/bibliography.ts +3 -3
  29. package/src/tool/dice-roller/i18n/de.ts +10 -10
  30. package/src/tool/dice-roller/i18n/en.ts +10 -10
  31. package/src/tool/dice-roller/i18n/es.ts +15 -17
  32. package/src/tool/dice-roller/i18n/fr.ts +16 -16
  33. package/src/tool/dice-roller/i18n/id.ts +10 -10
  34. package/src/tool/dice-roller/i18n/it.ts +9 -9
  35. package/src/tool/dice-roller/i18n/ja.ts +7 -7
  36. package/src/tool/dice-roller/i18n/ko.ts +8 -8
  37. package/src/tool/dice-roller/i18n/nl.ts +10 -10
  38. package/src/tool/dice-roller/i18n/pl.ts +9 -9
  39. package/src/tool/dice-roller/i18n/pt.ts +10 -10
  40. package/src/tool/dice-roller/i18n/ru.ts +16 -16
  41. package/src/tool/dice-roller/i18n/sv.ts +10 -10
  42. package/src/tool/dice-roller/i18n/tr.ts +8 -8
  43. package/src/tool/dice-roller/i18n/zh.ts +14 -14
  44. package/src/tool/excuse-generator/i18n/de.ts +5 -5
  45. package/src/tool/excuse-generator/i18n/es.ts +0 -6
  46. package/src/tool/excuse-generator/i18n/fr.ts +2 -2
  47. package/src/tool/excuse-generator/i18n/pl.ts +5 -5
  48. package/src/tool/excuse-generator/i18n/ru.ts +5 -5
  49. package/src/tool/excuse-generator/i18n/zh.ts +7 -7
  50. package/src/tool/fortune-cookie/component.astro +7 -10
  51. package/src/tool/fortune-cookie/i18n/de.ts +4 -4
  52. package/src/tool/fortune-cookie/i18n/en.ts +4 -4
  53. package/src/tool/fortune-cookie/i18n/es.ts +0 -5
  54. package/src/tool/fortune-cookie/i18n/fr.ts +5 -5
  55. package/src/tool/fortune-cookie/i18n/id.ts +4 -4
  56. package/src/tool/fortune-cookie/i18n/it.ts +1 -1
  57. package/src/tool/fortune-cookie/i18n/nl.ts +4 -4
  58. package/src/tool/fortune-cookie/i18n/pl.ts +4 -4
  59. package/src/tool/fortune-cookie/i18n/pt.ts +4 -4
  60. package/src/tool/fortune-cookie/i18n/ru.ts +15 -15
  61. package/src/tool/fortune-cookie/i18n/sv.ts +4 -4
  62. package/src/tool/fortune-cookie/i18n/tr.ts +3 -3
  63. package/src/tool/fortune-cookie/i18n/zh.ts +5 -5
  64. package/src/tool/glitch-image-distorter/component.astro +7 -7
  65. package/src/tool/glitch-image-distorter/i18n/de.ts +1 -1
  66. package/src/tool/glitch-image-distorter/i18n/en.ts +2 -2
  67. package/src/tool/glitch-image-distorter/i18n/fr.ts +3 -3
  68. package/src/tool/glitch-image-distorter/i18n/id.ts +1 -1
  69. package/src/tool/glitch-image-distorter/i18n/it.ts +1 -1
  70. package/src/tool/glitch-image-distorter/i18n/nl.ts +1 -1
  71. package/src/tool/glitch-image-distorter/i18n/pl.ts +1 -1
  72. package/src/tool/glitch-image-distorter/i18n/pt.ts +1 -1
  73. package/src/tool/glitch-image-distorter/i18n/ru.ts +11 -11
  74. package/src/tool/glitch-image-distorter/i18n/sv.ts +1 -1
  75. package/src/tool/glitch-image-distorter/i18n/tr.ts +1 -1
  76. package/src/tool/glitch-image-distorter/i18n/zh.ts +12 -12
  77. package/src/tool/synesthesia-painter/bibliography.ts +3 -3
  78. package/src/tool/synesthesia-painter/i18n/de.ts +12 -12
  79. package/src/tool/synesthesia-painter/i18n/en.ts +3 -3
  80. package/src/tool/synesthesia-painter/i18n/es.ts +5 -7
  81. package/src/tool/synesthesia-painter/i18n/fr.ts +8 -8
  82. package/src/tool/synesthesia-painter/i18n/id.ts +3 -3
  83. package/src/tool/synesthesia-painter/i18n/ja.ts +2 -2
  84. package/src/tool/synesthesia-painter/i18n/ko.ts +2 -2
  85. package/src/tool/synesthesia-painter/i18n/nl.ts +2 -2
  86. package/src/tool/synesthesia-painter/i18n/pl.ts +12 -12
  87. package/src/tool/synesthesia-painter/i18n/pt.ts +3 -3
  88. package/src/tool/synesthesia-painter/i18n/ru.ts +15 -15
  89. package/src/tool/synesthesia-painter/i18n/sv.ts +3 -3
  90. package/src/tool/synesthesia-painter/i18n/tr.ts +2 -2
  91. package/src/tool/synesthesia-painter/i18n/zh.ts +13 -13
  92. package/src/tool/zalgo-generator/component.astro +1 -1
  93. package/src/tool/zalgo-generator/i18n/de.ts +7 -7
  94. package/src/tool/zalgo-generator/i18n/en.ts +3 -3
  95. package/src/tool/zalgo-generator/i18n/es.ts +2 -9
  96. package/src/tool/zalgo-generator/i18n/fr.ts +7 -7
  97. package/src/tool/zalgo-generator/i18n/id.ts +3 -3
  98. package/src/tool/zalgo-generator/i18n/it.ts +2 -2
  99. package/src/tool/zalgo-generator/i18n/ja.ts +2 -2
  100. package/src/tool/zalgo-generator/i18n/ko.ts +2 -2
  101. package/src/tool/zalgo-generator/i18n/nl.ts +3 -3
  102. package/src/tool/zalgo-generator/i18n/pl.ts +7 -7
  103. package/src/tool/zalgo-generator/i18n/pt.ts +3 -3
  104. package/src/tool/zalgo-generator/i18n/ru.ts +7 -7
  105. package/src/tool/zalgo-generator/i18n/sv.ts +3 -3
  106. package/src/tool/zalgo-generator/i18n/tr.ts +3 -3
  107. package/src/tool/zalgo-generator/i18n/zh.ts +7 -7
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_ENTRIES } from '../entries';
3
+ import type { KnownLocale } from '../types';
4
+
5
+ interface ExpectedCounts {
6
+ seo: number;
7
+ faq: number;
8
+ howTo: number;
9
+ }
10
+
11
+ function countItems(arr: unknown[] | undefined): number {
12
+ return arr?.length ?? 0;
13
+ }
14
+
15
+ async function verifyLocaleParity(
16
+ entry: typeof ALL_ENTRIES[number],
17
+ loc: KnownLocale,
18
+ expected: ExpectedCounts,
19
+ ): Promise<void> {
20
+ const locContent = await entry.i18n[loc]?.();
21
+ expect(locContent, `Locale ${loc} missing content`).toBeDefined();
22
+
23
+ const locSeoCount = countItems(locContent?.seo);
24
+ const locFaqCount = countItems(locContent?.faq);
25
+ const locHowToCount = countItems(locContent?.howTo);
26
+
27
+ expect(
28
+ locSeoCount,
29
+ `Locale ${loc} SEO sections count (${locSeoCount}) must match EN (${expected.seo})`,
30
+ ).toBe(expected.seo);
31
+ expect(
32
+ locFaqCount,
33
+ `Locale ${loc} FAQ items count (${locFaqCount}) must match EN (${expected.faq})`,
34
+ ).toBe(expected.faq);
35
+ expect(
36
+ locHowToCount,
37
+ `Locale ${loc} HowTo steps count (${locHowToCount}) must match EN (${expected.howTo})`,
38
+ ).toBe(expected.howTo);
39
+ }
40
+
41
+ describe('SEO & i18n Structural Parity Suite', () => {
42
+ ALL_ENTRIES.forEach((entry) => {
43
+ describe(`Tool: ${entry.id}`, () => {
44
+ it('all 15 locales should have identical SEO section counts and types as English', async () => {
45
+ const enContent = await entry.i18n.en?.();
46
+ expect(enContent).toBeDefined();
47
+ const expected: ExpectedCounts = {
48
+ seo: countItems(enContent?.seo),
49
+ faq: countItems(enContent?.faq),
50
+ howTo: countItems(enContent?.howTo),
51
+ };
52
+
53
+ const locales = Object.keys(entry.i18n) as KnownLocale[];
54
+ for (const loc of locales) {
55
+ await verifyLocaleParity(entry, loc, expected);
56
+ }
57
+ });
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,124 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { ALL_ENTRIES } from '../entries';
3
+
4
+ const COPY_THRESHOLD = 0.9;
5
+
6
+ const STRUCTURAL_KEYS = new Set([
7
+ '@context',
8
+ '@type',
9
+ 'applicationCategory',
10
+ 'columns',
11
+ 'highlight',
12
+ 'icon',
13
+ 'level',
14
+ 'operatingSystem',
15
+ 'position',
16
+ 'positive',
17
+ 'price',
18
+ 'priceCurrency',
19
+ 'slug',
20
+ 'trend',
21
+ 'type',
22
+ 'url',
23
+ 'value',
24
+ 'variant',
25
+ ]);
26
+
27
+ function normalizeText(value: string): string {
28
+ return value
29
+ .replace(/<[^>]*>/g, ' ')
30
+ .replace(/&(?:amp|lt|gt|quot|apos|nbsp);/gi, ' ')
31
+ .replace(/[\u2018\u2019]/g, "'")
32
+ .replace(/[\u201c\u201d]/g, '"')
33
+ .replace(/\s+/g, ' ')
34
+ .trim()
35
+ .toLocaleLowerCase();
36
+ }
37
+
38
+ function collectText(value: unknown, path: string, parts: string[]): void {
39
+ if (typeof value === 'string') {
40
+ const normalized = normalizeText(value);
41
+ if (normalized.length >= 2) parts.push(normalized);
42
+ return;
43
+ }
44
+
45
+ if (Array.isArray(value)) {
46
+ value.forEach((item, index) => collectText(item, `${path}[${index}]`, parts));
47
+ return;
48
+ }
49
+
50
+ if (!value || typeof value !== 'object') return;
51
+
52
+ Object.entries(value).forEach(([key, child]) => {
53
+ if (STRUCTURAL_KEYS.has(key)) return;
54
+ collectText(child, `${path}.${key}`, parts);
55
+ });
56
+ }
57
+
58
+ function localeCorpus(content: unknown): string {
59
+ if (!content || typeof content !== 'object') return '';
60
+
61
+ const record = content as Record<string, unknown>;
62
+ const parts: string[] = [];
63
+ collectText(record.title, 'title', parts);
64
+ collectText(record.description, 'description', parts);
65
+ collectText(record.faqTitle, 'faqTitle', parts);
66
+ collectText(record.faq, 'faq', parts);
67
+ collectText(record.seo, 'seo', parts);
68
+ collectText(record.schemas, 'schemas', parts);
69
+ return parts.join(' ');
70
+ }
71
+
72
+ function tokenCounts(text: string): Map<string, number> {
73
+ const counts = new Map<string, number>();
74
+ for (const token of text.match(/[\p{L}\p{N}]+/gu) ?? []) {
75
+ counts.set(token, (counts.get(token) ?? 0) + 1);
76
+ }
77
+ return counts;
78
+ }
79
+
80
+ function copySimilarity(left: string, right: string): number {
81
+ const leftCounts = tokenCounts(left);
82
+ const rightCounts = tokenCounts(right);
83
+ const leftTotal = [...leftCounts.values()].reduce((sum, count) => sum + count, 0);
84
+ const rightTotal = [...rightCounts.values()].reduce((sum, count) => sum + count, 0);
85
+ if (leftTotal === 0 || rightTotal === 0) return 0;
86
+
87
+ let shared = 0;
88
+ for (const [token, count] of leftCounts) {
89
+ shared += Math.min(count, rightCounts.get(token) ?? 0);
90
+ }
91
+ return (2 * shared) / (leftTotal + rightTotal);
92
+ }
93
+
94
+ describe('Locales must not copy another locale wholesale', () => {
95
+ ALL_ENTRIES.forEach((entry) => {
96
+ it(`${entry.id} is not at least ${COPY_THRESHOLD * 100}% identical to another locale`, async () => {
97
+ const corpora = new Map<string, string>();
98
+
99
+ for (const [locale, loader] of Object.entries(entry.i18n)) {
100
+ if (!loader) continue;
101
+ corpora.set(locale, localeCorpus(await loader()));
102
+ }
103
+
104
+ const locales = [...corpora.keys()];
105
+ const violations: string[] = [];
106
+
107
+ for (let leftIndex = 0; leftIndex < locales.length; leftIndex += 1) {
108
+ for (let rightIndex = leftIndex + 1; rightIndex < locales.length; rightIndex += 1) {
109
+ const left = locales[leftIndex];
110
+ const right = locales[rightIndex];
111
+ const similarity = copySimilarity(corpora.get(left) ?? '', corpora.get(right) ?? '');
112
+
113
+ if (similarity >= COPY_THRESHOLD) {
114
+ violations.push(`${left} ↔ ${right}: ${(similarity * 100).toFixed(1)}%`);
115
+ }
116
+ }
117
+ }
118
+
119
+ expect(violations, `Locale copy threshold exceeded in ${entry.id}`).toEqual([]);
120
+ });
121
+ });
122
+ });
123
+
124
+
@@ -21,7 +21,7 @@ const { ui } = Astro.props;
21
21
 
22
22
  <div class="bead-controls">
23
23
  <div class="bead-control-group">
24
- <label class="bead-control-label">{ui.gridSizeLabel}</label>
24
+ <label class="bead-control-label" for="grid-width">{ui.gridSizeLabel}</label>
25
25
  <div class="bead-slider-row">
26
26
  <input type="range" id="grid-width" min="10" max="100" value="40" class="bead-slider bead-slider-pink" />
27
27
  <span id="grid-width-value" class="bead-slider-val bead-val-pink">40</span>
@@ -29,7 +29,7 @@ const { ui } = Astro.props;
29
29
  </div>
30
30
 
31
31
  <div class="bead-control-group">
32
- <label class="bead-control-label">{ui.colorCountLabel}</label>
32
+ <label class="bead-control-label" for="color-count">{ui.colorCountLabel}</label>
33
33
  <div class="bead-slider-row">
34
34
  <input type="range" id="color-count" min="2" max="32" value="12" class="bead-slider bead-slider-purple" />
35
35
  <span id="color-count-value" class="bead-slider-val bead-val-purple">12</span>
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro-Gaming:</strong> Authentische 8-Bit-Assets und Sprites in Sekunden.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Perlenbreite', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Farbpalettenplätze', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Perlenbreite', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Farbpalettenplätze', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Quantisierungsalgorithmus', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Exportformat (Muster + Anleitung)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> 8-bit authentic assets and sprites in seconds.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Bead width range', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Color palette slots', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Bead width range', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Color palette slots', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Quantization algorithm', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Export format (pattern + guide)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -96,20 +96,13 @@ export const content: BeadPatternGeneratorLocaleContent = {
96
96
  '<strong>Mosaicos:</strong> Murales de gran escala usando teselas cerámicas simplificadas.',
97
97
  '<strong>Retro Gaming:</strong> Assets y sprites con estética 8-bit auténtica en segundos.',
98
98
  ]},
99
- { type: 'paragraph', html: 'En una era de pantallas efímeras, crear algo físico es un acto revolucionario. Esta herramienta no busca automatizar el arte, sino <strong>empoderar al artesano</strong>. Te damos la precisión computacional para que tus manos puedan construir legados duraderos.' },
100
99
  { type: 'stats', items: [
101
- { value: '10100', label: 'Ancho del patrón (cuentas)', icon: 'mdi:arrow-expand-horizontal' },
102
- { value: '232', label: 'Colores en la paleta', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Ancho del patrón (cuentas)', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Colores en la paleta', icon: 'mdi:palette-swatch' },
103
102
  { value: 'K-Means', label: 'Algoritmo de cuantización', icon: 'mdi:function-variant' },
104
103
  { value: 'ZIP', label: 'Exportación (patrón + guía)', icon: 'mdi:zip-box' },
105
104
  ], columns: 4 },
106
- { type: 'glossary', items: [
107
- { term: 'Miyuki Delica', definition: 'Cuentas de cristal japonesas de alta precisión, cilíndricas y uniformes. Ideales para joyería y patrones geométricos complejos.' },
108
- { term: 'Hama Beads', definition: 'Cuentas de plástico que se fusionan con calor (plancha). Perfectas para proyectos de pixel art de gran formato.' },
109
- { term: 'Cuantización de color', definition: 'Proceso matemático para reducir los miles de colores de una imagen a una paleta limitada, manteniendo la fidelidad visual máxima posible.' },
110
- { term: 'Visión de túnel', definition: 'Modo de trabajo fila a fila que oscurece el resto del patrón para ayudar a concentrarse en la fila activa sin errores.' },
111
- { term: 'K-Means Clustering', definition: 'Algoritmo de aprendizaje no supervisado que agrupa píxeles por similitud cromática para encontrar los colores "centroide" de la imagen.' },
112
- ]},
105
+ { type: 'paragraph', html: 'En una era de pantallas efímeras, crear algo físico es un acto revolucionario. Esta herramienta no busca automatizar el arte, sino <strong>empoderar al artesano</strong>. Te damos la precisión computacional para que tus manos puedan construir legados duraderos.' },
113
106
  ],
114
107
  faq,
115
108
  bibliography,
@@ -81,7 +81,7 @@ export const content: BeadPatternGeneratorLocaleContent = {
81
81
  bibliographyTitle: 'Références'
82
82
  },
83
83
  seo: [
84
- { type: 'title', text: 'Alchimie Numérique : Transmutez les Pixels en Art Tangible', level: 2 },
84
+ { type: 'title', text: 'Alchimie Numérique: Transmutez les Pixels en Art Tangible', level: 2 },
85
85
  { type: 'paragraph', html: 'Bienvenue dans le <strong>Studio de Modèles Ultime</strong>. Un <em>moteur d\'intelligence chromatique</em> conçu pour les architectes du Pixel Art, les maîtres de la Miyuki et les visionnaires du point de croix. Votre pont entre le numérique et le fait-main.' },
86
86
  { type: 'card', icon: 'mdi:grid', title: 'La Grille Intelligente', html: 'Notre algorithme de <strong>sous-échantillonnage spatial</strong> ne se contente pas de "réduire" votre image. Il analyse la structure visuelle pour mapper des groupes de pixels complexes sur des cellules individuelles, préservant l\'intégrité des silhouettes et des contours comme le ferait un illustrateur expert.' },
87
87
  { type: 'card', icon: 'mdi:palette', title: 'Quantification de Couleurs K Means', html: 'Nous implémentons une variante de l\'algorithme <strong>K-Means Clustering</strong> qui trouve mathématiquement les tons "centroïdes" de votre image. Une fidélité visuelle étonnante avec une palette minimaliste de 12, 24 ou 32 couleurs.' },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming :</strong> Sprites et assets 8-bits authentiques en quelques secondes.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Largeur en perles', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Emplacements de palette', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Largeur en perles', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Emplacements de palette', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Algorithme de quantification', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Format d\'export (modèle + guide)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Aset dan sprite 8-bit otentik dalam hitungan detik.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Rentang lebar manik', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Slot palet warna', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Rentang lebar manik', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Slot palet warna', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Algoritma kuantisasi', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Format ekspor (pola + panduan)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Asset e sprite 8-bit autentici in pochi secondi.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Range larghezza perline', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Slot tavolozza colori', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Range larghezza perline', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Slot tavolozza colori', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Algoritmo quantizzazione', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Formato esportazione (schema + guida)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>レトロゲーム:</strong> 本物の8ビットアセットやスプライトを数秒で作成。',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'ビーズ幅の範囲', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'カラーパレット枠', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'ビーズ幅の範囲', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'カラーパレット枠', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: '減色アルゴリズム', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: '出力形式(図案+ガイド)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>레트로 게임:</strong> 정통 8비트 에셋 및 스프라이트를 단 몇 초 만에 제작.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: '비즈 너비 범위', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: '색상 팔레트 슬롯', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: '비즈 너비 범위', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: '색상 팔레트 슬롯', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: '양자화 알고리즘', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: '내보내기 형식 (도안 + 가이드)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Authentieke 8-bit assets en sprites in enkele seconden.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Kralenbreedte bereik', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Kleurpalet slots', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Kralenbreedte bereik', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Kleurpalet slots', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Kwantisatie-algoritme', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Exportformaat (patroon + gids)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Autentyczne 8-bitowe zasoby i sprite\'y w kilka sekund.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Zakres szerokości (koraliki)', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Liczba pól w palecie', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Zakres szerokości (koraliki)', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Liczba pól w palecie', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Średnich', label: 'Algorytm kwantyzacji', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Format eksportu (wzór + poradnik)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Assets e sprites 8-bit autênticos em segundos.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Intervalo de largura de contas', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Ranhuras de paleta de cores', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Intervalo de largura de contas', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Ranhuras de paleta de cores', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Algoritmo de quantização', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Formato de exportação (padrão + guia)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -9,7 +9,7 @@ const description = 'Создавайте пиксель-арт и схемы д
9
9
  const faq: BeadPatternGeneratorLocaleContent['faq'] = [
10
10
  { question: 'Что такое квантование цветов в схемах?', answer: 'Это процесс уменьшения тысяч цветов в фотографии до нескольких, соответствующих реальным доступным цветам бисера (например, Miyuki или Hama). Мы используем интеллектуальные алгоритмы для сохранения визуального сходства при минимальной палитре.' },
11
11
  { question: 'Можно ли использовать эту схему для вышивки крестом?', answer: 'Да, генератор создает сетчатую диаграмму, которая идеально подходит для вышивки крестиком. Вам просто нужно выбрать размер сетки, соответствующий вашей ткани (Aida 14, 18 и т. д.).' },
12
- { question: 'В чем разница между бисером Miyuki и Hama?', answer: 'Бисер Miyuki Delica это очень мелкий и точный стеклянный бисер для ювелирных изделий. Бисер Hama сделан из пластика и сплавляется утюгом. Наш инструмент позволяет настраивать соотношение сторон, чтобы схема не искажалась в зависимости от используемого материала.' },
12
+ { question: 'В чем разница между бисером Miyuki и Hama?', answer: 'Бисер Miyuki Delica - это очень мелкий и точный стеклянный бисер для ювелирных изделий. Бисер Hama сделан из пластика и сплавляется утюгом. Наш инструмент позволяет настраивать соотношение сторон, чтобы схема не искажалась в зависимости от используемого материала.' },
13
13
  { question: 'Как работает алгоритм дизеринга?', answer: 'Дизеринг создает иллюзию большего количества цветов путем смешивания пикселей разных цветов в разреженных паттернах. Это помогает цветовым градиентам выглядеть более плавными даже при ограниченной палитре бисера.' },
14
14
  ];
15
15
 
@@ -83,8 +83,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
83
83
  seo: [
84
84
  { type: 'title', text: 'Цифровая алхимия: превращение пикселей в осязаемое искусство', level: 2 },
85
85
  { type: 'paragraph', html: 'Добро пожаловать в <strong>Ultimate Pattern Studio</strong>. Это <em>движок хроматического интеллекта</em>, созданный для архитекторов пиксель-арта, мастеров Miyuki и визионеров вышивки крестом. Ваш мост между цифровым и рукотворным миром.' },
86
- { type: 'card', icon: 'mdi:grid', title: 'Интеллектуальная сетка', html: 'Наш алгоритм <strong>пространственного субсамплинга</strong> не просто «сжимает» ваше изображение. Он анализирует визуальную структуру, чтобы отобразить сложные группы пикселей на отдельные ячейки, сохраняя целостность силуэтов и краев, как это сделал бы опытный иллюстратор.' },
87
- { type: 'card', icon: 'mdi:palette', title: 'Квантование цвета методом K средних', html: 'Мы используем вариант алгоритма <strong>кластеризации K-средних</strong>, который математически находит «центроидные» тона вашего изображения. Потрясающая визуальная точность при минималистичной палитре из 12, 24 или 32 цветов.' },
86
+ { type: 'card', icon: 'mdi:grid', title: 'Интеллектуальная сетка', html: 'Наш алгоритм <strong>пространственного субсамплинга</strong> не просто \"сжимает\" ваше изображение. Он анализирует визуальную структуру, чтобы отобразить сложные группы пикселей на отдельные ячейки, сохраняя целостность силуэтов и краев, как это сделал бы опытный иллюстратор.' },
87
+ { type: 'card', icon: 'mdi:palette', title: 'Квантование цвета методом K средних', html: 'Мы используем вариант алгоритма <strong>кластеризации K-средних</strong>, который математически находит \"центроидные\" тона вашего изображения. Потрясающая визуальная точность при минималистичной палитре из 12, 24 или 32 цветов.' },
88
88
  { type: 'title', text: 'Мастерство в 3 шага', level: 3 },
89
89
  { type: 'card', icon: 'mdi:image-search', title: 'Идеальный выбор', html: 'Ищите <strong>высокий контраст</strong>, драматическое освещение и знаковые формы. Портреты с чистым фоном, логотипы и векторная графика переводятся великолепно.' },
90
90
  { type: 'card', icon: 'mdi:ruler', title: 'Размерная калибровка', html: '<strong>Miyuki Delica:</strong> 50 бисерин ≈ 8 см · <strong>Hama Midi:</strong> 50 бисерин ≈ 25 см · <strong>Вышивка крестом:</strong> 1 ячейка = 1 стежок.' },
@@ -97,12 +97,12 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Ретро-гейминг:</strong> аутентичные 8-битные ассеты и спрайты за считанные секунды.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Диапазон ширины в бисере', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Слоты цветовой палитры', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Диапазон ширины в бисере', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Слоты цветовой палитры', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Алгоритм квантования', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Формат экспорта (схема + гид)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
105
- { type: 'paragraph', html: 'В эпоху ускользающих экранов создание чего-то физического это революционный акт. Этот инструмент не стремится автоматизировать искусство, он призван <strong>расширить возможности мастера</strong>. Мы даем вам вычислительную точность, чтобы ваши руки могли создавать долговечное наследие.' },
105
+ { type: 'paragraph', html: 'В эпоху ускользающих экранов создание чего-то физического - это революционный акт. Этот инструмент не стремится автоматизировать искусство, он призван <strong>расширить возможности мастера</strong>. Мы даем вам вычислительную точность, чтобы ваши руки могли создавать долговечное наследие.' },
106
106
  ],
107
107
  faq,
108
108
  bibliography,
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Gaming:</strong> Autentiska 8-bitars tillgångar och sprites på några sekunder.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Breddintervall (pärlor)', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Färgpalettplatser', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Breddintervall (pärlor)', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Färgpalettplatser', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Kvantiseringsalgoritm', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Exportformat (mönster + guide)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>Retro Oyunlar:</strong> Saniyeler içinde otantik 8-bit varlıklar ve sprite\'lar.',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: 'Boncuk genişliği aralığı', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: 'Renk paleti yuvaları', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: 'Boncuk genişliği aralığı', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: 'Renk paleti yuvaları', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: 'Niceleme algoritması', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: 'Dışa aktarma formatı (desen + kılavuz)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -7,7 +7,7 @@ const title = '串珠图案生成器';
7
7
  const description = '根据您的照片生成适用于 Miyuki(米珠)或 Hama(拼拼豆豆)的像素艺术和串珠方案。包含颜色量化算法、隧道视野模式及 ZIP 导出功能。';
8
8
 
9
9
  const faq: BeadPatternGeneratorLocaleContent['faq'] = [
10
- { question: '图案生成中的“颜色量化”是什么?', answer: '这是将照片中成千上万种颜色减少到仅有的几种的过程,这些颜色对应于实际可用的珠子颜色(如 Miyuki 或 Hama)。我们使用智能算法,在保持视觉相似度的前提下尽可能减少调色板的颜色数量。' },
10
+ { question: '图案生成中的\"颜色量化\"是什么?', answer: '这是将照片中成千上万种颜色减少到仅有的几种的过程,这些颜色对应于实际可用的珠子颜色(如 Miyuki 或 Hama)。我们使用智能算法,在保持视觉相似度的前提下尽可能减少调色板的颜色数量。' },
11
11
  { question: '我可以将这个图案用于十字绣吗?', answer: '可以。生成器产生的网格图室与十字绣完美兼容。您只需选择与您的底布(如 Aida 14、18 等)匹配的网格大小。' },
12
12
  { question: 'Miyuki 米珠和 Hama 豆豆之间有什么区别?', answer: 'Miyuki Delica 米珠是用于珠宝制作的极小且精密的高品质玻璃珠。Hama 豆豆是塑料材质,通过熨斗加热融合。我们的工具允许您调整纵横比,确保图案不会因所选材质而变形。' },
13
13
  { question: '抖动(Dithering)算法是如何工作的?', answer: '抖动算法通过在稀疏图案中混合不同颜色的像素来创造更多颜色的错觉。即使在珠子调色板有限的情况下,它也能帮助颜色渐变看起来更平滑。' },
@@ -83,8 +83,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
83
83
  seo: [
84
84
  { type: 'title', text: '数字炼金术:将像素转化为触手可及的艺术', level: 2 },
85
85
  { type: 'paragraph', html: '欢迎来到<strong>终极图案工作室</strong>。这是一个专为像素艺术架构师、Miyuki 大师和十字绣远见者设计的<em>色彩智能引擎</em>。它是连接数字世界与手工艺术的桥梁。' },
86
- { type: 'card', icon: 'mdi:grid', title: '智能网格', html: '我们的<strong>空间下采样</strong>算法不仅是单纯地“缩小”图片。它会分析视觉结构,将复杂的像素群映射到单个单元格中,像专家插画师一样保留轮廓和边缘的完整性。' },
87
- { type: 'card', icon: 'mdi:palette', title: 'K Means 颜色量化', html: '我们采用了一种 <strong>K-Means 聚类</strong>算法的变体,通过数学计算找出图像的“主导”色调。即便在只有 12、24 或 32 色的极简调色板下,也能实现惊人的视觉忠实度。' },
86
+ { type: 'card', icon: 'mdi:grid', title: '智能网格', html: '我们的<strong>空间下采样</strong>算法不仅是单纯地\"缩小\"图片。它会分析视觉结构,将复杂的像素群映射到单个单元格中,像专家插画师一样保留轮廓和边缘的完整性。' },
87
+ { type: 'card', icon: 'mdi:palette', title: 'K Means 颜色量化', html: '我们采用了一种 <strong>K-Means 聚类</strong>算法的变体,通过数学计算找出图像的\"主导\"色调。即便在只有 12、24 或 32 色的极简调色板下,也能实现惊人的视觉忠实度。' },
88
88
  { type: 'title', text: '大师三部曲', level: 3 },
89
89
  { type: 'card', icon: 'mdi:image-search', title: '完美选择', html: '寻找<strong>高对比度</strong>、极具戏剧性的光影以及标志性形状。背景简单的肖像、Logo 和矢量艺术都能获得极佳的转换效果。' },
90
90
  { type: 'card', icon: 'mdi:ruler', title: '尺寸校准', html: '<strong>Miyuki Delica:</strong> 50 颗珠子 ≈ 8 厘米 · <strong>Hama Midi:</strong> 50 颗珠子 ≈ 25 厘米 · <strong>十字绣:</strong> 1 个单元格 = 1 针。' },
@@ -97,8 +97,8 @@ export const content: BeadPatternGeneratorLocaleContent = {
97
97
  '<strong>复古游戏:</strong> 数秒内即可生成地道的 8 位资产和精灵图。',
98
98
  ]},
99
99
  { type: 'stats', items: [
100
- { value: '10100', label: '珠子宽度范围', icon: 'mdi:arrow-expand-horizontal' },
101
- { value: '232', label: '调色板槽位', icon: 'mdi:palette-swatch' },
100
+ { value: '10-100', label: '珠子宽度范围', icon: 'mdi:arrow-expand-horizontal' },
101
+ { value: '2-32', label: '调色板槽位', icon: 'mdi:palette-swatch' },
102
102
  { value: 'K-Means', label: '量化算法', icon: 'mdi:function-variant' },
103
103
  { value: 'ZIP', label: '导出格式(图案 + 引导)', icon: 'mdi:zip-box' },
104
104
  ], columns: 4 },
@@ -1,5 +1,5 @@
1
1
  export const bibliography = [
2
- { name: 'D&D Beyond Dice mechanics rules', url: 'https://www.dndbeyond.com/sources/basic-rules/using-ability-scores' },
3
- { name: 'Roll20 Virtual tabletop and dice systems', url: 'https://roll20.net/' },
4
- { name: 'Pathfinder d20 System Reference', url: 'https://paizo.com/pathfinder' },
2
+ { name: 'D&D Beyond - Dice mechanics rules', url: 'https://www.dndbeyond.com/sources/basic-rules/using-ability-scores' },
3
+ { name: 'Roll20 - Virtual tabletop and dice systems', url: 'https://roll20.net/' },
4
+ { name: 'Pathfinder - d20 System Reference', url: 'https://paizo.com/pathfinder' },
5
5
  ];
@@ -95,17 +95,17 @@ export const content: DiceRollerLocaleContent = {
95
95
  },
96
96
  seo: [
97
97
  { type: 'title', text: 'Die Kunst des Zufalls: Geschichte und Mathematik der Würfel', level: 2 },
98
- { type: 'paragraph', html: 'Würfel gehören zu den ältesten Zufallsgeneratoren der Menschheit. <strong>Astragali</strong> Sprungbeine von Schafen und Ziegen wurden bereits 5000 v. Chr. in Mesopotamien und Ägypten als primitive vierseitige Würfel verwendet. Die Entwicklung vom geschnitzten Knochen bis hin zu modernen Ikosaedern aus Epoxidharz ist nicht nur ästhetischer Natur: Es ist eine Reise durch die Wahrscheinlichkeitstheorie und das Design von Spielmechaniken.' },
98
+ { type: 'paragraph', html: 'Würfel gehören zu den ältesten Zufallsgeneratoren der Menschheit. <strong>Astragali</strong> - Sprungbeine von Schafen und Ziegen - wurden bereits 5000 v. Chr. in Mesopotamien und Ägypten als primitive vierseitige Würfel verwendet. Die Entwicklung vom geschnitzten Knochen bis hin zu modernen Ikosaedern aus Epoxidharz ist nicht nur ästhetischer Natur: Es ist eine Reise durch die Wahrscheinlichkeitstheorie und das Design von Spielmechaniken.' },
99
99
  { type: 'title', text: 'Die Standard Würfelfamilie', level: 3 },
100
- { type: 'paragraph', html: 'Das am weitesten verbreitete Würfelset in Rollenspielen bekann gemacht durch <strong>Dungeons &amp; Dragons</strong> im Jahr 1974 besteht aus den fünf platonischen Körpern plus zwei zusätzlichen Formen: d4 (Tetraeder), d6 (Würfel), d8 (Oktaeder), d10 (Pentagonales Trapezoeder), d12 (Dodekaeder), d20 (Ikosaeder) und d100 (Prozentwürfel). Jedes Polyeder garantiert eine Gleichverteilung: Alle Flächen haben genau die gleiche Wahrscheinlichkeit, gewürfelt zu werden.' },
100
+ { type: 'paragraph', html: 'Das am weitesten verbreitete Würfelset in Rollenspielen - bekann gemacht durch <strong>Dungeons &amp; Dragons</strong> im Jahr 1974 - besteht aus den fünf platonischen Körpern plus zwei zusätzlichen Formen: d4 (Tetraeder), d6 (Würfel), d8 (Oktaeder), d10 (Pentagonales Trapezoeder), d12 (Dodekaeder), d20 (Ikosaeder) und d100 (Prozentwürfel). Jedes Polyeder garantiert eine Gleichverteilung: Alle Flächen haben genau die gleiche Wahrscheinlichkeit, gewürfelt zu werden.' },
101
101
  { type: 'list', items: [
102
- '<strong>d4 Tetraeder:</strong> Am gefährlichsten, wenn man barfuß darauf tritt. Vier dreieckige Flächen, 25 % Wahrscheinlichkeit pro Fläche. Häufig verwendet für Dolchschaden oder Zaubersprüche auf niedriger Stufe.',
103
- '<strong>d6 Würfel:</strong> Der universellste Würfel. In allen Brettspielen seit dem ägyptischen Senet vorhanden. Seine kubische Geometrie garantiert perfekte Gleichverteilung.',
104
- '<strong>d8 Oktaeder:</strong> Der Würfel für den Speer oder die Streitaxt. Acht gleichseitige dreieckige Flächen. 12,5 % Wahrscheinlichkeit pro Fläche.',
105
- '<strong>d10 Pentagonales Trapezoeder:</strong> Der einzige nicht-platonische Körper im Standardset. Zwei gegenüberliegende Flächen pro "Ecke". Unverzichtbar für den d100 (zwei kombinierte d10).',
106
- '<strong>d12 Dodekaeder:</strong> Der Würfel des Barbaren. Zwölf fünfeckige Flächen. In vielen Systemen unterschätzt, Protagonist beim D&D 5e Barbaren.',
107
- '<strong>d20 Ikosaeder:</strong> Der König des Rollenspiels. Zwanzig dreieckige Flächen. Protagonist des d20-Systems: entscheidet über Erfolg oder Misserfolg fast aller Aktionen.',
108
- '<strong>d100 Prozentwürfel:</strong> Zwei kombinierte d10 (Zehner + Einer). Definiert feine Wahrscheinlichkeiten in Systemen wie Cthulhu oder Warhammer Fantasy.',
102
+ '<strong>d4 - Tetraeder:</strong> Am gefährlichsten, wenn man barfuß darauf tritt. Vier dreieckige Flächen, 25 % Wahrscheinlichkeit pro Fläche. Häufig verwendet für Dolchschaden oder Zaubersprüche auf niedriger Stufe.',
103
+ '<strong>d6 - Würfel:</strong> Der universellste Würfel. In allen Brettspielen seit dem ägyptischen Senet vorhanden. Seine kubische Geometrie garantiert perfekte Gleichverteilung.',
104
+ '<strong>d8 - Oktaeder:</strong> Der Würfel für den Speer oder die Streitaxt. Acht gleichseitige dreieckige Flächen. 12,5 % Wahrscheinlichkeit pro Fläche.',
105
+ '<strong>d10 - Pentagonales Trapezoeder:</strong> Der einzige nicht-platonische Körper im Standardset. Zwei gegenüberliegende Flächen pro "Ecke". Unverzichtbar für den d100 (zwei kombinierte d10).',
106
+ '<strong>d12 - Dodekaeder:</strong> Der Würfel des Barbaren. Zwölf fünfeckige Flächen. In vielen Systemen unterschätzt, Protagonist beim D&D 5e Barbaren.',
107
+ '<strong>d20 - Ikosaeder:</strong> Der König des Rollenspiels. Zwanzig dreieckige Flächen. Protagonist des d20-Systems: entscheidet über Erfolg oder Misserfolg fast aller Aktionen.',
108
+ '<strong>d100 - Prozentwürfel:</strong> Zwei kombinierte d10 (Zehner + Einer). Definiert feine Wahrscheinlichkeiten in Systemen wie Cthulhu oder Warhammer Fantasy.',
109
109
  ]},
110
110
  { type: 'stats', items: [
111
111
  { value: '5000 v. Chr.', label: 'Erste Würfel (Astragali)', icon: 'mdi:history' },
@@ -124,7 +124,7 @@ export const content: DiceRollerLocaleContent = {
124
124
  { term: 'Patzer / Nat 1', definition: 'Das Würfeln des Minimalwerts (1) auf einem Würfel. Führt oft zu einem dramatischen Misserfolg oder einer negativen Konsequenz.' },
125
125
  { term: 'Würfelpool', definition: 'Eine Sammlung von Würfeln, die gleichzeitig geworfen werden. Der Pool in unserem Werkzeug zeigt jeden Würfeltyp gruppiert nach Anzahl an (z. B. 3d6 + 2d8).' },
126
126
  { term: 'Modifikator', definition: 'Eine feste Zahl, die zu einem Würfelergebnis addiert oder davon subtrahiert wird und die Fertigkeit, den Attributsbonus oder einen situationsbedingten Abzug eines Charakters darstellt.' },
127
- { term: 'Prozentwurf', definition: 'Ein Wurf mit zwei d10, um ein Ergebnis von 1100 zu erhalten, verwendet in fertigkeitsbasierten Systemen, in denen Fähigkeiten als Prozentsätze gemessen werden.' },
127
+ { term: 'Prozentwurf', definition: 'Ein Wurf mit zwei d10, um ein Ergebnis von 1-100 zu erhalten, verwendet in fertigkeitsbasierten Systemen, in denen Fähigkeiten als Prozentsätze gemessen werden.' },
128
128
  ]},
129
129
  ],
130
130
  faq,
@@ -95,17 +95,17 @@ export const content: DiceRollerLocaleContent = {
95
95
  },
96
96
  seo: [
97
97
  { type: 'title', text: 'The Art of Randomness: History and Mathematics of Dice', level: 2 },
98
- { type: 'paragraph', html: 'Dice are one of humanity\'s oldest randomness generators. <strong>Astragali</strong> ankle bones of sheep and goats were used as primitive four-sided dice as far back as 5000 BC in Mesopotamia and Egypt. The evolution from carved bone to modern epoxy resin icosahedra is not just aesthetic: it is a journey through probability theory and game mechanics design.' },
98
+ { type: 'paragraph', html: 'Dice are one of humanity\'s oldest randomness generators. <strong>Astragali</strong> - ankle bones of sheep and goats - were used as primitive four-sided dice as far back as 5000 BC in Mesopotamia and Egypt. The evolution from carved bone to modern epoxy resin icosahedra is not just aesthetic: it is a journey through probability theory and game mechanics design.' },
99
99
  { type: 'title', text: 'The Standard Dice Family', level: 3 },
100
- { type: 'paragraph', html: 'The most widespread set of dice in role-playing games popularized by <strong>Dungeons &amp; Dragons</strong> in 1974 consists of the five Platonic solids plus two additional shapes: d4 (tetrahedron), d6 (cube), d8 (octahedron), d10 (pentagonal trapezohedron), d12 (dodecahedron), d20 (icosahedron) and d100 (percentile die). Each polyhedron guarantees uniform distribution: all faces have exactly the same probability of landing.' },
100
+ { type: 'paragraph', html: 'The most widespread set of dice in role-playing games - popularized by <strong>Dungeons &amp; Dragons</strong> in 1974 - consists of the five Platonic solids plus two additional shapes: d4 (tetrahedron), d6 (cube), d8 (octahedron), d10 (pentagonal trapezohedron), d12 (dodecahedron), d20 (icosahedron) and d100 (percentile die). Each polyhedron guarantees uniform distribution: all faces have exactly the same probability of landing.' },
101
101
  { type: 'list', items: [
102
- '<strong>d4 Tetrahedron:</strong> The most dangerous if stepped on barefoot. Four triangular faces, 25% probability per face. Commonly used for dagger damage or low-level spells.',
103
- '<strong>d6 Cube:</strong> The most universal die. Present in all board games since the Egyptian senet. Its cubic geometry guarantees perfect equidistribution.',
104
- '<strong>d8 Octahedron:</strong> The die of the spear or battle axe. Eight equilateral triangular faces. 12.5% probability per face.',
105
- '<strong>d10 Pentagonal Trapezohedron:</strong> The only non-Platonic solid in the standard set. Two opposite faces per "vertex". Essential for the d100 (two d10 combined).',
106
- '<strong>d12 Dodecahedron:</strong> The barbarian\'s die. Twelve pentagonal faces. Underrated in many systems, protagonist in D&D 5e Barbarian.',
107
- '<strong>d20 Icosahedron:</strong> The king of RPG. Twenty triangular faces. Protagonist of the d20 system: determines success or failure of almost all actions.',
108
- '<strong>d100 Percentile:</strong> Two d10 combined (tens + units). Defines fine probabilities in systems like Call of Cthulhu or Warhammer Fantasy.',
102
+ '<strong>d4 - Tetrahedron:</strong> The most dangerous if stepped on barefoot. Four triangular faces, 25% probability per face. Commonly used for dagger damage or low-level spells.',
103
+ '<strong>d6 - Cube:</strong> The most universal die. Present in all board games since the Egyptian senet. Its cubic geometry guarantees perfect equidistribution.',
104
+ '<strong>d8 - Octahedron:</strong> The die of the spear or battle axe. Eight equilateral triangular faces. 12.5% probability per face.',
105
+ '<strong>d10 - Pentagonal Trapezohedron:</strong> The only non-Platonic solid in the standard set. Two opposite faces per "vertex". Essential for the d100 (two d10 combined).',
106
+ '<strong>d12 - Dodecahedron:</strong> The barbarian\'s die. Twelve pentagonal faces. Underrated in many systems, protagonist in D&D 5e Barbarian.',
107
+ '<strong>d20 - Icosahedron:</strong> The king of RPG. Twenty triangular faces. Protagonist of the d20 system: determines success or failure of almost all actions.',
108
+ '<strong>d100 - Percentile:</strong> Two d10 combined (tens + units). Defines fine probabilities in systems like Call of Cthulhu or Warhammer Fantasy.',
109
109
  ]},
110
110
  { type: 'stats', items: [
111
111
  { value: '5000 BC', label: 'First dice (astragali)', icon: 'mdi:history' },
@@ -124,7 +124,7 @@ export const content: DiceRollerLocaleContent = {
124
124
  { term: 'Fumble / Nat 1', definition: 'Rolling the minimum value (1) on a die. Often results in a dramatic failure or negative consequence.' },
125
125
  { term: 'Dice Pool', definition: 'A collection of dice rolled simultaneously. The pool in our tool shows each die type grouped by count (e.g., 3d6 + 2d8).' },
126
126
  { term: 'Modifier', definition: 'A fixed number added or subtracted from a roll result, representing a character\'s skill, attribute bonus, or situational penalty.' },
127
- { term: 'Percentile Roll', definition: 'A roll using two d10 to produce a result from 1100, used in skill-based systems where abilities are measured as percentages.' },
127
+ { term: 'Percentile Roll', definition: 'A roll using two d10 to produce a result from 1-100, used in skill-based systems where abilities are measured as percentages.' },
128
128
  ]},
129
129
  ],
130
130
  faq,