private void ExtractComments(POKey key, POSingularEntry entry) { foreach (var comment in entry.Comments) { if (!(comment is POTranslatorComment translatorComment)) { continue; } var commentText = translatorComment.Text; if (string.IsNullOrEmpty(commentText)) { continue; } commentText = commentText.Replace(PartialMatchComment, "").Trim(new char[] { ';', ' ' }); if (string.IsNullOrEmpty(commentText)) { continue; } if (Comments.ContainsKey(key.Id)) { Debug.WriteLine($"Duplicate translator comment: '{commentText}'"); continue; } Comments[key.Id] = commentText; } }
private void DisplayCatalogEntry() { if (_currentEntryIndex == null || _currentEntryIndex >= _catalog.Count || _currentEntryIndex < 0) { //err return; } _currentEntry = (POSingularEntry)_catalog[_currentEntryIndex]; idTextBox.Text = _currentEntry.Key.Id; translationTextBox.Text = _currentEntry.Translation; entryCountLabel.Text = (_currentEntryIndex + 1) + COUNT_SEPARATOR + _catalog.Count; var commentsTextBuilder = new StringBuilder(); foreach (var comment in _currentEntry.Comments) { if (comment.Kind == POCommentKind.Extracted) { commentsTextBuilder.AppendLine(((POExtractedComment)comment).Text); } else if (comment.Kind == POCommentKind.Reference) { commentsTextBuilder.AppendLine(GetReferenceCommentText((POReferenceComment)comment)); } } commentsTextBox.Text = commentsTextBuilder.ToString(); }
private void Generate_LineBreak_Core(string id, params string[] lines) { var generator = new POGenerator(new POGeneratorSettings { IgnoreEncoding = true, SkipInfoHeaders = true, }); var catalog = new POCatalog { Encoding = "UTF-8" }; var entry = new POSingularEntry(new POKey(id)); catalog.Add(entry); var sb = new StringBuilder(); generator.Generate(sb, catalog); var expected = new List <string>(); expected.Add(@"msgid """""); expected.AddRange(lines); expected.Add(@"msgstr """""); IEnumerable <string> actual = sb.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None).Skip(5).Take(lines.Length + 2); Assert.Equal(expected, actual); }
private POSingularEntry TransformSingularEntry(POSingularEntry singular) { string translation = Transform(singular.Translation); return(new POSingularEntry(singular.Key) { Translation = translation, Comments = singular.Comments, }); }
public static POCatalog GetDialogueCatalog(this DialogueDatabase db) { var actors = GetActors(db); var catalog = InitCatalog(); foreach (var conversation in db.conversations) { foreach (var dialogue in conversation.dialogueEntries) { foreach (var field in dialogue.fields) { if (string.IsNullOrWhiteSpace(field.value)) { continue; } if (!DialogueTranslatableFields.Contains(field.title)) { continue; } string key = $"{field.title}/{Field.LookupValue(dialogue.fields, "Articy Id")}"; string source = field.value; var entry = new POSingularEntry(new POKey(source, contextId: key)) { Comments = new List <POComment>() }; entry.Comments.Add(new POTranslatorComment { Text = $"Title = {conversation.Title}" }); entry.Comments.Add(new POTranslatorComment { Text = $"Description = {conversation.Description.Replace("\n", "\\n")}" }); if (actors.TryGetValue(dialogue.ActorID, out Actor actor)) { entry.Comments.Add(new POTranslatorComment { Text = $"Actor = {actor.Name}" }); } if (actors.TryGetValue(dialogue.ConversantID, out Actor conversant)) { entry.Comments.Add(new POTranslatorComment { Text = $"Conversant = {conversant.Name}" }); } catalog.Add(entry); } } } return(catalog); }
private void AddToCatalog(POCatalog catalog, ExtractedText extractedEntry) { var catalogKey = new POKey(extractedEntry.Japanese); var catalogEntry = new POSingularEntry(catalogKey) { Comments = new List <POComment> { new POReferenceComment { References = new POSourceReference[] { new POSourceReference($"{extractedEntry.Source}", extractedEntry.SourceLine) } } }, }; if (!string.IsNullOrEmpty(extractedEntry.English)) { catalogEntry.Translation = extractedEntry.English.Trim(' '); } var comment = extractedEntry.Comment ?? ""; // If we have Korean text add it to the comment as well. This gives us multiple strings to throw at a // machine translator to hopefully get better context. if (!string.IsNullOrEmpty(extractedEntry.Korean) && extractedEntry.Korean != extractedEntry.Japanese && !comment.Contains("Korean Text: ", StringComparison.Ordinal)) { if (comment.Length > 0) { comment += "; "; } // The comment we save the Korean text in can't contain new lines, tabs are just for visual convenience comment += "Korean Text: '" + extractedEntry.Korean.Replace("\r", "\\r", StringComparison.Ordinal) .Replace("\n", "\\n", StringComparison.Ordinal) .Replace("\t", "\\t", StringComparison.Ordinal) + "'"; } if (!string.IsNullOrEmpty(comment)) { catalogEntry.Comments.Add(new POTranslatorComment() { Text = comment }); } catalog.Add(catalogEntry); }
private static bool WasPartial(POSingularEntry entry) { foreach (var comment in entry.Comments) { if (!(comment is POTranslatorComment translatorComment)) { continue; } if (translatorComment.Text.Contains(PartialMatchComment, StringComparison.OrdinalIgnoreCase)) { return(true); } } return(false); }
public static POCatalog LanguageSourceToCatalog(I2.Loc.LanguageSourceAsset languageSource, int languageIndex) { var catalog = InitCatalog(); foreach (var term in languageSource.mSource.mTerms) { string key = term.Term; string source = term.Languages[languageIndex]; if (string.IsNullOrWhiteSpace(source) || source == "\"") { continue; } var entry = new POSingularEntry(new POKey(source, contextId: key)); catalog.Add(entry); } return(catalog); }
/// <summary> /// Creates a catalog for a translations dictionary for a given encoding and language /// </summary> /// <param name="fileEncoding">File encoding</param> /// <param name="htmlTextKeys">A list of translations</param> /// <param name="translationsLanguage">Translations language</param> /// <returns></returns> public POCatalog CreateCatalog(Encoding fileEncoding, IList <string> htmlTextKeys, string translationsLanguage) { var catalog = new POCatalog { // Setting Required Headers Encoding = fileEncoding.WebName, Language = translationsLanguage, // Setting Custom Headers Headers = CreateHeaders() }; foreach (var htmlTextKey in htmlTextKeys) { var poKey = new POKey(htmlTextKey); var poEntry = new POSingularEntry(poKey); catalog.Add(poEntry); } return(catalog); }
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { var translationResult = (TranslationResult)context.Object; var poCatalog = new POCatalog(); poCatalog.Language = translationResult.Language; poCatalog.Encoding = "UTF-8"; translationResult.Entries.ForEach(entry => { var poKey = new POKey(entry.Key, contextId: entry.Collection); var poEntry = new POSingularEntry(poKey); poEntry.Translation = entry.Value; poCatalog.Add(poEntry); }); var poGenerator = new POGenerator(); var memoryStream = new MemoryStream(); poGenerator.Generate(memoryStream, poCatalog, Encoding.UTF8); memoryStream.Position = 0; await memoryStream.CopyToAsync(context.HttpContext.Response.Body); }
/// <summary> /// Creates a catalog for a translations dictionary for a given encoding and language /// </summary> /// <param name="fileEncoding">File encoding</param> /// <param name="htmlTextTranslations">Translations dictionary</param> /// <param name="translationsLanguage">Translations language</param> /// <returns></returns> public POCatalog CreateCatalog(Encoding fileEncoding, IOrderedDictionary <string, string> htmlTextTranslations, string translationsLanguage) { var catalog = new POCatalog { // Setting Required Headers Encoding = fileEncoding.HeaderName, Language = translationsLanguage, // Setting Custom Headers Headers = CreateHeaders() }; foreach (var htmlTextTranslation in htmlTextTranslations) { var poKey = new POKey(htmlTextTranslation.Key); var poEntry = new POSingularEntry(poKey) { Translation = htmlTextTranslation.Value }; catalog.Add(poEntry); } return(catalog); }
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 POCatalog BuildTemplateCatalog(string?filePath, KeyValuePair <string, ExtractResult>[] fileTexts) { 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; for (var i = originalCatalog.Count - 1; i >= 0; i--) { var originalEntry = originalCatalog[i]; if (GetPOEntryFlags(originalEntry).Contains("removed")) { originalCatalog.RemoveAt(i); } } } } else { originalCatalog = null; } var groupsById = fileTexts .Where(fileText => fileText.Value.Texts != null) .SelectMany(fileText => fileText.Value.Texts !.Select(text => (text, fileText.Key))) .GroupBy(item => new POKey(item.text.Id, item.text.PluralId, item.text.ContextId)) .OrderBy(item => item.Key, POKeyComparer.Instance); var catalog = new POCatalog(); foreach (var groupById in groupsById) { var key = groupById.Key; foreach (var(text, sourceFilePath) in groupById) { if (!catalog.TryGetValue(key, out var entry)) { var state = "new"; if (originalCatalog != null && originalCatalog.TryGetValue(key, out var originalEntry)) { var hasChanged = originalEntry.Count == 0 || originalEntry[0] != text.Id || (text.PluralId == null ? originalEntry.Count > 1 : originalEntry.Count != 2 || originalEntry[1] != text.PluralId); state = hasChanged ? "changed" : null; } entry = text.PluralId == null ? (IPOEntry) new POSingularEntry(key) { Translation = text.Id } : new POPluralEntry(key) { text.Id, text.PluralId }; entry.Comments = new List <POComment>(); if (state != null) { entry.Comments.Add(new POFlagsComment { Flags = new HashSet <string> { state } }); } if (!NoReferences) { entry.Comments.Add(new POReferenceComment() { References = new List <POSourceReference>() }); } catalog.Add(entry); } if (!NoReferences) { var referenceComment = entry.Comments.OfType <POReferenceComment>().First(); referenceComment.References.Add(new POSourceReference(sourceFilePath, text.LineNumber)); } if (!NoComments && !string.IsNullOrEmpty(text.Comment)) { entry.Comments.Add(new POExtractedComment { Text = text.Comment }); } } } if (originalCatalog != null) { foreach (var originalEntry in originalCatalog) { if (!catalog.Contains(originalEntry.Key)) { var entry = new POSingularEntry(originalEntry.Key) { Translation = "***THIS ENTRY WAS REMOVED. DO NOT TRANSLATE!***" }; entry.Comments = new List <POComment> { new POFlagsComment { Flags = new HashSet <string> { "removed" } } }; catalog.Add(entry); } } } return(catalog); }
public static POCatalog CreateCatalog() { var result = new POCatalog(); result.HeaderComments = new POComment[] { new POTranslatorComment { Text = "header comment" } }; result.Headers = new OrderedDictionary <string, string> { { "Language-Team", "" }, { "PO-Revision-Date", "" }, { "POT-Creation-Date", "2018-06-22 07:01+0200" }, { "Project-Id-Version", "" }, { "Report-Msgid-Bugs-To", "" }, { "MIME-Version", "1.0" }, { "X-Generator", "Poedit 2.0.8" }, { "Last-Translator", "" }, }; result.Encoding = "UTF-8"; result.PluralFormCount = 2; result.PluralFormSelector = "(n != 1)"; result.Language = "en_US"; var key = new POKey("{0} hour to midnight", "{0} hours to midnight", "Home"); IPOEntry entry = new POPluralEntry(key) { "Translation of {0} hour to midnight", "Translation of {0} hours to midnight", }; entry.Comments = new POComment[] { new POTranslatorComment { Text = "some translator comment" }, new POExtractedComment { Text = "some extracted comment" }, new POReferenceComment { References = new POSourceReference[] { new POSourceReference("/Views/Home/Index.cshtml", 8) } }, new POFlagsComment { Flags = new SortedSet <string> { "fuzzy", "csharp-format" } }, new POPreviousValueComment { IdKind = POIdKind.Id, Value = "{0} hour to midnite" }, new POPreviousValueComment { IdKind = POIdKind.PluralId, Value = "{0} hours to midnite" }, }; result.Add(entry); key = new POKey($"Here is an example of how one might continue a very long string{Environment.NewLine}" + $"for the common case the string represents multi-line output.{Environment.NewLine}"); entry = new POSingularEntry(key) { Translation = "Some translation of long text" }; result.Add(entry); return(result); }
public async Task Visit(DataStructure dataStructure) { await Task.CompletedTask; var language = Thread.CurrentThread.CurrentCulture.Name; var projectName = dataStructure.Project.Name; var projectPath = dataStructure.ProjectDirectory; var localizerEntries = dataStructure.LocalizerEntries; var POFilePath = Path.Combine(projectPath, "Localization", language + ".po"); POCatalog catalog = null; if (File.Exists(POFilePath)) { using var sr = new StreamReader(POFilePath, Encoding.UTF8); var parser = new POParser(POParserSettings.Default); var result = parser.Parse(sr); if (result.Success) { catalog = result.Catalog; foreach (var r in catalog) { r.Comments.Clear(); } } else { var diagnostics = result.Diagnostics; // examine diagnostics, display an error, etc... foreach (var diagnostic in diagnostics) { if (diagnostic.Severity.Equals(Karambolo.PO.DiagnosticSeverity.Error)) { Console.WriteLine($"Error has occurred while Parse the PO file: {POFilePath}"); } } } } if (catalog == null) { catalog = new POCatalog { Encoding = Encoding.UTF8.BodyName, PluralFormCount = 1, PluralFormSelector = "0", Language = language }; var assembly = typeof(IVisitor).Assembly; catalog.Headers = new Dictionary <string, string> { { "PO-Revision-Date", DateTime.UtcNow.ToString() }, { "Project-Id-Version", projectName }, { "X-Crowdin-Generator", $"Generated by {assembly.GetName().Name} {assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}" }, }; } HashSet <POKey> sets = new HashSet <POKey>(); foreach (var entry in localizerEntries) { var key = new POKey(entry.Id, null, entry.ContextId); sets.Add(key); if (catalog.TryGetValue(key, out var POEntry)) { if (!POEntry.Comments.OfType <POExtractedComment>().Any(c => c.Text.Equals(entry.SourceCode))) { POEntry.Comments.Add(new POExtractedComment { Text = entry.SourceCode }); } var referenceComment = POEntry.Comments.OfType <POReferenceComment>().FirstOrDefault(); if (referenceComment == null) { POEntry.Comments.Add(new POReferenceComment { References = new List <POSourceReference>() { POSourceReference.Parse(entry.SourceReference) } }); } else { var sourceReference = POSourceReference.Parse(entry.SourceReference); if (!referenceComment.References.Any(r => r.FilePath.Equals(sourceReference.FilePath) && r.Line.Equals(sourceReference.Line))) { referenceComment.References.Add(sourceReference); } } } else { POEntry = new POSingularEntry(key) { Comments = new List <POComment>() { new POReferenceComment { References = new List <POSourceReference>() { POSourceReference.Parse(entry.SourceReference) } }, new POExtractedComment { Text = entry.SourceCode }, } }; catalog.Add(POEntry); } } var keys = catalog.Keys.ToList(); keys.Where(k => !sets.Contains(k)).ToList().ForEach(k => catalog.Remove(k)); if (catalog.Headers.ContainsKey("PO-Revision-Date")) { catalog.Headers["PO-Revision-Date"] = DateTime.UtcNow.ToString(); } var generator = new POGenerator(POGeneratorSettings.Default); using var sw = new StreamWriter(POFilePath, false, Encoding.UTF8); generator.Generate(sw, catalog); }