1 # ***** BEGIN GPL LICENSE BLOCK *****
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ***** END GPL LICENSE BLOCK *****
21 # Global settings used by all scripts in this dir.
22 # XXX Before any use of the tools in this dir, please make a copy of this file
24 # XXX This is a template, most values should be OK, but some you’ll have to
25 # edit (most probably, BLENDER_EXEC and SOURCE_DIR).
30 ###############################################################################
32 ###############################################################################
34 # The languages defined in Blender.
35 LANGUAGES_CATEGORIES = (
36 # Min completeness level, UI english label.
38 ( 0.33, "In Progress"),
42 # ID, UI english label, ISO code.
43 ( 0, "Default (Default)", "DEFAULT", ""),
44 ( 1, "English (English)", "en_US", "english"),
45 ( 2, "Japanese (日本語)", "ja_JP", "japanese"),
46 ( 3, "Dutch (Nederlandse taal)", "nl_NL", "dutch"),
47 ( 4, "Italian (Italiano)", "it_IT", "italian"),
48 ( 5, "German (Deutsch)", "de_DE", "german"),
49 ( 6, "Finnish (Suomi)", "fi_FI", "finnish"),
50 ( 7, "Swedish (Svenska)", "sv_SE", "swedish"),
51 ( 8, "French (Français)", "fr_FR", "french"),
52 ( 9, "Spanish (Español)", "es", "spanish"),
53 (10, "Catalan (Català)", "ca_AD", "catalan"),
54 (11, "Czech (Český)", "cs_CZ", "czech"),
55 (12, "Portuguese (Português)", "pt_PT", "portuguese_portugal"),
56 (13, "Simplified Chinese (简体中文)", "zh_CN", "Chinese (Simplified)_China.1252"),
57 (14, "Traditional Chinese (繁體中文)", "zh_TW", "Chinese (Traditional)_China.1252"),
58 (15, "Russian (Русский)", "ru_RU", "russian"),
59 (16, "Croatian (Hrvatski)", "hr_HR", "croatian"),
60 (17, "Serbian (Српски)", "sr_RS", "serbian"),
61 (18, "Ukrainian (Український)", "uk_UA", "ukrainian"),
62 (19, "Polish (Polski)", "pl_PL", "polish"),
63 (20, "Romanian (Român)", "ro_RO", "romanian"),
64 # Using the utf8 flipped form of Arabic (العربية).
65 (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG", "arabic"),
66 (22, "Bulgarian (Български)", "bg_BG", "bulgarian"),
67 (23, "Greek (Ελληνικά)", "el_GR", "greek"),
68 (24, "Korean (한국 언어)", "ko_KR", "korean"),
69 (25, "Nepali (नेपाली)", "ne_NP", "nepali"),
70 # Using the utf8 flipped form of Persian (فارسی).
71 (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR", "farsi"),
72 (27, "Indonesian (Bahasa indonesia)", "id_ID", "indonesian"),
73 (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin", "serbian (latin)"),
74 (29, "Kyrgyz (Кыргыз тили)", "ky_KG", "kyrgyz"),
75 (30, "Turkish (Türkçe)", "tr_TR", "turkish"),
76 (31, "Hungarian (Magyar)", "hu_HU", "hungarian"),
77 (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR", "protuguese_brazil"),
78 # Using the utf8 flipped form of Hebrew (עִבְרִית)).
79 (33, "Hebrew (תירִבְעִ)", "he_IL", "hebrew"),
80 (34, "Estonian (Eestlane)", "et_EE", "estonian"),
81 (35, "Esperanto (Esperanto)", "eo", "esperanto"),
82 (36, "Spanish from Spain (Español de España)", "es_ES", "spanish_spain"),
85 # Name of language file used by Blender to generate translations' menu.
86 LANGUAGES_FILE = "languages"
88 # The min level of completeness for a po file to be imported from /branches
89 # into /trunk, as a percentage. -1 means "import everything".
92 # Languages in /branches we do not want to import in /trunk currently...
93 IMPORT_LANGUAGES_SKIP = {'bg', 'ca', 'fi', 'el', 'ko', 'ne', 'pl', 'ro'}
95 # The comment prefix used in generated messages.txt file.
96 COMMENT_PREFIX = "#~ "
98 # The comment prefix used to mark sources of msgids, in po's.
99 COMMENT_PREFIX_SOURCE = "#: "
101 # The comment prefix used in generated messages.txt file.
102 CONTEXT_PREFIX = "MSGCTXT:"
107 # Undocumented operator placeholder string.
108 UNDOC_OPS_STR = "(undocumented operator)"
110 # The gettext domain.
113 # Our own "gettext" stuff.
114 # File type (ext) to parse.
115 PYGETTEXT_ALLOWED_EXTS = {".c", ".cpp", ".cxx", ".hpp", ".hxx", ".h"}
117 # Where to search contexts definitions, relative to SOURCE_DIR (defined below).
118 PYGETTEXT_CONTEXTS_DEFSRC = os.path.join("source", "blender", "blenfont",
121 # Regex to extract contexts defined in BLF_translation.h
122 # XXX Not full-proof, but should be enough here!
123 PYGETTEXT_CONTEXTS = "#define\\s+(BLF_I18NCONTEXT_[A-Z_0-9]+)\\s+\"([^\"]*)\""
126 # XXX Most unfortunately, we can't use named backreferences inside character sets,
127 # which makes the regexes even more twisty... :/
130 "(?P<{_}1>[\"'])(?P={_}1)" # Get opening quote (' or "), and closing immediately.
132 # Or match non-void string
133 "(?P<{_}2>[\"'])" # Get opening quote (' or ").
135 # This one is for crazy things like "hi \\\\\" folks!"...
136 r"(?:(?!<\\)(?:\\\\)*\\(?=(?P={_}2)))|"
137 # The most common case.
139 ")+.)" # Don't forget the last char!
140 "(?P={_}2)" # And closing quote.
142 str_clean_re = _str_base.format(_="g", capt="P<clean>")
143 # Here we have to consider two different cases (empty string and other).
145 _str_base.format(_="{_}1_", capt=":") +
146 # Optional loop start, this handles "split" strings...
147 "(?:(?<=[\"'])\\s*(?=[\"'])(?:"
148 + _str_base.format(_="{_}2_", capt=":") +
152 _ctxt_re = r"(?P<ctxt_raw>(?:" + _str_whole_re.format(_="_ctxt") + r")|(?:[A-Z_0-9]+))"
153 _msg_re = r"(?P<msg_raw>" + _str_whole_re.format(_="_msg") + r")"
154 PYGETTEXT_KEYWORDS = (() +
155 tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it)
156 for it in ("IFACE_", "TIP_", "N_")) +
158 tuple((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it)
159 for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_N_")) +
161 tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
162 for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf")) +
164 tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it)
165 for it in ("BMO_error_raise",)) +
167 tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
168 for it in ("modifier_setError",))
172 (r'((?<!\\)"|(?<!\\)\\(?!\\|"))', r"\\\1"),
176 # Should po parser warn when finding a first letter not capitalized?
177 WARN_MSGID_NOT_CAPITALIZED = True
179 # Strings that should not raise above warning!
180 WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
181 "", # Simplifies things... :p
208 "available with", # Is part of multi-line msg.
209 "virtual parents", # Is part of multi-line msg.
210 "description", # Addons' field. :/
211 "location", # Addons' field. :/
212 "author", # Addons' field. :/
213 "in memory to enable editing!", # Is part of multi-line msg.
219 WARN_MSGID_NOT_CAPITALIZED_ALLOWED |= set(lng[2] for lng in LANGUAGES)
222 ###############################################################################
224 ###############################################################################
226 # The tools path, should be OK.
227 TOOLS_DIR = os.path.join(os.path.dirname(__file__))
229 # The Python3 executable.You’ll likely have to edit it in your user_settings.py
230 # if you’re under Windows.
231 PYTHON3_EXEC = "python3"
233 # The Blender executable!
234 # This is just an example, you’ll most likely have to edit it in your user_settings.py!
235 BLENDER_EXEC = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "blender"))
237 # The xgettext tool. You’ll likely have to edit it in your user_settings.py if you’re under Windows.
238 GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
240 # The gettext msgmerge tool. You’ll likely have to edit it in your user_settings.py if you’re under Windows.
241 GETTEXT_MSGMERGE_EXECUTABLE = "msgmerge"
243 # The gettext msgfmt "compiler". You’ll likely have to edit it in your user_settings.py if you’re under Windows.
244 GETTEXT_MSGFMT_EXECUTABLE = "msgfmt"
246 # The svn binary... You’ll likely have to edit it in your user_settings.py if you’re under Windows.
247 SVN_EXECUTABLE = "svn"
249 # The FriBidi C compiled library (.so under Linux, .dll under windows...).
250 # You’ll likely have to edit it in your user_settings.py if you’re under Windows., e.g. using the included one:
251 # FRIBIDI_LIB = os.path.join(TOOLS_DIR, "libfribidi.dll")
252 FRIBIDI_LIB = "libfribidi.so.0"
254 # The name of the (currently empty) file that must be present in a po's directory to enable rtl-preprocess.
255 RTL_PREPROCESS_FILE = "is_rtl"
257 # The Blender source root path.
258 # This is just an example, you’ll most likely have to override it in your user_settings.py!
259 SOURCE_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "..", "..", "blender_msgs"))
261 # The bf-translation repository (you'll likely have to override this in your user_settings.py).
262 I18N_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "..", "..", "i18n"))
264 # The /branches path (overriden in bf-translation's i18n_override_settings.py).
265 BRANCHES_DIR = os.path.join(I18N_DIR, "branches")
267 # The /trunk path (overriden in bf-translation's i18n_override_settings.py).
268 TRUNK_DIR = os.path.join(I18N_DIR, "trunk")
270 # The /trunk/po path (overriden in bf-translation's i18n_override_settings.py).
271 TRUNK_PO_DIR = os.path.join(TRUNK_DIR, "po")
273 # The /trunk/mo path (overriden in bf-translation's i18n_override_settings.py).
274 TRUNK_MO_DIR = os.path.join(TRUNK_DIR, "locale")
276 # The file storing Blender-generated messages.
277 FILE_NAME_MESSAGES = os.path.join(TRUNK_PO_DIR, "messages.txt")
279 # The Blender source path to check for i18n macros.
280 POTFILES_SOURCE_DIR = os.path.join(SOURCE_DIR, "source")
282 # The "source" file storing which files should be processed by xgettext, used to create FILE_NAME_POTFILES
283 FILE_NAME_SRC_POTFILES = os.path.join(TRUNK_PO_DIR, "_POTFILES.in")
285 # The final (generated) file storing which files should be processed by xgettext.
286 FILE_NAME_POTFILES = os.path.join(TRUNK_PO_DIR, "POTFILES.in")
288 # The template messages file.
289 FILE_NAME_POT = os.path.join(TRUNK_PO_DIR, ".".join((DOMAIN, "pot")))
291 # Other py files that should be searched for ui strings, relative to SOURCE_DIR.
292 # Needed for Cycles, currently...
293 CUSTOM_PY_UI_FILES = [os.path.join("intern", "cycles", "blender", "addon", "ui.py"),]
296 # A cache storing validated msgids, to avoid re-spellchecking them.
297 SPELL_CACHE = os.path.join("/tmp", ".spell_cache")
300 # Custom override settings must be one dir above i18n tools itself!
302 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
304 from bl_i18n_override_settings import *
305 except ImportError: # If no i18n_override_settings available, it’s no error!
308 # Override with custom user settings, if available.
310 from user_settings import *
311 except ImportError: # If no user_settings available, it’s no error!