Skip to content

Instantly share code, notes, and snippets.

@yanli0303
Created August 18, 2017 05:00
Show Gist options
  • Save yanli0303/fae31de16ea85d8787f0c6a68c0d6770 to your computer and use it in GitHub Desktop.
Save yanli0303/fae31de16ea85d8787f0c6a68c0d6770 to your computer and use it in GitHub Desktop.
import sys
import os
import re
import json
def _parse_strings_file_path():
if len(sys.argv) < 2:
return
ff = sys.argv[1]
if os.path.exists(ff) and os.path.isfile(ff):
return ff
def _is_single_line_comment(line):
return line[0:2] == '//'
def _is_block_comment_open_tag(line):
return line[0:2] == '/*'
def _after_block_comment_end_tag(line):
pos_block_comment_end_tag = line.find('*/')
if pos_block_comment_end_tag == -1:
return None
return line[pos_block_comment_end_tag + 2:].strip()
re_key_value_line = re.compile(r'^"((?:\\"|[^"])+)"\s*=\s*"((?:\\"|[^"])+)"\s*;')
def _parse_line(line):
if not line:
return None
if line[0] != '"':
return 'Invalid localization string line, it should begin with a quote: {}'.format(line)
# if line[-1] != ';':
# return 'Invalid localization string line, it should end with a semicolon: {}'.format(line)
match = re.search(re_key_value_line, line)
groups = match.groups() if match else []
if not groups or len(groups) != 2:
return 'Invalid localization string line, it should as in `"key" = "value";`: {}'.format(line)
return groups
def parse(file):
line_number = 0
next_line_is_comment = False
# { "key": {"value": "", "line_number: 0} }
items = {}
# { "line#10": "unable to parse line, duplicated keys" }
errors = {}
# { "line#10": "duplicated values" }
warnings = {}
with open(file, 'r') as reader:
for raw_line in reader:
line_number += 1
if next_line_is_comment:
line = _after_block_comment_end_tag(raw_line)
if line is not None:
next_line_is_comment = False
else:
line = raw_line.strip()
if not line:
continue
if _is_single_line_comment(line):
continue
if _is_block_comment_open_tag(line):
after_end_tag = _after_block_comment_end_tag(line[2:])
if not after_end_tag:
next_line_is_comment = True
continue
line = after_end_tag
key_value_pair = _parse_line(line)
if not key_value_pair:
continue
line_id = 'line#{}'.format(line_number)
if isinstance(key_value_pair, str):
errors[line_id] = key_value_pair
continue
key, value = key_value_pair
# error: duplicated keys
existing_value = items.get(key)
if existing_value:
vv = existing_value.get('value')
ll = existing_value.get('line_number')
errors[line_id] = ' '.join([
'Duplicated localization string key:',
'key "{}" is already defined at line #{}'.format(key, ll),
'with value "{}".'.format(vv)
])
# warning: duplicated values
for kk, dd in items.items():
vv = dd.get('value')
ll = dd.get('line_number')
if vv == value:
warnings[line_id] = ' '.join([
'Duplicated localization string:',
'string "{}" has previously assigned to key "{}"'.format(vv, kk),
'at line #{}; consider combine them.'.format(ll)
])
items[key] = {'value': value, 'line_number': line_number}
return items, errors, warnings
if __name__ == "__main__":
src_file = _parse_strings_file_path()
if not src_file:
print("Please provide a filename as argument")
exit(1)
else:
items, errors, warnings = parse(src_file)
json_str = json.dumps({"items": items, "errors": errors, "warnings": warnings}, indent=4)
print(json_str)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment