| 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 | |