Commit 387bc15
committed
Update storing of virtual path for deep nesting
When translations are called inside deeply nested component blocks
(3+ levels) using renders_many/renders_one, they were incorrectly
resolving to an intermediate component's scope instead of the
partial's scope where the block was defined.
Example of the bug:
```erb
<!-- In app/views/shared/_action_menu_panel.html.erb -->
<%= render ActionMenuComponent.new do |menu| %>
<% menu.with_list do |list| %>
<% list.with_item do %>
<%= t(".menu_action") %> <!-- Should resolve to shared.action_menu_panel.menu_action -->
<% end %>
<% end %>
<% end %>
```
The translation would incorrectly resolve to `action_list_component.menu_action`
instead of `shared.action_menu_panel.menu_action`.
Previous Fix:
While a fix was added in #2389 to solve translation scope issues, the
`with_original_virtual_path` method only restored the virtual path
one level up to the immediate parent component, not to the original
partial where the block was defined.
This worked for 2-level nesting:
```erb
<!-- Partial → Component → Block (2 levels) -->
<%= render MyComponent.new do %>
<%= t(".title") %> <!-- Works correctly -->
<% end %>
```
But failed for 3+ level nesting:
```erb
<!-- Partial → Component1 → Component2 → Block (3 levels) -->
<%= render ActionMenuComponent.new do |menu| %>
<% menu.with_list do |list| %>
<% list.with_item do %>
<%= t(".menu_action") %> <!-- Resolved to wrong scope -->
<% end %>
<% end %>
<% end %>
```
Solution:
This change captures the virtual path at block definition time (when
`with_*` slot methods are called) and stores it on the slot. When the
block executes, it restores to the captured virtual path.
Implementation:
1. In slotable.rb: Capture `@virtual_path` when a block is provided to
a slot method and store it as `__vc_content_block_virtual_path`
2. In slot.rb: When executing the block, call
`@parent.with_captured_virtual_path(@__vc_content_block_virtual_path)`
to restore the captured path
3. In base.rb: The `with_captured_virtual_path` method temporarily sets
the virtual path to the captured value during block execution
After this fix, deeply nested translations work correctly:
```erb
<!-- Now works at any nesting depth -->
<%= render ActionMenuComponent.new do |menu| %>
<% menu.with_list do |list| %>
<% list.with_item do %>
<%= t(".menu_action") %> <!-- Correctly resolves to shared.action_menu_panel.menu_action -->
<% end %>
<% end %>
<% end %>
```
For test coverage: Tests for 3-level and 5-level nesting scenarios
using simplified test components inspired by Primer's ActionMenu pattern.
Builds on #2389.
Fixes #2386.1 parent 642bbce commit 387bc15
File tree
14 files changed
+183
-9
lines changed- lib/view_component
- test/sandbox
- app
- components
- config/locales
- test/components
14 files changed
+183
-9
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
363 | 363 | | |
364 | 364 | | |
365 | 365 | | |
366 | | - | |
| 366 | + | |
367 | 367 | | |
368 | 368 | | |
369 | 369 | | |
| |||
379 | 379 | | |
380 | 380 | | |
381 | 381 | | |
382 | | - | |
383 | | - | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
384 | 387 | | |
385 | 388 | | |
386 | | - | |
| 389 | + | |
387 | 390 | | |
388 | 391 | | |
389 | 392 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
| 61 | + | |
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
| 71 | + | |
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
390 | 390 | | |
391 | 391 | | |
392 | 392 | | |
393 | | - | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
394 | 399 | | |
395 | 400 | | |
396 | 401 | | |
| |||
408 | 413 | | |
409 | 414 | | |
410 | 415 | | |
411 | | - | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
412 | 419 | | |
413 | 420 | | |
414 | 421 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
0 commit comments