Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions sphinx_exercise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,16 @@
exercise_latex_number_reference,
visit_exercise_latex_number_reference,
depart_exercise_latex_number_reference,
visit_exercise_subtitle,
depart_exercise_subtitle,
visit_solution_subtitle,
depart_solution_subtitle,
)
from .transforms import (
CheckGatedDirectives,
MergeGatedSolutions,
MergeGatedExercises,
setup_i18n_for_subtitles,
)
from .post_transforms import (
ResolveTitlesInExercises,
Expand Down Expand Up @@ -279,6 +284,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.connect("config-inited", init_numfig) # event order - 1
app.connect("env-purge-doc", purge_exercises) # event order - 5 per file
app.connect("doctree-read", doctree_read) # event order - 8
app.connect("doctree-read", setup_i18n_for_subtitles) # mark subtitles translatable
app.connect("env-merge-info", merge_exercises) # event order - 9
app.connect("env-updated", validate_exercise_solution_order) # event order - 10
app.connect("build-finished", copy_asset_files) # event order - 16
Expand Down Expand Up @@ -312,9 +318,17 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_node(solution_start_node)
app.add_node(solution_end_node)
app.add_node(exercise_title)
app.add_node(exercise_subtitle)
app.add_node(exercise_subtitle,
singlehtml=(visit_exercise_subtitle, depart_exercise_subtitle),
html=(visit_exercise_subtitle, depart_exercise_subtitle),
latex=(visit_exercise_subtitle, depart_exercise_subtitle),
)
app.add_node(solution_title)
app.add_node(solution_subtitle)
app.add_node(solution_subtitle,
singlehtml=(visit_solution_subtitle, depart_solution_subtitle),
html=(visit_solution_subtitle, depart_solution_subtitle),
latex=(visit_solution_subtitle, depart_solution_subtitle),
)

app.add_node(
exercise_latex_number_reference,
Expand Down
11 changes: 10 additions & 1 deletion sphinx_exercise/directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,14 @@ def run(self) -> List[Node]:
subtitle_nodes, _ = self.state.inline_text(subtitle_text, self.lineno)
for subtitle_node in subtitle_nodes:
subtitle += subtitle_node
# Set attributes needed for i18n extraction
subtitle.rawsource = subtitle_text
subtitle.source = self.state.document.current_source
subtitle.line = self.lineno
# Also add as child of title for post-transforms to find
title += subtitle
else:
subtitle = None

# State Parsing
section = nodes.section(ids=["exercise-content"])
Expand Down Expand Up @@ -149,7 +156,9 @@ def run(self) -> List[Node]:
self.options["name"] = label

# Construct Node
node += title
node += title # Add title as child of node to be found for translation
if subtitle is not None:
node += subtitle
node += section
node["classes"].extend(classes)
node["ids"].append(label)
Expand Down
21 changes: 21 additions & 0 deletions sphinx_exercise/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,24 @@ def visit_exercise_latex_number_reference(self, node):

def depart_exercise_latex_number_reference(self, node):
pass

# Visitor functions for subtitle nodes
# These skip rendering - subtitle is only used in title for i18n
def visit_exercise_subtitle(self, node):
"""Visit exercise_subtitle - skip rendering (only in title)"""
raise docutil_nodes.SkipNode


def depart_exercise_subtitle(self, node):
"""Depart exercise_subtitle"""
pass


def visit_solution_subtitle(self, node):
"""Visit solution_subtitle - skip rendering"""
raise docutil_nodes.SkipNode


def depart_solution_subtitle(self, node):
"""Depart solution_subtitle"""
pass
16 changes: 16 additions & 0 deletions sphinx_exercise/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,19 @@ def apply(self):
if node.gated:
self.merge_nodes(node)
node.gated = False


def setup_i18n_for_subtitles(app, document):
"""
Event handler for 'doctree-read' event.
Marks exercise and solution subtitle nodes as translatable.
"""
from .nodes import exercise_subtitle, solution_subtitle

# Mark exercise subtitles as translatable
for node in findall(document, exercise_subtitle):
node['translatable'] = True

# Mark solution subtitles as translatable
for node in findall(document, solution_subtitle):
node['translatable'] = True