Skip to content

Commit f446a74

Browse files
author
o.nadymov
committed
Support for invalid multiple languages.
1 parent 099e0ec commit f446a74

File tree

7 files changed

+128
-19
lines changed

7 files changed

+128
-19
lines changed

src/Core.Common.LocalizableString.Tests/Core.Common.LocalizableString.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<!--<Nullable>enable</Nullable>-->
77

src/Core.Common.LocalizableString.Tests/LocalizableStringJsonConverterTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,51 @@ public void DeserializeObjectWithEmptyLocalizableString()
153153
// Assert
154154
Assert.That(obj.Description.Languages, Has.Count.EqualTo(2));
155155
}
156+
157+
[Test]
158+
public void DeserializeObjectListWithExcessLSCharacters()
159+
{
160+
// Arrange
161+
var language1 = "ru";
162+
var language2 = "en";
163+
// without the third EndPattern. Substring in string:
164+
var text = $"{LocalizableString.StartPattern}{language1}{LocalizableString.StartPattern}Текст на русском{LocalizableString.EndPattern}{LocalizableString.StartPattern}{language2}{LocalizableString.StartPattern}Text in English{LocalizableString.StartPattern}{language1}{LocalizableString.StartPattern}Снова текст на русском!{LocalizableString.EndPattern}";
165+
var testObjList = new List<TestClass>{
166+
new()
167+
{
168+
Name = "One",
169+
Description = text
170+
}
171+
};
172+
173+
// Act
174+
var json = JsonSerializer.Serialize(testObjList, _jsonSerializerOptions);
175+
var afterJson = JsonSerializer.Deserialize<List<TestClass>>(json, _jsonSerializerOptions);
176+
177+
// Assert
178+
Assert.That(afterJson[0].Description.OriginalString, Is.Not.EqualTo(text));
179+
Assert.That(afterJson[0].Description.OriginalString, Is.EqualTo(text.Replace(LocalizableString.StartPattern, string.Empty).Replace(LocalizableString.EndPattern, string.Empty)));
180+
}
181+
182+
[Test]
183+
public void DeserializeObjectListWithoutMultilanguage()
184+
{
185+
// Arrange
186+
var text = "string";
187+
var testObjList = new List<TestClass>{
188+
new()
189+
{
190+
Name = "One",
191+
Description = text
192+
}
193+
};
194+
195+
// Act
196+
var json = JsonSerializer.Serialize(testObjList, _jsonSerializerOptions);
197+
var afterJson = JsonSerializer.Deserialize<List<TestClass>>(json, _jsonSerializerOptions);
198+
199+
// Assert
200+
Assert.That(afterJson[0].Description.OriginalString, Is.EqualTo(text));
201+
}
156202
}
157203
}

src/Core.Common.LocalizableString.Tests/LocalizableStringTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,26 @@ public void DictionaryToLocalizableString()
128128
Assert.That(ls.GetCurrentString("en"), Is.EqualTo(enText));
129129
});
130130
}
131+
132+
[Test]
133+
public void StringWithLanguageInConstructorWithTwoSameLanguageCodes()
134+
{
135+
// Arrange
136+
var language1 = "ru";
137+
var language2 = "en";
138+
var text = $"{LocalizableString.StartPattern}{language1}{LocalizableString.StartPattern}Текст на русском{LocalizableString.EndPattern}{LocalizableString.StartPattern}{language2}{LocalizableString.StartPattern}Text in English{LocalizableString.EndPattern}{LocalizableString.StartPattern}{language1}{LocalizableString.StartPattern}Снова текст на русском!{LocalizableString.EndPattern}";
139+
140+
// Act
141+
var ls = new LocalizableString(text);
142+
143+
// Assert
144+
Assert.Multiple(() =>
145+
{
146+
Assert.That(ls, Is.Not.Null);
147+
Assert.That(ls.StringCurrent, Is.Not.Null);
148+
Assert.That(ls.OriginalString, Is.EqualTo(text));
149+
Assert.That(text, Does.Contain(ls.StringCurrent));
150+
});
151+
}
131152
}
132153
}

src/Core.Common.LocalizableString/Core.Common.LocalizableString.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net7.0;netstandard2.0</TargetFrameworks>
4+
<TargetFrameworks>net8.0;net7.0;netstandard2.0</TargetFrameworks>
55
<AssemblyName>Core.Common.LocalizableString</AssemblyName>
66
<RootNamespace>Core.Common.LocalizableString</RootNamespace>
77
<Title>Core.Common.LocalizableString</Title>
@@ -51,7 +51,7 @@
5151

