Add new ParagraphUnit or SegmentPair in Bilingual File

I'm pretty sure it is not possible, but just wanted to make sure:

I want to add a ParagraphUnit or SegmentPair in Bilingual File, is this possible?

I don't think this is possible because Paragraph Units/SegmentPairs are generated during Native to Bilingual Conversion process and there is

not method to add new ones during Batch Task. The closest I can get is adding ISegment to a IParagraph but that cause an error.

Usecase:

I want to add a new SubSegment for localization in bilingual file after creating a placeholder, I can add a SubSegmentReference, but the translatable content is usually added to a new ParagraphUnit.

Reference:

I pretty much am doing same thing as Expose Localizable Text Within a Tag (see following link), but I am working with the Bilingual File as a Batch Task, so cannot use InlinePlaceholderTag. (I am trying to create ParagraphUnit or SegmentPair manually)

Parents
  • Answering my own question, this is not possible. I looked at how Trados implements `Split Segments (Alt + Shift + T)` in the Editor and it is very complicated and none of that functionality is available in the public API.
  • Hello Jesse!

    I have not tested the following code inside a Batch task, but it works as a Bilingual processor (invoked from a console application), so it might be of use.

    Notes:

    1. The class should implement IBilingualFileTypeComponent to get access to ItemFactory property.

    2. You should somehow process subsegment references if they do present in your files. In our production application, for example, I delete them using the Visitor pattern you should be familiar with.

    3. This version just creates a paragraph unit for each segment pair, but the logic could be more complicated. In our production application, I export only segments with given stats (date created, confirmation level, match percent, etc.).

    using Sdl.FileTypeSupport.Framework.BilingualApi;
    using Sdl.FileTypeSupport.Framework.NativeApi;

    public class XLIFFSegmenter : AbstractBilingualContentProcessor, IBilingualFileTypeComponent
    {
        public override void Initialize(IDocumentProperties documentInfo)
        {
            base.Initialize(documentInfo);
        }

        public override void Complete()
        {
            base.Complete();
        }

        public override void SetFileProperties(IFileProperties properties)
        {
            base.SetFileProperties(properties);
        }

        public override void FileComplete()
        {
            base.FileComplete();
        }

        public override void ProcessParagraphUnit(IParagraphUnit paragraphUnit)
        {
            if (paragraphUnit.IsStructure == false)
            {
                foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs)
                {
                    LockTypeFlags flags = new LockTypeFlags();
                    if (segmentPair.Properties.IsLocked)
                        flags = LockTypeFlags.Manual;
                    else
                        flags = LockTypeFlags.Unlocked;
                    IParagraphUnit unit = ItemFactory.CreateParagraphUnit(flags); //we keep the locked status
                    unit.Properties.Contexts = paragraphUnit.Properties.Contexts; //we keep the context
                    ISegment source = ItemFactory.CreateSegment(segmentPair.Source.Properties);
                    ISegment target = ItemFactory.CreateSegment(segmentPair.Target.Properties);
                    FillSegment(source, segmentPair.Source);
                    FillSegment(target, segmentPair.Target);
                    unit.Source.Add(source);
                    unit.Target.Add(target);
                    Output.ProcessParagraphUnit(unit); //this actually creates a new unit in the output file
                }
            }
            else
            {
                Output.ProcessParagraphUnit(paragraphUnit); //we keep structure units as they are
            }
        }

        private void FillSegment(ISegment newSegment, ISegment oldSegment)
        {
            foreach (var item in oldSegment)
            {
                var newItem = item.Clone();
                newSegment.Add((IAbstractMarkupData)newItem); //this way, it doesn't give us an error
            }
        }
    }

Reply
  • Hello Jesse!

    I have not tested the following code inside a Batch task, but it works as a Bilingual processor (invoked from a console application), so it might be of use.

    Notes:

    1. The class should implement IBilingualFileTypeComponent to get access to ItemFactory property.

    2. You should somehow process subsegment references if they do present in your files. In our production application, for example, I delete them using the Visitor pattern you should be familiar with.

    3. This version just creates a paragraph unit for each segment pair, but the logic could be more complicated. In our production application, I export only segments with given stats (date created, confirmation level, match percent, etc.).

    using Sdl.FileTypeSupport.Framework.BilingualApi;
    using Sdl.FileTypeSupport.Framework.NativeApi;

    public class XLIFFSegmenter : AbstractBilingualContentProcessor, IBilingualFileTypeComponent
    {
        public override void Initialize(IDocumentProperties documentInfo)
        {
            base.Initialize(documentInfo);
        }

        public override void Complete()
        {
            base.Complete();
        }

        public override void SetFileProperties(IFileProperties properties)
        {
            base.SetFileProperties(properties);
        }

        public override void FileComplete()
        {
            base.FileComplete();
        }

        public override void ProcessParagraphUnit(IParagraphUnit paragraphUnit)
        {
            if (paragraphUnit.IsStructure == false)
            {
                foreach (ISegmentPair segmentPair in paragraphUnit.SegmentPairs)
                {
                    LockTypeFlags flags = new LockTypeFlags();
                    if (segmentPair.Properties.IsLocked)
                        flags = LockTypeFlags.Manual;
                    else
                        flags = LockTypeFlags.Unlocked;
                    IParagraphUnit unit = ItemFactory.CreateParagraphUnit(flags); //we keep the locked status
                    unit.Properties.Contexts = paragraphUnit.Properties.Contexts; //we keep the context
                    ISegment source = ItemFactory.CreateSegment(segmentPair.Source.Properties);
                    ISegment target = ItemFactory.CreateSegment(segmentPair.Target.Properties);
                    FillSegment(source, segmentPair.Source);
                    FillSegment(target, segmentPair.Target);
                    unit.Source.Add(source);
                    unit.Target.Add(target);
                    Output.ProcessParagraphUnit(unit); //this actually creates a new unit in the output file
                }
            }
            else
            {
                Output.ProcessParagraphUnit(paragraphUnit); //we keep structure units as they are
            }
        }

        private void FillSegment(ISegment newSegment, ISegment oldSegment)
        {
            foreach (var item in oldSegment)
            {
                var newItem = item.Clone();
                newSegment.Add((IAbstractMarkupData)newItem); //this way, it doesn't give us an error
            }
        }
    }

Children