diff --git a/lib/gettext/extractor.ex b/lib/gettext/extractor.ex index 284b794..2fc0e9a 100644 --- a/lib/gettext/extractor.ex +++ b/lib/gettext/extractor.ex @@ -299,12 +299,18 @@ defmodule Gettext.Extractor do def merge_template(existing, new, gettext_config) do protected_pattern = gettext_config[:excluded_refs_from_purging] + # Index both sides by message key so that matching is linear rather than + # quadratic in the number of messages. The first message for a key wins, + # which is what Expo.Messages.find/2 returns. + new_by_key = Enum.reduce(new.messages, %{}, &Map.put_new(&2, Message.key(&1), &1)) + existing_keys = MapSet.new(existing.messages, &Message.key/1) + # We go over the existing message in order so as to keep the existing # order as much as possible. old_and_merged = Enum.flat_map(existing.messages, fn message -> cond do - same = Messages.find(new, message) -> [merge_message(message, same)] + same = Map.get(new_by_key, Message.key(message)) -> [merge_message(message, same)] protected?(message, protected_pattern) -> [message] autogenerated?(message) -> [] true -> [message] @@ -313,7 +319,7 @@ defmodule Gettext.Extractor do # We reject all messages that appear in `existing` so that we're left # with the messages that only appear in `new`. - unique_new = Enum.reject(new.messages, &Messages.find(existing, &1)) + unique_new = Enum.reject(new.messages, &MapSet.member?(existing_keys, Message.key(&1))) messages = old_and_merged ++ unique_new