@jjlmoya/utils-tabletop 1.18.0 → 1.19.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 +2 -2
- package/src/tests/seo_parity.test.ts +60 -0
- package/src/tests/translation_copy.test.ts +124 -0
- package/src/tool/decision-wheel/i18n/de.ts +28 -0
- package/src/tool/decision-wheel/i18n/es.ts +28 -0
- package/src/tool/decision-wheel/i18n/fr.ts +28 -0
- package/src/tool/decision-wheel/i18n/id.ts +28 -0
- package/src/tool/decision-wheel/i18n/it.ts +28 -0
- package/src/tool/decision-wheel/i18n/ja.ts +28 -0
- package/src/tool/decision-wheel/i18n/ko.ts +28 -0
- package/src/tool/decision-wheel/i18n/nl.ts +28 -0
- package/src/tool/decision-wheel/i18n/pl.ts +28 -0
- package/src/tool/decision-wheel/i18n/pt.ts +28 -0
- package/src/tool/decision-wheel/i18n/sv.ts +28 -0
- package/src/tool/decision-wheel/i18n/tr.ts +28 -0
- package/src/tool/decision-wheel/i18n/zh.ts +28 -0
- package/src/tool/hidden-role-dealer/i18n/de.ts +10 -1
- package/src/tool/hidden-role-dealer/i18n/fr.ts +4 -1
- package/src/tool/hidden-role-dealer/i18n/id.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/it.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/ja.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/ko.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/nl.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/pl.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/pt.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/ru.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/sv.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/tr.ts +11 -1
- package/src/tool/hidden-role-dealer/i18n/zh.ts +11 -1
- package/src/tool/scatter-direction-selector/i18n/de.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/es.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/fr.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/id.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/it.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/ja.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/ko.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/nl.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/pl.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/pt.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/ru.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/sv.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/tr.ts +9 -0
- package/src/tool/scatter-direction-selector/i18n/zh.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jjlmoya/utils-tabletop",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"check": "astro check",
|
|
29
29
|
"type-check": "astro check",
|
|
30
30
|
"test": "vitest run",
|
|
31
|
-
"preversion": "npm run lint && npm run test",
|
|
31
|
+
"preversion": "npm run lint && npm run test && npm run build",
|
|
32
32
|
"postversion": "git push && git push --tags",
|
|
33
33
|
"patch": "npm version patch",
|
|
34
34
|
"minor": "npm version minor",
|
|
@@ -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
|
+
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'So Verwenden Sie das Entscheidungsrad', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Wählen Sie eine Vorlage oder erstellen Sie eigene Segmente mit Gewichtungen, um die Gewinnwahrscheinlichkeiten anzupassen.' },
|
|
44
|
+
{ type: 'title', text: "Weitere Szenarien", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Nutzen Sie das Rad für Abstimmungen, Zufallsbegegnungen und Spielaktionen." },
|
|
46
|
+
{ type: 'title', text: "Vorlagen nutzen", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Vorlagen laden häufige Entscheidungen für Brettspiele sofort." },
|
|
48
|
+
{ type: 'title', text: "Gewichtungen einstellen", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Gewichtungen machen einzelne Ergebnisse häufiger oder seltener." },
|
|
50
|
+
{ type: 'title', text: "Verlauf prüfen", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "Der Verlauf hält die letzten Drehungen für die Gruppe fest." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Kann ich Farben und Namen anpassen?',
|
|
52
60
|
answer: 'Ja, Sie können beliebig Segmente hinzufügen, Namen ändern, Farben wählen und die Gewichtung von 1 bis 5 anpassen.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Kann ich Ergebniswahrscheinlichkeiten ändern?",
|
|
64
|
+
answer: "Ja, ändern Sie das Gewicht eines Segments.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Wie viele Segmente sind möglich?",
|
|
68
|
+
answer: "Bis zu 16 Segmente sind möglich; mindestens zwei werden benötigt.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Welche Vorlagen gibt es?",
|
|
72
|
+
answer: "Ja oder Nein, Zahlen, Aktionen, eigene Optionen, D20, Gesinnung und Beute.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "Bleiben frühere Drehungen sichtbar?",
|
|
76
|
+
answer: "Ja, die letzten zehn Ergebnisse werden im Browser angezeigt.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Das Rad Drehen',
|
|
63
87
|
text: 'Klicken Sie auf Drehen und warten Sie, bis das Rad mit realistischer Verzögerung stoppt.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Ergebnis prüfen",
|
|
91
|
+
text: "Nach dem Stopp wird das Gewinnersegment hervorgehoben. Prüfen Sie den Verlauf der letzten Drehungen.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Cómo Usar la Ruleta de Decisiones', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'La ruleta facilita elegir al azar entre un conjunto de opciones. Elige un preajuste o crea tus propias secciones con diferentes pesos para ajustar las probabilidades.' },
|
|
44
|
+
{ type: 'title', text: "Más escenarios de decisión", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Usa la ruleta para votaciones, encuentros aleatorios y acciones de la partida." },
|
|
46
|
+
{ type: 'title', text: "Plantillas para juegos de mesa", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Las plantillas cargan rápidamente decisiones habituales de juegos de mesa." },
|
|
48
|
+
{ type: 'title', text: "Ajustar pesos de resultado", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Los pesos hacen que determinados resultados aparezcan más o menos veces." },
|
|
50
|
+
{ type: 'title', text: "Revisar el historial", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "El historial conserva los últimos giros para que el grupo los revise." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: '¿Puedo personalizar los colores y nombres?',
|
|
52
60
|
answer: 'Sí, puedes añadir secciones, cambiar las etiquetas de texto, asignar colores personalizados y ajustar su peso del 1 al 5.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "¿Puedo cambiar las probabilidades?",
|
|
64
|
+
answer: "Sí, modifica el peso de un segmento.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "¿Cuántos segmentos admite?",
|
|
68
|
+
answer: "Admite hasta 16 segmentos y necesita al menos dos.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "¿Qué plantillas hay disponibles?",
|
|
72
|
+
answer: "Sí o No, Números, Acciones, opciones propias, D20, Alineamiento y Botín.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "¿Se conservan los giros anteriores?",
|
|
76
|
+
answer: "Sí, el navegador muestra los diez últimos resultados.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Girar la Ruleta',
|
|
63
87
|
text: 'Haz clic en el botón de girar y observa la animación con físicas de deceleración realista.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Comprueba el resultado",
|
|
91
|
+
text: "Cuando se detenga, revisa el segmento ganador y el historial de giros.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Comment Utiliser la Roue de Décision', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Choisissez un modèle prédéfini ou créez vos propres options avec des poids personnalisés pour ajuster les probabilités de chaque secteur.' },
|
|
44
|
+
{ type: 'title', text: "Autres scénarios de décision", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Utilisez la roue pour les votes, les rencontres aléatoires et les actions de partie." },
|
|
46
|
+
{ type: 'title', text: "Modèles pour les jeux de plateau", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Les modèles chargent rapidement les décisions courantes des jeux de plateau." },
|
|
48
|
+
{ type: 'title', text: "Régler les pondérations", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Les pondérations rendent certains résultats plus ou moins fréquents." },
|
|
50
|
+
{ type: 'title', text: "Consulter l'historique", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "L'historique conserve les derniers tours pour le groupe." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Peut-on modifier les couleurs et les étiquettes?',
|
|
52
60
|
answer: 'Oui, vous pouvez éditer librement le nom, la couleur et le poids de chaque option présente sur la roue.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Puis-je modifier les probabilités ?",
|
|
64
|
+
answer: "Oui, modifiez le poids d'un segment.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Combien de segments sont possibles ?",
|
|
68
|
+
answer: "La roue accepte jusqu'à 16 segments et en nécessite au moins deux.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Quels modèles sont disponibles ?",
|
|
72
|
+
answer: "Oui ou Non, Nombres, Actions, options personnelles, D20, Alignement et Butin.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "Les tours précédents restent-ils visibles ?",
|
|
76
|
+
answer: "Oui, le navigateur affiche les dix derniers résultats.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Lancer le Tour',
|
|
63
87
|
text: 'Cliquez sur le bouton de rotation pour lancer la roue animée avec ralentissement réaliste.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Vérifier le résultat",
|
|
91
|
+
text: "À l'arrêt, vérifiez le segment gagnant puis l'historique des tours.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Cara Menggunakan Roda Keputusan', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Pilih prasetel atau buat segmen Anda sendiri dengan bobot untuk menyesuaikan probabilitas setiap pilihan.' },
|
|
44
|
+
{ type: 'title', text: "Skenario tambahan", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Gunakan roda untuk pemungutan suara, pertemuan acak, dan aksi permainan." },
|
|
46
|
+
{ type: 'title', text: "Preset permainan meja", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Preset memuat keputusan umum permainan meja dengan cepat." },
|
|
48
|
+
{ type: 'title', text: "Mengatur bobot hasil", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Bobot membuat hasil tertentu lebih sering atau lebih jarang muncul." },
|
|
50
|
+
{ type: 'title', text: "Meninjau riwayat", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "Riwayat menyimpan putaran terbaru untuk ditinjau bersama." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Apakah saya bisa mengubah warna dan nama?',
|
|
52
60
|
answer: 'Ya, Anda bebas menambah segmen, mengubah teks label, memilih warna, dan mengubah bobot dari 1 hingga 5.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Bisakah peluang diubah?",
|
|
64
|
+
answer: "Bisa, ubah bobot segmen.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Berapa banyak segmen yang tersedia?",
|
|
68
|
+
answer: "Hingga 16 segmen dapat digunakan dan minimal dua diperlukan.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Preset apa yang tersedia?",
|
|
72
|
+
answer: "Ya atau Tidak, Angka, Aksi, pilihan sendiri, D20, Keselarasan, dan Jarahan.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "Apakah putaran sebelumnya terlihat?",
|
|
76
|
+
answer: "Ya, browser menampilkan sepuluh hasil terakhir.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Putar Roda Keputusan',
|
|
63
87
|
text: 'Klik tombol putar untuk melihat animasi putaran dengan deselerasi fisik yang realistis.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Periksa hasil",
|
|
91
|
+
text: "Setelah roda berhenti, periksa segmen pemenang dan riwayat putaran.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Come Usare la Ruota delle Decisioni', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Scegli un set preimpostato o crea i tuoi spicchi personali impostando pesi diversi per calibrare le probabilità.' },
|
|
44
|
+
{ type: 'title', text: "Altri scenari decisionali", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Usa la ruota per votazioni, incontri casuali e azioni durante la partita." },
|
|
46
|
+
{ type: 'title', text: "Preset per giochi da tavolo", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "I preset caricano rapidamente le decisioni comuni dei giochi da tavolo." },
|
|
48
|
+
{ type: 'title', text: "Regolare i pesi", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "I pesi rendono alcuni risultati più o meno frequenti." },
|
|
50
|
+
{ type: 'title', text: "Consultare la cronologia", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "La cronologia conserva gli ultimi giri per il gruppo." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Posso personalizzare colori e testi?',
|
|
52
60
|
answer: 'Sì, puoi aggiungere nuovi spicchi, rinominarli, scegliere un colore e impostare un peso tra 1 e 5.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Posso cambiare le probabilità?",
|
|
64
|
+
answer: "Sì, modifica il peso di un segmento.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Quanti segmenti sono possibili?",
|
|
68
|
+
answer: "Sono supportati fino a 16 segmenti e ne servono almeno due.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Quali preset sono disponibili?",
|
|
72
|
+
answer: "Sì o No, Numeri, Azioni, opzioni proprie, D20, Allineamento e Bottino.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "I giri precedenti restano visibili?",
|
|
76
|
+
answer: "Sì, il browser mostra gli ultimi dieci risultati.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Girare la Ruota',
|
|
63
87
|
text: 'Fai clic sul pulsante di avvio e guarda la ruota rallentare con fisica realistica fino a fermarsi.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Controllare il risultato",
|
|
91
|
+
text: "Dopo l'arresto, controlla il segmento vincente e la cronologia dei giri.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: '意思決定ホイールの使い方', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'プリセットを選ぶか、独自の項目を作成して重みを設定し、当選確率を自由にコントロールできます。' },
|
|
44
|
+
{ type: 'title', text: "その他のシナリオ", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "投票、ランダムイベント、ゲーム中の行動選択にホイールを使えます。" },
|
|
46
|
+
{ type: 'title', text: "卓上ゲームのプリセット", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "プリセットで卓上ゲームの一般的な選択肢をすぐに読み込めます。" },
|
|
48
|
+
{ type: 'title', text: "重みを調整する", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "重みを変えると結果の出やすさを調整できます。" },
|
|
50
|
+
{ type: 'title', text: "履歴を確認する", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "履歴には最近のスピンが残り、グループで確認できます。" },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: '色や名前は変更できますか?',
|
|
52
60
|
answer: 'はい。セグメントを追加し、名前や色、1から5までの重要度の重みを自由に変更可能です。',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "確率を変更できますか?",
|
|
64
|
+
answer: "はい。セグメントの重みを変更します。",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "セグメントはいくつ置けますか?",
|
|
68
|
+
answer: "最大16個で、動作には2個以上必要です。",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "どんなプリセットがありますか?",
|
|
72
|
+
answer: "はい・いいえ、数字、アクション、カスタム、D20、属性、戦利品です。",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "以前のスピンは表示されますか?",
|
|
76
|
+
answer: "はい。ブラウザーに直近10件が表示されます。",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'ホイールをスピン',
|
|
63
87
|
text: 'スタートボタンをクリックすると、リアルな摩擦減速アニメーションを伴ってホイールが回転します。',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "結果を確認する",
|
|
91
|
+
text: "停止後に当選セグメントと最近のスピン履歴を確認します。",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: '결정 휠 사용법', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: '준비된 프리셋을 불러오거나 직접 항목을 만들고 가중치를 조절해 당첨 확률을 다르게 구성할 수 있습니다.' },
|
|
44
|
+
{ type: 'title', text: "추가 시나리오", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "투표, 무작위 만남, 게임 행동 선택에 룰렛을 사용할 수 있습니다." },
|
|
46
|
+
{ type: 'title', text: "테이블탑 게임 프리셋", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "프리셋으로 테이블탑 게임의 일반적인 선택지를 빠르게 불러옵니다." },
|
|
48
|
+
{ type: 'title', text: "결과 가중치 조정", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "가중치를 바꾸면 결과가 나올 가능성을 조절할 수 있습니다." },
|
|
50
|
+
{ type: 'title', text: "회전 기록 확인", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "기록에는 최근 회전 결과가 남아 그룹이 확인할 수 있습니다." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: '색상과 이름을 바꿀 수 있나요?',
|
|
52
60
|
answer: '네, 라벨 이름과 색상뿐만 아니라 각 세그먼트의 가중치 값을 1부터 5까지 조절할 수 있습니다.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "확률을 바꿀 수 있나요?",
|
|
64
|
+
answer: "네. 세그먼트의 가중치를 변경합니다.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "세그먼트는 몇 개까지 가능한가요?",
|
|
68
|
+
answer: "최대 16개이며 작동하려면 2개 이상 필요합니다.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "어떤 프리셋이 있나요?",
|
|
72
|
+
answer: "예 또는 아니요, 숫자, 행동, 사용자 지정, D20, 성향, 전리품입니다.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "이전 회전이 표시되나요?",
|
|
76
|
+
answer: "네. 브라우저에 최근 10개가 표시됩니다.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: '휠 돌리기',
|
|
63
87
|
text: '휠 돌리기를 실행하면 감속 물리가 적용된 부드러운 회전 애니메이션이 실행됩니다.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "결과 확인",
|
|
91
|
+
text: "룰렛이 멈춘 뒤 당첨 세그먼트와 최근 회전 기록을 확인합니다.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Hoe het Beslissingsrad te Gebruiken', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Kies een voorinstelling of maak uw eigen segmenten met gewichten om de kansen per keuze te bepalen.' },
|
|
44
|
+
{ type: 'title', text: "Meer beslisscenario's", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Gebruik het rad voor stemmingen, willekeurige ontmoetingen en spelacties." },
|
|
46
|
+
{ type: 'title', text: "Sjablonen voor bordspellen", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Sjablonen laden veelvoorkomende keuzes voor bordspellen snel." },
|
|
48
|
+
{ type: 'title', text: "Uitkomsten wegen", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Met gewichten maak je uitkomsten vaker of zeldzamer." },
|
|
50
|
+
{ type: 'title', text: "De geschiedenis bekijken", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "De geschiedenis bewaart recente draaien voor de groep." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Kan ik kleuren en namen aanpassen?',
|
|
52
60
|
answer: 'Ja, u kunt segmenten toevoegen, labels bewerken, kleuren kiezen en het gewicht van 1 tot 5 instellen.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Kan ik kansen wijzigen?",
|
|
64
|
+
answer: "Ja, wijzig het gewicht van een segment.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Hoeveel segmenten zijn mogelijk?",
|
|
68
|
+
answer: "Maximaal 16; er zijn minstens twee opties nodig.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Welke sjablonen zijn er?",
|
|
72
|
+
answer: "Ja of Nee, Getallen, Acties, eigen opties, D20, Uitlijning en Buit.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "Blijven eerdere draaien zichtbaar?",
|
|
76
|
+
answer: "Ja, de browser toont de tien recentste resultaten.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Draai aan het Rad',
|
|
63
87
|
text: 'Klik op de knop om de rotatie-animatie met realistische vertraging te starten.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Het resultaat controleren",
|
|
91
|
+
text: "Controleer na het stoppen het winnende segment en de recente draaigeschiedenis.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|
|
@@ -41,6 +41,14 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
41
41
|
},
|
|
42
42
|
{ type: 'title', text: 'Jak Używać Koła Decyzyjnego', level: 2 },
|
|
43
43
|
{ type: 'paragraph', html: 'Wybierz gotowy szablon lub stwórz własne wycinki z wagami określającymi szansę wylosowania każdej opcji.' },
|
|
44
|
+
{ type: 'title', text: "Dodatkowe scenariusze", level: 3 },
|
|
45
|
+
{ type: 'paragraph', html: "Użyj koła do głosowań, losowych spotkań i wyboru działań w grze." },
|
|
46
|
+
{ type: 'title', text: "Szablony do gier planszowych", level: 3 },
|
|
47
|
+
{ type: 'paragraph', html: "Szablony szybko wczytują typowe wybory w grach planszowych." },
|
|
48
|
+
{ type: 'title', text: "Ustawianie wag", level: 3 },
|
|
49
|
+
{ type: 'paragraph', html: "Wagi sprawiają, że wyniki pojawiają się częściej lub rzadziej." },
|
|
50
|
+
{ type: 'title', text: "Sprawdzanie historii", level: 3 },
|
|
51
|
+
{ type: 'paragraph', html: "Historia zachowuje ostatnie losowania dla całej grupy." },
|
|
44
52
|
],
|
|
45
53
|
faq: [
|
|
46
54
|
{
|
|
@@ -51,6 +59,22 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
51
59
|
question: 'Czy mogę dostosować kolory i nazwy?',
|
|
52
60
|
answer: 'Tak, możesz dodawać wycinki, zmieniać ich teksty, dobierać kolory oraz modyfikować wagę od 1 do 5.',
|
|
53
61
|
},
|
|
62
|
+
{
|
|
63
|
+
question: "Czy można zmienić prawdopodobieństwo?",
|
|
64
|
+
answer: "Tak, zmień wagę segmentu.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
question: "Ile segmentów jest możliwych?",
|
|
68
|
+
answer: "Maksymalnie 16; potrzebne są co najmniej dwa.",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
question: "Jakie szablony są dostępne?",
|
|
72
|
+
answer: "Tak lub Nie, Liczby, Działania, własne opcje, D20, Charakter i Łupy.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
question: "Czy poprzednie losowania są widoczne?",
|
|
76
|
+
answer: "Tak, przeglądarka pokazuje dziesięć ostatnich wyników.",
|
|
77
|
+
},
|
|
54
78
|
],
|
|
55
79
|
bibliography,
|
|
56
80
|
howTo: [
|
|
@@ -62,6 +86,10 @@ export const content: DecisionWheelLocaleContent = {
|
|
|
62
86
|
name: 'Zakręć Kołem',
|
|
63
87
|
text: 'Kliknij przycisk zakręcenia, aby uruchomić animację obrotu z fizyką naturalnego hamowania.',
|
|
64
88
|
},
|
|
89
|
+
{
|
|
90
|
+
name: "Sprawdź wynik",
|
|
91
|
+
text: "Po zatrzymaniu sprawdź zwycięski segment oraz historię ostatnich losowań.",
|
|
92
|
+
},
|
|
65
93
|
],
|
|
66
94
|
schemas: [
|
|
67
95
|
{
|