Just realize `broadcast_replace(_later)` uses the `I18n.locale` of the event trigger

For example, given the following Book model views

<%# app/views/books/_book.html.erb %>

<div id="<%= dom_id book %>">
  <p>
    <strong><%= Book.human_attribute_name(:title)%>:</strong>
    <%= book.title %>
  </p>
</div>
<%# app/views/books/show.html.erb %>

<%= turbo_stream_from @book %>
<%= render @book %>

If a user with the I18n.locale pt-BR updates the book and another user with the I18n.locale en is viewing the book page, the page for the en user will be updated with pt-BR translations.

Thinking better this makes sense, but as it caught me out of guard I’m creating this post to warning anyone else that not have this insight yet.

Probably the way to go on these cases is use some frontend I18n library.

we define some tricks in template with from_stream: true to render async in view from clients

# Model
  after_update_commit do
    broadcast_replace_to(
      :stream_data,
      target: ActionView::RecordIdentifier.dom_id(self),
      partial: "tracks/track",
      locals: { album:, track: self, from_stream: true }
    )
  end

# tracks/_track.html.erb
<div class="flex justify-end items-end gap-2">
        <% if from_stream %>
          <%= turbo_frame_tag dom_id(track, :actions), src: actions_album_track_path(album, track) %>
        <% else %>
          <%= render 'tracks/actions', album:, track: %>
        <% end %>
      </div>

this case can handle permissions of user also

1 Like

Interesting idea! Thanks for sharing!

I could not use the Giang idea, because I also need broadcast non-resources messages.
But I found a simple way to workaround it, so I’m sharing here

# lib/extensions/abroadcasts.rb

module Abroadcasts
  def broadcast_render_to(*, abroad: false, **)
    if abroad then abroadcast_render_to(*, **)
    else super(*, **)
    end
  end

  def broadcast_action_to(*, abroad: false, **)
    if abroad then abroadcast_action_to(*, **)
    else super(*, **)
    end
  end

  private

  def abroadcast_render_to(*, **)
    I18n.available_locales.each do |locale|
      I18n.with_locale locale do
        broadcast_render_to(I18n.locale, *, **)
      end
    end
  end

  def abroadcast_action_to(*, **)
    I18n.available_locales.each do |locale|
      I18n.with_locale locale do
        broadcast_action_to(I18n.locale, *, **)
      end
    end
  end
end

Turbo::Streams::Broadcasts.prepend(Abroadcasts)
# app/helpers/turbo_stream_helper.rb

module TurboStreamsHelper
  def turbo_stream_from(*streamables, abroad: false, **)
    return super(*streamables, **) unless abroad
    raise ArgumentError, "streamables can't be blank" unless streamables.any?(&:present?)
    super(I18n.locale, *streamables, **)
  end
end