Packages
gettext
0.5.0
1.0.2
1.0.1
retired
1.0.0
0.26.2
0.26.1
0.26.0
retired
0.25.0
0.24.0
0.23.1
0.23.0
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
0.20.0
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.2
0.12.1
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.0
Internationalization and localization through gettext
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/gettext.merge.ex
defmodule Mix.Tasks.Gettext.Merge do
use Mix.Task
@recursive true
@shortdoc "Merge template files into translation files"
@moduledoc """
Merges template files (`.pot` files) into translation files (`.po` files).
If two files are given as arguments, they must be a `.po` and a `.po`/`.pot`
file). The first one is the old PO file, while the second one is the last
generated one. They are merged and written over the first file.
mix gettext.merge priv/gettext/en/LC_MESSAGES/default.pot priv/gettext/default.pot
If one file is given as an argument, then that file must be a directory
containing gettext translations (with `.pot` files at the root level alongside
locale directories).
mix gettext.merge DIR
If the `--locale LOCALE` option is given, then only the PO files in
`DIR/LOCALE/LC_MESSAGES` will be merged with the POT files in `DIR`. If no
options are given, then all the PO files for all locales under `DIR` are
merged with the POT files in `DIR`.
"""
alias Gettext.Merger
def run(args) do
_ = Mix.Project.get!
case OptionParser.parse(args, strict: [locale: :string]) do
{opts, [arg1, arg2], _} ->
run_with_two_args(arg1, arg2, opts)
{opts, [arg], _} ->
run_with_one_arg(arg, opts)
{_, [], _} ->
Mix.raise "gettext.merge requires at least one argument to work." <>
"Use `mix help gettext.merge` to see the usage of this task."
{_, _, _} ->
Mix.raise "Too many arguments for the gettext.merge task. " <>
"Use `mix help gettext.merge` to see the usage of this task."
end
end
defp run_with_two_args(arg1, arg2, []) do
if Path.extname(arg1) == ".po" and Path.extname(arg2) in [".po", ".pot"] do
ensure_file_exists!(arg1)
ensure_file_exists!(arg2)
{path, contents} = merge_po_with_pot(arg1, arg2)
File.write!(path, contents)
Mix.shell.info "Wrote #{path}"
else
Mix.raise "Arguments must be a PO file and a PO/POT file"
end
end
defp run_with_one_arg(arg, opts) do
ensure_dir_exists!(arg)
if locale = opts[:locale] do
merge_locale_dir(arg, locale)
else
merge_all_locale_dirs(arg)
end
end
defp merge_po_with_pot(po_file, pot_file) do
{po_file, Merger.merge_files(po_file, pot_file)}
end
defp merge_locale_dir(pot_dir, locale) do
locale_dir = locale_dir(pot_dir, locale)
ensure_dir_exists!(locale_dir)
merge_dirs(locale_dir, pot_dir)
end
defp merge_all_locale_dirs(pot_dir) do
pot_dir
|> ls_locale_dirs
|> Enum.each(&merge_dirs(&1, pot_dir))
end
defp locale_dir(dir, locale) do
Path.join([dir, locale, "LC_MESSAGES"])
end
defp ls_locale_dirs(dir) do
dir
|> File.ls!
|> Enum.filter(&File.dir?(Path.join(dir, &1)))
|> Enum.map(&locale_dir(dir, &1))
end
defp merge_dirs(po_dir, pot_dir) do
pot_dir
|> Path.join("**/*.pot")
|> Path.wildcard()
|> Enum.map(&find_matching_po(&1, po_dir))
|> Enum.map(&merge_or_create/1)
|> Enum.each(&write_file/1)
# Now warn for every PO file that has no matching POT file.
po_dir
|> Path.join("**/*.po")
|> Path.wildcard()
|> Enum.reject(&po_has_matching_pot?(&1, pot_dir))
|> Enum.map(&warn_for_missing_pot_file(&1, pot_dir))
end
defp find_matching_po(pot_file, po_dir) do
domain = Path.basename(pot_file, ".pot")
{pot_file, Path.join(po_dir, "#{domain}.po")}
end
defp merge_or_create({pot_file, po_file}) do
if File.regular?(po_file) do
{po_file, Merger.merge_files(po_file, pot_file)}
else
{po_file, Merger.new_po_file(po_file, pot_file)}
end
end
defp write_file({path, contents}) do
File.write!(path, contents)
Mix.shell.info "Wrote #{path}"
end
defp po_has_matching_pot?(po_file, pot_dir) do
domain = Path.basename(po_file, ".po")
pot_path = Path.join(pot_dir, "#{domain}.pot")
File.exists?(pot_path)
end
defp warn_for_missing_pot_file(po_file, pot_dir) do
Mix.shell.info "Warning: PO file #{po_file} has no matching POT file in #{pot_dir}"
end
defp ensure_file_exists!(path) do
unless File.regular?(path), do: Mix.raise("No such file: #{path}")
end
defp ensure_dir_exists!(path) do
unless File.dir?(path), do: Mix.raise("No such directory: #{path}")
end
end