Skip to content

Commit

Permalink
Support marking messages as obsolete
Browse files Browse the repository at this point in the history
Implements #210
  • Loading branch information
maennchen committed Aug 1, 2022
1 parent 213a164 commit 34f59bc
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 14 deletions.
4 changes: 4 additions & 0 deletions lib/gettext.ex
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ defmodule Gettext do
messages are appended to the file. If `:sort_by_msgid` is set to `true`,
existing and new messages will be mixed and sorted alphabetically by msgid.
* `:on_obsolete` - controls what happens when obsolete messages are found.\
If `:mark_as_obsolete`, messages are kept and marked as obsolete.\
If `:delete`, obsolete messages are deleted. Defaults to `:delete`.
"""

defmodule Error do
Expand Down
2 changes: 0 additions & 2 deletions lib/gettext/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,6 @@ defmodule Gettext.Compiler do
singular_fun = :"#{locale}_#{domain}_lgettext"
plural_fun = :"#{locale}_#{domain}_lngettext"

# Remove obsolete messages (not needed at runtime)
# TODO: Resolve when implementing https://github.com/elixir-gettext/gettext/issues/210
messages = Enum.filter(messages, &match?(%{obsolete: false}, &1))

mapper =
Expand Down
24 changes: 21 additions & 3 deletions lib/gettext/merger.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ defmodule Gettext.Merger do
def merge(%Messages{} = old, %Messages{} = new, locale, opts)
when is_binary(locale) and is_list(opts) do
opts = put_plural_forms_opt(opts, old.headers, locale)
stats = %{new: 0, exact_matches: 0, fuzzy_matches: 0, removed: 0}
stats = %{new: 0, exact_matches: 0, fuzzy_matches: 0, removed: 0, marked_as_obsolete: 0}

{messages, stats} = merge_messages(old.messages, new.messages, opts, stats)

Expand Down Expand Up @@ -103,7 +103,19 @@ defmodule Gettext.Merger do
end
end)

{messages, put_in(stats.removed, map_size(unused))}
messages = Enum.map(messages, &%{&1 | obsolete: false})

{messages, stats} =
case Keyword.get(opts, :on_obsolete, :delete) do
:mark_as_obsolete ->
{messages ++ (unused |> Map.values() |> Enum.map(&%{&1 | obsolete: true})),
put_in(stats.marked_as_obsolete, map_size(unused))}

:delete ->
{messages, put_in(stats.removed, map_size(unused))}
end

{messages, stats}
end

defp adjust_number_of_plural_forms(%Message.Plural{} = message, plural_forms)
Expand Down Expand Up @@ -208,7 +220,13 @@ defmodule Gettext.Merger do
messages: Enum.map(pot.messages, &prepare_new_message(&1, plural_forms))
}

stats = %{new: length(po.messages), exact_matches: 0, fuzzy_matches: 0, removed: 0}
stats = %{
new: length(po.messages),
exact_matches: 0,
fuzzy_matches: 0,
removed: 0,
marked_as_obsolete: 0
}

{po, stats}
end
Expand Down
13 changes: 11 additions & 2 deletions lib/mix/tasks/gettext.merge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ defmodule Mix.Tasks.Gettext.Merge do
new messages in the target PO files will have this number of empty
plural forms. See the "Plural forms" section above.
* `--mark-as-obsolete` - marks obsolete messages as obsolete instead of
deleting them
"""

alias Expo.PO
Expand All @@ -109,7 +112,8 @@ defmodule Mix.Tasks.Gettext.Merge do
locale: :string,
fuzzy: :boolean,
fuzzy_threshold: :float,
plural_forms: :integer
plural_forms: :integer,
mark_as_obsolete: :boolean
]

def run(args) do
Expand Down Expand Up @@ -265,6 +269,10 @@ defmodule Mix.Tasks.Gettext.Merge do
|> Keyword.put_new_lazy(:fuzzy_threshold, fn ->
gettext_config[:fuzzy_threshold] || @default_fuzzy_threshold
end)
|> Keyword.put_new(
:on_obsolete,
if(opts[:marked_as_obsolete], do: :mark_as_obsolete, else: :delete)
)

threshold = opts[:fuzzy_threshold]

Expand All @@ -285,6 +293,7 @@ defmodule Mix.Tasks.Gettext.Merge do
pluralized = if stats.new == 1, do: "message", else: "messages"

"#{stats.new} new #{pluralized}, #{stats.removed} removed, " <>
"#{stats.exact_matches} unchanged, #{stats.fuzzy_matches} reworded (fuzzy)"
"#{stats.exact_matches} unchanged, #{stats.fuzzy_matches} reworded (fuzzy), " <>
"#{stats.marked_as_obsolete} marked as obsolete"
end
end
48 changes: 42 additions & 6 deletions test/gettext/merger_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,43 @@ defmodule Gettext.MergerTest do
assert message.msgid == "tomerge"
assert message.msgstr == "foo"

assert stats == %{exact_matches: 1, fuzzy_matches: 0, new: 0, removed: 2}
assert stats == %{
exact_matches: 1,
fuzzy_matches: 0,
new: 0,
removed: 2,
marked_as_obsolete: 0
}
end

test "obsolete messages are marked as obsolete" do
old_po = %Messages{
messages: [
%Message.Singular{msgid: "obs_auto", msgstr: "foo", flags: @autogenerated_flags},
%Message.Singular{msgid: "obs_manual", msgstr: "foo"},
%Message.Singular{msgid: "tomerge", msgstr: "foo", obsolete: true}
]
}

new_pot = %Messages{messages: [%Message.Singular{msgid: "tomerge", msgstr: ""}]}

assert {%Messages{
messages: [
%Message.Singular{msgid: "tomerge", obsolete: false},
%Message.Singular{msgid: "obs_auto", obsolete: true},
%Message.Singular{msgid: "obs_manual", obsolete: true}
]
},
stats} =
Merger.merge(old_po, new_pot, "en", @opts ++ [on_obsolete: :mark_as_obsolete])

assert stats == %{
exact_matches: 1,
fuzzy_matches: 0,
new: 0,
removed: 0,
marked_as_obsolete: 2
}
end

test "when messages match, the msgstr of the old one is preserved" do
Expand Down Expand Up @@ -193,7 +229,7 @@ defmodule Gettext.MergerTest do

assert {%Messages{messages: [message]}, stats} = Merger.merge(old_po, new_pot, "en", @opts)

assert stats == %{exact_matches: 0, fuzzy_matches: 1, new: 0, removed: 0}
assert %{exact_matches: 0, fuzzy_matches: 1, new: 0, removed: 0} = stats

assert message.msgid == "hello worlds!"
assert message.msgstr == ["foo"]
Expand Down Expand Up @@ -223,7 +259,7 @@ defmodule Gettext.MergerTest do
assert message.msgid == ["hello world!"]
assert message.msgstr == ["foo"]

assert stats == %{exact_matches: 1, fuzzy_matches: 0, new: 0, removed: 1}
assert %{exact_matches: 1, fuzzy_matches: 0, new: 0, removed: 1} = stats
end

test "exact matches do not prevent fuzzy matches for other messages" do
Expand Down Expand Up @@ -280,7 +316,7 @@ defmodule Gettext.MergerTest do
assert message_2.msgstr == ["foo"]
assert Message.has_flag?(message_2, "fuzzy")

assert stats == %{exact_matches: 0, new: 0, fuzzy_matches: 2, removed: 0}
assert %{exact_matches: 0, new: 0, fuzzy_matches: 2, removed: 0} = stats
end

test "filling in a fuzzy message preserves references" do
Expand Down Expand Up @@ -344,7 +380,7 @@ defmodule Gettext.MergerTest do
assert message.comments == ["# Guyanese Cocoballs"]
assert message.references == [{"new_file.txt", 2}]

assert stats == %{exact_matches: 0, fuzzy_matches: 1, new: 0, removed: 0}
assert %{exact_matches: 0, fuzzy_matches: 1, new: 0, removed: 0} = stats
end

# This has been verified with msgmerge too.
Expand All @@ -368,7 +404,7 @@ defmodule Gettext.MergerTest do
assert {%Messages{messages: [fuzzy_message, new_message]}, stats} =
Merger.merge(old_po, new_pot, "en", @opts)

assert stats == %{exact_matches: 0, fuzzy_matches: 1, new: 1, removed: 0}
assert %{exact_matches: 0, fuzzy_matches: 1, new: 1, removed: 0} = stats

assert fuzzy_message.msgid == "hello worlds!"
assert fuzzy_message.msgstr == ["cfoo"]
Expand Down
4 changes: 3 additions & 1 deletion test/mix/tasks/gettext.merge_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ defmodule Mix.Tasks.Gettext.MergeTest do
end)

assert output =~ "Wrote tmp/gettext.merge/it/LC_MESSAGES/foo.po"
assert output =~ "(1 new message, 0 removed, 0 unchanged, 0 reworded (fuzzy))"

assert output =~
"(1 new message, 0 removed, 0 unchanged, 0 reworded (fuzzy), 0 marked as obsolete)"

# The POT file is left unchanged
assert read_file("foo.pot") == pot_contents
Expand Down

0 comments on commit 34f59bc

Please sign in to comment.