Line 333: |
Line 333: |
| The new methods also handle null as you'd expect. For example, <samp>left.EqualsIgnoreCase(right)</samp> will be true if both are null. | | The new methods also handle null as you'd expect. For example, <samp>left.EqualsIgnoreCase(right)</samp> will be true if both are null. |
| |} | | |} |
| + | |
| + | ===SyntaxAbstractor=== |
| + | '''⚠ This is highly specialized.''' It's meant for vanilla unit tests, so it may not handle non-vanilla text correctly and may change at any time. |
| + | |
| + | The new <samp>SyntaxAbstractor</samp> class converts arbitrary text from content assets into language-independent syntax representations. These representations can be compared between languages to make sure they have the same sequence of commands, portraits, unlocalized metadata and delimiters, etc. This supports dialogue, event/festival, mail, and specific data formats. |
| + | |
| + | For example: |
| + | <syntaxhighlight lang="c#"> |
| + | SyntaxAbstractor abstractor = new(); |
| + | |
| + | // for an asset |
| + | string syntax = abstractor.ExtractSyntaxFor("Characters/Dialogue/Abigail", "Sun_old", "$p 17#I guess you think nothing would happen, right?$u|Maybe a wicked ghost would appear!"); // $p 17#text$u|text |
| + | |
| + | // for a format |
| + | string syntax = abstractor.ExtractMailSyntax("Hey there!^I had some extra wood lying around... I thought maybe you could use it. Take care! ^ -Robin %item id (O)388 50 %%[#]A Gift From Robin"); // text%item id (O)388 50%%[#]text |
| + | |
| + | // for arbitrary delimited data |
| + | string customData = "SomeKey/Example Title/An example description./Robin (O)788 Forest 110 81/-1/true/Hey, nice to see you!$h"; |
| + | int[] textFields = [1, 2]; |
| + | int[] dialogueFields = [6]; |
| + | string syntax = abstractor.ExtractDelimitedDataSyntax(customData, '/', textFields, dialogueFields); // SomeKey/text/text/Robin (O)788 Forest 110 81/-1/true/text$h |
| + | </syntaxhighlight> |
| + | |
| + | This is meant for unit tests that compare translations with the base text to make sure the basic format is the same. For example: |
| + | <syntaxhighlight lang="c#"> |
| + | SyntaxAbstractor syntax = new(); |
| + | |
| + | string baseSyntax = SyntaxAbstractor.ExtractDialogueSyntax(baseText); |
| + | string translatedSyntax = SyntaxAbstractor.ExtractDialogueSyntax(translatedText); |
| + | |
| + | if (baseSyntax != translatedSyntax) |
| + | { |
| + | Assert.Fail( |
| + | $""" |
| + | Syntax: |
| + | base: {baseSyntax} |
| + | local: {translatedSyntax} |
| + | {"".PadRight(GetDiffIndex(baseSyntax, translatedSyntax), ' ')}^ |
| + | Text: |
| + | base: {baseText} |
| + | local: {translatedText} |
| + | {"".PadRight(GetDiffIndex(baseText, translatedText), ' ')}^ |
| + | """ |
| + | ); |
| + | } |
| + | |
| + | // get the index at which two strings differ |
| + | int GetDiffIndex(string baseText, string translatedText) |
| + | { |
| + | int minLength = Math.Min(baseText.Length, translatedText.Length); |
| + | |
| + | for (int i = 0; i < minLength; i++) |
| + | { |
| + | if (baseText[i] != translatedText[i]) |
| + | return i; |
| + | } |
| + | |
| + | return minLength; |
| + | } |
| + | </syntaxhighlight> |
| | | |
| ===New utility fields & methods=== | | ===New utility fields & methods=== |