Files
exercises-dataset/data/exercises.schema.json
T
umutcakirai 6f3031b3b2 Add French (fr) exercise instructions
Adds a tenth language to all 1,324 exercises: `instructions.fr` and
`instruction_steps.fr`, plus the schema, README, viewer and setup guide.

Register matches the existing Spanish/Italian/Polish translations —
informal second-person imperative (tutoiement):

  en: Lie flat on your back with your knees bent and feet flat on the ground.
  fr: Allonge-toi sur le dos, les genoux fléchis et les pieds à plat au sol.

How it was produced
-------------------
The 7,710 English step sentences deduplicate to 4,414 unique strings.
Those were translated (LLM-assisted, glossary-constrained, then audited),
and the per-exercise arrays were rebuilt deterministically by mapping each
English step back through that table. `instructions.fr` is the join of
`instruction_steps.fr`, so the two can never drift.

A fixed glossary pinned the recurring terms — répétitions, position de
départ, haltère/barre, sangle abdominale, omoplates, largeur des épaules —
so terminology is consistent across all 1,324 records rather than varying
sentence by sentence.

Verified
--------
- 1,324 records validate against the updated schema; a record missing `fr`
  is now rejected.
- fr step count == en step count in every record (the dataset's existing
  invariant across all nine prior languages).
- instructions.fr == ' '.join(instruction_steps.fr) in every record.
- Every pre-existing field is byte-identical; `fr` is purely additive.
- No empty strings, none left in English, no vouvoiement across 7,710 steps.
- index.html embed stays in sync with data/exercises.json; the language
  picker renders "Français" and the steps display correctly.

Note for review: these are machine translations, reviewed programmatically
rather than by a native speaker. Happy to adjust any wording.
2026-07-10 15:58:52 +03:00

160 lines
5.0 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json",
"title": "Exercises Dataset",
"description": "Schema for data/exercises.json — an array of fitness exercise records with multilingual instructions and media references.",
"type": "array",
"items": {
"$ref": "#/$defs/exercise"
},
"$defs": {
"languageMap": {
"type": "object",
"description": "Instruction text keyed by ISO 639-1 language code.",
"properties": {
"en": { "type": "string" },
"es": { "type": "string" },
"it": { "type": "string" },
"tr": { "type": "string" },
"ru": { "type": "string" },
"zh": { "type": "string" },
"hi": { "type": "string" },
"pl": { "type": "string" },
"ko": { "type": "string" },
"fr": { "type": "string" }
},
"required": ["en", "es", "it", "tr", "ru", "zh", "hi", "pl", "ko", "fr"],
"additionalProperties": { "type": "string" }
},
"languageStepsMap": {
"type": "object",
"description": "Step-by-step instructions as an array of strings, keyed by ISO 639-1 language code.",
"properties": {
"en": { "$ref": "#/$defs/steps" },
"es": { "$ref": "#/$defs/steps" },
"it": { "$ref": "#/$defs/steps" },
"tr": { "$ref": "#/$defs/steps" },
"ru": { "$ref": "#/$defs/steps" },
"zh": { "$ref": "#/$defs/steps" },
"hi": { "$ref": "#/$defs/steps" },
"pl": { "$ref": "#/$defs/steps" },
"ko": { "$ref": "#/$defs/steps" },
"fr": { "$ref": "#/$defs/steps" }
},
"required": ["en", "es", "it", "tr", "ru", "zh", "hi", "pl", "ko", "fr"],
"additionalProperties": { "$ref": "#/$defs/steps" }
},
"steps": {
"type": "array",
"items": { "type": "string", "minLength": 1 }
},
"exercise": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique numeric identifier, zero-padded to 4 digits (e.g. \"0001\").",
"pattern": "^[0-9]{4}$"
},
"name": {
"type": "string",
"description": "Full exercise name (e.g. \"3/4 sit-up\").",
"minLength": 1
},
"category": {
"type": "string",
"description": "Body part category. Mirrors body_part.",
"minLength": 1
},
"body_part": {
"type": "string",
"description": "Body part targeted.",
"enum": [
"back",
"cardio",
"chest",
"lower arms",
"lower legs",
"neck",
"shoulders",
"upper arms",
"upper legs",
"waist"
]
},
"equipment": {
"type": "string",
"description": "Required equipment (e.g. \"dumbbell\", \"body weight\").",
"minLength": 1
},
"instructions": {
"$ref": "#/$defs/languageMap",
"description": "Full step-by-step instructions as a single string per language."
},
"instruction_steps": {
"$ref": "#/$defs/languageStepsMap",
"description": "Same instructions split into an ordered array of steps per language."
},
"muscle_group": {
"type": "string",
"description": "Primary synergist muscle group.",
"minLength": 1
},
"secondary_muscles": {
"type": "array",
"description": "Additional muscles involved.",
"items": { "type": "string", "minLength": 1 }
},
"target": {
"type": "string",
"description": "Primary target muscle (e.g. \"biceps\", \"abs\").",
"minLength": 1
},
"media_id": {
"type": "string",
"description": "Original media reference id (e.g. \"2gPfomN\").",
"minLength": 1
},
"image": {
"type": "string",
"description": "Path to the 180x180 thumbnail (e.g. \"images/0001-2gPfomN.jpg\").",
"pattern": "^images/.+\\.(jpg|jpeg|png)$"
},
"gif_url": {
"type": "string",
"description": "Path to the 180x180 animation GIF (e.g. \"videos/0001-2gPfomN.gif\").",
"pattern": "^videos/.+\\.gif$"
},
"attribution": {
"type": "string",
"description": "Media copyright notice.",
"minLength": 1
},
"created_at": {
"type": "string",
"description": "ISO 8601 timestamp of record creation.",
"format": "date-time"
}
},
"required": [
"id",
"name",
"category",
"body_part",
"equipment",
"instructions",
"instruction_steps",
"muscle_group",
"secondary_muscles",
"target",
"media_id",
"image",
"gif_url",
"attribution",
"created_at"
],
"additionalProperties": false
}
}
}