Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
LocParserManager.c
Go to the documentation of this file.
1[BaseContainerProps(configRoot: true)]
3{
4 [Attribute("{C014582791ECBF24}Language/localization.st", desc: "String table where new strings will be added.", params: "st")]
6
7 [Attribute("AR-", desc: "Project prefix added at the beginning of every string ID.")]
8 protected string m_sPrefix;
9
10 [Attribute("!", desc: "Ignore string when it starts with this expression.\nUsed to mark placeholder texts which are replaced by script.")]
11 protected string m_sPlaceholderPrefix;
12
13 [Attribute()]
14 protected ref array<ref LocParserRule> m_aRules;
15
18 protected bool m_bLogOnly;
20 protected ref array<BaseContainer> m_aRuleSources = {};
21 protected int m_iCurrentRule;
22
23 static const string LOCALIZED_PREFIX = "#"; // used by LocParserRule_Custom_StringParam
24
25 //------------------------------------------------------------------------------------------------
30 BaseContainer UpdateItem(out string id, string text)
31 {
32 //--- Add project prefix
33 if (!m_sPrefix.IsEmpty() && !id.StartsWith(m_sPrefix))
34 id = m_sPrefix + id;
35
36 //--- Check if the item already exist
37 string existingText;
38 bool exists = m_mIDs.Find(id, existingText);
39
40 LocalizationEditor stringEditor = Workbench.GetModule(LocalizationEditor);
41 BaseContainer stringTable = stringEditor.GetTable();
42 if (!stringTable)
43 {
44 Print(string.Format("Unable to open string table '%1'!", m_StringTablePath.GetPath()), LogLevel.WARNING);
45 return null;
46 }
47
48 BaseContainer item;
49 if (!m_bLogOnly && !exists)
50 {
51 //--- Create item
52 int index = m_mIDs.Count();
53 WorldEditorAPI worldEditorAPI = ((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();
54 if (!worldEditorAPI.CreateObjectArrayVariableMember(stringTable, null, "Items", "CustomStringTableItem", index))
55 return null;
56
57 //--- Retrieve the item
58 BaseContainerList items = stringTable.GetObjectArray("Items");
59 item = items.Get(index);
60
61 //--- Apply template
62 UpdateFromTemplate(stringEditor, item);
63
64 //--- Save mandatory information
65 string userName;
66 Workbench.GetUserName(userName);
67
68 stringEditor.ModifyProperty(item, item.GetVarIndex("Id"), id);
69 stringEditor.ModifyProperty(item, item.GetVarIndex("Target_en_us"), text);
70 stringEditor.ModifyProperty(item, item.GetVarIndex("SourceFile"), m_sFile);
71 stringEditor.ModifyProperty(item, item.GetVarIndex("Modified"), Workbench.GetPackedUtcTime().ToString());
72 stringEditor.ModifyProperty(item, item.GetVarIndex("Author"), userName);
73 stringEditor.ModifyProperty(item, item.GetVarIndex("LastChanged"), userName);
74 }
75
76 //--- Log results
77 Print(string.Format("%1", m_sContainerPath), LogLevel.VERBOSE);
78 if (exists)
79 {
80 Print(string.Format("%1%2 = \"%3\"", LOCALIZED_PREFIX, id, text), LogLevel.NORMAL);
81 if (text == existingText)
82 {
83 Print(string.Format("Item already localized, but its text is the same.\n ", id, existingText), LogLevel.WARNING);
84 }
85 else
86 {
87 Print(string.Format("%1%2 = \"%3\"\n Item already localized, and its text differs! Localized text will be used!\n ", LOCALIZED_PREFIX, id, existingText), LogLevel.ERROR);
88 }
89 }
90 else
91 {
92 Print(string.Format("%1%2 = \"%3\"\n ", LOCALIZED_PREFIX, id, text), LogLevel.NORMAL);
93 m_mIDs.Set(id, text);
94 }
95
96 return item;
97 }
98
99 //------------------------------------------------------------------------------------------------
103 protected void UpdateFromTemplate(notnull LocalizationEditor stringEditor, notnull BaseContainer item)
104 {
106 if (!itemTemplate)
107 return;
108
109 string varName;
110 for (int v = 0, varCount = item.GetNumVars(); v < varCount; v++)
111 {
112 varName = item.GetVarName(v);
113 if (!itemTemplate.IsVariableSet(varName))
114 continue;
115
116 switch (item.GetDataVarType(v))
117 {
118 case DataVarType.STRING:
119 {
120 string value;
121 itemTemplate.Get(varName, value);
122 stringEditor.ModifyProperty(item, v, value);
123 break;
124 }
125 case DataVarType.INTEGER:
126 {
127 int value;
128 itemTemplate.Get(varName, value);
129 stringEditor.ModifyProperty(item, v, value.ToString());
130 break;
131 }
132 case DataVarType.BOOLEAN:
133 {
134 bool value;
135 itemTemplate.Get(varName, value);
136 stringEditor.ModifyProperty(item, v, value.ToString());
137 break;
138 }
139 case DataVarType.STRING_ARRAY:
140 {
141 array<string> valueInput;
142 itemTemplate.Get(varName, valueInput);
143 string valueOutput;
144 foreach (int i, string entry : valueInput)
145 {
146 if (i > 0)
147 valueOutput += ",";
148
149 valueOutput += string.ToString(entry);
150 }
151
152 stringEditor.ModifyProperty(item, v, valueOutput);
153 break;
154 }
155 case DataVarType.INTEGER_ARRAY:
156 {
157 array<int> valueInput;
158 itemTemplate.Get(varName, valueInput);
159 string valueOutput;
160 foreach (int i, int entry : valueInput)
161 {
162 if (i > 0)
163 valueOutput += ",";
164
165 valueOutput += entry.ToString();
166 }
167
168 stringEditor.ModifyProperty(item, v, valueOutput);
169 break;
170 }
171 case DataVarType.BOOLEAN_ARRAY:
172 {
173 array<bool> valueInput;
174 itemTemplate.Get(varName, valueInput);
175 string valueOutput;
176 foreach (int i, bool entry : valueInput)
177 {
178 if (i > 0)
179 valueOutput += ",";
180
181 valueOutput += entry.ToString();
182 }
183 stringEditor.ModifyProperty(item, v, valueOutput);
184 break;
185 }
186 default:
187 {
188 Print(string.Format("Cannot copy variable '%1' from template, it has unsupported type %2!", varName, typename.EnumToString(DataVarType, item.GetDataVarType(v))), LogLevel.ERROR);
189 }
190 }
191 }
192 }
193
194 //------------------------------------------------------------------------------------------------
202 protected void ProcessContainer(BaseContainer container, out int foundCount, array<BaseContainer> objects, array<int> indexes, string path, out int index = 0)
203 {
204 if (!objects.IsEmpty())
205 {
206 string containerName;
207 if (m_sFileExt == "layout")
208 {
209 container.Get("Name", containerName);
210 }
211 else
212 {
213 containerName = container.GetName();
214 if (containerName.IsEmpty())
215 containerName = container.GetClassName();
216 }
217 path += " > " + containerName;
218 }
219
220 array<BaseContainer> objectsCopy = {};
221 objectsCopy.Copy(objects);
222 objectsCopy.InsertAt(container, 0);
223
224 array<int> indexesCopy = {};
225 indexesCopy.Copy(indexes);
226 indexesCopy.InsertAt(index, 0);
227
228 //--- Process variables
229 string varName, id, text;
230 bool found;
231 for (int v = 0, varCount = container.GetNumVars(); v < varCount; v++)
232 {
233 varName = container.GetVarName(v);
234
235 //--- Skip if inherited from parent
236 if (!container.IsVariableSetDirectly(varName))
237 continue;
238
239 if (container.IsType(varName, string) && container.Get(varName, text))
240 {
241 //--- String, try to localize it
242 if (text.IsEmpty())
243 continue;
244
245 //--- Already localized
246 if (text.Contains(LOCALIZED_PREFIX) || text.StartsWith(m_sPlaceholderPrefix))
247 continue;
248
249 //--- Localize
250 found = false;
251 foreach (int r, LocParserRule rule : m_aRules)
252 {
253 if (rule.Evaluate(m_sFileName, varName, objectsCopy))
254 {
255 indexesCopy.Set(indexesCopy.Count() - 1, index);
256 id = rule.GetID(m_sFileName, varName, objectsCopy, indexesCopy);
257 index++;
258 if (!id.IsEmpty())
259 {
260 found = true;
261 foundCount++;
262 id = m_sPrefix + id;
264 m_iCurrentRule = r;
265 rule.Localize(m_sFileName, varName, objectsCopy, id, text);
266
267 if (!m_bLogOnly)
268 container.Set(varName, LOCALIZED_PREFIX + id);
269 }
270 break;
271 }
272 }
273
274 //--- No rule caught it, but the string is still marked for localization
275 string uiWidget = container.GetUIWidget(v);
276 if (m_bLogOnly && !found && (uiWidget == "localeeditbox" || uiWidget == "editboxWithButton"))
277 {
278 foundCount++;
280 Print(string.Format("%1", m_sContainerPath), LogLevel.VERBOSE);
281 Print(string.Format("No rule found for: %1 = '%2'\n\n", varName, text), LogLevel.WARNING);
282 }
283
284 continue;
285 }
286
287 BaseContainer object = container.GetObject(varName);
288 if (object)
289 {
290 //--- Object, process its variables
291 ProcessContainer(object, foundCount, objectsCopy, indexesCopy, path + " > " + varName);
292 }
293 else
294 {
295 //--- Array of objects, process every element
296 BaseContainerList list = container.GetObjectArray(varName);
297 if (list)
298 {
299 int index2;
300 for (int l = 0, listCount = list.Count(); l < listCount; l++)
301 {
302 ProcessContainer(list.Get(l), foundCount, objectsCopy, indexesCopy, path + string.Format(" > %1[%2]", varName, l), index2);
303 }
304 }
305 }
306 }
307
308 //--- Process children
309 if (container)
310 {
311 for (int e = 0, count = container.GetNumChildren(); e < count; e++)
312 {
313 ProcessContainer(container.GetChild(e), foundCount, objectsCopy, indexesCopy, path);
314 }
315 }
316 }
317
318 //------------------------------------------------------------------------------------------------
324 protected void Run(BaseContainer source, bool logOnly, ResourceName stringTableOverride, string prefixOverride)
325 {
326 m_bLogOnly = logOnly;
327 if (stringTableOverride)
328 m_StringTablePath = stringTableOverride;
329
330 if (prefixOverride)
331 m_sPrefix = prefixOverride;
332
333 if (!Workbench.OpenModule(LocalizationEditor))
334 return;
335
336 LocalizationEditor stringEditor = Workbench.GetModule(LocalizationEditor);
337 stringEditor.SetOpenedResource(m_StringTablePath);
338 BaseContainer stringTable = stringEditor.GetTable();
339 if (!stringTable)
340 {
341 Print(string.Format("Unable to open string table '%1'!", m_StringTablePath.GetPath()), LogLevel.WARNING);
342 return;
343 }
344
345 //--- Get all items, so we can check if item exists
346 BaseContainerList items = stringTable.GetObjectArray("Items");
347 BaseContainer item;
348 string itemId, itemText;
349 int itemsCount = items.Count();
350 for (int i = 0; i < itemsCount; i++)
351 {
352 item = items.Get(i);
353 item.Get("Id", itemId);
354 item.Get("Target_en_us", itemText);
355 m_mIDs.Insert(itemId, itemText);
356 }
357
358 if (!m_bLogOnly)
359 {
360 if (!Workbench.OpenModule(WorldEditor))
361 return;
362
363 stringEditor.BeginModify("Automatic localization");
364 }
365
366 //--- Initialize rules
367 BaseContainerList rulesSource = source.GetObjectArray("m_aRules"); //--- Save sources, because CustomStringTableItem objects cannot be created in script
368 foreach (int r, LocParserRule rule : m_aRules)
369 {
370 m_aRuleSources.Insert(rulesSource.Get(r).GetObject("m_ItemTemplate"));
371 rule.InitRule(this);
372 }
373
374 //--- Get selected files
375 array<ResourceName> selection = {};
376 ResourceManager resourceManager = Workbench.GetModule(ResourceManager);
377 resourceManager.GetResourceBrowserSelection(selection.Insert, true);
378 WBProgressDialog progress = new WBProgressDialog("Processing...", resourceManager);
379
380 //--- Process files
381 int foundCount, foundCountPrev;
382 int selectionCount = selection.Count();
383 Resource resource;
384 BaseResourceObject baseResource;
385 BaseContainer container;
386 Managed instance;
387 for (int i = 0; i < selectionCount; i++)
388 {
389 progress.SetProgress(i / selectionCount);
390
391 m_sFile = selection[i];
392
393 resource = Resource.Load(m_sFile);
394 if (!resource || !resource.IsValid())
395 continue;
396
397 baseResource = resource.GetResource();
398 if (!baseResource)
399 continue;
400
401 container = baseResource.ToBaseContainer();
402 if (!container)
403 continue;
404
405 foundCountPrev = foundCount;
406 m_sFileName = FilePath.StripExtension(FilePath.StripPath(m_sFile), m_sFileExt);
407 m_sFileLink = string.Format("@\"%1\"", m_sFile.GetPath());
408 array<BaseContainer> objects = {};
409 array<int> indexes = {};
410 ProcessContainer(container, foundCount, objects, indexes, m_sFileLink);
411
412 if (!m_bLogOnly && foundCount != foundCountPrev)
413 {
414 BaseContainerTools.SaveContainer(container, m_sFile);
415 }
416 }
417
418 if (!m_bLogOnly)
419 {
420 stringEditor.EndModify();
421 if (foundCount > 0)
422 {
423 stringEditor.Save();
424
425 //--- Show only newly added strings
426 array<int> newIds = {};
427 for (int i = itemsCount, itemsCountNew = items.Count(); i <= itemsCountNew; i++)
428 {
429 newIds.Insert(i);
430 }
431 stringEditor.AddUserFilter(newIds, "New strings");
432 }
433 }
434
435 if (m_bLogOnly)
436 {
437 LogLevel logLevel = LogLevel.DEBUG;
438 if (foundCount > 0)
439 logLevel = LogLevel.WARNING;
440
441 Print(string.Format("%1 file(s) processed, %2 unlocalized string(s) found\n Logging only, no files were modified.", selectionCount, foundCount), logLevel);
442 }
443 else
444 {
445 Print(string.Format("%1 file(s) processed, %2 string(s) localized", selectionCount, foundCount), LogLevel.DEBUG);
446 }
447
448 m_mIDs = null;
449 stringEditor = null;
450 }
451
452 //------------------------------------------------------------------------------------------------
458 static void Run(ResourceName configPath, bool logOnly, ResourceName stringTableOverride, string prefixOverride)
459 {
460 Resource configResource = Resource.Load(configPath);
461 if (!configResource.IsValid())
462 {
463 Print(string.Format("Cannot load config '%1'!", configPath), LogLevel.WARNING);
464 return;
465 }
466
467 BaseResourceObject configContainer = configResource.GetResource();
468 if (!configContainer)
469 return;
470
471 BaseContainer configBase = configContainer.ToBaseContainer();
472 if (!configBase)
473 return;
474
475 if (configBase.GetClassName().ToType() != LocParserManager)
476 {
477 Print(string.Format("Config '%1' is of type '%2', must be 'LocParserManager'!", configPath, configBase.GetClassName()), LogLevel.WARNING);
478 return;
479 }
480
481 LocParserManager manager = LocParserManager.Cast(BaseContainerTools.CreateInstanceFromContainer(configBase));
482 if (manager)
483 manager.Run(configBase, logOnly, stringTableOverride, prefixOverride);
484 else
485 Print(string.Format("Unknown error when creating instance of config '%1'!", configPath), LogLevel.WARNING);
486 }
487}
string path
AddonBuildInfoTool id
CheckGUIDRequest exists
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
void UpdateFromTemplate(notnull LocalizationEditor stringEditor, notnull BaseContainer item)
BaseContainer UpdateItem(out string id, string text)
ref array< BaseContainer > m_aRuleSources
static void Run(ResourceName configPath, bool logOnly, ResourceName stringTableOverride, string prefixOverride)
void ProcessContainer(BaseContainer container, out int foundCount, array< BaseContainer > objects, array< int > indexes, string path, out int index=0)
ref map< string, string > m_mIDs
void Run(BaseContainer source, bool logOnly, ResourceName stringTableOverride, string prefixOverride)
static const string LOCALIZED_PREFIX
ResourceName m_StringTablePath
ref array< ref LocParserRule > m_aRules
ResourceName m_sFile
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
Definition Types.c:486
DataVarType
Definition DataVarType.c:18
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
proto native bool IsEmpty()