"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "translate/storage/jsonl10n.py" between
translate-toolkit-2.2.4.tar.gz and translate-toolkit-2.2.5.tar.gz

About: Translate Toolkit is a set of software and documentation designed to make localization of software more productive and less frustrating.

jsonl10n.py  (translate-toolkit-2.2.4):jsonl10n.py  (translate-toolkit-2.2.5)
skipping to change at line 70 skipping to change at line 70
} }
TODO: TODO:
- Handle ``\u`` and other escapes in Unicode - Handle ``\u`` and other escapes in Unicode
- Manage data type storage and conversion. True --> "True" --> True - Manage data type storage and conversion. True --> "True" --> True
""" """
import json import json
import os import uuid
from collections import OrderedDict from collections import OrderedDict
import six import six
from translate.misc.multistring import multistring
from translate.storage import base from translate.storage import base
class JsonUnit(base.TranslationUnit): class JsonUnit(base.TranslationUnit):
"""A JSON entry""" """A JSON entry"""
def __init__(self, source=None, ref=None, item=None, **kwargs): def __init__(self, source=None, ref=None, item=None, **kwargs):
self._id = None identifier = str(uuid.uuid4())
self._item = str(os.urandom(30)) self._id = '.' + identifier
if item is not None: self._item = identifier if item is None else item
self._item = item self._ref = OrderedDict() if ref is None else ref
self._ref = {}
if ref is not None:
self._ref = ref
if ref is None and item is None: if ref is None and item is None:
self._ref[self._item] = "" self._ref[self._item] = ""
if source: if source:
self.source = source self.source = source
super(JsonUnit, self).__init__(source) super(JsonUnit, self).__init__(source)
def getsource(self): def getsource(self):
return self.target return self.target
def setsource(self, source): def setsource(self, source):
skipping to change at line 140 skipping to change at line 138
def setid(self, value): def setid(self, value):
self._id = value self._id = value
def getid(self): def getid(self):
return self._id return self._id
def getlocations(self): def getlocations(self):
return [self.getid()] return [self.getid()]
def __str__(self):
"""Converts to a string representation."""
return ", ".join([
"%s: %s" % (k, self.__dict__[k]) for k in sorted(self.__dict__.keys(
)) if k not in ('_store', '_ref')
])
class JsonFile(base.TranslationStore): class JsonFile(base.TranslationStore):
"""A JSON file""" """A JSON file"""
UnitClass = JsonUnit UnitClass = JsonUnit
def __init__(self, inputfile=None, filter=None, **kwargs): def __init__(self, inputfile=None, filter=None, **kwargs):
"""construct a JSON file, optionally reading in from inputfile.""" """construct a JSON file, optionally reading in from inputfile."""
super(JsonFile, self).__init__(**kwargs) super(JsonFile, self).__init__(**kwargs)
self._filter = filter self._filter = filter
self.filename = '' self.filename = ''
self._file = u'' self._file = u''
if inputfile is not None: if inputfile is not None:
self.parse(inputfile) self.parse(inputfile)
def serialize(self, out): def serialize_units(self):
units = OrderedDict() units = OrderedDict()
for unit in self.unit_iter(): for unit in self.unit_iter():
path = unit.getid().lstrip('.') path = unit.getid().lstrip('.')
units[path] = unit.target units[path] = unit.target
return units
def serialize(self, out):
units = self.serialize_units()
out.write(json.dumps(units, separators=(',', ': '), out.write(json.dumps(units, separators=(',', ': '),
indent=4, ensure_ascii=False).encode(self.encoding) ) indent=4, ensure_ascii=False).encode(self.encoding) )
out.write(b'\n') out.write(b'\n')
def _extract_translatables(self, data, stop=None, prev="", name_node=None, def _extract_translatables(self, data, stop=None, prev="", name_node=None,
name_last_node=None, last_node=None): name_last_node=None, last_node=None):
"""Recursive function to extract items from the data files """Recursive function to extract items from the data files
:param data: the current branch to walk down :param data: the current branch to walk down
:param stop: a list of leaves to extract or None to extract everything :param stop: a list of leaves to extract or None to extract everything
skipping to change at line 229 skipping to change at line 237
for k, data, ref, item in self._extract_translatables(self._file, for k, data, ref, item in self._extract_translatables(self._file,
stop=self._filter) : stop=self._filter) :
unit = self.UnitClass(data, ref, item) unit = self.UnitClass(data, ref, item)
unit.setid(k) unit.setid(k)
self.addunit(unit) self.addunit(unit)
class JsonNestedFile(JsonFile): class JsonNestedFile(JsonFile):
"""A JSON file with nested keys""" """A JSON file with nested keys"""
def serialize(self, out): def nested_set(self, target, path, value):
def nested_set(target, path, value): if len(path) > 1:
if len(path) > 1: if path[0] not in target:
if path[0] not in target: target[path[0]] = OrderedDict()
target[path[0]] = OrderedDict() self.nested_set(target[path[0]], path[1:], value)
nested_set(target[path[0]], path[1:], value) else:
else: target[path[0]] = value
target[path[0]] = value
def serialize_units(self):
units = OrderedDict() units = OrderedDict()
for unit in self.unit_iter(): for unit in self.unit_iter():
path = unit.getid().lstrip('.').split('.') path = unit.getid().lstrip('.').split('.')
nested_set(units, path, unit.target) self.nested_set(units, path, unit.target)
out.write(json.dumps(units, separators=(',', ': '), return units
indent=4, ensure_ascii=False).encode(self.encoding)
)
out.write(b'\n')
class WebExtensionJsonUnit(base.TranslationUnit): class WebExtensionJsonUnit(base.TranslationUnit):
def __init__(self, source=None, ref=None, item=None): def __init__(self, source=None, ref=None, item=None):
identifier = str(uuid.uuid4())
self._id = identifier
self._item = identifier if item is None else item
self.notes = ''
self._rich_target = None
if ref: if ref:
self._node = ref self._node = ref
self.notes = ref['description'] if 'description' in ref:
self.notes = ref['description']
self._target = ref['message'] self._target = ref['message']
else: else:
self._node = OrderedDict((('message', ''), ('description', ''))) self._node = OrderedDict((('message', source if source else ''), ('d
super(WebExtensionJsonUnit, self).__init__(source) escription', '')))
if source:
self._target = source
super(WebExtensionJsonUnit, self).__init__()
def setid(self, value): def setid(self, value):
self._id = value self._id = value
def getid(self): def getid(self):
return self._id return self._id
def getlocations(self): def getlocations(self):
return [self.getid()] return [self.getid()]
def getsource(self):
return self.target
def setsource(self, source):
self.target = source
source = property(getsource, setsource)
def settarget(self, target): def settarget(self, target):
super(WebExtensionJsonUnit, self).settarget(target) super(WebExtensionJsonUnit, self).settarget(target)
self._node['message'] = target self._node['message'] = target
def addnote(self, text, origin=None, position="append"): def addnote(self, text, origin=None, position="append"):
super(WebExtensionJsonUnit, self).addnote(text, origin, position) super(WebExtensionJsonUnit, self).addnote(text, origin, position)
self._node['description'] = self.notes self._node['description'] = self.notes
def removenotes(self): def removenotes(self):
super(WebExtensionJsonUnit, self).removenotes() super(WebExtensionJsonUnit, self).removenotes()
self._node['description'] = self.notes if self.notes:
self._node['description'] = self.notes
else:
del self._node['description']
def __str__(self):
"""Converts to a string representation."""
return json.dumps(self._node, separators=(',', ': '), indent=4, ensure_a
scii=False)
class WebExtensionJsonFile(JsonFile): class WebExtensionJsonFile(JsonFile):
"""WebExtension JSON file """WebExtension JSON file
See following URLs for doc: See following URLs for doc:
https://developer.chrome.com/extensions/i18n https://developer.chrome.com/extensions/i18n
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Internationalizati on https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Internationalizati on
""" """
UnitClass = WebExtensionJsonUnit UnitClass = WebExtensionJsonUnit
def _extract_translatables(self, data, stop=None, prev="", name_node=None, def _extract_translatables(self, data, stop=None, prev="", name_node=None,
name_last_node=None, last_node=None): name_last_node=None, last_node=None):
for item in data: for item in data:
yield (item, item, data[item], None) yield (item, item, data[item], item)
def serialize(self, out): def serialize_units(self):
units = OrderedDict() units = OrderedDict()
for unit in self.unit_iter(): for unit in self.unit_iter():
units[unit.getid()] = unit._node units[unit.getid()] = unit._node
out.write(json.dumps(units, separators=(',', ': '), return units
indent=4, ensure_ascii=False).encode(self.encoding)
) class I18NextUnit(JsonUnit):
out.write(b'\n') """A i18next v3 format, JSON with plurals.
See https://www.i18next.com/
"""
def gettarget(self):
def change_type(value):
if isinstance(value, bool):
return str(value)
return value
if isinstance(self._item, list):
return multistring([
self._ref[item] for item in self._item
])
if isinstance(self._ref, list):
return change_type(self._ref[self._item])
elif isinstance(self._ref, dict):
return change_type(self._ref[self._item])
def settarget(self, target):
def change_type(oldvalue, newvalue):
if isinstance(oldvalue, bool):
newvalue = bool(newvalue)
return newvalue
def get_base(item):
"""Return base name for plurals"""
if '_0' in item[0]:
return item[0][:-2]
else:
return item[0]
def get_plurals(count, base):
if count <= 2:
return [base, base + '_plural'][:count]
return ['{0}_{1}'.format(base, i) for i in range(count)]
if isinstance(self._ref, list):
self._ref[int(self._item)] = change_type(self._ref[int(self._item)],
target)
elif isinstance(self._ref, dict):
cleanup = ()
if isinstance(target, multistring):
count = len(target.strings)
if not isinstance(self._item, list):
self._item = [self._item]
if count != len(self._item):
# Generate new plural labels
newitems = get_plurals(count, get_base(self._item))
cleanup = set(self._item) - set(newitems)
self._item = newitems
# Store plural values
for i, value in enumerate(target.strings):
self._ref[self._item[i]] = value
elif isinstance(self._item, list):
# Changing plural to singular
newitem = get_base(self._item)
cleanup = set(self._item) - set([newitem])
self._item = newitem
self._ref[self._item] = target
else:
self._ref[self._item] = change_type(self._ref[self._item], targe
t)
for item in cleanup:
if item in self._ref:
del self._ref[item]
else:
raise ValueError("We don't know how to handle:\n"
"Type: %s\n"
"Value: %s" % (type(self._ref), target))
target = property(gettarget, settarget)
def get_path(self):
if isinstance(self._item, list):
base = self.getid().lstrip('.').split('.')[:-1]
return [base + [item] for item in self._item]
return self.getid().lstrip('.').split('.')
class I18NextFile(JsonNestedFile):
"""A i18next v3 format, this is nested JSON with several additions.
See https://www.i18next.com/
"""
UnitClass = I18NextUnit
def _extract_translatables(self, data, stop=None, prev="", name_node=None,
name_last_node=None, last_node=None):
if isinstance(data, dict):
plurals_multiple = [key.rsplit('_', 1)[0] for key in data if key.end
swith('_0')]
plurals_simple = [key.rsplit('_', 1)[0] for key in data if key.endsw
ith('_plural')]
processed = set()
for k, v in six.iteritems(data):
# Check already processed items
if k in processed:
continue
plurals = []
plural_base = ''
if k in plurals_simple or k + '_plural' in plurals_simple:
if k.endswith('_plural'):
plural_base = k[:-7]
else:
plural_base = k
plurals_simple.remove(plural_base)
plurals = [k, k + '_plural']
elif '_' in k:
plural_base, digit = k.rsplit('_', 1)
if plural_base in plurals_multiple and digit.isdigit():
plurals_multiple.remove(plural_base)
plurals = ['{0}_{1}'.format(plural_base, order) for orde
r in range(10)]
if plurals:
sources = []
items = []
for key in plurals:
if key not in data:
break
processed.add(key)
sources.append(data[key])
items.append(key)
yield ("%s.%s" % (prev, plural_base), multistring(sources),
data, items)
continue
for x in self._extract_translatables(v, stop,
"%s.%s" % (prev, k),
k, None, data):
yield x
else:
parent = super(I18NextFile, self)._extract_translatables(
data, stop, prev, name_node, name_last_node, last_node
)
for x in parent:
yield x
def serialize_units(self):
units = OrderedDict()
for unit in self.unit_iter():
target = unit.target
path = unit.get_path()
if isinstance(target, multistring):
for i, value in enumerate(target.strings):
self.nested_set(units, path[i], value)
else:
self.nested_set(units, path, target)
return units
 End of changes. 17 change blocks. 
28 lines changed or deleted 58 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)