translations: more validations, ensure named placeholders match
This commit is contained in:
parent
3a8f6a0953
commit
dc6f333fae
|
@ -286,7 +286,7 @@ msgstr "تعبير الوظيفة المجدولة غير صحيح '%s'"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "من فضلك أضف المورد %(resource)s إلى الدليل %(config_resource)"
|
||||
msgstr "من فضلك أضف المورد %(resource)s إلى الدليل %(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -287,7 +287,7 @@ msgstr "Ugyldigt cron-udtryk '%s'"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "Tilføj ressource %(ressource)s til %(config_resource)s bibliotek"
|
||||
msgstr "Tilføj ressource %(resource)s til %(config_resource)s bibliotek"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -285,7 +285,7 @@ msgstr ""
|
|||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr ""
|
||||
"Kérem adja hozzá a(z) %(resource) erőforrást a %(config_resource) könyvtárhoz"
|
||||
"Kérem adja hozzá a(z) %(resource)s erőforrást a %(config_resource)s könyvtárhoz"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -293,7 +293,7 @@ msgstr "Espressione cron non valida '%s'"
|
|||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr ""
|
||||
"Aggiungi la/le risorse %(resource) nella/e cartella/e %(config_resource)"
|
||||
"Aggiungi la/le risorse %(resource)s nella/e cartella/e %(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -292,7 +292,7 @@ msgstr "A expressão cron '%s' é inválida"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "Adicionar o recurso %(resource)s à pasta %(config_resources)s"
|
||||
msgstr "Adicionar o recurso %(resource)s à pasta %(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -294,7 +294,7 @@ msgstr "A expressão de cron '%s' é inválida"
|
|||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr ""
|
||||
"Por favor, adicione o recurso %(resource)s para a diretoria "
|
||||
"%(config_resources)s"
|
||||
"%(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -290,7 +290,7 @@ msgstr "Недопустимое выражение cron '%s'"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "Пожалуйста, добавьте источник %(resource)s в папку %(config_resource)"
|
||||
msgstr "Пожалуйста, добавьте источник %(resource)s в папку %(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -289,7 +289,7 @@ msgstr "Biểu thức cron '%s' không hợp lệ"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "Vui lòng thêm tài nguyên %(resource) vào thư mục %(config_resource)"
|
||||
msgstr "Vui lòng thêm tài nguyên %(resource)s vào thư mục %(config_resource)s"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -287,7 +287,7 @@ msgstr "无效的 cron 正则表达式 '%s'"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "请将资源 %(resource) 添加到 %(config_resource) 目录"
|
||||
msgstr "请将资源 %(resource)s 添加到 %(config_resource)s 目录"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
|
@ -284,7 +284,7 @@ msgstr "無效的 cron 表述式 '%s'"
|
|||
# Settings dialog
|
||||
#, python-format
|
||||
msgid "Please add the resource %(resource)s to %(config_resource)s directory"
|
||||
msgstr "請將資源 %(resource)s 加入至 %(config_resource) 的路徑"
|
||||
msgstr "請將資源 %(resource)s 加入至 %(config_resource)s 的路徑"
|
||||
|
||||
# Settings dialog
|
||||
msgid "New Break"
|
||||
|
|
108
validate_po.py
108
validate_po.py
|
@ -23,24 +23,84 @@ import polib
|
|||
import re
|
||||
import sys
|
||||
|
||||
def has_equal_placeholders(left: str, right: str) -> bool:
|
||||
percents = re.finditer(r'%(?P<name>\(\w+\))?(?P<format>[a-z])', left)
|
||||
def validate_placeholders(message: str) -> bool:
|
||||
pos = 0
|
||||
|
||||
unnamed = defaultdict(int)
|
||||
named = []
|
||||
for percent in percents:
|
||||
if percent.group('name'):
|
||||
named.append(f"%({percent.group('name')}){percent.group('format')}")
|
||||
else:
|
||||
match = f"%{percent.group('format')}"
|
||||
unnamed[match] += 1
|
||||
success = True
|
||||
|
||||
count_placeholders = 0
|
||||
count_unnamed = 0
|
||||
|
||||
while True:
|
||||
index = message.find("%", pos)
|
||||
if index == -1:
|
||||
break
|
||||
|
||||
pos = index + 1
|
||||
|
||||
nextchar = message[pos : pos + 1]
|
||||
|
||||
name = None
|
||||
|
||||
if nextchar == "(":
|
||||
index = message.find(")", pos)
|
||||
if index == -1:
|
||||
success = False
|
||||
print(f"Unclosed parenthetical in '{message}'")
|
||||
break
|
||||
name = message[pos + 1 : index]
|
||||
|
||||
pos = index + 1
|
||||
|
||||
nextchar = message[pos : pos + 1]
|
||||
if nextchar not in ["%", "s", "d", "i", "f", "F"]:
|
||||
success = False
|
||||
print(f"Invalid format modifier in '{message}'")
|
||||
break
|
||||
|
||||
if nextchar != "%":
|
||||
count_placeholders += 1
|
||||
if name is None:
|
||||
count_unnamed += 1
|
||||
|
||||
pos += 1
|
||||
continue
|
||||
|
||||
if count_unnamed > 1:
|
||||
success = False
|
||||
print(f"Multiple unnamed placeholders in '{message}'")
|
||||
|
||||
if count_unnamed > 0 and count_placeholders > count_unnamed:
|
||||
success = False
|
||||
print(f"Mixing named and unnamed placeholders in '{message}'")
|
||||
|
||||
return success
|
||||
|
||||
def has_equal_placeholders(left: str, right: str) -> bool:
|
||||
def _get_placeholders(message: str) -> tuple:
|
||||
percents = re.finditer(r"%(?P<name>\(\w+\))?(?P<format>[a-z])", message)
|
||||
|
||||
unnamed = defaultdict(int)
|
||||
named = set()
|
||||
for percent in percents:
|
||||
if percent.group("name"):
|
||||
named.add(f"%({percent.group('name')}){percent.group('format')}")
|
||||
else:
|
||||
match = f"%{percent.group('format')}"
|
||||
unnamed[match] += 1
|
||||
return (unnamed, named)
|
||||
|
||||
(left_unnamed, left_named) = _get_placeholders(left)
|
||||
(right_unnamed, right_named) = _get_placeholders(right)
|
||||
|
||||
# count unnamed cases (eg. %s, %d)
|
||||
for match, count in unnamed.items():
|
||||
if right.count(match) != count:
|
||||
for match, count in left_unnamed.items():
|
||||
if right_unnamed.get(match, 0) != count:
|
||||
return False
|
||||
|
||||
# no need to count named cases - they are optional
|
||||
# named cases are optional - but ensure that translation does not add new ones
|
||||
if not right_named.issubset(left_named):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
@ -48,17 +108,23 @@ def validate_po(locale: str, path: str) -> bool:
|
|||
success = True
|
||||
po = polib.pofile(path)
|
||||
for entry in po:
|
||||
if entry.msgstr and not has_equal_placeholders(entry.msgid, entry.msgstr):
|
||||
print("Number of variables mismatched in " + locale)
|
||||
print(entry.msgid + " -> " + entry.msgstr)
|
||||
print()
|
||||
success = False
|
||||
for plural in entry.msgstr_plural.values():
|
||||
if plural and not has_equal_placeholders(entry.msgid, plural):
|
||||
if entry.msgstr:
|
||||
if not validate_placeholders(entry.msgstr):
|
||||
success = False
|
||||
if not has_equal_placeholders(entry.msgid, entry.msgstr):
|
||||
print("Number of variables mismatched in " + locale)
|
||||
print(entry.msgid + " -> " + plural)
|
||||
print(entry.msgid + " -> " + entry.msgstr)
|
||||
print()
|
||||
success = False
|
||||
for plural in entry.msgstr_plural.values():
|
||||
if plural:
|
||||
if not validate_placeholders(plural):
|
||||
success = False
|
||||
if not has_equal_placeholders(entry.msgid, plural):
|
||||
print("Number of variables mismatched in " + locale)
|
||||
print(entry.msgid + " -> " + plural)
|
||||
print()
|
||||
success = False
|
||||
return success
|
||||
|
||||
success = True
|
||||
|
|
Loading…
Reference in New Issue