Skip to content

Commit

Permalink
1.6 - Xcode 10's Intents.intentdefinition file format support
Browse files Browse the repository at this point in the history
  • Loading branch information
metasmile committed Sep 23, 2018
1 parent 7eb3052 commit 3ee5110
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 48 deletions.
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -16,7 +16,7 @@

setup(
name="strsync",
version="1.5",
version="1.6",
packages=[
'strsync',
],
Expand Down
37 changes: 0 additions & 37 deletions strsync/strintentdefinition_draft.py

This file was deleted.

3 changes: 1 addition & 2 deletions strsync/strparser.py
Expand Up @@ -10,7 +10,7 @@
from __future__ import print_function
from __future__ import absolute_import
import codecs, re, chardet

import plistlib, re
"""
Handler for Apple STRINGS translation files.
Expand All @@ -19,7 +19,6 @@

format_encoding = 'UTF-16'


def __unescape_key(s):
return s.replace('\\\n', '')

Expand Down
95 changes: 95 additions & 0 deletions strsync/strparser_intentdefinition.py
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-

'''
Intents.intentdefinition Parser
'''

import plistlib, re

def __rgetKeyPair(dictionary, key, idKey=None):
items = []
for k in dictionary:
if k == key:
items.append({"value": str(dictionary[k]), "id": str(dictionary[idKey]) if idKey is not None else None })
else:
if isinstance(dictionary[k], list):
for item in dictionary[k]:
items += __rgetKeyPair(item, key, idKey)
elif isinstance(dictionary[k], dict):
items += __rgetKeyPair(dictionary[k], key, idKey)
return items

def __rgetDict(dictionary, key):
items = []
for k in dictionary:
if k == key:
items.append(dictionary[k])
else:
if isinstance(dictionary[k], list):
for item in dictionary[k]:
items += __rgetDict(item, key)
elif isinstance(dictionary[k], dict):
items += __rgetDict(dictionary[k], key)
return items


def parse_strings(file):
l = plistlib.readPlist(file)

keys = [
'INIntentTitle',
'INIntentDescription',
# 'INEnumValueDisplayName', # This key already used in 'INEnums'
'INIntentParameterCombinationTitle',
'INIntentResponseCodeFormatString',
'INIntentParameterCombinationSubtitle'
]
enum_items = {}
for i, enums in enumerate(__rgetDict(l, 'INEnums')):
for m in enums:
enum_items[m['INEnumName']] = [
{
'displayName':v['INEnumValueDisplayName'],
'id':v['INEnumValueDisplayNameID'],
'name':v['INEnumValueName']
} for v in m['INEnumValues'] if v['INEnumValueDisplayName']
]

enum_params = {e['id']: e['value'] for e in __rgetKeyPair(l, 'INIntentParameterEnumType', 'INIntentParameterName')}

stringset = []
for k in keys:
a = __rgetKeyPair(l, k, k+"ID")
for kObj in a:
id, value = kObj['id'], kObj['value']

if len(value):
found_enum_params = list(re.finditer('\$\{(.+)\}', value, flags=re.X))
if found_enum_params:
for m in found_enum_params:
enum_key = m.group(1)
if enum_key in enum_params:
for i, e in enumerate(enum_items[enum_params[enum_key]]):
enumerated_value = value.replace('${%s}' % enum_key, e['displayName'])
enumerated_key = "{}-{}".format(id, e['id'])
stringset.append({
'key': enumerated_key,
'value': enumerated_value,
'comment': None,
'error': None}
)
else:
stringset.append({
'key': id,
'value': value,
'comment': None,
'error': None}
)
else:
stringset.append({
'key': id,
'value': value,
'comment': None,
'error': None}
)
return stringset
29 changes: 21 additions & 8 deletions strsync/strsync.py
Expand Up @@ -3,7 +3,7 @@
# Copyright (c) 2015 metasmile cyrano905@gmail.com (github.com/metasmile)

from __future__ import print_function
import strparser, strlocale, strtrans
import strparser, strparser_intentdefinition, strlocale, strtrans
import time, os, sys, argparse, codecs, csv
from os.path import expanduser
from fuzzywuzzy import fuzz
Expand Down Expand Up @@ -75,6 +75,7 @@ def main():

__DIR_SUFFIX__ = ".lproj"
__FILE_SUFFIX__ = ".strings"
__FILE_INTENT_SUFFIX__ = ".intentdefinition"
__FILE_DICT_SUFFIX__ = ".stringsdict"
__RESOURCE_PATH__ = expanduser(args['target path'])
__BASE_LANG__ = args['base_lang_name']
Expand Down Expand Up @@ -130,9 +131,6 @@ def main():

global_result_logs = {}

def strings_obj_from_file(file):
return strparser.parse_strings(filename=file)

def merge_two_dicts(x, y):
'''Given two dicts, merge them into a new dict as a shallow copy.'''
z = x.copy()
Expand Down Expand Up @@ -292,12 +290,12 @@ def insert_or_translate(target_file, lc):
return updated_content and (len(adding_keys) > 0 or len(updated_keys) > 0 or len(
removing_keys) > 0), updated_content, translated_kv, target_error_lines, target_verified_items

def write_file(target_file, list_of_content):
def write_file(target_file, parsed_list):
suc = False
try:
f = codecs.open(target_file, "w", "utf-8")
contents = ''
for content in list_of_content:
for content in parsed_list:
if content['comment']:
contents += '/*{0}*/'.format(content['comment']) + '\n'
contents += '"{0}" = "{1}";'.format(content['key'], content['value']) + '\n'
Expand All @@ -324,7 +322,7 @@ def notexist_or_empty_file(target_file):
return not os.path.exists(target_file) or os.path.getsize(target_file) == 0

def resolve_file_names(target_file_names):
return map(lambda f: f.decode('utf-8'), filter(lambda f: f.endswith(__FILE_SUFFIX__), target_file_names))
return map(lambda f: f.decode('utf-8'), filter(lambda f: f.endswith(__FILE_SUFFIX__) or f.endswith(__FILE_INTENT_SUFFIX__), target_file_names))

base_dict = {}
results_dict = {}
Expand All @@ -337,10 +335,25 @@ def resolve_file_names(target_file_names):
if os.path.basename(dir) == __BASE_RESOUCE_DIR__:
for _file in resolve_file_names(files):
f = os.path.join(dir, _file)

if notexist_or_empty_file(f):
continue

parsed_obj = strings_obj_from_file(f)
parsed_obj = None

# parse .strings
if f.endswith(__FILE_SUFFIX__):
parsed_obj = strparser.parse_strings(filename=f)

# parse .intentdefinition
elif f.endswith(__FILE_INTENT_SUFFIX__):
print('[i] Found "{0}" in {1}. Parse ....'.format(os.path.basename(f), __BASE_RESOUCE_DIR__))
parsed_obj = strparser_intentdefinition.parse_strings(f)
# replace to dest extenstion .strings
_file = _file.replace(__FILE_INTENT_SUFFIX__, __FILE_SUFFIX__)
# write original .strings file to local
write_file(os.path.join(dir, _file), parsed_obj)

if not parsed_obj:
continue

Expand Down

0 comments on commit 3ee5110

Please sign in to comment.