Skip to content

Instantly share code, notes, and snippets.

@GaretJax
Created March 4, 2015 10:56
Show Gist options
  • Save GaretJax/d39af8122f6e5ea78f01 to your computer and use it in GitHub Desktop.
Save GaretJax/d39af8122f6e5ea78f01 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from __future__ import print_function, unicode_literals
import os
import math
import glob
import click
import polib
from openpyxl import load_workbook
def hr(char='\u2500', width=None, **kwargs):
if width is None:
width = click.get_terminal_size()[0]
mult = int(math.ceil(width * 1.0 / len(char)))
click.secho((char * mult)[:width], **kwargs)
def get_pofiles(locale_folders, language):
for folder in locale_folders:
rw_ro, folder = folder.split(':', 1)
assert rw_ro in ['rw', 'ro']
read_only = rw_ro == 'ro'
po_file = os.path.join(folder, language, 'LC_MESSAGES', '*.po')
for path in glob.glob(po_file):
yield read_only, polib.pofile(path)
class MsgStr(object):
def __init__(self, entry, multiplicity=0):
self.entry = entry
self.multiplicity = multiplicity
def get(self):
if self.entry.msgid_plural:
return self.entry.msgstr_plural[self.multiplicity]
else:
assert self.multiplicity == 0
return self.entry.msgstr
def set(self, value):
if self.entry.msgid_plural:
self.entry.msgstr_plural[self.multiplicity] = value
else:
self.entry.msgstr = value
@click.command()
@click.option('--key-col', '-k', type=int)
@click.option('--trans-col', '-t', type=int, default=1)
@click.option('--sheet', '-s', type=int)
@click.option('--pretend/--no-pretend', default=False)
@click.option('--language', '-l')
@click.option('--hide-ok/--show-ok', default=False)
@click.argument('workbook', type=click.Path(exists=True))
@click.argument('locale_folders', nargs=-1)
def main(workbook, locale_folders, language, key_col, trans_col, sheet,
pretend, hide_ok):
wb = load_workbook(workbook)
ws = list(wb)[sheet-1]
rows = iter(ws.iter_rows())
headers = next(rows)
if key_col is None or trans_col is None:
click.echo('The following columns are available:')
for i, cell in enumerate(headers):
if cell.value is not None:
click.echo('{:2d}. {}'.format(i + 1, cell.value))
if key_col is None:
key_col = click.prompt('Which column contains the key?',
type=int, default=1)
if trans_col is None:
trans_col = click.prompt('Which column contains the translation?',
type=int)
key_col -= 1
trans_col -= 1
hr(fg='yellow')
click.secho(' Selected sheet: {}'.format(ws.title))
click.secho(' Key column: {}'.format(headers[key_col].value))
click.secho(' Value column: {}'.format(headers[trans_col].value))
click.secho(' Language: {}'.format(language))
hr(fg='yellow')
pofiles = list(get_pofiles(locale_folders, language))
for row in rows:
key = row[key_col].value
trans = row[trans_col].value
if key is None and trans is None:
# This row can be safely ignored
continue
entry, msgstr = find_entry(pofiles, key, trans)
if entry:
handle_entry(entry, msgstr, key, trans, hide_ok)
if not pretend:
for read_only, po in pofiles:
if not read_only:
po.save()
def find_entry(pofiles, key, trans):
for read_only, po in pofiles:
entry = po.find(key)
if entry is not None:
msgstr = MsgStr(entry, 0)
break
entry = po.find(key, by='msgid_plural')
if entry is not None:
msgstr = MsgStr(entry, 1)
break
else:
# TODO: How do we want to handle this?
click.secho('The entry "{}" was not found.'.format(key), fg='red')
return None, None
if read_only:
if trans != msgstr.get():
click.secho('The entry "{}" has been translated as "{}" in "{}" but the '
'file is marked as read-only.'.format(key, msgstr.get(), po.fpath),
fg='red')
return None, None
return entry, msgstr
def handle_entry(entry, msgstr, key, trans, hide_ok):
if not trans or trans == msgstr.get():
# Already up to date
if not hide_ok:
click.secho('The entry "{}" is already up to date.'.format(key),
fg='green')
if 'fuzzy' in entry.flags:
entry.flags.remove('fuzzy')
return
if not entry.translated():
# Entry is in the file, but has not been translated
click.secho('The entry "{}" has not been translated yet.'
.format(key), fg='yellow')
msgstr.set(trans)
if 'fuzzy' in entry.flags:
entry.flags.remove('fuzzy')
return
# Entry has been translated but needs update
# TODO: Ask for confirmation
hr()
click.secho('The entry "{}" was updated:'.format(key))
click.secho(' OLD: "{}"'.format(msgstr.get()))
click.secho(' NEW: "{}"'.format(trans))
msgstr.set(trans)
hr()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment