Changeset View
Changeset View
Standalone View
Standalone View
release/scripts/modules/bl_i18n_utils/utils.py
| Show First 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | for p in os.listdir(root_dir): | ||||
| if langs and uid not in langs: | if langs and uid not in langs: | ||||
| continue | continue | ||||
| po_file = os.path.join(root_dir, p, p + ".po") | po_file = os.path.join(root_dir, p, p + ".po") | ||||
| if not os.path.isfile(po_file): | if not os.path.isfile(po_file): | ||||
| continue | continue | ||||
| else: | else: | ||||
| continue | continue | ||||
| if uid in found_uids: | if uid in found_uids: | ||||
| printf("WARNING! {} id has been found more than once! only first one has been loaded!".format(uid)) | print("WARNING! {} id has been found more than once! only first one has been loaded!".format(uid)) | ||||
| continue | continue | ||||
| found_uids.add(uid) | found_uids.add(uid) | ||||
| yield uid, po_file | yield uid, po_file | ||||
| def list_po_dir(root_path, settings): | def list_po_dir(root_path, settings): | ||||
| """ | """ | ||||
| Generator. List given directory (expecting one sub-directory per languages) | Generator. List given directory (expecting one sub-directory per languages) | ||||
| ▲ Show 20 Lines • Show All 1,069 Lines • ▼ Show 20 Lines | def _dst(self, path, uid, kind): | ||||
| if kind == 'PO': | if kind == 'PO': | ||||
| if uid == self.settings.PARSER_TEMPLATE_ID: | if uid == self.settings.PARSER_TEMPLATE_ID: | ||||
| if not path.endswith(".pot"): | if not path.endswith(".pot"): | ||||
| return os.path.join(os.path.dirname(path), "blender.pot") | return os.path.join(os.path.dirname(path), "blender.pot") | ||||
| if not path.endswith(".po"): | if not path.endswith(".po"): | ||||
| return os.path.join(os.path.dirname(path), uid + ".po") | return os.path.join(os.path.dirname(path), uid + ".po") | ||||
| elif kind == 'PY': | elif kind == 'PY': | ||||
| if not path.endswith(".py"): | if not path.endswith(".py"): | ||||
| if self.src.get(self.settings.PARSER_PY_ID): | return os.path.join(path, "translations.py") | ||||
mont29: I don't think this is the proper fix... more something like:
```
if os.path.isdir(path)… | |||||
pioverfourAuthorUnsubmitted Done Inline ActionsAh, maybe I’m mistaken, but this always creates a translations.py, even for single-file scripts. I thought the intention was to create it only if the module is a directory, otherwise just put the translations at the end of the script. If that is the case, I think this is better? Let me know. @staticmethod
def _dst(self, path, uid, kind):
if isinstance(path, str):
if kind == 'PO':
if uid == self.settings.PARSER_TEMPLATE_ID:
if not path.endswith(".pot"):
return os.path.join(os.path.dirname(path), "blender.pot")
if not path.endswith(".po"):
return os.path.join(os.path.dirname(path), uid + ".po")
elif kind == 'PY':
if os.path.isdir(path):
return os.path.join(path, "translations.py")
return pathpioverfour: Ah, maybe I’m mistaken, but this always creates a `translations.py`, even for single-file… | |||||
mont29Unsubmitted Not Done Inline ActionsThat piece of code I proposed would be under the if not path.endswith(".py"): condition, so single py files would still be handled as expected. it just makes it safe(r) in case we ever get a non-py file, non directory path, for whatever reason. mont29: That piece of code I proposed would be under the `if not path.endswith(".py"):` condition, so… | |||||
pioverfourAuthorUnsubmitted Done Inline ActionsOh, right 🤦 pioverfour: Oh, right 🤦 | |||||
| return self.src[self.settings.PARSER_PY_ID] | |||||
| return os.path.join(os.path.dirname(path), "translations.py") | |||||
| return path | return path | ||||
| def __init__(self, kind=None, src=None, langs=set(), settings=settings): | def __init__(self, kind=None, src=None, langs=set(), settings=settings): | ||||
| self.settings = settings | self.settings = settings | ||||
| self.trans = {} | self.trans = {} | ||||
| self.src = {} # Should have the same keys as self.trans (plus PARSER_PY_ID for py file)! | self.src = {} # Should have the same keys as self.trans (plus PARSER_PY_ID for py file)! | ||||
| self.dst = self._dst # A callable that transforms src_path into dst_path! | self.dst = self._dst # A callable that transforms src_path into dst_path! | ||||
| if kind and src: | if kind and src: | ||||
| ▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | class I18n: | ||||
| def parse_from_py(self, src, langs=set()): | def parse_from_py(self, src, langs=set()): | ||||
| """ | """ | ||||
| src must be a valid path, either a py file or a module directory (in which case all py files inside it | src must be a valid path, either a py file or a module directory (in which case all py files inside it | ||||
| will be checked, first file matching will win!). | will be checked, first file matching will win!). | ||||
| if langs set is void, all languages found are loaded. | if langs set is void, all languages found are loaded. | ||||
| """ | """ | ||||
| default_context = self.settings.DEFAULT_CONTEXT | default_context = self.settings.DEFAULT_CONTEXT | ||||
| self.src[self.settings.PARSER_PY_ID], msgs = self.check_py_module_has_translations(src, self.settings) | self.py_file, msgs = self.check_py_module_has_translations(src, self.settings) | ||||
| if msgs is None: | if msgs is None: | ||||
| self.src[self.settings.PARSER_PY_ID] = src | self.py_file = src | ||||
| msgs = () | msgs = () | ||||
| for key, (sources, gen_comments), *translations in msgs: | for key, (sources, gen_comments), *translations in msgs: | ||||
| if self.settings.PARSER_TEMPLATE_ID not in self.trans: | if self.settings.PARSER_TEMPLATE_ID not in self.trans: | ||||
| self.trans[self.settings.PARSER_TEMPLATE_ID] = I18nMessages(self.settings.PARSER_TEMPLATE_ID, | self.trans[self.settings.PARSER_TEMPLATE_ID] = I18nMessages(self.settings.PARSER_TEMPLATE_ID, | ||||
| settings=self.settings) | settings=self.settings) | ||||
| self.src[self.settings.PARSER_TEMPLATE_ID] = self.src[self.settings.PARSER_PY_ID] | self.src[self.settings.PARSER_TEMPLATE_ID] = self.py_file | ||||
| if key in self.trans[self.settings.PARSER_TEMPLATE_ID].msgs: | if key in self.trans[self.settings.PARSER_TEMPLATE_ID].msgs: | ||||
| print("ERROR! key {} is defined more than once! Skipping re-definitions!") | print("ERROR! key {} is defined more than once! Skipping re-definitions!") | ||||
| continue | continue | ||||
| custom_src = [c for c in sources if c.startswith("bpy.")] | custom_src = [c for c in sources if c.startswith("bpy.")] | ||||
| src = [c for c in sources if not c.startswith("bpy.")] | src = [c for c in sources if not c.startswith("bpy.")] | ||||
| common_comment_lines = [self.settings.PO_COMMENT_PREFIX_GENERATED + c for c in gen_comments] + \ | common_comment_lines = [self.settings.PO_COMMENT_PREFIX_GENERATED + c for c in gen_comments] + \ | ||||
| [self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + c for c in custom_src] + \ | [self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + c for c in custom_src] + \ | ||||
| [self.settings.PO_COMMENT_PREFIX_SOURCE + c for c in src] | [self.settings.PO_COMMENT_PREFIX_SOURCE + c for c in src] | ||||
| ctxt = [key[0]] if key[0] else [default_context] | ctxt = [key[0]] if key[0] else [default_context] | ||||
| self.trans[self.settings.PARSER_TEMPLATE_ID].msgs[key] = I18nMessage(ctxt, [key[1]], [""], | self.trans[self.settings.PARSER_TEMPLATE_ID].msgs[key] = I18nMessage(ctxt, [key[1]], [""], | ||||
| common_comment_lines, False, False, | common_comment_lines, False, False, | ||||
| settings=self.settings) | settings=self.settings) | ||||
| for uid, msgstr, (is_fuzzy, user_comments) in translations: | for uid, msgstr, (is_fuzzy, user_comments) in translations: | ||||
| if uid not in self.trans: | if uid not in self.trans: | ||||
| self.trans[uid] = I18nMessages(uid, settings=self.settings) | self.trans[uid] = I18nMessages(uid, settings=self.settings) | ||||
| self.src[uid] = self.src[self.settings.PARSER_PY_ID] | self.src[uid] = self.py_file | ||||
| comment_lines = [self.settings.PO_COMMENT_PREFIX + c for c in user_comments] + common_comment_lines | comment_lines = [self.settings.PO_COMMENT_PREFIX + c for c in user_comments] + common_comment_lines | ||||
| self.trans[uid].msgs[key] = I18nMessage(ctxt, [key[1]], [msgstr], comment_lines, False, is_fuzzy, | self.trans[uid].msgs[key] = I18nMessage(ctxt, [key[1]], [msgstr], comment_lines, False, is_fuzzy, | ||||
| settings=self.settings) | settings=self.settings) | ||||
| # key = self.settings.PO_HEADER_KEY | # key = self.settings.PO_HEADER_KEY | ||||
| # for uid, trans in self.trans.items(): | # for uid, trans in self.trans.items(): | ||||
| # if key not in trans.msgs: | # if key not in trans.msgs: | ||||
| # trans.msgs[key] | # trans.msgs[key] | ||||
| self.unescape() | self.unescape() | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | def write_to_py(self, langs=set()): | ||||
| # Get the ref translation (ideally, PARSER_TEMPLATE_ID one, else the first one that pops up! | # Get the ref translation (ideally, PARSER_TEMPLATE_ID one, else the first one that pops up! | ||||
| # Ref translation will be used to generate sources "comments" | # Ref translation will be used to generate sources "comments" | ||||
| ref = self.trans.get(self.settings.PARSER_TEMPLATE_ID) or self.trans[list(self.trans.keys())[0]] | ref = self.trans.get(self.settings.PARSER_TEMPLATE_ID) or self.trans[list(self.trans.keys())[0]] | ||||
| # Get all languages (uids) and sort them (PARSER_TEMPLATE_ID and PARSER_PY_ID excluded!) | # Get all languages (uids) and sort them (PARSER_TEMPLATE_ID and PARSER_PY_ID excluded!) | ||||
| translations = self.trans.keys() - {self.settings.PARSER_TEMPLATE_ID, self.settings.PARSER_PY_ID} | translations = self.trans.keys() - {self.settings.PARSER_TEMPLATE_ID, self.settings.PARSER_PY_ID} | ||||
| if langs: | if langs: | ||||
| translations &= langs | translations &= langs | ||||
| translations = [('"' + lng + '"', " " * (len(lng) + 6), self.trans[lng]) for lng in sorted(translations)] | translations = [('"' + lng + '"', " " * (len(lng) + 6), self.trans[lng]) for lng in sorted(translations)] | ||||
| print(k for k in keys.keys()) | print(*(k for k in keys.keys())) | ||||
| for key in keys.keys(): | for key in keys.keys(): | ||||
| if ref.msgs[key].is_commented: | if ref.msgs[key].is_commented: | ||||
| continue | continue | ||||
| # Key (context + msgid). | # Key (context + msgid). | ||||
| msgctxt, msgid = ref.msgs[key].msgctxt, ref.msgs[key].msgid | msgctxt, msgid = ref.msgs[key].msgctxt, ref.msgs[key].msgid | ||||
| if not msgctxt: | if not msgctxt: | ||||
| msgctxt = default_context | msgctxt = default_context | ||||
| ret.append(tab + "(({}, \"{}\"),".format('"' + msgctxt + '"' if msgctxt else "None", msgid)) | ret.append(tab + "(({}, \"{}\"),".format('"' + msgctxt + '"' if msgctxt else "None", msgid)) | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | def write_to_py(self, langs=set()): | ||||
| "at the end of the file, you can move that section later if needed...".format(dst)) | "at the end of the file, you can move that section later if needed...".format(dst)) | ||||
| txt = ([txt, "", self.settings.PARSER_PY_MARKER_BEGIN] + | txt = ([txt, "", self.settings.PARSER_PY_MARKER_BEGIN] + | ||||
| _gen_py(self, langs) + | _gen_py(self, langs) + | ||||
| ["", self.settings.PARSER_PY_MARKER_END]) | ["", self.settings.PARSER_PY_MARKER_END]) | ||||
| else: | else: | ||||
| # We completely replace the text found between start and end markers... | # We completely replace the text found between start and end markers... | ||||
| txt = _gen_py(self, langs) | txt = _gen_py(self, langs) | ||||
| else: | else: | ||||
| printf("Creating python file {} containing translations.".format(dst)) | print("Creating python file {} containing translations.".format(dst)) | ||||
| txt = [ | txt = [ | ||||
| "# ***** BEGIN GPL LICENSE BLOCK *****", | "# SPDX-License-Identifier: GPL-2.0-or-later", | ||||
| "#", | |||||
| "# This program is free software; you can redistribute it and/or", | |||||
| "# modify it under the terms of the GNU General Public License", | |||||
| "# as published by the Free Software Foundation; either version 2", | |||||
| "# of the License, or (at your option) any later version.", | |||||
| "#", | |||||
| "# This program is distributed in the hope that it will be useful,", | |||||
| "# but WITHOUT ANY WARRANTY; without even the implied warranty of", | |||||
| "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", | |||||
| "# GNU General Public License for more details.", | |||||
| "#", | |||||
| "# You should have received a copy of the GNU General Public License", | |||||
| "# along with this program; if not, write to the Free Software Foundation,", | |||||
| "# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.", | |||||
| "#", | |||||
| "# ***** END GPL LICENSE BLOCK *****", | |||||
| "", | "", | ||||
| self.settings.PARSER_PY_MARKER_BEGIN, | self.settings.PARSER_PY_MARKER_BEGIN, | ||||
| "", | "", | ||||
| ] | ] | ||||
| txt += _gen_py(self, langs) | txt += _gen_py(self, langs) | ||||
| txt += [ | txt += [ | ||||
| "", | "", | ||||
| self.settings.PARSER_PY_MARKER_END, | self.settings.PARSER_PY_MARKER_END, | ||||
| Show All 14 Lines | |||||
I don't think this is the proper fix... more something like:
if os.path.isdir(path): return os.path.join(path, "translations.py") return os.path.join(os.path.dirname(path), "translations.py")?