Created
March 4, 2015 10:56
-
-
Save GaretJax/d39af8122f6e5ea78f01 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#!/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