From 2ebe86f6ef39e9d9b639432b4d9c31d23d4e53a8 Mon Sep 17 00:00:00 2001 From: Denis Righezza Date: Wed, 29 Jul 2026 18:30:44 +0200 Subject: [PATCH 1/2] Deduplicate source references when merging extracted messages Two extraction calls that resolve to the same msgid at the same file:line each contribute a reference group, and merge_messages_after_checks/2 concatenates them without uniquing. Macro-generated code produces N calls attributed to a single line, so the same comment is written N times. on the very next line is already uniqued; this makes consistent with it. --- lib/gettext/extractor_agent.ex | 2 +- test/gettext/extractor_test.exs | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/gettext/extractor_agent.ex b/lib/gettext/extractor_agent.ex index 5638f0f..10780bc 100644 --- a/lib/gettext/extractor_agent.ex +++ b/lib/gettext/extractor_agent.ex @@ -102,7 +102,7 @@ defmodule Gettext.ExtractorAgent do defp merge_messages_after_checks(message_1, message_2) do message_1 - |> Map.put(:references, message_1.references ++ message_2.references) + |> Map.put(:references, Enum.uniq(message_1.references ++ message_2.references)) |> Map.put( :extracted_comments, Enum.uniq(message_1.extracted_comments ++ message_2.extracted_comments) diff --git a/test/gettext/extractor_test.exs b/test/gettext/extractor_test.exs index 80f45ab..130c0fa 100644 --- a/test/gettext/extractor_test.exs +++ b/test/gettext/extractor_test.exs @@ -476,6 +476,41 @@ defmodule Gettext.ExtractorTest do Extractor.disable() end + test "duplicate references for one message are recorded once" do + Extractor.enable() + + code = """ + defmodule Gettext.ExtractorTest.SameLineGettext do + use Gettext.Backend, otp_app: :test_application + end + + defmodule SameLine do + require Gettext.Macros + + def bar do + [Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo"), Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo")] + end + end + """ + + Code.compile_string(code, Path.join(File.cwd!(), "same_line.ex")) + + [{_path, {:changed, contents}}] = + :test_application + |> Extractor.pot_files([]) + |> Enum.reject(&match?({_path, :unchanged}, &1)) + + references = + contents + |> IO.iodata_to_binary() + |> String.split("\n") + |> Enum.filter(&String.starts_with?(&1, "#: same_line.ex")) + + assert references == ["#: same_line.ex:9"] + after + Extractor.disable() + end + defp write_file(path, contents) do path |> Path.dirname() |> File.mkdir_p!() File.write!(path, contents) From f1ce73d9d478db4828af68dcbc2ef1dce026176b Mon Sep 17 00:00:00 2001 From: rigzad <81182605+rigzad@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:42:16 +0200 Subject: [PATCH 2/2] Update test/gettext/extractor_test.exs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jonatan Männchen --- test/gettext/extractor_test.exs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/gettext/extractor_test.exs b/test/gettext/extractor_test.exs index 130c0fa..2a147b4 100644 --- a/test/gettext/extractor_test.exs +++ b/test/gettext/extractor_test.exs @@ -481,15 +481,15 @@ defmodule Gettext.ExtractorTest do code = """ defmodule Gettext.ExtractorTest.SameLineGettext do - use Gettext.Backend, otp_app: :test_application + use Gettext.Backend, otp_app: :test_application end defmodule SameLine do - require Gettext.Macros + require Gettext.Macros - def bar do - [Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo"), Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo")] - end + def bar do + [Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo"), Gettext.Macros.gettext_with_backend(Gettext.ExtractorTest.SameLineGettext, "foo")] + end end """