Repository: mesonbuild/meson

Issue:
i18n: need update-po target that does msgmerge
There is currently a `$gettextname-pot` target to update the .pot template file from the input files with translations; and the .po files for the specified languages will be compiled and installed correctly on `ninja install`.

What is missing is an `update-po` target that
1.  updates the .pot template (i.e. depends on  `$gettextname-pot` target)
2.  uses msgmerge to update the `*.po` files based on the `.pot` file

For bonus points, add something to pass extra arguments to the various tools like this from a typical po/Makevars:

```
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
...
# Avoid line numbers in *.po, but keep them in *.pot.
MSGMERGE = msgmerge --no-location
MSGMERGE_UPDATE = msgmerge --no-location --update --backup=off
MSGFILTER = msgfilter --no-location
```

Issue #554 added an `args` kwarg but it's too general I think.

Note that one would likely want the `*.po` files to be update _in the source directory_, since these are maintained in git.

The typical workflow from a maintainer/releaser is:
1. download latest translated version of all the .po files from somewhere (if translators don't work directly on the repository)
2. update pot from source files to pick up any added/removed/changes translation strings
3. update po files based on pot template file, so new strings get added, changed strings marked as fuzzy translation etc.

Translators will then be notified when a new release is out (or pending) and can update the .po files as needed (fill in missing translations for new strings; update fuzzy translations, etc.), then the cycle repeats.

Note: there might be different workflows or I might be misremembering things, so entirely possible I made up most of the above ;)



Discussion:

Resolving patch:
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -33,6 +33,12 @@ def gettext(self, state, args, kwargs):
         pottarget = build.RunTarget(packagename + '-pot', sys.executable, potargs, [], state.subdir)
         gmoargs = [state.environment.get_build_command(), '--internal', 'gettext', 'gen_gmo'] + languages
         gmotarget = build.RunTarget(packagename + '-gmo', sys.executable, gmoargs, [], state.subdir)
+        updatepoargs = [state.environment.get_build_command(), '--internal', 'gettext', 'update_po', packagename]
+        updatepoargs.append('@@'.join(languages))
+        if datadirs:
+            updatepoargs.append('--datadirs=' + ':'.join(datadirs))
+        updatepoargs += extra_args
+        updatepotarget = build.RunTarget(packagename + '-update-po', sys.executable, updatepoargs, [], state.subdir)
         installcmd = [sys.executable,
                       state.environment.get_build_command(),
                       '--internal',
@@ -43,7 +49,7 @@ def gettext(self, state, args, kwargs):
                       state.environment.coredata.get_builtin_option('localedir'),
                       ] + languages
         iscript = build.InstallScript(installcmd)
-        return [pottarget, gmotarget, iscript]
+        return [pottarget, gmotarget, iscript, updatepotarget]
 
 def initialize():
     return I18nModule()
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
--- a/mesonbuild/scripts/gettext.py
+++ b/mesonbuild/scripts/gettext.py
@@ -38,6 +38,13 @@ def gen_gmo(src_sub, bld_sub, langs):
                                '-o', os.path.join(bld_sub, l + '.gmo')])
     return 0
 
+def update_po(src_sub, pkgname, langs):
+    potfile = os.path.join(src_sub, pkgname + '.pot')
+    for l in langs:
+        pofile = os.path.join(src_sub, l + '.po')
+        subprocess.check_call(['msgmerge', '-q', '-o', pofile, pofile, potfile])
+    return 0
+
 def do_install(src_sub, bld_sub, dest, pkgname, langs):
     for l in langs:
         srcfile = os.path.join(bld_sub, l + '.gmo')
@@ -62,6 +69,15 @@ def run(args):
         src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
         bld_sub = os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR'])
         return gen_gmo(src_sub, bld_sub, args[1:])
+    elif subcmd == 'update_po':
+        pkgname = args[1]
+        langs = args[2].split('@@')
+        datadirs = args[3][11:] if args[3].startswith('--datadirs=') else None
+        extra_args = args[4:] if datadirs is not None else args[3:]
+        src_sub = os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR'])
+        if run_potgen(src_sub, pkgname, datadirs, extra_args) != 0:
+            return 1
+        return update_po(src_sub, pkgname, langs)
     elif subcmd == 'install':
         subdir = args[1]
         pkgname = args[2]


Test patch: