-
Notifications
You must be signed in to change notification settings - Fork 486
Allow I18n in render lifecycle #2483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Maybe someone can help with the failing checks, I'm not sure what to do |
|
@23tux This looks good to me. Those checks are failing on |
Co-authored-by: Hans Lemuet <Spone@users.noreply.github.com>
|
@boardfish I added a test helper as well, could you have another look at it? Apart from the integration/system specs that require a browser (as I said, I had some problems with the setup and can't run them), all the tests pass on my machine. I added one commit to make the allocation spec more robust. And the Lint check also fails, but it doesn't seem to involve my changes. |
Co-authored-by: Hans Lemuet <Spone@users.noreply.github.com>
|
This sounds a bit like the issue I have been having with ViewComponent 4. Where we have some deeply nested component slots and it fails to resolve the Claude made a single file test case. # frozen_string_literal: true
# Run with: ruby virtual_path_issue_test.rb
#
# This test demonstrates an issue with ViewComponent where t('.key') in blocks
# passed from views to deeply nested component slots resolves to the wrong i18n scope.
#
# Issue: When a view passes a block containing t('.key') to a component slot,
# and that slot renders through multiple nested components, the virtual_path
# is set to the innermost component's path instead of the original view's path.
#
# Expected: t('.edit') should resolve to "test_views.index.edit" -> "Edit"
# Actual: t('.edit') resolves to "cell_component.edit" -> "Cell edit" (or missing translation)
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails", "~> 8.0"
gem "view_component", "~> 4.1"
end
require "action_controller/railtie"
require "action_view/railtie"
require "view_component"
require "view_component/test_helpers"
require "minitest/autorun"
class TestApp < Rails::Application
config.eager_load = false
config.logger = Logger.new($stdout)
config.logger.level = Logger::WARN
config.secret_key_base = "test"
routes.draw do
root to: "test#index"
end
end
Rails.application.initialize!
class CellComponent < ViewComponent::Base
erb_template <<~ERB
<td><%= content %></td>
ERB
end
class RowComponent < ViewComponent::Base
renders_many :cells, CellComponent
erb_template <<~ERB
<tr><% cells.each do |cell| %><%= cell %><% end %></tr>
ERB
end
class TableComponent < ViewComponent::Base
renders_many :rows, RowComponent
erb_template <<~ERB
<table><tbody><% rows.each do |row| %><%= row %><% end %></tbody></table>
ERB
end
class TestController < ActionController::Base
def index
render inline: <<~ERB, layout: false
<%= render(TableComponent.new) do |table| %>
<% table.with_row do |row| %>
<% row.with_cell do %>
<%= t('.edit') %>
<% end %>
<% end %>
<% end %>
ERB
end
end
class VirtualPathIssueTest < ActionDispatch::IntegrationTest
include ViewComponent::TestHelpers
setup do
I18n.backend.store_translations(:en, {
test: {
index: {
edit: "Edit from view"
}
},
cell_component: {
edit: "Edit from cell"
}
})
end
test "t('.key') in deeply nested slot block should use the view's virtual_path" do
get "/"
# The t('.edit') call is in the view (test/index), so it should resolve
# to "test.index.edit" -> "Edit from view"
#
# But due to the bug, it resolves using the cell component's virtual_path
# to "cell_component.edit" -> "Edit from cell"
assert_includes response.body, "Edit from view",
"Expected t('.edit') to resolve using view's scope (test.index.edit), " \
"but it used the component's scope instead. Response: #{response.body}"
end
end |
What are you trying to accomplish?
t(".some_key")inside a#render?method. Think ofdef render? = items.any?anditemsis a hash of translations@virtual_pathis actually set, I can now testt(..)calls in my helper method, because the teardown hasn't happened yet.What approach did you choose and why?
#render_inmethod into methods.@view_context.instance_variable_set(:@virtual_path, virtual_path)outside of the@output_buffer.with_buffer doblock. I just hope this doesn't break anything else.Anything you want to highlight for special attention from reviewers?
assert_allocations