Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
erlang: "27.2"
elixir: "1.18"
- os: ubuntu-24.04
erlang: "29.0"
elixir: "1.20"
lint: true
coverage: true

Expand All @@ -31,7 +31,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

- name: Install OTP and Elixir
uses: erlef/setup-beam@fc68ffb90438ef2936bbb3251622353b3dcb2f93 # v1.24.0
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish-to-hex.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:

steps:
- name: Checkout this repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

- name: Install Erlang and Elixir
uses: erlef/setup-beam@fc68ffb90438ef2936bbb3251622353b3dcb2f93 # v1.24.0
with:
otp-version: "27.2"
elixir-version: "1.18"
otp-version: "29.0"
elixir-version: "1.20"

- name: Fetch dependencies
run: mix deps.get
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

* Parallelize per-locale merging in `mix gettext.merge`.

## v1.0.2

* Only skip manifest removal on Elixir v1.19.3+
Expand Down
14 changes: 11 additions & 3 deletions lib/mix/tasks/gettext.merge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,17 @@ defmodule Mix.Tasks.Gettext.Merge do
end

defp merge_all_locale_dirs(pot_dir, opts, gettext_config) do
for locale <- File.ls!(pot_dir), File.dir?(Path.join(pot_dir, locale)) do
merge_dirs(locale_dir(pot_dir, locale), pot_dir, locale, opts, gettext_config)
end
pot_dir
|> File.ls!()
|> Enum.filter(&File.dir?(Path.join(pot_dir, &1)))
|> Task.async_stream(
fn locale ->
merge_dirs(locale_dir(pot_dir, locale), pot_dir, locale, opts, gettext_config)
end,
ordered: false,
timeout: :infinity
)
|> Stream.run()
end

