diagnostic to detect malformed format strings in lsg template message (#81503)
authorAllan Targino <13934447+allantargino@users.noreply.github.com>
Sun, 5 Feb 2023 19:19:43 +0000 (16:19 -0300)
committerGitHub <noreply@github.com>
Sun, 5 Feb 2023 19:19:43 +0000 (11:19 -0800)
fix https://github.com/dotnet/runtime/issues/52226

18 files changed:
docs/project/list-of-diagnostics.md
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf
src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs

index 9de7354..169bd9e 100644 (file)
@@ -133,7 +133,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
 |  __`SYSLIB1019`__ | Couldn't find a field of type Microsoft.Extensions.Logging.ILogger |
 |  __`SYSLIB1020`__ | Found multiple fields of type Microsoft.Extensions.Logging.ILogger |
 |  __`SYSLIB1021`__ | Can't have the same template with different casing |
-|  __`SYSLIB1022`__ | Can't have malformed format strings (like dangling {, etc)  |
+|  __`SYSLIB1022`__ | Logging method contains malformed format strings |
 |  __`SYSLIB1023`__ | Generating more than 6 arguments is not supported |
 |  __`SYSLIB1024`__ | Argument is using the unsupported out parameter modifier |
 |  __`SYSLIB1025`__ | Multiple logging methods cannot use the same event name within a class |
index 1c732cc..5192b75 100644 (file)
@@ -170,7 +170,7 @@ namespace Microsoft.Extensions.Logging.Generators
 
         public static DiagnosticDescriptor MalformedFormatStrings { get; } = new DiagnosticDescriptor(
             id: "SYSLIB1022",
-            title: new LocalizableResourceString(nameof(SR.MalformedFormatStringsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
+            title: new LocalizableResourceString(nameof(SR.MalformedFormatStringsTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
             messageFormat: new LocalizableResourceString(nameof(SR.MalformedFormatStringsMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)),
             category: "LoggingGenerator",
             DiagnosticSeverity.Error,
index a04ad02..ecbc1d7 100644 (file)
@@ -204,9 +204,15 @@ namespace Microsoft.Extensions.Logging.Generators
                                         SkipEnabledCheck = skipEnabledCheck
                                     };
 
-                                    ExtractTemplates(message, lm.TemplateMap, lm.TemplateList);
-
                                     bool keepMethod = true;   // whether or not we want to keep the method definition or if it's got errors making it so we should discard it instead
+
+                                    bool success = ExtractTemplates(message, lm.TemplateMap, lm.TemplateList);
+                                    if (!success)
+                                    {
+                                        Diag(DiagnosticDescriptors.MalformedFormatStrings, method.Identifier.GetLocation(), method.Identifier.ToString());
+                                        keepMethod = false;
+                                    }
+
                                     if (lm.Name[0] == '_')
                                     {
                                         // can't have logging method names that start with _ since that can lead to conflicting symbol names
@@ -595,81 +601,112 @@ namespace Microsoft.Extensions.Logging.Generators
             /// <summary>
             /// Finds the template arguments contained in the message string.
             /// </summary>
-            private static void ExtractTemplates(string? message, IDictionary<string, string> templateMap, List<string> templateList)
+            /// <returns>A value indicating whether the extraction was successful.</returns>
+            private static bool ExtractTemplates(string? message, IDictionary<string, string> templateMap, List<string> templateList)
             {
                 if (string.IsNullOrEmpty(message))
                 {
-                    return;
+                    return true;
                 }
 
                 int scanIndex = 0;
-                int endIndex = message!.Length;
+                int endIndex = message.Length;
 
+                bool success = true;
                 while (scanIndex < endIndex)
                 {
                     int openBraceIndex = FindBraceIndex(message, '{', scanIndex, endIndex);
-                    int closeBraceIndex = FindBraceIndex(message, '}', openBraceIndex, endIndex);
 
-                    if (closeBraceIndex == endIndex)
+                    if (openBraceIndex == -2) // found '}' instead of '{'
                     {
-                        scanIndex = endIndex;
+                        success = false;
+                        break;
                     }
-                    else
+                    else if (openBraceIndex == -1) // scanned the string and didn't find any remaining '{' or '}'
+                    {
+                        break;
+                    }
+
+                    int closeBraceIndex = FindBraceIndex(message, '}', openBraceIndex + 1, endIndex);
+
+                    if (closeBraceIndex <= -1) // unclosed '{'
                     {
-                        // Format item syntax : { index[,alignment][ :formatString] }.
-                        int formatDelimiterIndex = FindIndexOfAny(message, _formatDelimiters, openBraceIndex, closeBraceIndex);
+                        success = false;
+                        break;
+                    }
+
+                    // Format item syntax : { index[,alignment][ :formatString] }.
+                    int formatDelimiterIndex = FindIndexOfAny(message, _formatDelimiters, openBraceIndex, closeBraceIndex);
+                    string templateName = message.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1);
 
-                        string templateName = message.Substring(openBraceIndex + 1, formatDelimiterIndex - openBraceIndex - 1);
-                        templateMap[templateName] = templateName;
-                        templateList.Add(templateName);
-                        scanIndex = closeBraceIndex + 1;
+                    if (string.IsNullOrWhiteSpace(templateName)) // braces with no named argument, such as {} and { }
+                    {
+                        success = false;
+                        break;
                     }
+
+                    templateMap[templateName] = templateName;
+                    templateList.Add(templateName);
+
+                    scanIndex = closeBraceIndex + 1;
                 }
+
+                return success;
             }
 
-            private static int FindBraceIndex(string message, char brace, int startIndex, int endIndex)
+            /// <summary>
+            /// Searches for the next brace index in the message.
+            /// </summary>
+            /// <remarks> The search skips any sequences of {{ or }}.</remarks>
+            /// <example>{{prefix{{{Argument}}}suffix}}</example>
+            /// <returns>The zero-based index position of the first occurrence of the searched brace; -1 if the searched brace was not found; -2 if the wrong brace was found.</returns>
+            private static int FindBraceIndex(string message, char searchedBrace, int startIndex, int endIndex)
             {
-                // Example: {{prefix{{{Argument}}}suffix}}.
-                int braceIndex = endIndex;
+                Debug.Assert(searchedBrace is '{' or '}');
+
+                int braceIndex = -1;
                 int scanIndex = startIndex;
-                int braceOccurrenceCount = 0;
 
                 while (scanIndex < endIndex)
                 {
-                    if (braceOccurrenceCount > 0 && message[scanIndex] != brace)
+                    char current = message[scanIndex];
+
+                    if (current is '{' or '}')
                     {
-                        if (braceOccurrenceCount % 2 == 0)
+                        char currentBrace = current;
+
+                        int scanIndexBeforeSkip = scanIndex;
+                        while (current == currentBrace && ++scanIndex < endIndex)
                         {
-                            // Even number of '{' or '}' found. Proceed search with next occurrence of '{' or '}'.
-                            braceOccurrenceCount = 0;
-                            braceIndex = endIndex;
+                            current = message[scanIndex];
                         }
-                        else
+
+                        int bracesCount = scanIndex - scanIndexBeforeSkip;
+                        if (bracesCount % 2 != 0) // if it is an even number of braces, just skip them, otherwise, we found an unescaped brace
                         {
-                            // An unescaped '{' or '}' found.
+                            if (currentBrace == searchedBrace)
+                            {
+                                if (currentBrace == '{')
+                                {
+                                    braceIndex = scanIndex - 1; // For '{' pick the last occurrence.
+                                }
+                                else
+                                {
+                                    braceIndex = scanIndexBeforeSkip; // For '}' pick the first occurrence.
+                                }
+                            }
+                            else
+                            {
+                                braceIndex = -2; // wrong brace found
+                            }
+
                             break;
                         }
                     }
-                    else if (message[scanIndex] == brace)
+                    else
                     {
-                        if (brace == '}')
-                        {
-                            if (braceOccurrenceCount == 0)
-                            {
-                                // For '}' pick the first occurrence.
-                                braceIndex = scanIndex;
-                            }
-                        }
-                        else
-                        {
-                            // For '{' pick the last occurrence.
-                            braceIndex = scanIndex;
-                        }
-
-                        braceOccurrenceCount++;
+                        scanIndex++;
                     }
-
-                    scanIndex++;
                 }
 
                 return braceIndex;
index 12f892d..529263f 100644 (file)
     <value>Can't have the same template with different casing</value>
   </data>
   <data name="MalformedFormatStringsMessage" xml:space="preserve">
-    <value>Can't have malformed format strings (like dangling {, etc)</value>
+    <value>Logging method '{0}' contains malformed format strings</value>
   </data>
   <data name="GeneratingForMax6ArgumentsMessage" xml:space="preserve">
     <value>Generating more than 6 arguments is not supported</value>
   <data name="ShouldntReuseEventNamesTitle" xml:space="preserve">
     <value>Multiple logging methods should not use the same event name within a class</value>
   </data>
-</root>
+  <data name="MalformedFormatStringsTitle" xml:space="preserve">
+    <value>Logging method contains malformed format strings</value>
+  </data>
+</root>
\ No newline at end of file
index 416fc1c..36c6ba3 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Nemůže mít chybně formátované řetězce (třeba neuzavřené závorky { atd.).</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index 5fdfb17..14ace40 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Nicht wohlgeformte Formatzeichenfolgen (beispielsweise mit überzähligen geschweiften Klammern) sind unzulässig.</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index 508a09d..b6c52c9 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">No puede tener cadenas con formato incorrecto (como { final, etc.)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index 58fa9ed..b0b2006 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Chaînes de format incorrect (par exemple { non fermée, etc.)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index dc9403d..9c8da0c 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Impossibile avere stringhe di formato non valido (ad esempio, { tralasciato e così via)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index c68bf6b..304d24f 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">(dangling {など) 誤った形式の文字列を持つことはできません</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index 0a9542f..46b823d 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">잘못된 형식의 문자열(예: 짝이 맞지 않는 중괄호({))은 사용할 수 없음</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index f74d191..e12d5fb 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Nie może zawierać źle sformułowanego formatu ciągów (takich jak zawieszonego znaku „{”, itp.)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index df317c9..5cf0dd3 100644 (file)
     <body>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
         <source>Argument '{0}' is not referenced from the logging message</source>
-        <target state="translated">O argumento '{0}' não é referenciado na mensagem de registro em log</target>
+        <target state="new">Argument '{0}' is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
         <source>Argument is not referenced from the logging message</source>
-        <target state="translated">O argumento não é referenciado na mensagem de registro em log</target>
+        <target state="new">Argument is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="GeneratingForMax6ArgumentsMessage">
         <source>Generating more than 6 arguments is not supported</source>
-        <target state="translated">A geração de mais de 6 argumentos não é suportada</target>
+        <target state="new">Generating more than 6 arguments is not supported</target>
         <note />
       </trans-unit>
       <trans-unit id="InconsistentTemplateCasingMessage">
         <source>Can't have the same template with different casing</source>
-        <target state="translated">Não é possível ter o mesmo modelo com diferenças entre maiúsculas e minúsculas.</target>
+        <target state="new">Can't have the same template with different casing</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodNameMessage">
         <source>Logging method names cannot start with _</source>
-        <target state="translated">Os nomes dos métodos de registro em log não podem começar com _</target>
+        <target state="new">Logging method names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterNameMessage">
         <source>Logging method parameter names cannot start with _</source>
-        <target state="translated">Os nomes dos parâmetros do método de registro em log não podem começar com _</target>
+        <target state="new">Logging method parameter names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterOutMessage">
         <source>Argument '{0}' is using the unsupported out parameter modifier</source>
-        <target state="translated">O argumento '{0}' está usando o modificador de parâmetro out sem suporte</target>
+        <target state="new">Argument '{0}' is using the unsupported out parameter modifier</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterOutTitle">
         <source>Argument is using the unsupported out parameter modifier</source>
-        <target state="translated">O argumento está usando o modificador de parâmetro out sem suporte</target>
+        <target state="new">Argument is using the unsupported out parameter modifier</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodHasBodyMessage">
         <source>Logging methods cannot have a body</source>
-        <target state="translated">Os métodos de registro em log não podem ter um corpo</target>
+        <target state="new">Logging methods cannot have a body</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodIsGenericMessage">
         <source>Logging methods cannot be generic</source>
-        <target state="translated">Os métodos de registro em log não podem ser genéricos</target>
+        <target state="new">Logging methods cannot be generic</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustBePartialMessage">
         <source>Logging methods must be partial</source>
-        <target state="translated">Os métodos de registro em log devem ser parciais</target>
+        <target state="new">Logging methods must be partial</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustReturnVoidMessage">
         <source>Logging methods must return void</source>
-        <target state="translated">Os métodos de registro em log devem retornar nulos</target>
+        <target state="new">Logging methods must return void</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodShouldBeStaticMessage">
         <source>Logging methods must be static</source>
-        <target state="translated">Os métodos de registro em log devem ser estáticos</target>
+        <target state="new">Logging methods must be static</target>
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Não pode ter cadeia de caracteres de formato malformadas (como final {, etc)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
         <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
-        <target state="translated">Um valor LogLevel deve ser fornecido no atributo LoggerMessage ou como um parâmetro para o método de registro em log</target>
+        <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentMessage">
         <source>One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">Um dos argumentos para um método de log estático '{0}' deve implementar a interface Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentTitle">
         <source>One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">Um dos argumentos para um método de log estático deve implementar a interface Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldMessage">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">Não foi possível encontrar um campo do tipo Microsoft.Extensions.Logging.ILogger na classe {0}</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldTitle">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">Não foi possível encontrar um campo do tipo Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingRequiredTypeMessage">
         <source>Could not find definition for type {0}</source>
-        <target state="translated">Não foi possível encontrar a definição para o tipo {0}</target>
+        <target state="new">Could not find definition for type {0}</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingRequiredTypeTitle">
         <source>Could not find a required type definition</source>
-        <target state="translated">Não foi possível encontrar uma definição de tipo necessária</target>
+        <target state="new">Could not find a required type definition</target>
         <note />
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsMessage">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">Múltiplos campos do tipo Microsoft.Extensions.Logging.ILogger encontrados na classe {0}</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsTitle">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">Múltiplos campos encontrados do tipo Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageMessage">
         <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
-        <target state="translated">Remova o qualificador redundante (Info:, Aviso:, Erro:, etc) da mensagem de log, pois está implícito no nível de log especificado.</target>
+        <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
         <note />
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageTitle">
         <source>Redundant qualifier in logging message</source>
-        <target state="translated">Qualificador redundante na mensagem de registro de log</target>
+        <target state="new">Redundant qualifier in logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionExceptionInMessageTitle">
         <source>Don't include exception parameters as templates in the logging message</source>
-        <target state="translated">Não inclua parâmetros de exceção como modelos na mensagem de registro em log</target>
+        <target state="new">Don't include exception parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionInTemplateMessage">
         <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
-        <target state="translated">Não inclua um modelo para {0} na mensagem de registro em log, pois isso é implicitamente atendido</target>
+        <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
         <source>Don't include log level parameters as templates in the logging message</source>
-        <target state="translated">Não inclua parâmetros de nível de registro como modelos na mensagem de registro de log</target>
+        <target state="new">Don't include log level parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLoggerInMessageTitle">
         <source>Don't include logger parameters as templates in the logging message</source>
-        <target state="translated">Não inclua parâmetros de agente como modelos na mensagem de registro em log</target>
+        <target state="new">Don't include logger parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsMessage">
         <source>Multiple logging methods are using event id {0} in class {1}</source>
-        <target state="translated">Múltiplos métodos de registro em log estão usando a id de evento {0} na classe {1}</target>
+        <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsTitle">
         <source>Multiple logging methods cannot use the same event id within a class</source>
-        <target state="translated">Múltiplos métodos de registro em log não podem usar o mesmo id de evento dentro de uma classe</target>
+        <target state="new">Multiple logging methods cannot use the same event id within a class</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventNamesMessage">
         <source>Multiple logging methods are using event name {0} in class {1}</source>
-        <target state="translated">Múltiplos métodos de registro em log estão usando o nome de evento {0} na classe {1}</target>
+        <target state="new">Multiple logging methods are using event name {0} in class {1}</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventNamesTitle">
         <source>Multiple logging methods should not use the same event name within a class</source>
-        <target state="translated">Múltiplos métodos de registro em log não devem usar o mesmo nome de evento dentro de uma classe</target>
+        <target state="new">Multiple logging methods should not use the same event name within a class</target>
         <note />
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
         <source>Template '{0}' is not provided as argument to the logging method</source>
-        <target state="translated">O modelo '{0}' não é fornecido como argumento para o método de registro</target>
+        <target state="new">Template '{0}' is not provided as argument to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
         <source>Logging template has no corresponding method argument</source>
-        <target state="translated">O modelo de registro em log não tem nenhum argumento de método correspondente</target>
+        <target state="new">Logging template has no corresponding method argument</target>
         <note />
       </trans-unit>
     </body>
index b4c4c4a..7b0c9be 100644 (file)
     <body>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
         <source>Argument '{0}' is not referenced from the logging message</source>
-        <target state="translated">В сообщении ведения журнала нет ссылки на аргумент "{0}"</target>
+        <target state="new">Argument '{0}' is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
         <source>Argument is not referenced from the logging message</source>
-        <target state="translated">В сообщении ведения журнала нет ссылки на аргумент</target>
+        <target state="new">Argument is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="GeneratingForMax6ArgumentsMessage">
         <source>Generating more than 6 arguments is not supported</source>
-        <target state="translated">Формирование более 6 аргументов не поддерживается</target>
+        <target state="new">Generating more than 6 arguments is not supported</target>
         <note />
       </trans-unit>
       <trans-unit id="InconsistentTemplateCasingMessage">
         <source>Can't have the same template with different casing</source>
-        <target state="translated">Невозможно использовать шаблон с таким же именем в другом регистре</target>
+        <target state="new">Can't have the same template with different casing</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodNameMessage">
         <source>Logging method names cannot start with _</source>
-        <target state="translated">Имена методов ведения журнала не могут начинаться с символа "_"</target>
+        <target state="new">Logging method names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterNameMessage">
         <source>Logging method parameter names cannot start with _</source>
-        <target state="translated">Имена параметров метода ведения журнала не могут начинаться с символа "_"</target>
+        <target state="new">Logging method parameter names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterOutMessage">
         <source>Argument '{0}' is using the unsupported out parameter modifier</source>
-        <target state="translated">Аргумент "{0}" использует неподдерживаемый модификатор выходного параметра</target>
+        <target state="new">Argument '{0}' is using the unsupported out parameter modifier</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterOutTitle">
         <source>Argument is using the unsupported out parameter modifier</source>
-        <target state="translated">Аргумент использует неподдерживаемый модификатор выходного параметра</target>
+        <target state="new">Argument is using the unsupported out parameter modifier</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodHasBodyMessage">
         <source>Logging methods cannot have a body</source>
-        <target state="translated">У методов ведения журнала не может быть текста</target>
+        <target state="new">Logging methods cannot have a body</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodIsGenericMessage">
         <source>Logging methods cannot be generic</source>
-        <target state="translated">Методы ведения журнала не могут быть универсальными</target>
+        <target state="new">Logging methods cannot be generic</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustBePartialMessage">
         <source>Logging methods must be partial</source>
-        <target state="translated">Методы ведения журнала должны быть частичными</target>
+        <target state="new">Logging methods must be partial</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustReturnVoidMessage">
         <source>Logging methods must return void</source>
-        <target state="translated">Методы ведения журнала должны возвращать значение void</target>
+        <target state="new">Logging methods must return void</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodShouldBeStaticMessage">
         <source>Logging methods must be static</source>
-        <target state="translated">Методы ведения журнала должны быть статическими</target>
+        <target state="new">Logging methods must be static</target>
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Для строк формата не допускается неправильный формат (висячие символы "{" и т. п.)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
         <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
-        <target state="translated">Значение LogLevel должно быть указано в атрибуте LoggerMessage или в качестве параметра метода ведения журнала</target>
+        <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentMessage">
         <source>One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">Один из аргументов статического метода ведения журнала "{0}" должен реализовывать интерфейс Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentTitle">
         <source>One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">Один из аргументов статического метода ведения журнала должен реализовывать интерфейс Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldMessage">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">В классе {0} не найдены поля типа Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldTitle">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">Не удалось найти поле типа Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingRequiredTypeMessage">
         <source>Could not find definition for type {0}</source>
-        <target state="translated">Не найдено определение для типа {0}</target>
+        <target state="new">Could not find definition for type {0}</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingRequiredTypeTitle">
         <source>Could not find a required type definition</source>
-        <target state="translated">Не найдено требуемое определение типа</target>
+        <target state="new">Could not find a required type definition</target>
         <note />
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsMessage">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">В классе {0} обнаружено несколько полей типа Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsTitle">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">Обнаружено несколько полей типа Microsoft.Extensions.Logging.ILogger</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageMessage">
         <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
-        <target state="translated">Удалите избыточный квалификатор (Info:, Warning:, Error:, и т. п.) из сообщения журнала, поскольку квалификатор подразумевается на указанном уровне ведения журнала.</target>
+        <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
         <note />
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageTitle">
         <source>Redundant qualifier in logging message</source>
-        <target state="translated">Избыточный квалификатор в сообщении журнала</target>
+        <target state="new">Redundant qualifier in logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionExceptionInMessageTitle">
         <source>Don't include exception parameters as templates in the logging message</source>
-        <target state="translated">Не включайте параметры исключений в качестве шаблонов в сообщение ведения журнала</target>
+        <target state="new">Don't include exception parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionInTemplateMessage">
         <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
-        <target state="translated">Не включайте шаблон для {0} в сообщение ведения журнала, поскольку он используется неявным образом</target>
+        <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
         <source>Don't include log level parameters as templates in the logging message</source>
-        <target state="translated">Не включайте параметры уровня журнала в качестве шаблонов в сообщение ведения журнала</target>
+        <target state="new">Don't include log level parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLoggerInMessageTitle">
         <source>Don't include logger parameters as templates in the logging message</source>
-        <target state="translated">Не включайте параметры средства ведения журнала в качестве шаблонов в сообщение ведения журнала</target>
+        <target state="new">Don't include logger parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsMessage">
         <source>Multiple logging methods are using event id {0} in class {1}</source>
-        <target state="translated">Несколько методов ведения журнала используют идентификатор события {0} в классе {1}</target>
+        <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsTitle">
         <source>Multiple logging methods cannot use the same event id within a class</source>
-        <target state="translated">Несколько методов ведения журнала не могут использовать одинаковый ИД события в пределах класса</target>
+        <target state="new">Multiple logging methods cannot use the same event id within a class</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventNamesMessage">
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
         <source>Template '{0}' is not provided as argument to the logging method</source>
-        <target state="translated">Шаблон "{0}" не указан в качестве аргумента для метода ведения журнала</target>
+        <target state="new">Template '{0}' is not provided as argument to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
         <source>Logging template has no corresponding method argument</source>
-        <target state="translated">У шаблона журнала нет соответствующего аргумента метода</target>
+        <target state="new">Logging template has no corresponding method argument</target>
         <note />
       </trans-unit>
     </body>
index 0e8b2fb..b7b86da 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">Hatalı biçimlendirilmiş biçim dizeleri (aykırı { vb. gibi) içeremez</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index da8b1b4..28f6073 100644 (file)
@@ -4,32 +4,32 @@
     <body>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateMessage">
         <source>Argument '{0}' is not referenced from the logging message</source>
-        <target state="translated">未从日志记录消息中引用参数“{0}”</target>
+        <target state="new">Argument '{0}' is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ArgumentHasNoCorrespondingTemplateTitle">
         <source>Argument is not referenced from the logging message</source>
-        <target state="translated">未从日志记录消息中引用参数</target>
+        <target state="new">Argument is not referenced from the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="GeneratingForMax6ArgumentsMessage">
         <source>Generating more than 6 arguments is not supported</source>
-        <target state="translated">不支持生成 6 个以上的参数</target>
+        <target state="new">Generating more than 6 arguments is not supported</target>
         <note />
       </trans-unit>
       <trans-unit id="InconsistentTemplateCasingMessage">
         <source>Can't have the same template with different casing</source>
-        <target state="translated">不能有大小写不同的相同模板</target>
+        <target state="new">Can't have the same template with different casing</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodNameMessage">
         <source>Logging method names cannot start with _</source>
-        <target state="translated">日志记录方法名称不能以 _ 开头</target>
+        <target state="new">Logging method names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterNameMessage">
         <source>Logging method parameter names cannot start with _</source>
-        <target state="translated">日志记录方法参数名称不能以 _ 开头</target>
+        <target state="new">Logging method parameter names cannot start with _</target>
         <note />
       </trans-unit>
       <trans-unit id="InvalidLoggingMethodParameterOutMessage">
       </trans-unit>
       <trans-unit id="LoggingMethodHasBodyMessage">
         <source>Logging methods cannot have a body</source>
-        <target state="translated">日志记录方法不能有正文</target>
+        <target state="new">Logging methods cannot have a body</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodIsGenericMessage">
         <source>Logging methods cannot be generic</source>
-        <target state="translated">日志记录方法不能为泛型方法</target>
+        <target state="new">Logging methods cannot be generic</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustBePartialMessage">
         <source>Logging methods must be partial</source>
-        <target state="translated">日志记录方法必须为分部方法</target>
+        <target state="new">Logging methods must be partial</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodMustReturnVoidMessage">
         <source>Logging methods must return void</source>
-        <target state="translated">日志记录方法必须返回 void</target>
+        <target state="new">Logging methods must return void</target>
         <note />
       </trans-unit>
       <trans-unit id="LoggingMethodShouldBeStaticMessage">
         <source>Logging methods must be static</source>
-        <target state="translated">日志记录方法必须为静态方法</target>
+        <target state="new">Logging methods must be static</target>
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">不能有格式错误的格式字符串(例如悬空 { 等)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
         <source>A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</source>
-        <target state="translated">必须在 LoggerMessage 属性中提供 LogLevel 值或将其用作日志记录方法的参数</target>
+        <target state="new">A LogLevel value must be supplied in the LoggerMessage attribute or as a parameter to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentMessage">
         <source>One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">静态日志记录方法“{0}”的参数之一必须实施 Microsoft.Extensions.Logging.ILogger 接口</target>
+        <target state="new">One of the arguments to the static logging method '{0}' must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerArgumentTitle">
         <source>One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</source>
-        <target state="translated">静态日志记录方法的参数之一必须实现 Microsoft.Extensions.Logging.ILogger 接口</target>
+        <target state="new">One of the arguments to a static logging method must implement the Microsoft.Extensions.Logging.ILogger interface</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldMessage">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">在类 {0} 中找不到 Microsoft.Extensions.Logging.ILogger 类型的字段</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingLoggerFieldTitle">
         <source>Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">找不到 Microsoft.Extensions.Logging.ILogger 类型的字段。</target>
+        <target state="new">Couldn't find a field of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MissingRequiredTypeMessage">
         <source>Could not find definition for type {0}</source>
-        <target state="translated">找不到类型 {0} 的定义</target>
+        <target state="new">Could not find definition for type {0}</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingRequiredTypeTitle">
         <source>Could not find a required type definition</source>
-        <target state="translated">找不到所需的类型定义</target>
+        <target state="new">Could not find a required type definition</target>
         <note />
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsMessage">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</source>
-        <target state="translated">在类 {0} 中找到多个 Microsoft.Extensions.Logging.ILogger 类型的字段</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger in class {0}</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="MultipleLoggerFieldsTitle">
         <source>Found multiple fields of type Microsoft.Extensions.Logging.ILogger</source>
-        <target state="translated">找到 Microsoft.Extensions.Logging.ILogger 类型的多个字段</target>
+        <target state="new">Found multiple fields of type Microsoft.Extensions.Logging.ILogger</target>
         <note>{Locked="Microsoft.Extensions.Logging.ILogger"}</note>
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageMessage">
         <source>Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</source>
-        <target state="translated">从日志记录消息中删除冗余限定符(信息:、警告:、错误: 等),因为其在指定的日志级别中为隐式内容。</target>
+        <target state="new">Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level.</target>
         <note />
       </trans-unit>
       <trans-unit id="RedundantQualifierInMessageTitle">
         <source>Redundant qualifier in logging message</source>
-        <target state="translated">日志消息消息中的冗余限定符</target>
+        <target state="new">Redundant qualifier in logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionExceptionInMessageTitle">
         <source>Don't include exception parameters as templates in the logging message</source>
-        <target state="translated">不要将异常参数作为模板包含在日志记录消息中</target>
+        <target state="new">Don't include exception parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionInTemplateMessage">
         <source>Don't include a template for {0} in the logging message since it is implicitly taken care of</source>
-        <target state="translated">不要将 {0} 的模板包含在日志记录消息中,因为其被隐式处理</target>
+        <target state="new">Don't include a template for {0} in the logging message since it is implicitly taken care of</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLogLevelInMessageTitle">
         <source>Don't include log level parameters as templates in the logging message</source>
-        <target state="translated">不要将日志级别参数作为模板包含在日志记录消息中</target>
+        <target state="new">Don't include log level parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntMentionLoggerInMessageTitle">
         <source>Don't include logger parameters as templates in the logging message</source>
-        <target state="translated">不要将记录器参数作为模板包含在日志记录消息中</target>
+        <target state="new">Don't include logger parameters as templates in the logging message</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsMessage">
         <source>Multiple logging methods are using event id {0} in class {1}</source>
-        <target state="translated">多个日志记录方法正在类 {1} 中使用事件 ID {0}</target>
+        <target state="new">Multiple logging methods are using event id {0} in class {1}</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventIdsTitle">
         <source>Multiple logging methods cannot use the same event id within a class</source>
-        <target state="translated">多个日志记录方法不能在类中使用相同的事件 ID</target>
+        <target state="new">Multiple logging methods cannot use the same event id within a class</target>
         <note />
       </trans-unit>
       <trans-unit id="ShouldntReuseEventNamesMessage">
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentMessage">
         <source>Template '{0}' is not provided as argument to the logging method</source>
-        <target state="translated">未将模板“{0}”作为参数提供给日志记录方法</target>
+        <target state="new">Template '{0}' is not provided as argument to the logging method</target>
         <note />
       </trans-unit>
       <trans-unit id="TemplateHasNoCorrespondingArgumentTitle">
         <source>Logging template has no corresponding method argument</source>
-        <target state="translated">日志记录模板无相应的方法参数</target>
+        <target state="new">Logging template has no corresponding method argument</target>
         <note />
       </trans-unit>
     </body>
index c3dbe28..96b8c2d 100644 (file)
         <note />
       </trans-unit>
       <trans-unit id="MalformedFormatStringsMessage">
-        <source>Can't have malformed format strings (like dangling {, etc)</source>
-        <target state="translated">不能有格式錯誤的格式字串 (例如懸空 {, 等等)</target>
+        <source>Logging method '{0}' contains malformed format strings</source>
+        <target state="new">Logging method '{0}' contains malformed format strings</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="MalformedFormatStringsTitle">
+        <source>Logging method contains malformed format strings</source>
+        <target state="new">Logging method contains malformed format strings</target>
         <note />
       </trans-unit>
       <trans-unit id="MissingLogLevelMessage">
index 564444c..9d80c88 100644 (file)
@@ -325,40 +325,6 @@ namespace Microsoft.Extensions.Logging.Generators.Tests
             Assert.Empty(diagnostics);
         }
 
-#if false
-        // TODO: can't have the same template with different casing
-        [Fact]
-        public async Task InconsistentTemplateCasing()
-        {
-            IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
-                partial class C
-                {
-                    [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {p1} {P1}"")]
-                    static partial void M1(ILogger logger, int p1, int P1);
-                }
-            ");
-
-            Assert.Single(diagnostics);
-            Assert.Equal(DiagnosticDescriptors.InconsistentTemplateCasing.Id, diagnostics[0].Id);
-        }
-
-        // TODO: can't have malformed format strings (like dangling {, etc)
-        [Fact]
-        public async Task MalformedFormatString()
-        {
-            IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
-                partial class C
-                {
-                    [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {p1} {P1}"")]
-                    static partial void M1(ILogger logger, int p1, int P1);
-                }
-            ");
-
-            Assert.Single(diagnostics);
-            Assert.Equal(DiagnosticDescriptors.MalformedFormatStrings.Id, diagnostics[0].Id);
-        }
-#endif
-
         [Fact]
         public async Task InvalidParameterName()
         {
@@ -699,16 +665,16 @@ namespace Microsoft.Extensions.Logging.Generators.Tests
         }
 
         [Fact]
-        public async Task Templates()
+        public async Task MalformedFormatString()
         {
             IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
                 partial class C
                 {
-                    [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1"")]
+                    [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1 {A} M1 { M1"")]
                     static partial void M1(ILogger logger);
 
-                    [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2 {arg1} {arg2}"")]
-                    static partial void M2(ILogger logger, string arg1, string arg2);
+                    [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2 {A} M2 } M2"")]
+                    static partial void M2(ILogger logger);
 
                     [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = ""M3 {arg1"")]
                     static partial void M3(ILogger logger);
@@ -722,8 +688,65 @@ namespace Microsoft.Extensions.Logging.Generators.Tests
                     [LoggerMessage(EventId = 6, Level = LogLevel.Debug, Message = ""}M6 "")]
                     static partial void M6(ILogger logger);
 
-                    [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""M7 {{arg1}}"")]
+                    [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""{M7{"")]
+                    static partial void M7(ILogger logger);
+
+                    [LoggerMessage(EventId = 8, Level = LogLevel.Debug, Message = ""{{{arg1 M8"")]
+                    static partial void M8(ILogger logger);
+
+                    [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = ""arg1}}} M9"")]
+                    static partial void M9(ILogger logger);
+
+                    [LoggerMessage(EventId = 10, Level = LogLevel.Debug, Message = ""{} M10"")]
+                    static partial void M10(ILogger logger);
+
+                    [LoggerMessage(EventId = 11, Level = LogLevel.Debug, Message = ""{ } M11"")]
+                    static partial void M11(ILogger logger);
+                }
+            ");
+
+            Assert.Equal(11, diagnostics.Count);
+            foreach (var diagnostic in diagnostics)
+            {
+                Assert.Equal(DiagnosticDescriptors.MalformedFormatStrings.Id, diagnostic.Id);
+            }
+        }
+
+        [Fact]
+        public async Task ValidTemplates()
+        {
+            IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+                partial class C
+                {
+                    [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = """")]
+                    static partial void M1(ILogger logger);
+
+                    [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2"")]
+                    static partial void M2(ILogger logger);
+
+                    [LoggerMessage(EventId = 3, Level = LogLevel.Debug, Message = ""{arg1}"")]
+                    static partial void M3(ILogger logger, int arg1);
+
+                    [LoggerMessage(EventId = 4, Level = LogLevel.Debug, Message = ""M4 {arg1}"")]
+                    static partial void M4(ILogger logger, int arg1);
+
+                    [LoggerMessage(EventId = 5, Level = LogLevel.Debug, Message = ""{arg1} M5"")]
+                    static partial void M5(ILogger logger, int arg1);
+
+                    [LoggerMessage(EventId = 6, Level = LogLevel.Debug, Message = ""M6{arg1}M6{arg2}M6"")]
+                    static partial void M6(ILogger logger, string arg1, string arg2);
+
+                    [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = ""M7 {{const}}"")]
                     static partial void M7(ILogger logger);
+
+                    [LoggerMessage(EventId = 8, Level = LogLevel.Debug, Message = ""{{prefix{{{arg1}}}suffix}}"")]
+                    static partial void M8(ILogger logger, string arg1);
+
+                    [LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = ""prefix }}"")]
+                    static partial void M9(ILogger logger);
+
+                    [LoggerMessage(EventId = 10, Level = LogLevel.Debug, Message = ""}}suffix"")]
+                    static partial void M10(ILogger logger);
                 }
             ");