I18n: improve add-on translation tooling

- Allow versions from bl_info to be strings
  Versions are now allowed to be strings in extensions using
  blender_manifest.toml, so this commit prevents them from being badly
  formatted on extraction to add-on translations.

- Do not export Blender copyright text to add-on translations
  This text is only relevant for Blender and maybe core add-ons, not
  for the general case.

- Copy comment lines from add-on .po files to .py translations
  Without this comments added by translators could be lost since they
  were not copied over to the Python files.

- Fix indentation in add-on translations
  Some lines in the translation dict were off by a few spaces. This
  resulted in linting tools complaining about the indentation.

- Do not escape messages in add-on translations multiple times
  When extracting add-on messages, they would get escaped multiple
  times, resulting in invalid strings when they contained quotes for
  example.

  This happened because on updating the messages from the ref
  ones (those actually extracted from Blender), each ref I18nMessage
  would be assigned to the corresponding language I18nMessage, without
  copy. When this message was escaped, it happened once for every
  language since they were actually the same object.

  To avoid this, I18nMessage objects are copied when merging.

-----

Example tuple before PR:
```python
translations_tuple = (
    (("*", ""),
     ((), ()),
     ("fr_FR", "Project-Id-Version: AnimAll 0...1.1...0 (0)\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2024-05-26 17:10+0000\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: LANGUAGE <LL@li.org>\nLanguage: __POT__\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit",
               (False,
                ("Blender's translation file (po format).",
                 "Copyright (C) 2024 The Blender Authors.",
                 "This file is distributed under the same license as the Blender package.",
                 "FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))),
    ),
    (("*", "\\"Location\\" and \\"Shape Key\\" are redundant?"),
     (("extensions/user_default/animall/__init__.py:250",),
      ()),
     ("fr_FR", "",
               (False, ())),
    ),
    ...
```

After:
```python
translations_tuple = (
    (("*", ""),
     ((), ()),
     ("fr_FR", "Project-Id-Version: AnimAll 0.11.0 (0)\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2024-05-26 17:06+0000\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\nLast-Translator: FULL NAME <EMAIL@ADDRESS>\nLanguage-Team: LANGUAGE <LL@li.org>\nLanguage: __POT__\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit",
      (False, ("FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.",))),
     ),
    (("*", "\"Location\" and \"Shape Key\" are redundant?"),
     (("extensions/user_default/animall/__init__.py:250",),
      ()),
     ("fr_FR", "",
      (False, ())),
     ),
    ...
```

Pull Request: https://projects.blender.org/blender/blender/pulls/122273
This commit is contained in:
Damien Picard
2024-05-27 13:33:49 +02:00
committed by Bastien Montagne
parent f74d32e17f
commit 446a653cb7
2 changed files with 23 additions and 12 deletions

View File

@@ -1113,10 +1113,20 @@ def dump_addon_messages(addon_module_name, do_checks, settings):
addon = utils.enable_addons(addons={addon_module_name})[0]
addon_info = addon_utils.module_bl_info(addon)
ver = addon_info["name"] + " " + ".".join(str(v) for v in addon_info["version"])
ver = addon_info["name"] + " "
if type(addon_info["version"]) is str:
ver += addon_info["version"]
else:
ver += ".".join(str(v) for v in addon_info["version"])
rev = 0
curr_time = time.gmtime()
pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, ver, rev, curr_time, settings=settings)
pot = utils.I18nMessages.gen_empty_messages(
settings.PARSER_TEMPLATE_ID,
ver,
rev,
curr_time,
default_copyright=False,
settings=settings)
msgs = pot.msgs
minus_pot = utils.I18nMessages.gen_empty_messages(

View File

@@ -586,6 +586,7 @@ class I18nMessages:
if (not sm.msgstr or replace or (sm.is_fuzzy and (not m.is_fuzzy or replace))):
sm.msgstr = m.msgstr
sm.is_fuzzy = m.is_fuzzy
sm.comment_lines = m.comment_lines
def update(self, ref, use_similar=None, keep_old_commented=True):
"""
@@ -626,7 +627,7 @@ class I18nMessages:
if skey not in similar_pool[msgid]:
skey = tuple(similar_pool[msgid])[0]
# We keep org translation and comments, and mark message as fuzzy.
msg, refmsg = self.msgs[skey].copy(), ref.msgs[key]
msg, refmsg = self.msgs[skey].copy(), ref.msgs[key].copy()
msg.msgctxt = refmsg.msgctxt
msg.msgid = refmsg.msgid
msg.sources = refmsg.sources
@@ -634,10 +635,10 @@ class I18nMessages:
msg.is_commented = refmsg.is_commented
msgs[key] = msg
else:
msgs[key] = ref.msgs[key]
msgs[key] = ref.msgs[key].copy()
else:
for key in new_keys:
msgs[key] = ref.msgs[key]
msgs[key] = ref.msgs[key].copy()
# Add back all "old" and already commented messages as commented ones, if required
# (and translation was not void!).
@@ -1486,7 +1487,7 @@ class I18n:
translations = self.trans.keys() - {self.settings.PARSER_TEMPLATE_ID, self.settings.PARSER_PY_ID}
if langs:
translations &= langs
translations = [('"' + lng + '"', " " * (len(lng) + 6), self.trans[lng]) for lng in sorted(translations)]
translations = [('"' + lng + '"', self.trans[lng]) for lng in sorted(translations)]
print("Translated keys saved to .py file:")
print(*(k for k in keys.keys()))
for key in keys.keys():
@@ -1523,7 +1524,7 @@ class I18n:
else:
ret.append(tab + " (" + ('"' + gen_comments[0] + '",' if gen_comments else "") + ")),")
# All languages
for lngstr, lngsp, trans in translations:
for lngstr, trans in translations:
if trans.msgs[key].is_commented:
continue
# Language code and translation.
@@ -1533,15 +1534,15 @@ class I18n:
for comment in trans.msgs[key].comment_lines:
if comment.startswith(self.settings.PO_COMMENT_PREFIX):
comments.append(comment[_lencomm:])
ret.append(tab + lngsp + "(" + ("True" if trans.msgs[key].is_fuzzy else "False") + ",")
ret.append(tab + " (" + ("True" if trans.msgs[key].is_fuzzy else "False") + ",")
if len(comments) > 1:
ret.append(tab + lngsp + ' ("' + comments[0] + '",')
ret += [tab + lngsp + ' "' + s + '",' for s in comments[1:-1]]
ret.append(tab + lngsp + ' "' + comments[-1] + '"))),')
ret.append(tab + ' ("' + comments[0] + '",')
ret += [tab * 2 + '"' + s + '",' for s in comments[1:-1]]
ret.append(tab * 2 + '"' + comments[-1] + '"))),')
else:
ret[-1] = ret[-1] + " (" + (('"' + comments[0] + '",') if comments else "") + "))),"
ret.append(tab + "),")
ret.append(" " + "),")
ret += [
")",
"",