def locale_dir(pot_dir, locale) do
Expand Down
6 changes: 3 additions & 3 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%{
"castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
"castore": {:hex, :castore, "1.0.19", "6903cabdfd9d1af46454126e7c8385186659dd33ecfb74a885cae52221ad6109", [:mix], [], "hexpm", "3669e6cab13f54c2df26b3e6833745d647f35b6e30d8ddd5975df0d5c842ca98"},
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
"ex_doc": {:hex, :ex_doc, "0.40.3", "4a972ffe64bc07dc605af487e98fc19b72a4185f55ca031b94c0552d6071c1d9", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2756e357742fecd9749b489b85d67c9ce99c465f2e75728d9e6dc8d704b973de"},
"excoveralls": {:hex, :excoveralls, "0.18.3", "bca47a24d69a3179951f51f1db6d3ed63bca9017f476fe520eb78602d45f7756", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "746f404fcd09d5029f1b211739afb8fb8575d775b21f6a3908e7ce3e640724c6"},
"excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"},
"expo": {:hex, :expo, "1.1.1", "4202e1d2ca6e2b3b63e02f69cfe0a404f77702b041d02b58597c00992b601db5", [:mix], [], "hexpm", "5fb308b9cb359ae200b7e23d37c76978673aa1b06e2b3075d814ce12c5811640"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.1.0", "835f7e60792e08824cda445639555d7bf1bbbddb1b60b306e33cb6f6db24dc74", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "1cd6780fb1dd1a03979abaed0fe82712b0625118fd5257d3ebbf73f960c73c3c"},
Expand Down
5 changes: 4 additions & 1 deletion test/gettext/extractor_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -461,13 +461,16 @@ defmodule Gettext.ExtractorTest do
end
"""

# No trailing newline in the expected string below: the logged message ends
# without one, so when color is enabled the reset code (\e[0m) sits between
# the message and Logger's newline. Anchoring on "\n" would fail in a TTY.
assert capture_log(fn ->
Code.compile_string(code, Path.join(File.cwd!(), "foo.ex"))
end) =~
"""
Plural message for 'one error' is not matching:
Using 'multiple errors' instead of '%{count} errors'.
References: foo.ex:9, foo.ex:10
References: foo.ex:9, foo.ex:10\
"""
after
Extractor.disable()
Expand Down
6 changes: 5 additions & 1 deletion test/gettext/interpolation/default_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,12 @@ defmodule Gettext.Interpolation.DefaultTest do
)
end

# Building the empty bindings via `Map.drop/2` (rather than a `%{}`
# literal) keeps the compiler's type checker from inferring that
# `translate` only accepts maps with a `:count` key, which would flag
# this intentional missing-key case.
assert_raise MatchError, fn ->
translate.(%{})
translate.(Map.drop(%{count: 7}, [:count]))
end

assert {:ok, "7 shoes"} = translate.(%{count: 7})
Expand Down
3 changes: 1 addition & 2 deletions test/gettext/merger_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ defmodule Gettext.MergerTest do
%Message.Singular{msgid: "obs_auto", obsolete: true},
%Message.Singular{msgid: "obs_manual", obsolete: true}
]
},
stats} =
}, stats} =
Merger.merge(
old_po,
new_pot,
Expand Down
46 changes: 25 additions & 21 deletions test/mix/tasks/gettext.extract_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ defmodule Mix.Tasks.Gettext.ExtractTest do

test "extracting and extracting with --merge", %{test: test, tmp_dir: tmp_dir} = context do
create_test_mix_file(context)
mod = unique_module(test)

write_file(context, "lib/my_app.ex", """
defmodule MyApp.Gettext do
defmodule #{mod}.Gettext do
use Gettext.Backend, otp_app: #{inspect(test)}
end

defmodule MyApp do
use Gettext, backend: MyApp.Gettext
defmodule #{mod} do
use Gettext, backend: #{mod}.Gettext
def foo(), do: gettext("hello")
end
""")
Expand All @@ -43,8 +44,8 @@ defmodule Mix.Tasks.Gettext.ExtractTest do
# Test --merge too.

write_file(context, "lib/other.ex", """
defmodule MyApp.Other do
use Gettext, backend: MyApp.Gettext
defmodule #{mod}.Other do
use Gettext, backend: #{mod}.Gettext
def foo(), do: dgettext("my_domain", "other")
end
""")
Expand All @@ -70,21 +71,22 @@ defmodule Mix.Tasks.Gettext.ExtractTest do
test "--check-up-to-date should fail if no POT files have been created",
%{test: test, tmp_dir: tmp_dir} = context do
create_test_mix_file(context)
mod = unique_module(test)

write_file(context, "lib/my_app.ex", """
defmodule MyApp.Gettext do
defmodule #{mod}.Gettext do
use Gettext.Backend, otp_app: #{inspect(test)}
end

defmodule MyApp do
use Gettext, backend: MyApp.Gettext
defmodule #{mod} do
use Gettext, backend: #{mod}.Gettext
def foo(), do: gettext("hello")
end
""")

write_file(context, "lib/other.ex", """
defmodule MyApp.Other do
use Gettext, backend: MyApp.Gettext
defmodule #{mod}.Other do
use Gettext, backend: #{mod}.Gettext
def foo(), do: dgettext("my_domain", "other")
end
""")
Expand All @@ -109,14 +111,15 @@ defmodule Mix.Tasks.Gettext.ExtractTest do
test "--check-up-to-date should pass if nothing changed",
%{test: test, tmp_dir: tmp_dir} = context do
create_test_mix_file(context, write_reference_comments: false)
mod = unique_module(test)

write_file(context, "lib/my_app.ex", """
defmodule MyApp.Gettext do
defmodule #{mod}.Gettext do
use Gettext.Backend, otp_app: #{inspect(test)}
end

defmodule MyApp do
use Gettext, backend: MyApp.Gettext
defmodule #{mod} do
use Gettext, backend: #{mod}.Gettext
def foo(), do: gettext("hello")
end
""")
Expand All @@ -135,21 +138,22 @@ defmodule Mix.Tasks.Gettext.ExtractTest do
test "--check-up-to-date should fail if POT files are outdated",
%{test: test, tmp_dir: tmp_dir} = context do
create_test_mix_file(context)
mod = unique_module(test)

write_file(context, "lib/my_app.ex", """
defmodule MyApp.Gettext do
defmodule #{mod}.Gettext do
use Gettext.Backend, otp_app: #{inspect(test)}
end

defmodule MyApp do
use Gettext, backend: MyApp.Gettext
defmodule #{mod} do
use Gettext, backend: #{mod}.Gettext
def foo(), do: gettext("hello")
end
""")

write_file(context, "lib/other.ex", """
defmodule MyApp.Other do
use Gettext, backend: MyApp.Gettext
defmodule #{mod}.Other do
use Gettext, backend: #{mod}.Gettext
def foo(), do: dgettext("my_domain", "other")
end
""")
Expand All @@ -159,12 +163,12 @@ defmodule Mix.Tasks.Gettext.ExtractTest do
end)

write_file(context, "lib/my_app.ex", """
defmodule MyApp.Gettext do
defmodule #{mod}.Gettext do
use Gettext.Backend, otp_app: #{inspect(test)}
end

defmodule MyApp do
use Gettext, backend: MyApp.Gettext
defmodule #{mod} do
use Gettext, backend: #{mod}.Gettext
def foo(), do: gettext("hello world")
end
""")
Expand Down
10 changes: 10 additions & 0 deletions test/support/mix_project_helpers.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
defmodule GettextTest.MixProjectHelpers do
# Returns a module name segment that is unique per test. Tests in this suite
# run in the same VM and reuse fixture module names; because
# `Mix.Project.in_project/4` is called with `prune_code_paths: false`, every
# test's compiled fixtures stay in the code path. Reusing a module name across
# tests would let an earlier test's stale beam shadow the freshly compiled one,
# so we derive a unique base module name from the test name instead.
def unique_module(test) do
"MyApp" <> Integer.to_string(:erlang.phash2(test))
end

def create_test_mix_file(context, gettext_config \\ []) do
write_file(context, "mix.exs", """
defmodule MyApp.MixProject do
Expand Down
Loading