| File: Model\UnstructuredDocument.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.XliffTasks\Microsoft.DotNet.XliffTasks.csproj (Microsoft.DotNet.XliffTasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.IO; namespace XliffTasks.Model { internal sealed class UnstructuredDocument : TranslatableDocument { const string TranslatableSpanMarker = "@@@"; const string TranslatableSpanSeparator = "|"; private List<string> _fragments = new(); private List<UnstructuredTranslatableNode> _nodes = new(); protected override IEnumerable<TranslatableNode> GetTranslatableNodes() { return _nodes; } protected override void LoadCore(TextReader reader) { string text = reader.ReadToEnd(); int lastSpanEnd = 0; int spanStart = text.IndexOf(TranslatableSpanMarker); while (spanStart >= 0) { // the previous span of text is untranslatable and is simply copied string plainSpan = text.Substring(lastSpanEnd, spanStart - lastSpanEnd); _fragments.Add(plainSpan); // next, find the translatable span lastSpanEnd = text.IndexOf(TranslatableSpanMarker, spanStart + 1); if (lastSpanEnd < 0) { throw new InvalidOperationException($"No end of span marker '{TranslatableSpanMarker}' found."); } lastSpanEnd += TranslatableSpanMarker.Length; // account for the length of the end marker int spanLength = lastSpanEnd - spanStart - TranslatableSpanMarker.Length * 2; // trim off the marker start/end length string translatableSpan = text.Substring(spanStart + TranslatableSpanMarker.Length, spanLength); int separatorIndex = translatableSpan.IndexOf(TranslatableSpanSeparator); if (separatorIndex < 0) { throw new InvalidOperationException($"No span separator '{TranslatableSpanSeparator}' found."); } string id = translatableSpan.Substring(0, separatorIndex); string source = translatableSpan.Substring(separatorIndex + TranslatableSpanSeparator.Length); // keep the original span's text _nodes.Add(new UnstructuredTranslatableNode(_fragments, _fragments.Count, id, source)); _fragments.Add(source); spanStart = lastSpanEnd >= text.Length ? -1 // don't search beyond the end of the text : text.IndexOf(TranslatableSpanMarker, lastSpanEnd + 1); } if (lastSpanEnd < text.Length) { // add final span _fragments.Add(text.Substring(lastSpanEnd)); } } protected override void SaveCore(TextWriter writer) { foreach (string fragment in _fragments) { writer.Write(fragment); } } private sealed class UnstructuredTranslatableNode : TranslatableNode { private IList<string> _fragments; private int _fragmentIndex; public UnstructuredTranslatableNode(IList<string> fragments, int fragmentIndex, string id, string source) : base(id, source, null) { _fragments = fragments; _fragmentIndex = fragmentIndex; } public override void Translate(string translation) { _fragments[_fragmentIndex] = translation; } } } }