From fbbbb90af38769ecd2703652adf7b46066a8be00 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 19 Mar 2013 08:33:24 +0000 Subject: Some renaming/cleanup in i18n tools. --- .../modules/bl_i18n_utils/bl_extract_messages.py | 10 +- .../modules/bl_i18n_utils/languages_menu_utils.py | 96 ---- release/scripts/modules/bl_i18n_utils/rtl_utils.py | 195 ------- release/scripts/modules/bl_i18n_utils/settings.py | 4 +- .../scripts/modules/bl_i18n_utils/settings_user.py | 23 + .../modules/bl_i18n_utils/spell_check_utils.py | 598 --------------------- .../scripts/modules/bl_i18n_utils/user_settings.py | 23 - release/scripts/modules/bl_i18n_utils/utils.py | 6 +- .../modules/bl_i18n_utils/utils_languages_menu.py | 96 ++++ release/scripts/modules/bl_i18n_utils/utils_rtl.py | 195 +++++++ .../modules/bl_i18n_utils/utils_spell_check.py | 598 +++++++++++++++++++++ 11 files changed, 923 insertions(+), 921 deletions(-) delete mode 100755 release/scripts/modules/bl_i18n_utils/languages_menu_utils.py delete mode 100755 release/scripts/modules/bl_i18n_utils/rtl_utils.py create mode 100644 release/scripts/modules/bl_i18n_utils/settings_user.py delete mode 100644 release/scripts/modules/bl_i18n_utils/spell_check_utils.py delete mode 100644 release/scripts/modules/bl_i18n_utils/user_settings.py create mode 100755 release/scripts/modules/bl_i18n_utils/utils_languages_menu.py create mode 100755 release/scripts/modules/bl_i18n_utils/utils_rtl.py create mode 100644 release/scripts/modules/bl_i18n_utils/utils_spell_check.py (limited to 'release') diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py index 5e58bccc6a8..9be786f14c1 100644 --- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -30,7 +30,7 @@ import re import sys # XXX Relative import does not work here when used from Blender... -from bl_i18n_utils import settings as i18n_settings, utils +from bl_i18n_utils import settings as settings_i18n, utils import bpy @@ -43,10 +43,10 @@ filter_message = ignore_reg.match def init_spell_check(settings, lang="en_US"): try: - from bl_i18n_utils import spell_check_utils - return spell_check_utils.SpellChecker(settings, lang) + from bl_i18n_utils import utils_spell_check + return utils_spell_check.SpellChecker(settings, lang) except Exception as e: - print("Failed to import spell_check_utils ({})".format(str(e))) + print("Failed to import utils_spell_check ({})".format(str(e))) return None @@ -901,7 +901,7 @@ def main(): help="Override (some) default settings. Either a JSon file name, or a JSon string.") args = parser.parse_args() - settings = i18n_settings.I18nSettings() + settings = settings_i18n.I18nSettings() settings.from_json(args.settings) if args.output: diff --git a/release/scripts/modules/bl_i18n_utils/languages_menu_utils.py b/release/scripts/modules/bl_i18n_utils/languages_menu_utils.py deleted file mode 100755 index 789b1315659..00000000000 --- a/release/scripts/modules/bl_i18n_utils/languages_menu_utils.py +++ /dev/null @@ -1,96 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# 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 ***** - -# - -# Update "languages" text file used by Blender at runtime to build translations menu. - - -import os - - -OK = 0 -MISSING = 1 -TOOLOW = 2 -FORBIDDEN = 3 -FLAG_MESSAGES = { - OK: "", - MISSING: "No translation yet!", - TOOLOW: "Not enough advanced to be included...", - FORBIDDEN: "Explicitly forbidden!", -} - -def gen_menu_file(stats, settings): - # Generate languages file used by Blender's i18n system. - # First, match all entries in LANGUAGES to a lang in stats, if possible! - tmp = [] - for uid_num, label, uid, in settings.LANGUAGES: - if uid in stats: - if uid in settings.IMPORT_LANGUAGES_SKIP: - tmp.append((stats[uid], uid_num, label, uid, FORBIDDEN)) - else: - tmp.append((stats[uid], uid_num, label, uid, OK)) - else: - tmp.append((0.0, uid_num, label, uid, MISSING)) - stats = tmp - limits = sorted(settings.LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True) - idx = 0 - stats = sorted(stats, key=lambda it: it[0], reverse=True) - langs_cats = [[] for i in range(len(limits))] - highest_uid = 0 - for lvl, uid_num, label, uid, flag in stats: - if lvl < limits[idx][0]: - # Sub-sort languages by iso-codes. - langs_cats[idx].sort(key=lambda it: it[2]) - idx += 1 - if lvl < settings.IMPORT_MIN_LEVEL and flag == OK: - flag = TOOLOW - langs_cats[idx].append((uid_num, label, uid, flag)) - if abs(uid_num) > highest_uid: - highest_uid = abs(uid_num) - # Sub-sort last group of languages by iso-codes! - langs_cats[idx].sort(key=lambda it: it[2]) - data_lines = [ - "# File used by Blender to know which languages (translations) are available, ", - "# and to generate translation menu.", - "#", - "# File format:", - "# ID:MENULABEL:ISOCODE", - "# ID must be unique, except for 0 value (marks categories for menu).", - "# Line starting with a # are comments!", - "#", - "# Automatically generated by bl_i18n_utils/update_languages_menu.py script.", - "# Highest ID currently in use: {}".format(highest_uid), - ] - for cat, langs_cat in zip(limits, langs_cats): - data_lines.append("#") - # Write "category menu label"... - if langs_cat: - data_lines.append("0:{}:".format(cat[1])) - else: - # Do not write the category if it has no language! - data_lines.append("# Void category! #0:{}:".format(cat[1])) - # ...and all matching language entries! - for uid_num, label, uid, flag in langs_cat: - if flag == OK: - data_lines.append("{}:{}:{}".format(uid_num, label, uid)) - else: - # Non-existing, commented entry! - data_lines.append("# {} #{}:{}:{}".format(FLAG_MESSAGES[flag], uid_num, label, uid)) - with open(os.path.join(settings.TRUNK_MO_DIR, settings.LANGUAGES_FILE), 'w') as f: - f.write("\n".join(data_lines)) diff --git a/release/scripts/modules/bl_i18n_utils/rtl_utils.py b/release/scripts/modules/bl_i18n_utils/rtl_utils.py deleted file mode 100755 index 0544f93a262..00000000000 --- a/release/scripts/modules/bl_i18n_utils/rtl_utils.py +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/python3 - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# 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 ***** - -# - -# Preprocess right-to-left languages. -# You can use it either standalone, or through import_po_from_branches or -# update_trunk. -# -# Notes: This has been tested on Linux, not 100% it will work nicely on -# Windows or OsX. -# This uses ctypes, as there is no py3 binding for fribidi currently. -# This implies you only need the compiled C library to run it. -# Finally, note that it handles some formating/escape codes (like -# \", %s, %x12, %.4f, etc.), protecting them from ugly (evil) fribidi, -# which seems completely unaware of such things (as unicode is...). - -import sys -import ctypes -import re - - -#define FRIBIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */ -FRIBIDI_PAR_ON = 0x00000040 - - -#define FRIBIDI_FLAG_SHAPE_MIRRORING 0x00000001 -#define FRIBIDI_FLAG_REORDER_NSM 0x00000002 - -#define FRIBIDI_FLAG_SHAPE_ARAB_PRES 0x00000100 -#define FRIBIDI_FLAG_SHAPE_ARAB_LIGA 0x00000200 -#define FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE 0x00000400 - -#define FRIBIDI_FLAG_REMOVE_BIDI 0x00010000 -#define FRIBIDI_FLAG_REMOVE_JOINING 0x00020000 -#define FRIBIDI_FLAG_REMOVE_SPECIALS 0x00040000 - -#define FRIBIDI_FLAGS_DEFAULT ( \ -# FRIBIDI_FLAG_SHAPE_MIRRORING | \ -# FRIBIDI_FLAG_REORDER_NSM | \ -# FRIBIDI_FLAG_REMOVE_SPECIALS ) - -#define FRIBIDI_FLAGS_ARABIC ( \ -# FRIBIDI_FLAG_SHAPE_ARAB_PRES | \ -# FRIBIDI_FLAG_SHAPE_ARAB_LIGA ) - -FRIBIDI_FLAG_SHAPE_MIRRORING = 0x00000001 -FRIBIDI_FLAG_REORDER_NSM = 0x00000002 -FRIBIDI_FLAG_REMOVE_SPECIALS = 0x00040000 - -FRIBIDI_FLAG_SHAPE_ARAB_PRES = 0x00000100 -FRIBIDI_FLAG_SHAPE_ARAB_LIGA = 0x00000200 - -FRIBIDI_FLAGS_DEFAULT = FRIBIDI_FLAG_SHAPE_MIRRORING | FRIBIDI_FLAG_REORDER_NSM | FRIBIDI_FLAG_REMOVE_SPECIALS - -FRIBIDI_FLAGS_ARABIC = FRIBIDI_FLAG_SHAPE_ARAB_PRES | FRIBIDI_FLAG_SHAPE_ARAB_LIGA - - -MENU_DETECT_REGEX = re.compile("%x\\d+\\|") - - -##### Kernel processing funcs. ##### -def protect_format_seq(msg): - """ - Find some specific escaping/formating sequences (like \", %s, etc., - and protect them from any modification! - """ -# LRM = "\u200E" -# RLM = "\u200F" - LRE = "\u202A" - RLE = "\u202B" - PDF = "\u202C" - LRO = "\u202D" - RLO = "\u202E" - uctrl = {LRE, RLE, PDF, LRO, RLO} - # Most likely incomplete, but seems to cover current needs. - format_codes = set("tslfd") - digits = set(".0123456789") - - if not msg: - return msg - elif MENU_DETECT_REGEX.search(msg): - # An ugly "menu" message, just force it whole LRE if not yet done. - if msg[0] not in {LRE, LRO}: - msg = LRE + msg - - idx = 0 - ret = [] - ln = len(msg) - while idx < ln: - dlt = 1 -# # If we find a control char, skip any additional protection! -# if msg[idx] in uctrl: -# ret.append(msg[idx:]) -# break - # \" or \' - if idx < (ln - 1) and msg[idx] == '\\' and msg[idx + 1] in "\"\'": - dlt = 2 - # %x12| - elif idx < (ln - 2) and msg[idx] == '%' and msg[idx + 1] in "x" and msg[idx + 2] in digits: - dlt = 2 - while (idx + dlt) < ln and msg[idx + dlt] in digits: - dlt += 1 - if (idx + dlt) < ln and msg[idx + dlt] is '|': - dlt += 1 - # %.4f - elif idx < (ln - 3) and msg[idx] == '%' and msg[idx + 1] in digits: - dlt = 2 - while (idx + dlt) < ln and msg[idx + dlt] in digits: - dlt += 1 - if (idx + dlt) < ln and msg[idx + dlt] in format_codes: - dlt += 1 - else: - dlt = 1 - # %s - elif idx < (ln - 1) and msg[idx] == '%' and msg[idx + 1] in format_codes: - dlt = 2 - - if dlt > 1: - ret.append(LRE) - ret += msg[idx:idx + dlt] - idx += dlt - if dlt > 1: - ret.append(PDF) - - return "".join(ret) - - -def log2vis(msgs, settings): - """ - Globally mimics deprecated fribidi_log2vis. - msgs should be an iterable of messages to rtl-process. - """ - fbd = ctypes.CDLL(settings.FRIBIDI_LIB) - - for msg in msgs: - msg = protect_format_seq(msg) - - fbc_str = ctypes.create_unicode_buffer(msg) - ln = len(fbc_str) - 1 -# print(fbc_str.value, ln) - btypes = (ctypes.c_int * ln)() - embed_lvl = (ctypes.c_uint8 * ln)() - pbase_dir = ctypes.c_int(FRIBIDI_PAR_ON) - jtypes = (ctypes.c_uint8 * ln)() - flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC - - # Find out direction of each char. - fbd.fribidi_get_bidi_types(fbc_str, ln, ctypes.byref(btypes)) - -# print(*btypes) - - fbd.fribidi_get_par_embedding_levels(btypes, ln, - ctypes.byref(pbase_dir), - embed_lvl) - -# print(*embed_lvl) - - # Joinings for arabic chars. - fbd.fribidi_get_joining_types(fbc_str, ln, jtypes) -# print(*jtypes) - fbd.fribidi_join_arabic(btypes, ln, embed_lvl, jtypes) -# print(*jtypes) - - # Final Shaping! - fbd.fribidi_shape(flags, embed_lvl, ln, jtypes, fbc_str) - -# print(fbc_str.value) -# print(*(ord(c) for c in fbc_str)) - # And now, the reordering. - # Note that here, we expect a single line, so no need to do - # fancy things... - fbd.fribidi_reorder_line(flags, btypes, ln, 0, pbase_dir, embed_lvl, - fbc_str, None) -# print(fbc_str.value) -# print(*(ord(c) for c in fbc_str)) - - yield fbc_str.value diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index b94f49b74a2..f38635510b2 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -441,13 +441,13 @@ INTERN_PY_SYS_PATHS = "" # Custom override settings must be one dir above i18n tools itself! sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) try: - from bl_i18n_override_settings import * + from bl_i18n_settings_override import * except ImportError: # If no i18n_override_settings available, it’s no error! pass # Override with custom user settings, if available. try: - from user_settings import * + from settings_user import * except ImportError: # If no user_settings available, it’s no error! pass diff --git a/release/scripts/modules/bl_i18n_utils/settings_user.py b/release/scripts/modules/bl_i18n_utils/settings_user.py new file mode 100644 index 00000000000..23d9783cd0f --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/settings_user.py @@ -0,0 +1,23 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# 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 ***** + +# + +import os + +import settings diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py deleted file mode 100644 index 925166a3d8b..00000000000 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ /dev/null @@ -1,598 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# 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 ##### - -# - -import enchant -import os -import pickle -import re - - -class SpellChecker(): - """ - A basic spell checker. - """ - - # These must be all lower case for comparisons - uimsgs = { - # OK words - "aren", # aren't - "betweens", # yuck! in-betweens! - "boolean", "booleans", - "couldn", # couldn't - "decrement", - "derivate", - "doesn", # doesn't - "fader", - "hasn", # hasn't - "hoc", # ad-hoc - "indices", - "iridas", - "isn", # isn't - "iterable", - "kyrgyz", - "latin", - "merchantability", - "mplayer", - "vertices", - - # Merged words - "addon", "addons", - "antialiasing", - "arcsine", "arccosine", "arctangent", - "autoclip", - "autocomplete", - "autoname", - "autosave", - "autoscale", - "autosmooth", - "autosplit", - "backface", "backfacing", - "backimage", - "backscattered", - "bandnoise", - "bindcode", - "bitrate", - "blendfile", - "blendin", - "bonesize", - "boundbox", - "boxpack", - "buffersize", - "builtin", "builtins", - "bytecode", - "chunksize", - "customdata", - "dataset", "datasets", - "de", - "defocus", - "denoise", - "despill", "despilling", - "editcurve", - "editmesh", - "filebrowser", - "filelist", - "filename", "filenames", - "filepath", "filepaths", - "forcefield", "forcefields", - "fulldome", "fulldomes", - "fullscreen", - "gridline", - "hemi", - "inbetween", - "inscatter", "inscattering", - "libdata", - "lightless", - "localview", - "lookup", "lookups", - "mathutils", - "midlevel", - "midground", - "mixdown", - "multi", - "multifractal", - "multires", "multiresolution", - "multisampling", - "multitexture", - "multiuser", - "namespace", - "keyconfig", - "playhead", - "polyline", - "popup", "popups", - "pre", - "precache", "precaching", - "precalculate", - "prefetch", - "premultiply", "premultiplied", - "prepass", - "prepend", - "preprocess", "preprocessing", - "preseek", - "raytree", - "readonly", - "realtime", - "rekey", - "remesh", - "reprojection", - "resize", - "restpose", - "retarget", "retargets", "retargeting", "retargeted", - "ringnoise", - "rolloff", - "screencast", "screenshot", "screenshots", - "selfcollision", - "shadowbuffer", "shadowbuffers", - "singletexture", - "spellcheck", "spellchecking", - "startup", - "stateful", - "starfield", - "subflare", "subflares", - "subframe", "subframes", - "subclass", "subclasses", "subclassing", - "subdirectory", "subdirectories", "subdir", "subdirs", - "submodule", "submodules", - "subpath", - "subsize", - "substep", "substeps", - "targetless", - "textbox", "textboxes", - "tilemode", - "timestamp", "timestamps", - "timestep", "timesteps", - "todo", - "un", - "unbake", - "uncomment", - "undeformed", - "undistort", "undistortion", - "ungroup", "ungrouped", - "unhide", - "unindent", - "unkeyed", - "unpremultiply", - "unprojected", - "unreacted", - "unregister", - "unselected", - "unsubdivided", "unsubdivide", - "unshadowed", - "unspill", - "unstitchable", - "vectorscope", - "whitespace", "whitespaces", - "worldspace", - "workflow", - - # Neologisms, slangs - "affectable", - "automagic", "automagically", - "blobby", - "blockiness", "blocky", - "collider", "colliders", - "deformer", "deformers", - "determinator", - "editability", - "keyer", - "lacunarity", - "numerics", - "occluder", - "passepartout", - "perspectively", - "pixelate", - "polygonization", - "selectability", - "slurph", - "stitchable", - "symmetrize", - "trackability", - "transmissivity", - "rasterized", "rasterization", "rasterizer", - "renderer", "renderable", "renderability", - - # Abbreviations - "aero", - "amb", - "anim", - "bool", - "calc", - "config", "configs", - "const", - "coord", "coords", - "degr", - "dof", - "dupli", "duplis", - "eg", - "esc", - "expr", - "fac", - "fra", - "frs", - "grless", - "http", - "init", - "kbit", "kb", - "lang", "langs", - "lclick", "rclick", - "lensdist", - "loc", "rot", "pos", - "lorem", - "luma", - "mem", - "multicam", - "num", - "ok", - "orco", - "ortho", - "persp", - "pref", "prefs", - "prev", - "param", - "premul", - "quad", "quads", - "quat", "quats", - "recalc", "recalcs", - "refl", - "sce", - "sel", - "spec", - "struct", "structs", - "sys", - "tex", - "tri", "tris", - "uv", "uvs", "uvw", "uw", "uvmap", - "ve", - "vec", - "vel", # velocity! - "vert", "verts", - "vis", - "xyz", "xzy", "yxz", "yzx", "zxy", "zyx", - "xy", "xz", "yx", "yz", "zx", "zy", - - # General computer/science terms - "boid", "boids", - "equisolid", - "euler", "eulers", - "fribidi", - "gettext", - "hashable", - "intrinsics", - "isosurface", - "jitter", "jittering", "jittered", - "keymap", "keymaps", - "lambertian", - "laplacian", - "metadata", - "msgfmt", - "nand", "xnor", - "normals", - "numpad", - "octree", - "opengl", - "pulldown", "pulldowns", - "quantized", - "samplerate", - "scrollback", - "scrollbar", - "scroller", - "searchable", - "spacebar", - "tooltip", "tooltips", - "trackpad", - "unicode", - "viewport", "viewports", - "viscoelastic", - "wildcard", "wildcards", - - # General computer graphics terms - "anaglyph", - "bezier", "beziers", - "bicubic", - "bilinear", - "blackpoint", "whitepoint", - "blinn", - "bokeh", - "catadioptric", - "centroid", - "chrominance", - "codec", "codecs", - "collada", - "compositing", - "crossfade", - "deinterlace", - "dropoff", - "dv", - "eigenvectors", - "equirectangular", - "fisheye", - "framerate", - "gimbal", - "grayscale", - "icosphere", - "inpaint", - "lightmap", - "lossless", "lossy", - "matcap", - "midtones", - "mipmap", "mipmaps", "mip", - "ngon", "ngons", - "ntsc", - "nurb", "nurbs", - "perlin", - "phong", - "radiosity", - "raytrace", "raytracing", "raytraced", - "renderfarm", - "shader", "shaders", - "specular", "specularity", - "spillmap", - "sobel", - "tonemap", - "toon", - "timecode", - "voronoi", - "voxel", "voxels", - "wireframe", - "zmask", - "ztransp", - - # Blender terms - "audaspace", - "bbone", - "breakdowner", - "bspline", - "bweight", - "colorband", - "datablock", "datablocks", - "despeckle", - "dopesheet", - "dupliface", "duplifaces", - "dupliframe", "dupliframes", - "dupliobject", "dupliob", - "dupligroup", - "duplivert", - "editbone", - "editmode", - "fcurve", "fcurves", - "fluidsim", - "frameserver", - "enum", - "keyframe", "keyframes", "keyframing", "keyframed", - "metaball", "metaballs", - "metaelement", "metaelements", - "metastrip", "metastrips", - "movieclip", - "mpoly", - "mtex", - "nabla", - "navmesh", - "outliner", - "paintmap", "paintmaps", - "polygroup", "polygroups", - "poselib", - "pushpull", - "pyconstraint", "pyconstraints", - "shapekey", "shapekeys", - "shrinkfatten", - "shrinkwrap", - "softbody", - "stucci", - "sunsky", - "subsurf", - "tessface", "tessfaces", - "texface", - "timeline", "timelines", - "tosphere", - "uilist", - "vcol", "vcols", - "vgroup", "vgroups", - "vinterlace", - "wetmap", "wetmaps", - "wpaint", - "uvwarp", - - # Algorithm names - "beckmann", - "catmull", - "catrom", - "chebychev", - "courant", - "kutta", - "lennard", - "minkowski", - "minnaert", - "musgrave", - "nayar", - "netravali", - "oren", - "prewitt", - "runge", - "verlet", - "worley", - - # Acronyms - "aa", "msaa", - "ao", - "api", - "asc", "cdl", - "ascii", - "atrac", - "bsdf", - "bw", - "ccd", - "cmd", - "cpus", - "ctrl", - "cw", "ccw", - "dev", - "djv", - "dpi", - "dvar", - "dx", - "eo", - "fh", - "fov", - "fft", - "futura", - "gfx", - "gl", - "glsl", - "gpl", - "gpu", "gpus", - "hc", - "hdc", - "hdr", - "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode - "hsv", "hsva", - "id", - "ior", - "itu", - "lhs", - "lmb", "mmb", "rmb", - "kb", - "mocap", - "msgid", "msgids", - "mux", - "ndof", - "ppc", - "precisa", - "px", - "qmc", - "rgb", "rgba", - "rhs", - "rv", - "sdl", - "sl", - "smpte", - "svn", - "ui", - "unix", - "vbo", "vbos", - "ycc", "ycca", - "yuv", "yuva", - - # Blender acronyms - "bge", - "bli", - "bpy", - "bvh", - "dbvt", - "dop", # BLI K-Dop BVH - "ik", - "nla", - "py", - "qbvh", - "rna", - "rvo", - "simd", - "sph", - "svbvh", - - # Files types/formats - "avi", - "attrac", - "autocad", - "autodesk", - "bmp", - "btx", - "cineon", - "dpx", - "dxf", - "eps", - "exr", - "fbx", - "ffmpeg", - "flac", - "gzip", - "ico", - "jpg", "jpeg", - "json", - "matroska", - "mdd", - "mkv", - "mpeg", "mjpeg", - "mtl", - "ogg", - "openjpeg", - "osl", - "oso", - "piz", - "png", - "po", - "quicktime", - "rle", - "sgi", - "stl", - "svg", - "targa", "tga", - "tiff", - "theora", - "vorbis", - "wav", - "xiph", - "xml", - "xna", - "xvid", - } - - _valid_before = "(?<=[\\s*'\"`])|(?<=[a-zA-Z][/-])|(?<=^)" - _valid_after = "(?=[\\s'\"`.!?,;:])|(?=[/-]\\s*[a-zA-Z])|(?=$)" - _valid_words = "(?:{})(?:(?:[A-Z]+[a-z]*)|[A-Z]*|[a-z]*)(?:{})".format(_valid_before, _valid_after) - _split_words = re.compile(_valid_words).findall - - @classmethod - def split_words(cls, text): - return [w for w in cls._split_words(text) if w] - - def __init__(self, settings, lang="en_US"): - self.settings = settings - self.dict_spelling = enchant.Dict(lang) - self.cache = set(self.uimsgs) - - cache = self.settings.SPELL_CACHE - if cache and os.path.exists(cache): - with open(cache, 'rb') as f: - self.cache |= set(pickle.load(f)) - - def __del__(self): - cache = self.settings.SPELL_CACHE - if cache and os.path.exists(cache): - with open(cache, 'wb') as f: - pickle.dump(self.cache, f) - - def check(self, txt): - ret = [] - - if txt in self.cache: - return ret - - for w in self.split_words(txt): - w_lower = w.lower() - if w_lower in self.cache: - continue - if not self.dict_spelling.check(w): - ret.append((w, self.dict_spelling.suggest(w))) - else: - self.cache.add(w_lower) - - if not ret: - self.cache.add(txt) - - return ret diff --git a/release/scripts/modules/bl_i18n_utils/user_settings.py b/release/scripts/modules/bl_i18n_utils/user_settings.py deleted file mode 100644 index 23d9783cd0f..00000000000 --- a/release/scripts/modules/bl_i18n_utils/user_settings.py +++ /dev/null @@ -1,23 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# 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 ***** - -# - -import os - -import settings diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index f9890d79144..e9af87e0c81 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -31,7 +31,9 @@ import sys import tempfile #import time -from bl_i18n_utils import settings, rtl_utils +from bl_i18n_utils import (settings, + utils_rtl, + ) import bpy @@ -402,7 +404,7 @@ class I18nMessages: for k, m in self.msgs.items(): keys.append(k) trans.append(m.msgstr) - trans = rtl_utils.log2vis(trans, self.settings) + trans = utils_rtl.log2vis(trans, self.settings) for k, t in zip(keys, trans): self.msgs[k].msgstr = t diff --git a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py new file mode 100755 index 00000000000..789b1315659 --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py @@ -0,0 +1,96 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# 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 ***** + +# + +# Update "languages" text file used by Blender at runtime to build translations menu. + + +import os + + +OK = 0 +MISSING = 1 +TOOLOW = 2 +FORBIDDEN = 3 +FLAG_MESSAGES = { + OK: "", + MISSING: "No translation yet!", + TOOLOW: "Not enough advanced to be included...", + FORBIDDEN: "Explicitly forbidden!", +} + +def gen_menu_file(stats, settings): + # Generate languages file used by Blender's i18n system. + # First, match all entries in LANGUAGES to a lang in stats, if possible! + tmp = [] + for uid_num, label, uid, in settings.LANGUAGES: + if uid in stats: + if uid in settings.IMPORT_LANGUAGES_SKIP: + tmp.append((stats[uid], uid_num, label, uid, FORBIDDEN)) + else: + tmp.append((stats[uid], uid_num, label, uid, OK)) + else: + tmp.append((0.0, uid_num, label, uid, MISSING)) + stats = tmp + limits = sorted(settings.LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True) + idx = 0 + stats = sorted(stats, key=lambda it: it[0], reverse=True) + langs_cats = [[] for i in range(len(limits))] + highest_uid = 0 + for lvl, uid_num, label, uid, flag in stats: + if lvl < limits[idx][0]: + # Sub-sort languages by iso-codes. + langs_cats[idx].sort(key=lambda it: it[2]) + idx += 1 + if lvl < settings.IMPORT_MIN_LEVEL and flag == OK: + flag = TOOLOW + langs_cats[idx].append((uid_num, label, uid, flag)) + if abs(uid_num) > highest_uid: + highest_uid = abs(uid_num) + # Sub-sort last group of languages by iso-codes! + langs_cats[idx].sort(key=lambda it: it[2]) + data_lines = [ + "# File used by Blender to know which languages (translations) are available, ", + "# and to generate translation menu.", + "#", + "# File format:", + "# ID:MENULABEL:ISOCODE", + "# ID must be unique, except for 0 value (marks categories for menu).", + "# Line starting with a # are comments!", + "#", + "# Automatically generated by bl_i18n_utils/update_languages_menu.py script.", + "# Highest ID currently in use: {}".format(highest_uid), + ] + for cat, langs_cat in zip(limits, langs_cats): + data_lines.append("#") + # Write "category menu label"... + if langs_cat: + data_lines.append("0:{}:".format(cat[1])) + else: + # Do not write the category if it has no language! + data_lines.append("# Void category! #0:{}:".format(cat[1])) + # ...and all matching language entries! + for uid_num, label, uid, flag in langs_cat: + if flag == OK: + data_lines.append("{}:{}:{}".format(uid_num, label, uid)) + else: + # Non-existing, commented entry! + data_lines.append("# {} #{}:{}:{}".format(FLAG_MESSAGES[flag], uid_num, label, uid)) + with open(os.path.join(settings.TRUNK_MO_DIR, settings.LANGUAGES_FILE), 'w') as f: + f.write("\n".join(data_lines)) diff --git a/release/scripts/modules/bl_i18n_utils/utils_rtl.py b/release/scripts/modules/bl_i18n_utils/utils_rtl.py new file mode 100755 index 00000000000..0544f93a262 --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/utils_rtl.py @@ -0,0 +1,195 @@ +#!/usr/bin/python3 + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# 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 ***** + +# + +# Preprocess right-to-left languages. +# You can use it either standalone, or through import_po_from_branches or +# update_trunk. +# +# Notes: This has been tested on Linux, not 100% it will work nicely on +# Windows or OsX. +# This uses ctypes, as there is no py3 binding for fribidi currently. +# This implies you only need the compiled C library to run it. +# Finally, note that it handles some formating/escape codes (like +# \", %s, %x12, %.4f, etc.), protecting them from ugly (evil) fribidi, +# which seems completely unaware of such things (as unicode is...). + +import sys +import ctypes +import re + + +#define FRIBIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */ +FRIBIDI_PAR_ON = 0x00000040 + + +#define FRIBIDI_FLAG_SHAPE_MIRRORING 0x00000001 +#define FRIBIDI_FLAG_REORDER_NSM 0x00000002 + +#define FRIBIDI_FLAG_SHAPE_ARAB_PRES 0x00000100 +#define FRIBIDI_FLAG_SHAPE_ARAB_LIGA 0x00000200 +#define FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE 0x00000400 + +#define FRIBIDI_FLAG_REMOVE_BIDI 0x00010000 +#define FRIBIDI_FLAG_REMOVE_JOINING 0x00020000 +#define FRIBIDI_FLAG_REMOVE_SPECIALS 0x00040000 + +#define FRIBIDI_FLAGS_DEFAULT ( \ +# FRIBIDI_FLAG_SHAPE_MIRRORING | \ +# FRIBIDI_FLAG_REORDER_NSM | \ +# FRIBIDI_FLAG_REMOVE_SPECIALS ) + +#define FRIBIDI_FLAGS_ARABIC ( \ +# FRIBIDI_FLAG_SHAPE_ARAB_PRES | \ +# FRIBIDI_FLAG_SHAPE_ARAB_LIGA ) + +FRIBIDI_FLAG_SHAPE_MIRRORING = 0x00000001 +FRIBIDI_FLAG_REORDER_NSM = 0x00000002 +FRIBIDI_FLAG_REMOVE_SPECIALS = 0x00040000 + +FRIBIDI_FLAG_SHAPE_ARAB_PRES = 0x00000100 +FRIBIDI_FLAG_SHAPE_ARAB_LIGA = 0x00000200 + +FRIBIDI_FLAGS_DEFAULT = FRIBIDI_FLAG_SHAPE_MIRRORING | FRIBIDI_FLAG_REORDER_NSM | FRIBIDI_FLAG_REMOVE_SPECIALS + +FRIBIDI_FLAGS_ARABIC = FRIBIDI_FLAG_SHAPE_ARAB_PRES | FRIBIDI_FLAG_SHAPE_ARAB_LIGA + + +MENU_DETECT_REGEX = re.compile("%x\\d+\\|") + + +##### Kernel processing funcs. ##### +def protect_format_seq(msg): + """ + Find some specific escaping/formating sequences (like \", %s, etc., + and protect them from any modification! + """ +# LRM = "\u200E" +# RLM = "\u200F" + LRE = "\u202A" + RLE = "\u202B" + PDF = "\u202C" + LRO = "\u202D" + RLO = "\u202E" + uctrl = {LRE, RLE, PDF, LRO, RLO} + # Most likely incomplete, but seems to cover current needs. + format_codes = set("tslfd") + digits = set(".0123456789") + + if not msg: + return msg + elif MENU_DETECT_REGEX.search(msg): + # An ugly "menu" message, just force it whole LRE if not yet done. + if msg[0] not in {LRE, LRO}: + msg = LRE + msg + + idx = 0 + ret = [] + ln = len(msg) + while idx < ln: + dlt = 1 +# # If we find a control char, skip any additional protection! +# if msg[idx] in uctrl: +# ret.append(msg[idx:]) +# break + # \" or \' + if idx < (ln - 1) and msg[idx] == '\\' and msg[idx + 1] in "\"\'": + dlt = 2 + # %x12| + elif idx < (ln - 2) and msg[idx] == '%' and msg[idx + 1] in "x" and msg[idx + 2] in digits: + dlt = 2 + while (idx + dlt) < ln and msg[idx + dlt] in digits: + dlt += 1 + if (idx + dlt) < ln and msg[idx + dlt] is '|': + dlt += 1 + # %.4f + elif idx < (ln - 3) and msg[idx] == '%' and msg[idx + 1] in digits: + dlt = 2 + while (idx + dlt) < ln and msg[idx + dlt] in digits: + dlt += 1 + if (idx + dlt) < ln and msg[idx + dlt] in format_codes: + dlt += 1 + else: + dlt = 1 + # %s + elif idx < (ln - 1) and msg[idx] == '%' and msg[idx + 1] in format_codes: + dlt = 2 + + if dlt > 1: + ret.append(LRE) + ret += msg[idx:idx + dlt] + idx += dlt + if dlt > 1: + ret.append(PDF) + + return "".join(ret) + + +def log2vis(msgs, settings): + """ + Globally mimics deprecated fribidi_log2vis. + msgs should be an iterable of messages to rtl-process. + """ + fbd = ctypes.CDLL(settings.FRIBIDI_LIB) + + for msg in msgs: + msg = protect_format_seq(msg) + + fbc_str = ctypes.create_unicode_buffer(msg) + ln = len(fbc_str) - 1 +# print(fbc_str.value, ln) + btypes = (ctypes.c_int * ln)() + embed_lvl = (ctypes.c_uint8 * ln)() + pbase_dir = ctypes.c_int(FRIBIDI_PAR_ON) + jtypes = (ctypes.c_uint8 * ln)() + flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC + + # Find out direction of each char. + fbd.fribidi_get_bidi_types(fbc_str, ln, ctypes.byref(btypes)) + +# print(*btypes) + + fbd.fribidi_get_par_embedding_levels(btypes, ln, + ctypes.byref(pbase_dir), + embed_lvl) + +# print(*embed_lvl) + + # Joinings for arabic chars. + fbd.fribidi_get_joining_types(fbc_str, ln, jtypes) +# print(*jtypes) + fbd.fribidi_join_arabic(btypes, ln, embed_lvl, jtypes) +# print(*jtypes) + + # Final Shaping! + fbd.fribidi_shape(flags, embed_lvl, ln, jtypes, fbc_str) + +# print(fbc_str.value) +# print(*(ord(c) for c in fbc_str)) + # And now, the reordering. + # Note that here, we expect a single line, so no need to do + # fancy things... + fbd.fribidi_reorder_line(flags, btypes, ln, 0, pbase_dir, embed_lvl, + fbc_str, None) +# print(fbc_str.value) +# print(*(ord(c) for c in fbc_str)) + + yield fbc_str.value diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py new file mode 100644 index 00000000000..925166a3d8b --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -0,0 +1,598 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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 ##### + +# + +import enchant +import os +import pickle +import re + + +class SpellChecker(): + """ + A basic spell checker. + """ + + # These must be all lower case for comparisons + uimsgs = { + # OK words + "aren", # aren't + "betweens", # yuck! in-betweens! + "boolean", "booleans", + "couldn", # couldn't + "decrement", + "derivate", + "doesn", # doesn't + "fader", + "hasn", # hasn't + "hoc", # ad-hoc + "indices", + "iridas", + "isn", # isn't + "iterable", + "kyrgyz", + "latin", + "merchantability", + "mplayer", + "vertices", + + # Merged words + "addon", "addons", + "antialiasing", + "arcsine", "arccosine", "arctangent", + "autoclip", + "autocomplete", + "autoname", + "autosave", + "autoscale", + "autosmooth", + "autosplit", + "backface", "backfacing", + "backimage", + "backscattered", + "bandnoise", + "bindcode", + "bitrate", + "blendfile", + "blendin", + "bonesize", + "boundbox", + "boxpack", + "buffersize", + "builtin", "builtins", + "bytecode", + "chunksize", + "customdata", + "dataset", "datasets", + "de", + "defocus", + "denoise", + "despill", "despilling", + "editcurve", + "editmesh", + "filebrowser", + "filelist", + "filename", "filenames", + "filepath", "filepaths", + "forcefield", "forcefields", + "fulldome", "fulldomes", + "fullscreen", + "gridline", + "hemi", + "inbetween", + "inscatter", "inscattering", + "libdata", + "lightless", + "localview", + "lookup", "lookups", + "mathutils", + "midlevel", + "midground", + "mixdown", + "multi", + "multifractal", + "multires", "multiresolution", + "multisampling", + "multitexture", + "multiuser", + "namespace", + "keyconfig", + "playhead", + "polyline", + "popup", "popups", + "pre", + "precache", "precaching", + "precalculate", + "prefetch", + "premultiply", "premultiplied", + "prepass", + "prepend", + "preprocess", "preprocessing", + "preseek", + "raytree", + "readonly", + "realtime", + "rekey", + "remesh", + "reprojection", + "resize", + "restpose", + "retarget", "retargets", "retargeting", "retargeted", + "ringnoise", + "rolloff", + "screencast", "screenshot", "screenshots", + "selfcollision", + "shadowbuffer", "shadowbuffers", + "singletexture", + "spellcheck", "spellchecking", + "startup", + "stateful", + "starfield", + "subflare", "subflares", + "subframe", "subframes", + "subclass", "subclasses", "subclassing", + "subdirectory", "subdirectories", "subdir", "subdirs", + "submodule", "submodules", + "subpath", + "subsize", + "substep", "substeps", + "targetless", + "textbox", "textboxes", + "tilemode", + "timestamp", "timestamps", + "timestep", "timesteps", + "todo", + "un", + "unbake", + "uncomment", + "undeformed", + "undistort", "undistortion", + "ungroup", "ungrouped", + "unhide", + "unindent", + "unkeyed", + "unpremultiply", + "unprojected", + "unreacted", + "unregister", + "unselected", + "unsubdivided", "unsubdivide", + "unshadowed", + "unspill", + "unstitchable", + "vectorscope", + "whitespace", "whitespaces", + "worldspace", + "workflow", + + # Neologisms, slangs + "affectable", + "automagic", "automagically", + "blobby", + "blockiness", "blocky", + "collider", "colliders", + "deformer", "deformers", + "determinator", + "editability", + "keyer", + "lacunarity", + "numerics", + "occluder", + "passepartout", + "perspectively", + "pixelate", + "polygonization", + "selectability", + "slurph", + "stitchable", + "symmetrize", + "trackability", + "transmissivity", + "rasterized", "rasterization", "rasterizer", + "renderer", "renderable", "renderability", + + # Abbreviations + "aero", + "amb", + "anim", + "bool", + "calc", + "config", "configs", + "const", + "coord", "coords", + "degr", + "dof", + "dupli", "duplis", + "eg", + "esc", + "expr", + "fac", + "fra", + "frs", + "grless", + "http", + "init", + "kbit", "kb", + "lang", "langs", + "lclick", "rclick", + "lensdist", + "loc", "rot", "pos", + "lorem", + "luma", + "mem", + "multicam", + "num", + "ok", + "orco", + "ortho", + "persp", + "pref", "prefs", + "prev", + "param", + "premul", + "quad", "quads", + "quat", "quats", + "recalc", "recalcs", + "refl", + "sce", + "sel", + "spec", + "struct", "structs", + "sys", + "tex", + "tri", "tris", + "uv", "uvs", "uvw", "uw", "uvmap", + "ve", + "vec", + "vel", # velocity! + "vert", "verts", + "vis", + "xyz", "xzy", "yxz", "yzx", "zxy", "zyx", + "xy", "xz", "yx", "yz", "zx", "zy", + + # General computer/science terms + "boid", "boids", + "equisolid", + "euler", "eulers", + "fribidi", + "gettext", + "hashable", + "intrinsics", + "isosurface", + "jitter", "jittering", "jittered", + "keymap", "keymaps", + "lambertian", + "laplacian", + "metadata", + "msgfmt", + "nand", "xnor", + "normals", + "numpad", + "octree", + "opengl", + "pulldown", "pulldowns", + "quantized", + "samplerate", + "scrollback", + "scrollbar", + "scroller", + "searchable", + "spacebar", + "tooltip", "tooltips", + "trackpad", + "unicode", + "viewport", "viewports", + "viscoelastic", + "wildcard", "wildcards", + + # General computer graphics terms + "anaglyph", + "bezier", "beziers", + "bicubic", + "bilinear", + "blackpoint", "whitepoint", + "blinn", + "bokeh", + "catadioptric", + "centroid", + "chrominance", + "codec", "codecs", + "collada", + "compositing", + "crossfade", + "deinterlace", + "dropoff", + "dv", + "eigenvectors", + "equirectangular", + "fisheye", + "framerate", + "gimbal", + "grayscale", + "icosphere", + "inpaint", + "lightmap", + "lossless", "lossy", + "matcap", + "midtones", + "mipmap", "mipmaps", "mip", + "ngon", "ngons", + "ntsc", + "nurb", "nurbs", + "perlin", + "phong", + "radiosity", + "raytrace", "raytracing", "raytraced", + "renderfarm", + "shader", "shaders", + "specular", "specularity", + "spillmap", + "sobel", + "tonemap", + "toon", + "timecode", + "voronoi", + "voxel", "voxels", + "wireframe", + "zmask", + "ztransp", + + # Blender terms + "audaspace", + "bbone", + "breakdowner", + "bspline", + "bweight", + "colorband", + "datablock", "datablocks", + "despeckle", + "dopesheet", + "dupliface", "duplifaces", + "dupliframe", "dupliframes", + "dupliobject", "dupliob", + "dupligroup", + "duplivert", + "editbone", + "editmode", + "fcurve", "fcurves", + "fluidsim", + "frameserver", + "enum", + "keyframe", "keyframes", "keyframing", "keyframed", + "metaball", "metaballs", + "metaelement", "metaelements", + "metastrip", "metastrips", + "movieclip", + "mpoly", + "mtex", + "nabla", + "navmesh", + "outliner", + "paintmap", "paintmaps", + "polygroup", "polygroups", + "poselib", + "pushpull", + "pyconstraint", "pyconstraints", + "shapekey", "shapekeys", + "shrinkfatten", + "shrinkwrap", + "softbody", + "stucci", + "sunsky", + "subsurf", + "tessface", "tessfaces", + "texface", + "timeline", "timelines", + "tosphere", + "uilist", + "vcol", "vcols", + "vgroup", "vgroups", + "vinterlace", + "wetmap", "wetmaps", + "wpaint", + "uvwarp", + + # Algorithm names + "beckmann", + "catmull", + "catrom", + "chebychev", + "courant", + "kutta", + "lennard", + "minkowski", + "minnaert", + "musgrave", + "nayar", + "netravali", + "oren", + "prewitt", + "runge", + "verlet", + "worley", + + # Acronyms + "aa", "msaa", + "ao", + "api", + "asc", "cdl", + "ascii", + "atrac", + "bsdf", + "bw", + "ccd", + "cmd", + "cpus", + "ctrl", + "cw", "ccw", + "dev", + "djv", + "dpi", + "dvar", + "dx", + "eo", + "fh", + "fov", + "fft", + "futura", + "gfx", + "gl", + "glsl", + "gpl", + "gpu", "gpus", + "hc", + "hdc", + "hdr", + "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode + "hsv", "hsva", + "id", + "ior", + "itu", + "lhs", + "lmb", "mmb", "rmb", + "kb", + "mocap", + "msgid", "msgids", + "mux", + "ndof", + "ppc", + "precisa", + "px", + "qmc", + "rgb", "rgba", + "rhs", + "rv", + "sdl", + "sl", + "smpte", + "svn", + "ui", + "unix", + "vbo", "vbos", + "ycc", "ycca", + "yuv", "yuva", + + # Blender acronyms + "bge", + "bli", + "bpy", + "bvh", + "dbvt", + "dop", # BLI K-Dop BVH + "ik", + "nla", + "py", + "qbvh", + "rna", + "rvo", + "simd", + "sph", + "svbvh", + + # Files types/formats + "avi", + "attrac", + "autocad", + "autodesk", + "bmp", + "btx", + "cineon", + "dpx", + "dxf", + "eps", + "exr", + "fbx", + "ffmpeg", + "flac", + "gzip", + "ico", + "jpg", "jpeg", + "json", + "matroska", + "mdd", + "mkv", + "mpeg", "mjpeg", + "mtl", + "ogg", + "openjpeg", + "osl", + "oso", + "piz", + "png", + "po", + "quicktime", + "rle", + "sgi", + "stl", + "svg", + "targa", "tga", + "tiff", + "theora", + "vorbis", + "wav", + "xiph", + "xml", + "xna", + "xvid", + } + + _valid_before = "(?<=[\\s*'\"`])|(?<=[a-zA-Z][/-])|(?<=^)" + _valid_after = "(?=[\\s'\"`.!?,;:])|(?=[/-]\\s*[a-zA-Z])|(?=$)" + _valid_words = "(?:{})(?:(?:[A-Z]+[a-z]*)|[A-Z]*|[a-z]*)(?:{})".format(_valid_before, _valid_after) + _split_words = re.compile(_valid_words).findall + + @classmethod + def split_words(cls, text): + return [w for w in cls._split_words(text) if w] + + def __init__(self, settings, lang="en_US"): + self.settings = settings + self.dict_spelling = enchant.Dict(lang) + self.cache = set(self.uimsgs) + + cache = self.settings.SPELL_CACHE + if cache and os.path.exists(cache): + with open(cache, 'rb') as f: + self.cache |= set(pickle.load(f)) + + def __del__(self): + cache = self.settings.SPELL_CACHE + if cache and os.path.exists(cache): + with open(cache, 'wb') as f: + pickle.dump(self.cache, f) + + def check(self, txt): + ret = [] + + if txt in self.cache: + return ret + + for w in self.split_words(txt): + w_lower = w.lower() + if w_lower in self.cache: + continue + if not self.dict_spelling.check(w): + ret.append((w, self.dict_spelling.suggest(w))) + else: + self.cache.add(w_lower) + + if not ret: + self.cache.add(txt) + + return ret -- cgit v1.2.3