Last active
August 29, 2015 14:25
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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