Skip to content

Instantly share code, notes, and snippets.

@fle
Last active August 29, 2015 14:25
Show Gist options
  • Save fle/643d555be36624a8f4d6 to your computer and use it in GitHub Desktop.
Save fle/643d555be36624a8f4d6 to your computer and use it in GitHub Desktop.
Automatically creates a new .po file with msgstr strings built from msgid strings prefixed by [`lang`]. Goal is ability to check easily where you forgot to add a gettext call.
"""
Based on a .po file `source`, creates a .po file `destination` with msgstr
strings built from msgid strings prefixed by [`lang`]
$ python3 utils/mock_po_file.py --lang FR --source en.po --destination fr.po
Example :
# en.po
msgid "Hello"
msgstr ""
# fr.po
msgid "Hello"
msgstr "[FR] Hello"
"""
import sys
import optparse
from os import path
BLANK_LINE = '\n'
MSGID_START = 'msgid "'
MSGID_MULTI = 'msgid ""\n"'
MSGID_MULTI_START_BY_NL = 'msgid ""\n"\\n'
MSGID_PLURAL_START = 'msgid_plural "'
MSGID_PLURAL_MULTI = 'msgid_plural ""\n"'
MSGID_PLURAL_MULTI_START_BY_NL = 'msgid_plural ""\n"\\n'
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--lang', dest='lang',
help='destination language (ex: EN)')
parser.add_option(
'--source', dest='source',
help='Path to .po source file')
parser.add_option(
'--destination', dest='destination',
help='Path to .po destination file')
options, args = parser.parse_args()
if not options.lang:
parser.error('Lang not given')
if not options.source:
parser.error('Source file not given')
elif not path.isfile(options.source):
parser.error('Source file does not exist')
if not options.destination:
parser.error('Destination file not given')
elif not path.isdir(path.abspath(path.dirname(options.destination))):
parser.error('Destination directory does not exist')
return options
def _msgid2msgstr(msgid, is_plural, has_plural, lang):
"""
msgid can be :
- classical form (no singular/plural)
- singular form
- plural form
msgid can also :
- be mono-line
- be multi-lines and start directly with text
- be multi-lines and start with a \n
"""
if not is_plural and not has_plural:
msgstr_start = 'msgstr'
start = MSGID_START
start_multi = MSGID_MULTI
start_by_nl_multi = MSGID_MULTI_START_BY_NL
elif not is_plural and has_plural:
msgstr_start = 'msgstr[0]'
start = MSGID_START
start_multi = MSGID_MULTI
start_by_nl_multi = MSGID_MULTI_START_BY_NL
elif is_plural and has_plural:
msgstr_start = 'msgstr[1]'
start = MSGID_PLURAL_START
start_multi = MSGID_PLURAL_MULTI
start_by_nl_multi = MSGID_PLURAL_MULTI_START_BY_NL
if msgid.startswith(start_by_nl_multi):
msgstr = msgid.replace(
start_by_nl_multi,
'%s ""\n"\\n[%s]' % (msgstr_start, lang))
elif msgid.startswith(start_multi):
msgstr = msgid.replace(
start_multi,
'%s ""\n"[%s] ' % (msgstr_start, lang))
else:
msgstr = msgid.replace(
start,
'%s "[%s] ' % (msgstr_start, lang))
return msgstr
def main():
""" Fill a po file with msgid preceded by [<lang>] """
options = _parse_args()
if path.isfile(options.destination):
print("/!\ Warning /!\ ")
print("Do really want to override %s?" % options.destination)
conf = input('(Y/N) > ')
if conf != 'Y':
exit()
content = ''
msgid = None
msgid_plural = None
in_header = True
with open(options.source, 'r') as f:
for i, line in enumerate(f):
if in_header and line == BLANK_LINE:
in_header = False
elif line.startswith('"Language: '):
content += '"Language: {}\\n"\n'.format(options.lang)
continue
elif in_header:
# keep any line intact in file headers (until first blank line)
content += '{}'.format(line)
continue
if not line.startswith("msgstr"):
# keep any line intact but msgstr
content += '{}'.format(line)
if line.startswith(MSGID_START):
# We are reading the begining of a msgid string
# Start collect it
msgid = '{}'.format(line)
continue
elif line.startswith(MSGID_PLURAL_START):
# We are reading the begining of a msgid plural string
# Start collect it
msgid_plural = '{}'.format(line)
continue
elif msgid_plural is not None and line.startswith('"'):
# Continue collecting msgid_plural string
msgid_plural += '{}'.format(line)
elif msgid is not None and line.startswith('"'):
# Continue collecting msgid string
msgid += '{}'.format(line)
elif msgid is not None and line.startswith('msgstr'):
has_plural = msgid_plural is not None
# Transform msgid into msgstr prefixed by language code
msgstr = _msgid2msgstr(
msgid,
False,
has_plural,
options.lang)
content += '{}'.format(msgstr)
if msgid_plural is not None:
# If any, transform msgid plural form into msgstr prefixed
# by language code
msgstr = _msgid2msgstr(
msgid_plural,
True,
has_plural,
options.lang)
content += '{}'.format(msgstr)
msgid = None
msgid_plural = None
else:
pass
# Write destination po file
with open(options.destination, 'w') as f:
f.write(content)
if __name__ == '__main__':
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment