Reputation: 181
Consider a python package that has multilanguage support (using gettext
). How to compile *.po
files to *.mo
files on the fly when executing setup.py
? I really don't want to distribute precompiled *.mo
files.
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from distutils.core import setup
setup(
name='tractorbeam',
version='0.1.0',
url='http://starfleet.org/tractorbeam/',
description='Pull beer out of the fridge while sitting on the couch.',
author='James T. Kirk',
author_email= '[email protected]',
packages=['tractorbeam'],
package_data={
'tractorbeam': [
'locale/*.po',
'locale/*.mo', # How to compile on the fly?
]
},
install_requires=[
'requests'
]
)
Thanks in advance!
Upvotes: 5
Views: 2894
Reputation: 789
I could share my version of *.mo
files compilation process:
import glob
import pathlib
import subprocess
(...)
PO_FILES = 'translations/locale/*/LC_MESSAGES/app_name.po'
def create_mo_files():
mo_files = []
prefix = 'app_name'
for po_path in glob.glob(str(pathlib.Path(prefix) / PO_FILES)):
mo = pathlib.Path(po_path.replace('.po', '.mo'))
subprocess.run(['msgfmt', '-o', str(mo), po_path], check=True)
mo_files.append(str(mo.relative_to(prefix)))
return mo_files
(...)
setup(
(...)
package_data = {
'app_name': [
(...)
] + create_mo_files(),
},
)
@edit Comment:
For example pl
translation file:
app_name/translations/locale/pl/LC_MESSAGES/app_name.po
function create_mo_files()
creates compiled app_name.mo
file
app_name/translations/locale/pl/LC_MESSAGES/app_name.mo
and then on package build this app_name.mo
file is copying to
package/translations/locale/pl/LC_MESSAGES/app_name.po
Upvotes: 1
Reputation: 5027
I know this question begins to be a bit old, but in case anyone's still looking for an answer: it's possible to add a function to setup.py
that will compile po files and return the data_files
list. I didn't choose to include them in package_data
because data_files
's description looked more appropriate:
configuration files, message catalogs, data files, anything which doesn’t fit in the previous categories.
Of course you can only append this list to the one you're already using, but assuming you only have these mo files to add in data_files, you can write:
setup(
.
.
.
data_files=create_mo_files(),
.
.
.
)
For your information, here's the function create_mo_files()
I use. I don't pretend it's the best implementation possible. I put it here because it looks useful and is easy to adapt. Note that it's a bit more extra-complicated than what you need because it doesn't assume there's only one po file to compile per directory, it deals with several instead; note also that it assumes that all po files are located in something like locale/language/LC_MESSAGES/*.po
, you'll have to change it to fit your needs:
def create_mo_files():
data_files = []
localedir = 'relative/path/to/locale'
po_dirs = [localedir + '/' + l + '/LC_MESSAGES/'
for l in next(os.walk(localedir))[1]]
for d in po_dirs:
mo_files = []
po_files = [f
for f in next(os.walk(d))[2]
if os.path.splitext(f)[1] == '.po']
for po_file in po_files:
filename, extension = os.path.splitext(po_file)
mo_file = filename + '.mo'
msgfmt_cmd = 'msgfmt {} -o {}'.format(d + po_file, d + mo_file)
subprocess.call(msgfmt_cmd, shell=True)
mo_files.append(d + mo_file)
data_files.append((d, mo_files))
return data_files
(you'll have to import os
and subprocess
to use it)
Upvotes: 4