1 | /**************************************************************************/ |
2 | /* editor_property_name_processor.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "editor_property_name_processor.h" |
32 | |
33 | #include "core/string/translation.h" |
34 | #include "editor_settings.h" |
35 | |
36 | EditorPropertyNameProcessor *EditorPropertyNameProcessor::singleton = nullptr; |
37 | |
38 | EditorPropertyNameProcessor::Style EditorPropertyNameProcessor::get_default_inspector_style() { |
39 | if (!EditorSettings::get_singleton()) { |
40 | return STYLE_CAPITALIZED; |
41 | } |
42 | const Style style = (Style)EDITOR_GET("interface/inspector/default_property_name_style" ).operator int(); |
43 | if (style == STYLE_LOCALIZED && !is_localization_available()) { |
44 | return STYLE_CAPITALIZED; |
45 | } |
46 | return style; |
47 | } |
48 | |
49 | EditorPropertyNameProcessor::Style EditorPropertyNameProcessor::get_settings_style() { |
50 | if (!EditorSettings::get_singleton()) { |
51 | return STYLE_LOCALIZED; |
52 | } |
53 | const bool translate = EDITOR_GET("interface/editor/localize_settings" ); |
54 | return translate ? STYLE_LOCALIZED : STYLE_CAPITALIZED; |
55 | } |
56 | |
57 | EditorPropertyNameProcessor::Style EditorPropertyNameProcessor::get_tooltip_style(Style p_style) { |
58 | return p_style == STYLE_LOCALIZED ? STYLE_CAPITALIZED : STYLE_LOCALIZED; |
59 | } |
60 | |
61 | bool EditorPropertyNameProcessor::is_localization_available() { |
62 | if (!EditorSettings::get_singleton()) { |
63 | return false; |
64 | } |
65 | const Vector<String> forbidden = String("en" ).split("," ); |
66 | return forbidden.find(EDITOR_GET("interface/editor/editor_language" )) == -1; |
67 | } |
68 | |
69 | String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const { |
70 | HashMap<String, String>::ConstIterator cached = capitalize_string_cache.find(p_name); |
71 | if (cached) { |
72 | return cached->value; |
73 | } |
74 | |
75 | Vector<String> parts = p_name.split("_" , false); |
76 | for (int i = 0; i < parts.size(); i++) { |
77 | // Articles/conjunctions/prepositions which should only be capitalized when not at beginning and end. |
78 | if (i > 0 && i + 1 < parts.size() && stop_words.find(parts[i]) != -1) { |
79 | continue; |
80 | } |
81 | HashMap<String, String>::ConstIterator remap = capitalize_string_remaps.find(parts[i]); |
82 | if (remap) { |
83 | parts.write[i] = remap->value; |
84 | } else { |
85 | parts.write[i] = parts[i].capitalize(); |
86 | } |
87 | } |
88 | const String capitalized = String(" " ).join(parts); |
89 | |
90 | capitalize_string_cache[p_name] = capitalized; |
91 | return capitalized; |
92 | } |
93 | |
94 | String EditorPropertyNameProcessor::process_name(const String &p_name, Style p_style) const { |
95 | switch (p_style) { |
96 | case STYLE_RAW: { |
97 | return p_name; |
98 | } break; |
99 | |
100 | case STYLE_CAPITALIZED: { |
101 | return _capitalize_name(p_name); |
102 | } break; |
103 | |
104 | case STYLE_LOCALIZED: { |
105 | const String capitalized = _capitalize_name(p_name); |
106 | if (TranslationServer::get_singleton()) { |
107 | return TranslationServer::get_singleton()->property_translate(capitalized); |
108 | } |
109 | return capitalized; |
110 | } break; |
111 | } |
112 | ERR_FAIL_V_MSG(p_name, "Unexpected property name style." ); |
113 | } |
114 | |
115 | String EditorPropertyNameProcessor::translate_group_name(const String &p_name) const { |
116 | if (TranslationServer::get_singleton()) { |
117 | return TranslationServer::get_singleton()->property_translate(p_name); |
118 | } |
119 | return p_name; |
120 | } |
121 | |
122 | EditorPropertyNameProcessor::EditorPropertyNameProcessor() { |
123 | ERR_FAIL_COND(singleton != nullptr); |
124 | singleton = this; |
125 | |
126 | // The following initialization is parsed by the l10n extraction script with a regex. |
127 | // The map name and value definition format should be kept synced with the regex. |
128 | // https://github.com/godotengine/godot-editor-l10n/blob/main/scripts/common.py |
129 | capitalize_string_remaps["2d" ] = "2D" ; |
130 | capitalize_string_remaps["3d" ] = "3D" ; |
131 | capitalize_string_remaps["aa" ] = "AA" ; |
132 | capitalize_string_remaps["aabb" ] = "AABB" ; |
133 | capitalize_string_remaps["adb" ] = "ADB" ; |
134 | capitalize_string_remaps["ao" ] = "AO" ; |
135 | capitalize_string_remaps["api" ] = "API" ; |
136 | capitalize_string_remaps["apk" ] = "APK" ; |
137 | capitalize_string_remaps["arm32" ] = "arm32" ; |
138 | capitalize_string_remaps["arm64" ] = "arm64" ; |
139 | capitalize_string_remaps["arm64-v8a" ] = "arm64-v8a" ; |
140 | capitalize_string_remaps["armeabi-v7a" ] = "armeabi-v7a" ; |
141 | capitalize_string_remaps["arvr" ] = "ARVR" ; |
142 | capitalize_string_remaps["astc" ] = "ASTC" ; |
143 | capitalize_string_remaps["bbcode" ] = "BBCode" ; |
144 | capitalize_string_remaps["bg" ] = "BG" ; |
145 | capitalize_string_remaps["bidi" ] = "BiDi" ; |
146 | capitalize_string_remaps["bp" ] = "BP" ; |
147 | capitalize_string_remaps["bpc" ] = "BPC" ; |
148 | capitalize_string_remaps["bpm" ] = "BPM" ; |
149 | capitalize_string_remaps["bptc" ] = "BPTC" ; |
150 | capitalize_string_remaps["bvh" ] = "BVH" ; |
151 | capitalize_string_remaps["ca" ] = "CA" ; |
152 | capitalize_string_remaps["ccdik" ] = "CCDIK" ; |
153 | capitalize_string_remaps["cd" ] = "CD" ; |
154 | capitalize_string_remaps["cpu" ] = "CPU" ; |
155 | capitalize_string_remaps["csg" ] = "CSG" ; |
156 | capitalize_string_remaps["db" ] = "dB" ; |
157 | capitalize_string_remaps["dof" ] = "DoF" ; |
158 | capitalize_string_remaps["dpi" ] = "DPI" ; |
159 | capitalize_string_remaps["dtls" ] = "DTLS" ; |
160 | capitalize_string_remaps["eol" ] = "EOL" ; |
161 | capitalize_string_remaps["erp" ] = "ERP" ; |
162 | capitalize_string_remaps["etc" ] = "ETC" ; |
163 | capitalize_string_remaps["etc2" ] = "ETC2" ; |
164 | capitalize_string_remaps["fabrik" ] = "FABRIK" ; |
165 | capitalize_string_remaps["fbx" ] = "FBX" ; |
166 | capitalize_string_remaps["fbx2gltf" ] = "FBX2glTF" ; |
167 | capitalize_string_remaps["fft" ] = "FFT" ; |
168 | capitalize_string_remaps["fg" ] = "FG" ; |
169 | capitalize_string_remaps["filesystem" ] = "FileSystem" ; |
170 | capitalize_string_remaps["fov" ] = "FOV" ; |
171 | capitalize_string_remaps["fps" ] = "FPS" ; |
172 | capitalize_string_remaps["fs" ] = "FS" ; |
173 | capitalize_string_remaps["fsr" ] = "FSR" ; |
174 | capitalize_string_remaps["fxaa" ] = "FXAA" ; |
175 | capitalize_string_remaps["gdscript" ] = "GDScript" ; |
176 | capitalize_string_remaps["ggx" ] = "GGX" ; |
177 | capitalize_string_remaps["gi" ] = "GI" ; |
178 | capitalize_string_remaps["gl" ] = "GL" ; |
179 | capitalize_string_remaps["glb" ] = "GLB" ; |
180 | capitalize_string_remaps["gles2" ] = "GLES2" ; |
181 | capitalize_string_remaps["gles3" ] = "GLES3" ; |
182 | capitalize_string_remaps["gltf" ] = "glTF" ; |
183 | capitalize_string_remaps["gpu" ] = "GPU" ; |
184 | capitalize_string_remaps["gui" ] = "GUI" ; |
185 | capitalize_string_remaps["guid" ] = "GUID" ; |
186 | capitalize_string_remaps["hdr" ] = "HDR" ; |
187 | capitalize_string_remaps["hidpi" ] = "hiDPI" ; |
188 | capitalize_string_remaps["hipass" ] = "High-pass" ; |
189 | capitalize_string_remaps["hl" ] = "HL" ; |
190 | capitalize_string_remaps["hsv" ] = "HSV" ; |
191 | capitalize_string_remaps["html" ] = "HTML" ; |
192 | capitalize_string_remaps["http" ] = "HTTP" ; |
193 | capitalize_string_remaps["id" ] = "ID" ; |
194 | capitalize_string_remaps["ids" ] = "IDs" ; |
195 | capitalize_string_remaps["igd" ] = "IGD" ; |
196 | capitalize_string_remaps["ik" ] = "IK" ; |
197 | capitalize_string_remaps["image@2x" ] = "Image @2x" ; |
198 | capitalize_string_remaps["image@3x" ] = "Image @3x" ; |
199 | capitalize_string_remaps["iod" ] = "IOD" ; |
200 | capitalize_string_remaps["ios" ] = "iOS" ; |
201 | capitalize_string_remaps["ip" ] = "IP" ; |
202 | capitalize_string_remaps["ipad" ] = "iPad" ; |
203 | capitalize_string_remaps["iphone" ] = "iPhone" ; |
204 | capitalize_string_remaps["ipv6" ] = "IPv6" ; |
205 | capitalize_string_remaps["ir" ] = "IR" ; |
206 | capitalize_string_remaps["itunes" ] = "iTunes" ; |
207 | capitalize_string_remaps["jit" ] = "JIT" ; |
208 | capitalize_string_remaps["k1" ] = "K1" ; |
209 | capitalize_string_remaps["k2" ] = "K2" ; |
210 | capitalize_string_remaps["kb" ] = "(KB)" ; // Unit. |
211 | capitalize_string_remaps["lcd" ] = "LCD" ; |
212 | capitalize_string_remaps["ldr" ] = "LDR" ; |
213 | capitalize_string_remaps["lod" ] = "LOD" ; |
214 | capitalize_string_remaps["lods" ] = "LODs" ; |
215 | capitalize_string_remaps["lowpass" ] = "Low-pass" ; |
216 | capitalize_string_remaps["macos" ] = "macOS" ; |
217 | capitalize_string_remaps["mb" ] = "(MB)" ; // Unit. |
218 | capitalize_string_remaps["mjpeg" ] = "MJPEG" ; |
219 | capitalize_string_remaps["mms" ] = "MMS" ; |
220 | capitalize_string_remaps["ms" ] = "(ms)" ; // Unit |
221 | capitalize_string_remaps["msaa" ] = "MSAA" ; |
222 | capitalize_string_remaps["msdf" ] = "MSDF" ; |
223 | // Not used for now as AudioEffectReverb has a `msec` property. |
224 | //capitalize_string_remaps["msec"] = "(msec)"; // Unit. |
225 | capitalize_string_remaps["navmesh" ] = "NavMesh" ; |
226 | capitalize_string_remaps["nfc" ] = "NFC" ; |
227 | capitalize_string_remaps["ok" ] = "OK" ; |
228 | capitalize_string_remaps["opengl" ] = "OpenGL" ; |
229 | capitalize_string_remaps["opentype" ] = "OpenType" ; |
230 | capitalize_string_remaps["openxr" ] = "OpenXR" ; |
231 | capitalize_string_remaps["osslsigncode" ] = "osslsigncode" ; |
232 | capitalize_string_remaps["pck" ] = "PCK" ; |
233 | capitalize_string_remaps["png" ] = "PNG" ; |
234 | capitalize_string_remaps["po2" ] = "(Power of 2)" ; // Unit. |
235 | capitalize_string_remaps["ppc32" ] = "ppc32" ; |
236 | capitalize_string_remaps["ppc64" ] = "ppc64" ; |
237 | capitalize_string_remaps["pvrtc" ] = "PVRTC" ; |
238 | capitalize_string_remaps["pvs" ] = "PVS" ; |
239 | capitalize_string_remaps["rcedit" ] = "rcedit" ; |
240 | capitalize_string_remaps["rcodesign" ] = "rcodesign" ; |
241 | capitalize_string_remaps["rgb" ] = "RGB" ; |
242 | capitalize_string_remaps["rid" ] = "RID" ; |
243 | capitalize_string_remaps["rmb" ] = "RMB" ; |
244 | capitalize_string_remaps["rpc" ] = "RPC" ; |
245 | capitalize_string_remaps["rv64" ] = "rv64" ; |
246 | capitalize_string_remaps["s3tc" ] = "S3TC" ; |
247 | capitalize_string_remaps["scp" ] = "SCP" ; |
248 | capitalize_string_remaps["sdf" ] = "SDF" ; |
249 | capitalize_string_remaps["sdfgi" ] = "SDFGI" ; |
250 | capitalize_string_remaps["sdk" ] = "SDK" ; |
251 | capitalize_string_remaps["sec" ] = "(sec)" ; // Unit. |
252 | capitalize_string_remaps["signtool" ] = "signtool" ; |
253 | capitalize_string_remaps["sms" ] = "SMS" ; |
254 | capitalize_string_remaps["srgb" ] = "sRGB" ; |
255 | capitalize_string_remaps["ssao" ] = "SSAO" ; |
256 | capitalize_string_remaps["ssh" ] = "SSH" ; |
257 | capitalize_string_remaps["ssil" ] = "SSIL" ; |
258 | capitalize_string_remaps["ssl" ] = "SSL" ; |
259 | capitalize_string_remaps["sss" ] = "SSS" ; |
260 | capitalize_string_remaps["stderr" ] = "stderr" ; |
261 | capitalize_string_remaps["stdout" ] = "stdout" ; |
262 | capitalize_string_remaps["sv" ] = "SV" ; |
263 | capitalize_string_remaps["svg" ] = "SVG" ; |
264 | capitalize_string_remaps["taa" ] = "TAA" ; |
265 | capitalize_string_remaps["tcp" ] = "TCP" ; |
266 | capitalize_string_remaps["textfile" ] = "TextFile" ; |
267 | capitalize_string_remaps["tls" ] = "TLS" ; |
268 | capitalize_string_remaps["ui" ] = "UI" ; |
269 | capitalize_string_remaps["uri" ] = "URI" ; |
270 | capitalize_string_remaps["url" ] = "URL" ; |
271 | capitalize_string_remaps["urls" ] = "URLs" ; |
272 | capitalize_string_remaps["us" ] = U"(µs)" ; // Unit. |
273 | capitalize_string_remaps["usb" ] = "USB" ; |
274 | capitalize_string_remaps["usec" ] = U"(µsec)" ; // Unit. |
275 | capitalize_string_remaps["uuid" ] = "UUID" ; |
276 | capitalize_string_remaps["uv" ] = "UV" ; |
277 | capitalize_string_remaps["uv1" ] = "UV1" ; |
278 | capitalize_string_remaps["uv2" ] = "UV2" ; |
279 | capitalize_string_remaps["vector2" ] = "Vector2" ; |
280 | capitalize_string_remaps["vpn" ] = "VPN" ; |
281 | capitalize_string_remaps["vram" ] = "VRAM" ; |
282 | capitalize_string_remaps["vrs" ] = "VRS" ; |
283 | capitalize_string_remaps["vsync" ] = "V-Sync" ; |
284 | capitalize_string_remaps["wap" ] = "WAP" ; |
285 | capitalize_string_remaps["webp" ] = "WebP" ; |
286 | capitalize_string_remaps["webrtc" ] = "WebRTC" ; |
287 | capitalize_string_remaps["websocket" ] = "WebSocket" ; |
288 | capitalize_string_remaps["wine" ] = "wine" ; |
289 | capitalize_string_remaps["wifi" ] = "Wi-Fi" ; |
290 | capitalize_string_remaps["x86" ] = "x86" ; |
291 | capitalize_string_remaps["x86_32" ] = "x86_32" ; |
292 | capitalize_string_remaps["x86_64" ] = "x86_64" ; |
293 | capitalize_string_remaps["xr" ] = "XR" ; |
294 | capitalize_string_remaps["xray" ] = "X-Ray" ; |
295 | capitalize_string_remaps["xy" ] = "XY" ; |
296 | capitalize_string_remaps["xz" ] = "XZ" ; |
297 | capitalize_string_remaps["yz" ] = "YZ" ; |
298 | |
299 | // Articles, conjunctions, prepositions. |
300 | // The following initialization is parsed in `editor/translations/scripts/common.py` with a regex. |
301 | // The word definition format should be kept synced with the regex. |
302 | stop_words = LocalVector<String>({ |
303 | "a" , |
304 | "an" , |
305 | "and" , |
306 | "as" , |
307 | "at" , |
308 | "by" , |
309 | "for" , |
310 | "in" , |
311 | "not" , |
312 | "of" , |
313 | "on" , |
314 | "or" , |
315 | "over" , |
316 | "per" , |
317 | "the" , |
318 | "then" , |
319 | "to" , |
320 | }); |
321 | } |
322 | |
323 | EditorPropertyNameProcessor::~EditorPropertyNameProcessor() { |
324 | singleton = nullptr; |
325 | } |
326 | |