Skip to content

Commit b3246ba

Browse files
committed
Check and autocorrect translated configuration files
Check and autocorrect the attributes of the option settings in translated configuration files. Check and autocorrect the value tags of the option settings in translated configuration files. Note: during the corrections no automatic translations are done.
1 parent f4ce44f commit b3246ba

1 file changed

Lines changed: 216 additions & 6 deletions

File tree

src/configgen.py

Lines changed: 216 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -732,19 +732,24 @@ def collectOptions(elem):
732732
options = set()
733733
messages = set()
734734
optionsWithElems = {}
735+
attrib = {}
736+
values = set()
735737
for group in elem.getElementsByTagName('group'):
736738
for option in group.getElementsByTagName('option'):
737739
optionId = option.getAttribute('id')
738740
optionType = option.getAttribute('type')
739741
if optionId and optionType!='obsolete':
740742
options.add(optionId)
741743
optionsWithElems[optionId] = option
744+
attrib[optionId] = sorted(option.attributes.items())
745+
if option.getElementsByTagName('value'):
746+
values.add(optionId)
742747
for generator in elem.getElementsByTagName('generator'):
743748
for message in generator.getElementsByTagName('message'):
744749
messageId = message.getAttribute('name')
745750
messages.add(messageId)
746751

747-
return (options,optionsWithElems,messages)
752+
return (options,optionsWithElems,messages,attrib,values)
748753

749754
def syncWarnings(typ, existing, language):
750755
missing = existing - language
@@ -777,7 +782,7 @@ def syncLocalizedConfig(elem, configFile, translationsDir, autoSync=False):
777782
import os
778783
import shutil
779784

780-
existingOptions, existingOptionsWithElements, existingMessages = collectOptions(elem)
785+
existingOptions, existingOptionsWithElements, existingMessages, existingAttrib, existingValues = collectOptions(elem)
781786
print("Found %d active options in %s" % (len(existingOptions), configFile))
782787
print("Found %d active messages in %s" % (len(existingMessages), configFile))
783788

@@ -801,12 +806,104 @@ def syncLocalizedConfig(elem, configFile, translationsDir, autoSync=False):
801806
print(" Error parsing %s: %s" % (configFile, e))
802807
continue
803808

804-
langOptions, langOptionsWithElements, langMessages = collectOptions(langDoc)
809+
langOptions, langOptionsWithElements, langMessages, langAttrib, langValues = collectOptions(langDoc)
805810

806811
optionsError = syncWarnings('Options', existingOptions, langOptions)
807812
messagesError = syncWarnings('Messages', existingMessages, langMessages)
808813

