Exemple #1
0
        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);
        }
Exemple #2
0
        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);
         }
     }
 }
Exemple #4
0
        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>();
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
            }
        }