private bool CheckHeader(IPOEntry entry) { if (entry == null || entry.Key.Id != string.Empty) { return(false); } if (!(entry is POSingularEntry)) { AddError(DiagnosticCodes.HeaderNotSingular); return(false); } if (entry.Key.PluralId != null || entry.Key.ContextId != null) { AddWarning(DiagnosticCodes.InvalidHeaderEntryKey); } if (entry.Comments != null && entry.Comments.Any(c => c.Kind == POCommentKind.PreviousValue || c.Kind == POCommentKind.Reference)) { AddWarning(DiagnosticCodes.InvalidHeaderComment); } return(true); }
private void WriteEntry(IPOEntry entry) { if (!HasFlags(Flags.SkipComments) && entry.Comments != null) { WriteComments(entry.Comments); } if (entry.Key.ContextId != null) { ResetBuilder(); _builder.Append(POCatalog.ContextIdToken); _builder.Append(' '); AppendPOString(entry.Key.ContextId); _writer.WriteLine(_builder); } ResetBuilder(); _builder.Append(POCatalog.IdToken); _builder.Append(' '); AppendPOString(entry.Key.Id); _writer.WriteLine(_builder); if (entry.Key.PluralId != null) { ResetBuilder(); _builder.Append(POCatalog.PluralIdToken); _builder.Append(' '); AppendPOString(entry.Key.PluralId); _writer.WriteLine(_builder); } switch (entry) { case POSingularEntry singularEntry: ResetBuilder(); _builder.Append(POCatalog.TranslationToken); _builder.Append(' '); AppendPOString(singularEntry.Translation); _writer.WriteLine(_builder); break; case POPluralEntry pluralEntry: var n = pluralEntry.Count; for (var i = 0; i < n; i++) { ResetBuilder(); _builder.Append(POCatalog.TranslationToken); _builder.Append('['); _builder.Append(i); _builder.Append(']'); _builder.Append(' '); AppendPOString(pluralEntry[i]); _writer.WriteLine(_builder); } break; default: throw new InvalidOperationException(); } }
static void EnsureTranslationCount(IPOEntry entry, int pluralFormCount) { if (entry is POPluralEntry pluralEntry && pluralEntry.Count > pluralFormCount) { for (int i = pluralEntry.Count - 1; i >= pluralFormCount; i--) { pluralEntry.RemoveAt(i); } } }
public void Generate(TextWriter writer, POCatalog catalog) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (catalog == null) { throw new ArgumentNullException(nameof(catalog)); } if (!HasFlags(Flags.IgnoreEncoding)) { if (writer.Encoding.GetByteCount(" ") > 1) { throw new ArgumentException(Resources.EncodingNotSingleByte, nameof(writer)); } if (catalog.Encoding == null || Encoding.GetEncoding(catalog.Encoding).WebName != writer.Encoding.WebName) { throw new ArgumentException(Resources.EncodingMismatch, nameof(writer)); } } _writer = writer; _catalog = catalog; _stringBreak = "\"" + _writer.NewLine + "\""; _lineStartIndex = 0; try { IPOEntry entry = CreateHeaderEntry(); if (entry != null) { WriteEntry(entry); } var n = catalog.Count; for (var i = 0; i < n; i++) { _writer.WriteLine(); WriteEntry(catalog[i]); } } finally { _builder.Clear(); if (_builder.Capacity > 1024) { _builder.Capacity = 1024; } } }
private static POCatalog BuildCatalog(string filePath, POCatalog templateCatalog) { POCatalog?originalCatalog; if (File.Exists(filePath)) { using (var reader = new StreamReader(filePath)) { var parseResult = new POParser().Parse(reader); if (!parseResult.Success) { var diagnosticMessages = parseResult.Diagnostics .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error); throw new CommandException($"Template file \"{filePath}\" is invalid: {string.Join(Environment.NewLine, diagnosticMessages)}"); } originalCatalog = parseResult.Catalog; } } else { originalCatalog = null; } var catalog = new POCatalog(); foreach (var templateEntry in templateCatalog) { var flags = new HashSet <string>(GetPOEntryFlags(templateEntry)); if (flags.Contains("removed")) { continue; } IEnumerable <string> originalFlags; if (originalCatalog != null && originalCatalog.TryGetValue(templateEntry.Key, out var originalEntry)) { originalFlags = GetPOEntryFlags(originalEntry); } else { (originalFlags, originalEntry) = (Enumerable.Empty <string>(), null); } var isNew = flags.Remove("new"); var hasChanged = flags.Remove("changed"); var isOriginalFuzzy = originalFlags.Contains("fuzzy"); IPOEntry entry = (hasChanged ? templateEntry : (originalEntry ?? templateEntry)) switch { POSingularEntry singularEntry => new POSingularEntry(templateEntry.Key) { Translation = singularEntry.Translation }, POPluralEntry pluralEntry => new POPluralEntry(templateEntry.Key, pluralEntry), _ => throw new InvalidOperationException() }; if (isNew || hasChanged || isOriginalFuzzy) { flags.Add("fuzzy"); entry.Comments = templateEntry.Comments?.Where(comment => !(comment is POFlagsComment)).ToList() ?? new List <POComment>(); entry.Comments.Add(new POFlagsComment { Flags = flags }); } else { entry.Comments = templateEntry.Comments; } catalog.Add(entry); } return(catalog); }
private static IEnumerable <string> GetPOEntryFlags(IPOEntry entry) => entry.Comments? .OfType <POFlagsComment>() .Where(flagsComment => flagsComment.Flags != null && flagsComment.Flags.Count > 0) .SelectMany(flagsComment => flagsComment.Flags) ?? Enumerable.Empty <string>();
private bool TryReadEntry(bool allowEmptyId, out IPOEntry result) { if (_line == null) { result = null; return(false); } var entryLocation = new TextLocation(_lineIndex, _columnIndex); List <POComment> comments = _commentBuffer != null?ParseComments() : null; Dictionary <int, string> translations = null; string id = null, pluralId = null, contextId = null; IPOEntry entry = null; EntryTokens expectedTokens = EntryTokens.Id | EntryTokens.PluralId | EntryTokens.ContextId; do { EntryTokens token = DetectEntryToken(out int tokenLength) & expectedTokens; if (token == EntryTokens.None) { if (!(expectedTokens == EntryTokens.Translation && entry is POPluralEntry)) { AddError(DiagnosticCodes.UnexpectedToken, new TextLocation(_lineIndex, _columnIndex)); result = null; return(false); } else { break; } } _columnIndex += tokenLength; switch (token) { case EntryTokens.Id: _columnIndex = FindNextTokenInLine(requireWhiteSpace: true); if (_columnIndex < 0 || !TryReadString(out id)) { result = null; return(false); } expectedTokens &= ~EntryTokens.Id; expectedTokens |= EntryTokens.Translation; break; case EntryTokens.PluralId: _columnIndex = FindNextTokenInLine(requireWhiteSpace: true); if (_columnIndex < 0 || !TryReadString(out pluralId)) { result = null; return(false); } expectedTokens &= ~EntryTokens.PluralId; break; case EntryTokens.ContextId: _columnIndex = FindNextTokenInLine(requireWhiteSpace: true); if (_columnIndex < 0 || !TryReadString(out contextId)) { result = null; return(false); } expectedTokens &= ~EntryTokens.ContextId; break; case EntryTokens.Translation: var originalColumnIndex = _columnIndex; TryReadPluralIndex(out int?pluralIndex); _columnIndex = FindNextTokenInLine(requireWhiteSpace: true); if (_columnIndex < 0 || !TryReadString(out string value)) { result = null; return(false); } if (!allowEmptyId && entry == null && id == string.Empty) { AddError(Resources.InvalidEntryKey, entryLocation); result = null; return(false); } // plural if (pluralId != null) { if (pluralIndex != null) { if (pluralIndex < 0 || pluralIndex >= _catalog.PluralFormCount) { AddWarning(DiagnosticCodes.InvalidPluralIndex, new TextLocation(_lineIndex, originalColumnIndex)); break; } } else { AddWarning(DiagnosticCodes.MissingPluralIndex, new TextLocation(_lineIndex, originalColumnIndex)); pluralIndex = 0; } if (entry == null) { entry = new POPluralEntry(new POKey(id, pluralId, contextId)) { Comments = comments, }; translations = new Dictionary <int, string>(); } if (translations.ContainsKey(pluralIndex.Value)) { AddWarning(DiagnosticCodes.DuplicatePluralForm, entryLocation, pluralIndex.Value); } translations[pluralIndex.Value] = value; expectedTokens = EntryTokens.Translation; } // singular else { if (pluralIndex != null) { if (pluralIndex != 0) { AddError(DiagnosticCodes.InvalidPluralIndex, new TextLocation(_lineIndex, originalColumnIndex)); break; } else { AddWarning(DiagnosticCodes.UnnecessaryPluralIndex, new TextLocation(_lineIndex, originalColumnIndex)); } } entry = new POSingularEntry(new POKey(id, null, contextId)) { Comments = comments, Translation = value }; expectedTokens = EntryTokens.None; } break; } SeekNextToken(); }while (_line != null && expectedTokens != EntryTokens.None); if (entry is POPluralEntry pluralEntry) { var n = _catalog.PluralFormCount; for (var i = 0; i < n; i++) { if (translations.TryGetValue(i, out string value)) { pluralEntry.Add(value); } else { pluralEntry.Add(null); AddWarning(DiagnosticCodes.MissingPluralForm, entryLocation, i); } } } if (entry == null) { AddError(DiagnosticCodes.IncompleteEntry, entryLocation); result = null; return(false); } result = entry; return(true); }
public void ParseWithStringDecodingOptions() { CheckCatalog(new POStringDecodingOptions { }, Environment.NewLine, Environment.NewLine); CheckCatalog(new POStringDecodingOptions { KeepKeyStringsPlatformIndependent = true }, "\n", Environment.NewLine); CheckCatalog(new POStringDecodingOptions { KeepTranslationStringsPlatformIndependent = true }, Environment.NewLine, "\n"); CheckCatalog(new POStringDecodingOptions { KeepKeyStringsPlatformIndependent = true, KeepTranslationStringsPlatformIndependent = true }, "\n", "\n"); void CheckCatalog(POStringDecodingOptions options, string expectedKeyStringNewLine, string expectedTranslationStringNewLine) { var parserSettings = new POParserSettings { StringDecodingOptions = options }; var parser = new POParser(parserSettings); POParseResult result = parser.Parse(new MemoryStream(Resources.NewLineTestPO)); Assert.True(result.Success); POCatalog catalog = result.Catalog; Assert.Equal(4, catalog.Headers.Count); Assert.Equal("en_US", catalog.Headers["Language"]); Assert.Equal(1, catalog.Count); Assert.Equal( new POKey($"Id of{expectedKeyStringNewLine}a long text", $"Plural id of{expectedKeyStringNewLine}a long text", $"Context id of{expectedKeyStringNewLine}a long text"), catalog[0].Key); IPOEntry entry = catalog[0]; Assert.Equal(2, entry.Count); Assert.Equal($"Singular translation of{expectedTranslationStringNewLine}a long text", entry[0]); Assert.Equal($"Plural translation of{expectedTranslationStringNewLine}a long text", entry[1]); IList <POComment> comments = catalog[0].Comments; Assert.Equal(3, comments?.Count ?? 0); POComment comment = comments[0]; Assert.Equal(POCommentKind.PreviousValue, comment.Kind); Assert.Equal(POIdKind.ContextId, ((POPreviousValueComment)comment).IdKind); Assert.Equal($"Previous context id of{expectedKeyStringNewLine}a long text", ((POPreviousValueComment)comment).Value); comment = comments[1]; Assert.Equal(POCommentKind.PreviousValue, comment.Kind); Assert.Equal(POIdKind.Id, ((POPreviousValueComment)comment).IdKind); Assert.Equal($"Previous id of{expectedKeyStringNewLine}a long text", ((POPreviousValueComment)comment).Value); comment = comments[2]; Assert.Equal(POCommentKind.PreviousValue, comment.Kind); Assert.Equal(POIdKind.PluralId, ((POPreviousValueComment)comment).IdKind); Assert.Equal($"Previous plural id of{expectedKeyStringNewLine}a long text", ((POPreviousValueComment)comment).Value); } }