809-
if autoSync and (optionsError or messagesError):
814+
# attributes handling
815+
extraOptions = langOptions - existingOptions
816+
langMatch = langOptions - extraOptions
817+
attribError = set()
818+
for optionId in langMatch:
819+
missingAttrib = set(existingAttrib[optionId]) - set(langAttrib[optionId])
820+
extraAttrib = set(langAttrib[optionId]) - set(existingAttrib[optionId])
821+
if missingAttrib:
822+
attribError.add(optionId)
823+
print(" Missing %d %s for %s" % (len(missingAttrib), "attributes", optionId))
824+
825+
if extraAttrib:
826+
attribError.add(optionId)
827+
print(" Extra %d %s for %s" % (len(extraAttrib), "attributes", optionId))
828+
if not attribError:
829+
print(" OK - all %s are synchronized" % "attributes")
830+
831+
# values handling
832+
valuesError = False
833+
# we only need options that are also in the original
834+
langValues = langValues - extraOptions
835+
# language options that should have values
836+
missingAllValues = existingValues - langValues
837+
if missingAllValues:
838+
print(" Missing %d %s: %s" % (len(missingAllValues), "all values", ', '.join(sorted(list(missingAllValues))[:5])))
839+
if len(missingAllValues) > 5:
840+
print(" ... and %d more" % (len(missingAllValues) - 5))
841+
valuesError = True
842+
# language options that should have no values
843+
extraAllValues = langValues - existingValues
844+
if extraAllValues:
845+
print(" Extra %d %s: %s" % (len(extraAllValues), "all values", ', '.join(sorted(list(extraAllValues))[:5])))
846+
if len(extraAllValues) > 5:
847+
print(" ... and %d more" % (len(extraAllValues) - 5))
848+
valuesError = True
849+
850+
# both have values, some furter investigations
851+
bothValues = existingValues - missingAllValues
852+
# partial extra / missing attr
853+
bothError = set()
854+
for optionId in bothValues:
855+
optionElem = existingOptionsWithElements[optionId]
856+
langElem = langOptionsWithElements[optionId]
857+
optValues = set()
858+
langValues = set()
859+
for optValue in optionElem.getElementsByTagName('value'):
860+
optValues.add(optValue.getAttribute('name'))
861+
for langValue in langElem.getElementsByTagName('value'):
862+
langValues.add(langValue.getAttribute('name'))
863+
missingValues = optValues - langValues
864+
missingLen = len(missingValues)
865+
extraLen = len(langValues - optValues)
866+
if missingLen:
867+
print(" Missing %d %s for %s" % (missingLen, "values", optionId))
868+
bothError.add(optionId)
869+
if extraLen:
870+
print(" Extra %d %s for %s" % (extraLen, "values", optionId))
871+
bothError.add(optionId)
872+
# both have value elements
873+
bothName = optValues - missingValues
874+
for name in bothName:
875+
toCorrect = False
876+
for optValue in optionElem.getElementsByTagName('value'):
877+
if optValue.getAttribute('name') == name:
878+
optAttr = set(optValue.attributes.items())
879+
break
880+
for langValue in langElem.getElementsByTagName('value'):
881+
if langValue.getAttribute('name') == name:
882+
langAttr = set(langValue.attributes.items())
883+
break
884+
missing = optAttr - langAttr
885+
extra = langAttr - optAttr
886+
if missing or extra:
887+
if len(missing) == 1 and len(extra) == 1:
888+
for attr, dummy in missing:
889+
missAttr = attr
890+
break
891+
for attr, dummy in extra:
892+
extraAttr = attr
893+
break
894+
if missAttr != 'desc' or extraAttr != 'desc':
895+
bothError.add(optionId)
896+
toCorrect = True
897+
else:
898+
bothError.add(optionId)
899+
toCorrect = True
900+
if toCorrect:
901+
print(" Differences in attributes for %s with name %s for %s" % ("value", name, optionId))
902+
903+
if not (valuesError or bothError):
904+
print(" OK - all %s are synchronized" % "values")
905+
906+
if autoSync and (optionsError or messagesError or attribError or valuesError or bothError):
810907
print(" Auto-syncing...")
811908

812909
rootElement = langDoc.documentElement
@@ -838,6 +935,118 @@ def syncLocalizedConfig(elem, configFile, translationsDir, autoSync=False):
838935
parentGroupNew.appendChild(importedElem)
839936
print(" Added: %s" % optionId)
840937

