102 lines
2.4 KiB
Elixir
102 lines
2.4 KiB
Elixir
|
defmodule Mix.Tasks.Expo.Msguniq do
|
||
|
@shortdoc "Unifies duplicate translations in message catalog"
|
||
|
|
||
|
@moduledoc """
|
||
|
Unifies duplicate translations in the given PO file.
|
||
|
|
||
|
By default, this task outputs the file on standard output. If you want to
|
||
|
*overwrite* the given PO file, pass in the `--output` flag.
|
||
|
|
||
|
*This task is available since v0.5.0.*
|
||
|
|
||
|
## Usage
|
||
|
|
||
|
mix expo.msguniq PO_FILE [--output-file=OUTPUT_FILE]
|
||
|
|
||
|
## Options
|
||
|
|
||
|
* `--output-file` (`-o`) - File to store the output in. `-` for
|
||
|
standard output. Defaults to `-`.
|
||
|
|
||
|
"""
|
||
|
@moduledoc since: "0.5.0"
|
||
|
|
||
|
use Mix.Task
|
||
|
|
||
|
alias Expo.Message
|
||
|
alias Expo.Messages
|
||
|
alias Expo.PO
|
||
|
alias Expo.PO.DuplicateMessagesError
|
||
|
|
||
|
@switches [output_file: :string]
|
||
|
@aliases [o: :output_file]
|
||
|
@default_options [output_file: "-"]
|
||
|
|
||
|
@impl Mix.Task
|
||
|
def run(args) do
|
||
|
{:ok, _} = Application.ensure_all_started(:expo)
|
||
|
{opts, argv} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
||
|
|
||
|
opts = Keyword.merge(@default_options, opts)
|
||
|
|
||
|
output =
|
||
|
case opts[:output_file] do
|
||
|
"-" -> IO.stream(:stdio, :line)
|
||
|
file -> File.stream!(file)
|
||
|
end
|
||
|
|
||
|
file =
|
||
|
case argv do
|
||
|
[] ->
|
||
|
Mix.raise("""
|
||
|
mix expo.msguniq failed due to missing po file path argument
|
||
|
""")
|
||
|
|
||
|
[_file_one, _file_two | _other_files] ->
|
||
|
Mix.raise("""
|
||
|
mix expo.msguniq failed due to multiple po file path arguments
|
||
|
Only one is currently supported
|
||
|
""")
|
||
|
|
||
|
[file] ->
|
||
|
file
|
||
|
end
|
||
|
|
||
|
case PO.parse_file(file) do
|
||
|
{:ok, _messages} ->
|
||
|
:ok
|
||
|
|
||
|
{:error, %DuplicateMessagesError{duplicates: duplicates, catalogue: catalogue}} ->
|
||
|
po =
|
||
|
duplicates
|
||
|
|> Enum.reduce(catalogue, &merge_duplicate/2)
|
||
|
|> PO.compose()
|
||
|
|> Enum.map(&List.wrap/1)
|
||
|
|
||
|
_output = Enum.into(po, output)
|
||
|
|
||
|
IO.puts(:stderr, IO.ANSI.format("Merged #{length(duplicates)} translations"))
|
||
|
|
||
|
{:error, error} ->
|
||
|
raise error
|
||
|
end
|
||
|
end
|
||
|
|
||
|
defp merge_duplicate(
|
||
|
{duplicate, _error_message, _line, _original_line},
|
||
|
%Messages{messages: messages} = po
|
||
|
) do
|
||
|
%Messages{
|
||
|
po
|
||
|
| messages:
|
||
|
Enum.map(messages, fn message ->
|
||
|
if Message.key(message) == Message.key(duplicate) do
|
||
|
Message.merge(message, duplicate)
|
||
|
else
|
||
|
message
|
||
|
end
|
||
|
end)
|
||
|
}
|
||
|
end
|
||
|
end
|