diff --git a/MN.L10n.BuildTasks/MN.L10n.BuildTasks.csproj b/MN.L10n.BuildTasks/MN.L10n.BuildTasks.csproj
index a4625e6..759b992 100644
--- a/MN.L10n.BuildTasks/MN.L10n.BuildTasks.csproj
+++ b/MN.L10n.BuildTasks/MN.L10n.BuildTasks.csproj
@@ -6,7 +6,7 @@
Exe
MN.L10n.BuildTasks.Program
true
- 4.0.1
+ 4.0.4
Chris Gårdenberg
MultiNet Interactive AB
diff --git a/MN.L10n.Tests/ParserTests.cs b/MN.L10n.Tests/ParserTests.cs
index 9a5ef98..297d2a4 100644
--- a/MN.L10n.Tests/ParserTests.cs
+++ b/MN.L10n.Tests/ParserTests.cs
@@ -115,5 +115,56 @@ public void LineBreakCharInCall()
Assert.Collection(result, x => Assert.Equal("Hello\nBrother", x.Phrase));
}
+
+ [Fact]
+ public void TestEscapedStringContainerCharacter()
+ {
+ var parser = new L10nParser();
+ var result = parser.Parse(@"_s(""Hello \""friend\"". How it do?"")");
+
+ Assert.Collection(result, x => Assert.Equal(@"Hello ""friend"". How it do?", x.Phrase));
+ }
+
+ [Fact]
+ public void TestEscapedStringContainerCharacter2()
+ {
+ var parser = new L10nParser();
+ var result = parser.Parse(@"_s('Hello \""friend\"". How it do?')");
+
+ Assert.Collection(result, x => Assert.Equal(@"Hello \""friend\"". How it do?", x.Phrase));
+ }
+
+ [Fact]
+ public void TestEscapedStringContainerCharacter3()
+ {
+ var parser = new L10nParser();
+ var result = parser.Parse(@"_s('Hello \'friend\'. How it do?')");
+
+ Assert.Collection(result, x => Assert.Equal(@"Hello 'friend'. How it do?", x.Phrase));
+ }
+
+ [Fact]
+ public void TestEscapedStringContainerCharacterFirstChar()
+ {
+ var parser = new L10nParser();
+ var result = parser.Parse(@"_s(""\""friend\""!"")");
+
+ Assert.Collection(result, x => Assert.Equal(@"""friend""!", x.Phrase));
+ }
+
+ [Fact]
+ public void TestEscapedStringContainerCharacterVerbatim()
+ {
+ var src = @"
+ _s(
+ @""Hej """"bror""""
+Nej""
+ )
+ ";
+ var parser = new L10nParser();
+ var result = parser.Parse(src).ToList();
+ Assert.Single(result);
+ Assert.Equal(@"Hej ""bror""\nNej", result[0].Phrase.Trim());
+ }
}
}
diff --git a/MN.L10n/L10nParser.cs b/MN.L10n/L10nParser.cs
index d021e77..889cc2b 100644
--- a/MN.L10n/L10nParser.cs
+++ b/MN.L10n/L10nParser.cs
@@ -86,6 +86,7 @@ bool TryPeek(int forward)
{
break;
}
+
isVerbatim = true;
}
else
@@ -115,6 +116,7 @@ bool TryPeek(int forward)
continue;
}
}
+
if (inToken)
{
_tokenContent.Append(source[_pos]);
@@ -143,7 +145,7 @@ bool TryPeek(int forward)
phrase = phrase.Substring(0, phrase.Length - 1);
}
- yield return new PhraseInvocation
+ yield return Unescape(new PhraseInvocation
{
Phrase = phrase,
Row = row,
@@ -151,7 +153,7 @@ bool TryPeek(int forward)
EndChar = _pos,
IsEscaped = isEscaped,
StringContainer = _stringContainer
- };
+ }, isVerbatim);
inToken = false;
}
}
@@ -159,9 +161,11 @@ bool TryPeek(int forward)
{
var _tail = source[_pos - 1];
var _peek = source[_pos + 1];
- if (source[_pos] == _stringContainer && _peek != _stringContainer && _tail != _stringContainer)
+ if (source[_pos] == _stringContainer && _peek != _stringContainer &&
+ _tail != _stringContainer)
{
- var phrase = _tokenContent.ToString().Replace("\n", "\\n").Replace("\r", "").Replace("\"\"", "\\\"");
+ var phrase = _tokenContent.ToString().Replace("\n", "\\n").Replace("\r", "")
+ .Replace("\"\"", "\\\"");
// Hoppa över sista \ om den är escape:ad
if (isEscaped)
@@ -169,31 +173,70 @@ bool TryPeek(int forward)
phrase = phrase.Substring(0, phrase.Length - 1);
}
- yield return new PhraseInvocation
+ yield return Unescape(new PhraseInvocation
{
Phrase = phrase,
Row = row,
StartChar = startChar,
EndChar = _pos,
StringContainer = _stringContainer
- };
+ }, isVerbatim);
inToken = false;
}
}
-
- if (inToken && !isVerbatim && source[_pos] == '\\' && TryPeek(1) && source[_pos + 1] == 'n')
- {
- _pos++;
- _tokenContent.Append('\n');
- }
- else
- {
- _tokenContent.Append(source[_pos]);
- }
+ _tokenContent.Append(source[_pos]);
}
+
break;
}
}
}
+
+ private PhraseInvocation Unescape(PhraseInvocation phraseInvocation, bool isVerbatim)
+ {
+ if (isVerbatim)
+ {
+ for (var i = 0; i < phraseInvocation.Phrase.Length; i++)
+ {
+ if (phraseInvocation.Phrase[i] == '\\' && i + 1 < phraseInvocation.Phrase.Length)
+ {
+ if (phraseInvocation.Phrase[i + 1] == phraseInvocation.StringContainer)
+ {
+ phraseInvocation.Phrase = phraseInvocation.Phrase.Remove(i, 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (var i = 0; i < phraseInvocation.Phrase.Length; i++)
+ {
+ if (phraseInvocation.Phrase[i] == '\\' && i + 1 < phraseInvocation.Phrase.Length)
+ {
+ switch (phraseInvocation.Phrase[i + 1])
+ {
+ case 'n':
+ phraseInvocation.Phrase = phraseInvocation.Phrase.Remove(i, 2).Insert(i, "\n");
+ break;
+ case 't':
+ phraseInvocation.Phrase = phraseInvocation.Phrase.Remove(i, 2).Insert(i, "\t");
+ break;
+ case '\\':
+ phraseInvocation.Phrase = phraseInvocation.Phrase.Remove(i, 2).Insert(i, "\\");
+ break;
+ default:
+ if (phraseInvocation.Phrase[i + 1] == phraseInvocation.StringContainer)
+ {
+ phraseInvocation.Phrase = phraseInvocation.Phrase.Remove(i, 1);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ return phraseInvocation;
+ }
}
}
diff --git a/MN.L10n/MN.L10n.csproj b/MN.L10n/MN.L10n.csproj
index 2cfe70b..f528924 100644
--- a/MN.L10n/MN.L10n.csproj
+++ b/MN.L10n/MN.L10n.csproj
@@ -12,14 +12,14 @@ Translation package
https://github.com/MultinetInteractive/MN.L10n
git
© 20XX MultiNet Interactive AB
- 4.1.1
+ 4.1.3
latest
True
Now includes analyzer
Library
- 4.1.1
+ 4.1.3