938+
# handle option attributes
939+
for optionId in attribError:
940+
existingElem = existingOptionsWithElements[optionId]
941+
langElem = langOptionsWithElements[optionId]
942+
for attr,val in langElem.attributes.items():
943+
langElem.removeAttribute(attr)
944+
for attr,val in existingElem.attributes.items():
945+
langElem.setAttribute(attr,val)
946+
947+
# handle values
948+
for optionId in extraAllValues:
949+
optionElem = langOptionsWithElements[optionId]
950+
for valueElem in optionElem.getElementsByTagName('value'):
951+
optionElem.removeChild(valueElem)
952+
print(" Removed all values of: %s" % optionId)
953+
954+
for optionId in missingAllValues:
955+
existingElem = existingOptionsWithElements[optionId]
956+
langElem = langOptionsWithElements[optionId]
957+
for valueElem in existingElem.getElementsByTagName('value'):
958+
importedElem = langDoc.importNode(valueElem, True)
959+
langElem.appendChild(importedElem)
960+
print(" Added all values for: %s" % optionId)
961+
962+
# handle bothValue errors
963+
for optionId in bothError:
964+
optionElem = existingOptionsWithElements[optionId]
965+
langElem = langOptionsWithElements[optionId]
966+
optValues = set()
967+
langValues = set()
968+
for optValue in optionElem.getElementsByTagName('value'):
969+
optValues.add(optValue.getAttribute('name'))
970+
for langValue in langElem.getElementsByTagName('value'):
971+
langValues.add(langValue.getAttribute('name'))
972+
missing = optValues - langValues
973+
extra = langValues - optValues
974+
existingElem = existingOptionsWithElements[optionId]
975+
langElem = langOptionsWithElements[optionId]
976+
if missing:
977+
for miss in missing:
978+
for allVal in existingElem.getElementsByTagName('value'):
979+
if allVal.getAttribute('name') == miss:
980+
importedElem = langDoc.importNode(allVal, True)
981+
langElem.appendChild(importedElem)
982+
print(" Added: value %s of %s" % (miss,optionId))
983+
if extra:
984+
for extr in extra:
985+
for allVal in langElem.getElementsByTagName('value'):
986+
if allVal.getAttribute('name') == extr:
987+
langElem.removeChild(allVal)
988+
print(" Removed: value %s of %s" % (extr,optionId))
989+
990+
# both have value elements
991+
bothName = optValues - missing
992+
for name in bothName:
993+
toCorrect = False
994+
for optValue in optionElem.getElementsByTagName('value'):
995+
if optValue.getAttribute('name') == name:
996+
optAttr = set(optValue.attributes.items())
997+
break
998+
for langValue in langElem.getElementsByTagName('value'):
999+
if langValue.getAttribute('name') == name:
1000+
langAttr = set(langValue.attributes.items())
1001+
break
1002+
missing = optAttr - langAttr
1003+
extra = langAttr - optAttr
1004+
if missing or extra:
1005+
if len(missing) == 1 and len(extra) == 1:
1006+
for attr, dummy in missing:
1007+
missAttr = attr
1008+
break
1009+
for attr, dummy in extra:
1010+
extraAttr = attr
1011+
break
1012+
if missAttr != 'desc' or extraAttr != 'desc':
1013+
toCorrect = True
1014+
else:
1015+
toCorrect = True
1016+
1017+
if toCorrect:
1018+
optHasDesc = False
1019+
for optValue in optionElem.getElementsByTagName('value'):
1020+
if optValue.getAttribute('name') == name:
1021+
for attr, dummy in optValue.attributes.items():
1022+
if attr == 'desc':
1023+
optHasDesc = True
1024+
break
1025+
break
1026+
langHasDesc = False
1027+
for langValue in langElem.getElementsByTagName('value'):
1028+
if langValue.getAttribute('name') == name:
1029+
for attr, dummy in langValue.attributes.items():
1030+
if attr == 'desc':
1031+
langHasDesc = True
1032+
break
1033+
break
1034+
for langValue in langElem.getElementsByTagName('value'):
1035+
if langValue.getAttribute('name') == name:
1036+
for attr, dummy in langValue.attributes.items():
1037+
if attr != 'desc' or not optHasDesc:
1038+
langValue.removeAttribute(attr)
1039+
lang = langValue
1040+
break
1041+
for optValue in optionElem.getElementsByTagName('value'):
1042+
if optValue.getAttribute('name') == name:
1043+
for attr, val in optValue.attributes.items():
1044+
if attr != 'desc' or not langHasDesc:
1045+
lang.setAttribute(attr,val)
1046+
break
1047+
1048+
1049+
# handle generator / messages
8411050
missingMessages = existingMessages - langMessages
8421051
extraMessages = langMessages - existingMessages
8431052

@@ -856,7 +1065,8 @@ def syncLocalizedConfig(elem, configFile, translationsDir, autoSync=False):
8561065
for messageId in missingMessages:
8571066
for message in parentGenerator.getElementsByTagName('message'):
8581067
if messageId == message.getAttribute('name'):
859-
parentGeneratorNew.appendChild(message)
1068+
importedElem = langDoc.importNode(message, True)
1069+
parentGeneratorNew.appendChild(importedElem)
8601070
print(" Added: %s" % messageId)
8611071

8621072
backupFile = configFile + ".bak"
@@ -1110,7 +1320,7 @@ def main():
11101320
print("#include \"configdoc.h\"")
11111321
print("#include \"docintf.h\"")
11121322
print("")
1113-
##
1323+
11141324
print("void addConfigDocs{0}(DocIntf *doc)".format(locale))
11151325
print("{")
11161326
for n in elem.childNodes:

0 commit comments

Comments
 (0)