5252
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789.`))' == 'netstandard'">
5353
<!-- Properties for netstandard -->
54-
<PackageReference Include="System.Text.Json" Version="7.0.2" />
54+
<PackageReference Include="System.Text.Json" Version="8.0.5" />
5555
</ItemGroup>
5656

5757
<ItemGroup>

src/Core.Common.LocalizableString/Extensions/LocalizableStringExtensions.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,22 @@ public static LocalizableString AsLocalizableString(this IDictionary dict)
8686
/// </summary>
8787
public static object AsJsonCompatible(this LocalizableString localizableString)
8888
{
89-
var languages = localizableString.Languages;
90-
if (languages.Count > 0)
89+
if (localizableString.HaveMultipleLanguages)
9190
{
92-
var dict = new OrderedDictionary();
93-
foreach (var language in languages)
91+
var languages = localizableString.Languages;
92+
if (languages.Count > 0)
9493
{
95-
var currentString = localizableString.GetCurrentString(language);
96-
EnsureIsJsonCompatible(currentString, localizableString.OriginalString);
94+
var dict = new OrderedDictionary();
95+
foreach (var language in languages)
96+
{
97+
var currentString = localizableString.GetCurrentString(language);
98+
EnsureIsJsonCompatible(currentString, localizableString.OriginalString);
9799

98-
dict[language] = currentString;
99-
}
100+
dict[language] = currentString;
101+
}
100102

101-
return dict;
103+
return dict;
104+
}
102105
}
103106

104107
var oneLanguageString = localizableString.StringCurrent;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace Core.Common
2+
{
3+
/// <summary>
4+
/// String extensions.
5+
/// </summary>
6+
public static class StringExtensions
7+
{
8+
/// <summary>
9+
/// Count of sub-string occurrences within the string.
10+
/// </summary>
11+
public static int CountSubstring(this string text, string value)
12+
{
13+
return (text.Length - text.Replace(value, string.Empty).Length) / value.Length;
14+
}
15+
}
16+
}

src/Core.Common.LocalizableString/LocalizableString.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace Core.Common
1616
[DataContract]
1717
public class LocalizableString : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
1818
{
19+
private enum ValidationState { SingleLanguage, ValidMultipleLanguages, InvalidMultipleLanguages }
20+
1921
[IgnoreDataMember]
2022
private string _stringCurrent;
2123

@@ -102,18 +104,43 @@ private void ProcessOriginalString(string s)
102104
{
103105
if (s == null) return;
104106

105-
if (!Regex.IsMatch(s, Pattern))
107+
var state = Validate(s);
108+
109+
if (state == ValidationState.SingleLanguage)
106110
{
107111
_stringOriginal = _stringCurrent = s;
108112
_haveMultipleLanguages = false;
109113
}
110-
else
114+
else if (state == ValidationState.ValidMultipleLanguages)
111115
{
112116
_haveMultipleLanguages = true;
113117
_stringOriginal = s;
114118

115119
_stringCurrent = GetString(_stringOriginal, true);
116120
}
121+
else
122+
{
123+
_stringOriginal = _stringCurrent = s.Replace(StartPattern, string.Empty).Replace(EndPattern, string.Empty);
124+
_haveMultipleLanguages = false;
125+
}
126+
}
127+
128+
private static ValidationState Validate(string s)
129+
{
130+
if (!Regex.IsMatch(s, Pattern))
131+
{
132+
return ValidationState.SingleLanguage;
133+
}
134+
135+
var countStartPatterns = s.CountSubstring(StartPattern);
136+
var countEndPatterns = s.CountSubstring(EndPattern);
137+
if (countStartPatterns == countEndPatterns * 2)
138+
{
139+
return ValidationState.ValidMultipleLanguages;
140+
}
141+
142+
return ValidationState.InvalidMultipleLanguages;
143+
117144
}
118145

119146
/// <summary>
@@ -525,13 +552,9 @@ public string StringCurrent
525552
/// <summary>
526553
/// GetString
527554
/// </summary>
528-
/// <param name="s"></param>
529-
/// <param name="getFirstValueIfNotExists"></param>
530-
/// <param name="codeLanguage"></param>
531-
/// <returns></returns>
532555
private string GetString(string s, bool getFirstValueIfNotExists = false, string codeLanguage = null)
533556
{
534-
if (codeLanguage == null) codeLanguage = CurrentLanguageKey;
557+
codeLanguage ??= CurrentLanguageKey;
535558

536559
var matches = Regex.Matches(s, Pattern);
537560

0 commit comments

Comments
 (0)